Application 기능으로 이해하기 - Probe

appti·2024년 4월 5일
0

쿠버네티스 인강

목록 보기
5/15

서론

해당 글은 일프로 님의 인프런 강의 쿠버네티스 어나더 클래스 (지상편) - Sprint 1, 2의 내용을 정리한 글입니다.

해당 글에 사용된 내용, 사진 및 그림은 모두 강의와 강의 자료에 포함된 내용입니다.

Probe 기본 개념

예제 환경

  • 세 개의 Probe가 존재
    • startupProbe
      • periodSeconds : 10
        • 10초마다 /ready 엔드 포인트로 요청해 기동 상태 확인
      • successThreshold : 1
        • 성공 수치를 1로 설정
      • failureThreshold : 10
        • 실패 수치를 10으로 설정
    • readinessProbe
      • periodSeconds : 10
        • 10초마다 /ready 엔드 포인트로 요청해 트래픽을 전달할 수 있는 상태인지 확인
        • 성공 시 서비스 활성화, 실패 시 연결 종료
      • successThreshold : 1
        • 성공 수치를 1로 설정
      • failureThreshold : 2
        • 실패 수치를 2로 설정
    • livenessProbe
      • periodSeconds : 10
        • 10초마다 /ready 엔드 포인트로 요청해 애플리케이션이 정상 동작하는지 모니터링
        • 실패 시 애플리케이션 재시작
  • 컨테이너 애플리케이션에는 /url이라는 엔드 포인트가 존재

동작 과정

  1. 컨테이너 내 애플리케이션이 기동 중인 경우
    1.1 기동이 될 때 까지 startupProbe는 계속 실패
    1.2 failureThreadhold를 10으로 설정했으므로 10회 실패 전 응답이 있으면 성공으로 간주
    그림에서는 3회만에 성공했다고 가정
    1.3 쿠버네티스에서 성공한 startupProbe를 중단하고, readinessProbe와 livenessProbe 트리거
  2. 애플리케이션이 사라있는 동안 10초 간격으로 readinessProbe와 livenessProbe가 /ready 엔드 포인트로 요청, 200 OK 결과 반환
  3. 애플리케이션에 문제가 생겨 /ready 엔드 포인트로 요청했을 때 실패
    3-1. readinessProbe 실패로 인해 서비스 비활성화 및 외부와의 연결 종료, livenessProbe 실패로 인해 애플리케이션 재시작

의문점

  • 왜 3개의 probe가 모두 동일한 url을 호출하고 있는지?
    • 동일한 엔드 포인트로 인한 요청이 실패할 경우 3개의 probe가 모두 실패
    • probe를 하나를 사용하나 3개를 사용하나 동작에는 차이가 없는 상태
    • 각 probe의 용도를 파악하고 정확하게 사용할 필요가 있음

Application 로그를 통한 Probe 동작 분석

사전 작업

// HPA minReplica 1로 바꾸기 - Master Node
kubectl patch -n anotherclass-123 hpa api-tester-1231-default -p '{"spec":{"minReplicas":1}}'
  • 로그 식별의 편의성을 위해 minReplica를 2에서 1로 변경

실습

  • 파드 강제 삭제

  • 애플리케이션 기동 중
    • startupProbe 실패

  • 애플리케이션 기동 완료
    • startupProbe 성공
    • readinessProbe, livenessProbe 트리거
    • 아직 ConfigMap등의 초기화 작업이 끝나지 않았으므로 readinessProbe 실패
    • 애플리케이션이 기동 중이므로 livenessProbe 성공

  • 애플리케이션 초기화 작업 완료
    • readinessProbe, livenessProbe 모두 성공
  • 앞으로 애플리케이션이 기동하는 동안 10초 간격으로 헬스 체크 수행

로그 분석

  • App 초기화 단계
    • 스프링 부트의 DispatcherServlet 초기화
    • 초기화가 완료되기 전에는 startupProbe는 실패하다가 완료된 이후 성공
      • 로그의 경우 임의로 애플리케이션 내부에서 출력했기 때문에 실제로 애플리케이션이 동작을 하자마자 startupProbe가 호출되고 실패함
  • User 초기화 단계
    • 예시에서는 ConfigMap을 초기화하는 과정
    • readinessProbe는 실패, livenessProbe는 성공
  • 모든 초기화 완료 후
    • readinessProbe, livenessProbe 모두 성공
    • 10초마다 헬스 체크 수행

