diff --git a/.gitignore b/.gitignore index 1c27b74c5..f600d32b6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ /bin/ -/manager +/manager* *.tgz /*gpu-operator*.tgz /helm-charts-k8s/charts/*.tgz @@ -26,6 +26,7 @@ tests/pytests/* .cline_storage .vscode +.idea branch_policy.yml tools-internal/* docs-internal/* diff --git a/.wordlist.txt b/.wordlist.txt index 6d634eb09..f4cbdd1c8 100644 --- a/.wordlist.txt +++ b/.wordlist.txt @@ -163,6 +163,7 @@ PreStateDB prometheus Promethues quay +QEMU QPX RAS RBAC diff --git a/Dockerfile b/Dockerfile index 33fda9144..0be902b9a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ ARG GOLANG_BASE_IMG=golang:1.26.5 ARG OPERATOR_CONTROLLER_BASE_IMAGE=registry.access.redhat.com/ubi9/ubi-minimal:9.8 # Build the manager binary -FROM ${GOLANG_BASE_IMG} AS builder +FROM --platform=$BUILDPLATFORM ${GOLANG_BASE_IMG} AS builder USER root @@ -36,16 +36,20 @@ RUN cd helm-charts-k8s/charts && \ tar -xvzf node-feature-discovery-chart-0.18.3.tgz ARG TARGET +# No defaults: buildx sets these per --platform; a default would pin the arch. +ARG TARGETARCH +ARG TARGETOS # Build -RUN git config --global --add safe.directory ${PWD} && make ${TARGET} +RUN git config --global --add safe.directory ${PWD} && GOOS=${TARGETOS} GOARCH=${TARGETARCH} make ${TARGET} -RUN curl -LO https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl && \ +RUN curl -LO https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/${TARGETARCH}/kubectl && \ chmod +x ./kubectl FROM ${OPERATOR_CONTROLLER_BASE_IMAGE} ARG TARGET +ARG TARGETARCH COPY --from=builder /opt/app-root/src/${TARGET} /usr/local/bin/manager COPY --from=builder /opt/app-root/src/kubectl /usr/local/bin/kubectl diff --git a/Dockerfile.build b/Dockerfile.build index eb2494afe..721d4f62a 100644 --- a/Dockerfile.build +++ b/Dockerfile.build @@ -24,6 +24,8 @@ RUN apt-get update -y && \ protobuf-compiler \ locales \ ca-certificates \ + qemu-user-static \ + libc6-arm64-cross \ sudo && \ apt-get clean && rm -rf /var/lib/apt/lists/* @@ -71,12 +73,16 @@ RUN curl -o /usr/local/bin/kubectl -LO 'https://dl.k8s.io/release/v1.36.2/bin/li ARG INSECURE_REGISTRY RUN echo "INSECURE_REGISTRY is: $INSECURE_REGISTRY" && \ - if [ -n "$INSECURE_REGISTRY" ]; then \ mkdir -p /etc/docker && \ + if [ -n "$INSECURE_REGISTRY" ]; then \ echo "{ \ - \"insecure-registries\": [\"$INSECURE_REGISTRY\"] \ + \"insecure-registries\": [\"$INSECURE_REGISTRY\"], \ + \"features\": {\"containerd-snapshotter\": true} \ }" > /etc/docker/daemon.json; \ else \ + echo "{ \ + \"features\": {\"containerd-snapshotter\": true} \ + }" > /etc/docker/daemon.json; \ echo "INSECURE_REGISTRY is not set"; \ fi diff --git a/Makefile b/Makefile index 877ecb7c0..f20451d5d 100644 --- a/Makefile +++ b/Makefile @@ -353,12 +353,15 @@ docs-lint: ## Run docs Markdown lint + spelling (full ROCm-style docs lint). ##@ Build -manager: $(shell find -name "*.go") go.mod go.sum ## Build manager binary. +manager: $(shell find -name "*.go") go.mod go.sum ## Build manager binary (honors GOOS/GOARCH from the environment). go build -ldflags="-X main.Version=$(PROJECT_VERSION) -X main.GitCommit=$(GIT_COMMIT) -X main.BuildTag=$(HOURLY_TAG_LABEL)" -o $@ ./cmd +# Build platform, default amd64. Set to a list (linux/amd64,linux/arm64) for multi-arch. +PLATFORM ?= linux/amd64 + .PHONY: docker-build -docker-build: ## Build docker image with the manager. - DOCKER_BUILDKIT=1 $(CONTAINER_ENGINE) build -t $(IMG) --label HOURLY_TAG=$(HOURLY_TAG_LABEL) --build-arg TARGET=manager --build-arg GOLANG_BASE_IMG=$(GOLANG_BASE_IMG) --build-arg OPERATOR_CONTROLLER_BASE_IMAGE=$(OPERATOR_CONTROLLER_BASE_IMAGE) . +docker-build: ## Build docker image with the manager (PLATFORM, default linux/amd64). + DOCKER_BUILDKIT=1 $(CONTAINER_ENGINE) buildx build --platform "$(PLATFORM)" -t $(IMG) --label HOURLY_TAG=$(HOURLY_TAG_LABEL) --build-arg TARGET=manager --build-arg GOLANG_BASE_IMG=$(GOLANG_BASE_IMG) --build-arg OPERATOR_CONTROLLER_BASE_IMAGE=$(OPERATOR_CONTROLLER_BASE_IMAGE) . .PHONY: docker-push docker-push: ## Push docker image with the manager. @@ -369,8 +372,8 @@ docker-save: ## Save the container image with the manager. $(CONTAINER_ENGINE) save $(IMG) | gzip > $(IMAGE_NAME).tar.gz .PHONY: docker-build-utils -docker-build-utils: ## Build docker image for utils container. - DOCKER_BUILDKIT=1 $(CONTAINER_ENGINE) build -t $(UTILS_IMG) --label HOURLY_TAG=$(HOURLY_TAG_LABEL) -f internal/utils_container/Dockerfile . +docker-build-utils: ## Build docker image for utils container (PLATFORM, default linux/amd64). + DOCKER_BUILDKIT=1 $(CONTAINER_ENGINE) buildx build --platform "$(PLATFORM)" -t $(UTILS_IMG) --label HOURLY_TAG=$(HOURLY_TAG_LABEL) -f internal/utils_container/Dockerfile . .PHONY: docker-push-utils docker-push-utils: ## Push docker image for utils container. diff --git a/docs/contributing/developer-guide.md b/docs/contributing/developer-guide.md index cb51e709f..2b37d8d22 100644 --- a/docs/contributing/developer-guide.md +++ b/docs/contributing/developer-guide.md @@ -67,6 +67,35 @@ make docker-push > Note: If you're using a remote registry that requires authentication, ensure you've logged in using `docker login` before pushing. +### Building the controller manager image for a specific architecture + +`make docker-build` runs `$(CONTAINER_ENGINE) buildx build` and is architecture-configurable through the `PLATFORM` variable, which defaults to `linux/amd64`. Set it to a single platform, or a comma-separated list for a multi-arch build. This works with `docker buildx` and with `podman` 4.0+ (which aliases `podman buildx build` to `podman build`). + +```bash +# Default: builds a linux/amd64 image and loads it into the local image store +make docker-build + +# Build a single arm64 image +make docker-build PLATFORM=linux/arm64 +``` + +`buildx` populates the `TARGETOS`/`TARGETARCH` build arguments per platform, which drive both the Go cross-compilation (`GOOS`/`GOARCH`) and the architecture-specific `kubectl` download. With no override, `make docker-build` produces a `linux/amd64` image, unchanged from the previous default. + +A single-platform build is loaded into the local image store automatically. A **multi-platform** `PLATFORM` (e.g. `linux/amd64,linux/arm64`) cannot be loaded locally — buildx must push the resulting manifest list straight to a registry, which the `docker-build` target does not do. For that case, run buildx directly with `--push`. + +The utils container image build follows the same convention through the same `PLATFORM` variable: + +```bash +make docker-build-utils # linux/amd64 +make docker-build-utils PLATFORM=linux/arm64 +``` + +> Note: When building for an architecture different from your host, register QEMU emulation once per host so the runtime stage can execute: +> +> ```bash +> docker run --privileged --rm tonistiigi/binfmt --install arm64,ppc64le +> ``` + - Generate Helm charts: - For vanilla Kubernetes: `make helm` - For OpenShift: `OPENSHIFT=1 make helm` diff --git a/internal/utils_container/Dockerfile b/internal/utils_container/Dockerfile index 77913f234..064d192eb 100644 --- a/internal/utils_container/Dockerfile +++ b/internal/utils_container/Dockerfile @@ -16,9 +16,11 @@ RUN microdnf install -y util-linux pciutils kmod tar jq systemd && \ ADD LICENSE /licenses/LICENSE # Install kubectl and oc +# No default: buildx sets TARGETARCH per --platform. +ARG TARGETARCH RUN mkdir -p /oc && cd /oc && \ - curl -SsLO 'https://mirror.openshift.com/pub/openshift-v4/clients/ocp/latest/openshift-client-linux-amd64-rhel9.tar.gz' && \ - tar -xzf openshift-client-linux-amd64-rhel9.tar.gz -C /oc && \ + curl -SsLO "https://mirror.openshift.com/pub/openshift-v4/clients/ocp/latest/openshift-client-linux-${TARGETARCH}-rhel9.tar.gz" && \ + tar -xzf "openshift-client-linux-${TARGETARCH}-rhel9.tar.gz" -C /oc && \ cp ./kubectl /usr/local/bin && chmod +x /usr/local/bin/kubectl && \ cp ./oc /usr/local/bin && chmod +x /usr/local/bin/oc && \ rm -rf /oc