Add guide on creating multi-arch manifests (#2306)
* Add guide on creating multi-arch manifests While kaniko itself does not natively support building multi-arch container manifests, it may be used in combination with tools such as manifest-tool to create and merge seperate arch builds into a single manifest. Fixes https://github.com/GoogleContainerTools/kaniko/issues/1102 Fixes https://github.com/GoogleContainerTools/kaniko/issues/786 * Add missing toc entry
This commit is contained in:
parent
c1436d4c70
commit
cce5d313b3
168
README.md
168
README.md
|
|
@ -94,6 +94,7 @@ _If you are interested in contributing to kaniko, see
|
||||||
- [Flag `--oci-layout-path`](#flag---oci-layout-path)
|
- [Flag `--oci-layout-path`](#flag---oci-layout-path)
|
||||||
- [Flag `--push-retry`](#flag---push-retry)
|
- [Flag `--push-retry`](#flag---push-retry)
|
||||||
- [Flag `--registry-certificate`](#flag---registry-certificate)
|
- [Flag `--registry-certificate`](#flag---registry-certificate)
|
||||||
|
- [Flag `--registry-client-cert`](#flag---registry-client-cert)
|
||||||
- [Flag `--registry-mirror`](#flag---registry-mirror)
|
- [Flag `--registry-mirror`](#flag---registry-mirror)
|
||||||
- [Flag `--reproducible`](#flag---reproducible)
|
- [Flag `--reproducible`](#flag---reproducible)
|
||||||
- [Flag `--single-snapshot`](#flag---single-snapshot)
|
- [Flag `--single-snapshot`](#flag---single-snapshot)
|
||||||
|
|
@ -113,6 +114,13 @@ _If you are interested in contributing to kaniko, see
|
||||||
- [Security](#security)
|
- [Security](#security)
|
||||||
- [Verifying Signed Kaniko Images](#verifying-signed-kaniko-images)
|
- [Verifying Signed Kaniko Images](#verifying-signed-kaniko-images)
|
||||||
- [Kaniko Builds - Profiling](#kaniko-builds---profiling)
|
- [Kaniko Builds - Profiling](#kaniko-builds---profiling)
|
||||||
|
- [Creating Multi-arch Container Manifests Using Kaniko and Manifest-tool](#creating-multi-arch-container-manifests-using-kaniko-and-manifest-tool)
|
||||||
|
- [General Workflow](#general-workflow)
|
||||||
|
- [Limitations and Pitfalls](#limitations-and-pitfalls)
|
||||||
|
- [Example CI Pipeline (GitLab)](#example-ci-pipeline-gitlab)
|
||||||
|
- [Building the Separate Container Images](#building-the-separate-container-images)
|
||||||
|
- [Merging the Container Manifests](#merging-the-container-manifests)
|
||||||
|
- [On the Note of Adding Versioned Tags](#on-the-note-of-adding-versioned-tags)
|
||||||
- [Comparison with Other Tools](#comparison-with-other-tools)
|
- [Comparison with Other Tools](#comparison-with-other-tools)
|
||||||
- [Community](#community-1)
|
- [Community](#community-1)
|
||||||
- [Limitations](#limitations)
|
- [Limitations](#limitations)
|
||||||
|
|
@ -1135,6 +1143,163 @@ profiling,
|
||||||
2. If you are using the kaniko `debug` image, you can copy the file in the
|
2. If you are using the kaniko `debug` image, you can copy the file in the
|
||||||
`pre-stop` container lifecycle hook.
|
`pre-stop` container lifecycle hook.
|
||||||
|
|
||||||
|
## Creating Multi-arch Container Manifests Using Kaniko and Manifest-tool
|
||||||
|
|
||||||
|
While Kaniko itself currently does not support creating multi-arch manifests
|
||||||
|
(contributions welcome), one can use tools such as [manifest-tool](https://github.com/estesp/manifest-tool)
|
||||||
|
to stitch multiple separate builds together into a single container manifest.
|
||||||
|
|
||||||
|
### General Workflow
|
||||||
|
|
||||||
|
The general workflow for creating multi-arch manifests is as follows:
|
||||||
|
|
||||||
|
1. Build separate container images using Kaniko on build hosts matching your
|
||||||
|
target architecture and tag them with the appropriate ARCH tag.
|
||||||
|
2. Push the separate images to your container registry.
|
||||||
|
3. Manifest-tool identifies the separate manifests in your container registry,
|
||||||
|
according to a given template.
|
||||||
|
4. Manifest-tool pushes a combined manifest referencing the separate manifests.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Limitations and Pitfalls
|
||||||
|
|
||||||
|
The following conditions must be met:
|
||||||
|
|
||||||
|
1. You need access to build-machines running the desired architectures
|
||||||
|
(running Kaniko in an emulator, e.g. QEMU should also be possible but goes
|
||||||
|
beyond the scope of this documentation). This is something to keep in mind
|
||||||
|
when using SaaS build tools such as github.com or gitlab.com, of which at the
|
||||||
|
time of writing neither supports any non-x86_64 SaaS runners ([GitHub](https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources),[GitLab](https://docs.gitlab.com/ee/ci/runners/saas/linux_saas_runner.html#machine-types-available-for-private-projects-x86-64)),
|
||||||
|
so be prepared to bring your own machines ([GitHub](https://docs.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners),[GitLab](https://docs.gitlab.com/runner/register/).
|
||||||
|
2. Kaniko needs to be able to run on the desired architectures. At the time of
|
||||||
|
writing, the official Kaniko container supports [linux/amd64, linux/arm64,
|
||||||
|
linux/s390x and linux/ppc64le (not on *-debug images)](https://github.com/GoogleContainerTools/kaniko/blob/main/.github/workflows/images.yaml).
|
||||||
|
3. The container registry of your choice must be OCIv1 or Docker v2.2
|
||||||
|
compatible.
|
||||||
|
|
||||||
|
### Example CI Pipeline (GitLab)
|
||||||
|
|
||||||
|
It is up to you to find an automation tool that suits your needs best.
|
||||||
|
We recommend using a modern CI/CD system such as GitHub workflows or GitLab CI.
|
||||||
|
As we (the authors) happen to use GitLab CI, the following examples are
|
||||||
|
tailored to this specific platform but the underlying principles should apply
|
||||||
|
anywhere else and the examples are kept simple enough, so that you should be
|
||||||
|
able to follow along, even without any previous experiences with this specific
|
||||||
|
platform. When in doubt, visit the [gitlab-ci.yml reference page](https://docs.gitlab.com/ee/ci/yaml/index.html)
|
||||||
|
for a comprehensive overview of the GitLab CI keywords.
|
||||||
|
|
||||||
|
#### Building the Separate Container Images
|
||||||
|
|
||||||
|
gitlab-ci.yml:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# define a job for building the containers
|
||||||
|
build-container:
|
||||||
|
stage: container-build
|
||||||
|
# run parallel builds for the desired architectures
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- ARCH: amd64
|
||||||
|
- ARCH: arm64
|
||||||
|
tags:
|
||||||
|
# run each build on a suitable, preconfigured runner (must match the target architecture)
|
||||||
|
- runner-${ARCH}
|
||||||
|
image:
|
||||||
|
name: gcr.io/kaniko-project/executor:debug
|
||||||
|
entrypoint: [""]
|
||||||
|
script:
|
||||||
|
# build the container image for the current arch using kaniko
|
||||||
|
- >-
|
||||||
|
/kaniko/executor
|
||||||
|
--context "${CI_PROJECT_DIR}"
|
||||||
|
--dockerfile "${CI_PROJECT_DIR}/Dockerfile"
|
||||||
|
# push the image to the GitLab container registry, add the current arch as tag.
|
||||||
|
--destination "${CI_REGISTRY_IMAGE}:${ARCH}"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Merging the Container Manifests
|
||||||
|
|
||||||
|
gitlab-ci.yml:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# define a job for creating and pushing a merged manifest
|
||||||
|
merge-manifests:
|
||||||
|
stage: container-build
|
||||||
|
# all containers must be build before merging them
|
||||||
|
# alternatively the job may be configured to run in a later stage
|
||||||
|
needs:
|
||||||
|
- container-build
|
||||||
|
artifacts: false
|
||||||
|
tags:
|
||||||
|
# may run on any architecture supported by manifest-tool image
|
||||||
|
- runner-xyz
|
||||||
|
image:
|
||||||
|
name: mplatform/manifest-tool:alpine
|
||||||
|
script:
|
||||||
|
- >-
|
||||||
|
manifest-tool
|
||||||
|
# authorize against your container registry
|
||||||
|
--username=${CI_REGISTRY_USER}
|
||||||
|
--password=${CI_REGISTRY_PASSWORD}
|
||||||
|
push from-args
|
||||||
|
# define the architectures you want to merge
|
||||||
|
--platforms linux/amd64,linux/arm64
|
||||||
|
# "ARCH" will be automatically replaced by manifest-tool
|
||||||
|
# with the appropriate arch from the platform definitions
|
||||||
|
--template ${CI_REGISTRY_IMAGE}:ARCH
|
||||||
|
# The name of the final, combined image which will be pushed to your registry
|
||||||
|
--target ${CI_REGISTRY_IMAGE}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### On the Note of Adding Versioned Tags
|
||||||
|
|
||||||
|
For simplicity's sake we deliberately refrained from using versioned
|
||||||
|
tagged images (all builds will be tagged as "latest") in the
|
||||||
|
previous examples, as we feel like this adds to much platform and workflow
|
||||||
|
specific code.
|
||||||
|
|
||||||
|
Nethertheless, for anyone interested in how we handle (dynamic) versioning in
|
||||||
|
GitLab, here is a short rundown:
|
||||||
|
|
||||||
|
- If you are only interested in building tagged releases, you can simply
|
||||||
|
use the [GitLab predefined](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html) `CI_COMMIT_TAG` variable when running a tag pipeline.
|
||||||
|
- When you (like us) want to additionally build container images outside of
|
||||||
|
releases, things get a bit messier. In our case, we added a additional job
|
||||||
|
which runs before the build and merge jobs (don't forget to extend the `needs`
|
||||||
|
section of the build and merge jobs accordingly), which will set the tag to
|
||||||
|
`latest` when running on the default branch, to the commit hash when run on
|
||||||
|
other branches and to the release tag when run on a tag pipeline.
|
||||||
|
|
||||||
|
gitlab-ci.yml:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
container-get-tag:
|
||||||
|
stage: pre-container-build-stage
|
||||||
|
tags:
|
||||||
|
- runner-xyz
|
||||||
|
image: busybox
|
||||||
|
script:
|
||||||
|
# All other branches are tagged with the currently built commit SHA hash
|
||||||
|
- |
|
||||||
|
# If pipeline runs on the default branch: Set tag to "latest"
|
||||||
|
if test "$CI_COMMIT_BRANCH" == "$CI_DEFAULT_BRANCH"; then
|
||||||
|
tag="latest"
|
||||||
|
# If pipeline is a tag pipeline, set tag to the git commit tag
|
||||||
|
elif test -n "$CI_COMMIT_TAG"; then
|
||||||
|
tag="$CI_COMMIT_TAG"
|
||||||
|
# Else set the tag to the git commit sha
|
||||||
|
else
|
||||||
|
tag="$CI_COMMIT_SHA"
|
||||||
|
fi
|
||||||
|
- echo "tag=$tag" > build.env
|
||||||
|
# parse tag to the build and merge jobs.
|
||||||
|
# See: https://docs.gitlab.com/ee/ci/variables/#pass-an-environment-variable-to-another-job
|
||||||
|
artifacts:
|
||||||
|
reports:
|
||||||
|
dotenv: build.env
|
||||||
|
```
|
||||||
|
|
||||||
## Comparison with Other Tools
|
## Comparison with Other Tools
|
||||||
|
|
||||||
Similar tools include:
|
Similar tools include:
|
||||||
|
|
@ -1152,7 +1317,8 @@ All of these tools build container images with different approaches.
|
||||||
BuildKit (and `img`) can perform as a non-root user from within a container but
|
BuildKit (and `img`) can perform as a non-root user from within a container but
|
||||||
requires seccomp and AppArmor to be disabled to create nested containers.
|
requires seccomp and AppArmor to be disabled to create nested containers.
|
||||||
`kaniko` does not actually create nested containers, so it does not require
|
`kaniko` does not actually create nested containers, so it does not require
|
||||||
seccomp and AppArmor to be disabled.
|
seccomp and AppArmor to be disabled. BuildKit supports "cross-building"
|
||||||
|
multi-arch containers by leveraging QEMU.
|
||||||
|
|
||||||
`orca-build` depends on `runc` to build images from Dockerfiles, which can not
|
`orca-build` depends on `runc` to build images from Dockerfiles, which can not
|
||||||
run inside a container (for similar reasons to `img` above). `kaniko` doesn't
|
run inside a container (for similar reasons to `img` above). `kaniko` doesn't
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 12 KiB |
Loading…
Reference in New Issue