Skip to content

Commit

Permalink
Enable Multi-Platform Support for kubemacpool Image Builds
Browse files Browse the repository at this point in the history
These changes enable building and pushing kubemacpool container images for
multiple platforms (amd64, s390x, arm64) from a single Dockerfile.
Enhanced multi-platform support in the build process by adding a PLATFORMS
argument in the Makefile for amd64, s390x, and arm64 architectures.
Multi-platform build support is provided for both Docker and Podman container runtimes.

Signed-off-by: Ashok Pariya [email protected]
  • Loading branch information
ashokpariya0 committed Nov 25, 2024
1 parent f61b413 commit 1d5d286
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 11 deletions.
40 changes: 31 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ 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,)
PLATFORMS ?= linux/amd64,linux/s390x
# Set the platforms for building a multi-platform supported image.
# Example:
# PLATFORMS ?= linux/amd64,linux/arm64,linux/s390x
# Alternatively, you can export the PLATFORMS variable like this:
# export PLATFORMS=linux/arm64,linux/s390x,linux/amd64
ARCH := $(shell uname -m | sed 's/x86_64/amd64/')
DOCKER_BUILDER ?= kubemacpool-docker-builder
KUBEMACPOOL_IMAGE_TAGGED_1 := ${REGISTRY}/${IMG}:${IMAGE_TAG}
KUBEMACPOOL_IMAGE_TAGGED_2 := ${REGISTRY}/${IMG}:${IMAGE_GIT_TAG}

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

Expand Down Expand Up @@ -83,18 +93,23 @@ 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:
ifeq ($(OCI_BIN),podman)
$(MAKE) build-multiarch-kubemacpool-podman
else ifeq ($(OCI_BIN),docker)
$(MAKE) build-multiarch-kubemacpool-docker
else
$(error Unsupported OCI_BIN value: $(OCI_BIN))
endif

# Push the docker image
docker-push:
$(OCI_BIN) push ${TLS_SETTING} ${REGISTRY}/${IMG}:${IMAGE_TAG}
$(OCI_BIN) tag ${REGISTRY}/${IMG}:${IMAGE_TAG} ${REGISTRY}/${IMG}:${IMAGE_GIT_TAG}
$(OCI_BIN) push ${TLS_SETTING} ${REGISTRY}/${IMG}:${IMAGE_GIT_TAG}
ifeq ($(OCI_BIN),podman)
podman manifest push ${TLS_SETTING} ${KUBEMACPOOL_IMAGE_TAGGED_1} ${KUBEMACPOOL_IMAGE_TAGGED_1}
podman tag ${KUBEMACPOOL_IMAGE_TAGGED_1} ${KUBEMACPOOL_IMAGE_TAGGED_2}
podman manifest push ${TLS_SETTING} ${KUBEMACPOOL_IMAGE_TAGGED_2} ${KUBEMACPOOL_IMAGE_TAGGED_2}
endif

cluster-up:
./cluster/up.sh
Expand All @@ -115,7 +130,15 @@ vendor: $(GO)
$(GO) mod tidy -compat=$(GO_VERSION)
$(GO) mod vendor

build-multiarch-kubemacpool-docker:
ARCH=$(ARCH) PLATFORMS=$(PLATFORMS) KUBEMACPOOL_IMAGE_TAGGED_1=$(KUBEMACPOOL_IMAGE_TAGGED_1) KUBEMACPOOL_IMAGE_TAGGED_2=$(KUBEMACPOOL_IMAGE_TAGGED_2) DOCKER_BUILDER=$(DOCKER_BUILDER) ./hack/build-kubemacpool-docker.sh

build-multiarch-kubemacpool-podman:
ARCH=$(ARCH) PLATFORMS=$(PLATFORMS) KUBEMACPOOL_IMAGE_TAGGED_1=$(KUBEMACPOOL_IMAGE_TAGGED_1) KUBEMACPOOL_IMAGE_TAGGED_2=$(KUBEMACPOOL_IMAGE_TAGGED_2) ./hack/build-kubemacpool-podman.sh

.PHONY: \
build-multiarch-kubemacpool-docker \
build-multiarch-kubemacpool-podman \
vendor \
test \
deploy \
Expand All @@ -128,7 +151,6 @@ vendor: $(GO)
fmt \
vet \
check \
manager \
container \
push \
cluster-up \
Expand Down
21 changes: 19 additions & 2 deletions build/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,21 @@
ARG BUILD_ARCH=amd64
FROM --platform=linux/${BUILD_ARCH} quay.io/centos/centos:stream9 AS builder
RUN dnf install -y tar gzip jq && dnf clean all
RUN ARCH=$(uname -m | sed 's/x86_64/amd64/') && \
GO_VERSION=$(curl -L -s "https://go.dev/dl/?mode=json" | jq -r '.[0].version') && \
curl -L "https://go.dev/dl/${GO_VERSION}.linux-${ARCH}.tar.gz" -o go.tar.gz && \
tar -C /usr/local -xzf go.tar.gz && \
rm go.tar.gz
ENV PATH=$PATH:/usr/local/go/bin
WORKDIR /go/src/kubemacpool
COPY . .

ARG TARGETOS
ARG TARGETARCH

RUN CGO_ENABLED=0 GOOS=${TARGETOS} 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"]
17 changes: 17 additions & 0 deletions hack/build-kubemacpool-docker.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash

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

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

BUILD_ARGS="--no-cache --build-arg BUILD_ARCH=$ARCH -f build/Dockerfile -t $KUBEMACPOOL_IMAGE_TAGGED_1 -t $KUBEMACPOOL_IMAGE_TAGGED_2 . --push"

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
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_1" ]; then
echo "Error: ARCH, PLATFORMS, and KUBEMACPOOL_IMAGE_TAGGED_1 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_1}" || true
podman manifest rm "${KUBEMACPOOL_IMAGE_TAGGED_2}" || true
podman rmi "${KUBEMACPOOL_IMAGE_TAGGED_1}" || true
podman rmi "${KUBEMACPOOL_IMAGE_TAGGED_2}" || true

podman manifest create "${KUBEMACPOOL_IMAGE_TAGGED_1}"

for platform in "${PLATFORM_LIST[@]}"; do
podman build \
--no-cache \
--build-arg BUILD_ARCH="$ARCH" \
--platform "$platform" \
--manifest "${KUBEMACPOOL_IMAGE_TAGGED_1}" \
-f build/Dockerfile .
done
55 changes: 55 additions & 0 deletions hack/init-buildx.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/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)
curl -L https://github.com/docker/buildx/releases/download/"${BUILDX_VERSION}"/buildx-"${BUILDX_VERSION}".linux-amd64 --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}")"

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

0 comments on commit 1d5d286

Please sign in to comment.