Google Kubernetes Engine Pipeline using Cloud Build

Solution for Google Kubernetes Engine Pipeline using Cloud Build. 1 lab: GSP1077. Fast copy-paste commands for Google Cloud.

GSP1077 — Google Kubernetes Engine Pipeline using Cloud Build

Estimated time: 40 minutes

# 🚀 Google Kubernetes Engine Pipeline using Cloud Build > ⚠️ **Disclaimer:** This is an independent, community-made walkthrough created for educational purposes, hands-on practice, and Google Cloud certification preparation. This guide is designed to help learners understand Google Cloud services and complete practical exercises. Always attempt the lab yourself first and follow Google Cloud Skills Boost / Qwiklabs Terms of Service. This walkthrough is not affiliated with or endorsed by Google,

#!/bin/bash
# ==============================================================================
# ORBIT OF OPS - PART 1: INFRASTRUCTURE & APP REPO SETUP
# ==============================================================================
GREEN='\e[1;32m'
CYAN='\e[1;36m'
YELLOW='\e[1;33m'
BLUE='\e[1;34m'
MAGENTA='\e[1;35m'
WHITE='\e[1;37m'
RED='\e[1;31m'
RESET='\e[0m'
BOLD='\e[1m'

clear
echo -e "${CYAN}${BOLD}"
cat << "EOF"
  ____       _     _ _            __    ___            
 / __ \     | |   (_) |          / _|  / _ \           
| |  | |_ __| |__  _| |_   ___  | |_  | | | |_ __  ___ 
| |  | | '__| '_ \| | __| / _ \ |  _| | | | | '_ \/ __|
| |__| | |  | |_) | | |_ | (_) || |   | |_| | |_) \__ \
 \____/|_|  |_.__/|_|\__| \___/ |_|    \___/| .__/|___/
                                            | |        
                                            |_|        
EOF
echo -e "${RESET}"
echo -e "${BLUE}${BOLD}╔════════════════════════════════════════════════════════════╗${RESET}"
echo -e "${BLUE}${BOLD}║   🚀 PART 1: GCP INFRASTRUCTURE & FIRST BUILD              ║${RESET}"
echo -e "${BLUE}${BOLD}║   🌐 BROUGHT TO YOU BY ORBIT OF OPS                        ║${RESET}"
echo -e "${BLUE}${BOLD}╚════════════════════════════════════════════════════════════╝${RESET}\n"

echo -e "${YELLOW}${BOLD}[Orbit of Ops] Auto-fetching Project, Zone, and Region...${RESET}"
export PROJECT_ID=$(gcloud config get-value project 2>/dev/null)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)' 2>/dev/null)
export ZONE=$(gcloud compute project-info describe --format="value(commonInstanceMetadata.items[google-compute-default-zone])" 2>/dev/null | tail -n 1)

if [[ -z "$ZONE" ]]; then
    read -p "Please enter the lab Zone (e.g., us-east1-c): " ZONE
    export ZONE
fi
export REGION=${ZONE%-*}
gcloud config set compute/region $REGION 2>/dev/null

echo -e "✅ Project ID: ${GREEN}$PROJECT_ID${RESET}"
echo -e "✅ Region:     ${GREEN}$REGION${RESET}\n"

echo -e "${BLUE}${BOLD}[Orbit of Ops] Enabling required APIs...${RESET}"
gcloud services enable container.googleapis.com cloudbuild.googleapis.com secretmanager.googleapis.com containeranalysis.googleapis.com
sleep 15

echo -e "\n${BLUE}${BOLD}[Orbit of Ops] Creating Artifact Registry & GKE Cluster...${RESET}"
gcloud artifacts repositories create my-repository --repository-format=docker --location=$REGION --quiet
gcloud container clusters create hello-cloudbuild --num-nodes 1 --region $REGION --async

echo -e "\n${BLUE}${BOLD}[Orbit of Ops] Configuring Git & Creating App Repository...${RESET}"
export GITHUB_USERNAME=$(gh api user -q ".login")
export USER_EMAIL=$(gcloud auth list --filter=status:ACTIVE --format="value(account)")
git config --global user.name "${GITHUB_USERNAME}"
git config --global user.email "${USER_EMAIL}"

