본문 바로가기
AWS

[EKS 모범 사례] 스케쥴링/probe

by HH_g 2024. 8. 10.

여러 노드에 replicas 스케줄링

모든 replicas의 파드가 동일한 노드에서 실행되고 있으면 해당 노드를 사용할 수 없어질 때 여러 파드를 배포하는 것의 유용성이 떨어지게됩니다. 파드 anti-affinity 또는 파드 topology spread contraints을 사용해 디플로이먼트의 파드를 여러 워커 노드에 분산시키는 것을 권장합니다.

여러 AZ에서 실행하여 일반적인 애플리케이션의 신뢰성을 더욱 개선할 수 있습니다.

 

파드 anti-affinity 규칙 사용

아래 매니페스트는 쿠버네티스 스케줄러에게 파드를 별도의 노드와 AZ에 배치하도록 prefer라고 지시합니다. 이렇게 되어있다면 별도의 노드나 AZ가 필요하지 않습니다. 그렇게 하면 각 AZ에서 실행 중인 파드가 있으면 쿠버네티스가 어떤 파드도 스케줄링할 수 없기 때문입니다. 애플리케이션에 단 세 개의 복제본이 필요한 경우, topologyKey: topology.kubernetes.io/zone에 대해 requiredDuringSchedulingIgnoredDuringExecution를 사용할 수 있으며, 쿠버네티스 스케줄러는 동일한 AZ에 두 개의 파드를 스케줄링하지 않습니다.

 

파드 anti-affinity 규칙을 사용하면 특정 라벨을 가진 파드들이 동일한 토폴로지 도메인 (예: 동일한 노드, 동일한 AZ)에 배치되지 않도록 제어할 수 있습니다. 이를 통해 파드들이 서로 다른 노드나 AZ에 배치되도록 하여, 장애에 대한 내결함성을 높일 수 있습니다.

 

 

apiVersion: apps/v1
kind: Deployment
metadata:
  name: spread-host-az
  labels:
    app: web-server
spec:
  replicas: 4
  selector:
    matchLabels:
      app: web-server
  template:
    metadata:
      labels:
        app: web-server
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - web-server
              topologyKey: topology.kubernetes.io/zone
            weight: 100
          - podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - web-server
              topologyKey: kubernetes.io/hostname 
            weight: 99
      containers:
      - name: web-app
        image: nginx:1.16-alpine
  • preferredDuringSchedulingIgnoredDuringExecution: 스케줄러에게 파드를 특정 조건에 따라 배치하도록 "선호(preferred)" 지시를 내립니다.
  • podAffinityTerm의 labelSelector를 통해 app: web-server 라벨을 가진 파드들을 참조합니다.
  • topologyKey를 통해 topology.kubernetes.io/zone과 kubernetes.io/hostname을 사용하여, 동일한 존 및 호스트에 동일한 라벨을 가진 파드가 배치되지 않도록 선호합니다.

 

파드 Topology Spread Constraints

파드 topology spread constraints를 사용하면 파드가 다양한 토폴로지 도메인 (예: 노드, AZ)에 균등하게 분산되도록 제어할 수 있습니다. 이는 파드들이 최대한 균등하게 분산되도록 하여, 특정 도메인에서의 리소스 사용률을 최적화하고 내결함성을 보장합니다.

 

apiVersion: apps/v1
kind: Deployment
metadata:
  name: spread-constraints
  labels:
    app: web-server