Application 동작 중심의 Probe 이해

  • 쿠버네티스의 요구사항에 따라 Probe 동작 이해
    • 쿠버네티스는 애플리케이션을 편리하게 관리하기 위한 도구
    • 애플리케이션 동작을 기반으로 분석

  • 애플리케이션 동작

    1. 애플리케이션 초기화
    2. User 초기화
    3. 애플리케이션 기동
    4. 애플리케이션 장애 발생
  • 자동화 요구사항

    1. 애플리케이션 초기화 수행 -> 초기화가 끝나지 않았기 때문에 API를 받을 수 없음 -> 초기화가 끝났는지 애플리케이션 상태 체크 필요
      1-1. 외부 API 접근 금지 -> 애플리케이션이 초기화되지 않았기 때문
    2. 애플리케이션 초기화 완료, User 초기화 수행 -> 초기화가 끝났기 때문에 API를 받을 수 있음 -> 애플리케이션이 살아있는지 상태 체크 필요
      2-1. 외부 API 접근 금지 -> 애플리케이션만이 초기화되었고 정상적으로 서비스를 제공하기 위한 User 초기화 작업이 수행 중이기 때문
    3. 애플리케이션 기동 -> 애플리케이션 초기화 & User 초기화 작업 모두 수행 완료 -> 애플리케이션이 살아있는지 상태 체크 필요 (L4 스위치로 외부 트래픽 허용 처리)
      3-1. 외부 API 접근 허용 -> 서비스를 정상적으로 제공하기 위한 모든 준비가 끝났기 때문
    4. 애플리케이션 장애 발생 -> 애플리케이션 재기동 필요
  • 쿠버네티스 제공 기능

    1. 애플리케이션 초기화 -> startupProbe를 통해 판단
      1-1. service와 파드는 selector로 연결을 했지만 쿠버네티스는 실제 연결을 하지 않음
    2. 애플리케이션 초기화 완료, User 초기화 수행 -> startupProbe 중단, livenessProbe, readinessProbe 트리거
      2-1. livenessProbe는 설정된 API를 계속 호출하며 정상적인 상황이라면 항상 성공하고, 실패한다면 비정상적인 상황이므로 파드 재기동
      2-2. readinessProbe는 User 초기화 완료 전까지 계속 실패 -> 성공 시 service와 파드를 연결해 외부 트래픽 접속 허용
      2-3. readinessProbe가 API 호출을 실패하면 service와 파드를 분리해 외부 트래픽 접속 차단
      2-4. readinessProbe가 API 호출을 다시 성공하면 service와 파드를 다시 연결해 외부 트래픽 접속 허용
  • readinessProbe의 용도

    • 애플리케이션이 기동이 된 상태지만 의도적으로 외부 트래픽을 받지 않게 사용
      • 이러한 의도에 따라 readinessProbe와 livenessProbe가 동일한 url을 받게 할지, 분리할지가 결정됨
  • 정리

    • startupProbe
      • 애플리케이션의 기동 상태를 확인해 애플리케이션이 정상적으로 초기화되기 전 외부 트래픽을 차단하고자 할 때 사용
      • 스프링 부트 애플리케이션의 ApplicationContext refresh 과정이 다 끝나지 않아 API 호출을 아예 수행하지 못할 때 사용
    • readinessProbe
      • 애플리케이션이 기동되었지만, 외부 트래픽을 차단하고자 할 때 사용
      • 스프링 부트 애플리케이션의 초기화는 모두 끝났으나, 정상적인 서비스를 제공하기 위해 필요한 전처리 작업을 수행할 때 사용
    • livenessProbe
      • 애플리케이션의 기동 상태를 확인해 애플리케이션이 비정상적인 상태일 때 파드를 재기동하기 위해 사용
  • 주의사항

    • readinessProbe나 livenessProbe는 애플리케이션이 죽을 때 까지 주기적으로 헬스 체크를 수행하므로 이러한 API는 최대한 비용이 적게 처리해야 함

API 날려보며 Probe 동작 확인하기

# 외부 API 실패 
curl http://192.168.56.30:31231/hello

  • 애플리케이션 초기화 단계
  • 애플리케이션이 기동 중이기 때문에 외부 API 실패

# 외부 API 실패 
curl http://192.168.56.30:31231/hello