gh repo create hello-cloudbuild-app --private 

cd ~
mkdir hello-cloudbuild-app
gcloud storage cp -r gs://spls/gsp1077/gke-gitops-tutorial-cloudbuild/* hello-cloudbuild-app
cd ~/hello-cloudbuild-app

sed -i "s/us-central1/$REGION/g" cloudbuild.yaml cloudbuild-delivery.yaml cloudbuild-trigger-cd.yaml kubernetes.yaml.tpl

git init
git config credential.helper gcloud.sh
git remote add google https://github.com/${GITHUB_USERNAME}/hello-cloudbuild-app
git branch -m master
git add . && git commit -m "initial commit"

echo -e "\n${BLUE}${BOLD}[Orbit of Ops] Submitting Initial Build to Cloud Build...${RESET}"
COMMIT_ID="$(git rev-parse --short=7 HEAD)"
gcloud builds submit --tag="${REGION}-docker.pkg.dev/${PROJECT_ID}/my-repository/hello-cloudbuild:${COMMIT_ID}" .

echo -e "\n${MAGENTA}${BOLD}╔════════════════════════════════════════════════════════════╗${RESET}"
echo -e "${MAGENTA}${BOLD}║  🎉 PART 1 COMPLETE! PLEASE PERFORM THE UI STEP BELOW!     ║${RESET}"
echo -e "${MAGENTA}${BOLD}╚════════════════════════════════════════════════════════════╝${RESET}"
#!/bin/bash
# ==============================================================================
# ORBIT OF OPS - PART 2: SSH KEYS & ENV REPOSITORY SETUP
# ==============================================================================
GREEN='\e[1;32m'
CYAN='\e[1;36m'
YELLOW='\e[1;33m'
BLUE='\e[1;34m'
MAGENTA='\e[1;35m'
RESET='\e[0m'
BOLD='\e[1m'

echo -e "${CYAN}${BOLD}╔════════════════════════════════════════════════════════════╗${RESET}"
echo -e "${CYAN}${BOLD}║   🚀 PART 2: KEYS, SECRETS, AND CD PIPELINE                ║${RESET}"
echo -e "${CYAN}${BOLD}║   🌐 BROUGHT TO YOU BY ORBIT OF OPS                        ║${RESET}"
echo -e "${CYAN}${BOLD}╚════════════════════════════════════════════════════════════╝${RESET}\n"

export PROJECT_ID=$(gcloud config get-value project 2>/dev/null)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)' 2>/dev/null)
export ZONE=$(gcloud compute project-info describe --format="value(commonInstanceMetadata.items[google-compute-default-zone])" 2>/dev/null | tail -n 1)
export REGION=${ZONE%-*}
export GITHUB_USERNAME=$(gh api user -q ".login")
export USER_EMAIL=$(gcloud auth list --filter=status:ACTIVE --format="value(account)")

echo -e "${BLUE}${BOLD}[Orbit of Ops] Triggering the CI Pipeline...${RESET}"
cd ~/hello-cloudbuild-app
git add .
git commit -m "Triggering CI Pipeline"
git push google master

echo -e "\n${BLUE}${BOLD}[Orbit of Ops] Generating SSH Keys & Uploading to Secret Manager...${RESET}"
cd ~
mkdir -p workingdir && cd workingdir
ssh-keygen -t rsa -b 4096 -N '' -f id_github -C "${USER_EMAIL}"

gcloud secrets create ssh_key_secret --replication-policy="automatic"
gcloud secrets versions add ssh_key_secret --data-file=id_github

echo -e "\n${BLUE}${BOLD}[Orbit of Ops] Adding Deploy Key to GitHub via API...${RESET}"
SSH_KEY_CONTENT=$(cat id_github.pub)
gh repo create hello-cloudbuild-env --private 
gh api --method POST -H "Accept: application/vnd.github.v3+json" \
  /repos/${GITHUB_USERNAME}/hello-cloudbuild-env/keys \
  -f title="SSH_KEY" -f key="$SSH_KEY_CONTENT" -F read_only=false
rm id_github*

