無知

갈 길이 먼 공부 일기

기술 공부/쿠버네티스

쿠버네티스 (15) | 오토스케일링

moozii 2022. 3. 31. 19:10
앞으로의 스터디 내용은 <Kubernetes in Action>을 기반으로 진행합니다.
자세한 내용은, 해당 책을 확인해주세요! 
http://www.yes24.com/Product/Goods/89607047 

 

 

핵심 내용

- CPU 사용률 기반 파드 자동 수평 스케일링

- 사용자 정의 메트릭 기반 파드 자동 수평 스케일링

- 파드 수직 스케일링의 어려움

- 클러스터 노드 자동 수평 스케일링

 

 

@HorizontalPodAutoscaler&nbsp;https://kubernetes.io/ko/docs/tasks/run-application/horizontal-pod-autoscale/

 

 

수평적 파드 오토스케일링

컨트롤러를 통한 파드 레플리카 수의 자동 조정이 이루어진다.

 

1. Horizontal 컨트롤러가 HorizontalPodAutoScaler, HPA 리소스를 작성해 활성화시키고 스케일링을 설정한다.

2. 컨트롤러는 주기적으로 파드 메트릭을 확인한다. [따라서 즉각적으로 이뤄지지는 않는다]

3. 컨트롤러는 HPA 리소스에 설정된 대상 메트릭 값을 만족하는 레플리카 수를 계산한다. 

4. 컨트롤러는 대상 리소스 내 레플리카 수 필드 값을 조절한다. 

(대상 리소스에는 디플로이먼트, 레플리카셋, 레플리케이션컨트롤러, 스테이트풀셋 등이 존재한다.)

 

 

 

오토스케일링 프로세스 상세

1. 파드 메트릭 얻기
2. 필요한 파드 수 계산
3. 스케일링된 리소스 레플리카 수 갱신

 

1. 파드 메트릭 얻기

1.1 설명 : 확장 가능한 리소스 오브젝트에서 관리하는 전체 파드의 메트릭을 수합. 

 

1.2 메트릭 수집 위치 : 오토스케일러가 직접 수집하지 않고,

1.2.1. 파드 및 노드 메트릭을 cAdvisor 에이전트가 수집하고,

1.2.2 힙스터로 그 데이터를 집계하면(이전 장에서 다뤘듯 힙스터는 이제 사용하지 않고 metrics server를 이용할 것으로 추정) - 책의 설명에 따르면 쿠버네티스 버전 1.8부터 힙스터가 아니라, 오토스케일러가 리소스 메트릭의 집계된 버전 API를 통해 데이터를 얻는다고 나온다. 아래 쪽에 공식문서를 확인해보니, 추측대로 메트릭 서버를 활용하여 데이터를 가져온다. 

1.2.3 오토스케일러 컨트롤러가 그 수집된 데이터를 REST를 통해 쿼리로 가져오는 방식이다. 

 

[HorizontalPodAutoscaler는 어떻게 작동하는가?]

각 주기마다, 컨트롤러 관리자는 각 HorizontalPodAutoscaler 정의에 지정된 메트릭에 대해 리소스 사용률을 질의한다. 컨트롤러 관리자는 리소스 메트릭 API(파드 단위 리소스 메트릭 용) 또는 사용자 지정 메트릭 API(다른 모든 메트릭 용)에서 메트릭을 가져온다. 파드 단위 리소스 메트릭(예 : CPU)의 경우 컨트롤러는 HorizontalPodAutoscaler가 대상으로하는 각 파드에 대한 리소스 메트릭 API에서 메트릭을 가져온다. 그런 다음, 목표 사용률 값이 설정되면, 컨트롤러는 각 파드의 컨테이너에 대한 동등한 자원 요청을 퍼센트 단위로 하여 사용률 값을 계산한다. 대상 원시 값이 설정된 경우 원시 메트릭 값이 직접 사용된다. 그리고, 컨트롤러는 모든 대상 파드에서 사용된 사용률의 평균 또는 원시 값(지정된 대상 유형에 따라 다름)을 가져와서 원하는 레플리카의 개수를 스케일하는데 사용되는 비율을 생성한다.

HorizontalPodAutoscaler를 사용하는 일반적인 방법은 집약된 API(metrics.k8s.io, custom.metrics.k8s.io, 또는 external.metrics.k8s.io)로부터 메트릭을 가져오도록 설정하는 것이다. metrics.k8s.io API는 보통 메트릭 서버(Metrics Server)라는 애드온에 의해 제공되며, Metrics Server는 별도로 실행해야 한다. 자원 메트릭에 대한 추가 정보는 Metrics Server를 참고한다.

https://kubernetes.io/ko/docs/tasks/run-application/horizontal-pod-autoscale/ 
 

Horizontal Pod Autoscaling

쿠버네티스에서, HorizontalPodAutoscaler 는 워크로드 리소스(예: 디플로이먼트 또는 스테이트풀셋)를 자동으로 업데이트하며, 워크로드의 크기를 수요에 맞게 자동으로 스케일링하는 것을 목표로 한

kubernetes.io

[Kubernetes API Aggregation Layer]

The aggregation layer allows Kubernetes to be extended with additional APIs, beyond what is offered by the core Kubernetes APIs. The additional APIs can either be ready-made solutions such as a metrics server, or APIs that you develop yourself. The aggregation layer is different from Custom Resources, which are a way to make the kube-apiserver recognise new kinds of object.

https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/apiserver-aggregation/ 
 

Kubernetes API Aggregation Layer

