Kubernetes Readiness Probe 장애를 Events와 로그로 추적하기

mizu·2026년 8월 29일

K8S

목록 보기
7/10

Overview

Kubernetes에서 Pod의 STATUSRunning이라고 해서 애플리케이션이 트래픽을 받을 준비까지 끝났다는 뜻은 아니다. 컨테이너 프로세스는 떠 있을 수 있지만, readiness probe가 실패하면 Pod는 Ready 상태가 되지 않는다. 이 경우 Deployment rollout은 새 ReplicaSet을 만들었더라도 available replica를 확보하지 못해 멈춘 것처럼 보인다.

이번 실습에서는 nginx Deployment가 rollout 중 0 of 2 updated replicas are available 상태에 머물렀다. 원인은 readiness probe가 nginx가 실제로 응답하는 /80 포트가 아니라 /ready8080 포트를 바라보고 있었기 때문이다.

공식 Kubernetes 문서 기준으로 readiness probe는 컨테이너가 트래픽을 받을 준비가 되었는지 판단하는 검사다.

probe가 실패하면 해당 Pod IP는 매칭되는 Service의 EndpointSlice에서 ready backend로 취급되지 않는다. 즉 readiness는 단순한 상태 표시가 아니라, rollout과 트래픽 라우팅 모두에 영향을 준다.

참고 문서:

최소 재현 예제

문제의 핵심은 readiness probe가 애플리케이션이 실제로 listen하지 않는 포트와 경로를 확인했다는 점이다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  namespace: cka-a01
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: web
          image: nginx:1.25
          ports:
            - containerPort: 80
          readinessProbe:
            httpGet:
              path: /ready
              port: 8080
            initialDelaySeconds: 2
            periodSeconds: 5
            failureThreshold: 3

nginx 기본 이미지는 80 포트에서 / 경로에 응답한다. 그런데 probe는 8080 포트의 /ready를 확인하고 있었다.

증상

rollout 상태를 확인하면 Deployment가 available replica를 만들지 못하고 있었다.

kubectl rollout status deploy/web -n cka-a01
Waiting for deployment "web" rollout to finish: 0 of 2 updated replicas are available...

Pod가 완전히 죽은 상태라면 이미지 pull 실패, CrashLoopBackOff, 프로세스 종료 등을 의심할 수 있다. 하지만 이 경우 핵심은 컨테이너 시작이 아니라 readiness였다. Events를 보면 kubelet이 readiness probe를 반복해서 실패시키고 있었다.

kubectl get events -n cka-a01 --sort-by=.lastTimestamp
Warning Unhealthy pod/web-79cd87b765-75bqm Readiness probe failed:
Get "http://<pod-ip-1>:8080/ready": dial tcp <pod-ip-1>:8080: connect: connection refused

Warning Unhealthy pod/web-79cd87b765-vp9fc Readiness probe failed:
Get "http://<pod-ip-2>:8080/ready": dial tcp <pod-ip-2>:8080: connect: connection refused

여기서 중요한 단서는 connect: connection refused다. kubelet이 Pod IP의 8080 포트로 HTTP 요청을 보냈지만, 그 포트에서 수신 중인 프로세스가 없었다.

원인

Deployment 자체가 ReplicaSet과 Pod를 만들지 못한 것은 아니었다. 컨테이너도 시작됐다. 하지만 readiness probe가 잘못된 endpoint를 검사했기 때문에 Pod가 Ready로 전환되지 않았다.

원인은 두 가지 필드였다.

 readinessProbe:
   httpGet:
-    path: /ready
-    port: 8080
+    path: /
+    port: 80
   initialDelaySeconds: 2
   periodSeconds: 5
   failureThreshold: 3

수정

nginx가 실제로 응답하는 경로와 포트에 맞춰 readiness probe를 변경했다.

readinessProbe:
  httpGet:
    path: /
    port: 80
  initialDelaySeconds: 2
  periodSeconds: 5
  failureThreshold: 3

이 수정은 애플리케이션 로직을 바꾸는 것이 아니라 Kubernetes가 준비 상태를 확인하는 방법을 실제 컨테이너 동작에 맞춘 것이다.

검증

수정 후 Deployment와 Pod 상태는 정상으로 돌아왔다.

kubectl get deploy,pod -n cka-a01 -o wide
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES       SELECTOR
deployment.apps/web   2/2     2            2           12m   web          nginx:1.25   app=web