echo -e "\n${BLUE}${BOLD}[Orbit of Ops] Granting IAM Permissions...${RESET}"
gcloud projects add-iam-policy-binding ${PROJECT_NUMBER} --member=serviceAccount:${PROJECT_NUMBER}[email protected] --role=roles/secretmanager.secretAccessor --quiet
gcloud projects add-iam-policy-binding ${PROJECT_NUMBER} --member=serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com --role=roles/container.developer --quiet

echo -e "\n${BLUE}${BOLD}[Orbit of Ops] Setting up 'hello-cloudbuild-env' Repository...${RESET}"
cd ~
mkdir hello-cloudbuild-env
gcloud storage cp -r gs://spls/gsp1077/gke-gitops-tutorial-cloudbuild/* hello-cloudbuild-env
cd hello-cloudbuild-env

sed -i "s/us-central1/$REGION/g" cloudbuild.yaml cloudbuild-delivery.yaml cloudbuild-trigger-cd.yaml kubernetes.yaml.tpl
ssh-keyscan -t rsa github.com > known_hosts.github
chmod +x known_hosts.github

git init
git config credential.helper gcloud.sh
git remote add google https://github.com/${GITHUB_USERNAME}/hello-cloudbuild-env
git branch -m master
git add . && git commit -m "initial commit"
git push google master

echo -e "\n${BLUE}${BOLD}[Orbit of Ops] Configuring Deployment Pipeline YAML...${RESET}"
git checkout -b production

cat << 'EOF' > cloudbuild.yaml
steps:
- name: 'gcr.io/cloud-builders/kubectl'
  id: Deploy
  args: [ 'apply', '-f', 'kubernetes.yaml' ]
  env:
  - 'CLOUDSDK_COMPUTE_REGION=REGION_PLACEHOLDER'
  - 'CLOUDSDK_CONTAINER_CLUSTER=hello-cloudbuild'
- name: 'gcr.io/cloud-builders/git'
  secretEnv: ['SSH_KEY']
  entrypoint: 'bash'
  args:
  - -c
  - |
    echo "$SSH_KEY" >> /root/.ssh/id_rsa
    chmod 400 /root/.ssh/id_rsa
    cp known_hosts.github /root/.ssh/known_hosts
  volumes:
  - name: 'ssh'
    path: /root/.ssh
- name: 'gcr.io/cloud-builders/git'
  args: [ 'clone', '--recurse-submodules', '[email protected]:GITHUB_USERNAME_PLACEHOLDER/hello-cloudbuild-env.git' ]
  volumes:
  - name: ssh
    path: /root/.ssh
- name: 'gcr.io/cloud-builders/gcloud'
  id: Copy to production branch
  entrypoint: /bin/sh
  args:
  - '-c'
  - |
    set -x && \
    cd hello-cloudbuild-env && \
    git config user.email $(gcloud auth list --filter=status:ACTIVE --format='value(account)') && \
    sed "s/GOOGLE_CLOUD_PROJECT/${PROJECT_ID}/g" kubernetes.yaml.tpl | \
    git fetch origin production && \
    git checkout production && \
    git checkout $COMMIT_SHA kubernetes.yaml && \
    git commit -m "Manifest from commit $COMMIT_SHA $(git log --format=%B -n 1 $COMMIT_SHA)" && \
    git push origin production
  volumes:
  - name: ssh
    path: /root/.ssh
availableSecrets:
  secretManager:
  - versionName: projects/${PROJECT_NUMBER}/secrets/ssh_key_secret/versions/1
    env: 'SSH_KEY'
options:
  logging: CLOUD_LOGGING_ONLY
EOF

sed -i "s/REGION_PLACEHOLDER/$REGION/g" cloudbuild.yaml
sed -i "s/GITHUB_USERNAME_PLACEHOLDER/${GITHUB_USERNAME}/g" cloudbuild.yaml

git add cloudbuild.yaml
git commit -m "Create cloudbuild.yaml for deployment"
git checkout -b candidate
git push google production
git push google candidate