The aggregation layer allows Kubernetes to be extended with additional APIs, beyond what is offered by the core Kubernetes APIs. The additional APIs can either be ready-made solutions such as a metrics server, or APIs that you develop yourself. The aggrega

kubernetes.io

[메트릭 서버]

메트릭 서버는 클러스터 전역에서 리소스 사용량 데이터를 집계한다. kube-up.sh 스크립트에 의해 생성된 클러스터에는 기본적으로 메트릭 서버가 디플로이먼트 오브젝트로 배포된다. 만약 다른 쿠버네티스 설치 메커니즘을 사용한다면, 제공된 디플로이먼트 components.yaml 파일을 사용하여 메트릭 서버를 배포할 수 있다. 메트릭 서버는 각 노드에서 Kubelet에 의해 노출된 Summary API에서 메트릭을 수집하고, 쿠버네티스 aggregator를 통해 메인 API 서버에 등록된다.

https://kubernetes.io/ko/docs/tasks/debug-application-cluster/resource-metrics-pipeline/#%EB%A9%94%ED%8A%B8%EB%A6%AD-%EC%84%9C%EB%B2%84 
 

리소스 메트릭 파이프라인

컨테이너 CPU 및 메모리 사용량과 같은 리소스 사용량 메트릭은 쿠버네티스의 메트릭 API를 통해 사용할 수 있다. 이 메트릭은 kubectl top 커맨드 사용하여 사용자가 직접적으로 액세스하거나, Horizo

kubernetes.io

[Kubernetes Metrics Server]

Metrics Server is a scalable, efficient source of container resource metrics for Kubernetes built-in autoscaling pipelines. Metrics Server collects resource metrics from Kubelets and exposes them in Kubernetes apiserver through Metrics API for use by Horizontal Pod Autoscaler and Vertical Pod Autoscaler. Metrics API can also be accessed by kubectl top, making it easier to debug autoscaling pipelines. Metrics Server is not meant for non-autoscaling purposes. For example, don't use it to forward metrics to monitoring solutions, or as a source of monitoring solution metrics. In such cases please collect metrics from Kubelet /metrics/resource endpoint directly.

https://github.com/kubernetes-sigs/metrics-server 
 

GitHub - kubernetes-sigs/metrics-server: Scalable and efficient source of container resource metrics for Kubernetes built-in aut

Scalable and efficient source of container resource metrics for Kubernetes built-in autoscaling pipelines. - GitHub - kubernetes-sigs/metrics-server: Scalable and efficient source of container reso...

github.com

 

 

 

2. 필요한 파드 수 계산

2.1 파드 수 계산 방법

 

2.1.1. 계산의 입력 값을 설정한다.

2.1.1.1. 파드 메트릭 세트, 즉 파드 당 여러 메트릭 사용이 가능하다. 

2.1.1.2. 모든 레플리카 내 메트릭의 평균 값을 이용한다

 

2.1.2. 계산의 출력값을 구한다.

2.1.2.1. 일반론

2.1.2.1.1. 앞서 구한 평균 값을 기반으로 지정 목표값과 가능한 가깝게 하는 숫자를 찾는다. 

2.1.2.1.2. 계산의 출력 값은, 파드 레플리카 수, 하나의 정수이다.

2.1.2.1.3. 계산 과정은 메트릭 값이 빠르게 변하는 불안정한 상황에서 이루어지므로 간략한 논리 과정만 살펴본다.

[알고리즘 세부 정보]

이 메트릭을 사용하면 HPA 컨트롤러는 스케일링 대상에서 파드의 평균 사용률을 60%로 유지한다. 사용률은 파드의 요청된 리소스에 대한 현재 리소스 사용량 간의 비율이다. 사용률 계산 및 평균 산출 방법에 대한 자세한 내용은 알고리즘을 참조한다. 가장 기본적인 관점에서, HorizontalPodAutoscaler 컨트롤러는 원하는(desired) 메트릭 값과 현재(current) 메트릭 값 사이의 비율로 작동한다. 

원하는 레플리카 수 = ceil[현재 레플리카 수 * ( 현재 메트릭 값 / 원하는 메트릭 값 )]

https://kubernetes.io/ko/docs/tasks/run-application/horizontal-pod-autoscale/#%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%84%B8%EB%B6%80-%EC%A0%95%EB%B3%B4 
 

Horizontal Pod Autoscaling

쿠버네티스에서, HorizontalPodAutoscaler 는 워크로드 리소스(예: 디플로이먼트 또는 스테이트풀셋)를 자동으로 업데이트하며, 워크로드의 크기를 수요에 맞게 자동으로 스케일링하는 것을 목표로 한

kubernetes.io

 

 

2.1.2.2. 오토스케일러가 단일 메트릭만을 고려할 경우

2.1.2.2.1. 모든 파드의 해당 메트릭 값을 더한 뒤 HPA 리소스에 정의된 목표값으로 나누어, 큰 정수로 반올림한다.

 

2.1.2.3. 오토스케일러가 여러 파드 메트릭을 기반으로 하는 경우

2.1.2.3.1. 각 메트릭의 레플리카 수를 개별적으로 계산한다.

2.1.2.3.2. 개별적으로 계산된 레플리카 수 중 가장 높은 값을 취한다. 

 

 

 

 

 

3. 스케일링된 리소스 레플리카 수 갱신

3.1. 스케일링된 리소스 오브젝트의 레플리카 개수 필드를 원하는 값으로 갱신한다.

3.1.1. 오토스케일러 컨트롤러가 스케일 대상 리소스 replicas 필드를 스케일 서브 리소스를 통해 변경한다.

3.1.1.1. API 서버가 스케일 서브 리소스를 노출하면, 오토스케일러는 해당 리소스를 대상으로 동작 가능하다.

