In this article, we’ll talk about the builds for Red Hat OpenShift operator and how it simplifies building multi-arch builds on clusters with compute nodes of mixed architecture. This lets you create a single build object as opposed to separate builds for each architecture, as needed for the standard build/BuildConfig
-based method in Red Hat OpenShift. The operator also takes care of creating and pushing a manifest list of the resulting images.
Building a manifest-listed image
Let’s walk through the process of building a manifest-listed image with 2 architectures on a multi-arch compute cluster.
We’ll accomplish this in the following steps:
- Prerequisites: A running multi-arch compute cluster and a client to interact with it. For this example, our cluster has nodes of amd64, and arm64.
- Install and configure the operator.
- Create a new project.
- Configure and add the ClusterBuildStrategy to our cluster.
- Create the build YAML and start the build.
- Verify the images are built for all architectures.
- Create and push a manifest list.
First, we need to install the oc client utility to interact with our multi-arch compute cluster. Check that oc
is installed correctly using the oc version
command. If you do not have oc
, you can follow the installation docs.
$ ./oc version
Client Version: 4.19.4
Kustomize Version: v5.5.0
Server Version: 4.19.2
Kubernetes Version: v1.32.5
To access a multi-arch compute cluster with the builds for Red Hat OpenShift operator available, you’ll need OpenShift Container Platform 4.17 or later. You will need your access credentials, such as the cluster URL and kubeconfig file provided during installation.
Our cluster looks like this:
$ oc get nodes --label-columns='kubernetes.io/arch'
NAME STATUS ROLES AGE VERSION ARCH
aarch64-01.example.com Ready worker 426d v1.32.5 arm64
aarch64-02.example.com Ready worker 426d v1.32.5 arm64
x86-04.example.com Ready worker 417d v1.32.5 amd64
x86-05.example.com Ready worker 408d v1.32.5 amd64
x86-01.example.com Ready control-plane,master 426d v1.32.5 amd64
x86-02.example.com Ready control-plane,master 426d v1.32.5 amd64
x86-03.example.com Ready control-plane,master 426d v1.32.5 amd64
Follow the installation section of the builds for Red Hat OpenShift documentation to install the operator using the web console or via CLI.
Use the verification steps included in the docs to ensure everything installed properly:
$ oc get openshiftbuilds
NAME AGE
cluster 23h
$ oc get shipwrightbuilds
NAME AGE
cluster-8hjrb 23h
openshift-builds 385d
openshift-builds-mrda 351d
$ oc get pods -n openshift-builds
NAME READY STATUS RESTARTS AGE
openshift-builds-operator-b59cc7f4d-47nxd 2/2 Running 0 23h
shared-resource-csi-driver-node-2m6jk 2/2 Running 0 23h
...
shared-resource-csi-driver-webhook-597d666db8-6nrpf 1/1 Running 0 23h
shipwright-build-controller-6b966c8dd9-45x57 1/1 Running 0 23h
shipwright-build-webhook-f656dd877-2skzb 1/1 Running 0 23h
Now that the operator is installed, you can use your cluster to create builds for multiple architectures simultaneously. We’ll do this by using the multiarch-native-buildah ClusterBuildStrategy. This creates jobs that place a build on nodes of the architectures you choose in your configuration and then stitches them together into a manifest list/index image.
You can find the YAML files used in this section here.
Let’s use oc
to log in to the cluster:
$ oc login --token=sha256~*********************************** --server=https://example.com:6443
Logged into "https://example.com:6443" as "kube:admin" using the token provided.
Using project "default".
Create a new project called demo
:
$ oc new-project demo
Now using project "demo" on server "https://example.com:6443"
Next, create a role and role bindings to ensure that you have permissions to work in the cluster:
$ oc apply -f ./clusterrole_multiarch_native_buildah_cr.yaml.yaml
role.rbac.authorization.k8s.io/multiarch-native-buildah-pipeline created
$ oc apply -f ./rolebinding_multiarch_native_buildah_cr.yaml
rolebinding.rbac.authorization.k8s.io/multiarch-native-buildah-pipeline created
$ oc apply -f ./rolebinding_multiarch_native_buildah_scc_okd_cr.yaml
rolebinding.rbac.authorization.k8s.io/multiarch-native-buildah-pipeline-scc-privileged created
Confirm that they were created correctly:
$ oc get clusterrole | grep multiarch
multiarch-native-buildah-pipeline
$ oc get rolebinding | grep multiarch
multiarch-native-buildah-pipeline ClusterRole/multiarch-native-buildah-pipeline 2m44s
multiarch-native-buildah-pipeline-scc-privileged ClusterRole/system:openshift:scc:privileged 2m35s
Apply the multiarch-native-buildah
ClusterBuildStrategy to the cluster:
$ oc apply -f ./buildstrategy_multiarch_native_buildah_cr.yaml
clusterbuildstrategy.shipwright.io/multiarch-native-buildah created
$ oc get clusterbuildstrategies | grep multiarch
multiarch-native-buildah 35s
Now that the ClusterBuildStrategy exists in the cluster and has the permissions to run, you can use it to create your builds. Let’s create a build YAML that specifies the 2 architectures in the cluster.
We’re pulling from the example in the Shipwright documentation for the strategy.
$ cat multiarch-native-buildah-example.yaml
---
apiVersion: shipwright.io/v1beta1
kind: Build
metadata:
name: multiarch-native-buildah-example
namespace: demo
spec:
source:
type: Git
git:
url: https://github.com/shipwright-io/sample-go
contextDir: docker-build
strategy:
name: multiarch-native-buildah
kind: ClusterBuildStrategy
paramValues:
- name: architectures
values:
- value: "amd64"
- value: "arm64"
- name: build-contexts
values:
- value: "ghcr.io/shipwright-io/shipwright-samples/golang:1.18=docker://ghcr.io/shipwright-io/shipwright-samples/golang:1.18"
# The buildah `--from` replaces the first FROM statement
- name: from
value: "" # Using the build-contexts for this example
# The runtime-stage-from implements the logic to replace the last stage FROM image of a Dockerfile
- name: runtime-stage-from
value: docker://gcr.io/distroless/static:nonroot
- name: dockerfile
value: Dockerfile
output:
image: image-registry.openshift-image-registry.svc:5000/build-examples/taxi-app
Now, you can trigger the build and see that it succeeds on all architectures:
$ oc create -f multiarch-native-buildah-example.yaml
build.shipwright.io/multiarch-native-buildah-example created
$ oc get BuildRun
NAME SUCCEEDED REASON STARTTIME COMPLETIONTIME
multiarch-native-buildah-example-52ff9 True Succeeded 91s 24s
$ oc get Jobs
NAME STATUS COMPLETIONS DURATION AGE
multiarch-native-buildah-example-52ff9-dr7dv-job-amd64 Complete 1/1 24s 72s
multiarch-native-buildah-example-52ff9-dr7dv-job-arm64 Complete 1/1 19s 72s
If you look at the logs for the build, you can see that artifacts were built for both architectures and the BuildRun
completed successfully after creating a manifest list of the 2 built images.
$ oc logs multiarch-native-buildah-example-zlk56-7rqc4-pod step-package-manifest-list-and-push
...
[INFO] Creating manifest list
d96bcabffb37bc10d84399b9955713ee59d2894da7b6980e4b8c14b6230b9b2f
[INFO] Adding the amd64 manifest to the manifest list
d96bcabffb37bc10d84399b9955713ee59d2894da7b6980e4b8c14b6230b9b2f: sha256:21284365a4ee6daf0fa5270826bbb5248599ec9d4d46a4d000532b1cd7073ad8
[INFO] Adding the arm64 manifest to the manifest list
d96bcabffb37bc10d84399b9955713ee59d2894da7b6980e4b8c14b6230b9b2f: sha256:1fec58eb2d9ad6ddbd3ff49410c0a1e8441b80e680b550e35f254c40cb43fe8b
[INFO] Pushing the manifest list taxi-app to the registry as image-registry.openshift-image-registry.svc:5000/build-examples/taxi-app
Getting image list signatures
Copying 2 images generated from 2 images in list
Copying image sha256:21284365a4ee6daf0fa5270826bbb5248599ec9d4d46a4d000532b1cd7073ad8 (1/4)
Getting image source signatures
Copying blob sha256:07e19bf3ffe596fa6f41a082b58c7e6397a8aa24ba7d601824b148a47ddfcd46
[INFO] Manifest list pushed successfully. BuildRun succeeded.
Summary
You have successfully created and run a build of two different architectures using the multiarch-native-buildah
ClusterBuildStrategy on our multi-arch cluster and built a manifest list of the resulting images, all in a single build object. Using builds for Red Hat OpenShift simplifies the process of using build and BuildConfig
objects manually, as we detailed in our previous article in this series.
The post Build on multi-arch clusters with builds for Red Hat OpenShift appeared first on Red Hat Developer.