반응형

목차

  1. 쿠버네티스의 장점
  2. 라이브니스 프로브란
  3. HTTP 기반 라이브니스 프로브
  4. 이외의 속성 설정
  5. 효율적으로 프로브 생성하기

쿠버네티스의 장점

쿠버네티스를 사용하면 얻을 수 있는 주요 이점은 쿠버네티스에 컨테이너 목록을 제공해 해당 컨테이너를 클러스터 어딘가에서 계속 실행되도록 할 수 있다는 것입니다.

 

파드 리소스를 생성하고 쿠버네티스가 이 파드를 실행할 워커 노드를 지정하며 해당 노드에서 파드의 컨테이너가 싱행되도록 함으로써 이 작업을 수행합니다. 그러나 그 컨테이너 중 하나 또는 파드 안에 있는 모든 컨테이너가 죽으면 어떻게 될까요?

 

파드가 노드에 스케줄링되는 즉시, 해당 노드의  Kubelet은 파드의 컨테이너를 실행하고 파드가 존재하는 한 컨테이너가 계속 실행되도록 할 것입니다. 컨테이너의 주 프로세스에 크래시(Crash)가 발생했다면 kubelet이 컨테이너를 다시 시작합니다.

 

만약 여러분의 애플리케이션에 버그가 있어 가끔씩 크래시가 발생하는 경우에는 쿠버네티스가 애플리케이션을 자동으로 다시 시작하므로, 애플리케이션에서 특별한 작업을 하지 않더라도 쿠버네티스에서 애플리케이션을 실행하는 것만으로도 자동으로 치유할 수 있는 능력이 주어집니다.

 

그러나 때때로 애플리케이션은 프로세스의 크래시 없이도 작동이 중단되는 경우가 있습니다. 일례로 자바 애플리케이션이 메모리 누수가 있어서 OutofMemoryErrors를 발생시키기 시작하더라도 JVM 프로세스는 계속 실행될 것 입니다. 애플리케이션이 더 이상 제대로 동작하지 않는다는 신호를 쿠버네티스에 보내서, 쿠버네티스가 애플리케이션을 다시 시작하도록 록 도와준다면 좋을 것입니다.

 

크래시가 발생한 컨테이너는  자동으로 다시 시작한다고 했으므로 이러한 유형의 오류를 캐치해서 프로세스를 종료할 수도 있습니다. 하지만 이 방법이 모든 문제를 해결할 수는 없습니다.

 

예를 들어 애플리케이션이 무한 루프나 교착 상태에 빠져서 응답을 하지 않는 상황이라면 어떨까요? 이런 경우 애플리케이션이 다시 시작되도록 하려면 애플리케이션 내부의 기능에 의존하지 말고 외부에서 애플리케이션의 상태를 체크해야 합니다.

  • JVM : Java Virtual Machine

라이브니스 프로브란

쿠버네티스는 라이브니스 프로브(Liveness probe)를 통해 컨테이너가 살아 있는지 확인할 수 있습니다. 파드의 스펙(specification)에 각 컨테이너의 라이브니스 프로브를 지정할 수 있습니다. 쿠버네티스는 주기적으로 프로브를 실행하고 프로브가 실패할 경우 컨테이너를 다시 시작합니다. 이와 비슷하게 레디니스 프로브(Reainess probe)도 있는데 이는 쓰임새가 다르기 때문에 혼동하지 않도록 주의해야 합니다.

 

쿠버네티스는 다음 세가지 메커니즘을 통해 컨테이너에 프로브를 실행합니다.

  1. HTTP GET 프로브
    지정한 IP 주소, 포트, 경로에 HTTP GET 요청을 수행합니다. 프로브가 응답을 수신하고 응답 코드가 오류를 나타내지 않는 경우(즉, HTTP 응답 코드가 200~399인 경우)에 프로브가 성공했다고 간주됩니다. 서버가 오류 응답 코드를 반환하거나 전혀 응답하지 않으면 프로브가 실패한 것으로 간주돼 컨테이너를 다시 시작합니다.

  2. TCP 소켓 프로브
    컨테이너의 지정된 포트에 TCP 연결을 시도합니다.연결에 성공하면 프로브가 성공한 것이고, 그렇지 않으면 컨테이너가 다시 시작합니다.

  3. Exec 프로브
    컨테이너 내의 임의 명령을 실행하고 명령의 종료 상태 코드를 확인합니다. 상태 코드가 0이면 프로브가 성공한 것입니다. 모든 다른 코드는 실패로 간주됩니다.