3.1.1.1.1. 스케일 서브 리소스 노출 리소스들은 다음과 같다 : 디플로이먼트, 레플리카셋, 레플리케이션 컨트롤러, 스테이트풀셋

 

3.2. 리소스 오브젝트가 추가 파드 생성 혹은 초과 파드 삭제 등의 작업을 진행한다.

 

 

 

 

 

예시 : CPU 사용률 기반 오토스케일링

 

1. CPU 사용량의 적정 수준

1.1. 서비스 요구에 대응하기 위해서는 CPU 사용량이 100% 미만이어야 한다

1.2. 목표 CPU 사용량은 절대 90% 미만으로 설정해 순간적인 부하 발생 시 제어 가능하도록 여유 공간을 확보한다

1.3. CPU 사용량은 대개 불안정하므로 CPU 사용량이 80%에 도달하는 등 임계점에 도달하기 전 스케일아웃을 수행해야 한다

 

2. CPU 사용량의 측정

2.1. CPU 사용량 측정 일반론

2.1.1. CPU 사용량은 컨테이너 리소스 요청을 통해 요구한 값을 보장받는다

2.1.2. CPU 사용량은 노드 내 프로세스가 여유있을 경우 여유분을 추가적으로 사용하며 사용량이 늘어난다

2.1.3. CPU 사용량의 비율 기준이 불명확하다. 노드 기준일 수도, 요구 보장량의 비율일 수도, 제한량의 비율일 수도 있다.

 

2.2. 오토스케일러의 경우 CPU 사용률 기준은 파드의 요청량이다. 

2.2.1. 오토스케일러는 파드 실제 CPU 사용량과 CPU 요청량을 비교한다

2.2.2. 오토스케일링이 필요한 파드는 LimitRange 오브젝트를 활용하는 등 직간접적으로 CPU 요청을 설정해야만 한다.

 

3. CPU 사용량 기반 HPA 생성

3.1. CPU 리소스 요청을 명세에 포함하는 디플로이먼트 생성

3.2. HPA 오브젝트 생성해 앞서 만든 디플로이먼트를 가리킨다.

3.2.1. 명령어 : kubectl autoscale deployment {deployment_name} --cpu-percent=30 --min=1 max=5

3.2.1.1. 명령어 해설 : kubia 디플로이먼트를 대상으로 지정, 목표 CPU 사용률은 30%로 설정, 최소 및 최대 레플리카 수를 지정. 오토스케일러는 CPU 사용률이 30%에 근접하도록 레플리카 수를 해당 범위 내에서 조정. 

$ cat deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kubia
spec:
  replicas: 3
  selector:
    matchLabels:
     app: kubia
  template:
    metadata:
      name: kubia
      labels:
        app: kubia
    spec:
      containers:
      - image: luksa/kubia:v1
        name: nodejs
        resources:
          requests:
            cpu: 100m
$ k create -f deployment.yaml
deployment.apps/kubia created

$ k autoscale deployment kubia --cpu-percent=30 --min=1 --max=5
horizontalpodautoscaler.autoscaling/kubia autoscaled
[Issue 1]

error: unable to recognize "deployment.yaml": no matches for kind "Deployment" in version "extensions/v1beta1"
error: unable to recognize "deployment.yaml": no matches for kind "Deployment" in version "extensions/v1"

>> You need to change Deployment and StatefulSet apiVersion to apiVersion: apps/v1.
https://stackoverflow.com/questions/58481850/no-matches-for-kind-deployment-in-version-extensions-v1beta1 
[Issue 2]

error: error validating "deployment.yaml": error validating data: ValidationError(Deployment.spec): missing required field "selector" in io.k8s.api.apps.v1.DeploymentSpec; if you choose to ignore these errors, turn validation off with --validate=false

The Deployment "kubia" is invalid: spec.template.metadata.labels: Invalid value: map[string]string{"app":"kubia"}: `selector` does not match template `labels`

>> You need to add selector in spec of Deployment. And also, these selector should match with labels in PodTemplate. https://stackoverflow.com/questions/48582951/deployment-invalid-spec-template-metadata-labels-invalid-value 
https://kubernetes.io/ko/docs/concepts/workloads/controllers/deployment/ 
 

디플로이먼트

디플로이먼트(Deployment) 는 파드와 레플리카셋(ReplicaSet)에 대한 선언적 업데이트를 제공한다. 디플로이먼트에서 의도하는 상태 를 설명하고, 디플로이먼트 컨트롤러(Controller)는 현재 상태에서 의

kubernetes.io

$ k get hpa kubia -o yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  creationTimestamp: "2022-03-30T01:52:01Z"
  name: kubia
  namespace: default
  resourceVersion: "338236"
  uid: 52f6e3c1-5c8f-403c-b3f9-832cce294fc9
spec:
  maxReplicas: 5
  metrics:
  - resource:
      name: cpu
      target:
        averageUtilization: 30
        type: Utilization
    type: Resource
  minReplicas: 1
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: kubia
status:
  currentMetrics: null
  desiredReplicas: 0

 

 

 

4. 실습 : 스케일업 

4.1. 사전 준비

4.1.1. kubectl expose deployment {deployment_name} --port=80 --target-port=8080

4.1.2. 파드를 서비스를 통해 노출되도록 설정해, 생성 파드를 하나의 URL로 접근

 

4.2. 리소스 현황 주기적 확인

4.2.1. watch 명령문을 반복문으로 변경

4.2.1.1. watch -n 1 kubectl get hpa,deployment

4.2.2. 주기적으로 k get 명령을 직접 실행

 

