Learning Path: Transform a monolith into a GKE app - Deploy the app to a GKE cluster

This is the fifth and final tutorial in a learning path that teaches you how tomodularize and containerize a monolithic app.

The learning path consists of the following tutorials:

  1. Overview
  2. Understand the monolith
  3. Modularize the monolith
  4. Prepare the modular app for containerization
  5. Containerize the modular app
  6. Deploy the app to a GKE cluster (this tutorial)

In the previous tutorial,Containerize the modular app, youprepared the modular Cymbal Books app for deployment. You containerized theapp's modules, tested the resulting containers, and pushed the container imagestoArtifact Registry.

In this tutorial, you deploy the containerized app to a Google Kubernetes Engine cluster.This step completes the transformation of the Cymbal Books app into a modularand scalable system that runs on a Kubernetes cluster.

Costs

Following the steps in this tutorial incurs charges on your Google Cloudaccount. Costs begin when you enable GKE and deploy the CymbalBooks sample app. These costs include per-cluster charges forGKE, as outlined on thePricing page, and charges for runningCompute Engine VMs.

To avoid unnecessary charges, ensure that you disable GKE ordelete the project once you have completed this tutorial.

Before you begin

Before you begin this tutorial, make sure that you completed the earliertutorials in the series. For an overview of the whole series, and links toparticular tutorials, seeLearning Path: Transform a monolith into a GKE app - Overview.

In particular, you need to have performed the steps in the previous tutorial,Containerize the modular app.

Set up the GKE cluster

Before you can deploy the modular Cymbal Books app, you must first create aGKE cluster. This cluster provides the infrastructure in whichyour app's containers will run.

In this tutorial, you use thegcloud CLI to create thecluster. Alternatively, you can use theGoogle Cloud console, which provides agraphical user interface (GUI) for creating and managing Google Cloudresources such as GKE clusters.

Create and verify a GKE cluster

A GKE cluster provides the computing resources that are needed torun your containers in Kubernetes. Follow these steps to create a cluster byusing thegcloud CLI.

  1. Go to theGoogle Cloud console.

  2. In the console, click theActivate Cloud Shell button:Activate Cloud Shell

    A Cloud Shell session opens inside a frame lower on the console.

  3. Set your default project in the Google Cloud CLI:

    gcloudconfigsetprojectPROJECT_ID

    ReplacePROJECT_ID with the project ID of the projectthat you created or selected in theselect or create a Google Cloud projectsection of the previous tutorial. A project ID is a unique string thatdifferentiates your project from all other projects in Google Cloud. Tolocate the project ID, go to theproject selector.On that page, you can see the project IDs for each of your Google Cloudprojects.

  4. Create a GKE cluster:

    gcloudcontainerclusterscreateCLUSTER_NAME\--location=CONTROL_PLANE_LOCATION\--num-nodes=2

    Replace the following:

    • CLUSTER_NAME: a name for your cluster, such ascymbal-cluster.

    • CONTROL_PLANE_LOCATION: the Compute Enginelocation of the control plane of yourcluster. Provide a region for regional clusters, or a zone for zonal clusters, such asus-central1 oreurope-west1-b.

  5. Retrieve the cluster's credentials so that thekubectl CLI can connect tothe cluster:

    gcloudcontainerclustersget-credentialsCLUSTER_NAME\--location=CONTROL_PLANE_LOCATION

    This command updates your Kubernetes config file, which is stored by defaultin~/.kube/config. This config file contains the credentials thatkubectl requires to interact with your GKE cluster.

  6. Verify thatkubectl is connected to the cluster by listing the clusternodes:

    kubectlgetnodes

    If the setup is successful, this command lists the nodes in yourGKE cluster. Because you created the cluster with--num-nodes=2, you should see information about two nodes, similar to thefollowing:

    NAME                                         STATUS    ROLES    AGE    VERSIONgke-nov18-default-pool-6a8f9caf-bryg   Ready     <none>   30s    v1.30.8-gke.1128000gke-nov18-default-pool-6a8f9caf-ut0i   Ready     <none>   30s    v1.30.8-gke.1128000

    In this example, both nodes are in theReady state. This state means thatthe GKE cluster is ready to host your containerizedworkloads!

Deploy the app

Now that you've created a GKE cluster, you can deploy the CymbalBooks app to it. To deploy an app to a cluster, you apply the Kubernetesmanifest to the cluster.

Apply the Kubernetes manifest

In Cloud Shell, deploy the app to the GKE cluster by runningthe following commands:

  1. Navigate to the root directory of the containerized application:

    cdkubernetes-engine-samples/quickstarts/monolith-to-microservices/containerized/
  2. Apply the Kubernetes manifest:

    kubectlapply-fkubernetes_manifest.yaml

The previous command instructs Kubernetes to create the resources specified inthekubernetes-manifest.yaml file. These resources include Services, aDeployment, and Pods.

