CODE WITH SIBIN

Solving Real Problems with Real Code


Deploying a Spring Boot Application on Google Kubernetes Engine (GKE)

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

  1. Go to Cloud Build in GCP Console
  2. Click "Create Trigger"
  3. Connect your repository
  4. Set the configuration file to cloudbuild.yaml
  5. 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:

  1. Containerized Spring Boot application
  2. GKE cluster with autoscaling
  3. CI/CD pipeline
  4. Monitoring and logging
  5. 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.

Leave a Reply

Your email address will not be published. Required fields are marked *