파드와 그 엔드포인트의 종료 동작 탐구하기

파드와 그 엔드포인트의 종료 동작 탐구하기 (Explore Termination Behavior for Pods And Their Endpoints)

애플리케이션을 '서비스로 애플리케이션 연결하기'에 설명된 것 같은 단계로 Service와 연결했다면, 네트워크에 노출된, 지속적으로 실행되는 복제 애플리케이션이 있어요. 이 튜토리얼은 파드의 종료 흐름을 살펴보고 정상적인 연결 드레이닝(graceful connection draining)을 구현하는 방법을 탐구하는 데 도움을 줘요.

출처: 문서

본문

파드와 그 엔드포인트의 종료 프로세스

업그레이드하거나 스케일 다운하기 위해 파드를 종료해야 하는 경우가 자주 있어요. 애플리케이션 가용성을 개선하려면 적절한 활성 연결 드레이닝(active connections draining)을 구현하는 것이 중요할 수 있어요.

이 튜토리얼은 간단한 nginx 웹 서버를 사용해 그 개념을 시연하며, 해당 엔드포인트 상태 및 제거와 관련된 파드 종료의 흐름을 설명해요.

엔드포인트 종료가 있는 예시 흐름

다음은 '파드 종료' 문서에 설명된 예시 흐름이에요.

단일 nginx 레플리카(데모 목적으로만)를 포함하는 Deployment와 Service가 있다고 해 보죠.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      terminationGracePeriodSeconds: 120 # 아주 긴 유예 기간
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
        lifecycle:
          preStop:
            # 실제 종료는 terminationGracePeriodSeconds 까지의 어떤 시간이든 걸릴 수 있습니다.
            # 이 예시에서는 최소한 terminationGracePeriodSeconds 기간만큼 대기하다가,
            # 120초에 컨테이너는 강제 종료됩니다.
            # 참고: 이 모든 시간 동안 nginx는 요청을 계속 처리합니다.
            sleep: 180
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80

이제 위 파일들을 사용해 Deployment 파드와 Service를 만들어요.

kubectl apply -f pod-with-graceful-termination.yaml

kubectl apply -f explore-graceful-termination-nginx.yaml

파드와 Service가 실행 중이면, 관련 EndpointSlice의 이름을 얻을 수 있어요.

kubectl get endpointslice

출력은 다음과 비슷해요.

NAME                  ADDRESSTYPE   PORTS   ENDPOINTS                 AGE
nginx-service-6tjbr   IPv4          80      10.12.1.199,10.12.1.201   22m

그 상태를 보고 엔드포인트 하나가 등록되어 있는지 확인할 수 있어요.

kubectl get endpointslices -o json -l kubernetes.io/service-name=nginx-service

출력은 다음과 비슷해요.

{
    "addressType": "IPv4",
    "apiVersion": "discovery.k8s.io/v1",
    "endpoints": [
        {
            "addresses": [
                "10.12.1.201"
            ],
            "conditions": {
                "ready": true,
                "serving": true,
                "terminating": false

이제 파드를 종료하고, 파드가 정상 종료 기간 구성(graceful termination period configuration)을 존중하며 종료되는지 확인해요.

kubectl delete pod nginx-deployment-7768647bf9-b4b9s

모든 파드:

kubectl get pods

출력은 다음과 비슷해요.

NAME                                READY   STATUS        RESTARTS      AGE
nginx-deployment-7768647bf9-b4b9s   1/1     Terminating   0             4m1s
nginx-deployment-7768647bf9-rkxlw   1/1     Running       0             8s

새 파드가 스케줄링되었음을 볼 수 있어요.

새 파드에 대한 새 엔드포인트가 생성되는 동안, 이전 엔드포인트는 종료(terminating) 상태로 계속 존재해요.

kubectl get endpointslice -o json nginx-service-6tjbr

출력은 다음과 비슷해요.

{
    "addressType": "IPv4",
    "apiVersion": "discovery.k8s.io/v1",
    "endpoints": [
        {
            "addresses": [
                "10.12.1.201"
            ],
            "conditions": {
                "ready": false,
                "serving": true,
                "terminating": true
            },
            "nodeName": "gke-main-default-pool-dca1511c-d17b",
            "targetRef": {
                "kind": "Pod",
                "name": "nginx-deployment-7768647bf9-b4b9s",
                "namespace": "default",
                "uid": "66fa831c-7eb2-407f-bd2c-f96dfe841478"
            },
            "zone": "us-central1-c"
        },
        {
            "addresses": [
                "10.12.1.202"
            ],
            "conditions": {
                "ready": true,
                "serving": true,
                "terminating": false
            },
            "nodeName": "gke-main-default-pool-dca1511c-d17b",
            "targetRef": {
                "kind": "Pod",
                "name": "nginx-deployment-7768647bf9-rkxlw",
                "namespace": "default",
                "uid": "722b1cbe-dcd7-4ed4-8928-4a4d0e2bbe35"
            },
            "zone": "us-central1-c"

이를 통해 애플리케이션은 종료 중에 자신의 상태를 전달할 수 있고, 클라이언트(로드 밸런서 같은)는 연결 드레이닝 기능을 구현할 수 있어요. 이 클라이언트들은 종료 중인 엔드포인트를 감지하고 그에 대한 특수 로직을 구현할 수 있어요.

쿠버네티스에서 종료 중인 엔드포인트는 항상 ready 상태가 false로 설정돼 있어요. 이는 역호환성을 위해 필요한 일이에요. 그래서 기존 로드 밸런서가 정규 트래픽에 그것을 사용하지 않게 하기 위해서요. 종료 중인 파드에 트래픽 드레이닝이 필요하다면, 실제 준비 상태는 serving 조건으로 확인할 수 있어요.

파드가 삭제되면 이전 엔드포인트도 삭제돼요.

더 알아보기 (Learn more)