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

Enable Multi-Platform Support for kubemacpool Image Builds #441

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

ashokpariya0
Copy link
Contributor

@ashokpariya0 ashokpariya0 commented Nov 25, 2024

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.

What this PR does / why we need it:
The upstream kubemacpool image (link) currently supports only the amd64 architecture. The proposed changes in this PR enable multi-platform support for the kubemacpool image, broadening its compatibility to include additional architectures.

Special notes for your reviewer:

Multiplatform Build Instruction: https://gist.github.com/ashokpariya0/33cf22401d17153b7f91b40295397ccd

Multi-platform build support is enabled for both Docker and Podman container runtimes, and the necessary changes have been made accordingly.
The PLATFORMS variable defines the target platforms for building the manager image, allowing support for multiple architectures.

To use this feature, you need to:

For Docker:

Have access to docker buildx. More information: [Docker Buildx Documentation](https://docs.docker.com/build/building/multi-platform/)
Ensure that BuildKit is enabled. More information: [Docker BuildKit Enhancements](https://docs.docker.com/develop/develop-images/build_enhancements/)
For Podman:

No additional dependencies are required to build multi-platform images. Podman supports this feature natively.

Release note:

None

@kubevirt-bot
Copy link
Collaborator

Hi @ashokpariya0. Thanks for your PR.

PRs from untrusted users cannot be marked as trusted with /ok-to-test in this repo meaning untrusted PR authors can never trigger tests themselves. Collaborators can still trigger tests on the PR using /test all.

I understand the commands that are listed here.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@oshoval
Copy link
Member

oshoval commented Dec 1, 2024

cc @RamLavi

Copy link
Member

@RamLavi RamLavi left a comment

Choose a reason for hiding this comment

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

Hey @ashokpariya0 , thank you for this change.
I added some comments, please take a look

Makefile Outdated
# 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}
Copy link
Member

Choose a reason for hiding this comment

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

please change KUBEMACPOOL_IMAGE_TAGGED_1 --> KUBEMACPOOL_IMAGE_TAGGED
and KUBEMACPOOL_IMAGE_TAGGED_2 --> KUBEMACPOOL_IMAGE_GIT_TAGGED
the current naming is not good, but it is still better than meaningless enumeration.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

Copy link
Member

Choose a reason for hiding this comment

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

Please change it in the appropriate commit. There should be no existence of KUBEMACPOOL_IMAGE_TAGGED_1 during any commit

$(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)
Copy link
Member

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.

Copy link
Contributor Author

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.

Copy link
Member

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:

ifeq ($(OCI_BIN),podman)
    push,tag,etc...
endif
...

my original question is - why are you limiting it like this?

Copy link
Contributor Author

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.

Copy link
Member

@oshoval oshoval Dec 10, 2024

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

Copy link
Contributor Author

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

Copy link
Member

@oshoval oshoval Dec 10, 2024

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

Copy link
Contributor Author

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

@@ -1,4 +1,21 @@
ARG BUILD_ARCH=amd64
Copy link
Member

Choose a reason for hiding this comment

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

please separate into 2 commits:

  1. moving repo go build to container (+1 btw)
  2. Adding multi arch thing..

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

Copy link
Member

Choose a reason for hiding this comment

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

You did so but the order of the commits is wrong.
Please separate to 2 commits. The first commit only moves the repo go build to a container, setting the ground to the main commit. The second does the main thing this PR is meant to do which is adding the multi arch

@@ -0,0 +1,25 @@
#!/bin/bash

if [ -z "$ARCH" ] || [ -z "$PLATFORMS" ] || [ -z "$KUBEMACPOOL_IMAGE_TAGGED_1" ]; then
Copy link
Member

Choose a reason for hiding this comment

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

I'm missing KUBEMACPOOL_IMAGE_TAGGED_2 in the podman script. Is this intentional?
I would want both tag to be there. having both latest and sha-specific tags allow us to be flexible picking the desired image when deployed from other operators like CNAO.

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, both tags are properly handled.
For multi-architecture support, we create a single manifest and tag it with both the git_sha_tag and the latest tag before pushing. This process, managed in the Makefile, ensures that both tags are properly handled.

Makefile Outdated
container: manager
$(OCI_BIN) build build/ -t ${REGISTRY}/${IMG}:${IMAGE_TAG}
container:
ifeq ($(OCI_BIN),podman)
Copy link
Member

Choose a reason for hiding this comment

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

I prefer not over-complicating the Makefile with these conditions.
please call to a build-multiarch-kubemacpool script that deals with both podman and docker cases.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

--no-cache \
--build-arg BUILD_ARCH="$ARCH" \
--platform "$platform" \
--manifest "${KUBEMACPOOL_IMAGE_TAGGED_1}" \
Copy link
Member

Choose a reason for hiding this comment

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

again what happened to KUBEMACPOOL_IMAGE_TAGGED_2 tagging?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As mentioned earlier, this script creates only a single Podman manifest(this how multi-platform build works with podman), while the tagging with git_sha is handled in the Makefile. so both tags are properly handled.

@oshoval
Copy link
Member

oshoval commented Dec 1, 2024

Thanks for the review Ram

Please note that imo we should not merge any new PRs about cross compilation until
kubevirt/cluster-network-addons-operator#1923 (comment) issue is solved

  1. We must make sure we have local machines that can run it (for me personally since the new machine isn't accessible right now, the old machine will take time to upgrade)
    Alternative, we need to keep old docker support for now - EDIT machines back to business
  2. CNAO merged PR might have some problems (some errors that are mentioned, need to check if they are important)
    and also not sure how all the lanes run - EDIT - Vanilla main is fine on all lanes, and the error is just an error we ignore (rm when image not found) iiuc.

Even if this effort is important, we should not rush it until it is done correctly please.

@ashokpariya0
Copy link
Contributor Author

kubevirt/cluster-network-addons-operator#1923 (comment)
Hey @ashokpariya0 , thank you for this change. I added some comments, please take a look

Okay, noted! I'll make the necessary updates.

@ashokpariya0 ashokpariya0 force-pushed the enable-multi-platform-kubemacpool branch from 1d5d286 to 33e4a6b Compare December 2, 2024 07:12
@kubevirt-bot
Copy link
Collaborator

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please ask for approval from ramlavi. For more information see the Kubernetes Code Review Process.

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

Copy link
Member

@oshoval oshoval left a comment

Choose a reason for hiding this comment

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

some comments (fast pass)
thanks

Makefile Outdated
@@ -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
Copy link
Member

Choose a reason for hiding this comment

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

imo need to check benchmark before doing both
or best to just use the auto detect and have optional all flag as raised on CNAO please

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done, Added auto detach and all flag option in latest commit.

build/Dockerfile Outdated
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') && \
Copy link
Member

Choose a reason for hiding this comment

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

better to get go version from go.mod please
easier to maintain

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.


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

BUILD_ARGS="--no-cache --build-arg BUILD_ARCH=$ARCH -f build/Dockerfile -t $KUBEMACPOOL_IMAGE_TAGGED -t $KUBEMACPOOL_IMAGE_GIT_TAGGED . --push"
Copy link
Member

Choose a reason for hiding this comment

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

why no cache?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed.


for platform in "${PLATFORM_LIST[@]}"; do
podman build \
--no-cache \
Copy link
Member

Choose a reason for hiding this comment

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

why no cache?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It seems --no-cache is recommend approach. Without --no-cache, the build is faster because it reuses previous layers. But this can sometimes cause outdated or incorrect dependencies to be used. Using --no-cache forces a fresh build, making sure all steps in the Dockerfile run again without using old layers. Since we already remove the old manifest before creating a new one, I think --no-cache is the best choice. However, I'm open to other suggestions.

Copy link
Member

Choose a reason for hiding this comment

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

imho we can omit it please and use caching, docker caching seems too fundamental to have bugs beside corner cases
we use caching so far and it is fine iiuc
speed is important (of course unless we find in the future it is buggy and then can report / workaround 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.

Okay sure.

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
Copy link
Member

Choose a reason for hiding this comment

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

is it fine it has hardcoded linux-amd64 ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

good catch, fixed it.

Copy link
Member

@oshoval oshoval Dec 2, 2024

Choose a reason for hiding this comment

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

thanks, saw this on another PR of this effort (commented there)

@ashokpariya0 ashokpariya0 force-pushed the enable-multi-platform-kubemacpool branch 2 times, most recently from 621f919 to 44f660a Compare December 2, 2024 14:15
@ashokpariya0
Copy link
Contributor Author

@RamLavi @oshoval I have addressed all the review comments and responded to the questions. Please take a look.

rm go${GO_VERSION}.${BUILDOS}-${BUILDARCH}.tar.gz

ENV PATH=$PATH:/usr/local/go/bin
COPY . .
Copy link
Member

@oshoval oshoval Dec 2, 2024

Choose a reason for hiding this comment

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

please consider adding a RUN go mod download before the copy, to improve layer building

ref k8snetworkplumbingwg/ovs-cni#336

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

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

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

@oshoval oshoval Dec 2, 2024

Choose a reason for hiding this comment

The 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 ?
i would expect something like
go build -o build/_output/bin/manager ./cmd/manager

(unless it compiles based on module name, not remote)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, this is correct only,
Please check

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

Copy link
Member

@oshoval oshoval Dec 3, 2024

Choose a reason for hiding this comment

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

thanks,
imho it is better to be explicit with what we build please
./cmd/manager
EDIT - but no need in this PR if this was the case already

else
./hack/init-buildx.sh "$DOCKER_BUILDER"
docker buildx build --platform "$PLATFORMS" $BUILD_ARGS
docker buildx rm "$DOCKER_BUILDER" || true
Copy link
Member

@oshoval oshoval Dec 2, 2024

Choose a reason for hiding this comment

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

worth to add please redir of stderr to /dev/null, else the error would always be marked on CI spyglass (same please for all other repos where this effort was done)

(as done on hack/build-kubemacpool-podman.sh)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@ashokpariya0 ashokpariya0 force-pushed the enable-multi-platform-kubemacpool branch from 44f660a to 18f484e Compare December 2, 2024 16:38
@ashokpariya0
Copy link
Contributor Author

@RamLavi @oshoval All the review comments have been addressed. Please take a look.

@ashokpariya0
Copy link
Contributor Author

@RamLavi @oshoval I have addressed all the review comments. Please have a look.
cc @phoracek @ormergi

Copy link
Member

@RamLavi RamLavi left a comment

Choose a reason for hiding this comment

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

please reorder the PR so that it is easier to review

$(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)
Copy link
Member

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:

ifeq ($(OCI_BIN),podman)
    push,tag,etc...
endif
...

my original question is - why are you limiting it like this?

@@ -1,4 +1,21 @@
ARG BUILD_ARCH=amd64
Copy link
Member

Choose a reason for hiding this comment

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

You did so but the order of the commits is wrong.
Please separate to 2 commits. The first commit only moves the repo go build to a container, setting the ground to the main commit. The second does the main thing this PR is meant to do which is adding the multi arch

Makefile Outdated
# 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}
Copy link
Member

Choose a reason for hiding this comment

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

Please change it in the appropriate commit. There should be no existence of KUBEMACPOOL_IMAGE_TAGGED_1 during any commit

@ashokpariya0 ashokpariya0 force-pushed the enable-multi-platform-kubemacpool branch from 18f484e to fa19101 Compare December 11, 2024 10:13
…plumbingwg#440)

The origin-kube-rbac-proxy image is not compatible with the s390x
architecture. This change deploys an image that is multi arch supported.

Signed-off-by: Ashok Pariya <[email protected]>
These changes provide multi-platform build support for the Kubemacpool CNI,
enabling builds for Docker and Podman container runtimes.

Signed-off-by: Ashok Pariya [email protected]
@ashokpariya0 ashokpariya0 force-pushed the enable-multi-platform-kubemacpool branch from fa19101 to bc8283b Compare December 11, 2024 11:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants