For symmetry and ease of transition between the docker specific jobs/roles and generic container jobs/roles it is advantageous to have the container upload role skip pushing artifacts to the final registry location if we are relying on the intermediate registry instead. Update the container upload role to skip pushing to the actual registry if the promote var is set to intermediate registry. This allows us to avoid reshuffling all of our jobs as we migrate between the two implementations. Change-Id: I3cae9e03517cb0a5ce8e9369bf43fd052cac97ff
11 KiB
This is one of a collection of roles which are designed to work together to build, upload, and promote container images in a gating context:
- :zuul
build-container-image
: Build the images. - :zuul
upload-container-image
: Upload the images to a registry. - :zuul
promote-container-image
: Promote previously uploaded images.
All roles accept the same input data, principally a list of dictionaries representing the images to build. YAML anchors can be used to supply the same data to all three roles.
Building
The :zuulbuild-container-image
role is designed to be used in
check and gate pipelines and simply builds the images. It
can be used to verify that the build functions, or it can be followed by
the use of subsequent roles to upload the images to a registry.
Uploading
The :zuulupload-container-image
role uploads the images to a
registry. It can be used in one of two modes:
Using tags as part of a two-step promote pipeline. This mode is designed to minimize the time the published registry tag is out of sync with the changes Zuul has merged to the underlying code repository.
In this mode, the role is intended to run in the gate pipeline. Zuul will build and upload the resulting image with a single tag prefixed with the change ID (e.g.
change_12345_<tag>
). Thus at the completion of the gate job, all the layers of the new container are uploaded, but the<tag>
in the remote repository will not have been updated.Once the gate queue is successfully finished Zuul will merge the change to the code-repository. At this point, a small window opens where the
<tag>
is pointing to a container that does not reflect the state of the code-repository. The merge of the change will trigger the promote pipeline which uses a very quick, executor-only job to retag<tag>
tochange_12345_<tag>
. Since this step does not require any nodes or upload any data, it generally takes only a few seconds. The remote container pointed to by<tag>
will now reflect the underlying code closing the out-of-sync window.When running in this mode uploads are only made if
promote_container_image_method
is unset or set totag
. Otherwise we skip upload to the registry.The second mode allows for use of this job in release and tag pipelines to directly upload a release build with the final set of tags.
In this mode,
upload_container_image_promote: false
should be set. The role will build and upload the resulting image to the remote repository with the final tags.This should be used with tag and release pipelines, where committed code has been tagged for publishing. The tagged commit is "known good" thanks to gating, so the build and upload process is expected to work unconditionally.
This can be used in a post-commit pipeline, with the caveat that it has a much longer window where published code is out of sync with the published image, as the image must be completely rebuilt and uploaded after code merge in the gate job.
The alternative promote method can be thought of as a "speculative" upload. There is a possibility the gate job uploads layers and creates a temporary tag, but either the container upload or another co-gating job fails, causing the gate jobs to fail overall. This causes extra uploads, unsued layers and unused tags that require cleaning up. Since changes have merged before the release pipeline starts, the upload will simply not run if the gate jobs fail. This avoids uploading or tagging anything that will not be used. The trade-off is a higher latency between merging code and publishing final tags.
Transient network failures can cause upload errors in both cases. Although the promote job may fail, leaving the tag incorrectly unmodified, the promote job's relatively simplicity minimises potential error. The release pipeline does more work, exposing it to a higher chance of failures such as transient network errors etc., also resulting in the repository tag being out-of-date. In both cases developers must pay close attention as failures in these pipelines are often less noticable than code not merging with a gate-job failure.
Promoting
As discussed above, the :zuulpromote-container-image
role is designed to be used
in a promote pipeline.
In tag
mode, it re-tags a previously uploaded image by
copying the temporary change-id based tags made during upload to the
final production tags supplied by :zuulbuild-container-image.container_images.tags
. It is
intended to run very quickly and with no dependencies, so it can run
directly on the Zuul executor.
Once this role completes, the temporary upload tags are no longer
required. The role removes the change-id tags from the repository in the
registry, and removes any similar change-ids tags. This keeps the
repository tidy in the case that gated changes fail to merge after
uploading their staged images. Remvoing these tags is a registry
specific operation. You should double check the api_token
requirements for your registry described below. For more details see
:zuulremove-registry-tag
.
In intermediate-registry
mode, this role queries Zuul to
find the build performed by the build role in the gate
. It
then copies this image from the intermediate-registry to the final
location in the remote registry.
Dependencies
The build and upload roles require a container runtime that should be
installed before use; for example by using either the :zuulensure-docker
or :zuulensure-podman
roles. The
promote job assumes skopeo is available
on the executor.
Role Variables
The default container filename name to use. Serves as the base for :zuul
build-container-image.container_images.container_filename
. This allows a global overriding of the container filename name, for example when building all images from different folders with similarily named containerfiles.If omitted, the default depends on the container command used. Typically, this is
Dockerfile
fordocker
andContainerfile
(with a fallback onDockerfile
) forpodman
.