Skip to content

Commit

Permalink
Add multi-platform support for macvtap cni image builds.
Browse files Browse the repository at this point in the history
These changes enable building and pushing macvtap 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 Dec 10, 2024
1 parent 82f52bd commit 4103e3d
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 8 deletions.
36 changes: 30 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,18 @@ OCI_BIN ?= docker

# tools
GITHUB_RELEASE ?= $(GOBIN)/github-release
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))
# 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
# or export PLATFORMS=all to automatically include all supported platforms.
DOCKER_BUILDER ?= macvtap-docker-builder
MACVTAP_IMAGE_TAGGED := ${IMAGE_REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}

# Make does not offer a recursive wildcard function, so here's one:
rwildcard=$(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2))
Expand All @@ -30,7 +42,7 @@ go_sources=$(call rwildcard,cmd/,*.go) $(call rwildcard,pkg/,*.go) $(call rwildc

# Configure Go
export GOOS=linux
export GOARCH=amd64
export GOARCH=$(shell uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
export CGO_ENABLED=0
export GO111MODULE=on
export GOFLAGS=-mod=vendor
Expand Down Expand Up @@ -69,17 +81,21 @@ vet: $(go_sources) $(GO)
$(GO) vet ./pkg/... ./cmd/... ./tests/...

docker-build:
$(OCI_BIN) build -t ${IMAGE_REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG} -f ./cmd/Dockerfile .
ifeq ($(OCI_BIN),podman)
$(MAKE) build-multiarch-macvtap-podman
else ifeq ($(OCI_BIN),docker)
$(MAKE) build-multiarch-macvtap-docker
else
$(error Unsupported OCI_BIN value: $(OCI_BIN))
endif

docker-push:
ifeq ($(OCI_BIN),podman)
$(OCI_BIN) push --tls-verify=false ${IMAGE_REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}
else
$(OCI_BIN) push ${IMAGE_REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}
podman manifest push --tls-verify=false ${MACVTAP_IMAGE_TAGGED} ${MACVTAP_IMAGE_TAGGED}
endif

docker-tag-latest:
$(OCI_BIN) tag ${IMAGE_REGISTRY}/${IMAGE_NAME}:latest ${IMAGE_REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}
$(OCI_BIN) tag ${IMAGE_REGISTRY}/${IMAGE_NAME}:latest ${MACVTAP_IMAGE_TAGGED}

cluster-up:
./cluster/up.sh
Expand Down Expand Up @@ -122,8 +138,16 @@ release: docker-build docker-push
release: $(GITHUB_RELEASE)
TAG=$(IMAGE_TAG) GITHUB_RELEASE=$(GITHUB_RELEASE) DESCRIPTION=./version/description ./hack/release.sh

build-multiarch-macvtap-docker:
PLATFORMS=$(PLATFORMS) MACVTAP_IMAGE_TAGGED=$(MACVTAP_IMAGE_TAGGED) DOCKER_BUILDER=$(DOCKER_BUILDER) ./hack/build-macvtap-docker.sh

build-multiarch-macvtap-podman:
PLATFORMS=$(PLATFORMS) MACVTAP_IMAGE_TAGGED=$(MACVTAP_IMAGE_TAGGED) ./hack/build-macvtap-podman.sh

.PHONY: \
all \
build-multiarch-macvtap-docker \
build-multiarch-macvtap-podman \
check \
cluster-up \
cluster-down \
Expand Down
1 change: 1 addition & 0 deletions automation/publish.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
source automation/check-patch.setup.sh
cd ${TMP_PROJECT_PATH}

export PLATFORMS=all
IMAGE_TAG=${IMAGE_TAG:-$(git log -1 --pretty=%h)-$(date +%s)}
make docker-build
make docker-tag-latest
Expand Down
12 changes: 10 additions & 2 deletions cmd/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
# Multi-stage dockerfile building a container image with both binaries included

FROM quay.io/projectquay/golang:1.20 as builder
FROM --platform=$BUILDPLATFORM quay.io/projectquay/golang:1.20 AS builder
ENV GOPATH=/go
WORKDIR /go/src/github.com/kubevirt/macvtap-cni
ARG TARGETOS
ARG TARGETARCH
ENV TARGETOS=${TARGETOS:-linux}
ENV TARGETARCH=${TARGETARCH:-amd64}

ENV GOOS=${TARGETOS}
ENV GOARCH=${TARGETARCH}

COPY . .
RUN GOOS=linux CGO_ENABLED=0 go build -o /macvtap-deviceplugin github.com/kubevirt/macvtap-cni/cmd/deviceplugin
RUN GOOS=linux CGO_ENABLED=0 go build -o /macvtap-cni github.com/kubevirt/macvtap-cni/cmd/cni

FROM registry.access.redhat.com/ubi8/ubi-minimal
FROM --platform=linux/${TARGETARCH} registry.access.redhat.com/ubi8/ubi-minimal
COPY --from=builder /macvtap-deviceplugin /macvtap-deviceplugin
COPY --from=builder /macvtap-cni /macvtap-cni
18 changes: 18 additions & 0 deletions hack/build-macvtap-docker.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/usr/bin/env bash

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

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

BUILD_ARGS="-f cmd/Dockerfile -t $MACVTAP_IMAGE_TAGGED . --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
docker buildx rm "$DOCKER_BUILDER" 2>/dev/null || echo "Builder ${DOCKER_BUILDER} not found or already removed, skipping."
fi
22 changes: 22 additions & 0 deletions hack/build-macvtap-podman.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env bash

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

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

podman manifest rm "${MACVTAP_IMAGE_TAGGED}" 2>/dev/null || true
podman manifest rm "${MARKER_IMAGE_GIT_TAGGED}" 2>/dev/null || true
podman rmi "${MACVTAP_IMAGE_TAGGED}" 2>/dev/null || true
podman rmi "${MARKER_IMAGE_GIT_TAGGED}" 2>/dev/null || true

podman manifest create "${MACVTAP_IMAGE_TAGGED}"

for platform in "${PLATFORM_LIST[@]}"; do
podman build \
--platform "$platform" \
--manifest "${MACVTAP_IMAGE_TAGGED}" \
-f cmd/Dockerfile .
done
56 changes: 56 additions & 0 deletions hack/init-buildx.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#!/usr/bin/env 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

0 comments on commit 4103e3d

Please sign in to comment.