spec:
  replicas: 4
  selector:
    matchLabels:
      app: web-server
  template:
    metadata:
      labels:
        app: web-server
    spec:
      topologySpreadConstraints:
      - maxSkew: 1
        topologyKey: topology.kubernetes.io/zone
        whenUnsatisfiable: DoNotSchedule
        labelSelector:
          matchLabels:
            app: web-server
      - maxSkew: 1
        topologyKey: kubernetes.io/hostname
        whenUnsatisfiable: DoNotSchedule
        labelSelector:
          matchLabels:
            app: web-server
      containers:
      - name: web-app
        image: nginx:1.16-alpine
  • maxSkew: 파드가 토폴로지 도메인 간에 불균형하게 분산될 수 있는 최대 정도를 정의합니다. 값이 1이면 파드들이 최대한 균등하게 분산됩니다.
  • topologyKey: 토폴로지 도메인의 유형을 정의합니다. 여기서는 topology.kubernetes.io/zone과 kubernetes.io/hostname을 사용하여 존과 호스트 간에 파드를 분산시킵니다.
  • whenUnsatisfiable: 제약 조건을 충족할 수 없는 경우 스케줄러가 어떻게 행동할지를 정의합니다. DoNotSchedule은 조건을 충족할 수 없는 경우 파드를 스케줄링하지 않습니다.
  • labelSelector: 특정 라벨을 가진 파드를 선택하여 제약 조건을 적용합니다.

이러한 규칙들을 통해 쿠버네티스 스케줄러가 파드를 배치할 때 내결함성과 가용성을 극대화할 수 있습니다. Anti-affinity 규칙은 특정 파드들이 동일한 도메인에 배치되지 않도록 하는 데 유용하며, Topology Spread Constraints는 파드들이 다양한 도메인에 균등하게 분산되도록 하는 데 유용합니다.

 

상태 점검 및 자가 복구

 

쿠버네티스는 세 가지 유형의 상태 검사를 지원합니다.

  1. Liveness probe
  2. Startup probe (쿠버네티스 버전 1.16 이상에서 지원)
  3. Readiness probe

쿠버네티스 에이전트인 Kubelet은 위에서 언급한 모든 검사를 실행할 책임이 있습니다. Kubelet은 세 가지 방법으로 파드의 상태를 확인할 수 있습니다. kubelet은 파드의 컨테이너 내에서 셸 명령을 실행하거나, 컨테이너에 HTTP GET 요청을 보내거나, 지정된 포트에 TCP 소켓을 열 수 있습니다.

컨테이너 내에서 셸 스크립트를 실행하는 exec 기반 프로브를 선택하는 경우, TimeoutSeconds 값이 만료되기 전에 셸 명령어가 종료되는지 확인하십시오. 그렇지 않으면 노드에 노드 장애를 일으키는 <defunct> 프로세스가 생깁니다.

권장 사항

Liveness Probe를 사용하여 비정상 파드 제거

Liveness probe는 프로세스가 계속 실행되지만 애플리케이션이 응답하지 않는 교착 상태를 감지할 수 있습니다.

예를 들어 포트 80에서 수신 대기하는 웹 서비스를 실행 중인 경우 파드의 포트 80에서 HTTP GET 요청을 보내도록 Liveness 프로브를 구성할 수 있습니다.

Kubelet은 주기적으로 GET 요청을 파드에 보내고 응답을 기다립니다. 파드가 200-399 사이에서 응답하면 kubelet은 파드가 정상이라고 간주하고, 그렇지 않으면 파드는 비정상으로 표시됩니다. 파드가 상태 체크에 계속 실패하면 kubelet은 파드를 종료합나다.

initialDelaySeconds를 사용하여 첫 번째 프로브를 지연시킬 수 있습니다.

Liveness Probe를 사용할 때는 모든 파드가 동시에 Liveness Probe에 실패하는 상황이 발생하지 않도록 해야 합니다.

  • 모든 파드가 동시에 Liveness Probe에 실패하면, 쿠버네티스는 모든 파드를 재시작하려고 시도합니다. 이 경우 애플리케이션 전체가 오프라인 상태가 될 수 있습니다.
  • 특히, 애플리케이션의 모든 파드가 동시에 실패하면 서비스 가용성에 심각한 영향을 미칠 수 있습니다.

파드 외부 요소에 의존하지 않도록 Liveness Probe를 구성해야 합니다

 

시작하는 데 시간이 오래 걸리는 어플리케이션에는 Startup Probe를 사용하십시오.

