This comprehensive guide will walk you through deploying a Spring Boot application on Google Kubernetes Engine (GKE) from scratch, covering everything from project setup to production deployment.
Prerequisites
- Google Cloud Platform (GCP) account
- Basic knowledge of Spring Boot and Kubernetes
- Docker installed on your local machine
- JDK 17 or later
- Maven or Gradle build tool
Part 1: Setting Up Your Spring Boot Application
1. Create a Spring Boot Application
If you don't have an existing application, create one:
# Using Spring Initializr (https://start.spring.io/)
# Or with curl:
curl https://start.spring.io/starter.zip -d dependencies=web,actuator \
-d type=gradle-project -d language=java -d bootVersion=3.2.0 \
-d groupId=com.example -d artifactId=myapp -o myapp.zip
unzip myapp.zip
cd myapp
2. Add a Simple REST Controller
Create src/main/java/com/example/myapp/MyController.java
:
package com.example.myapp;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyController {
@GetMapping("/")
public String home() {
return "Hello from Spring Boot on GKE!";
}
@GetMapping("/health")
public String health() {
return "OK";
}
}
3. Configure Actuator for Health Checks
Add to application.properties
or application.yml
:
management:
endpoint:
health:
show-details: always
endpoints:
web:
exposure:
include: health,info
4. Test Locally
./gradlew bootRun
# Or for Maven: ./mvnw spring-boot:run
Visit http://localhost:8080
to verify it works.
Part 2: Containerizing Your Application
1. Create a Dockerfile
Create Dockerfile
in the project root:
# Build stage
FROM eclipse-temurin:17-jdk-jammy as builder
WORKDIR /workspace/app
COPY gradlew .
COPY gradle gradle
COPY build.gradle .
COPY settings.gradle .
COPY src src
RUN chmod +x gradlew
RUN ./gradlew bootJar
# Run stage
FROM eclipse-temurin:17-jre-jammy
WORKDIR /app
COPY --from=builder /workspace/app/build/libs/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
2. Build the Docker Image
docker build -t my-spring-boot-app .
3. Test the Container Locally
docker run -p 8080:8080 my-spring-boot-app
Verify at http://localhost:8080
.
Part 3: Setting Up Google Cloud Platform
1. Install Google Cloud SDK
Follow instructions for your OS: https://cloud.google.com/sdk/docs/install
2. Initialize and Authenticate
gcloud init
gcloud auth login
gcloud auth configure-docker
3. Create a GCP Project
gcloud projects create my-spring-boot-project --name="Spring Boot on GKE"
gcloud config set project my-spring-boot-project
4. Enable Required APIs
gcloud services enable \
container.googleapis.com \
containerregistry.googleapis.com \
compute.googleapis.com
Part 4: Pushing Docker Image to Google Container Registry (GCR)
1. Tag Your Image
docker tag my-spring-boot-app gcr.io/my-spring-boot-project/my-spring-boot-app:1.0.0
2. Push to GCR
docker tag my-spring-boot-app gcr.io/my-spring-boot-project/my-spring-boot-app:1.0.0
Part 5: Setting Up Google Kubernetes Engine (GKE)
1. Create a GKE Cluster
gcloud container clusters create-auto my-spring-cluster \
--region us-central1 \
--project my-spring-boot-project
For production, consider a standard cluster with more control:
gcloud container clusters create my-spring-cluster \
--region us-central1 \
--num-nodes=2 \
--machine-type=e2-medium \
--enable-autoscaling --min-nodes=1 --max-nodes=5 \
--enable-vertical-pod-autoscaling \
--enable-autorepair \
--enable-autoupgrade
2. Configure kubectl
gcloud container clusters get-credentials my-spring-cluster --region us-central1
Verify connection:
kubectl get nodes
Part 6: Deploying to Kubernetes
1. Create Kubernetes Deployment Manifest
Create deployment.yaml
:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-spring-boot-app
labels:
app: my-spring-boot-app
spec:
replicas: 2
selector:
matchLabels:
app: my-spring-boot-app
template:
metadata:
labels:
app: my-spring-boot-app
spec:
containers:
- name: my-spring-boot-app
image: gcr.io/my-spring-boot-project/my-spring-boot-app:1.0.0
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
livenessProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 20
periodSeconds: 5
resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
cpu: "1000m"
memory: "1024Mi"
2. Create Kubernetes Service Manifest
Create service.yaml
:
apiVersion: v1
kind: Service
metadata:
name: my-spring-boot-service
spec:
type: LoadBalancer
selector:
app: my-spring-boot-app
ports:
- protocol: TCP
port: 80
targetPort: 8080
3. Deploy to Kubernetes
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
4. Verify Deployment
kubectl get pods
kubectl get deployments
kubectl get services
Wait for the external IP to be assigned to your service, then visit it in your browser.
Part 7: Advanced Configuration
1. Horizontal Pod Autoscaling
Create hpa.yaml
:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: my-spring-boot-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-spring-boot-app
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
Apply it:
kubectl apply -f hpa.yaml
2. ConfigMaps for Application Properties
Create configmap.yaml
:
apiVersion: v1
kind: ConfigMap
metadata:
name: spring-boot-config
data:
application.yaml: |
server:
port: 8080
spring:
application:
name: my-spring-boot-app
management:
endpoints:
web:
exposure:
include: health,info
endpoint:
health:
show-details: always
Update your deployment to use the ConfigMap:
# Add this to your deployment.yaml under spec.template.spec
volumes:
- name: config-volume
configMap:
name: spring-boot-config
containers:
- name: my-spring-boot-app
# ... existing container config ...
volumeMounts:
- name: config-volume
mountPath: /config
env:
- name: SPRING_CONFIG_LOCATION
value: file:/config/application.yaml
3. Secrets Management
Create a secret (e.g., for database credentials):
kubectl create secret generic db-secret \
--from-literal=username=admin \
--from-literal=password=secretpassword
Reference it in your deployment:
env:
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: db-secret
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
Part 8: CI/CD Pipeline Setup
1. Create Cloud Build Trigger
Create cloudbuild.yaml
:
steps:
# Build the application
- name: 'gcr.io/cloud-builders/gradle'
args: ['build']
id: 'build'
# Build Docker image
- name: 'gcr.io/cloud-builders/docker'
args: ['build', '-t', 'gcr.io/$PROJECT_ID/my-spring-boot-app:$COMMIT_SHA', '.']
id: 'docker-build'
# Push Docker image
- name: 'gcr.io/cloud-builders/docker'
args: ['push', 'gcr.io/$PROJECT_ID/my-spring-boot-app:$COMMIT_SHA']
id: 'docker-push'
# Deploy to Kubernetes
- name: 'gcr.io/cloud-builders/gcloud'
args: ['kubectl', 'set', 'image', 'deployment/my-spring-boot-app',
'my-spring-boot-app=gcr.io/$PROJECT_ID/my-spring-boot-app:$COMMIT_SHA',
'--cluster=gke_${PROJECT_ID}_us-central1_my-spring-cluster']
id: 'deploy'
images:
- 'gcr.io/$PROJECT_ID/my-spring-boot-app:$COMMIT_SHA'
2. Set Up GitHub/GitLab Trigger
- Go to Cloud Build in GCP Console
- Click "Create Trigger"
- Connect your repository
- Set the configuration file to
cloudbuild.yaml
- Configure the trigger conditions (e.g., on push to main branch)
Part 9: Monitoring and Logging
1. Enable Cloud Monitoring and Logging
gcloud container clusters update my-spring-cluster \
--region us-central1 \
--monitoring=SYSTEM,APISERVER,CONTROLLER-MANAGER,SCHEDULER \
--logging=SYSTEM,WORKLOAD
2. Access Logs
kubectl logs -f <pod-name>
Or view in Cloud Logging console.
3. Set Up Prometheus Monitoring
Add Prometheus dependency to your Spring Boot app:
implementation 'io.micrometer:micrometer-registry-prometheus'
Update actuator exposure:
management:
endpoints:
web:
exposure:
include: health,info,prometheus
Deploy Prometheus to your cluster:
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/prometheus-engine/v0.4.3/examples/example-app.yaml
Part 10: Production Considerations
1. Database Connectivity
For production, consider using Cloud SQL:
gcloud sql instances create my-spring-db \
--database-version=POSTGRES_13 \
--cpu=2 \
--memory=7680MB \
--region=us-central1
Configure your Spring Boot app to use it with proper connection pooling.
2. SSL/TLS Termination
Set up Google Cloud Load Balancer with SSL certificate:
gcloud compute ssl-certificates create my-ssl-cert \
--domains=myapp.example.com \
--global
Update your service to use the certificate.
3. Backup and Disaster Recovery
Set up regular backups for your database and consider:
gcloud container clusters update my-spring-cluster \
--region us-central1 \
--enable-backup-restore \
--backup-config-bucket=my-backup-bucket
4. Cost Optimization
- Use preemptible nodes for non-critical workloads
- Right-size your pods
- Implement cluster autoscaling
- Monitor with Cloud Billing reports
Part 11: Maintenance and Updates
1. Rolling Updates
kubectl set image deployment/my-spring-boot-app my-spring-boot-app=gcr.io/my-spring-boot-project/my-spring-boot-app:2.0.0
kubectl rollout status deployment/my-spring-boot-app
2. Rollback
kubectl rollout undo deployment/my-spring-boot-app
3. Scaling
kubectl scale deployment my-spring-boot-app --replicas=5
Part 12: Cleanup
When you're done testing:
# Delete the deployment and service
kubectl delete -f deployment.yaml
kubectl delete -f service.yaml
# Delete the cluster
gcloud container clusters delete my-spring-cluster --region us-central1
# Delete the container image
gcloud container images delete gcr.io/my-spring-boot-project/my-spring-boot-app:1.0.0
# Delete the project (careful!)
gcloud projects delete my-spring-boot-project
Conclusion
You've now successfully deployed a Spring Boot application on Google Kubernetes Engine with production-grade configurations. This setup includes:
- Containerized Spring Boot application
- GKE cluster with autoscaling
- CI/CD pipeline
- Monitoring and logging
- Production considerations like SSL and databases
For further optimization, consider implementing service meshes like Istio, advanced monitoring with Grafana, and more sophisticated CI/CD workflows with multiple environments.