ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Kubernetes] ReadinessProbe 알아보기
    Kubernetes 2023. 6. 16. 12:29
    728x90
    반응형

     

     

    - 목차

     

    들어가며.

    이번 글에서는 쿠버네티스의 ReadinessProbe 설정이 대해서 알아보려고 합니다.

    쿠버네티스는 3가지 Probe 설정을 취합니다.

    첫번째 Probe 는 livenessProbe 이고, 두번째 Probe 는 이번 글에서 알아볼 주제인 readinessProbe 입니다.

    그리고 마지막으로 startupProbe 가 존재합니다.

     

    Probe 는 Pod 의 컨테이너의 상태를 체크할 수 있는 기능입니다.

    kubelet 은 주기적으로 Pod 의 컨테이너의 상태 체크를 수행하게 되는데요.

    이름 그대로 livenessProbe 는 컨테이너가 정상적으로 살아있는지를 확인하는 절차입니다.

    만약 livenessProbe 를 통한 상태체크의 결과가 정상적이지 않다면 해당 컨테이너는 재시작되게 됩니다.

    그리고 readinessProbe 는 컨테이너가 외부에서 발생하는 요청을 정상적으로 처리할 준비가 되었는지를 판단합니다.

    readinessProbe 가 정상적으로 동작한다면 이 시점부터 외부 네트워크 트래픽이 해당 Pod 의 컨테이너로 전달됩니다.

     

     

    HTTP Api 서버 준비하기.

    ReadinessProbe 를 실습하기 위해서 먼저 간단한 API 서버를 만들어보겠습니다.

    3개의 파일이 필요합니다.

    파일의 구성은 아래와 같구요. 모두 같은 Path 에 위치합니다.

    ├── Dockerfile
    ├── fast_api_main.py
    ├── requirements.txt

     

    requirements.txt

    annotated-types==0.6.0
    anyio==4.3.0
    click==8.1.7
    exceptiongroup==1.2.0
    fastapi==0.110.1
    h11==0.14.0
    idna==3.7
    pydantic==2.6.4
    pydantic_core==2.16.3
    sniffio==1.3.1
    starlette==0.37.2
    typing_extensions==4.11.0
    uvicorn==0.29.0

     

    fast_api_main.py

    from fastapi import FastAPI
    
    app = FastAPI()
    
    @app.get("/health")
    def health_check():
        return {"message": ""}

     

    Dockerfile.

    FROM python:3.9
    WORKDIR /code/app
    COPY ./requirements.txt /code/requirements.txt
    RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
    COPY . /code/app
    CMD ["uvicorn", "fast_api_main:app", "--host", "0.0.0.0", "--port", "8000"]

     

    도커 이미지 만들기.

    아래의 docker build 명령어를 통해서 도커 이미지를 생성합니다.

    docker build -t fastapi:0.0.1 .
    REPOSITORY  TAG    IMAGE ID       CREATED         SIZE
    fastapi     0.0.1  d1ff227f8298   5 minutes ago   1.02GB

     

     

    KinD 로 쿠버네티스 실행하기.

    아래의 링크는 KinD 로 로컬 환경에서 쿠버네티스를 실행할 수 있는 가이드를 담고 있습니다.

    https://westlife0615.tistory.com/407

     

    KinD 알아보기.

    - 목차 소개. KinD 는 "카인드" 라고 발음되며, 로컬 머신에서 쿠버네티스를 간편하게 실행할 수 있는 도구입니다. KinD 는 Kubernetes in Docker 의 약자이구요. Docker 를 활용하여 쿠버네티스 환경을 구성

    westlife0615.tistory.com

     

    FastAPI 어플리케이션에 대한 도커 이미지를 생성하였기 때문에 쿠버네티스를 실행시킵니다.

     

    FastAPI 도커 이미지를 쿠버네티스에 추가하기.

    저희는 생성한 이미지를 Docker Hub 와 같은 레지스트리에 등록하지 않을 예정입니다.

    그래서 아래와 같은 명령어를 통해서 KinD 로컬 쿠버네티스 내부로 이미지를 등록합니다.

    kind load docker-image fastapi:0.0.1 --name test-cluster
    Image: "fastapi:0.0.1" with ID "sha256:d1ff227f8298d61ce2379f7b67f24da98ad8a1136a3585d5385f2c144e12e1b9" not yet present on node "test-cluster-control-plane", loading...

     

     

    Pod 와 Service 생성하기.

     

     

    Pod 와 Service 를 위한 yaml 파일을 생성합니다.

    아래의 /tmp/fastapi.yaml 파일은 하나의 Static Pod 와 Service 를 생성하는 내용을 담습니다.

    그리고 위에서 생성한 Docker Image 를 기반으로 합니다.

    cat <<EOF> /tmp/fastapi.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: fastapi
      namespace: default
      labels:
        app: fastapi
    spec:
      containers:
      - name: fastapi-container
        image: fastapi:0.0.1
        imagePullPolicy: Never
        ports:
        - containerPort: 8000
        readinessProbe:		
          httpGet:
            path: /health
            port: 8000
          initialDelaySeconds: 3
          periodSeconds: 3
      restartPolicy: Always
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: fastapi-service
      namespace: default
    spec:
      selector:
        app: fastapi
      ports:
        - protocol: TCP
          port: 8000
          targetPort: 8000
    EOF

     

    < Pod 와 Service 생성 Kubectl 명령어 >

    kubectl apply -f /tmp/fastapi.yaml

     

    ReadinessProbe 란 ?

    위에서 간단히 설정하였지만, readinessProbe 를 통해서 Pod 의 컨테이너를 외부의 네트워크 트래픽을 전달받을 수 있습니다.

    즉, ReadinessProbe 에 의해서 컨테이너의 준비 상태가 정상임이 파악되어야 비로소 클라이언트의 요청을 처리할 수 있게 됩니다.

    이를 Pod 의 상태 관점에서 본다면 Running 상태에서 Ready 상태로 변경되는 기준을 제공합니다.

    만약 ReadinessProbe 에 의해서 준비 단계에 대한 검증을 패스하지 못한다면,

    아래의 Pod 의 상태가 아래처럼 READY 가 1/1 로 출력되지 않습니다.

    0/1 과 같이 실행 중인 컨테이너가 없음이 표시되죠.

    kubectl -n default get pod fastapi
    NAME      READY   STATUS    RESTARTS   AGE
    fastapi   1/1     Running   0          3m22s

     

     

    그리고 Ready 상태가 되어야지만 Service 와 Endpoint 가 연결됩니다.

    Service 는 외부의 네트워크 트래픽을 Pod 에게 전달하는 기능을 수행합니다.

    그리고 Endpoint 가 Pod 와 Pod 의 IP 를 Service 에게 제공하는 매개체 역할을 수행하죠.

    Pod 가 Ready 상태가 되지 못한다면 Service 와 Endpoint 의 연결이 수립되지 않습니다.

     

    Service 와 Endpoint.

    Kubernetes 의 Service 에 대한 자세한 설명은 아래의 링크로 대체하겠습니다.

    https://westlife0615.tistory.com/212

     

    [Kubernetes] Service 이해하기

    - 목차 들어가며. Kubernetes 의 Service 는 Pod 들을 네트워크적으로 묶어줍니다. 네트워크적으로 묶는다는 의미는 하나의 단일 IP 를 통해서 Pod 에게 트래픽을 전송할 수 있는 의미입니다. 이를 그림

    westlife0615.tistory.com

     

    Ready 상태의 Pod 와 Service & Endpoint.

    간단히 Ready 상태의 Pod 와 Service 가 어떻게 연결되어 있는지 살펴보겠습니다.

    Pod 의 상태는 아래와 같습니다.

    1개의 Container 가 정상적으로 동작 중이구요. Pod 의 상태 또한 Running 입니다.

    kubectl get pod fastapi
    NAME      READY   STATUS    RESTARTS   AGE
    fastapi   1/1     Running   0          8m26s

     

    그리고 Pod 의 IP 는 10.244.0.9 로 설정되어 있죠.

    kubectl get pod fastapi -o=jsonpath='{.status.podIP}'

     

    10.244.0.9%

     

     

    아래는 Service 의 상태입니다.

    눈여겨 보아야할 점은 Endpoints 가 Pod 의 IP 인 10.244.0.9 로 설정되어 있다는 점입니다.

    kubectl describe service fastapi-service
    Name:              fastapi-service
    Namespace:         default
    Labels:            <none>
    Annotations:       <none>
    Selector:          app=fastapi
    Type:              ClusterIP
    IP Family Policy:  SingleStack
    IP Families:       IPv4
    IP:                10.96.241.183
    IPs:               10.96.241.183
    Port:              <unset>  8000/TCP
    TargetPort:        8000/TCP
    Endpoints:         10.244.0.9:8000
    Session Affinity:  None
    Events:            <none>

     

     

    이렇게 Ready 상태의 Pod 는 Service 와 Endpoint 에 의해서 외부 트래픽을 수용할 수 있게 됩니다.

     

    Not-Ready 상태의 Pod 와 Service & Endpoint.

    Not-Ready 상태를 구현하기 위해서 저는 Pod 의 ReadinessProbe 를 수정하였습니다.

    간단히 readinessProbe 의 httpGet 의 path 를 존재하지 않는 API Path 로 설정하였습니다.

    cat <<EOF> /tmp/fastapi.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: fastapi
      namespace: default
      labels:
        app: fastapi
    spec:
      containers:
      - name: fastapi-container
        image: fastapi:0.0.1
        imagePullPolicy: Never
        ports:
        - containerPort: 8000
        readinessProbe:		
          httpGet:
            path: /health-unknown
            port: 8000
          initialDelaySeconds: 3
          periodSeconds: 3
      restartPolicy: Always
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: fastapi-service
      namespace: default
    spec:
      selector:
        app: fastapi
      ports:
        - protocol: TCP
          port: 8000
          targetPort: 8000
    EOF
    kubectl apply -f /tmp/fastapi.yaml

     

    결과는 아래와 같습니다.

    먼저 Pod 는 Ready 상태가 되지 못합니다.

    kubectl get pod fastapi
    NAME      READY   STATUS    RESTARTS   AGE
    fastapi   0/1     Running   0          25s

     

    그리고 Service 또한 Endpoint 가 연결되지 않습니다.

    kubectl describe service fastapi-service
    Name:              fastapi-service
    Namespace:         default
    Labels:            <none>
    Annotations:       <none>
    Selector:          app=fastapi
    Type:              ClusterIP
    IP Family Policy:  SingleStack
    IP Families:       IPv4
    IP:                10.96.241.183
    IPs:               10.96.241.183
    Port:              <unset>  8000/TCP
    TargetPort:        8000/TCP
    Endpoints:         
    Session Affinity:  None
    Events:            <none>

     

     

    ReadinessProbe 설정.

    어떻게 ReadinessProbe 를 설정할 수 있는지에 대해서 알아보겠습니다.

    Probe 의 적용 대상은 Pod 이며, 구체적으로 Pod 내부의 Container 를 그 대상으로 삼습니다.

    Running 또는 Ready 상태가 아닌 Container 의 Health Check 와 조치를 취할 수 있습니다.

    httpGet.

    httpGet 은 Container 의 어플리케이션의 Probe Health Check 를 수행할 수 있도록 설정할 수 있는 방법 중 하나입니다.

    http 프로토콜을 기반으로 Probe 를 적용하는 만큼 웹 애플리케이션 서버에게 이러한 Probe 방식이 적합합니다.

    특정 Path 로 Health Check API 를 만들고 이를 외부로 노출시켜 사용합니다.

     

    제가 실습을 위해서 사용한 FastAPI 예시에서 /health 라는 이름으로 API 를 만들어 사용하였고,

    항상 200 StatusCode 를 리턴하도록 설계되어 있습니다.

     

    initialDelaySeconds.

    kubelet 은 Pod 의 Probe Health Check 를 수행합니다.

    initialDelaySeconds 는 이름에서 유추할 수 있듯이, 최초 Probe Health Check 를 수행하기 전 대기하는 시간입니다.

    아래 로그는 FastAPI 의 로그입니다.

    저는 initialDelaySeconds 를 10초로 설정해두었는데요.

    아래의 로그처럼 최초 서버 시작 로그 이후에 10초 정도가 지난 후에 최초의 /health API 가 호출됨을 확인할 수 있습니다.

    2023-01-12T03:18:02+09:00 INFO:     Started server process [1]
    2023-01-12T03:18:02+09:00 INFO:     Waiting for application startup.
    2023-01-12T03:18:02+09:00 INFO:     Application startup complete.
    2023-01-12T03:18:02+09:00 INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
    2023-01-12T03:18:13+09:00 INFO:     10.244.0.1:36282 - "GET /health HTTP/1.1" 200 OK
    2023-01-12T03:18:16+09:00 INFO:     10.244.0.1:36288 - "GET /health HTTP/1.1" 200 OK
    2023-01-12T03:18:19+09:00 INFO:     10.244.0.1:36304 - "GET /health HTTP/1.1" 200 OK
    2023-01-12T03:18:22+09:00 INFO:     10.244.0.1:34438 - "GET /health HTTP/1.1" 200 OK
    2023-01-12T03:18:25+09:00 INFO:     10.244.0.1:34454 - "GET /health HTTP/1.1" 200 OK

     

    periodSeconds.

    periodSeconds 는 주기적으로 Health Check 를 수행하는 주기입니다.

    아래는 FastAPI 의 로그인데요.

    저는 periodSeconds 를 3초로 설정하였고, 아래와 같이 3초 주기로 /health API 가 호출됨을 확인할 수 있죠.

    2023-01-12T03:54:32+09:00 INFO:     10.244.0.1:55196 - "GET /health HTTP/1.1" 200 OK
    2023-01-12T03:54:35+09:00 INFO:     10.244.0.1:55206 - "GET /health HTTP/1.1" 200 OK
    2023-01-12T03:54:38+09:00 INFO:     10.244.0.1:43406 - "GET /health HTTP/1.1" 200 OK
    2023-01-12T03:54:41+09:00 INFO:     10.244.0.1:43422 - "GET /health HTTP/1.1" 200 OK
    2023-01-12T03:54:44+09:00 INFO:     10.244.0.1:43432 - "GET /health HTTP/1.1" 200 OK
    2023-01-12T03:54:47+09:00 INFO:     10.244.0.1:43442 - "GET /health HTTP/1.1" 200 OK
    2023-01-12T03:54:50+09:00 INFO:     10.244.0.1:50598 - "GET /health HTTP/1.1" 200 OK
    2023-01-12T03:54:53+09:00 INFO:     10.244.0.1:50612 - "GET /health HTTP/1.1" 200 OK
    2023-01-12T03:54:56+09:00 INFO:     10.244.0.1:50628 - "GET /health HTTP/1.1" 200 OK
    2023-01-12T03:54:59+09:00 INFO:     10.244.0.1:56818 - "GET /health HTTP/1.1" 200 OK
    2023-01-12T03:55:02+09:00 INFO:     10.244.0.1:56826 - "GET /health HTTP/1.1" 200 OK
    2023-01-12T03:55:05+09:00 INFO:     10.244.0.1:56838 - "GET /health HTTP/1.1" 200 OK
    2023-01-12T03:55:08+09:00 INFO:     10.244.0.1:42786 - "GET /health HTTP/1.1" 200 OK
    2023-01-12T03:55:11+09:00 INFO:     10.244.0.1:42798 - "GET /health HTTP/1.1" 200 OK
    2023-01-12T03:55:14+09:00 INFO:     10.244.0.1:42810 - "GET /health HTTP/1.1" 200 OK
    2023-01-12T03:55:17+09:00 INFO:     10.244.0.1:42822 - "GET /health HTTP/1.1" 200 OK
    2023-01-12T03:55:20+09:00 INFO:     10.244.0.1:42514 - "GET /health HTTP/1.1" 200 OK

     

     

    반응형

    'Kubernetes' 카테고리의 다른 글

    Kubernetes Ephemeral Volume  (0) 2023.08.09
    [Kubernetes] Service 이해하기  (0) 2023.08.01
    Kubernetes Pod 이해하기  (0) 2023.07.26
    Kubernetes Event 이해하기  (0) 2023.06.16
    [Kubernetes] Metrics Server 알아보기  (0) 2023.05.09
Designed by Tistory.