앱을 시작하는 데 추가 시간이 필요한 경우 Startup Probe를 사용하여 Liveness 및 Readniness Probe를 지연시킬 수 있습니다. 예를 들어 데이터베이스로 부터 데이터를 캐싱해야 하는 Java 앱이 제대로 작동하려면 최대 2분이 걸릴 수 있습니다. 완전히 작동하기 전까지는 모든 Liveness 또는 Readniness Probe가 실패할 수 있습니다. Startup Probe를 구성하면 Liveness 또는 Readniness Probe를 실행하기 전에 Java 앱을 정상상태로 만들 수 있습니다.

Startup Probe가 성공할 때까지 다른 모든 프로브는 비활성화됩니다. 쿠버네티스가 애플리케이션 시작을 위해 대기해야 하는 최대 시간을 정의할 수 있습니다. 최대 구성 시간이 지난 후에도 파드가 여전히 스타트업 프로브에 실패하면 파드는 종료되고 새 파드가 생성됩니다.

Startup Probe는 Liveness Probe와 비슷합니다. 즉, 실패하면 파드가 다시 생성됩니다.

애플리케이션 시작 시간을 예측할 수 없는 경우에는 Startup Probe를 사용해야 합니다.

애플리케이션을 시작하는 데 10초가 걸린다는 것을 알고 있다면 대신 initialDelaySeconds와 함께 Liveness/Readiness Probe를 사용해야 합니다.

 

Readiness Probe를 사용하여 부분적으로 사용할 수 없는 상태를 감지하세요

Liveness probe는 파드 종료(즉, 앱 재시작)를 통해 해결되는 앱 장애를 감지하는 반면, Readiness Probe는 앱을 temporarily 사용할 수 없는 상태를 감지합니다. 이러한 상황에서는 앱이 일시적으로 응답하지 않을 수 있지만 이 작업이 완료되면 다시 정상이 될 것으로 예상됩니다.

예를 들어, 집중적인 디스크 I/O 작업 중에는 애플리케이션이 일시적으로 요청을 처리할 수 없을 수 있습니다. 여기서 애플리케이션의 파드를 종료하는 것은 해결책이 아니며, 동시에 파드로 전송된 추가 요청이 실패할 수 있습니다.

Readiness Probe를 사용하여 앱의 일시적인 가용성 중단을 감지하고 다시 작동할 때까지 해당 파드에 대한 요청 전송을 중단할 수 있습니다.

실패로 인해 파드가 재생성되는 Liveness Probe와 달리, Readiness Probe가 실패하면 파드는 쿠버네티스 서비스로부터 어떠한 트래픽도 수신하지 않게 됩니다. Readiness Probe가 성공하면 파드는 서비스로부터 트래픽을 다시 수신합니다.

Liveness Probe와 마찬가지로 파드 외부의 리소스(예: 데이터베이스)에 의존하는 Readiness Probe를 구성하지 마십시오.

다음은 잘못 구성된 Readiness로 인해 애플리케이션이 작동하지 않을 수 있는 시나리오입니다. 앱의 데이터베이스에 연결할 수 없을 때 파드의 Readiness Probe에 장애가 발생하면 다른 파드 복제본도 동일한 상태 점검 기준을 공유하므로 동시에 실패합니다. 이러한 방식으로 프로브를 설정하면 데이터베이스를 사용할 수 없을 때마다 파드의 Readiness Probe가 실패하고 쿠버네티스가 모든 파드로 트래픽 전송을 중지할 수 있습니다.

Readiness Probes 사용의 부작용은 디플로이먼트를 업데이트하는 데 걸리는 시간을 늘릴 수 있다는 것입니다. Readiness Probe가 성공하지 않는 한 새 replicaset은 트래픽을 수신하지 않습니다. 그때까지는 기존 replicaset이 계속해서 트래픽을 수신하게 됩니다.

 

 

 

'AWS' 카테고리의 다른 글

[EKS] Python 코드로 EKS 클러스터 접근하기  (0) 2024.09.29
[AWS] Assume role  (0) 2024.09.29
[AWS] EBS EFS 선택 기준  (0) 2024.09.17
[EKS 모범 사례] - karpenter  (0) 2024.08.10
[AWS] EKS Workshop 실습  (1) 2024.08.10