HTTP 기반 라이브니스 프로브

Node.js 애플리케이션에 라이브니스 프로브를 추가하는 방법을 살펴봅시다. 웹 애플리케이션이므로 웹 서버가 요청을 처리하는지 체크하는 라이브니스 프로브를 추가하는 것이 좋을 것입니다. 그러나 이 Node.js 애플리케이션은 너무 단순해서 쉽게 실패가 발생하지 않으므로 인위적으로 실패하게 만들어야 합니다.

 

이 프로브를 사용하면 처음 다섯 번째까지는 적절히 처리하고 이후의 모든 요청은 오류를 반환합니다. 라이브니스 프로브 덕분에 이런 현상이 발생하면 컨테이너가 다시 시작돼 클라이언트의 요청을 다시 적절히 처리하게 됩니다.

 

해당 컨테이너 이미지는 감사하게도 도커 허브에 푸시했주었기 때문에 직접 이미지를 빌드할 필요는 없고 바로 테스트 해보실 수 있을 것입니다. pod를 생성하는 YAML 파일에 다음 HTTP GET 라이브니스 프로브가 포함된 새 파드를 생성합니다. 예시는 다음과 같습니다.

apiVersion: v1
kind: pod
metadata:
  name: kubia-liveness
spec:
  container:
    - image: luksa/kubia-unhealthy               <  약간의 문제가 있는 이미지 파일
      name: kubia
      livenessProbe:                                       <  HTTP GET을 수행하는 라이브니스 프로브
      httpGet:
        path: /                                                   <  HTTP 요청 자료
        port: 8080                                             <  프로브가 연결해야 하는 네트워크 포트

이 파드 디스크립터는 쿠버네티스가 주기적으로 "/" 경로와 8080포드에 HTTP GET을 요청해 컨테이너가 정상 작동되는지 확인하도록 httpGet 라이브니스 프로브를 정의합니다. 이 요청은 컨테이너가 실행되는 즉시 시작됩니다.

 

다섯 번의 요청 후에 애플리케이션은 HTTP 상태 코드 500을 반환하기 시작하고 쿠버네티스가 프로브를 실패한 것으로 간주해 컨테이너를 다시 시작합니다.

  • Node.js는 Chrome의 V8 JavaScript 엔진을 기반으로 구축된 오픈 소스 교차 플랫폼 런타임 환경으로 개발자가 JavaScript를 사용하여 서버 측 애플리케이션을 만들 수 있습니다.

이외의 속성 설정

kubectl describe는 라이브니스 프로브에 관한 추가적인 정보도 표시되는 것을 알 수 있습니다. 명시적으로 지정한 라이브니스 프로브 옵션 외에도 지연(delay), 제한 시간(timeout), 기간(period) 등과 같은 추가 속성을 볼 수도 있습니다. 다음 예시의 라이브니스 프로브 옵션에 대해 살펴보겠습니다.

kubectl describe pod kubia-liveness

이전에 작성했던 YAML 파일을 kubectl apply 명령어로 싱행한 후 위 명령어를 작성하면 출력되는 정보에서 컨테이너가 현재 실행 중이지만 오류로 인해 이전에 종료된 것을 확인할 수 있습니다. 종료 코드는 137일텐데 이는 프로세스가 외부 신호에 의해 종료되었음을 나타냅니다.

 

이 숫자는 128+n이고 n은 프로세스에 전송된 시그널 번호이고, 이 시그널로 인해 컨테이너가 종료됐음을 의미합니다. 이 예시에서는 신호를 죽이는 코드인 9이고, 이에 따라 강제 종료됐다는 것을 알 수 있습니다.

 

