Achieve Zero‑Downtime Deployments with K8s and Spring Boot: Health Checks, Rolling Updates, and Autoscaling
This guide explains how to combine Kubernetes and Spring Boot to implement zero‑downtime releases by configuring readiness and liveness probes, defining graceful shutdown, applying rolling update strategies, setting up horizontal pod autoscaling, integrating Prometheus monitoring, and separating configuration via ConfigMaps for reusable images.
Zero‑Downtime Deployment with K8s and Spring Boot
Health Check
Readiness probe + Liveness probe
Probe types: exec, tcpSocket, httpGet
Business Layer
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>Define access port, path and permissions in application.yaml:
management:
server:
port: 50000 # enable independent management port
endpoint:
health:
probes:
enabled: true
endpoints:
web:
exposure:
base-path: /actuator
include: healthExpose the following endpoints:
http://127.0.0.1:50000/actuator/health/readiness
http://127.0.0.1:50000/actuator/health/livenessOperations Layer
K8s deployment template ( deployment.yaml) with probes:
apiVersion: apps/v1
kind: Deployment
spec:
template:
spec:
containers:
- name: {APP_NAME}
image: {IMAGE_URL}
ports:
- containerPort: {APP_PORT}
- name: management-port
containerPort: 50000
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: management-port
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 1
successThreshold: 1
failureThreshold: 6
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: management-port
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 1
successThreshold: 1
failureThreshold: 6Rolling Update
Rolling update strategy to achieve zero‑downtime releases:
apiVersion: apps/v1
kind: Deployment
metadata:
name: {APP_NAME}
spec:
selector:
matchLabels:
app: {APP_NAME}
replicas: {REPLICAS}
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1Graceful Shutdown
Enable graceful shutdown in Spring Boot and expose the shutdown endpoint:
spring:
lifecycle:
timeout-per-shutdown-phase: 30s
server:
port: 8080
shutdown: graceful
management:
server:
port: 50000
endpoint:
shutdown:
enabled: true
health:
probes:
enabled: true
endpoints:
web:
exposure:
base-path: /actuator
include: health,shutdownCall the shutdown endpoint:
curl -X POST 127.0.0.1:50000/actuator/shutdownOperations Layer
Dockerfile template (ensure curl is installed):
FROM openjdk:8-jdk-alpine
ARG JAR_FILE
ARG WORK_PATH="/app"
ARG EXPOSE_PORT=8080
ENV JAVA_OPTS=""
ENV JAR_FILE=${JAR_FILE}
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' > /etc/timezone \
&& sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories \
&& apk add --no-cache curl
COPY target/$JAR_FILE $WORK_PATH/
WORKDIR $WORK_PATH
EXPOSE $EXPOSE_PORT
ENTRYPOINT exec java $JAVA_OPTS -jar $JAR_FILEAutoscaling
Define resource limits and create a HorizontalPodAutoscaler:
apiVersion: apps/v1
kind: Deployment
spec:
template:
spec:
containers:
- name: {APP_NAME}
resources:
limits:
cpu: 0.5
memory: 1Gi
requests:
cpu: 0.15
memory: 300Mi
---
kind: HorizontalPodAutoscaler
apiVersion: autoscaling/v2beta2
metadata:
name: {APP_NAME}
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: {APP_NAME}
minReplicas: {REPLICAS}
maxReplicas: 6
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50Prometheus Integration
Dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>Configure Prometheus endpoints:
management:
server:
port: 50000
metrics:
tags:
application: ${spring.application.name}
endpoints:
web:
exposure:
base-path: /actuator
include: metrics,prometheusExpose /actuator/metric and /actuator/prometheus:
http://127.0.0.1:50000/actuator/metric
http://127.0.0.1:50000/actuator/prometheusAnnotate pods for Prometheus scraping:
apiVersion: apps/v1
kind: Deployment
spec:
template:
metadata:
annotations:
prometheus.io/port: "50000"
prometheus.io/path: /actuator/prometheus
prometheus.io/scrape: "true"Config Separation
Generate a ConfigMap from an external application-test.yaml file:
# Generate ConfigMap YAML (dry‑run)
kubectl create cm -n <namespace> <APP_NAME> --from-file=application-test.yaml --dry-run=1 -o yaml > configmap.yaml
# Apply the ConfigMap
kubectl apply -f configmap.yamlMount the ConfigMap and activate a profile:
apiVersion: apps/v1
kind: Deployment
spec:
template:
spec:
env:
- name: SPRING_PROFILES_ACTIVE
value: test
volumeMounts:
- name: conf
mountPath: "/app/config"
readOnly: true
volumes:
- name: conf
configMap:
name: {APP_NAME}Summary Configuration
Combined dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>Unified application.yaml settings:
spring:
application:
name: project-sample
profiles:
active: @profileActive@
lifecycle:
timeout-per-shutdown-phase: 30s
server:
port: 8080
shutdown: graceful
management:
server:
port: 50000
metrics:
tags:
application: ${spring.application.name}
endpoint:
shutdown:
enabled: true
health:
probes:
enabled: true
endpoints:
web:
exposure:
base-path: /actuator
include: health,shutdown,metrics,prometheusDockerfile (same as above) and final deployment.yaml include readiness/liveness probes, resource limits, autoscaling, and Prometheus annotations.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
