Kubernetes probe와 설정 주입
Compose에서는 컨테이너 하나의 상태만 보았지만 Kubernetes는 재시작 여부와 Service 트래픽 편입 여부를 별도로 판단합니다. 같은 health URL을 두 probe에 복사하면 외부 DB 장애가 pod 재시작 폭주로 번질 수 있으므로 신호의 책임부터 나눠야 합니다.
이 절의 manifest에는 학습용 registry digest와 비밀번호 자리표시자가 들어 있습니다. 실제 cluster에 적용하기 전에 조직 registry의 digest, Secret 관리 방식, 같은 namespace의 postgres Service가 준비되어 있어야 합니다.
probe는 재시작과 트래픽 판단을 나눈다
startup probe는 느린 첫 기동 동안 liveness가 성급하게 재시작하지 않도록 막습니다. 그 뒤 liveness는 JVM이 회복 불가능한 상태인지, readiness는 지금 요청을 받아도 되는지를 판단합니다. DB처럼 외부 의존성은 readiness에만 포함해 pod는 살려 두고 트래픽만 제외합니다.
Actuator probe를 Deployment에 연결한다
add-additional-paths를 켜면 Actuator의 /actuator/health/liveness, /actuator/health/readiness와 별도로 주 서버 포트에 /livez, /readyz가 생깁니다. manifest는 이름 붙은 http 포트를 사용해 컨테이너 포트 변경 지점을 한곳으로 모읍니다.
apiVersion: v1
kind: ConfigMap
metadata:
name: study-log-config
data:
SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/studylog
MANAGEMENT_ENDPOINT_HEALTH_PROBES_ADD_ADDITIONAL_PATHS: "true"
---
apiVersion: v1
kind: Secret
metadata:
name: study-log-secrets
type: Opaque
stringData:
SPRING_DATASOURCE_USERNAME: studylog
SPRING_DATASOURCE_PASSWORD: replace-before-apply
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: study-log-api
spec:
replicas: 2
selector:
matchLabels:
app: study-log-api
template:
metadata:
labels:
app: study-log-api
spec:
terminationGracePeriodSeconds: 40
containers:
- name: api
image: registry.example.com/study-log-api@sha256:8f1c9d6a5b4e3f20718293a4b5c6d7e8f90123456789abcdef0123456789abcd
ports:
- name: http
containerPort: 8080
envFrom:
- configMapRef:
name: study-log-config
- secretRef:
name: study-log-secrets
startupProbe:
httpGet:
path: /livez
port: http
periodSeconds: 5
failureThreshold: 30
livenessProbe:
httpGet:
path: /livez
port: http
periodSeconds: 10
failureThreshold: 3
readinessProbe:
httpGet:
path: /readyz
port: http
periodSeconds: 5
failureThreshold: 2
---
apiVersion: v1
kind: Service
metadata:
name: study-log-api
spec:
selector:
app: study-log-api
ports:
- name: http
port: 80
targetPort: httpmanagement.endpoint.health.probes.enabled=true
management.endpoint.health.probes.add-additional-paths=true
management.endpoint.health.group.readiness.include=readinessState,db
management.endpoint.health.show-details=never
spring.lifecycle.timeout-per-shutdown-phase=30s종료 유예 40초가 Boot의 graceful shutdown 30초보다 길어야 진행 중 요청을 정리할 시간이 남습니다. 반대로 probe 주기와 failure threshold는 재시작·트래픽 제외까지 허용할 시간을 결정하므로 SLO보다 짧고 일시적 흔들림보다는 길게 잡습니다.
설정 변경과 pod 상태 전이를 관찰한다
먼저 cluster 없이 가능한 client dry-run으로 YAML 구조를 확인합니다. 그 검사는 image 존재, Secret 안전성, DB 연결, probe 성공을 보장하지 않습니다. 아래의 server dry-run과 실제 apply는 자리표시자를 교체하고 변경 권한을 받은 학습용 namespace에서만 실행합니다.
kubectl apply --dry-run=client -f k8s/study-log.yaml
# 아래 명령은 image digest와 Secret을 교체하고 study namespace가 준비된 뒤 실행한다.
kubectl -n study apply --dry-run=server -f k8s/study-log.yaml
kubectl -n study apply -f k8s/study-log.yaml
kubectl -n study rollout status deployment/study-log-api --timeout=3mstartup 이후 `/livez`가 성공하고, DB 연결까지 준비되면 `/readyz`가 성공해야 합니다. ConfigMap과 Secret을 env로 읽는 값은 기존 pod 안에서 자동 갱신되지 않으므로 설정만 바꿨다면 새 rollout을 명시적으로 시작해야 합니다.외부 DB 장애를 liveness에 넣지 않는다
DB 장애 때문에 모든 pod를 재시작하면 부하가 커집니다. 의존성 장애는 readiness와 관측 신호로 처리합니다.
DB가 복구되면 같은 pod가 readiness에 다시 들어오는지 관찰합니다. liveness까지 실패한다면 health group에 db가 잘못 포함됐는지부터 확인해야 합니다.
probe가 안정적으로 동작해야 새 image를 일부 또는 순차적으로 노출한 뒤 사용자 지표로 승격 여부를 결정할 수 있습니다.