쿠버네티스의 워크로드 배치 과정테인트와 TolerationNodeSelector어피니티 및 안티어피니티를 이용한 파드 배정지정node affinitypod affinity자동 스케일링을 이용하여 처리 용량 제어선점과 우선순위를 이용한 리소스 보호우선순위 등급
쿠버네티스의 워크로드 배치 과정
- 새로 생성된 파드는 실행될 노드가 지정될 때까지 우선 보류(pending)상태가 됨
- 그리고 스케쥴러가 보류 상태의 파드를 발견하면 이 파드를 실행하기 가장 적절한 노드를 찾기 시작함
- 워크로드 배치 과정
필터링
: 부적격한 노드를 후보에서 제거하는 과정스코어링
: 후보에 남아 있는 노드에 점수를 매겨 가장 적합한 노드를 선택
테인트와 Toleration
테인트
: 레이블과 마찬가지로 키-값 형태이며, 스케줄러가 노드를 분류하는 기준이 됨- master 테인트는 기본적으로 컨트롤 플레인에 적용되며, 그래서 컨트롤 플레인 노드에는 애플리케이션이 실행되지 않음
# 노드의 목록과 각 노드에 부여된 테인트를 출력 kubectl get nodes -o=jsonpath='{range .items[*]}{.metadata.name}{.spec.taints[*].key}{end}' # 모든 노드에 테인트를 하나 추가 kubectl taint nodes --all kiamol-disk=hdd:NoSchedule
- 위 테인트(
NoSchedule
)를 추가하면 파드가 특별히 이 테인트를 용납(toleration
)하지 않는 한 이 노드에서는 애플리케이션 실행이 되지 않음
apiVersion: apps/v1 kind: Deployment metadata: name: sleep2 labels: kiamol: ch19 spec: selector: matchLabels: app: sleep2 template: metadata: labels: app: sleep2 spec: containers: - name: sleep image: kiamol/ch03-sleep tolerations: - key: "kiamol-disk" operator: "Equal" value: "hdd" effect: "NoSchedule"
NoSchedule
이펙트는 파드 정의에 톨러레이션이 없는 한 스케줄러의 필터링 단계에서 노드가 배제되기 때문에 강력한 테인트임PreferNoSchedule
이 있음. 이 테인트를 가진 노드는 스코어링 단계까지 넘어가지만 다른 노드보다 낮은 점수를 받음PreferNoSchedule
은 파드에 톨러레이션이 있고 다른 적합한 노드가 남아 있지 않는 한 이 노드에서 파드를 실행하지 말라는 의미NodeSelector
노드셀렉터는 레이블 정보에 따라 노드를 필터링 단계에서 배제하는 역할을 함
apiVersion: apps/v1 kind: Deployment metadata: name: sleep2 labels: kiamol: ch19 spec: selector: matchLabels: app: sleep2 template: metadata: labels: app: sleep2 spec: containers: - name: sleep image: kiamol/ch03-sleep tolerations: - key: "kiamol-disk" operator: "Equal" value: "hdd" effect: "NoSchedule" nodeSelector: kubernetes.io/arch: zxSpectrum
- 노드셀렉터는 특정 레이블이 부여된 노드에서만 애플리케이션이 실행되도록 강제할 수 있음
- 레이블의 완전 일치보다 유연한 적용이 필요할 때가 있는데, 이런 미세조절에는 어피니티(affinity)와 안티어피니티(antiaffinity)가 쓰임
어피니티 및 안티어피니티를 이용한 파드 배정지정
- 노드에
어피니티
를 선언해두면 이들 노드에 파드가 실행되도록 강제할 수 있음
- 어피니티에도 노드셀렉터가 쓰이지만 단순한 완전일치가 아닌 일치표현식을 사용함
- 필요 조건을 만족하는 노드를 찾지 못하면 파드가 실행되지 않는다는 점을 기억하고, 이를 대비하는 우선 조건을 마련해 두어야 함
node affinity
apiVersion: apps/v1 kind: Deployment metadata: name: sleep2 labels: kiamol: ch19 spec: selector: matchLabels: app: sleep2 template: metadata: labels: app: sleep2 spec: containers: - name: sleep image: kiamol/ch03-sleep tolerations: - key: "kiamol-disk" operator: "Equal" value: "hdd" effect: "NoSchedule" affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/arch operator: In values: - amd64 - key: kubernetes.io/os operator: In values: - linux - windows - matchExpressions: - key: beta.kubernetes.io/arch operator: In values: - amd64 - key: beta.kubernetes.io/os operator: In values: - linux - windows preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: kubernetes.io/os operator: In values: - linux - weight: 1 preference: matchExpressions: - key: beta.kubernetes.io/os operator: In values: - linux
- requiredDuringSchedulingIgnoredDuringExecution 키워드는 신규파드(
during scheduling
)에는 강제되나 기존 파드(during execution
)에는 강제되지 않는다는 의미
- 필요 조건
- 여러 개의 일치 표현식이 AND 조건으로 연결
- 여러 개의 셀렉터는 or 조건으로 연결
- 우선 조건
- 여러 개의 일치 표현식은 AND 조건
- OR 조건 사용하려면 여러 개의 우선 조건 작성
pod affinity
- 다른 파드와 같은 노드에 배정해야 할 때는 어피니티를 작성
- 서로 통신하는 컴포넌트끼리 같은 노드에 배정하여 네트워크 부하를 줄이려는 경우
- 서로 다른 노드에 배정해야 할 때는 안티어피니티를 작성
- 같은 컴포넌트의 레플리카를 서로 다른 노드에 흩어 놓아 중복성을 확보하는 경우
apiVersion: apps/v1 kind: Deployment metadata: name: numbers-web labels: kiamol: ch19 app: numbers spec: selector: matchLabels: app: numbers component: web template: metadata: labels: app: numbers component: web spec: containers: - name: web image: kiamol/ch03-numbers-web affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - numbers - key: component operator: In values: - api topologyKey: "kubernetes.io/hostname"
- 토폴로지는 클러스터의 물리적 레이아웃, 즉 노드의 물리적 위치를 가리킴
- 토폴로지 키는 어피니티의 적용 단위를 결정
- 적용 단위가 호스트 네임이면 파드를 같은 노드에 실행하라는 의미가 되고, region이나 zone이 될 때는 지역이 같은 노드끼리 실행하라는 의미가 됨
자동 스케일링을 이용하여 처리 용량 제어
수평 스케일링
: 기존 노드를 활용하여 자동으로 애플리케이션의 파드 수를 조절해주는 기능파드를 언제 어떻게 스케일링할지 기술한 오토스케일 정의를 배치할 수는 있지만, 기존 파드의 부하를 확인할 방법이 필요함 → metrics-server 컴포넌트
- metrics-server에서 수집되는 측정값은 CPU나 메모리 사용량 같은 기본적인 컴퓨팅 리소스 사용량 뿐이며 질의가 들어온 시점의 현재 수치만 응답함
apiVersion: autoscaling/v1 kind: HorizontalPodAutoscaler metadata: name: pi-cpu labels: kiamol: ch19 spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: pi-web minReplicas: 1 maxReplicas: 5 targetCPUUtilizationPercentage: 75
- HPA는
디플로이먼트
나스테이트풀셋
같은 파드 컨트롤러를 스케일링 대상으로 삼으며 cpu 사용량에 따라 조절할 레플리카 수의 범위를 지정함
- HPA는 실행 중인 모든 파드의 평균 cpu 사용량을 감시하다
- 지정된 사용량보다 낮아지면 파드 감소
- 높아지면 파드 증가
- 이 때 파드 수는 지정한 범위 안에서만 변경됨
- 파라미터들 (
autoscaling/v2
에서부터 해당 파라미터들 조정 가능) - 레플리카 증가 및 감소를 시작하기까지 기다리는 대기 시간
- 한 번에 늘리는파드 수
- 파드를 증감시키는 간격
apiVersion: autoscaling/v2beta2 kind: HorizontalPodAutoscaler metadata: name: pi-cpu labels: kiamol: ch19 spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: pi-web minReplicas: 1 maxReplicas: 5 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 75 behavior: scaleDown: stabilizationWindowSeconds: 30 # 측정값이 기준 아래로 내려온 후 30초 대기하고 policies: - type: Percent value: 50 # 현재 파드 수의 50%를 감소시킴 periodSeconds: 15 # 스케일링 동작이 적용될 시간주기
- 프로메테우스에서 수집한 측정값도 기준으로 삼을 수 있음
- 측정값이 수집되고 있다면 인입 HTTP 요청 수나 큐에 쌓인 메시지 수 같은 것도 기준으로 삼을 수 있음
선점과 우선순위를 이용한 리소스 보호
- 간혹 특정노드에 과부하가 걸릴 때, 쿠버네티스는 선제적으로 몇몇 파드를 강제종료하여 노드가 기능을 회복할 수 있도록 함 →
축출
(eviction)
- 축출된 파드는 나중에 사용자가 문제 원인을 파악할 수 있도록 노드에 남겨두지만, 그 안의 파드 컨테이너는 종료 및 삭제되어 메모리 및 디스크 용량 회수
선점
은 리소스 정의나 리소스쿼터, 배정이나 스케일링 등에 문제가 생겨 노드의 메모리 또는 디스크 용량 같은 리소스가 고갈된 상태에서 발생함- 선점 발생 시, 쿠버네티스는 해당 노드가 과부하 상태라 간주, 상황해결시 까지 파드를 축출함
- 그리고 노드에 테인트를 부여하여 신규 파드가 배정되지 않도록 함
- 과부하 상태가 완화되면 테인트가 제거되고 다시 새로운 파드 배정받을 수 있게 됨
우선순위 등급
워크로드의 중요도를 분류할 수 있는 수단
apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: kiamol-low labels: kiamol: ch19 value: 100 globalDefault: true description: "Low priority - OK to be evicted" --- apiVersion: apps/v1 kind: Deployment metadata: name: stress-high labels: kiamol: ch19 spec: replicas: 2 selector: matchLabels: app: stress level: high template: metadata: labels: app: stress level: high spec: priorityClassName: kiamol-low containers: - name: stress image: kiamol/ch19-stress env: - name: MEMORY_STRESS_MB value: "300" resources: requests: memory: 250Mi limits: memory: 350Mi --- apiVersion: apps/v1 kind: Deployment metadata: name: stress-low labels: kiamol: ch19 spec: replicas: 4 selector: matchLabels: app: stress level: low template: metadata: labels: app: stress level: low spec: priorityClassName: kiamol-low containers: - name: stress image: kiamol/ch19-stress env: - name: MEMORY_STRESS_MB value: "300" resources: requests: memory: 50Mi limits: memory: 350Mi
- 우선순위 등급이 다르게 부여된 두 버전의 애플리케이션이 있을 때, 메모리 고갈 상태가 발생하면 두 애플리케이션 중 우선순위 등급이 낮은 쪽의 파드가 축출됨
- 축출될 파드를 결정하는 데 우선순위 등급만 관여하지는 않고, 만약 우선순위가 같다면 파드가 초기 요청한 양보다 초과 점유하고 있는 메모리양이 많은 순서대로 축출할 파드를 결정