4.3. 리소스 부하 생성

4.3.1. kubia 서비스에 반복 접속하는 파드를 실행

4.3.2. kubectl run -it --rm --restart=Never loadgenerator --image=busybox -- sh -c "while true; do wget -0 - -q http://kubia.default; done"

4.3.2.1. 명령어 해설 : -it 옵션으로 콘솔을 대상 프로세스에 붙여 프로세스 출력 직접 확인 가능. -rm 옵션으로 파드 종료 이후 삭제. --restart=Never 옵션으로 디플로이먼트 오브젝트 관리 대상 파드 생성이 아닌, 비관리 파드를 직접 생성. (명령 종료 후 모두 정리됨)

 

 

 

최대 스케일링 비율 이해

1. 한 작업/단계 당 최대 확장 개수 제한

1.1. 오토스케일러는 2개를 초과하는 레플리카가 존재할 경우, 1번의 스케일링 작업에서 최대 2배의 레플리카만 생성 가능하다.

1.2. 오토스케일러는 2개 이하의 레플리카가 존재할 경우, 1번의 스케일링 작업에서 최대 4개로 확장 가능하다.

 

2. 한 작업/단계 당 최대 확장 속도 제한

2.1. 이전 작업 이후 3분 간 아무런 리스케일링 이벤트가 발생하지 않는 경우에만 스케일 업이 발생한다

2.2. 이전 작업 이후 5분 간 아무런 리스케일링 이벤트가 발생하지 않는 경우에만 스케일 다운이 발생한다

 

 

 

HPA 오브젝트의 목표 메트릭값 변경

kubectl edit hpa {hpa_name}

>> spec.metrics.targetAverageUtilization: 30 -> 60

 

 

 

메모리 소비량 기반 스케일링

1. 메모리 기반 오토스케일링의 문제

1.1. 스케일 업 후 오래된 파드는 반드시 메모리 해제가 필요하다.

1.1.1. 메모리 해제 작업은 애플리케이션이 직접 수행해야 하고, 시스템이 대신 수행할 수 없다

1.1.2. 애플리케이션 메모리 사용량은 시스템으로 조절되지 않으므로 반복적인 스케일업이 파드 최대 한계까지 진행된다.

 

 

 

사용자 정의 메트릭 기반 스케일링

1. HPA 사용 메트릭 정의

1.1. spec.metrics.type: Resource ) 메트릭 유형을 지정

1.2. spec.metrics.resource.name: cpu ) 사용률을 모니터링할 리소스를 지정

1.2.1. spec.metrics.resource.meticName: qps 형태도 가능

1.3. spec.metrics.resource.targetAvergaeUtilization: 30 ) 해당 리소스의 목표 사용률을 지정

1.3.1. spec.metrics.resource.targetAverageValue: 100 형태도 가능

[사용자 정의 메트릭을 이용하는 스케일링]

autoscaling/v2beta2 API 버전을 사용하는 경우, (쿠버네티스 또는 어느 쿠버네티스 구성 요소에도 포함되어 있지 않은) 커스텀 메트릭을 기반으로 스케일링을 수행하도록 HorizontalPodAutoscaler를 구성할 수 있다. 이 경우 HorizontalPodAutoscaler 컨트롤러가 이러한 커스텀 메트릭을 쿠버네티스 API로부터 조회한다.

https://kubernetes.io/ko/docs/tasks/run-application/horizontal-pod-autoscale/ 

기본적으로 HorizontalPodAutoscaler 컨트롤러는 일련의 API에서 메트릭을 검색한다. 이러한 API에 접속하려면 클러스터 관리자는 다음을 확인해야 한다.

1. API 애그리게이션 레이어 활성화
2. 해당 API 등록:
2.1. 리소스 메트릭의 경우, 일반적으로 이것은 메트릭-서버가 제공하는 metrics.k8s.io API이다. 클러스터 애드온으로 시작할 수 있다.
2.2. 사용자 정의 메트릭의 경우, 이것은 custom.metrics.k8s.io API이다. 메트릭 솔루션 공급 업체에서 제공하는 "어댑터" API 서버에서 제공한다. 사용 가능한 쿠버네티스 메트릭 어댑터가 있는지 확인하려면 사용하고자 하는 메트릭 파이프라인을 확인한다.
2.3. 외부 메트릭의 경우, 이것은 external.metrics.k8s.io API이다. 위에 제공된 사용자 정의 메트릭 어댑터에서 제공될 수 있다.

이런 다양한 메트릭 경로와 각각의 다른 점에 대한 상세 내용은 관련 디자인 제안서인 HPA V2, custom.metrics.k8s.io, external.metrics.k8s.io를 참조한다. 어떻게 사용하는지에 대한 예시는 커스텀 메트릭 사용하는 작업 과정과 외부 메트릭스 사용하는 작업 과정을 참조한다.

https://kubernetes.io/ko/docs/tasks/run-application/horizontal-pod-autoscale/#%EB%A9%94%ED%8A%B8%EB%A6%AD-api%EB%A5%BC-%EC%9C%84%ED%95%9C-%EC%A7%80%EC%9B%90

[다양한 메트릭 및 사용자 정의 메트릭을 기초로한 오토스케일링]

파드 메트릭과 오브젝트 메트릭 두 가지의 사용자 정의 메트릭 이 있다. 파드 메트릭과 오브젝트 메트릭. 이 메트릭은 클러스터에 특화된 이름을 가지고 있으며, 더 고급화된 클러스터 모니터링 설정이 필요하다.

