Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add multi platform support #444

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 23 additions & 10 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,19 @@ IMAGE_GIT_TAG ?= $(shell git describe --abbrev=8 --tags)
IMG ?= $(REPO)/kubemacpool
OCI_BIN ?= $(shell if podman ps >/dev/null 2>&1; then echo podman; elif docker ps >/dev/null 2>&1; then echo docker; fi)
TLS_SETTING := $(if $(filter $(OCI_BIN),podman),--tls-verify=false,)
PLATFORM_LIST ?= linux/amd64,linux/s390x,linux/arm64
ARCH := $(shell uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
PLATFORMS ?= linux/${ARCH}
PLATFORMS := $(if $(filter all,$(PLATFORMS)),$(PLATFORM_LIST),$(PLATFORMS))
# Define the platforms for building a multi-platform image.
# Example:
# PLATFORMS ?= linux/amd64,linux/arm64,linux/s390x
# Alternatively, you can set the PLATFORMS variable using:
# export PLATFORMS=linux/arm64,linux/s390x,linux/amd64
# or export PLATFORMS=all to automatically include all supported platforms.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be a PR that set platforms=all on the release right ? (unless there is already)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@oshoval I don't see any post-submit Prow jobs that handle the release for the macpool CNI image.

@RamLavi Could you please let me know how the image is being built and pushed to quay.io?
Also, please note that we need to set PLATFORMS=all before running make build to ensure the image is built with multi-platform support.

Copy link
Member

@oshoval oshoval Dec 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

github/ci/prow-deploy/files/jobs/k8snetworkplumbingwg/kubemacpool/kubemacpool-postsubmits.yaml ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, thanks! I found it here: kubemacpool-postsubmits.yaml.

I’ll go ahead and submit the PR for that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DOCKER_BUILDER ?= kubemacpool-docker-builder
KUBEMACPOOL_IMAGE_TAGGED := ${REGISTRY}/${IMG}:${IMAGE_TAG}
KUBEMACPOOL_IMAGE_GIT_TAGGED := ${REGISTRY}/${IMG}:${IMAGE_GIT_TAG}

BIN_DIR = $(CURDIR)/build/_output/bin/

Expand Down Expand Up @@ -83,24 +96,25 @@ generate: generate-go generate-deploy generate-test generate-external
check: $(GO)
./hack/check.sh

manager: $(GO)
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 $(GO) build -o $(BIN_DIR)/manager github.com/k8snetworkplumbingwg/kubemacpool/cmd/manager

# Build the docker image
container: manager
$(OCI_BIN) build build/ -t ${REGISTRY}/${IMG}:${IMAGE_TAG}
container:
./hack/build-multiarch-kubemacpool.sh $(ARCH) $(PLATFORMS) $(KUBEMACPOOL_IMAGE_TAGGED) $(KUBEMACPOOL_IMAGE_GIT_TAGGED) $(DOCKER_BUILDER) $(OCI_BIN) $(REGISTRY)

# Push the docker image
docker-push:
$(OCI_BIN) push ${TLS_SETTING} ${REGISTRY}/${IMG}:${IMAGE_TAG}
@if [ "$(OCI_BIN)" = "podman" ]; then \
podman manifest push ${TLS_SETTING} ${REGISTRY}/${IMG}:${IMAGE_TAG} ${REGISTRY}/${IMG}:${IMAGE_TAG}; \
fi
@if [[ "${REGISTRY}" == localhost* || "${REGISTRY}" == 127.0.0.1* ]]; then \
echo "Local registry detected (${REGISTRY}). Skipping IMAGE_GIT_TAG handling."; \
else \
if skopeo inspect docker://${REGISTRY}/${IMG}:${IMAGE_GIT_TAG} >/dev/null 2>&1; then \
echo "Tag '${IMAGE_GIT_TAG}' already exists. Skipping tagging and push."; \
echo "Tag '${IMAGE_GIT_TAG}' already exists. Skipping tagging and push."; \
elif skopeo inspect docker://${REGISTRY}/${IMG}:${IMAGE_GIT_TAG} 2>&1 | grep -q "manifest unknown"; then \
$(OCI_BIN) tag ${REGISTRY}/${IMG}:${IMAGE_TAG} ${REGISTRY}/${IMG}:${IMAGE_GIT_TAG}; \
$(OCI_BIN) push ${TLS_SETTING} ${REGISTRY}/${IMG}:${IMAGE_GIT_TAG}; \
if [ "$(OCI_BIN)" = "podman" ]; then \
podman tag ${REGISTRY}/${IMG}:${IMAGE_TAG} ${REGISTRY}/${IMG}:${IMAGE_GIT_TAG}; \
podman manifest push ${TLS_SETTING} ${REGISTRY}/${IMG}:${IMAGE_GIT_TAG} ${REGISTRY}/${IMG}:${IMAGE_GIT_TAG}; \
fi \
else \
echo "Error checking for tag '${IMAGE_GIT_TAG}'. Aborting to avoid potential overwrite."; \
exit 1; \
Expand Down Expand Up @@ -139,7 +153,6 @@ vendor: $(GO)
fmt \
vet \
check \
manager \
container \
push \
cluster-up \
Expand Down
31 changes: 29 additions & 2 deletions build/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,31 @@
ARG BUILD_ARCH=amd64
FROM --platform=linux/${BUILD_ARCH} quay.io/centos/centos:stream9 AS builder
ARG TARGETOS
ARG TARGETARCH
ENV TARGETOS=${TARGETOS:-linux}
ENV TARGETARCH=${TARGETARCH:-amd64}

ARG BUILDOS
ARG BUILDARCH
ENV BUILDOS=${BUILDOS:-linux}
ENV BUILDARCH=${BUILDARCH:-amd64}

WORKDIR /go/src/kubemacpool
RUN dnf install -y wget && dnf clean all
COPY go.mod .
COPY go.sum .
RUN GO_VERSION=$(sed -En 's/^go +(.*)$/\1/p' go.mod) && \
wget -q https://dl.google.com/go/go${GO_VERSION}.${BUILDOS}-${BUILDARCH}.tar.gz && \
tar -C /usr/local -xzf go${GO_VERSION}.${BUILDOS}-${BUILDARCH}.tar.gz && \
rm go${GO_VERSION}.${BUILDOS}-${BUILDARCH}.tar.gz

ENV PATH=$PATH:/usr/local/go/bin
RUN go mod download
COPY . .

RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -o build/_output/bin/manager github.com/k8snetworkplumbingwg/kubemacpool/cmd/manager

# Copy the controller-manager into a thin image
FROM registry.access.redhat.com/ubi9/ubi-minimal
COPY _output/bin/manager /
FROM --platform=linux/${TARGETARCH} registry.access.redhat.com/ubi9/ubi-minimal
COPY --from=builder /go/src/kubemacpool/build/_output/bin/manager /
ENTRYPOINT ["/manager"]
28 changes: 28 additions & 0 deletions hack/build-kubemacpool-docker.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/bin/bash

if [ -z "$ARCH" ] || [ -z "$PLATFORMS" ] || [ -z "$KUBEMACPOOL_IMAGE_TAGGED" ] || [ -z "$KUBEMACPOOL_IMAGE_GIT_TAGGED" ] || [ -z "$DOCKER_BUILDER" ] || [ -z "$REGISTRY" ]; then
echo "Error: ARCH, PLATFORMS, KUBEMACPOOL_IMAGE_TAGGED, KUBEMACPOOL_IMAGE_GIT_TAGGED and DOCKER_BUILDER must be set."
exit 1
fi

IFS=',' read -r -a PLATFORM_LIST <<< "$PLATFORMS"

if [[ "${REGISTRY}" == localhost* || "${REGISTRY}" == 127.0.0.1* ]]; then
echo "Local registry detected (${REGISTRY}). Skipping $KUBEMACPOOL_IMAGE_GIT_TAGGED handling.";
BUILD_ARGS="--build-arg BUILD_ARCH=$ARCH -f build/Dockerfile -t $KUBEMACPOOL_IMAGE_TAGGED . --push"
else
if skopeo inspect docker://${KUBEMACPOOL_IMAGE_GIT_TAGGED} >/dev/null 2>&1; then
echo "Tag '${KUBEMACPOOL_IMAGE_GIT_TAGGED}' already exists in the registry. Skipping tagging with ${KUBEMACPOOL_IMAGE_GIT_TAGGED}."
BUILD_ARGS="--build-arg BUILD_ARCH=$ARCH -f build/Dockerfile -t $KUBEMACPOOL_IMAGE_TAGGED . --push"
else
BUILD_ARGS="--build-arg BUILD_ARCH=$ARCH -f build/Dockerfile -t $KUBEMACPOOL_IMAGE_TAGGED -t $KUBEMACPOOL_IMAGE_GIT_TAGGED . --push"
fi
fi

if [ ${#PLATFORM_LIST[@]} -eq 1 ]; then
docker build --platform "$PLATFORMS" $BUILD_ARGS
else
./hack/init-buildx.sh "$DOCKER_BUILDER"
docker buildx build --platform "$PLATFORMS" $BUILD_ARGS
docker buildx rm "$DOCKER_BUILDER" 2>/dev/null || echo "Builder ${DOCKER_BUILDER} not found or already removed, skipping."
fi
25 changes: 25 additions & 0 deletions hack/build-kubemacpool-podman.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/bin/bash

if [ -z "$ARCH" ] || [ -z "$PLATFORMS" ] || [ -z "$KUBEMACPOOL_IMAGE_TAGGED" ] || [ -z "$KUBEMACPOOL_IMAGE_GIT_TAGGED" ]; then
echo "Error: ARCH, PLATFORMS, KUBEMACPOOL_IMAGE_TAGGED, and KUBEMACPOOL_IMAGE_GIT_TAGGED must be set."
exit 1
fi

IFS=',' read -r -a PLATFORM_LIST <<< "$PLATFORMS"

# Remove any existing manifest and image
podman manifest rm "${KUBEMACPOOL_IMAGE_TAGGED}" 2>/dev/null || true
podman manifest rm "${KUBEMACPOOL_IMAGE_GIT_TAGGED}" 2>/dev/null || true
RamLavi marked this conversation as resolved.
Show resolved Hide resolved
podman rmi "${KUBEMACPOOL_IMAGE_TAGGED}" 2>/dev/null || true
podman rmi "${KUBEMACPOOL_IMAGE_GIT_TAGGED}" 2>/dev/null || true
podman rmi $(podman images --filter "dangling=true" -q) 2>/dev/null || true

podman manifest create "${KUBEMACPOOL_IMAGE_TAGGED}"

for platform in "${PLATFORM_LIST[@]}"; do
podman build \
--build-arg BUILD_ARCH="$ARCH" \
--platform "$platform" \
--manifest "${KUBEMACPOOL_IMAGE_TAGGED}" \
-f build/Dockerfile .
done
19 changes: 19 additions & 0 deletions hack/build-multiarch-kubemacpool.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/bash

ARCH=$1
PLATFORMS=$2
KUBEMACPOOL_IMAGE_TAGGED=$3
KUBEMACPOOL_IMAGE_GIT_TAGGED=$4
DOCKER_BUILDER=$5
OCI_BIN=$6
REGISTRY=$7

if [ "$OCI_BIN" == "podman" ]; then
ARCH=$ARCH PLATFORMS=$PLATFORMS KUBEMACPOOL_IMAGE_TAGGED=$KUBEMACPOOL_IMAGE_TAGGED KUBEMACPOOL_IMAGE_GIT_TAGGED=$KUBEMACPOOL_IMAGE_GIT_TAGGED ./hack/build-kubemacpool-podman.sh
elif [ "$OCI_BIN" == "docker" ]; then
ARCH=$ARCH PLATFORMS=$PLATFORMS KUBEMACPOOL_IMAGE_TAGGED=$KUBEMACPOOL_IMAGE_TAGGED KUBEMACPOOL_IMAGE_GIT_TAGGED=$KUBEMACPOOL_IMAGE_GIT_TAGGED DOCKER_BUILDER=$DOCKER_BUILDER REGISTRY=$REGISTRY ./hack/build-kubemacpool-docker.sh
else
echo "Unsupported OCI_BIN value: $OCI_BIN"
exit 1
fi

56 changes: 56 additions & 0 deletions hack/init-buildx.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#!/bin/bash

check_buildx() {
export DOCKER_CLI_EXPERIMENTAL=enabled

if ! docker buildx > /dev/null 2>&1; then
mkdir -p ~/.docker/cli-plugins
BUILDX_VERSION=$(curl -s https://api.github.com/repos/docker/buildx/releases/latest | jq -r .tag_name)
ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
curl -L https://github.com/docker/buildx/releases/download/"${BUILDX_VERSION}"/buildx-"${BUILDX_VERSION}".linux-"${ARCH}" --output ~/.docker/cli-plugins/docker-buildx
chmod a+x ~/.docker/cli-plugins/docker-buildx
fi
}

create_or_use_buildx_builder() {
local builder_name=$1
if [ -z "$builder_name" ]; then
echo "Error: Builder name is required."
exit 1
fi

check_buildx

current_builder="$(docker buildx inspect "${builder_name}" 2>/dev/null)" || echo "Builder '${builder_name}' not found"

if ! grep -q "^Driver: docker$" <<<"${current_builder}" && \
grep -q "linux/amd64" <<<"${current_builder}" && \
grep -q "linux/arm64" <<<"${current_builder}" && \
grep -q "linux/s390x" <<<"${current_builder}"; then
echo "The current builder already has multi-architecture support (amd64, arm64, s390x)."
echo "Skipping setup as the builder is already configured correctly."
exit 0
fi

# Check if the builder already exists by parsing the output of `docker buildx ls`
# We check if the builder_name appears in the list of active builders
existing_builder=$(docker buildx ls | grep -w "$builder_name" | awk '{print $1}')

if [ -n "$existing_builder" ]; then
echo "Builder '$builder_name' already exists."
echo "Using existing builder '$builder_name'."
docker buildx use "$builder_name"
else
echo "Creating a new Docker Buildx builder: $builder_name"
docker buildx create --driver-opt network=host --use --name "$builder_name"
echo "The new builder '$builder_name' has been created and set as active."
fi
}

if [ $# -eq 1 ]; then
create_or_use_buildx_builder "$1"
else
echo "Usage: $0 <builder_name>"
echo "Example: $0 mybuilder"
exit 1
fi
3 changes: 2 additions & 1 deletion hack/install-go.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

destination=$1
version=$(grep "^go " go.mod |awk '{print $2}')
tarball=go$version.linux-amd64.tar.gz
arch=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
tarball=go$version.linux-$arch.tar.gz
url=https://dl.google.com/go/

mkdir -p $destination
Expand Down
Loading