-
Notifications
You must be signed in to change notification settings - Fork 9
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
feat: build multi-architecture images in by default #157
feat: build multi-architecture images in by default #157
Conversation
Hi @nestoracunablanco. Thanks for your PR. I'm waiting for a kubevirt member to verify that this patch is reasonable to test. If it is, they should reply with Once the patch is verified, the new status will be reflected by the 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. |
Makefile
Outdated
podman push ${IMG_REPOSITORY}:amd64-${IMG_TAG} && \ | ||
podman push ${IMG_REPOSITORY}:s390x-${IMG_TAG} && \ | ||
podman manifest push ${IMG} |
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 familiar with multi-arch images. When the image is pulled, is the arch determined by the system where the podman is running? Can I just call podman run ${IMG}
?
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.
It can be made this way, but this does not look like it to me. These docs should help: https://docs.podman.io/en/latest/markdown/podman-manifest.1.html#examples
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.
@akrejcir, after you have added the manifest and the images to it, you can simply use 'podman run', and it will automatically select the appropriate architecture during the pull.
@0xFelix, you are correct. However, for this to work, the host must have the capability to execute non-native binaries. As I am not familiar with the specifics of your CI workers, I chose a more generic approach.
Dockerfile
Outdated
|
||
# amd64 target image | ||
FROM --platform=amd64 registry.access.redhat.com/ubi8/ubi-micro as amd64-build |
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.
Can the --platform
be a parameter passed to podman when building? We could then avoid code duplication.
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.
Yes, according to the docs this is possible.
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.
Done.
@nestoracunablanco While we are at it, can you also add a build for arm64? |
5671f18
to
db0b49e
Compare
@0xFelix, I have made the code in the Dockerfile more generic and adjusted the Makefile accordingly. I hope you find it more to your liking now. |
/ok-to-test |
ab7ae3c
to
52a0b1c
Compare
Dockerfile
Outdated
RUN microdnf install -y make tar gzip which && microdnf clean all | ||
RUN export ARCH=$(uname -m | sed 's/x86_64/amd64/'); curl -L https://go.dev/dl/go1.21.6.linux-${ARCH}.tar.gz | tar -C /usr/local -xzf - |
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.
RUN export ARCH=$(uname -m | sed 's/x86_64/amd64/'); curl -L https://go.dev/dl/go1.21.6.linux-${ARCH}.tar.gz | tar -C /usr/local -xzf - | |
RUN ARCH=$(uname -m | sed 's/x86_64/amd64/') curl -L https://go.dev/dl/go1.21.6.linux-${ARCH}.tar.gz | tar -C /usr/local -xzf - |
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.
This change does not work with my podman version. How did you test it?
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.
Ah yes, I see.
It would only work with something like this:
RUN ARCH=$(uname -m | sed 's/x86_64/amd64/') bash -c 'curl -L https://go.dev/dl/go1.21.6.linux-${ARCH}.tar.gz | tar -C /usr/local -xzf -'
Let's leave it like it is.
ENV PATH=$PATH:/usr/local/go/bin | ||
ARG TARGET_ARCH=amd64 | ||
FROM registry.access.redhat.com/ubi8/ubi-minimal as base | ||
ARG TARGET_ARCH |
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.
Is it necessary to redefine TARGET_ARCH
here?
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.
Yes, it works with my Podman without any issues. However, it appears that in the container engine used in the CI, it does not work as expected. Essentially, if we do not reactivate the ARG in every stage, it will not be readable in the FROM statement on line 34. It took me a while to figure out why the tests were failing.
Dockerfile
Outdated
# Build | ||
RUN . ${ENVFILE}; CGO_ENABLED=0 GOOS=linux GOARCH=${ARCH} GO111MODULE=on make build | ||
# compile for the TARGET_ARCH | ||
RUN CGO_ENABLED=0 GOOS=linux GOARCH=${TARGET_ARCH} GO111MODULE=on make build |
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.
RUN CGO_ENABLED=0 GOOS=linux GOARCH=${TARGET_ARCH} GO111MODULE=on make build | |
RUN CGO_ENABLED=0 GOOS=linux GOARCH=${TARGET_ARCH} make build |
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.
That should be the default.
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.
Done.
Makefile
Outdated
@@ -24,11 +24,17 @@ build: fmt vet | |||
|
|||
.PHONY: build-container | |||
build-container: fmt vet test | |||
podman build -t ${IMG} . | |||
podman manifest rm ${IMG} || true && \ | |||
podman build --build-arg TARGET_ARCH=amd64 --manifest=${IMG} -t ${IMG_REPOSITORY}:amd64-${IMG_TAG} . && \ |
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.
Do we really need the additional $arch-${IMG_TAG}
tags? IMO we can omit them. The manifest keeps track of all images.
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.
You are correct that the manifest keeps track of them. However, when we upload to a container registry, these images can appear without any tagging. This could prevent accidental deletion. I can make changes if this is a concern for you.
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.
Sounds like a bug in those registries to me if they don't make use of manifests? I'd remove the additional tags.
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.
Done.
7e7beca
to
6a76eb4
Compare
Dockerfile
Outdated
|
||
|
||
FROM registry.access.redhat.com/ubi8/ubi-minimal | ||
FROM --platform=linux/${TARGET_ARCH} registry.access.redhat.com/ubi8/ubi-micro |
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.
Can we keep ubi-minimal
here?
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.
You are making a good point. Here is why I changed it to ubi-micro:
- When a container image is built, the FROM instruction checks if the image exists in the cache. If it does not, it downloads it.
- The issue arises when the downloaded image is from a different architecture, causing the builder image instructions to fail.
- In other words, the initial call of
make build-container
may succeed, but subsequent calls would fail.
Could you please explain why you chose the ubi-minimal image?
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 was not aware that ubi-micro
exists. It may be better than ubi-minimal
, because it is smaller.
We should look into it and maybe use it.
If it is a technical problem to keep ubi-minimal
, then it's ok to use ubi-micro
.
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.
If we keep ubi-micro
, could we use it across all build stages?
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.
@0xFelix, the same argument as before applies here. The underlying issue here is not about micro versus minimal. It is about how podman manages and utilizes existing images before building a new one.
For instance, consider a scenario where there is a tagged image as registry.access.redhat.com/ubi8/ubi-micro
from a different architecture in your system, and you have the following Dockerfile:
FROM registry.access.redhat.com/ubi8/ubi-micro
RUN uname -m
The image build will fail because you are attempting to execute a binary from an incompatible architecture.
Therefore, I propose the approach of keeping the builder steps aligned with the host architecture, cross-compiling, using a different image source, while the target images are tailored for the target architecture.
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.
Thank you for the explanation.
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 don't quite understand, that means depending on the images I have on my host the build might fail? In this case it only works because ubi-micro
needs to be pulled when using ubi-minimal
in the stages before? Or does this only apply to multi-stage builds? From what you say it sounds like a common issue though?
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.
Hey @0xFelix, if the ubi-minimal
image on your system is from your architecture, it should work without any issues. This is because each time we build the image using ubi-micro
, we specify the architecture using --platform=linux/${TARGET_ARCH}
.
The example I mentioned 4 days ago was just to explain why I opted for this approach. The main issue here arises because podman
or docker
tries to use an existing image for building without checking if the architecture matches. As you mentioned, this is a common problem.
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 tried it myself, and even though I got it working, for the builder we need to stay on ubi-minimal
, because ubi-micro
has no dnf
to install dependencies of the build. But for the final image we should keep it.
6a76eb4
to
db0c550
Compare
Looks good to me. /approve |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: akrejcir The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
Dockerfile
Outdated
RUN echo "export ARCH=`uname -m | sed 's/x86_64/amd64/'`" >> ${ENVFILE} | ||
ENV PATH=$PATH:/usr/local/go/bin | ||
ARG TARGET_ARCH=amd64 | ||
FROM registry.access.redhat.com/ubi8/ubi-minimal as base |
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.
FROM registry.access.redhat.com/ubi8/ubi-minimal as base | |
FROM registry.access.redhat.com/ubi9/ubi-minimal as base |
Use the latest ubi here?
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.
Done.
Dockerfile
Outdated
FROM base as builder | ||
|
||
RUN . ${ENVFILE}; curl -L https://go.dev/dl/go1.22.4.linux-${ARCH}.tar.gz | tar -C /usr/local -xzf - | ||
# in multistage builds the ARG must be renewed | ||
ARG TARGET_ARCH |
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.
Can we drop this extra FROM
and ARG
?
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.
Done
Dockerfile
Outdated
# in multistage builds the ARG must be renewed | ||
ARG TARGET_ARCH |
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.
Is it required to renew it here although it is not used below?
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.
With the last change is no longer a requirement. Deleted.
@@ -24,11 +24,14 @@ build: fmt vet | |||
|
|||
.PHONY: build-container | |||
build-container: fmt vet test | |||
podman build -t ${IMG} . | |||
podman manifest rm ${IMG} || true && \ | |||
podman build --build-arg TARGET_ARCH=amd64 --manifest=${IMG} . && \ |
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.
Can you add --platform
args here to prevent the issue you experienced above?
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.
That could potentially lead to additional issues. For instance, consider a scenario where your host can run applications designed for a different architecture. If this happens and the build fails silently due to incorrect parameters, the build process will run very slowly.
Dockerfile
Outdated
|
||
|
||
FROM registry.access.redhat.com/ubi8/ubi-minimal | ||
FROM --platform=linux/${TARGET_ARCH} registry.access.redhat.com/ubi8/ubi-micro |
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 tried it myself, and even though I got it working, for the builder we need to stay on ubi-minimal
, because ubi-micro
has no dnf
to install dependencies of the build. But for the final image we should keep it.
db0c550
to
1a4900b
Compare
Hello @0xFelix, could you please specify if there are any aspects of the PR that require clarification? Additionally, could you indicate the level of detail you need? |
This feature utilizes cross-compiling to generate binary files for the amd64, s390x and arm64 architectures, followed by the creation of images. Signed-off-by: Nestor Acuna-Blanco <nestor.acuna@ibm.com>
1a4900b
to
ece5884
Compare
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.
/lgtm
Thanks for adding the explanation.
@akrejcir: new pull request created: #179 In response to this:
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. |
This feature utilizes cross-compiling to generate binary files for the amd64 and s390x architectures, followed by the creation of images for both architectures.
What this PR does / why we need it: multiarch images enablement
Which issue(s) this PR fixes:
Fixes #
Special notes for your reviewer:
Release note: