{"id":10542,"date":"2022-03-11T07:10:37","date_gmt":"2022-03-11T07:10:37","guid":{"rendered":"https:\/\/blog.cloudthat.com\/?p=10542"},"modified":"2024-06-25T11:04:13","modified_gmt":"2024-06-25T11:04:13","slug":"deploying-a-highly-available-and-scalable-java-tomcat-application-on-google-kubernetes-engine-gke","status":"publish","type":"blog","link":"https:\/\/www.cloudthat.com\/resources\/blog\/deploying-a-highly-available-and-scalable-java-tomcat-application-on-google-kubernetes-engine-gke","title":{"rendered":"Deploying a Highly Available and Scalable JAVA Tomcat Application on Google Kubernetes Engine (GKE)"},"content":{"rendered":"<h2>Introduction<\/h2>\n<p>Google Kubernetes Engine is a fully managed Kubernetes cluster offered by Google Cloud Platform.<\/p>\n<p>GKE offers two modes of the operational cluster: Standard and Autopilot.<\/p>\n<ul>\n<li>Standard is the full-fledged cluster that gives you complete control over the nodes to tune and run customized workloads.<\/li>\n<li>Autopilot mode\u00a0is a hassle-free, fully managed solution that manages your entire cluster&#8217;s infrastructure without worrying about configuring and monitoring. Although it comes with per-pod billing, Autopilot ensures you pay only for your running pods, not system components, operating system overhead, or unallocated capacity.<\/li>\n<\/ul>\n<p>In this blog, we are going to deploy a highly available application on GKE with a step-by-step guide.<\/p>\n<p><a href=\"https:\/\/content.cloudthat.com\/resources\/wp-content\/uploads\/2022\/11\/GKE1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-10543\" src=\"https:\/\/content.cloudthat.com\/resources\/wp-content\/uploads\/2022\/11\/GKE1.png\" alt=\"GKE\" width=\"626\" height=\"451\" \/><\/a><\/p>\n<h3>Perquisites:<\/h3>\n<ol>\n<li>A GCP Account<\/li>\n<li>A sample WAR application<\/li>\n<li>A MySQL instance if you have a database connected with the application<\/li>\n<\/ol>\n<h3>Kubernetes components to be covered:<\/h3>\n<ol>\n<li>Deployment<\/li>\n<li>Service<\/li>\n<li>Ingress<\/li>\n<li>Secrets(tls)<\/li>\n<\/ol>\n<h3>Step by Step Guide<\/h3>\n<p>Step 1: Activate GCP Cloud Shell by clicking on the icon\u00a0<a href=\"https:\/\/content.cloudthat.com\/resources\/wp-content\/uploads\/2022\/11\/GKE-icon.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-10544\" src=\"https:\/\/content.cloudthat.com\/resources\/wp-content\/uploads\/2022\/11\/GKE-icon.png\" alt=\"GKE icon\" width=\"24\" height=\"25\" \/><\/a> from the right top of the console<\/p>\n<p>It will activate the Cloud Shell as per below:<\/p>\n<p><a href=\"https:\/\/content.cloudthat.com\/resources\/wp-content\/uploads\/2022\/11\/GKE2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-10545\" src=\"https:\/\/content.cloudthat.com\/resources\/wp-content\/uploads\/2022\/11\/GKE2.png\" alt=\"GKE\" width=\"624\" height=\"93\" \/><\/a><\/p>\n<blockquote><p>Note: The Project has already been selected as we open Cloudshell from web browser. Use <strong>gcloud config set project [PROJECT_ID]<\/strong> to change project.<\/p><\/blockquote>\n<p>Step 2: Create a <strong>ct-demo<\/strong> repository for storing container images in the Docker repository<\/p>\n<pre class=\"nums:false nums-toggle:false lang:default decode:true \">$ gcloud artifacts repositories create ct-demo \\\r\n   --repository-format=docker \\\r\n   --location=asia-south1 \\\r\n   --description=\"Docker repository\"\r\n<\/pre>\n<p>Step 3: Create a Dockerfile<\/p>\n<pre class=\"nums:false nums-toggle:false lang:default decode:true \">$ mkdir ct-demo &amp;&amp; cd ct-demo\r\n$ cat &lt;&lt;EOF &gt; Dockerfile \r\nFROM tomcat:8.5.73-jdk8-corretto\r\n\r\nADD ROOT.war \/usr\/local\/tomcat\/webapps\/\r\n\r\nEXPOSE 8080\r\nCMD [\"catalina.sh\", \"run\"]\r\n<\/pre>\n<p>Step 4: Upload your WAR application in CloudShell<\/p>\n<p><a href=\"https:\/\/content.cloudthat.com\/resources\/wp-content\/uploads\/2022\/11\/GKE3.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-10547\" src=\"https:\/\/content.cloudthat.com\/resources\/wp-content\/uploads\/2022\/11\/GKE3.png\" alt=\"GKE\" width=\"470\" height=\"192\" \/><\/a><\/p>\n<p><a href=\"https:\/\/content.cloudthat.com\/resources\/wp-content\/uploads\/2022\/11\/GKE4.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-10548\" src=\"https:\/\/content.cloudthat.com\/resources\/wp-content\/uploads\/2022\/11\/GKE4.png\" alt=\"GKE\" width=\"332\" height=\"376\" \/><\/a><\/p>\n<p>Step 5: Create Docker image from Dockerfile in the same directory where WAR file is uploaded<\/p>\n<pre class=\"nums:false nums-toggle:false lang:default decode:true \">$ docker build -t asia-south1-docker.pkg.dev\/${PROJECT_ID}\/ct-demo\/demo-app:v1 .\r\n$ docker images \r\n<\/pre>\n<p><strong>Output:<\/strong><\/p>\n<pre class=\"nums:false nums-toggle:false lang:default decode:true\">REPOSITORY                                                 TAG     IMAGE ID       CREATED          SIZE\r\nasia-south1-docker.pkg.dev\/my-project\/ct-demo\/demo-app    v1      25cfadb1bf28   10 seconds ago   154 MB<\/pre>\n<blockquote><p>Note: The PROJECT_ID is environment variable to store Project ID information. Instead of env variable you can also use paste Project ID directly in above command<\/p><\/blockquote>\n<p>Step 6: Push Docker Image in Artifact repository created in Step 2<\/p>\n<pre class=\"nums:false nums-toggle:false lang:default decode:true\">$ gcloud auth configure-docker asia-south1-docker.pkg.dev\r\n\r\n$ docker push asia-south1-docker.pkg.dev\/${PROJECT_ID}\/ct-demo\/demo-app:v1\r\n<\/pre>\n<p>Step 7: Create GKE Cluster<\/p>\n<pre class=\"nums:false nums-toggle:false lang:default decode:true \">$ gcloud config set compute\/zone asia-south1-a\r\n\r\n$ gcloud container clusters create demo-cluster\r\n\r\n#It will take few minutes for cluster to come up.\r\n\r\n#verify cluster by running command below \r\n$ kubectl get nodes<\/pre>\n<p>Step 8: Create deployment.yml from below textbox and run command<\/p>\n<pre class=\"nums:false nums-toggle:false lang:default decode:true\">apiVersion: apps\/v1\r\nkind: Deployment\r\nmetadata:\r\n  name: demoapp\r\nspec:\r\n  replicas: 1\r\n  template:\r\n    metadata:\r\n      name: demoapp\r\n      labels:\r\n        app: demoapp\r\n    spec:\r\n      containers:\r\n      - image: asia-south1-docker.pkg.dev\/my-project \/ct-demo\/demo-app:v1\r\n        name: demoapp-pod\r\n        readinessProbe:\r\n         httpGet:\r\n           path: \/rest\/health\r\n           port: 8080\r\n        ports:         #Container port number\r\n        - containerPort: 8080         \r\n        env:          #Set the environment variable for the container, and you can connect mysql with the tomcat\r\n        - name: JAVA_OPTS\r\n          value: \u201c-dDB\u201d \r\n  selector:\r\n    matchLabels:\r\n      app: demoapp<\/pre>\n<pre class=\"nums:false nums-toggle:false lang:default decode:true\">$ kubectl create -f deployment.yml<\/pre>\n<p>Step 9: Create service.yml from below textbox and run command<\/p>\n<pre class=\"nums:false nums-toggle:false lang:default decode:true \">apiVersion: v1\r\nkind: Service\r\nmetadata:\r\n  name: nodeport-svc-demo\r\nspec:\r\n  type: NodePort\r\n  selector:\r\n    app: demoapp\r\n  ports:\r\n  - name: demo-port\r\n    protocol: TCP\r\n    port: 80\r\n    targetPort: 8080<\/pre>\n<pre class=\"nums:false nums-toggle:false lang:default decode:true\">$ kubectl create -f service.yml<\/pre>\n<p>Step 10: Upload SSL to cloud shell and add SSL into secrets that Ingress controller will use for SSL-termination<\/p>\n<pre class=\"nums:false nums-toggle:false lang:default decode:true\">$ kubectl create secret tls demo-ssl-cert \\\r\n  --cert=path\/to\/cert\/file \\\r\n  --key=path\/to\/key\/file<\/pre>\n<p>Step 11: Create ingress.yml from below textbox and run the command<\/p>\n<pre class=\"nums:false nums-toggle:false lang:default decode:true \">apiVersion: networking.k8s.io\/v1\r\nkind: Ingress\r\nmetadata:\r\n  name: demo-ingress-lb\r\nspec:\r\n  tls:\r\n  - secretName: demo-ssl-cert\r\n  rules:\r\n  - http:\r\n      paths:\r\n      - pathType: ImplementationSpecific\r\n        backend:\r\n          service:\r\n            name: nodeport-svc-demoa\r\n            port:\r\n              name: demo-port<\/pre>\n<pre class=\"nums:false nums-toggle:false lang:default decode:true\">$ kubectl create -f ingress.yml<\/pre>\n<p>Step 12: Review all the resources and test your application by requesting an External IP of the ingress controller<\/p>\n<pre class=\"nums:false nums-toggle:false lang:default decode:true \">$ kubectl get all\r\n\r\n$ kubectl get ingress<\/pre>\n<p><strong>Output:<\/strong><\/p>\n<pre class=\"nums:false nums-toggle:false lang:default decode:true \">NAME                   CLASS    HOSTS   ADDRESS        PORTS     AGE\r\ndemo-ingress-lb   &lt;none&gt;   *       31.4.62.179   80, 443   44s<\/pre>\n<h3>Optional:<\/h3>\n<p>To Create <strong>HorizontalPodAutoscaler <\/strong>on deployment on the basis of CPU usage<\/p>\n<pre class=\"nums:false nums-toggle:false lang:default decode:true\">$ kubectl autoscale deployment demo-app --cpu-percent=80 --min=1 --max=5<\/pre>\n<p>Keep it up! You have deployed a highly available and scalable Tomcat application on GKE<\/p>\n<p>I hope you find this blog helpful for your Kubernetes (GKE) journey<\/p>\n<p>Please do not forget to delete resources to avoid incurring charges to your Google account using the below commands<\/p>\n<pre class=\"nums:false nums-toggle:false lang:default decode:true \"># Delete Ingress\r\n$ kubectl delete ingress demo-ingress-lb\r\n\r\n# Delete Cluster  \r\n$ gcloud container clusters delete demo-cluster --zone asia-south1-a\r\n\r\n# Delete you container image repository\r\n$ gcloud artifacts docker images delete \\\r\n    asia-south1-docker.pkg.dev\/${PROJECT_ID}\/ct-demo\/demo-app:v1 \\\r\n    --delete-tags --quiet<\/pre>\n<h3>Conclusion:<\/h3>\n<p><a href=\"https:\/\/www.cloudthat.com\/training\/vmware\/kubernetes-fundamentals-and-cluster-operations\/\">Kubernetes<\/a> works on the same design principles that run popular Google services and provides the same advantages as automatic management, monitoring, and liveness probes for application containers, automatic scaling, rolling updates, and more. When running your applications on a cluster, you use Google&#8217;s 10+ years of technology and experience to run production workloads in containers.<\/p>\n<p>For detailed information on Kubernetes works, here is a blog on <a href=\"https:\/\/blog.cloudthat.com\/what-is-kubernetes-a-beginners-guide-with-real-world-illustration\/?utm_source=blog-website&amp;utm-medium=text-link&amp;utm_campaign=what-is-kubernetes-a-beginners-guide-with-real-world-illustration\/\" target=\"_blank\" rel=\"noopener\"><strong>Beginner&#8217;s Guide with Real-world Illustration<\/strong><\/a><\/p>\n<h3>About CloudThat<\/h3>\n<p>We here at\u00a0<a href=\"https:\/\/www.cloudthat.com\/\" target=\"_blank\" rel=\"noopener\"><strong>CloudThat<\/strong>\u00a0<\/a>are the official Google Cloud Partner, AWS Advanced Consulting Partner, Microsoft gold partner, helping people develop knowledge on cloud and help their businesses aim for higher goals using best in industry cloud computing practices and expertise. We are on a mission to build\u00a0a robust\u00a0cloud computing ecosystem by disseminating\u00a0knowledge on technological intricacies within the cloud space.\u00a0Our blogs, webinars,\u00a0case studies, and white papers\u00a0enable all the stakeholders in the cloud computing sphere.<\/p>\n<p>Feel free to drop a comment or any queries that you have regarding Google Cloud Platform, Google Kubernetes Engine, consulting requirements and we will get back to you quickly. To get started, go through\u00a0our\u00a0<a href=\"https:\/\/www.cloudthat.com\/expert-advisory\/?utm_source=blog-website&amp;utm-medium=text-link&amp;utm_campaign=expert-advisory\"><strong>Expert Advisory\u00a0<\/strong><\/a>page\u00a0and\u00a0<a href=\"https:\/\/www.cloudthat.com\/managed-services-packages\/\"><strong>Managed Services Package<\/strong><\/a><strong>\u00a0<\/strong>that is\u00a0<a href=\"https:\/\/cloudthat.com\/?utm_source=blog-website&amp;utm-medium=text-link&amp;utm_campaign=cloudthat.com\/\"><strong>CloudThat<\/strong><\/a><strong>\u2019s<\/strong>\u00a0offerings.<\/p>\n","protected":false},"author":219,"featured_media":10731,"parent":0,"comment_status":"open","ping_status":"open","template":"","blog_category":[3607,3718],"user_email":"prarthitm@cloudthat.com","published_by":"324","primary-authors":"","secondary-authors":"","acf":[],"_links":{"self":[{"href":"https:\/\/www.cloudthat.com\/resources\/wp-json\/wp\/v2\/blog\/10542"}],"collection":[{"href":"https:\/\/www.cloudthat.com\/resources\/wp-json\/wp\/v2\/blog"}],"about":[{"href":"https:\/\/www.cloudthat.com\/resources\/wp-json\/wp\/v2\/types\/blog"}],"author":[{"embeddable":true,"href":"https:\/\/www.cloudthat.com\/resources\/wp-json\/wp\/v2\/users\/219"}],"replies":[{"embeddable":true,"href":"https:\/\/www.cloudthat.com\/resources\/wp-json\/wp\/v2\/comments?post=10542"}],"version-history":[{"count":1,"href":"https:\/\/www.cloudthat.com\/resources\/wp-json\/wp\/v2\/blog\/10542\/revisions"}],"predecessor-version":[{"id":45727,"href":"https:\/\/www.cloudthat.com\/resources\/wp-json\/wp\/v2\/blog\/10542\/revisions\/45727"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.cloudthat.com\/resources\/wp-json\/"}],"wp:attachment":[{"href":"https:\/\/www.cloudthat.com\/resources\/wp-json\/wp\/v2\/media?parent=10542"}],"wp:term":[{"taxonomy":"blog_category","embeddable":true,"href":"https:\/\/www.cloudthat.com\/resources\/wp-json\/wp\/v2\/blog_category?post=10542"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}