Skip to content

Commit aa036bf

Browse files
committed
x86 to arm64 on gke
1 parent a72f352 commit aa036bf

7 files changed

Lines changed: 815 additions & 1 deletion

File tree

assets/contributors.csv

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,5 @@ Alejandro Martinez Vicente,Arm,,,,
104104
Mohamad Najem,Arm,,,,
105105
Ruifeng Wang,Arm,,,,
106106
Zenon Zhilong Xiu,Arm,,zenon-zhilong-xiu-491bb398,,
107-
Zbynek Roubalik,Kedify,,,,
107+
Zbynek Roubalik,Kedify,,,,
108+
Rani Chowdary Mandepudi, Arm,,,,
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
---
2+
title: From x86 to Arm on GKE - Build, Deploy, and Migrate with Google Axion
3+
draft: true
4+
cascade:
5+
draft: true
6+
7+
minutes_to_complete: 90
8+
9+
who_is_this_for: This learning path is for cloud, platform and SRE engineers operating Kubernetes on Google Cloud who need a prescriptive path to build multi‑arch images and migrate services from x86 to Arm (Google Axion) using production‑grade practices.
10+
11+
learning_objectives:
12+
13+
- Build and publish Docker images that support both amd64 and arm64 with Docker Buildx and Artifact Registry.
14+
- Create a GKE Standard cluster with x86 (amd64) nodes and add an Arm (arm64) node pool using Axion-based C4A machine types.
15+
- Deploy to amd64 first, then migrate to arm64 using Kustomize overlays for safe, incremental rollout.
16+
- Optionally automate builds and rollouts end-to-end with Cloud Build and Skaffold.
17+
18+
prerequisites:
19+
- A [Google Cloud account](https://console.cloud.google.com/)with billing enabled.
20+
- Cloud Shell access (recommended) to run all steps in the browser; no local setup required.
21+
- (Optional if not using Cloud Shell) A Linux/macOS workstation with Docker (Buildx enabled), kubectl, the Google Cloud CLI (gcloud), and Git.
22+
- Basic familiarity with Docker, Kubernetes, and gcloud.
23+
24+
author:
25+
- Pranay Bakre
26+
- Rani Chowdary Mandepudi
27+
28+
### Tags
29+
skilllevels: Advanced
30+
subjects: Containers and Virtualization
31+
armips:
32+
- Neoverse
33+
operatingsystems:
34+
- Linux
35+
tools_software_languages:
36+
- Kubernetes
37+
38+
39+
further_reading:
40+
- resource:
41+
title: GKE documentation
42+
link: https://cloud.google.com/kubernetes-engine/docs
43+
type: documentation
44+
- resource:
45+
title: Create Arm based clusters and node pools
46+
link: https://cloud.google.com/kubernetes-engine/docs/how-to/create-arm-clusters-nodes
47+
type: documentation
48+
49+
50+
51+
52+
53+
### FIXED, DO NOT MODIFY
54+
# ================================================================================
55+
weight: 1 # _index.md always has weight of 1 to order correctly
56+
layout: "learningpathall" # All files under learning paths have this same wrapper
57+
learning_path_main_page: "yes" # This should be surfaced when looking for related content. Only set for _index.md of learning path content.
58+
---
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
# ================================================================================
3+
# FIXED, DO NOT MODIFY THIS FILE
4+
# ================================================================================
5+
weight: 21 # Set to always be larger than the content in this path to be at the end of the navigation.
6+
title: "Next Steps" # Always the same, html page title.
7+
layout: "learningpathall" # All files under learning paths have this same wrapper for Hugo processing.
8+
---
Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
---
2+
title: Automate builds and rollout with Cloud Build & Skaffold
3+
weight: 5
4+
5+
### FIXED, DO NOT MODIFY
6+
layout: learningpathall
7+
---
8+
9+
Google [**Cloud Build**](https://cloud.google.com/build/docs/set-up) is a managed CI/CD service that runs your containerized build and deploy steps in isolated runners. In this page you'll automate the flow you performed manually: **build multi-arch images, deploy to GKE on amd64, then migrate to arm64**, and print the app's external IP.
10+
11+
## What this pipeline does
12+
- Authenticates Docker to **Artifact Registry**.
13+
- Builds and pushes **amd64 + arm64** images with **Docker Buildx** (QEMU enabled in the runner).
14+
- Connects to your **GKE** cluster.
15+
- Applies the **amd64** Kustomize overlay, verifies pods, then applies the **arm64** overlay and verifies again.
16+
- Prints the **frontend-external** LoadBalancer IP at the end.
17+
18+
19+
{{% notice Tip %}}
20+
Run this from the **microservices-demo** repo root in **Cloud Shell**. Ensure you completed earlier pages (GAR created, images path/tag decided, GKE cluster with amd64 + arm64 node pools, and Kustomize overlays present).
21+
{{% /notice %}}
22+
23+
## Grant IAM to the Cloud Build service account
24+
Cloud Build runs as a per-project service account: `<PROJECT_NUMBER>@cloudbuild.gserviceaccount.com`. Grant it the minimal roles needed to build, push, log, and interact with GKE.
25+
26+
```bash
27+
# Uses env vars set earlier: PROJECT_ID, REGION, CLUSTER_NAME, GAR
28+
PROJECT_NUMBER="$(gcloud projects describe "${PROJECT_ID}" --format='value(projectNumber)')"
29+
CLOUD_BUILD_SA="${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com"
30+
31+
gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
32+
--member="serviceAccount:${CLOUD_BUILD_SA}" \
33+
--role="roles/cloudbuild.builds.builder"
34+
35+
gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
36+
--member="serviceAccount:${CLOUD_BUILD_SA}" \
37+
--role="roles/container.developer"
38+
39+
gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
40+
--member="serviceAccount:${CLOUD_BUILD_SA}" \
41+
--role="roles/artifactregistry.writer"
42+
43+
gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
44+
--member="serviceAccount:${CLOUD_BUILD_SA}" \
45+
--role="roles/logging.logWriter"
46+
```
47+
48+
## Update skaffold.yaml for deploy-only
49+
50+
This will let Cloud Build handle image builds and use Skaffold only to apply the Kustomize overlays.
51+
52+
```yaml
53+
apiVersion: skaffold/v3
54+
kind: Config
55+
metadata:
56+
name: app
57+
manifests:
58+
kustomize:
59+
paths:
60+
- kustomize/base
61+
deploy:
62+
kubectl: {}
63+
profiles:
64+
- name: deploy-amd
65+
patches:
66+
- op: replace
67+
path: /manifests/kustomize/paths/0
68+
value: kustomize/overlays/amd64
69+
- name: migrate-arm
70+
patches:
71+
- op: replace
72+
path: /manifests/kustomize/paths/0
73+
value: kustomize/overlays/arm64
74+
---
75+
apiVersion: skaffold/v3
76+
kind: Config
77+
metadata:
78+
name: loadgenerator
79+
requires:
80+
- configs: [app]
81+
manifests:
82+
rawYaml:
83+
- ./kubernetes-manifests/loadgenerator.yaml
84+
deploy:
85+
kubectl: {}
86+
87+
```
88+
89+
## Create cloudbuild.yaml
90+
91+
This pipeline installs `Docker + Buildx` in the runner, enables QEMU, builds two services as examples (extend as desired), connects to your cluster, deploys to amd64, verifies, migrates to arm64, verifies, and prints the external IP. 
92+
93+
```yaml
94+
substitutions:
95+
_REGION: ${REGION}
96+
_CLUSTER: ${CLUSTER_NAME}
97+
_REPO: ${GAR}
98+
99+
options:
100+
machineType: "N1_HIGHCPU_8"
101+
logging: CLOUD_LOGGING_ONLY
102+
timeout: "7200s"
103+
104+
steps:
105+
# 1) Authenticate Docker to Artifact Registry
106+
- name: gcr.io/google.com/cloudsdktool/cloud-sdk
107+
entrypoint: bash
108+
args:
109+
- -ceu
110+
- |
111+
echo "Auth to GAR..."
112+
gcloud auth configure-docker "$(echo "${_REPO}" | awk -F/ '{print $1}')" --quiet
113+
114+
# 2) Build and push multi-arch images (examples: adservice, cartservice)
115+
- name: gcr.io/google.com/cloudsdktool/google-cloud-cli:stable
116+
entrypoint: bash
117+
env:
118+
- DOCKER_BUILDKIT=1
119+
- CLOUDSDK_CORE_DISABLE_PROMPTS=1
120+
args:
121+
- -ceu
122+
- |
123+
apt-get update && apt-get install -y docker.io curl
124+
mkdir -p ~/.docker/cli-plugins/
125+
curl -sSL https://github.com/docker/buildx/releases/download/v0.14.0/buildx-v0.14.0.linux-amd64 \
126+
-o ~/.docker/cli-plugins/docker-buildx
127+
chmod +x ~/.docker/cli-plugins/docker-buildx
128+
129+
# Start Docker daemon in the runner
130+
dockerd > /var/log/dockerd.log 2>&1 &
131+
timeout 30 sh -c 'until docker info >/dev/null 2>&1; do sleep 1; done'
132+
133+
# Enable QEMU for cross-arch builds and create builder
134+
docker run --privileged --rm tonistiigi/binfmt --install all
135+
docker buildx create --name multi --use || true
136+
docker buildx inspect --bootstrap
137+
138+
# Build and push multi-arch images
139+
docker buildx build --platform linux/amd64,linux/arm64 \
140+
-t "${_REPO}/adservice:v1" \
141+
src/adservice --push
142+
143+
docker buildx build --platform linux/amd64,linux/arm64 \
144+
-t "${_REPO}/cartservice:v1" \
145+
src/cartservice --push
146+
147+
# 3) Connect kubectl to the target cluster
148+
- name: gcr.io/google.com/cloudsdktool/cloud-sdk:slim
149+
entrypoint: bash
150+
args:
151+
- -ceu
152+
- |
153+
gcloud container clusters get-credentials "${_CLUSTER}" --region "${_REGION}"
154+
155+
# 4) Deploy to amd64 node pool
156+
- name: gcr.io/k8s-skaffold/skaffold:v2.16.1
157+
id: deploy-amd
158+
entrypoint: bash
159+
args:
160+
- -ceu
161+
- |
162+
skaffold deploy --filename=skaffold.yaml --config loadgenerator -p deploy-amd
163+
164+
# 5) Verify pods on amd64
165+
- name: gcr.io/google.com/cloudsdktool/cloud-sdk:latest
166+
entrypoint: bash
167+
args:
168+
- -ceu
169+
- |
170+
echo "Pods on amd64:"
171+
kubectl get pods -o wide
172+
173+
# 6) Migrate to arm64 node pool
174+
- name: gcr.io/k8s-skaffold/skaffold:v2.16.1
175+
id: migrate-arm
176+
entrypoint: bash
177+
args:
178+
- -ceu
179+
- |
180+
skaffold deploy --filename=skaffold.yaml --config loadgenerator -p migrate-arm
181+
182+
# 7) Verify pods on arm64 and print the external IP
183+
- name: gcr.io/google.com/cloudsdktool/cloud-sdk:latest
184+
entrypoint: bash
185+
args:
186+
- -ceu
187+
- |
188+
echo "Pods on arm64:"
189+
kubectl get pods -o wide
190+
echo "Fetching external IP for the frontend service..."
191+
IP=$(kubectl get svc frontend-external -o=jsonpath='{.status.loadBalancer.ingress[0].ip}')
192+
echo "Open http://${IP} in your browser."
193+
```
194+
195+
{{% notice Note %}}
196+
In production, add one build step per microservice (or a loop) and enable caching. The example above builds two images for brevity, mirroring the manual steps you completed earlier. 
197+
{{% /notice %}}
198+
199+
## Run the pipeline
200+
201+
From the repo root:
202+
203+
```bash
204+
gcloud builds submit --config=cloudbuild.yaml --substitutions=_CLUSTER="${CLUSTER_NAME}",_REGION="${REGION}",_REPO="${GAR}"
205+
```
206+
207+
The final step prints in the build description:
208+
209+
```
210+
Open http://<EXTERNAL-IP> in your browser.
211+
```
212+
213+
Open that URL to load the storefront and confirm the full build - deploy - migrate flow is automated.

0 commit comments

Comments
 (0)