이외에도 initialDelaySeconds 속성을 사용해 라이브니스 프로브에 추가해 초기 지연 시간을 설정할수도 있습니다.

livenessProbe:
  httpGet:
    path: /
    port: 8080
  initialDelaySeconds: 15    <  시간의 기준은 초(s) 입니다. 즉, 첫 프로브 실행까지 15초를 대기하겠다는 뜻입니다.

초기 지연을 설정하지 않으면 프로브는 컨테이너가 시작되자마자 프로브를 시작합니다. 이 경우 대부분 애플리케이션이 요청을 받을 준비가 돼 있지 않기 때문에 프로브가 실패하게 됩니다. 실패 횟수가 실패 임곗값을 초과하면 요청을 올바르게 응답하기 전에 컨테이너가 다시작됩니다. 때문에 초기 지연을 필수적으로 설정해줘야 하는 것이죠.


효율적으로 프로브 생성하기

운영 환경에서 실행 중인 파드는 반드시 라이브니스 프로브를 정의해야 합니다. 정의하지 않으면 쿠버네티스가 애플리케이션이 살아 있는지를 알 수 있는 방법이 없습니다. 프로세스가 실행되는 한 쿠버네티스는 컨테이너가 정상적이라고 간주하게 될 것입니다. 이제 효율적으로 프로브를 생성하기 위한 예시를 알아보겠습니다.

 

  1. 라이브니스 프로브가 확인해야 하는 사항
    위에서 만든 간단한 라이브니스 프로브는 단순히 서버가 응답하는지만 검사합니다. 지나치게 단순해 보이지만, 이런 라이브니스 프로브는 엄청난 일을 합니다. 컨테이너 내에서 실행 중인 웹 서버가 HTTP 요청에 응답하지 않으면 컨테이너가 다시 시작되기 때문입니다. 라이브니스 프로브가 없는 것에 비하면 커다란 개선 사항이며, 대부분 이것으로 충분합니다.

    그러나 더 나은 라이브니스 프로브를 위해 특정 URL 경로에 요청하도록 브로브를 구성해 애플리케이션 내에서 실행 중인 모든 주요 구성 요소가 살아 있는지 또는 응답이 없는지 확인하도록 구성할 수 있습니다.

    라이브니스 프로브는 애플리케이션의 내부만 체크하고, 외부 요인의 영향을 받지 않도록 해야합니다. 예를 들어 프론트엔드 웹서버의 라이브니스 프로브는 웹서버가 백엔드 데이터베이스에 연결할 수 없을 때 실패를 반환해서는 안 됩니다. 근본적인 원인이 데이터베이스 자체에 있을 경우, 웹 서버 컨테이너를 재시작한다 하더라도 문제가 해결되지는 않습니다.

  2. 프로브 가볍게 유지하기
    라이브니스 프로브는 너무 많은 연산 리소스를 사용해서는 안 되며, 완료하는 데 너무 오래 걸리지 않아야 합니다. 기본적으로 프로브는 비교적 자주 실행되며 1초 내에 완료돼야 합니다. 너무 많은 일을 하는 프로브는 컨테이너의 속도를 상당히 느려지게 만듭니다.

    그래서 컨테이너가 사용할 수 있는 CPU 시간과 할당량을 제한하는 방법이 있는데, 이는 나중에 다뤄보도록 하겠습니다. 프로브의 CPU 사용 시간은 컨테이너의 CPU 시간 할당량으로 계산되므로, 라이브니스 프로브를 무겁게 만들면 메인 애플리케이션 프로세스에서 사용할 수 있는 CPU 시간이 줄어들게 됩니다.

  3. 프로브에 재시도 루프를 구연하지 않기
    프로브의 실패 임곗값을 설정할 수 있으며, 컨테이너가 강제 종료되려면 프로브가 여러 번 실패해야 함을 알게 되었을 것입니다. 그러나 실패 임곗값을 1로 설정하더라도, 쿠버네티스는 실패를 한 번 했다고 간주하기 전에 프로브를 여러 번 재시도 합니다. 따라서 프로브에 자체적인 재시도 루프를 구현하는 것은 헛수고 입니다.
반응형