Kubernetes for Java & Python Developers
Master Pods, Deployments, Services & CI/CD pipelines with real project examples tailored for Java Spring Boot and Python Django/FastAPI applications.
Core Kubernetes Concepts
Pods
The smallest deployable units in Kubernetes. For Java/Python apps, a pod typically contains your application container and sidecars for logging, monitoring, or service mesh.
Developer Tip: Don’t put multiple app containers in one pod unless they’re tightly coupled.
Deployments
Manages the lifecycle of pods. Handles rolling updates, rollbacks, and scaling. Essential for zero-downtime deployments of your Java/Python applications.
Java Tip: Set proper memory limits for JVM apps. Python Tip: Use Gunicorn/Uvicorn workers appropriately.
Services
Abstract way to expose your application. Load balances traffic to pods. Types: ClusterIP (internal), NodePort, LoadBalancer, and Ingress for HTTP routing.
Real-world: Use Ingress for web apps, ClusterIP for microservices communication.
Pod vs Deployment: Quick Comparison
apiVersion: v1
kind: Pod
metadata:
name: java-app-pod
spec:
containers:
- name: spring-boot-app
image: myapp:1.0
ports:
- containerPort: 8080
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "1Gi"
cpu: "500m"apiVersion: apps/v1
kind: Deployment
metadata:
name: java-app-deployment
spec:
replicas: 3
selector:
matchLabels:
app: java-app
template:
metadata:
labels:
app: java-app
spec:
containers:
- name: spring-boot-app
image: myapp:1.0
ports:
- containerPort: 8080
livenessProbe:
httpGet:
path: /actuator/health
port: 8080
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080Java vs Python in Kubernetes
Key Differences & Best Practices
# Dockerfile for Spring Boot FROM openjdk:17-jdk-slim WORKDIR /app COPY target/*.jar app.jar # JVM Memory Configuration ENV JAVA_OPTS="-Xmx512m -Xms256m" ENV SPRING_PROFILES_ACTIVE="k8s" # Health Checks (Spring Actuator) HEALTHCHECK --interval=30s --timeout=3s \ CMD curl -f http://localhost:8080/actuator/health || exit 1 EXPOSE 8080 ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]
Best Practices:
- Set JVM memory limits in Dockerfile & K8s
- Use Spring Actuator for health checks
- Enable graceful shutdown
- Use ConfigMaps for application.properties
# Dockerfile for FastAPI
FROM python:3.11-slim
WORKDIR /app
# Install dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy application
COPY . .
# Gunicorn configuration
ENV WORKERS=4
ENV PORT=8000
# Health check endpoint
HEALTHCHECK --interval=30s --timeout=3s \
CMD curl -f http://localhost:8000/health || exit 1
EXPOSE 8000
CMD ["gunicorn", "main:app", \
"--workers", "4", \
"--worker-class", "uvicorn.workers.UvicornWorker", \
"--bind", "0.0.0.0:8000"]Best Practices:
- Use Gunicorn with Uvicorn workers for async
- Set appropriate worker counts based on CPU
- Implement /health endpoint
- Use environment variables for configuration
Memory Management
Java: Set -Xmx and -Xms flags. Monitor heap usage with JMX or Micrometer.
Python: Watch for memory leaks. Use workers appropriately. Consider using PyPy for CPU-bound tasks.
Health Checks
Java: Spring Boot Actuator provides /health, /readiness, /liveness endpoints out of the box.
Python: Implement custom health endpoints or use FastAPI’s health check extensions.
Configuration
Both: Use ConfigMaps and Secrets. Never hardcode configurations. Use environment-specific profiles.
Production Deployments
Complete Deployment Example
apiVersion: v1
kind: ConfigMap
metadata:
name: spring-app-config
data:
application.properties: |
server.port=8080
spring.datasource.url=${DB_URL}
logging.level.root=INFO
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-boot-deployment
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: spring-boot-app
template:
metadata:
labels:
app: spring-boot-app
spec:
containers:
- name: spring-app
image: myregistry/spring-app:1.2.0
ports:
- containerPort: 8080
env:
- name: DB_URL
valueFrom:
secretKeyRef:
name: db-secret
key: url
- name: JAVA_OPTS
value: "-Xmx512m -Xms256m -XX:+UseG1GC"
volumeMounts:
- name: config-volume
mountPath: /app/config
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
initialDelaySeconds: 60
periodSeconds: 10
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 30
periodSeconds: 5
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "1Gi"
cpu: "500m"
volumes:
- name: config-volume
configMap:
name: spring-app-configRolling Update Strategy
Before Update
During Update
After Update
Commands for Deployment Management
# Deploy application kubectl apply -f spring-deployment.yaml # Check rollout status kubectl rollout status deployment/spring-boot-deployment # View deployment history kubectl rollout history deployment/spring-boot-deployment # Rollback to previous version kubectl rollout undo deployment/spring-boot-deployment # Scale deployment kubectl scale deployment spring-boot-deployment --replicas=5 # Update image version kubectl set image deployment/spring-boot-deployment \ spring-app=myregistry/spring-app:1.3.0
Services & Networking
Service Types Comparison
ClusterIP
Use Case: Internal communication between microservices
Java Example: Spring Boot service calling another Spring Boot service
Python Example: FastAPI service calling a Django REST API
kind: Service
apiVersion: v1
metadata:
name: internal-service
spec:
type: ClusterIP
selector:
app: my-app
ports:
- port: 8080
targetPort: 8080NodePort
Use Case: Development/testing, exposing to external traffic directly
Port Range: 30000-32767
Not Recommended for production web applications
kind: Service
apiVersion: v1
metadata:
name: nodeport-service
spec:
type: NodePort
selector:
app: my-app
ports:
- port: 80
targetPort: 8080
nodePort: 30007LoadBalancer
Use Case: Cloud providers (AWS, GCP, Azure)
Creates: External load balancer
Cost: Additional cloud costs
kind: Service
apiVersion: v1
metadata:
name: loadbalancer-service
spec:
type: LoadBalancer
selector:
app: my-app
ports:
- port: 80
targetPort: 8080Ingress
Use Case: Production web applications (HTTP/HTTPS)
Features: SSL termination, path-based routing, virtual hosts
Requires: Ingress Controller (nginx, traefik)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
spec:
rules:
- host: app.tktips.org
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: spring-app-service
port:
number: 8080Complete Example: Spring Boot with Ingress
# Spring Boot Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-boot-api
spec:
replicas: 3
selector:
matchLabels:
app: spring-api
template:
metadata:
labels:
app: spring-api
spec:
containers:
- name: api
image: myapp/api:2.1.0
ports:
- containerPort: 8080
env:
- name: SPRING_PROFILES_ACTIVE
value: "production"
---
# Service
apiVersion: v1
kind: Service
metadata:
name: spring-api-service
spec:
selector:
app: spring-api
ports:
- port: 80
targetPort: 8080
---
# Ingress (NGINX)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
tls:
- hosts:
- api.tktips.org
secretName: api-tls-secret
rules:
- host: api.tktips.org
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: spring-api-service
port:
number: 80CI/CD Pipeline for Kubernetes
Modern CI/CD Pipeline for Java & Python Apps
1. Code Commit
Developer pushes code to Git repository (GitHub/GitLab)
2. Build & Test
Java: Maven/Gradle build + unit tests
Python: pip install + pytest
3. Build Image
Create Docker image
Tag with commit SHA
Push to registry
4. Security Scan
Scan for vulnerabilities
Check dependencies
Image signing
5. Deploy to K8s
Update deployment
Canary/Rolling update
Health checks
6. Monitor & Verify
Monitor metrics
Automated rollback if needed
Performance verification
GitHub Actions Example
name: Java CI/CD to Kubernetes
on:
push:
branches: [ main ]
jobs:
build-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
- name: Build with Maven
run: mvn clean package -DskipTests
- name: Run tests
run: mvn test
- name: Build Docker image
run: |
docker build -t myregistry/java-app:${{ github.sha }} .
docker push myregistry/java-app:${{ github.sha }}
deploy:
needs: build-test
runs-on: ubuntu-latest
steps:
- name: Deploy to Kubernetes
run: |
# Update deployment with new image
kubectl set image deployment/java-app \
java-app=myregistry/java-app:${{ github.sha }}
kubectl rollout status deployment/java-app
- name: Run integration tests
run: |
# Test the deployed application
./scripts/integration-test.shname: Python CI/CD to Kubernetes
on:
push:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Run tests
run: |
pytest --cov=app tests/
build-deploy:
needs: test
runs-on: ubuntu-latest
steps:
- name: Build Docker image
run: |
docker build -t myregistry/python-app:${{ github.sha }} .
docker push myregistry/python-app:${{ github.sha }}
- name: Configure kubectl
uses: azure/setup-kubectl@v3
with:
version: 'latest'
- name: Deploy to Kubernetes
run: |
# Use kustomize for environment-specific configs
kustomize build k8s/overlays/prod | \
kubectl apply -f -
kubectl rollout status deployment/python-app
- name: Health check
run: |
# Wait for service to be healthy
./scripts/health-check.shGitOps with ArgoCD/Flux
Recommended for production: Use GitOps tools to sync your Kubernetes manifests automatically.
# ArgoCD Application Manifest
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: java-app
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/yourrepo/k8s-manifests
targetRevision: HEAD
path: apps/java-app/overlays/prod
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=trueReal Project Examples
E-commerce Microservices (Java)
Stack: Spring Boot + MySQL + Redis + Kafka
K8s Components:
- Deployments for each service
- ConfigMaps for application properties
- Secrets for database credentials
- Ingress for API gateway
- Horizontal Pod Autoscaler
- StatefulSets for MySQL and Kafka
k8s/
βββ base/
β βββ deployment.yaml
β βββ service.yaml
β βββ hpa.yaml
βββ overlays/
β βββ dev/
β βββ prod/
βββ databases/
βββ mysql-statefulset.yaml
βββ redis-deployment.yamlData Processing Pipeline (Python)
Stack: FastAPI + Celery + PostgreSQL + RabbitMQ
K8s Components:
- Deployments for API and workers
- Jobs for batch processing
- CronJobs for scheduled tasks
- PersistentVolumeClaims for data
- Network Policies for security
- Service Mesh for observability
apiVersion: apps/v1
kind: Deployment
metadata:
name: celery-worker
spec:
replicas: 5
template:
spec:
containers:
- name: worker
image: python-worker:latest
command: ["celery", "-A", "tasks", "worker"]
resources:
requests:
cpu: "200m"
memory: "256Mi"Hybrid Java-Python Application
Scenario: Java backend + Python ML service
Architecture:
- Spring Boot REST API (Java)
- FastAPI ML service (Python)
- Shared Redis cache
- Unified monitoring with Prometheus
- Centralized logging with Loki
# Java calls Python service String mlUrl = "http://ml-service/predict"; ResponseEntityresponse = restTemplate.postForEntity(mlUrl, data, String.class); # Python service definition apiVersion: v1 kind: Service metadata: name: ml-service spec: selector: app: ml-api ports: - port: 8000 targetPort: 8000
Deployment Strategies in Practice
Blue-Green Deployment
Use when: Zero downtime critical
Java/Python: Perfect for both
Implementation: Two identical environments, switch traffic at load balancer
Canary Release
Use when: Testing with real users
Implementation: Gradually route traffic to new version
# Using Istio for traffic splitting
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
spec:
hosts:
- myapp.tktips.org
http:
- route:
- destination:
host: myapp
subset: v1
weight: 90
- destination:
host: myapp
subset: v2
weight: 10Rolling Update
Use when: Default for most apps
K8s Native: Built into Deployments
Configuration: maxSurge and maxUnavailable
Quick Tips & Best Practices
π‘ Resource Limits
Always set memory and CPU limits for Java apps. JVM needs to know its limits for garbage collection tuning.
π Python Workers
For Python web apps, set worker count based on available CPU: workers = 2 * CPU cores + 1
π§ Health Checks
Implement proper liveness and readiness probes. Spring Boot Actuator and FastAPI health endpoints make this easy.
π¦ Multi-Stage Builds
Use multi-stage Docker builds to keep image sizes small. Critical for fast deployments.
π Secrets Management
Never store secrets in configmaps. Use Kubernetes Secrets or external secret managers like HashiCorp Vault.
π Monitoring
Java: Use Micrometer with Prometheus. Python: Use Prometheus client library. Both integrate seamlessly with K8s.
π Graceful Shutdown
Handle SIGTERM signals properly. Spring Boot and FastAPI both support graceful shutdown out of the box.
π Startup Probes
Use startup probes for apps with long initialization (like Spring Boot with large context).
Common Issues & Solutions
Java: OOM Killed
Problem: Container killed due to memory limit
Solution: Set -Xmx lower than container memory limit (leave room for overhead)
JAVA_OPTS="-Xmx512m" # for 1Gi container limitPython: High CPU Usage
Problem: Gunicorn workers using too much CPU
Solution: Tune worker count and threads
workers = (2 * cpu_cores) + 1Both: Slow Startup
Problem: Pods taking too long to start
Solution: Use startup probes and consider readiness gates
Essential kubectl Commands
# Get pods with wide output kubectl get pods -o wide # Watch pods in real-time kubectl get pods --watch # Describe a specific pod kubectl describe pod <pod-name> # Get logs from a pod kubectl logs <pod-name> -f # follow logs # Execute command in pod kubectl exec -it <pod-name> -- /bin/bash # Port forward to local machine kubectl port-forward pod/<pod-name> 8080:8080 # Get all resources in namespace kubectl get all -n <namespace> # Check events for troubleshooting kubectl get events --sort-by=.metadata.creationTimestamp # Apply configuration kubectl apply -f deployment.yaml # Rollback deployment kubectl rollout undo deployment/<deployment-name>
Ready to Deploy Your Java/Python Apps on Kubernetes?
Start with our step-by-step tutorials and example projects.