You first encountered Services in theChange the modular code section in thePrepare the modular app for containerization tutorial.In that tutorial, you updated the app's code to use Service names instead oflocalhost. That update enables Kubernetes to route requests between modulesand ensures that the modules can communicate with each other within a cluster.Now, when you apply the manifest, Kubernetes creates the Services inside thecluster.

ADeployment is a Kubernetes API object that lets you run multiple replicas of Pods that are distributed among the nodes in a cluster.. The next section explains what Pods are.

What is a Kubernetes Pod?

In the previous tutorial, you created a container image for each module of theCymbal Books app. For example, you created container images based on thehome_app andbook_details_app modules.

When you use thekubectl apply command to deploy the Kubernetes manifest,Kubernetes pulls your container images from Artifact Registry into the cluster. In thecluster, the container images become containers, and the containers run insidePods.

A Pod is an isolated environment in which containers run, and it performs thefollowing tasks:

  • Allocates CPU and memory: a Pod provides the resources that containersneed to operate.
  • Provides networking: each Pod has its own IP address. This enables thePod to communicate with other Pods.

Pods run onnodes, which are the machines that provide computing power forthe cluster. Kubernetes automatically assigns Pods to nodes and distributes thePods across the cluster's nodes to reduce the risk of overloading any singlenode. This distribution helps the cluster use its computing and memory resourcesefficiently.

Verify the Deployment

After you apply the Kubernetes manifest with thekubectl apply command, verifythat the app was deployed successfully to the cluster. To verify theDeployment, check that the Pods and Services are running correctly.

Check the Pods

To view the Pods in your cluster, run the following command:

kubectlgetpods

This command lists the Pods and their current status. Look for theSTATUScolumn to confirm that all Pods are marked asRunning, which indicates thatthey are successfully running and ready to serve requests. The expected outputlooks like the following:

NAME                             READY   STATUS    RESTARTS   AGEhome-app-67d59c6b6d-abcde        1/1     Running   0          30sbook-details-app-6d8bcbc58f-xyz  1/1     Running   0          30sbook-reviews-app-75db4c4d7f-def  1/1     Running   0          30simages-app-7f8c75c79c-ghi        1/1     Running   0          30s

A Pod's status initially appears asPending while it's being created and itscontainers are in the process of starting. If a Pod remainsPending for anextended period, the cluster might lack sufficient resources for that Pod toenter a healthyRunning state. If a Pod has a status ofCrashLoopBackOff,there might be a problem with the container. Troubleshooting steps are providedlater in the tutorial.

Check the Services

Services enable communication between Pods and allow external clients (forexample, users, automated scripts, or monitoring tools) to access the app. Toview the Services in your cluster, run the following command:

kubectlgetservices

Output from this command looks like the following:

NAME               TYPE           CLUSTER-IP      EXTERNAL-IP       PORT(S)        AGEhome-app-service   LoadBalancer   10.12.3.4       35.185.1.2        80:30837/TCP   30sdetails-service    ClusterIP      10.12.3.5       <none>            80/TCP         30sreviews-service    ClusterIP      10.12.3.6       <none>            80/TCP         30simages-service     LoadBalancer   10.12.3.7       34.125.6.3        80:32014/TCP   30s

Key fields to observe in the output are the following:

  • TYPE: this field indicates how the Service is exposed.Services of typeLoadBalancer provide external access to the app.
  • EXTERNAL-IP: for a Service of typeLoadBalancer, theEXTERNAL-IP field shows the public IP address that users can enter intotheir web browser to access the app. For a Service of typeClusterIP, thisfield is empty becauseClusterIP Services are only accessiblewithin the cluster.

Test the deployment

After you deploy the Cymbal Books app to the GKE cluster, verifythat the app is accessible and that the containers can communicate with eachother.

Access the app

Confirm that the app is accessible by following these steps:

  1. Retrieve the external IP address for thehome-app-service:

    kubectlgetservices

    Look for the**EXTERNAL-IP** column in the output, and note the IP addressthat's associated withhome-app-service.

  2. Open a web browser and enter the following URL:

    http://EXTERNAL-IP

    ReplaceEXTERNAL-IP with the IP address that you foundin the previous step.

  3. Verify that the homepage of the Cymbal Books app loads correctly.

Verify inter-service communication

The containers in the Cymbal Books app rely on Services to exchange information.Ensure that the containers can communicate effectively by following these steps:

  1. Retrieve the external IP address for thehome-app-service as describedearlier.

  2. Use the app's interface to test interactions between containers. To do that,confirm that the following features work by clicking all available links inthe app's interface:

    • Check book cover images: confirm that the book cover images loadcorrectly on both the homepage and the book details page. If they do,home_app andbook_details_app containers are successfullycommunicating with theimages_app container.
    • View book details: navigate to a book details page from the homepage. If you see a book's details, thehome_app container is correctlycommunicating with thebook_details_app.
    • View book reviews: click a book review link to verify that thehome_app container can communicate with thebook_reviews_appcontainer.

Your app is now running on a GKE cluster!