이러한 대체 메트릭 타입중 첫 번째는 파드 메트릭 이다. 이 메트릭은 파드들을 설명하고, 파드들 간의 평균을 내며, 대상 값과 비교하여 레플리카 개수를 결정한다. 이것들은 AverageValue의 target만을 지원한다는 것을 제외하면, 자원 메트릭과 매우 유사하게 동작한다. 파드 메트릭은 이처럼 메트릭 블록을 사용하여 정의된다.

두 번째 대체 메트릭 타입은 오브젝트 메트릭 이다. 이 메트릭은 파드를 기술하는 대신에 동일한 네임스페이스 내에 다른 오브젝트를 표현한다. 이 메트릭은 반드시 오브젝트로부터 가져올 필요는 없다. 단지 오브젝트를 기술할 뿐이다. 오브젝트 메트릭은 Value과 AverageValue의 target 타입을 지원한다. Value를 사용할 경우 대상은 API로부터 반환되는 메트릭과 직접 비교된다. AverageValue를 사용할 경우, 대상 값과 비교되기 이전에 사용자 정의 메트릭 API로부터 반환된 값은 파드의 개수로 나눠진다. 다음은 requests-per-second 메트릭을 YAML로 기술한 예제이다.

https://kubernetes.io/ko/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/#%EB%8B%A4%EC%96%91%ED%95%9C-%EB%A9%94%ED%8A%B8%EB%A6%AD-%EB%B0%8F-%EC%82%AC%EC%9A%A9%EC%9E%90-%EC%A0%95%EC%9D%98-%EB%A9%94%ED%8A%B8%EB%A6%AD%EC%9D%84-%EA%B8%B0%EC%B4%88%EB%A1%9C%ED%95%9C-%EC%98%A4%ED%86%A0%EC%8A%A4%EC%BC%80%EC%9D%BC%EB%A7%81 
 

HorizontalPodAutoscaler 연습

HorizontalPodAutoscaler(약어: HPA)는 워크로드 리소스(예: 디플로이먼트 또는 스테이트풀셋)를 자동으로 업데이트하며, 워크로드의 크기를 수요에 맞게 자동으로 스케일링하는 것을 목표로 한다. 수평

kubernetes.io

 

 

2. 메트릭 유형 : 총 3가지의 메트릭 유형이 존재 : Resource / Pods / Object

2.1. 리소스 메트릭 유형 : 오토스케일러가 오토스케일링 결정을, 컨테이너의 리소스 요청 항목 등 리소스 메트릭 기반으로 진행

 

2.2. 파드 메트릭 유형 : 파드와 관련된 다른 메트릭을 참조.

2.2.1. 파드 메트릭 유형 예시 : QPS (초당 질의수), 메시지 브로커의 큐 메시지 수 등

 

2.3. 오브젝트 메트릭 유형 : 파드에 직접 관련되지 않는 메트릭을 참조.

2.3.1. 오브젝트 메트릭 유형 예시 : 인그레스 등 클러스터 오브젝트 메트릭, QPS, 평균 요청 대기 시간 등.

2.3.2. HPA 정의 내 대상 오브젝트 및 목표값 정의를 통해, 오토스케일러가 모든 대상 파드 메트릭의 평균 값을 구하는 다른 방식과 달리, 1개 오브젝트의 단일 메트릭을 얻을 수 있음. 

 

2.3.2.1. spec.metrics.resource.metricName: latencyMillis

2.3.2.2. spec.metrics.resource.target.apiVersion: extensions/v1beta1

2.3.2.3. spec.metrics.resource.target.kind: Ingress

2.3.2.4. spec.metrics.resource.target.name: frontend

2.3.2.5. spec.metrics.resource.targetValue: 20

 

2.3.2.6. spec.metrics.resource.scaleTargetRef.apiVersion: extensions/v1beta1

2.3.2.7. spec.metrics.resource.scaleTargetRef.kind: Deployment

2.3.2.8. spec.metrics.resource.scaleTargetRef.name: kubia

 

 

 

오토스케일링 적합 메트릭 결정

레플리카 수를 조절할 때 선형적으로, 혹은 그에 가깝게 해당 관찰 메트릭의 평균 값이 변화하는 메트릭이 적합하다.

 

 

 

레플리카 수를 0으로 감소

- 수평적 파드 오토스케일러는 레플리카 최소값 필드를 0으로 설정할 수 없음 >> 아래 최신 문서 확인 요망.

- 유휴, 유휴 해제 [idling, un-idling] 기능을 통해, 특정 서비스 제공 파드를 0으로 축소할 수 있음. 신규 요청이 들어올 시 파드가 깨어나 요청을 처리할 수 있을 때까지 차단되다 요청이 추후 파드로 전달. 

[암시적 유지 관리 모드 비활성화]

HPA 구성 자체를 변경할 필요없이 대상에 대한 HPA를 암시적으로 비활성화할 수 있다. 대상의 의도한 레플리카 수가 0으로 설정되고, HPA의 최소 레플리카 수가 0 보다 크면, 대상의 의도한 레플리카 수 또는 HPA의 최소 레플리카 수를 수동으로 조정하여 다시 활성화할 때까지 HPA는 대상 조정을 중지한다(그리고 ScalingActive 조건 자체를 false로 설정).


https://kubernetes.io/ko/docs/tasks/run-application/horizontal-pod-autoscale/#%EB%A9%94%ED%8A%B8%EB%A6%AD-API%EB%A5%BC-%EC%9C%84%ED%95%9C-%EC%A7%80%EC%9B%90 
 

Horizontal Pod Autoscaling

쿠버네티스에서, HorizontalPodAutoscaler 는 워크로드 리소스(예: 디플로이먼트 또는 스테이트풀셋)를 자동으로 업데이트하며, 워크로드의 크기를 수요에 맞게 자동으로 스케일링하는 것을 목표로 한

