This tutorial shows you how to package a web application in a Docker container image, and run that container image on a Google Kubernetes Engine (GKE) cluster. Then, you deploy the web application as a load-balanced set of replicas that can scale to the needs of your users.
Objectives
- Package a sample web application into a Docker image.
- Upload the Docker image to Container Registry.
- Create a GKE cluster.
- Deploy the sample app to the cluster.
- Manage autoscaling for the deployment.
- Expose the sample app to the internet.
- Deploy a new version of the sample app.
Before you begin
Take the following steps to enable the Kubernetes Engine API:- Visit the Kubernetes Engine page in the Google Cloud Console.
- Create or select a project.
- Wait for the API and related services to be enabled. This can take several minutes.
-
Make sure that billing is enabled for your Cloud project. Learn how to confirm that billing is enabled for your project.
Option A: Use Cloud Shell
You can follow this tutorial using Cloud Shell, which comes
preinstalled with the gcloud
, docker
, and kubectl
command-line tools used
in this tutorial. If you use Cloud Shell, you don't need to install these
command-line tools on your workstation.
To use Cloud Shell:
- Go to the Google Cloud Console.
Click the Activate Cloud Shell
button at the top of the Cloud Console window.
A Cloud Shell session opens inside a new frame at the bottom of the Cloud Console and displays a command-line prompt.
Option B: Use command-line tools locally
If you prefer to follow this tutorial on your workstation, follow these steps to install the necessary tools.
Install the Cloud SDK, which includes the
gcloud
command-line tool.Using the
gcloud
command line tool, install the Kubernetes command-line tool.kubectl
is used to communicate with Kubernetes, which is the cluster orchestration system of GKE clusters:gcloud components install kubectl
Install Docker Community Edition (CE) on your workstation. You use this to build a container image for the application.
Install the Git source control tool to fetch the sample application from GitHub.
Building the container image
In this tutorial, you deploy a sample web
application called hello-app
, a web server written
in Go that responds to all requests with the message
Hello, World!
on port 8080.
GKE accepts Docker images as the application deployment format.
Before deploying hello-app
to GKE, you must package
the hello-app
source code as a Docker image.
To build a Docker image, you need source code and a Dockerfile. A Dockerfile contains instructions on how the image is built.
Download the
hello-app
source code and Dockerfile by running the following commands:git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples cd kubernetes-engine-samples/hello-app
Set the
PROJECT_ID
environment variable to your Google Cloud project ID (PROJECT_ID
). ThePROJECT_ID
variable associates the container image with your project's Container Registry.export PROJECT_ID=PROJECT_ID
Confirm that the
PROJECT_ID
environment variable has the correct value:echo $PROJECT_ID
Build and tag the Docker image for
hello-app
:docker build -t gcr.io/${PROJECT_ID}/hello-app:v1 .
This command instructs Docker to build the image using the
Dockerfile
in the current directory and tag it with a name, such asgcr.io/my-project/hello-app:v1
. Thegcr.io
prefix refers to Container Registry, where the image is hosted. Running this command does not upload the image.Run the
docker images
command to verify that the build was successful:docker images
Output:
REPOSITORY TAG IMAGE ID CREATED SIZE gcr.io/my-project/hello-app v1 25cfadb1bf28 10 seconds ago 54 MB
Running your container locally (optional)
Test your container image using your local Docker engine:
docker run --rm -p 8080:8080 gcr.io/${PROJECT_ID}/hello-app:v1
If you're using Cloud Shell, click the Web Preview button
and then select the
8080
port number. GKE opens the preview URL on its proxy service in a new browser window.Otherwise, open a new terminal window (or a Cloud Shell tab) and run the following command to verify that the container works and responds to requests with "Hello, World!":
curl http://localhost:8080
After you've seen a successful response, you can shut down the container by pressing Ctrl+C in the tab where the
docker run
command is running.
Pushing the Docker image to Container Registry
You must upload the container image to a registry so that your GKE cluster can download and run the container image. In Google Cloud, Container Registry is available by default.
Enable the Container Registry API for the Google Cloud project you are working on:
gcloud services enable containerregistry.googleapis.com
Configure the Docker command-line tool to authenticate to Container Registry:
gcloud auth configure-docker
Push the Docker image that you just built to Container Registry:
docker push gcr.io/${PROJECT_ID}/hello-app:v1
Creating a GKE cluster
Now that the Docker image is stored in Container Registry, create a GKE
cluster
to run hello-app
. A GKE cluster consists of a pool of Compute Engine VM instances
running Kubernetes, the open source cluster orchestration
system that powers GKE.
Cloud Shell
Set your project ID option for the
gcloud
tool:gcloud config set project $PROJECT_ID
Set your zone or region. Depending on the mode of operation that you choose to use in GKE, specify a default zone or region. If you use the Standard mode, your cluster is zonal (for this tutorial), so set your default compute zone. If you use the Autopilot mode, your cluster is regional, so set your default compute region. Choose the zone or region that is closest to you.
Standard cluster, such as
us-west1-a
:gcloud config set compute/zone COMPUTE_ZONE
Autopilot cluster, such as
us-west1
:gcloud config set compute/region COMPUTE_REGION
Create a cluster named
hello-cluster
:Standard cluster:
gcloud container clusters create hello-cluster
Autopilot cluster:
gcloud container clusters create-auto hello-cluster
It takes a few minutes for your GKE cluster to be created and health-checked.
After the command completes, run the following command to see the cluster's three Nodes:
kubectl get nodes
Output:
NAME STATUS ROLES AGE VERSION gke-hello-cluster-default-pool-229c0700-cbtd Ready <none> 92s v1.18.12-gke.1210 gke-hello-cluster-default-pool-229c0700-fc5j Ready <none> 91s v1.18.12-gke.1210 gke-hello-cluster-default-pool-229c0700-n9l7 Ready <none> 92s v1.18.12-gke.1210
Console
Visit the Google Kubernetes Engine menu in Cloud Console.
Click add_box Create.
Choose Standard or Autopilot mode and click Configure.
In the Name field, enter the name
hello-cluster
.Select a zone or region:
Standard cluster: Under Location type, select Zonal and then select a Compute Engine zone from the Zone drop-down list, such as
us-west1-a
.Autopilot cluster: Select a Compute Engine region from the Region drop-down list, such as
us-west1
.
Click Create. This creates a GKE cluster.
Wait for the cluster to be created. When the cluster is ready, a green check mark appears next to the cluster name.
Deploying the sample app to GKE
You are now ready to deploy the Docker image you built to your GKE cluster.
Kubernetes represents applications as Pods, which are scalable units holding one or more containers. The Pod is the smallest deployable unit in Kubernetes. Usually, you deploy Pods as a set of replicas that can be scaled and distributed together across your cluster. One way to deploy a set of replicas is through a Kubernetes Deployment.
In this section, you create a Kubernetes Deployment to run hello-app
on your
cluster. This Deployment has replicas (Pods). One Deployment Pod contains only
one container: the hello-app
Docker image.
You also create a HorizontalPodAutoscaler resource that scales the number
of Pods from 3 to a number between 1 and 5, based on CPU load.
Cloud Shell
Ensure that you are connected to your GKE cluster.
gcloud container clusters get-credentials hello-cluster --zone COMPUTE_ZONE
Create a Kubernetes Deployment for your
hello-app
Docker image.kubectl create deployment hello-app --image=gcr.io/${PROJECT_ID}/hello-app:v1
Set the baseline number of Deployment replicas to 3.
kubectl scale deployment hello-app --replicas=3
Create a
HorizontalPodAutoscaler
resource for your Deployment.kubectl autoscale deployment hello-app --cpu-percent=80 --min=1 --max=5
To see the Pods created, run the following command:
kubectl get pods
Output:
NAME READY STATUS RESTARTS AGE hello-app-784d7569bc-hgmpx 1/1 Running 0 10s hello-app-784d7569bc-jfkz5 1/1 Running 0 10s hello-app-784d7569bc-mnrrl 1/1 Running 0 15s
Console
Visit the GKE Workloads menu in Cloud Console.
Click add_box Deploy.
In the Container section, select Existing container image.
In the Image path field, click Select.
In the Select container image pane, select the
hello-app
image you pushed to Container Registry and click Select.In the Container section, click Done, then click Continue.
In the Configuration section, under Labels, enter
app
for Key andhello-app
for Value.Under Configuration YAML, click View YAML. This opens a YAML configuration file representing the two Kubernetes API resources about to be deployed into your cluster: one Deployment, and one
HorizontalPodAutoscaler
for that Deployment.Click Close, then click Deploy.
When the Deployment Pods are ready, the Deployment details page opens.
Under Managed pods, note the three running Pods for the
hello-app
Deployment.
Exposing the sample app to the internet
While Pods do have individually-assigned IP addresses, those IPs can only be reached from inside your cluster. Also, GKE Pods are designed to be ephemeral, starting or stopping based on scaling needs. And when a Pod crashes due to an error, GKE automatically redeploys that Pod, assigning a new Pod IP address each time.
What this means is that for any Deployment, the set of IP addresses corresponding to the active set of Pods is dynamic. We need a way to 1) group Pods together into one static hostname, and 2) expose a group of Pods outside the cluster, to the internet.
Kubernetes Services solve for both of these problems.
Services group Pods
into one static IP address, reachable from any Pod inside the cluster.
GKE also assigns a DNS hostname
to that static IP. For example, hello-app.default.svc.cluster.local
.
The default Service type in GKE is called ClusterIP,
where the Service gets an IP address reachable only from inside the cluster.
To expose a Kubernetes Service outside the cluster, create a Service of
type LoadBalancer
.
This type of Service spawns an External Load Balancer IP for a set of Pods,
reachable through the internet.
In this section, you expose the hello-app
Deployment to the internet using a
Service of type LoadBalancer
.
Cloud Shell
Use the
kubectl expose
command to generate a Kubernetes Service for thehello-app
deployment:kubectl expose deployment hello-app --name=hello-app-service --type=LoadBalancer --port 80 --target-port 8080
Here, the
--port
flag specifies the port number configured on the Load Balancer, and the--target-port
flag specifies the port number that thehello-app
container is listening on.Run the following command to get the Service details for
hello-app-service
:kubectl get service
Output:
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE hello-app-service 10.3.251.122 203.0.113.0 80:30877/TCP 10s
Copy the
EXTERNAL_IP
address to the clipboard (for instance:203.0.113.0
).
Console
Visit the Google Kubernetes Engine Workloads menu in Cloud Console.
Click hello-app.
From the Deployment details page, click list Actions > Expose.
In the Expose dialog, set the Target port to
8080
. This is the port thehello-app
container listens on.From the Service type drop-down list, select Load balancer.
Click Expose to create a Kubernetes Service for
hello-app
.When the Load Balancer is ready, the Service details page opens.
Scroll down to the External endpoints field, and copy the IP address.
Now that the hello-app
Pods are exposed to the internet through a Kubernetes Service,
you can open a new browser tab, and navigate to the Service IP address you copied
to the clipboard. A Hello, World!
message appears, along with a Hostname
field. The Hostname
corresponds to one of the three hello-app
Pods serving your
HTTP request to your browser.
Deploying a new version of the sample app
In this section, you upgrade hello-app
to a new version by building and deploying
a new Docker image to your GKE cluster.
GKE's rolling update feature
lets you update your Deployments without downtime. During a rolling update, your GKE cluster
incrementally replaces the existing hello-app
Pods with Pods containing the Docker image for the new version.
During the update, your load balancer service routes traffic only into available Pods.
Return to Cloud Shell, where you have cloned the hello app source code and Dockerfile. Update the function
hello()
in themain.go
file to report the new version2.0.0
.Build and tag a new
hello-app
Docker image.docker build -t gcr.io/${PROJECT_ID}/hello-app:v2 .
Push the image to Container Registry.
docker push gcr.io/${PROJECT_ID}/hello-app:v2
Now you're ready to update your hello-app
Kubernetes Deployment to use a new Docker image.
Cloud Shell
Apply a rolling update to the existing
hello-app
Deployment with an image update using thekubectl set image
command:kubectl set image deployment/hello-app hello-app=gcr.io/${PROJECT_ID}/hello-app:v2
Watch the running Pods running the
v1
image stop, and new Pods running thev2
image start.watch kubectl get pods
Output:
NAME READY STATUS RESTARTS AGE hello-app-89dc45f48-5bzqp 1/1 Running 0 2m42s hello-app-89dc45f48-scm66 1/1 Running 0 2m40s
In a separate tab, navigate again to the
hello-app-service
External IP. You should now see theVersion
set to2.0.0.
Console
Visit the Google Kubernetes Engine Workloads menu in Cloud Console.
Click hello-app.
On the Deployment details page, click list Actions > Rolling update.
In the Rolling update dialog, set the Image of hello-app field to
gcr.io/PROJECT_ID/hello-app:v2
, replacingPROJECT_ID
with your project ID.Click Update.
On the Deployment details page, inspect the Active Revisions section. You should now see two Revisions, 1 and 2. Revision 1 corresponds to the initial Deployment you created earlier. Revision 2 is the rolling update you just started.
After a few moments, refresh the page. Under Managed pods, all of the replicas of
hello-app
now correspond to Revision 2.In a separate tab, navigate again to the Service IP address you copied. The
Version
should be2.0.0.
Cleaning up
To avoid incurring charges to your Google Cloud account for the resources used in this tutorial, either delete the project that contains the resources, or keep the project and delete the individual resources.
Delete the Service: This deallocates the Cloud Load Balancer created for your Service:
kubectl delete service hello-app-service
Delete the cluster: This deletes the resources that make up the cluster, such as the compute instances, disks, and network resources:
gcloud container clusters delete hello-cluster --zone COMPUTE_ZONE
Delete your container images: This deletes the Docker images you pushed to Container Registry.
gcloud container images delete gcr.io/${PROJECT_ID}/hello-app:v1 --force-delete-tags --quiet gcloud container images delete gcr.io/${PROJECT_ID}/hello-app:v2 --force-delete-tags --quiet
What's next
Learn about Pricing for GKE and use the Pricing Calculator to estimate costs.
Read the Load Balancers tutorial, which demonstrates advanced load balancing configurations for web applications.
Configure a static IP and domain name for your application.
Explore other Kubernetes Engine tutorials.
Try out other Google Cloud features for yourself. Have a look at our tutorials.
Try it for yourself
If you're new to Google Cloud, create an account to evaluate how GKE performs in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
Try GKE free