echo -e "\n${MAGENTA}${BOLD}╔════════════════════════════════════════════════════════════╗${RESET}"
echo -e "${MAGENTA}${BOLD}║  🎉 PART 2 COMPLETE! PLEASE PERFORM THE UI STEP BELOW!     ║${RESET}"
echo -e "${MAGENTA}${BOLD}╚════════════════════════════════════════════════════════════╝${RESET}"
#!/bin/bash
# ==============================================================================
# ORBIT OF OPS - PART 3: FINAL DEPLOYMENT TRIGGERS
# ==============================================================================
GREEN='\e[1;32m'
CYAN='\e[1;36m'
YELLOW='\e[1;33m'
BLUE='\e[1;34m'
MAGENTA='\e[1;35m'
RESET='\e[0m'
BOLD='\e[1m'

echo -e "${CYAN}${BOLD}╔════════════════════════════════════════════════════════════╗${RESET}"
echo -e "${CYAN}${BOLD}║   🚀 PART 3: FINAL E2E PIPELINE TRIGGER                    ║${RESET}"
echo -e "${CYAN}${BOLD}║   🌐 BROUGHT TO YOU BY ORBIT OF OPS                        ║${RESET}"
echo -e "${CYAN}${BOLD}╚════════════════════════════════════════════════════════════╝${RESET}\n"

export PROJECT_ID=$(gcloud config get-value project 2>/dev/null)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)' 2>/dev/null)
export ZONE=$(gcloud compute project-info describe --format="value(commonInstanceMetadata.items[google-compute-default-zone])" 2>/dev/null | tail -n 1)
export REGION=${ZONE%-*}
export GITHUB_USERNAME=$(gh api user -q ".login")

cd ~/hello-cloudbuild-app
ssh-keyscan -t rsa github.com > known_hosts.github
chmod +x known_hosts.github

git add .
git commit -m "Adding known_host file."
git push google master

echo -e "\n${BLUE}${BOLD}[Orbit of Ops] Updating APP cloudbuild.yaml to trigger CD...${RESET}"
cat << 'EOF' > cloudbuild.yaml
steps:
- name: 'python:3.7-slim'
  id: Test
  entrypoint: /bin/sh
  args: [ '-c', 'pip install flask && python test_app.py -v' ]
- name: 'gcr.io/cloud-builders/docker'
  id: Build
  args: [ 'build', '-t', 'REGION_PLACEHOLDER-docker.pkg.dev/$PROJECT_ID/my-repository/hello-cloudbuild:$SHORT_SHA', '.' ]
- name: 'gcr.io/cloud-builders/docker'
  id: Push
  args: [ 'push', 'REGION_PLACEHOLDER-docker.pkg.dev/$PROJECT_ID/my-repository/hello-cloudbuild:$SHORT_SHA' ]
- name: 'gcr.io/cloud-builders/git'
  secretEnv: ['SSH_KEY']
  entrypoint: 'bash'
  args:
  - -c
  - |
    echo "$SSH_KEY" >> /root/.ssh/id_rsa
    chmod 400 /root/.ssh/id_rsa
    cp known_hosts.github /root/.ssh/known_hosts
  volumes:
  - name: 'ssh'
    path: /root/.ssh
- name: 'gcr.io/cloud-builders/git'
  args: [ 'clone', '--recurse-submodules', '[email protected]:GITHUB_USERNAME_PLACEHOLDER/hello-cloudbuild-env.git' ]
  volumes:
  - name: ssh
    path: /root/.ssh
- name: 'gcr.io/cloud-builders/gcloud'
  id: Change directory
  entrypoint: /bin/sh
  args:
  - '-c'
  - |
    cd hello-cloudbuild-env && \
    git checkout candidate && \
    git config user.email $(gcloud auth list --filter=status:ACTIVE --format='value(account)')
  volumes:
  - name: ssh
    path: /root/.ssh
- name: 'gcr.io/cloud-builders/gcloud'
  id: Generate manifest
  entrypoint: /bin/sh
  args:
  - '-c'
  - |
     sed "s/GOOGLE_CLOUD_PROJECT/${PROJECT_ID}/g" kubernetes.yaml.tpl | \
     sed "s/COMMIT_SHA/${SHORT_SHA}/g" > hello-cloudbuild-env/kubernetes.yaml
  volumes:
  - name: ssh
    path: /root/.ssh
