Deploy a Java application to Kubernetes on Google Kubernetes Engine
Get the Spring Boot Getting Started Example source code
git clone https://github.com/spring-guides/gs-spring-boot.git
cd gs-spring-boot/complete
Run the Application Locally
You can start the Spring Boot application normally with the Spring Boot plugin:
./mvnw -DskipTests spring-boot:run
Package the Java application as a Docker container
Next, prepare your app to run on Kubernetes. The first step is to define the container and its contents.
First, create the JAR deployable for the application
./mvnw -DskipTests package
Use Jib to create the container image and push it to the Container Registry.
./mvnw -DskipTests com.google.cloud.tools:jib-maven-plugin:build \
-Dimage=gcr.io/$GOOGLE_CLOUD_PROJECT/hello-java:v1
At this point you now have a project-wide Docker image available which Kubernetes can access and orchestrate as you'll see in a few minutes.
You can test the image locally with the following command which will run a Docker container as a daemon on port 8080 from your newly-created container image:
docker run -ti --rm -p 8080:8080 \
gcr.io/$GOOGLE_CLOUD_PROJECT/hello-java:v1
Create your cluster
A cluster consists of a Kubernetes master API server managed by Google and a set of worker nodes. The worker nodes are Compute Engine virtual machines. Let's use the gcloud CLI from your CloudShell session to create a cluster with two n1-standard-1 nodes (this will take a few minutes to complete):
gcloud container clusters create hello-java-cluster \
--num-nodes 2 \
--machine-type n1-standard-1 \
--zone us-central1-c
Deploy your application to Kubernetes
A Kubernetes deployment can create, manage, and scale multiple instances of your application using the container image you've just created. Let's deploy one instance of your application into Kubernetes using the kubectl run command:
kubectl run hello-java \
--image=gcr.io/$GOOGLE_CLOUD_PROJECT/hello-java:v1 \
--port=8080
deployment.apps/hello-java created
To view the deployment you just created, simply run:
kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
hello-java 1 1 1 1 39s
To view the application instances created by the deployment, run this command:
kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-java-9cc6bbf87-62np4 1/1 Running 0 1m
Allow external traffic
By default, the pod is only accessible by its internal IP within the cluster. In order to make the hello-java container accessible from outside the kubernetes virtual network, you have to expose the pod as a kubernetes service.
From Cloud Shell you can expose the pod to the public internet with the kubectl expose command combined with the --type=LoadBalancer flag. This flag is required for the creation of an externally accessible IP :
kubectl expose deployment hello-java --type=LoadBalancer
service/hello-java exposed
To find the publicly-accessible IP address of the service, simply request kubectl to list all the cluster services:
kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-java LoadBalancer 10.15.245.109 35.209.103.19 8080:32124/TCP 2m
kubernetes ClusterIP 10.15.240.1 <none> 443/TCP 7m
You should now be able to reach the service by pointing your browser to this address: http://<EXTERNAL_IP>:8080
curl http://35.209.103.19:8080/
Greetings from Spring Boot!
Scale up your service
One of the powerful features offered by Kubernetes is how easy it is to scale your application. Suppose you suddenly need more capacity for your application; you can simply tell the replication controller to manage a new number of replicas for your application instances:
kubectl scale deployment hello-java --replicas=3
deployment.extensions/hello-java scaled
kubectl get deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
hello-java 3 3 3 3 7m
Note the declarative approach here - rather than starting or stopping new instances you declare how many instances should be running at all time. Kubernetes reconciliation loops simply make sure the reality matches what you requested and takes action if needed.
Roll out an upgrade to your service
At some point the application that you've deployed to production will require bug fixes or additional features. Kubernetes is here to help you deploy a new version to production without impacting your users.
vim src/main/java/hello/HelloController.java
Update the value of the response:
package hello;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
@RestController
public class HelloController {
@RequestMapping("/")
public String index() {
return "Greetings from Admatic!";
}
}
Then rebuild the application with the latest changes:
./mvnw -DskipTests package
Then use Jib to build and push a new version of the container image:
./mvnw -DskipTests com.google.cloud.tools:jib-maven-plugin:build \
-Dimage=gcr.io/$GOOGLE_CLOUD_PROJECT/hello-java:v2
You can use kubectl set image command to ask Kubernetes to deploy the new version of your application across the entire cluster one instance at a time with rolling update:
kubectl set image deployment/hello-java \
hello-java=gcr.io/$GOOGLE_CLOUD_PROJECT/hello-java:v2
deployment.extensions/hello-java image updated
Check http://EXTERNAL_IP:8080 again to see that it's returning the new response.
curl http://35.209.103.19:8080/
Greetings from Admatic!
Roll back
Oops - did you make a mistake with a new version of the application? Perhaps the new version contained an error and you need to rollback quickly. With Kubernetes, you can roll back to the previous state easily. Let's rollback the application by running:
kubectl rollout undo deployment/hello-java