Skip to content
No description, website, or topics provided.
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.

Simple GCB to GKE CICD Pipeline Codelab


Install Cloud SDK, git and kubectl

  • git 2.14.0+
  • gcloud 179.0.0+
  • Install kubectl with Cloud SDK:
    gcloud components install kubectl

Setup the Repo

Before getting started, you need to click on the 'fork' button in the upper right corner this repository.

After the fork is complete, click the green "clone or download" link, and copy the clone url.

Next, clone your fork of the repository:

git clone${USERNAME}/gcb-gke-codelab.git
cd gcb-gke-codelab

Create a GCP project

Create a new GCP project and capture the projectId in the PROJECT_ID env var:

PROJECT_ID=$(gcloud projects create --name "${PROJECT_NAME}" --format='value(projectId)')

At the prompt type 'y' to accept generated project id.

Set the default project:

gcloud config set project ${PROJECT_ID}

Set the default zone:

gcloud config set compute/zone ${COMPUTE_ZONE}

Ensure the default credentials are available on your local machine:

gcloud auth application-default login

Enable Billing on your project:

On Mac:


Use xdg-open with Linux, start with Windows

Enable the required GCP APIs:

gcloud services enable --async \ \ \ \ \ \ \ \

Use gcloud services list --enabled to check progress

Create a GKE cluster

Create the cluster:

gcloud container clusters create ${CLUSTER_NAME} --async

It can take up to five minutes to provision the Kubernetes clusters. Use the gcloud command to check the status of each cluster:

gcloud container clusters list

Grant the Container Builder service account developer access to the GKE API to fetch credentials and apply changes to the cluster.

PROJECT_NUMBER=$(gcloud projects describe ${PROJECT_ID} --format='value(projectNumber)')
gcloud projects add-iam-policy-binding ${PROJECT_NUMBER} \
  --member=serviceAccount:${PROJECT_NUMBER} \

The project is setup at this point. Now what???

Create The App Pipeline


Create k8s Resources

Wait for cluster to be running to execute this section

Get cluster credentials and make available to kubectl

gcloud container clusters get-credentials ${CLUSTER_NAME} --zone ${COMPUTE_ZONE}
mkdir k8s

Create a Deployment file

kubectl run ${APP_NAME}${PROJECT_NAME}/${APP_NAME} --port=3000 --env="GET_HOSTS_FROM=dns" --labels="app=${APP_NAME}" --dry-run -o yaml > k8s/deployment.yaml

Create a Service file

kubectl create service loadbalancer ${APP_NAME} --tcp=80:3000 --dry-run -o yaml > k8s/service.yaml

Create Service and Deployment resources

kubectl apply -f k8s/

Create a build pipeline config file

touch cloudbuild.yaml

Open cloudbuild.yaml in your favorite editor

Copy/paste the following into cloudbuild.yaml:

Add docker build step:

# Build the image
- id: 'Build docker image'
  name: ''
  args: [ 'build', '-t', '$PROJECT_ID/$_APP_NAME:$SHORT_SHA', '.' ]

Push image to registry:

# Push updated image
- id: 'Push image to registry'
  name: ''
  args: [ 'push', '$PROJECT_ID/$_APP_NAME:$SHORT_SHA' ]

Patch Deployment manifest file:

# Patch the Deployment
- id: 'Patch manifest with new image'
  name: ''
  entrypoint: 'sh'
    - '-c'
    - |
      gcloud container clusters get-credentials \

      cat <<EOF > patch.yaml
              - name: ${_APP_NAME}

      kubectl patch --local -o yaml \
        -f k8s/deployment.yaml \
        -p "$(cat patch.yaml)" \
        > deployment.yaml

      mv deployment.yaml k8s/deployment.yaml

Apply change to the GKE cluster:

# Apply change
- id: 'Apply update to cluster'
  name: ''
  args: [ 'apply', '-f', 'k8s/']

Tell the build that you created an image:

# Associate image that was pushed to GCR with the build history UI

Save the file

Test the pipeline

Manually trigger a build from the CLI

gcloud container builds submit . \
    --config cloudbuild.yaml \
    --substitutions \

Get the app url

List Service

kubectl get service ${APP_NAME}

Note the external IP address once it's provisioned. Save it for later.


See if it worked:

open ${URL}

Create the Trigger

We're going to create a build trigger that will kick off the build and deploy pipeline on changes to source code.

Get your environment variable values


Go to Build Triggers page in Cloud Console


Follow prompts to OAuth into GitHub and select your repo.

Create trigger with following:

Field Value
Name Deploy on push to master
Trigger type branch
Branch master
Build configuration cloudbuild.yaml
cloudbuild.yaml location cloudbuild.yaml

Save Trigger

Test the Trigger

Update the hello message at app/lib/get-welcome-message.js

git add .
git commit -m 'your message'
git push

A new build should kick off. When complete you should see your new welcome message.

Check build status


Check that your change is live

open ${URL}

Next Steps

This was intended as a quickstart codelab for familiarizing yourself with GKE, GCB, and setting up a CICD pipeline.

For a more real-world pipeline, see this pipeline tutorial or evolve this project and implement some of the following:

  • Browse the supported and community contributed builder images to get a sense of available functionality
  • Speed up your build by pulling in your previously built image and doing a --cache-from build
  • Commit updates to manifest files back to repo to keep as source of truth. Use hub CLI tool to commit changes back to repo from build.
  • Create multiple cluster like qa, staging, and prod, and create additional build triggers connecting them, e.g. deploy to qa on push to a feature branch, push to prod on git tag.
  • Separate infrastructure manifest files from application code
  • Use PRs as manual gates for promoting changes to prod without rebuilding
  • See Kelsey Hightower's production-ready pipeline tutorial for an example of these and other best practices


Delete the GCP Project:

gcloud projects delete ${PROJECT_ID}

Delete the GitHub repo

curl -X DELETE "${USERNAME}/${repo}"
You can’t perform that action at this time.