kubernetes.io

https://github.com/openshift/service-idler

 

GitHub - openshift/service-idler: A controller for idling and unidling groups of scalable Kubernetes resources

A controller for idling and unidling groups of scalable Kubernetes resources - GitHub - openshift/service-idler: A controller for idling and unidling groups of scalable Kubernetes resources

github.com

 

 

 

 

 

수직적 파드 오토스케일링

1. 수직적 파드 오토스케일링의 필요성

1.1. 수평적 확장이 불가능한 경우

 

2. 방법

2.1. 파드 매니페스트 내 리소스 요청량 필드를 변경해 수행 가능

2.2. Vertical Pod Autoscaler 사용

 

[Vertical Pod Autoscaler]

Vertical Pod Autoscaler (VPA) frees the users from necessity of setting up-to-date resource limits and requests for the containers in their pods. When configured, it will set the requests automatically based on usage and thus allow proper scheduling onto nodes so that appropriate resource amount is available for each pod. It will also maintain ratios between limits and requests that were specified in initial containers configuration. It can both down-scale pods that are over-requesting resources, and also up-scale pods that are under-requesting resources based on their usage over time. Autoscaling is configured with a Custom Resource Definition object called VerticalPodAutoscaler. It allows to specify which pods should be vertically autoscaled as well as if/how the resource recommendations are applied. To enable vertical pod autoscaling on your cluster please follow the installation procedure described below.

https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler 
 

GitHub - kubernetes/autoscaler: Autoscaling components for Kubernetes

Autoscaling components for Kubernetes. Contribute to kubernetes/autoscaler development by creating an account on GitHub.

github.com

 

 

 

 

 

수평적 클러스터 노드 확장

1. 노드 확장의 필요성

1.1. 모든 노드가 한계에 도달해 더 이상 파드를 추가할 수 없을 경우

 

 

 

2. 클러스터 오토스케일러 소개

2.1. 기능 : 노드에 리소스가 부족해서 스케줄링할 수 없는 파드를 발견, 추가 노드를 자동으로 공급. 오랜 시간 사용률이 낮으면 노드 감소.

 

2.2. 추가 노드 요청

2.2.1. 스케줄러가 파드를 기존 노드에 스케줄링하지 못하는 현상이 발생

 

2.2.2. 클러스터 오토스케일러가 새로운 노드의 파드 수용 가능 여부를 확인

2.2.2.1. 수용 가능 노드 그룹이 하나일 경우, 클라우드 제공자가 새로운 노드를 그룹에 추가하도록 해당 노드 그룹 크기 증가

2.2.2.2. 수용 가능 노드 그룹이 둘 이상일 경우, 최적의 옵션을 선택. 설정 가능한 노드가 없을 경우 무작위 선택.

 

2.2.3. 클러스터 오토스케일러가 클라우드 제공자에 추가 노드 시작을 요청

 

2.3. 새로운 노드 시작

2.4. 해당 노드 kubelet이 API 서버에 접속해 노드 리소스를 만들어 노드를 등록

2.5. 파드를 해당 노드에 스케줄링

 

[Cluster Autoscaler]

Cluster Autoscaler is a tool that automatically adjusts the size of the Kubernetes cluster when one of the following conditions is true: there are pods that failed to run in the cluster due to insufficient resources. there are nodes in the cluster that have been underutilized for an extended period of time and their pods can be placed on other existing nodes.

https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler 
 

GitHub - kubernetes/autoscaler: Autoscaling components for Kubernetes

Autoscaling components for Kubernetes. Contribute to kubernetes/autoscaler development by creating an account on GitHub.

github.com

 

 

 

 

3. 노드 종료

3.1. 자동 노드 종료

3.1.1. 오토스케일러가 모든 노드에 요청된 CPU와 메모리를 모니터링해 수행

3.1.2. 오토스케일러가 모니터링 중 리소스 활용도가 낮은 노드를 '필요 없다'고 간주

 

3.1.3. 노드 중단 결정은 아래의 요인에 따라 진행

3.1.3.1. 해당 노드에서만 실행 중인 시스템 파드가 있다면 중단 불가 (데몬셋 등으로 인한 배포 제외)

3.1.3.2. 클러스터 오토스케일러가, 노드에서 실행 중인 파드가 다른 노드로 다시 스케줄링 될 수 있음을 알고 있는 경우만 반환 가능

 

3.1.4. 종료 노드 선택 후 스케줄링 불가 표시

3.1.5. 종료 예정 노드 내 실행 중인 파드를 모두 제거

3.1.6. 노드가 소속된 레플리카셋 혹은 타 컨트롤러에 의해 교체 파드 생성 및 남은 노드에 스케줄링 진행

 

 

 

3.2. 수동 노드 종료

3.2.1. 노드를 수동으로 스케줄링 불가 표시

3.2.1.1. kubectl cordon <node>

3.2.1.2. 스케줄링 금지 해제 명령 kubectl uncordon <node> 이전까지 금지 상태 유지

 

3.2.2. 노드를 수동으로 배출 (draining) = 스케줄링 불가 표시 + 해당 노드 내 실행 중인 모든 파드 종료. 

3.2.2.1. kubectl drain <node>

3.2.2.2. 스케줄링 금지 해제 명령 kubectl uncordon 이전까지 금지 상태 유지

 

 

 

 

클러스터 오토스케일러 활성화

클러스터 스케일 다운 내 서비스 중단 제한

