Cloud Build, GKE, and Infrastructure Automation on GCP work together to create a powerful, end-to-end DevOps pipeline.
Here’s how they come together to deploy a simple web application:
Imagine you have a containerized web application. Your Dockerfile defines how to build this container image.
# Dockerfile
FROM ubuntu:latest
RUN apt-get update && apt-get install -y nginx
COPY html/ /var/www/html/
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
And your application code is in a directory called html/ with an index.html file.
Your cloudbuild.yaml file orchestrates the build process in Cloud Build.
# cloudbuild.yaml
steps:
- name: 'gcr.io/cloud-builders/docker'
args: ['build', '-t', 'gcr.io/$PROJECT_ID/my-web-app:$COMMIT_SHA', '.']
- name: 'gcr.io/cloud-builders/docker'
args: ['push', 'gcr.io/$PROJECT_ID/my-web-app:$COMMIT_SHA']
- name: 'gcr.io/cloud-builders/kubectl'
args: ['apply', '-f', 'kubernetes/deployment.yaml']
env:
- 'CLOUDSDK_COMPUTE_ZONE=us-central1-a'
- 'CLOUDSDK_CONTAINER_CLUSTER=my-gke-cluster'
This cloudbuild.yaml tells Cloud Build to:
- Build a Docker image of your application, tagging it with the Git commit SHA for versioning.
- Push that image to Google Container Registry (GCR).
- Use
kubectlto apply a Kubernetes deployment configuration to your GKE cluster.
The kubernetes/deployment.yaml file defines how your application runs on GKE.
# kubernetes/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-web-app-deployment
spec:
replicas: 3
selector:
matchLabels:
app: my-web-app
template:
metadata:
labels:
app: my-web-app
spec:
containers:
- name: my-web-app
image: gcr.io/$PROJECT_ID/my-web-app:$COMMIT_SHA
ports:
- containerPort: 80
This deployment specifies that you want 3 replicas of your my-web-app container, using the image built and pushed by Cloud Build.
When you push a commit to your Git repository (e.g., GitHub, Bitbucket), Cloud Build is triggered. It executes the steps defined in cloudbuild.yaml, builds the container, pushes it, and then updates your GKE cluster with the new image. GKE then ensures that 3 instances of your application are running.
The "Infrastructure Automation" part comes in when you manage your GKE cluster itself. Tools like Terraform or Pulumi can define your GKE cluster, its node pools, networking, and other infrastructure as code. This means you can version control your entire infrastructure, making it reproducible and auditable.
Here’s a snippet of a Terraform configuration for a GKE cluster:
# main.tf
resource "google_container_cluster" "primary" {
name = "my-gke-cluster"
location = "us-central1-a"
initial_node_count = 1
node_pool {
node_count = 3
node_locations = ["us-central1-a", "us-central1-b"]
}
logging_service = "logging.googleapis.com/kubernetes"
monitoring_service = "monitoring.googleapis.com/kubernetes"
}
This Terraform code declares a GKE cluster named my-gke-cluster in us-central1-a with specific node pool configurations. When you run terraform apply, Terraform provisions this exact infrastructure on GCP.
The most surprising aspect is how seamlessly these components integrate. Cloud Build doesn’t need explicit credentials to push to GCR or deploy to GKE; it uses the service account it’s provisioned with, which is automatically granted the necessary IAM roles. This "pull" of configuration and deployment by Cloud Build, and the "push" of infrastructure state by Terraform, creates a robust, automated workflow.
The next logical step is to introduce service mesh capabilities, like Anthos Service Mesh, to manage traffic, security, and observability between your microservices running on GKE.