- name: 'gcr.io/cloud-builders/gcloud'
  id: Push manifest
  entrypoint: /bin/sh
  args:
  - '-c'
  - |
    set -x && \
    cd hello-cloudbuild-env && \
    git add kubernetes.yaml && \
    git commit -m "Deploying image REGION_PLACEHOLDER-docker.pkg.dev/$PROJECT_ID/my-repository/hello-cloudbuild:${SHORT_SHA} Built from commit ${COMMIT_SHA}" && \
    git push origin candidate
  volumes:
  - name: ssh
    path: /root/.ssh
availableSecrets:
  secretManager:
  - versionName: projects/${PROJECT_NUMBER}/secrets/ssh_key_secret/versions/1
    env: 'SSH_KEY'
options:
  logging: CLOUD_LOGGING_ONLY
EOF

sed -i "s/REGION_PLACEHOLDER/$REGION/g" cloudbuild.yaml
sed -i "s/GITHUB_USERNAME_PLACEHOLDER/${GITHUB_USERNAME}/g" cloudbuild.yaml

git add cloudbuild.yaml
git commit -m "Trigger CD pipeline"
git push google master

echo -e "\n${BLUE}${BOLD}[Orbit of Ops] Pushing Final Application Code Change...${RESET}"
sed -i 's/Hello World/Hello Cloud Build/g' app.py
sed -i 's/Hello World/Hello Cloud Build/g' test_app.py
git add app.py test_app.py
git commit -m "Hello Cloud Build"
git push google master

echo -e "\n${MAGENTA}${BOLD}╔════════════════════════════════════════════════════════════╗${RESET}"
echo -e "${MAGENTA}${BOLD}║           🎉 AUTOMATION COMPLETED SUCCESSFULLY 🎉          ║${RESET}"
echo -e "${MAGENTA}${BOLD}╚════════════════════════════════════════════════════════════╝${RESET}"
echo -e "${WHITE}${BOLD}Wait for the final Build to succeed in Cloud Build, then check your progress!${RESET}"
#!/bin/bash
# ==============================================================================
# ORBIT OF OPS - GCE_STOCKOUT CLUSTER FIX
# ==============================================================================
GREEN='\e[1;32m'
CYAN='\e[1;36m'
YELLOW='\e[1;33m'
BLUE='\e[1;34m'
MAGENTA='\e[1;35m'
WHITE='\e[1;37m'
RED='\e[1;31m'
RESET='\e[0m'
BOLD='\e[1m'

echo -e "${CYAN}${BOLD}╔════════════════════════════════════════════════════════════╗${RESET}"
echo -e "${CYAN}${BOLD}║   🛠️ ORBIT OF OPS: GCE_STOCKOUT CLUSTER FIX                ║${RESET}"
echo -e "${CYAN}${BOLD}╚════════════════════════════════════════════════════════════╝${RESET}\n"

# Fetch the current region
export REGION=$(gcloud config get-value compute/region 2>/dev/null)
if [[ -z "$REGION" ]]; then
    read -p "Enter your lab region (e.g., europe-west4): " REGION
fi

echo -e "${YELLOW}${BOLD}[Orbit of Ops] Deleting the stuck regional cluster...${RESET}"
gcloud container clusters delete hello-cloudbuild --region=$REGION --quiet || true

echo -e "\n${YELLOW}${BOLD}[Orbit of Ops] We need to pick a different zone in $REGION to avoid the stockout.${RESET}"
echo -e "${WHITE}${BOLD}Available zones in $REGION:${RESET}"
gcloud compute zones list --filter="region:($REGION)" --format="value(name)"

echo ""
read -p "Enter one of the zones listed above (e.g., ${REGION}-a): " NEW_ZONE

echo -e "\n${BLUE}${BOLD}[Orbit of Ops] Recreating cluster in $NEW_ZONE... This will take a few minutes.${RESET}"
gcloud container clusters create hello-cloudbuild --num-nodes 1 --zone=$NEW_ZONE

echo -e "\n${MAGENTA}${BOLD}╔════════════════════════════════════════════════════════════╗${RESET}"
echo -e "${MAGENTA}${BOLD}║  🎉 CLUSTER RECREATED! CHECK YOUR PROGRESS IN THE LAB!     ║${RESET}"
echo -e "${MAGENTA}${BOLD}╚════════════════════════════════════════════════════════════╝${RESET}"