Advanced · Ship
Production Implementation: Immutable Deploy Pipeline
Package a minimal image, wire probes and graceful shutdown, and deliver through a pipeline whose secrets never appear in logs or layers.
Primary source: Spring Boot 3.5 Reference: Container Images & Probes
Lesson 4 of 4
1d streakThe Architectural Question
Images that bake configuration break the moment they leave one environment; missing readiness probes make every deploy an outage window.
What this guide proves
- Bake a non-root JVM image with layered jars
- Split liveness from readiness and prove rolling behavior
- Inject secrets at runtime from the platform, never the image
Enterprise GitOps & Declarative Infrastructure As Code
In modern enterprise architectures, manual kubectl commands are forbidden. GitOps establishes a single source of truth: the Git repository containing declarative Kubernetes manifests synchronized by controllers like ArgoCD or Flux.
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service
labels:
app: order-service
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: order-service
template:
metadata:
labels:
app: order-service
spec:
containers:
- name: app
image: registry.internal/order-service:v2.1.0
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 15
periodSeconds: 5
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
initialDelaySeconds: 30
periodSeconds: 10Zero-Downtime Deployment: Rolling vs Blue/Green vs Canary
Achieving true zero-downtime deployments requires aligning application backward compatibility with routing strategies:
| Strategy | Mechanics | Pros & Cons |
|---|---|---|
| Rolling Update | Gradually replaces old pods with new pods 1-by-1 | Low resource cost; both versions run concurrently, requiring database backward compatibility |
| Blue/Green | Deploys full duplicate v2 fleet, switches router at once | Instant rollback; requires 2x compute capacity and database backward/forward compatibility |
| Canary Release | Routes 5% of traffic to v2, monitors error rates, then scales | Limits blast radius; requires advanced ingress/service mesh (Istio, Linkerd, Envoy) |
Automated Health-Driven Rollbacks via Prometheus & Argo Rollouts
Enterprise delivery pipelines must not rely on humans staring at dashboards. Automated rollbacks must trigger if the new release exhibits elevated HTTP 5xx error rates, latency regression, or container crash loops.
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: success-rate-check
spec:
metrics:
- name: success-rate
interval: 1m
successCondition: result[0] >= 0.999
failureLimit: 2
provider:
prometheus:
address: http://prometheus.monitoring:9090
query: |
sum(rate(http_server_requests_seconds_count{status!~"5.*",app="order-service"}[1m]))
/
sum(rate(http_server_requests_seconds_count{app="order-service"}[1m]))End-to-End Production Deployment Verification Checklist
Prior to signing off on a production deployment, verify all four golden deployment signals:
# 1. Verify Pod Disruption Budget (PDB) is present to prevent node drain outages
kubectl get pdb order-service-pdb
# 2. Verify rolling update maxUnavailable is 0
kubectl get deployment order-service -o jsonpath='{.spec.strategy.rollingUpdate.maxUnavailable}'
# EXPECTED: 0 (or 0%)
# 3. Simulate rolling update and observe zero HTTP request drops
hey -n 10000 -c 50 -q 50 http://api.internal/orders &
kubectl rollout restart deployment order-service
wait
# EXPECTED: 10,000 requests, 0 status 502/503/504 errors!Active Recall Checkpoint
Why does a rolling update require strict backward-compatible database migrations?
Hint: Review expand-and-contract schema migration patterns.
Show answer & explanation
During a rolling update, pods running version N and version N+1 operate concurrently against the same database schema. If version N+1 makes a breaking schema change (like dropping or renaming a column), version N pods will immediately crash.
Runtime Architecture & Flow
High-value visual model
Readiness, Liveness and Shutdown
Safe rollout depends on separating traffic routing, restart decisions, and termination drain.
1. Startup
The pod starts, loads configuration, and warms required infrastructure.
2. Readiness passes
The platform may now route traffic to this instance.
3. Readiness fails before stop
Traffic is removed before in-flight work is drained.
4. Graceful termination
HTTP requests, consumers, and pools close within the termination budget.
Working Implementation
Core Spring Implementation
Immutable deployment with probes and graceful shutdown
Promote one immutable image through environments, gate traffic with readiness, restart with liveness, and drain in-flight requests using server.shutdown=graceful.
Component Boundaries
- 01CI builds and scans a non-root image once; configuration and secrets inject at runtime and never bake into layers.
- 02Readiness controls Service endpoints; liveness controls restarts, so a downstream outage flips readiness only.
- 03management.endpoint.health.probes.enabled exposes /actuator/health/readiness and /liveness outside Kubernetes, and server.shutdown=graceful drains active requests on SIGTERM.
Required Evidence
- kubectl delete pod logs the Tomcat line "Commencing graceful shutdown. Waiting for active requests to complete" followed by "Graceful shutdown complete".
- terminationGracePeriodSeconds exceeds the slowest in-flight request, proven by zero 5xx spikes during a rolling update.
- Rollback pins the previous image digest, with Flyway migrations verified forward-compatible before promotion.
Implementation sequence
Step-by-Step Integration
Follow these structured steps to inject Core Spring functionality cleanly across your boundaries.
Bake a minimal non-root image
Dockerfile
Root-owned containers fail restricted Pod Security Standards and widen blast radius; the same digest moves unchanged across environments, or bootBuildImage produces an equivalent Paketo non-root OCI image without a Dockerfile.
FROM eclipse-temurin:21-jre
WORKDIR /app
RUN addgroup --system spring && adduser --system spring --ingroup spring
COPY target/app.jar app.jar
USER spring:spring
ENTRYPOINT ["java", "-jar", "/app/app.jar"]Verify Configuration
docker inspect --format "{{.Config.User}}" app:1.0.0 prints spring, and trivy image app:1.0.0 reports no critical CVEs in the base layer.
Split liveness from readiness
deployment.yaml
Probe endpoints ship disabled by default and switch on automatically when deployed to Kubernetes, or set management.endpoint.health.probes.enabled=true; binding liveness to downstream dependencies converts a cache blip into a restart storm.
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080Verify Configuration
kubectl get pods shows READY 1/1 only after curl localhost:8080/actuator/health/readiness returns {"status":"UP"}; stopping Redis flips readiness to HTTP 503 {"status":"OUT_OF_SERVICE"} while /actuator/health/liveness keeps returning 200.
Synthesis & Production Verification
Deliberate Failure Condition
- Break: Copy application-prod.yml containing credentials into the image
- Observe: Anyone who can pull the image owns your database, and config changes require a rebuild
- Repair: Immutable images stay environment-free: inject values at runtime so one artifact serves every environment safely.
Production Acceptance Criteria
- One image boots dev and prod differing only in environment variables
- Readiness gates traffic until the app can serve
- SIGTERM drains in-flight requests before exit
Key Takeaway
Enterprise delivery uses declarative GitOps synchronization with RollingUpdate or Canary strategies, backed by automated health-driven rollbacks on SLO regression.
Architectural & Technical Review
Core Interview Questions
Q01How does GitOps with declarative Kubernetes manifests prevent configuration drift across environments?Show answer
GitOps controllers like ArgoCD continuously reconcile the live cluster state against declarative manifests in Git. Any manual changes made in the cluster are automatically overwritten or flagged as out-of-sync.
Q02What are the trade-offs between RollingUpdate, Blue/Green, and Canary deployment strategies?Show answer
RollingUpdate uses minimal resources but runs mixed versions simultaneously, requiring database backward compatibility. Blue/Green offers instant rollback but requires 2x compute capacity. Canary limits blast radius by routing a small percentage of traffic first.
Q03How do automated analysis templates trigger automatic deployment rollbacks based on Prometheus metrics?Show answer
Analysis templates query Prometheus for golden signals (HTTP 5xx error rate, p99 latency) during canary rollout. If the error rate exceeds the SLO threshold, the rollout controller aborts promotion and scales old pods back up.
Production Pitfalls
Critical Anti-Patterns
- Pitfall: Deploying breaking database schema migrations simultaneously with rolling application updates — Version N pods still running will crash immediately when version N+1 removes or alters columns.
- Pitfall: Setting rollingUpdate maxUnavailable > 0 without adequate replica headroom — Causes capacity drops and request throttling during high-traffic midday deployments.
Module Certification Quiz
Prove Module Mastery
Comprehensive question set covering all lessons in this module.
Primary Documentation & Specifications
Lesson Primary References
Supplementary Module Resources