diff --git a/Makefile b/Makefile index 2d73ec4c1..31fe0f868 100644 --- a/Makefile +++ b/Makefile @@ -15,11 +15,16 @@ CMDS=wekafsplugin all: build -.PHONY: build-% build clean +.PHONY: build-% build clean build-debug deploy-debug # understand what is the version tag VERSION ?= $(shell cat charts/csi-wekafsplugin/Chart.yaml | grep appVersion | awk '{print $$2}' | tr -d '"') +TIMESTAMP := $(shell date +%Y%m%d-%H%M%S) +DEBUG_VERSION ?= $(VERSION)-debug-$(TIMESTAMP) DOCKER_IMAGE_NAME?=csi-wekafs +DEBUG_IMAGE_NAME?=csi-wekafs-debug +QUAY_REGISTRY?=quay.io/weka.io +DEBUG_IMAGE?=$(QUAY_REGISTRY)/$(DEBUG_IMAGE_NAME):$(DEBUG_VERSION) $(CMDS:%=build-%): build-%: docker buildx build --platform linux/amd64 --build-arg VERSION=$(VERSION) -t $(DOCKER_IMAGE_NAME):$(VERSION) -f Dockerfile --label revision=$(VERSION) . @@ -31,3 +36,105 @@ push: build clean: -rm -rf bin + +# Build debug binaries locally (fast on native arch) +.PHONY: build-debug-binaries +build-debug-binaries: + @echo "🔨 Building debug binaries locally for linux/amd64..." + @mkdir -p bin + CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \ + -gcflags="all=-N -l" \ + -ldflags "-X main.version=$(DEBUG_VERSION)" \ + -o ./bin/wekafsplugin-debug \ + ./cmd/wekafsplugin + CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \ + -gcflags="all=-N -l" \ + -ldflags "-X main.version=$(DEBUG_VERSION)" \ + -o ./bin/metricsserver-debug \ + ./cmd/metricsserver + @echo "✅ Debug binaries built in ./bin/" + +# Build debug image with Delve and debug symbols +.PHONY: build-debug +build-debug: build-debug-binaries + @echo "🔨 Building DEBUG Docker image..." + docker buildx build --platform linux/amd64 \ + --build-arg VERSION=$(DEBUG_VERSION) \ + -t $(DEBUG_IMAGE_NAME):$(DEBUG_VERSION) \ + -t $(DEBUG_IMAGE) \ + -f debug.Dockerfile \ + --label revision=$(DEBUG_VERSION) \ + --label debug=true \ + --load . + @echo "✅ Debug image built: $(DEBUG_IMAGE)" + +# Complete debug deployment: build, push to Quay, and update deployment +.PHONY: deploy-debug +deploy-debug: build-debug + @echo "📤 Pushing debug image to Quay.io..." + docker push $(DEBUG_IMAGE) + @echo "✅ Debug image pushed: $(DEBUG_IMAGE)" + @echo "" + @echo "🚀 Deploying debug image to cluster..." + @# Get the release name and namespace from helm + @RELEASE_NAME=$$(helm list --all-namespaces -o json | jq -r '.[] | select(.chart | startswith("csi-wekafsplugin")) | .name' | head -n1); \ + NAMESPACE=$$(helm list --all-namespaces -o json | jq -r '.[] | select(.chart | startswith("csi-wekafsplugin")) | .namespace' | head -n1); \ + if [ -z "$$RELEASE_NAME" ] || [ -z "$$NAMESPACE" ]; then \ + echo "❌ Could not find csi-wekafsplugin helm release. Please specify manually:"; \ + echo " RELEASE_NAME= NAMESPACE= make deploy-debug"; \ + exit 1; \ + fi; \ + echo "Found release: $$RELEASE_NAME in namespace: $$NAMESPACE"; \ + echo "Setting imagePullPolicy to Always to force pull..."; \ + kubectl patch deployment $$RELEASE_NAME-controller -n $$NAMESPACE --type='json' \ + -p='[{"op":"replace","path":"/spec/template/spec/containers/0/imagePullPolicy","value":"Always"}]' 2>/dev/null || echo "⚠️ Failed to patch controller imagePullPolicy"; \ + kubectl patch daemonset $$RELEASE_NAME-node -n $$NAMESPACE --type='json' \ + -p='[{"op":"replace","path":"/spec/template/spec/containers/0/imagePullPolicy","value":"Always"}]' 2>/dev/null || echo "⚠️ Failed to patch node imagePullPolicy"; \ + echo "Updating controller deployment..."; \ + kubectl set image deployment/$$RELEASE_NAME-controller -n $$NAMESPACE wekafs=$(DEBUG_IMAGE) || echo "⚠️ Controller deployment not found or failed to update"; \ + echo "Updating node daemonset..."; \ + kubectl set image daemonset/$$RELEASE_NAME-node -n $$NAMESPACE wekafs=$(DEBUG_IMAGE) || echo "⚠️ Node daemonset not found or failed to update"; \ + echo "Forcing pod restart to pull new image..."; \ + kubectl rollout restart deployment/$$RELEASE_NAME-controller -n $$NAMESPACE 2>/dev/null || echo "⚠️ Failed to restart controller"; \ + kubectl rollout restart daemonset/$$RELEASE_NAME-node -n $$NAMESPACE 2>/dev/null || echo "⚠️ Failed to restart node"; \ + echo ""; \ + echo "⏰ Adjusting timeouts and enabling Delve for debugging..."; \ + kubectl patch deployment $$RELEASE_NAME-controller -n $$NAMESPACE --type='json' \ + -p='[{"op": "remove", "path": "/spec/template/spec/containers/0/livenessProbe"}]' 2>/dev/null || echo "⚠️ No liveness probe to remove from controller"; \ + kubectl patch daemonset $$RELEASE_NAME-node -n $$NAMESPACE --type='json' \ + -p='[{"op": "remove", "path": "/spec/template/spec/containers/0/livenessProbe"}]' 2>/dev/null || echo "⚠️ No liveness probe to remove from node"; \ + echo "Setting up Delve entrypoint for controller..."; \ + kubectl patch deployment $$RELEASE_NAME-controller -n $$NAMESPACE --type='json' \ + -p='[{"op":"add","path":"/spec/template/spec/containers/0/command","value":["dlv","exec","--api-version=2","--headless","--listen=0.0.0.0:2345","--accept-multiclient","/wekafsplugin","--"]}]' 2>/dev/null || echo "⚠️ Failed to patch controller command"; \ + echo "Setting up Delve entrypoint for node..."; \ + kubectl patch daemonset $$RELEASE_NAME-node -n $$NAMESPACE --type='json' \ + -p='[{"op":"add","path":"/spec/template/spec/containers/0/command","value":["dlv","exec","--api-version=2","--headless","--listen=0.0.0.0:2345","--accept-multiclient","/wekafsplugin","--"]}]' 2>/dev/null || echo "⚠️ Failed to patch node command"; \ + echo "Exposing Delve port 2345 in controller..."; \ + kubectl patch deployment $$RELEASE_NAME-controller -n $$NAMESPACE --type='json' \ + -p='[{"op":"add","path":"/spec/template/spec/containers/0/ports/-","value":{"containerPort":2345,"name":"delve","protocol":"TCP"}}]' 2>/dev/null || echo "⚠️ Port may already exist or failed to add"; \ + echo "Exposing Delve port 2345 in node..."; \ + kubectl patch daemonset $$RELEASE_NAME-node -n $$NAMESPACE --type='json' \ + -p='[{"op":"add","path":"/spec/template/spec/containers/0/ports/-","value":{"containerPort":2345,"name":"delve","protocol":"TCP"}}]' 2>/dev/null || echo "⚠️ Port may already exist or failed to add"; \ + echo ""; \ + echo "⏳ Waiting for pods to restart..."; \ + sleep 5; \ + kubectl wait --for=condition=ready pod -l app=$$RELEASE_NAME-controller -n $$NAMESPACE --timeout=120s 2>/dev/null || echo "⚠️ Controller pod not ready yet"; \ + kubectl wait --for=condition=ready pod -l app=$$RELEASE_NAME-node -n $$NAMESPACE --timeout=120s 2>/dev/null || echo "⚠️ Node pods not ready yet"; \ + echo ""; \ + echo "✅ Debug deployment complete!"; \ + echo ""; \ + echo "📎 To start debugging:"; \ + echo " 1. Find a pod:"; \ + echo " Controller: kubectl get pods -n $$NAMESPACE -l app=$$RELEASE_NAME-controller"; \ + echo " Node: kubectl get pods -n $$NAMESPACE -l app=$$RELEASE_NAME-node"; \ + echo ""; \ + echo " 2. Port forward to the pod:"; \ + echo " kubectl port-forward 2345:2345 -n $$NAMESPACE"; \ + echo ""; \ + echo " 3. Connect your debugger to localhost:2345"; \ + echo " - GoLand/IntelliJ: Run -> Edit Configurations -> Go Remote"; \ + echo " - VSCode: Use 'Connect to server' launch configuration with port 2345"; \ + echo ""; \ + echo "⚠️ Note: Liveness probes removed and Delve enabled. Restore normal operation with helm upgrade when done."; \ + echo ""; \ + echo "💡 Tip: Use '--accept-multiclient' flag allows multiple debugger connections" diff --git a/debug.Dockerfile b/debug.Dockerfile new file mode 100644 index 000000000..acb34d192 --- /dev/null +++ b/debug.Dockerfile @@ -0,0 +1,37 @@ +ARG UBI_HASH=9.6-1754584681 + +# Build Delve using Debian-based golang (compatible with UBI/glibc) +FROM golang:1.25.0 AS delve-builder +RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go install -ldflags "-s -w -extldflags '-static'" github.com/go-delve/delve/cmd/dlv@latest + +FROM registry.access.redhat.com/ubi9-minimal:${UBI_HASH} +LABEL maintainers="WekaIO, LTD" +LABEL description="Weka CSI Driver (Debug Build)" + +# Install required packages +RUN microdnf install -y util-linux libselinux-utils pciutils binutils jq procps less container-selinux && \ + microdnf clean all && \ + rm -rf /var/cache/dnf + +RUN mkdir -p /licenses +COPY LICENSE /licenses + +LABEL maintainer="csi@weka.io" +LABEL name="WEKA CSI Plugin (Debug)" +LABEL vendor="weka.io" +LABEL summary="This image is used by WEKA CSI Plugin and incorporates both Controller and Node modules with debug support" +LABEL description="Container Storage Interface (CSI) plugin for WEKA - the data platform for AI (Debug Build with Delve)" +LABEL url="https://www.weka.io" + +# Copy pre-built debug binaries (built on host) +COPY --chmod=755 ./bin/wekafsplugin-debug /wekafsplugin +COPY --chmod=755 ./bin/metricsserver-debug /metricsserver +COPY --from=delve-builder --chmod=755 /go/bin/dlv /usr/local/bin/dlv + +# Verify dlv is present and executable +RUN /usr/local/bin/dlv version + +# Expose NFS ports and Delve debug port +EXPOSE 2049 111/tcp 111/udp 2345 + +ENTRYPOINT ["/wekafsplugin"]