Congratulations! You've seen how to transform a monolithic app into a modular,containerized system that runs on a live GKE cluster. Along theway, you learned how to divide tightly coupled code into independent modules,build and push container images to a repository, define Kubernetes manifests,and deploy your app from the registry to GKE. That's a majoraccomplishment, and it reflects the real-world steps teams take to modernizeapplications for the cloud!

Troubleshooting

If the app doesn't respond or containers fail to communicate, use the followingtroubleshooting steps to diagnose and resolve common issues.

Check the status of your Pods

Start by listing all Pods in your cluster to determine if they are running asexpected:

kubectlgetpods

Review the output to confirm that each Pod is in theRunning state. If any Podisn't running, note its name for further inspection.

Inspect Pod logs

If a Pod isn't handling requests properly, check its logs to look for any errormessages:

kubectllogsPOD_NAME

ReplacePOD_NAME with the name of the Pod you want toinspect. This command is useful for identifying startup issues or runtimeerrors.

Describe a Pod for detailed information

If a Pod remains in a non-Running state for longer than five minutes—forexample, it's in aPending,ContainerCreating, orCrashLoopBackOffstate—you can see detailed information about the Pod's status and eventsby using the following command:

kubectldescribepodPOD_NAME

ReplacePOD_NAME with the name of the Pod that you wantdetailed information about.

TheEvents section in the output might indicate that resource constraints orissues with image pulls are preventing the Pod from starting properly.

Verify Service configuration

Ensure that your Services are set up correctly, especially the Service thatexposes the home module with an external IP address. List the Services with thefollowing command:

kubectlgetservices

If you notice that the Service for the home module has anEXTERNAL-IP addressthat's listed asPending, run the following command:

kubectldescribeserviceSERVICE_NAME

ReplaceSERVICE_NAME with the name of the home moduleService.

This command provides more details about the Service configuration and helps youidentify delays in assigning the external IP address or other configurationissues.

Check cluster events

You can examine cluster events to determine if a problem is affecting multiplecomponents of your cluster:

kubectlgetevents

This command can determine if broader resource or network issues are affectingyour deployment.

Clean up resources

Running a GKE cluster incurs costs. After you complete thistutorial, clean up your resources to avoid additional charges. Follow thesesteps to remove the cluster and, optionally, the entire project.

Delete the GKE cluster

To delete the GKE cluster, use the following command:

gcloudcontainerclustersdeleteCLUSTER_NAME--location=CONTROL_PLANE_LOCATION

Replace the following:

  • CLUSTER_NAME: the name of the cluster you created, suchascymbal-cluster.

  • CONTROL_PLANE_LOCATION: the Compute Enginelocation of the control plane of yourcluster. Provide a region for regional clusters, or a zone for zonal clusters.

When prompted, confirm the deletion.

Verify that the cluster is deleted

To ensure that the cluster was deleted, run the following command:

gcloudcontainerclusterslist

The cluster should no longer appear in the output. If it does, wait a fewmoments and try again.

(Optional) Delete the Google Cloud project

If you created a Google Cloud project specifically for this tutorial and you nolonger need it, you can delete the entire Google Cloud project. Deleting theproject removes all resources and stops billing for the project:

  1. In the Google Cloud console, open theManage Resources page.
  2. Select the project you want to delete.
  3. ClickDelete Project and follow the prompts to confirm.

Summary of the series

Congratulations! By completing this learning path, you've learned thefundamentals of converting a monolithic app into a modular, containerized appthat runs on a Kubernetes cluster. The following steps summarize the process:

  1. Understand the monolith

    • Explored the structure of the Cymbal Books monolithic app.
    • Set up a local Python environment to run the monolith and tested itsendpoints.
    • Gained an understanding of the app's codebase to prepare it formodularization.
  2. Modularize the monolith

    • Learned how to split monolithic code into separate modules. Each modulehandles a distinct feature, such as displaying book details or reviews.
    • Saw how these modules are implemented as independent Flask apps runningon different ports.
    • Tested the modularized app.
  3. Prepare the modular code for containerization

    • Learned that you had to update URLs inhome.py to use Service namesinstead oflocalhost.
    • Learned how the Kubernetes manifest defines Services that enable theapp's modules, which already communicate with each other, to find eachother within the context of a Kubernetes cluster.
  4. Containerize the modular app

    • Set up a Google Cloud project and cloned the app from GitHub intoCloud Shell.
    • Built container images for each module using Docker and testedcontainers locally.
    • Pushed the container images to Artifact Registry to prepare the app fordeployment to a cluster.
    • Updated the Kubernetes manifest to refer to the container image paths inArtifact Registry.
  5. Deploy the app to a GKE cluster (the tutorial you're in now):

    • Created a GKE cluster.
    • Deployed the container images from Artifact Registry to the GKEcluster.
    • Tested the final version of the app, which is now scalable and runs in aKubernetes environment!

What's next

For further practical training about how to create clusters, see our series,Learning Path: Scalable applications.

Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2026-02-18 UTC.