NAME                       READY   STATUS    RESTARTS   IP            NODE
pod/web-785b864f78-9mcbm   1/1     Running   0          <pod-ip-1>   minikube
pod/web-785b864f78-mblc2   1/1     Running   0          <pod-ip-2>   minikube

describe pod에서도 readiness probe가 http://:80/로 바뀐 것을 확인할 수 있다.

kubectl describe pod -n cka-a01 -l app=web
Ready:          True
Readiness:      http-get http://:80/ delay=2s timeout=1s period=5s #success=1 #failure=3

rollout도 성공했다.

kubectl rollout status deploy/web -n cka-a01
deployment "web" successfully rolled out

revision도 1에서 2로 변경됐다.

kubectl rollout history deploy/web -n cka-a01
REVISION  CHANGE-CAUSE
1         <none>
2         <none>

마지막으로 nginx 로그에서 kubelet probe 요청이 HTTP 200으로 처리되는 것을 확인했다.

kubectl logs -n cka-a01 deploy/web --tail=30
<kubelet-source-ip> - - [28/Aug/2026:15:51:49 +0000] "GET / HTTP/1.1" 200 615 "-" "kube-probe/1.28" "-"
<kubelet-source-ip> - - [28/Aug/2026:15:51:51 +0000] "GET / HTTP/1.1" 200 615 "-" "kube-probe/1.28" "-"

Troubleshooting 순서

이런 증상이 보이면 다음 순서로 확인한다.

  1. Deployment rollout 상태를 확인한다.
kubectl rollout status deploy/<name> -n <namespace>
  1. Pod 상태와 READY 컬럼을 확인한다.
kubectl get pod -n <namespace> -o wide
  1. Events에서 readiness probe 실패 메시지를 찾는다.
kubectl get events -n <namespace> --sort-by=.lastTimestamp
  1. Pod describe에서 실제 probe 설정을 확인한다.
kubectl describe pod -n <namespace> -l app=<label>
  1. 컨테이너가 실제로 어떤 포트와 경로에 응답하는지 로그나 직접 요청으로 검증한다.
kubectl logs -n <namespace> deploy/<name> --tail=30

구조 설명

Deployment는 ReplicaSet을 관리하고, ReplicaSet은 Pod를 만든다. 하지만 Deployment가 available replica를 확보하려면 Pod가 단순히 생성되고 컨테이너가 시작되는 것만으로는 부족하다. Pod가 readiness probe를 통과해야 한다.

흐름은 다음과 같다.

Deployment
  -> ReplicaSet
    -> Pod
      -> kubelet readiness probe
        -> Ready=True
          -> Deployment available replica 증가

Pod는 Running이면서 동시에 Ready=False일 수 있다. 이 상태에서는 프로세스는 떠 있지만 Kubernetes는 아직 이 Pod를 트래픽 처리 가능한 backend로 보지 않는다.

Rollback 판단

이 실습에서는 rollback보다 forward fix가 적절했다. 문제 필드가 명확했고, /ready:8080에서 /:80으로 바꾸는 작은 설정 오류였기 때문이다.

다만 새 revision이 더 큰 장애를 만들었거나 원인이 불분명하다면 다음 명령으로 이전 revision으로 되돌릴 수 있다.

kubectl rollout undo deploy/web -n cka-a01

운영 환경에서는 rollback과 forward fix를 기계적으로 고르기보다, 현재 장애 영향과 원인의 명확성을 함께 봐야 한다. 원인이 작고 확실하면 forward fix가 빠를 수 있고, 원인이 불명확하거나 고객 영향이 커지고 있으면 known-good revision으로 되돌리는 판단이 더 안전할 수 있다.

정리

이번 문제의 핵심은 RunningReady를 구분하는 것이다. 컨테이너가 시작됐더라도 readiness probe가 실패하면 Deployment는 available replica를 확보하지 못한다. Events에는 kubelet이 어떤 endpoint를 검사했고 왜 실패했는지가 남는다.

Kubernetes troubleshooting에서 Events는 단순 참고 정보가 아니다. 특히 readiness, scheduling, image pull, mount 실패처럼 control plane과 kubelet이 판단한 이유를 볼 때 가장 먼저 확인할 만한 evidence다.

profile
문제를 해결해보자 ✨

0개의 댓글