zuul-jobs/roles/build-container-image/common.rst
Clark Boylan 5994ce4049 Gracefully handle use of intermediate registry in container upload role
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
2023-05-09 16:18:42 -07:00

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:

  • :zuulbuild-container-image: Build the images.
  • :zuulupload-container-image: Upload the images to a registry.
  • :zuulpromote-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:

  1. 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> to change_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 to tag. Otherwise we skip upload to the registry.

  2. 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 :zuulbuild-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 for docker and Containerfile (with a fallback on Dockerfile) for podman.