노드 종료가 클러스터 오토스케일러 혹은 시스템 관리자로 진행될 경우 해당 노드 내 파드 제공 서비스 중단 불가 설정

 

1. PodDisruptionBudget 리소스

1.1. 파드 레이블 셀렉터와, 항상 사용 가능해야 하는 파드의 최소 최대 개수를 정의

1.2. 명령어 kubectl create pdb kubia-pdb --selelctor=app=kubia --min-available=3 ) 항상 3개 이상의 해당 레이블을 가진 인스턴스가 존재하도록 설정

1.3. min-available 값으로 정수가 아닌 백분율을 사용할 경우, 전체 파드 내 비율을 의미. 

1.4. maxUnavailable 값으로 일정 개수 이상 파드가 종료되지 않도록 지정 가능

[파드 disruption budgets]

쿠버네티스는 자발적인 중단이 자주 발생하는 경우에도 고 가용성 애플리케이션을 실행하는 데 도움이 되는 기능을 제공한다. 애플리케이션 소유자로써, 사용자는 각 애플리케이션에 대해 PodDisruptionBudget(PDB)을 만들 수 있다. PDB는 자발적 중단으로 일시에 중지되는 복제된 애플리케이션 파드의 수를 제한한다. 예를 들어, 정족수 기반의 애플리케이션이 실행 중인 레플리카의 수가 정족수 이하로 떨어지지 않도록 한다. 웹 프런트 엔드는 부하를 처리하는 레플리카의 수가 일정 비율 이하로 떨어지지 않도록 보장할 수 있다. 클러스터 관리자와 호스팅 공급자는 직접적으로 파드나 디플로이먼트를 제거하는 대신 Eviction API로 불리는 PodDisruptionBudget을 준수하는 도구를 이용해야 한다. 예를 들어, kubectl drain 하위 명령을 사용하면 노드를 서비스 중단으로 표시할 수 있다. kubectl drain 을 실행하면, 도구는 사용자가 서비스를 중단하는 노드의 모든 파드를 축출하려고 한다. kubectl 이 사용자를 대신하여 수행하는 축출 요청은 일시적으로 거부될 수 있으며, 도구는 대상 노드의 모든 파드가 종료되거나 설정 가능한 타임아웃이 도래할 때까지 주기적으로 모든 실패된 요청을 다시 시도한다. PDB는 애플리케이션이 필요로 하는 레플리카의 수에 상대적으로, 용인할 수 있는 레플리카의 수를 지정한다. 예를 들어 .spec.replicas: 5 의 값을 갖는 디플로이먼트는 어느 시점에든 5개의 파드를 가져야 한다. 만약 해당 디플로이먼트의 PDB가 특정 시점에 파드를 4개 허용한다면, Eviction API는 한 번에 1개(2개의 파드가 아닌)의 파드의 자발적인 중단을 허용한다. 파드 그룹은 레이블 셀렉터를 사용해서 지정한 애플리케이션으로 구성되며 애플리케이션 컨트롤러(디플로이먼트, 스테이트풀셋 등)를 사용한 것과 같다. 파드의 "의도"하는 수량은 해당 파드를 관리하는 워크로드 리소스의 .spec.replicas 를 기반으로 계산한다. 컨트롤 플레인은 파드의 .metadata.ownerReferences 를 검사하여 소유하는 워크로드 리소스를 발견한다. 비자발적 중단은 PDB로는 막을 수 없지만, 버짓은 차감된다. 애플리케이션의 롤링 업그레이드로 파드가 삭제되거나 사용할 수 없는 경우 중단 버짓에 영향을 준다. 그러나 워크로드 리소스(디플로이먼트, 스테이트풀셋과 같은)는 롤링 업데이트 시 PDB의 제한을 받지 않는다. 대신, 애플리케이션 업데이트 중 실패 처리는 특정 워크로드 리소스에 대한 명세에서 구성된다. Eviction API를 사용하여 파드를 축출하면, PodSpec의 terminationGracePeriodSeconds 설정을 준수하여 정상적으로 종료됨 상태가 된다.

https://kubernetes.io/ko/docs/concepts/workloads/pods/disruptions/ 
 

중단(disruption)

이 가이드는 고가용성 애플리케이션을 구성하려는 소유자와 파드에서 발생하는 장애 유형을 이해하기 원하는 애플리케이션 소유자를 위한 것이다. 또한 클러스터의 업그레이드와 오토스케일

kubernetes.io

 

 

 

 

추가 설명

[Immutable Server]

Automated configuration tools (such as CFEngine, Puppet, or Chef) allow you to specify how servers should be configured, and bring new and existing machines into compliance. This helps to avoid the problem of fragile SnowflakeServers. Such tools can create PhoenixServers that can be torn down and rebuilt at will. An Immutable Server is the logical conclusion of this approach, a server that once deployed, is never modified, merely replaced with a new updated instance.

https://martinfowler.com/bliki/ImmutableServer.html 
[AWS Auto Scaling]

AWS Auto Scaling은 애플리케이션을 모니터링하고 용량을 자동으로 조정하여, 최대한 저렴한 비용으로 안정적이고 예측 가능한 성능을 유지합니다. AWS Auto Scaling을 사용하면 몇 분 만에 손쉽게 여러 서비스 전체에서 여러 리소스에 대해 애플리케이션 규모 조정을 설정할 수 있습니다. 이 서비스는 간단하면서도 강력한 사용자 인터페이스를 제공하므로 이를 사용하여 Amazon EC2 인스턴스와 스팟 플릿, Amazon ECS 작업, Amazon DynamoDB 테이블 및 인덱스, Amazon Aurora 복제본 등 리소스에 대한 규모 조정 계획을 수립할 수 있습니다. AWS Auto Scaling을 사용하면 성능과 비용을 최적화하거나 둘 사이의 적절한 균형을 유지하기 위한 권장 사항을 활용해 간단하게 규모를 조정할 수 있습니다. 이미 Amazon EC2 Auto Scaling을 사용하여 Amazon EC2 인스턴스의 규모를 동적으로 조정하고 있는 경우, 이제 AWS Auto Scaling과 결합하여 다른 AWS 서비스의 추가 리소스를 조정할 수 있습니다. AWS Auto Scaling을 사용하면 항상 적시에 올바른 리소스가 애플리케이션에 할당됩니다.