# 내부 API 성공
kubectl exec -n anotherclass-123 -it api-tester-1231-75dd57f8cb-tpdpb -- curl localhost:8080/hello

  • 애플리케이션 초기화 이후 User 초기화 단계
  • 내부 API는 성공하지만, 외부 API를 수행하기에는 모든 초기화 작업이 수행되지 않았으므로 실패

# 외부 API 성공
curl http://192.168.56.30:31231/hello

# 내부 API 성공
kubectl exec -n anotherclass-123 -it api-tester-1231-75dd57f8cb-tpdpb -- curl localhost:8080/hello

  • 애플리케이션 초기화, User 초기화 모두 성공
  • 이후 startupProbe 비활성화, readinessProbe와 livenessProbe 트리거
    • 10초 간격으로 애플리케이션 헬스 체크

# 트래픽 중단
curl http://192.168.56.30:31231/traffic-off

# 외부 API 실패
curl http://192.168.56.30:31231/hello

  • readinessProbe 실패로 인해 외부 트래픽 접근 금지

# 트래픽 재개
kubectl exec -n anotherclass-123 -it api-tester-1231-75dd57f8cb-tpdpb -- curl localhost:8080/traffic-on


# 장애 발생 
curl http://192.168.56.30:31231/server-error

  • readinessProbe 3번 실패로 인해 파드 재기동

일시적인 장애 상황에서의 Probe 활용

  • 문제 상황
    • 애플리케이션에서 시간이 지난다면 자연스럽게 해결되는 일시적인 장애 발생
    • readinessProbe와 livenessProbe가 실패하면서 파드 재기동
    • 살아있는 다른 파드의 부하가 커지고 문제가 생긴 애플리케이션이 처리 중인 작업이 모두 실패
  • 개선 방안
    1. 애플리케이션에서 시간이 지난다면 자연스럽게 해결되는 일시적인 장애 발생
    2. readinessProbe의 경우 외부 트래픽을 차단하므로 그대로 유지
    3. livenessProbe의 경우 readinessProbe의 주기보다 길게 설정해 파드가 너무 빠르게 재시작하지 않도록 설정
      3-1. 애플리케이션마다 파드 수명을 적절히 설정해야 함

응용 과제 - Pod(Probe)

응용 1

startupProbe가 실패 되도록 설정해서 Pod가 무한 재기동 상태가 되도록 설정해 보세요.

  • startupProbe는 애플리케이션 초기화를 체크하는 Probe
  • 쿠버네티스만을 활용해 항상 startupProbe가 실패하도록 설정하기 위해서 다음과 같은 실패 조건을 쉽게 충족시킬 수 있도록 설정을 변경하면 됨
    • periodSeconds
      • 애플리케이션이 초기화되기 위해 소모되는 시간보다 훨씬 짧은 주기로 startupProbe를 실행하도록 변경
    • failureThreshold
      • startupProbe가 실패했음을 판단하는 수치를 매우 낮게 측정
startupProbe:
  httpGet:
    path: "/startup"
    port: 8080
  periodSeconds: 1
  failureThreshold: 1

응용 2

일시적 장애 상황(App 내부 부하 증가)가 시작 된 후, 30초 뒤에 트래픽이 중단되고, 3분 뒤에는 App이 재기동 되도록 설정해 보세요.

# 부하 증가 API - (App 내부 isAppReady와 isAppLive를 False로 바꿈)
curl http://192.168.56.30:31231/server-load-on

# 외부 API 실패
curl http://192.168.56.30:31231/hello

# 부하 감소 API - (App 내부 isAppReady와 isAppLive를 True로 바꿈)
curl http://192.168.56.30:31231/server-load-off
  • 30초 뒤에 트래픽 중단
    • readinessProbe의 주기 및 실패 한도를 변경해서 처리
  • 3분 뒤 애플리케이션 재기동
    • livenessProbe의 주기 및 실패 한도를 변경해서 처리
readinessProbe:
  httpGet:
    path: "/readiness"
    port: 8080
  periodSeconds: 15
  failureThreshold: 2
livenessProbe:
  httpGet:
    path: "/liveness"
    port: 8080
  periodSeconds: 60
  failureThreshold: 3

응용 3

Secret 파일(/usr/src/myapp/datasource/postgresql-info.yaml)이 존재하는지 체크하는 readinessProbe를 만들어 보세요.

readinessProbe:
  exec:
    command: 
      - cat
      - /usr/src/myapp/datasource/postgresql-info.yaml
  periodSeconds: 10
  failureThreshold: 3
profile
안녕하세요

0개의 댓글