생존성, 준비성 및 시작 프로브
생존성, 준비성 및 시작 프로브 (Liveness, Readiness, and Startup Probes)
Kubernetes는 Pod에 있는 컨테이너의 상태를 지속적으로 모니터링할 수 있도록 프로브(probe)를 정의하게 해줍니다. 프로브는 kubelet이 컨테이너에 대해 주기적으로 수행하는 진단입니다. 진단을 수행하기 위해 kubelet은 컨테이너 안에서 코드를 실행하거나 네트워크 요청을 합니다.
프로브 결과에 따라 Kubernetes는 비정상 컨테이너를 재시작하거나 준비되지 않은 컨테이너로의 트래픽 전송을 중단할 수 있습니다.
출처: 문서
본문
프로브 유형 (Types of probe)
kubelet은 선택적으로 실행 중인 컨테이너에 대해 세 가지 종류의 프로브를 수행하고 대응할 수 있으며, 각각 다른 목적을 제공합니다.
- 시작 프로브 (Startup probe)
- 생존성 프로브 (Liveness probe)
- 준비성 프로브 (Readiness probe)
시작 프로브 (Startup probe)
시작 프로브는 컨테이너 안의 애플리케이션이 시작되었는지 확인합니다. 시작 프로브가 구성되면, Kubernetes는 시작 프로브가 성공할 때까지 생존성 또는 준비성 프로브를 실행하지 않으므로 애플리케이션이 초기화를 마칠 시간을 줍니다.
이 유형의 프로브는 주기적으로 실행되는 생존성 및 준비성 프로브와 달리 시작 시에만 실행됩니다. 시작 프로브가 실패하면 kubelet이 컨테이너를 죽이고, 컨테이너는 재시작 정책(restart policy)에 따릅니다.
생존성 프로브 (Liveness probe)
생존성 프로브는 컨테이너를 언제 재시작할지 결정합니다. 예를 들어 생존성 프로브는 애플리케이션이 실행 중이지만 진행할 수 없는 교착 상태(deadlock)를 잡을 수 있습니다. 그런 상태의 컨테이너를 재시작하면 버그가 있어도 애플리케이션을 더 사용 가능하게 만드는 데 도움이 될 수 있어요.
컨테이너가 구성된 허용치보다 더 많이 생존성 프로브에 실패하면, kubelet은 그 컨테이너를 재시작합니다. 생존성 프로브는 준비성 프로브가 성공하기를 기다리지 않습니다. 생존성 프로브를 실행하기 전에 기다리고 싶다면 initialDelaySeconds를 정의하거나 시작 프로브를 사용하면 됩니다.
주의: 생존성 프로브는 애플리케이션 실패에서 회복하는 강력한 방법이 될 수 있지만 주의해서 사용해야 합니다. 생존성 프로브는 교착 상태 같은 회복 불가능한 애플리케이션 실패를 진정으로 나타내도록 신중하게 구성해야 합니다. 생존성 프로브의 잘못된 구현은 연쇄 실패(cascading failures)로 이어질 수 있습니다. 이는 높은 부하에서 컨테이너 재시작, 애플리케이션이 덜 확장 가능해지면서 발생하는 실패한 클라이언트 요청, 일부 실패한 Pod로 인한 나머지 Pod의 증가된 작업 부하를 초래합니다. 생존성과 준비성 프로브의 차이점과 언제 애플리케이션에 적용해야 하는지 이해하세요.
준비성 프로브 (Readiness probe)
준비성 프로브는 컨테이너가 트래픽을 받을 준비가 되었는지 결정합니다. 이는 네트워크 연결 설정, 파일 로드, 캐시 워밍 같은 시간이 걸리는 초기 작업을 수행하도록 애플리케이션을 기다릴 때 유용합니다. 준비성 프로브는 컨테이너 수명 주기 후반, 예를 들어 일시적인 결함이나 과부하에서 회복할 때에도 유용할 수 있습니다.
준비성 프로브가 실패 상태를 반환하면 EndpointSlice 컨트롤러는 Pod와 일치하는 모든 Service의 EndpointSlices에서 Pod의 IP 주소를 제거합니다.
준비성 프로브는 컨테이너의 전체 수명 주기 동안 실행됩니다.
참고: Pod가 삭제될 때 요청을 드레인할 수 있기를 원한다면 준비성 프로브가 반드시 필요한 것은 아닙니다. Pod가 삭제되면 EndpointSlice의 해당 엔드포인트가 자신의 조건을 업데이트합니다. 엔드포인트의 ready 조건이
false로 설정되므로 로드 밸런서가 일반 트래픽에 Pod를 사용하지 않습니다. kubelet이 Pod 삭제를 처리하는 방법에 대한 자세한 내용은 Pod 종료를 참고하세요.
각 프로브를 언제 사용해야 하는가 (When to use each probe)
시작 프로브는 언제 사용해야 하는가? (When should you use a startup probe?)
시작 프로브는 서비스를 받기까지 오래 걸리는 컨테이너를 가진 Pod에 유용합니다. 긴 생존성 간격을 설정하는 대신, 컨테이너가 시작될 때 프로빙하기 위한 별도의 구성을 설정해 생존성 간격이 허용하는 것보다 더 긴 시간을 허용할 수 있어요.
컨테이너가 보통 \( initialDelaySeconds + failureThreshold \times periodSeconds \)보다 더 오래 걸려 시작된다면, 생존성 프로브와 같은 엔드포인트를 확인하는 시작 프로브를 지정해야 합니다. periodSeconds의 기본값은 10초입니다. 그런 다음 생존성 프로브의 기본값을 바꾸지 않고 컨테이너가 시작될 수 있도록 failureThreshold를 충분히 높게 설정해야 합니다. 이는 교착 상태로부터 보호하는 데 도움이 됩니다.
생존성 프로브는 언제 사용해야 하는가? (When should you use a liveness probe?)
컨테이너의 프로세스가 문제를 만나거나 비정상이 될 때 스스로 충돌할 수 있다면 생존성 프로브가 반드시 필요하지는 않습니다. kubelet이 Pod의 restartPolicy에 따라 올바른 동작을 자동으로 수행할 것입니다.
프로브가 실패하면 컨테이너가 죽고 재시작되길 원한다면, 생존성 프로브를 지정하고 restartPolicy를 Always 또는 OnFailure로 지정하세요.
생존성 프로브의 일반적인 패턴은 준비성 프로브와 같은 저비용 HTTP 엔드포인트를 사용하되 더 높은 failureThreshold를 사용하는 것입니다. 이는 Pod가 강제로 죽기 전에 일정 기간 동안 준비되지 않음(not-ready)으로 관찰되도록 보장합니다.
준비성 프로브는 언제 사용해야 하는가? (When should you use a readiness probe?)
프로브가 성공할 때만 Pod에 트래픽을 보내기 시작하려면 준비성 프로브를 지정하세요. 준비성 프로브는 생존성 프로브와 같을 수 있지만, 스펙에 준비성 프로브가 존재한다는 것은 Pod가 트래픽을 받지 않고 시작하며, 프로브가 성공하기 시작한 후에만 트래픽을 받기 시작한다는 뜻입니다.
또한 준비성 프로브를 사용해 생존성 프로브와 다른 준비성 전용 엔드포인트를 확인함으로써 컨테이너가 유지보수를 위해 스스로 내려가게 할 수 있어요.
앱이 백엔드 서비스에 대한 엄격한 의존성을 가질 때는 생존성과 준비성 프로브를 모두 구현할 수 있습니다. 생존성 프로브는 앱 자체가 정상일 때 통과하고, 준비성 프로브는 각 필수 백엔드 서비스가 사용 가능한지 추가로 확인합니다. 이는 오류 메시지로만 응답할 수 있는 Pod로 트래픽이 향하는 것을 피하는 데 도움이 됩니다.
시작 중에 큰 데이터, 구성 파일 또는 마이그레이션 로드 작업이 필요한 컨테이너의 경우 시작 프로브 사용을 고려하세요. 그러나 실패한 앱과 여전히 시작 데이터를 처리 중인 앱의 차이를 감지하고 싶다면 준비성 프로브를 선호할 수 있습니다.
검사 메커니즘 (Check mechanisms)
프로브를 사용해 컨테이너를 확인하는 방법은 네 가지가 있습니다. 각 프로브는 이 네 가지 메커니즘 중 정확히 하나를 정의해야 합니다.
주의: 다른 메커니즘과 달리 exec 프로브의 구현은 실행될 때마다 여러 프로세스의 생성/포크를 수반합니다. 결과적으로 pod 밀도가 높고
initialDelaySeconds,periodSeconds간격이 낮은 클러스터에서 어떤 프로브든 exec 메커니즘으로 구성하면 노드의 CPU 사용에 오버헤드를 도입할 수 있습니다. 그런 시나리오에서는 오버헤드를 피하기 위해 대체 프로브 메커니즘 사용을 고려하세요.
프로브 결과 (Probe results)
kubelet은 각 프로브 실행의 결과를 평가하고 그에 따라 조치를 취합니다. 각 프로브는 세 가지 결과 중 하나를 가집니다.
- Success: 컨테이너가 진단을 통과했습니다.
- Failure: 컨테이너가 진단에 실패했습니다.
- Unknown: 진단 자체가 실패했습니다(예: 명령 실행 불가, 포트 접속 불가). 이 경우 kubelet은 3번의 재시도를 수행합니다.
컨테이너가 특정 프로브를 제공하지 않으면 kubelet은 항상 결과를 Success로 간주합니다. 특히 준비성 프로브의 경우 초기 지연(initial delay) 전에는 결과가 Failure로 간주됩니다.
구성 필드 (Configuration fields)
프로브에는 시작, 생존성, 준비성 검사의 동작을 더 정밀하게 제어하는 데 사용할 수 있는 여러 필드가 있습니다. 예를 들어:
apiVersion: v1
kind: Pod
metadata:
name: probe-example
spec:
containers:
- name: app
image: registry.k8s.io/e2e-test-images/agnhost:2.40
ports:
- containerPort: 8080
startupProbe:
httpGet:
path: /healthz
port: 8080
failureThreshold: 30
periodSeconds: 10
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
readinessProbe:
httpGet:
path: /ready
port: 8080
periodSeconds: 5
주의: 준비성 프로브의 잘못된 구현은 컨테이너의 프로세스 수가 계속 증가하고, 이를 확인하지 않으면 리소스 기아(starvation)를 초래할 수 있습니다.
프로브 수준 terminationGracePeriodSeconds (Probe-level terminationGracePeriodSeconds)
1.25 이상에서 사용자는 프로브 스펙의 일부로 프로브 수준의 terminationGracePeriodSeconds를 지정할 수 있습니다. Pod 수준과 프로브 수준의 terminationGracePeriodSeconds가 모두 설정되면 kubelet은 프로브 수준 값을 사용합니다.
terminationGracePeriodSeconds를 설정할 때 다음 사항을 유의하세요.
- kubelet은 Pod에 프로브 수준
terminationGracePeriodSeconds필드가 있으면 항상 그것을 존중합니다. terminationGracePeriodSeconds필드가 설정된 기존 Pod가 있고 더 이상 프로브별 종료 유예 기간을 사용하고 싶지 않다면, 해당 기존 Pod를 삭제해야 합니다.
예를 들어:
spec:
terminationGracePeriodSeconds: 3600 # pod-level
containers:
- name: test
image: ...
ports:
- name: liveness-port
containerPort: 8080
livenessProbe:
httpGet:
path: /healthz
port: liveness-port
failureThreshold: 1
periodSeconds: 60
# Override pod-level terminationGracePeriodSeconds
terminationGracePeriodSeconds: 60
프로브 수준 terminationGracePeriodSeconds는 준비성 프로브에는 설정할 수 없습니다. API 서버가 이를 거부합니다.
프로브 메커니즘 상세 (Probe mechanism details)
HTTP 프로브 (HTTP probes)
HTTP 프로브에는 httpGet에 설정할 수 있는 추가 필드가 있습니다.
host: 연결할 호스트 이름. 기본값은 Pod IP입니다. 아마도 대신httpHeaders에 "Host"를 설정하고 싶을 것입니다.scheme: 호스트에 연결하는 데 사용할 스킴(HTTP 또는 HTTPS). 기본값은 "HTTP"입니다.path: HTTP 서버에서 접근할 경로. 기본값은 "/"입니다.httpHeaders: 요청에 설정할 사용자 정의 헤더. HTTP는 반복 헤더를 허용합니다.port: 컨테이너에서 접근할 포트의 이름 또는 번호. 번호는 1에서 65535 범위여야 합니다.protocol: 프로브 요청에 사용할 프로토콜. 기본값은HTTP1입니다.HTTP2로 설정하면 HTTP/2 클리어텍스트(h2c)로 프로브합니다.H2CContainerProbe기능 게이트를 활성화해야 합니다.
HTTP 프로브의 경우 kubelet은 검사를 수행하기 위해 지정된 포트와 경로로 HTTP 요청을 보냅니다. kubelet은 httpGet의 선택적 host 필드로 주소가 재정의되지 않는 한, 프로브를 Pod의 IP 주소로 보냅니다. scheme 필드가 HTTPS로 설정되면 kubelet은 인증서 검증을 건너뛰고 HTTPS 요청을 보냅니다. 대부분의 시나리오에서는 host 필드를 설정하고 싶지 않을 것입니다. 설정하는 시나리오가 하나 있습니다. 컨테이너가 127.0.0.1에서 수신하고 Pod의 hostNetwork 필드가 true인 경우입니다. 그러면 httpGet 아래의 host를 127.0.0.1로 설정해야 합니다. Pod가 가상 호스트에 의존한다면(더 일반적인 경우일 것입니다) host를 사용하지 말고 httpHeaders에서 Host 헤더를 설정해야 합니다.
HTTP 프로브의 경우 kubelet은 필수 Host 헤더 외에 두 개의 요청 헤더를 보냅니다.
User-Agent, 기본값은kube-probe/1.37입니다(1.37은 kubelet 버전).Accept, 기본값은*/*입니다.
프로브에 대해 httpHeaders를 정의해 이 헤더들을 재정의할 수 있습니다. 예를 들어:
livenessProbe:
httpGet:
httpHeaders:
- name: Accept
value: application/json
startupProbe:
httpGet:
httpHeaders:
- name: User-Agent
value: MyUserAgent
이 두 헤더를 빈 값으로 정의해 제거할 수도 있습니다.
livenessProbe:
httpGet:
httpHeaders:
- name: Accept
value: ""
startupProbe:
httpGet:
httpHeaders:
- name: User-Agent
value: ""
이 기능을 사용하려면 클러스터의 모든 관련 컴포넌트에서 H2CContainerProbe 기능 게이트를 활성화해야 합니다.
자세한 내용은 기능 게이트 활성화/비활성화 (Enable Or Disable Feature Gates)를 참고하세요.
protocol 필드를 HTTP2로 설정해 HTTP 프로브가 HTTP/2 클리어텍스트(h2c)를 사용하도록 구성할 수 있습니다. protocol이 HTTP2로 설정되면 kubelet은 HTTP/1.1 대신 h2c(평문 TCP 위의 HTTP/2)를 사용합니다. 기본 프로토콜은 HTTP1입니다. protocol: HTTP2를 설정하려면 scheme: HTTP(기본값)가 필요합니다. API 서버는 protocol: HTTP2와 scheme: HTTPS의 조합을 거부합니다. 자세한 내용은 HTTP 프로브와 함께 HTTP/2 클리어텍스트(h2c) 사용을 참고하세요.
리다이렉트 처리 (Redirect handling)
kubelet이 HTTP를 사용해 컨테이너를 프로브할 때, 리다이렉트가 같은 호스트로의 경우에만 리다이렉트를 따릅니다. 여기에는 프로브가 scheme: HTTP로 구성됐더라도 HTTP에서 HTTPS로 프로토콜을 바꾸는 리다이렉트도 포함됩니다.
리다이렉트가 다른 호스트 이름으로의 경우 kubelet은 그것을 따르지 않습니다. 대신 kubelet은 프로브를 성공으로 취급하고 ProbeWarning 이벤트를 기록합니다.
kubelet이 리다이렉트를 따르고 총 11개 이상의 리다이렉트를 받으면 프로브는 성공으로 간주되고 ProbeWarning 이벤트를 기록합니다. 예를 들어:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 29m default-scheduler Successfully assigned default/httpbin-7b8bc9cb85-bjzwn to daocloud
Normal Pulling 29m kubelet Pulling image "docker.io/kennethreitz/httpbin"
Normal Pulled 24m kubelet Successfully pulled image "docker.io/kennethreitz/httpbin" in 5m12.402735213s
Normal Created 24m kubelet Created container httpbin
Normal Started 24m kubelet Started container httpbin
Warning ProbeWarning 4m11s (x1197 over 24m) kubelet Readiness probe warning: Probe terminated redirects
주의:
httpGet프로브를 처리할 때 kubelet은 응답 본문을 10KiB 뒤에 읽기를 중단합니다. 프로브의 성공은 응답 헤더에 있는 응답 상태 코드에 의해서만 결정됩니다. 10KiB보다 큰 응답 본문을 반환하는 엔드포인트를 프로브하면 kubelet은 상태 코드에 따라 프로브를 성공으로 표시하지만, 10KiB 한도에 도달한 후 연결을 닫습니다. 이 갑작스러운 닫힘은 애플리케이션 로그에 connection reset by peer 또는 broken pipe 오류로 나타날 수 있으며, 이는 정당한 네트워크 문제와 구별하기 어려울 수 있습니다. 신뢰할 수 있는httpGet프로브를 위해 최소한의 응답 본문을 반환하는 전용 상태 확인 엔드포인트를 사용하는 것이 강력히 권장됩니다. 큰 페이로드를 가진 기존 엔드포인트를 사용해야 한다면 HEAD 요청을 수행하는 exec 프로브 사용을 고려하세요.
TCP 프로브 (TCP probes)
TCP 프로브의 경우 kubelet은 Pod가 아니라 노드에서 프로브 연결을 만듭니다. 이는 kubelet이 서비스 이름을 해석할 수 없기 때문에 host 매개변수에 서비스 이름을 사용할 수 없다는 뜻입니다.
gRPC 프로브 (gRPC probes)
애플리케이션이 gRPC Health Checking Protocol을 구현한다면, 이를 애플리케이션 시작, 생존성 또는 준비성 검사에 사용하도록 Kubernetes를 구성할 수 있습니다.
다음은 매니페스트 예시입니다.
apiVersion: v1
kind: Pod
metadata:
name: etcd-with-grpc
spec:
containers:
- name: etcd
image: registry.k8s.io/etcd:3.5.1-0
command: [ "/usr/local/bin/etcd", "--data-dir", "/var/lib/etcd", "--listen-client-urls", "http://0.0.0.0:2379", "--advertise-client-urls", "http://127.0.0.1:2379", "--log-level", "debug"]
ports:
- containerPort: 2379
livenessProbe:
grpc:
port: 2379
initialDelaySeconds: 10
gRPC 프로브를 사용하려면 port를 구성해야 합니다. 서로 다른 유형의 프로브와 서로 다른 기능의 프로브를 구분하려면 service 필드를 사용할 수 있습니다. service를 liveness 값으로 설정하고 gRPC Health Checking 엔드포인트가 service를 readiness로 설정했을 때와 다르게 이 요청에 응답하게 할 수 있습니다. 이렇게 하면 두 개의 다른 포트에서 수신하지 않고도 같은 엔드포인트를 여러 종류의 컨테이너 상태 검사에 사용할 수 있어요. 자체 사용자 지정 서비스 이름을 지정하고 프로브 유형도 지정하려면 Kubernetes 프로젝트는 그 둘을 결합한 이름을 사용할 것을 권장합니다. 예: myservice-liveness(-를 구분자로 사용).
참고: HTTP나 TCP 프로브와 달리 상태 검사 포트를 이름으로 지정할 수 없고, 사용자 지정 호스트네임을 구성할 수 없습니다.
구성 문제(예: 잘못된 포트나 서비스, 구현되지 않은 상태 확인 프로토콜)는 HTTP 및 TCP 프로브와 유사하게 프로브 실패로 간주됩니다.
이 기능을 사용하려면 클러스터의 모든 관련 컴포넌트에서 GRPCContainerProbeTLS 기능 게이트를 활성화해야 합니다.
자세한 내용은 기능 게이트 활성화/비활성화를 참고하세요.
mode 필드를 TLS로 설정해 gRPC 프로브가 TLS로 연결하도록 구성할 수 있습니다. mode가 TLS로 설정되면 kubelet은 InsecureSkipVerify와 함께 TLS를 사용합니다(서버 인증서를 검증하지 않음). 기본 모드는 Plaintext입니다. 자세한 내용은 gRPC 프로브와 함께 TLS 사용을 참고하세요.
다음 단계 (What's next)
- Liveness, Readiness and Startup Probes 구성하는 방법 알아보기
- 프로브 관련 필드의 전체 명세는 API 참조: Pod, Container, Probe 참조