|
| 1 | +--- |
| 2 | +title: How to Migrate an x86 Workload to Arm64 on AWS |
| 3 | +weight: 2 |
| 4 | + |
| 5 | +### FIXED, DO NOT MODIFY |
| 6 | +layout: learningpathall |
| 7 | +--- |
| 8 | + |
| 9 | +### 1. Assess Workload Compatibility |
| 10 | + |
| 11 | +Before migrating, determine whether your applications can run on 64-bit Arm architecture. Most modern applications built with portable runtimes (e.g., Java, Go, Python, Node.js) can run seamlessly on 64-bit Arm with little or no modifications. Check your container images and dependencies for 64-bit Arm compatibility. Fortunately, our [pipelines-tutorial](https://www.google.com/url?q=https://github.com/openshift/pipelines-tutorial&sa=D&source=editors&ust=1749822472442265&usg=AOvVaw1m8Dc2XNThwRLw9jJ9AX-L) doesn't have these restrictions. |
| 12 | + |
| 13 | +### 2. Enable Multi-Arch Support in Red Hat OpenShift |
| 14 | + |
| 15 | +Red Hat OpenShift supports multi-architecture workloads, allowing you to run both 64-bit x86 and 64-bit Arm based nodes in the same cluster. Red Hat OpenShift's [documentation](https://www.google.com/url?q=https://docs.redhat.com/en/documentation/openshift_container_platform/4.18/html/postinstallation_configuration/configuring-multi-architecture-compute-machines-on-an-openshift-cluster%23multi-architecture-verifying-cluster-compatibility_creating-multi-arch-compute-nodes-aws&sa=D&source=editors&ust=1749822472444182&usg=AOvVaw3zaXidSPcmXJdpHXRLF8jq) will be your guide for this process. |
| 16 | + |
| 17 | +### 3. Add 64-bit Arm MachineSets |
| 18 | + |
| 19 | +To migrate to Graviton-based EC2 instances: |
| 20 | + |
| 21 | +Ensure that the Red Hat Openshift cluster is using the multi-arch release payload. |
| 22 | + |
| 23 | +``` |
| 24 | +$oc adm release info -o jsonpath="{ .metadata.metadata}" |
| 25 | +{"release.openshift.io/architecture":"multi","url":"https://access.redhat.com/errata/xxx"}$ |
| 26 | +
|
| 27 | +``` |
| 28 | + |
| 29 | +* Decide on a scheduling strategy. Manual with Taints/Tolerations, or [Multiarch Tuning O](https://www.google.com/url?q=https://docs.redhat.com/en/documentation/openshift_container_platform/4.18/html/postinstallation_configuration/configuring-multi-architecture-compute-machines-on-an-openshift-cluster%23multiarch-tuning-operator&sa=D&source=editors&ust=1749822472450131&usg=AOvVaw1zslJ0RW8K9Lq_t6bf9Jrt)[perator](https://www.google.com/url?q=https://docs.redhat.com/en/documentation/openshift_container_platform/4.18/html/postinstallation_configuration/configuring-multi-architecture-compute-machines-on-an-openshift-cluster%23multiarch-tuning-operator&sa=D&source=editors&ust=1749822472450917&usg=AOvVaw1QxXa3syc7ziLPLvut2YZv). |
| 30 | + Since we have 1 workload (our build pipeline) we'll go the Taint and Toleration routes. We've added this taint to our new Arm machine sets: |
| 31 | + |
| 32 | +``` |
| 33 | + taints: |
| 34 | +
|
| 35 | + - effect: NoSchedule |
| 36 | +
|
| 37 | + key: newarch |
| 38 | +
|
| 39 | + value: arm64 |
| 40 | +``` |
| 41 | +This prevents existing x86 workloads from being scheduled to the Arm nodes. |
| 42 | + |
| 43 | +* Reimport needed imagestreams with import-mode set to 'PreserveOriginal' |
| 44 | + |
| 45 | +``` |
| 46 | + oc import-image php -n openshift --all --confirm --import-mode='PreserveOriginal' |
| 47 | + oc import-image python -n openshift --all --confirm --import-mode='PreserveOriginal' |
| 48 | +``` |
| 49 | + |
| 50 | +### 4. Rebuild and Verify Container Images |
| 51 | + |
| 52 | +Note: Red Hat OpenShift only supports native architecture container builds. Cross-architecture container builds are not supported. |
| 53 | + |
| 54 | +To build 64-bit Arm compatible images, we've modified the openshift-pipelines tutorial to patch deployments with the Tekton Task's podTemplate information. This will allow us to pass a podTemplate for building and deploying our newly built application on the target architecture. It also makes it easy to revert back to 64-bit x86 by re-running the pipeline without the template. |
| 55 | + |
| 56 | +Create a podTemplate defining a toleration and a node affinity to make the builds deploy on arm machines: |
| 57 | + |
| 58 | +arm64.yaml |
| 59 | +``` |
| 60 | +tolerations: |
| 61 | +
|
| 62 | +- key: "newarch" |
| 63 | +
|
| 64 | + value: "arm64" |
| 65 | +
|
| 66 | + operator: "Equal" |
| 67 | +
|
| 68 | + effect: "NoSchedule" |
| 69 | +
|
| 70 | + affinity: |
| 71 | +
|
| 72 | + nodeAffinity: |
| 73 | +
|
| 74 | + requiredDuringSchedulingIgnoredDuringExecution: |
| 75 | +
|
| 76 | + nodeSelectorTerms: |
| 77 | +
|
| 78 | + - matchExpressions: |
| 79 | +
|
| 80 | + - key: "kubernetes.io/arch" |
| 81 | +
|
| 82 | + operator: "In" |
| 83 | +
|
| 84 | + values: |
| 85 | +
|
| 86 | + * "arm64" |
| 87 | +
|
| 88 | + - key: "kubernetes.io/os" |
| 89 | +
|
| 90 | + operator: "In" |
| 91 | +
|
| 92 | + values: |
| 93 | +
|
| 94 | + - "linux" |
| 95 | +``` |
| 96 | + |
| 97 | +Next we update 02\_update\_deployment\_task.yaml |
| 98 | +This includes extract patching to include the podTemplate's nodeAffinity/tolerations. |
| 99 | + |
| 100 | +02\_update\_deployment\_task.yaml |
| 101 | +``` |
| 102 | +apiVersion: tekton.dev/v1 |
| 103 | +
|
| 104 | +kind: Task |
| 105 | +
|
| 106 | +metadata: |
| 107 | +
|
| 108 | +name: update-deployment |
| 109 | +
|
| 110 | +spec: |
| 111 | +
|
| 112 | +params: |
| 113 | +
|
| 114 | +- name: deployment |
| 115 | +
|
| 116 | + description: The name of the deployment patch the image |
| 117 | +
|
| 118 | + type: string |
| 119 | +
|
| 120 | +- name: IMAGE |
| 121 | +
|
| 122 | + description: Location of image to be patched with |
| 123 | +
|
| 124 | + type: string |
| 125 | +
|
| 126 | +- name: taskrun-name |
| 127 | +
|
| 128 | + type: string |
| 129 | +
|
| 130 | + description: Name of the current TaskRun (injected from context) |
| 131 | +
|
| 132 | + steps: |
| 133 | +
|
| 134 | + - name: patch |
| 135 | +
|
| 136 | + image: image-registry.openshift-image-registry.svc:5000/openshift/cli:latest |
| 137 | +
|
| 138 | + command: \["/bin/bash", "-c"\] |
| 139 | +
|
| 140 | + args: |
| 141 | +
|
| 142 | + - |- |
| 143 | +
|
| 144 | + oc patch deployment $(inputs.params.deployment) --patch='{"spec":{"template":{"spec":{ |
| 145 | +
|
| 146 | + "containers":\[{ |
| 147 | +
|
| 148 | + "name": "$(inputs.params.deployment)", |
| 149 | +
|
| 150 | + "image":"$(inputs.params.IMAGE)" |
| 151 | +
|
| 152 | + }\] |
| 153 | +
|
| 154 | + }}}}' |
| 155 | +
|
| 156 | + \# Find my own TaskRun name |
| 157 | +
|
| 158 | + MY\_TASKRUN\_NAME="$(params.taskrun-name)" |
| 159 | +
|
| 160 | + echo "TaskRun name: $MY\_TASKRUN\_NAME" |
| 161 | +
|
| 162 | + \# Fetch the podTemplate |
| 163 | +
|
| 164 | + PODTEMPLATE\_JSON=$(kubectl get taskrun "$MY\_TASKRUN\_NAME" -o jsonpath='{.spec.podTemplate}') |
| 165 | +
|
| 166 | + if \[ -z "$PODTEMPLATE\_JSON" \]; then |
| 167 | +
|
| 168 | + echo "No podTemplate found in TaskRun...Remove tolerations and affinity." |
| 169 | +
|
| 170 | + oc patch deployment "$(inputs.params.deployment)" \\\\ |
| 171 | +
|
| 172 | + --type merge \\\\ |
| 173 | +
|
| 174 | + -p "{\\"spec\\": {\\"template\\": {\\"spec\\": {\\"tolerations\\": null, \\"affinity\\": null}}}}" |
| 175 | +
|
| 176 | + else |
| 177 | +
|
| 178 | + echo "Found podTemplate:" |
| 179 | +
|
| 180 | + echo "$PODTEMPLATE\_JSON" |
| 181 | +
|
| 182 | + oc patch deployment "$(inputs.params.deployment)" \\\\ |
| 183 | +
|
| 184 | + --type merge \\\\ |
| 185 | +
|
| 186 | + -p "{\\"spec\\": {\\"template\\": {\\"spec\\": $PODTEMPLATE\_JSON }}}" |
| 187 | +
|
| 188 | + fi |
| 189 | +
|
| 190 | + \# issue: https://issues.redhat.com/browse/SRVKP-2387 |
| 191 | +
|
| 192 | + \# images are deployed with tag. on rebuild of the image tags are not updated, hence redeploy is not happening |
| 193 | +
|
| 194 | + \# as a workaround update a label in template, which triggers redeploy pods |
| 195 | +
|
| 196 | + \# target label: "spec.template.metadata.labels.patched\_at" |
| 197 | +
|
| 198 | + \# NOTE: this workaround works only if the pod spec has imagePullPolicy: Always |
| 199 | +
|
| 200 | + patched\_at\_timestamp=\`date +%s\` |
| 201 | +
|
| 202 | + oc patch deployment $(inputs.params.deployment) --patch='{"spec":{"template":{"metadata":{ |
| 203 | +
|
| 204 | + "labels":{ |
| 205 | +
|
| 206 | + "patched\_at": '\\"$patched\_at\_timestamp\\"' |
| 207 | +
|
| 208 | + } |
| 209 | +
|
| 210 | + }}}}' |
| 211 | +``` |
| 212 | +And we need to update 04\_pipeline.yaml to pass the taskrun-name to the update-deployment task: |
| 213 | + |
| 214 | +``` |
| 215 | +- name: update-deployment |
| 216 | +
|
| 217 | + taskRef: |
| 218 | +
|
| 219 | + name: update-deployment |
| 220 | +
|
| 221 | + params: |
| 222 | +
|
| 223 | + - name: deployment |
| 224 | +
|
| 225 | + value: $(params.deployment-name) |
| 226 | +
|
| 227 | + - name: IMAGE |
| 228 | +
|
| 229 | + value: $(params.IMAGE) |
| 230 | +
|
| 231 | + - name: taskrun-name //add these |
| 232 | +
|
| 233 | + value: $(context.taskRun.name) //lines |
| 234 | +``` |
| 235 | + |
| 236 | +Now we can redeploy the UI and API using the arm64.yaml podTemplate. This will force all parts of the build pipeline and deployment to our tainted 64-bit Arm nodes. |
| 237 | +``` |
| 238 | +tkn pipeline start build-and-deploy \\\\ |
| 239 | +
|
| 240 | +--prefix-name build-deploy-api-pipelinerun-arm64 \\\\ |
| 241 | +
|
| 242 | +-w name=shared-workspace,volumeClaimTemplateFile=https://raw.githubusercontent.com/openshift/pipelines-tutorial/master/01\_pipeline/03\_persistent\_volume\_claim.yaml \\\\ |
| 243 | +
|
| 244 | +-p deployment-name=pipelines-vote-api \\\\ |
| 245 | +
|
| 246 | +-p git-url=https://github.com/openshift/pipelines-vote-api.git \\\\ |
| 247 | +
|
| 248 | +-p IMAGE=image-registry.openshift-image-registry.svc:5000/pipelines-tutorial/pipelines-vote-api-arm64 |
| 249 | +
|
| 250 | +--use-param-defaults \\\\ |
| 251 | +--pod-template arm64.yaml |
| 252 | +``` |
| 253 | +``` |
| 254 | +tkn pipeline start build-and-deploy \\\\ |
| 255 | +
|
| 256 | +--prefix-name build-deploy-ui-pipelinerun-arm64 \\\\ |
| 257 | +
|
| 258 | +-w name=shared-workspace,volumeClaimTemplateFile=https://raw.githubusercontent.com/openshift/pipelines-tutorial/master/01\_pipeline/03\_persistent\_volume\_claim.yaml \\\\ |
| 259 | +
|
| 260 | +-p deployment-name=pipelines-vote-ui \\\\ |
| 261 | +
|
| 262 | +-p git-url=https://github.com/openshift/pipelines-vote-ui.git \\\\ |
| 263 | +
|
| 264 | +-p IMAGE=image-registry.openshift-image-registry.svc:5000/pipelines-tutorial/pipelines-vote-ui-arm64 \\\\ |
| 265 | +
|
| 266 | +--use-param-defaults \\\\ |
| 267 | +--pod-template arm64.yaml |
| 268 | +``` |
| 269 | + |
| 270 | +Once the pods are up and running, you can safely remove the x86 worker nodes from the cluster, and remove the taints from the Arm worker nodes (if you choose to do so). |
| 271 | + |
| 272 | + |
0 commit comments