-
Notifications
You must be signed in to change notification settings - Fork 34
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
Enable Multi-Platform Support for kubemacpool Image Builds #441
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
@@ -1,4 +1,31 @@ | ||||
ARG BUILD_ARCH=amd64 | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. please separate into 2 commits:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You did so but the order of the commits is wrong. |
||||
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 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 . . | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. please consider adding a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||||
|
||||
RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -o build/_output/bin/manager github.com/k8snetworkplumbingwg/kubemacpool/cmd/manager | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is it just me or it builds remote sources which is not correct ? (unless it compiles based on module name, not remote) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, this is correct only, Line 87 in f61b413
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thanks, |
||||
|
||||
# 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"] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
#!/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" | ||
|
||
BUILD_ARGS="--build-arg BUILD_ARCH=$ARCH -f build/Dockerfile -t $KUBEMACPOOL_IMAGE_TAGGED -t $KUBEMACPOOL_IMAGE_GIT_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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
#!/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 | ||
podman rmi "${KUBEMACPOOL_IMAGE_TAGGED}" 2>/dev/null || true | ||
podman rmi "${KUBEMACPOOL_IMAGE_GIT_TAGGED}" 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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
#!/bin/bash | ||
|
||
ARCH=$1 | ||
PLATFORMS=$2 | ||
KUBEMACPOOL_IMAGE_TAGGED=$3 | ||
KUBEMACPOOL_IMAGE_GIT_TAGGED=$4 | ||
DOCKER_BUILDER=$5 | ||
OCI_BIN=$6 | ||
|
||
if [ "$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 ./hack/build-kubemacpool-docker.sh | ||
elif [ "$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 | ||
else | ||
echo "Unsupported OCI_BIN value: $OCI_BIN" | ||
exit 1 | ||
fi | ||
|
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is there no docker counterpart?
In any case, if we don't want to support pushing with docker, we should be explicit, failing the operation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I understand this. In the existing code (https://github.com/k8snetworkplumbingwg/kubemacpool/blob/main/Makefile#L94-L98), I don't see any check to prevent pushing the image in the Docker case either. Just for clarification—docker buildx build combines both build and push into a single command, so there isn't a separate push command. This is the way it works.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me rephrase: in the existing code (https://github.com/k8snetworkplumbingwg/kubemacpool/blob/main/Makefile#L94-L98) you can either do docker/podman push/tag using the OCI_BIN env var.
Now however, you can only do it with podman:
my original question is - why are you limiting it like this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For building multi-platform images using docker buildx build, the build and push operations are combined into a single command, Therefore, the separate push and tag logic, which currently applies only to podman, isn't needed for docker when using buildx.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
theoretically it is possible to split even for docker single arch / multi arch ?
(i see here
--push
flag is used so i wonder)https://github.com/k8snetworkplumbingwg/kubemacpool/pull/441/files#diff-8a6127c87c24bc27e5595386a152b920da0266e3b6d185a3e632cab440abf09bR10-R18
not saying we need to, first trying to understand
doing so gives advantage of more flexibility and symmetry
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently it's not possible for multi arch images:
Below is the reason:
With docker buildx, the build result is stored only in the build cache by default. There are two options to handle the result, which I've already tested: --push and --load.
The --push flag pushes the built image to a container registry.
The --load flag loads the resulting image into the local Docker daemon. However, the --load option currently only supports single-platform images or simpler images. It does not work with multi-platform builds (i.e., manifest lists).
When using the --load flag with a multi-platform build, you'll encounter the following error:
docker exporter does not currently support exporting manifest lists
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for the explanation
theoretically for single arch, it is possible then right?
it is nice to have, as it will allow to just build instead build + push, but i am not sure it worths the effort, and all the other repos have it combined already
moreover we encourage podman over docker
it is Ram's decision here anyhow
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct, but with single arch we can directly use docker build , for multiplatform we need to use docker buildx build and we have to do like this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see now. I don't like the asymmetry of it, but having build+push to the local repo isn't such a bad thing.
Thanks for the explanation