https://aws.amazon.com/ko/autoscaling/ 
[What is Amazon EC2 Auto Scaling?]

Amazon EC2 Auto Scaling helps you ensure that you have the correct number of Amazon EC2 instances available to handle the load for your application. You create collections of EC2 instances, called Auto Scaling groups. You can specify the minimum number of instances in each Auto Scaling group, and Amazon EC2 Auto Scaling ensures that your group never goes below this size. You can specify the maximum number of instances in each Auto Scaling group, and Amazon EC2 Auto Scaling ensures that your group never goes above this size. If you specify the desired capacity, either when you create the group or at any time thereafter, Amazon EC2 Auto Scaling ensures that your group has this many instances. If you specify scaling policies, then Amazon EC2 Auto Scaling can launch or terminate instances as demand on your application increases or decreases.

Configuration templates
Your group uses a launch template, or a launch configuration (not recommended, offers fewer features), as a configuration template for its EC2 instances. You can specify information such as the AMI ID, instance type, key pair, security groups, and block device mapping for your instances. For more information, see Launch templates and Launch configurations.

https://docs.aws.amazon.com/autoscaling/ec2/userguide/what-is-amazon-ec2-auto-scaling.html 

Launch templates
A launch template is similar to a launch configuration, in that it specifies instance configuration information. It includes the ID of the Amazon Machine Image (AMI), the instance type, a key pair, security groups, and other parameters used to launch EC2 instances. However, defining a launch template instead of a launch configuration allows you to have multiple versions of a launch template.

https://docs.aws.amazon.com/autoscaling/ec2/userguide/LaunchTemplates.html 
[EKS > Auto Scaling]

Amazon EKS는 두 가지 자동 크기 조정 제품을 지원합니다. Kubernetes Cluster Autoscaler 및 Karpenter 오픈 소스 자동 크기 조정 프로젝트. Cluster Autoscaler는 AWS 크기 조정 그룹을 사용하는 반면 Karpenter는 Amazon EC2 플릿과 직접 작동합니다.

Kubernetes Cluster Autoscaler는 포드가 실패하거나 다른 노드로 다시 예약될 때 클러스터의 노드 수를 자동으로 조정합니다. Cluster Autoscaler는 일반적으로 클러스터에 배포로 설치됩니다. 리더 선출을 사용하여 고가용성을 보장할 수 있지만 확장은 한 번에 하나의 복제본으로만 수행됩니다.

https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/autoscaling.html 
[Graceful Shutdown과 SIGINT/SIGTERM/SIGKILL]

Graceful Shutdown이란 무엇인가?
프로그램이 종료될 때 최대한 side effect가 없도록 로직들을 잘 처리하고 종료하는 것을 말한다.

Gracueful Shutdown <-> Hard Shutdown
우아한 종료의 대척점에는 Hard Shutdown이 있다. 
- 코드를 커밋하고 푸시한 뒤 컴퓨터를 끄고 퇴근하는 것: graceful shutdown
- 그대로 컴퓨터를 바로 끄고 퇴근하는 것: hard shutdown
하고있던 작업을 적절히 마무리한 뒤 종료되는 것이 핵심이다. 비즈니스 로직을 해치고 싶지 않기 때문이다. 의도한 종료든 의도하지 않은 종료든 간에 최대한 side effect를 줄이고 싶기 때문이다. 

SIGINT/SIGTERM/SIGKILL
그러면 우아한 종료는 어떻게 구현하는가? 프로그램을 종료하라는 유닉스 신호를 catch하여 처리 로직을 하는 형태로 구현할 수 있다. 유닉스 신호는 유닉스 계열 등의 운영체제에서 사용하는 프로세스 간 통신의 일종이다. 프로그램 실행 중에 ctrl + c를 입력하면 SIGINT 시그널이 프로세스로 가게 되고, 대게 프로그램이 종료된다.

SIGTERM은 프로그램을 종료하는 일반적인 방법이다.
SIGINT는 유저가 직접 프로그램 종료를 지시했다는 것이 명확하다는 점에서 차이가 있다. SIGINT의 INT는 interrupt에서 온 것인데, 결과적으로 프로그램이 종료된다는 점에서는 SIGTERM과 다를 바 없다. SIGINT와 SIGTERM은 둘 다 catch가 가능하다. 프로그램은 각 시그널을 전송받았을 때 자신만의 로직을 처리할 수 있다. 현재 대부분의 프로그램들은 SIGINT를 받았을 때 프로그램을 종료하는 형태로 구현되어있다.

SIGKILL은 말 그대로 프로세스를 kill 한다. catch가 불가능하다. 들어온 요청을 다 처리하고 종료한다든가, db에 유저가 작성중이던 텍스트 데이터를 저장한다든가 같은 로직을 처리하는 것이 불가능하다. SIGKILL에 대한 시그널 핸들러는 만들 수 없다.

출처: https://2kindsofcs.tistory.com/53 [세상에는 두 종류의 cs가 있습니다.]