1. HPA 알고리즘
replica 계산 알고리즘
desired_replica = ceil(current_replica * (현재 값/목표 값))
위의 알고리즘을 이해하기 위해서 시나리오를 준비했습니다.
시나리오 1
응용 프로그램에 일부 비즈니스 요구 사항이 있고 물리적 제한을 기반으로 이상적인 CPU/메모리 수를 제시한다고 가정합니다. 작업자 노드에 대해 대상 CPU를 60% 미만으로 유지하려고 합니다. 그런 다음 트래픽이 급증하여 현재 사용률이 90%에 도달했습니다. 배포 개체에 3개의 복제본이 정의되어 있고 포드에 과부하가 걸립니다. 알고리즘을 사용하여 원하는 포드 수를 찾을 수 있습니다.
목표 CPU 사용률: 60%
현재 사용률: 90%
현재 포드: 3
원하는 포드 = ceil(current_pods * (현재 값/목표 값))
원하는 포드 = ceil(3*(.9/.6)) = 5
이 시나리오에서 HPA 컨트롤러는 배포의 복제본을 5개로 변경하고 스케줄러는 2개의 포드를 더 추가하여 요구 사항을 업데이트합니다.
시나리오 2
일정 기간 후에 트래픽이 감소했고 현재 사용률이 20%로 떨어졌다고 가정해 보겠습니다. 추가 복제본이 자동으로 줄어들기를 바랍니다. HPA 컨트롤러가 어떻게 우리의 소원을 들어주는지 봅시다.
대상 CPU 사용률: 60%
현재 사용률: 20%
현재 포드: 5
원하는 포드 = ceil(5*(.3/.6)) = 2
여기에서는 2개의 복제본만 있으면 충분하다고 판단하고 배포 컨트롤러에 이 수로 줄이도록 지시합니다. 그러나 배포 개체의 최소 복제본 수는 3입니다. 따라서 kubernetes는 이를 존중하고 복제본 수를 5에서 3으로 줄입니다.
2. k8s 에서의 오토스케일링
1) Cluster Autoscaler
- 클러스터 자동 확장 처리 알고리즘이 Pending Pod를 확인합니다.
- 클러스터 자동 확장 처리에 의해 새로운 Worker Node를 요청합니다.
- Kubernetes는 기본 인프라(ex, GCP, AWS, Azur)에 의한 프로비저닝된 새 노드를 감지합니다.
- Kubernetes 스케쥴러는 보류 중인 포드를 새 노드에 할당 합니다.
2) VPA (Vertical Pod Autoscaling)
VPA(Vertical Pod Autoscaling)는 컨테이너 리소스가 과소 또는 과도하게 활용되지 않도록 합니다. 최적화된 CPU 및 메모리 요청/제한 값을 권장하고 클러스터 리소스가 효율적으로 사용되도록 자동으로 업데이트할 수도 있습니다.
vpa는 pod의 resource 사용량에 맞게 resource request를 조절해서 pod가 node에 스케쥴링될때 적절한 크기의 resouce를 할당받을 수 있도록 합니다.
vpa는 hpa와 마찬가지로 metric server를 통해 pod들의 resource 사용량을 관찰합니다. 이 resource사용량이 일정기준 이상으로 늘어나면 pod를 scale out하고, 그 반대일때는 scale in합니다.
VPA github
resources:
requests:
memory: {{ .Values.minMem }}
cpu: {{ .Values.minCpu }}
limits:
memory: {{ .Values.maxMem }}
cpu: {{ .Values.maxCpu }}
vpa는 deployment의 yaml 파일에서 request, limit의 값을 비율에 맞춰서 업데이트를 수행합니다.
apiVersion: "autoscaling.k8s.io/v1beta2"
kind: VerticalPodAutoscaler
metadata:
name: test-vpa
spec:
targetRef:
apiVersion: "apps/v1"
kind: Deployment
name: test
updatePolicy:
updateMode: "Auto"
resourcePolicy:
containerPolicies:
- containerName: '*'
minAllowed:
cpu: 100m
memory: 50Mi
maxAllowed:
cpu: 1
memory: 500Mi
controlledResources: ["cpu", "memory"]
- Auto mode : VPA는 Pod의 리소스 사용량을 일정 주기 이상 모니터링 한 후에, 그 Metric을 기반으로, Pod resource의 request값을 변경해주는 방식.
- Manual mode : VPA가 직접 request 내용을 변경하지 않고, 적절하게 필요한 request양을 추천해줍니다.
# kubectl get vpa [vpa name] -o yaml
recommendation:
containerRecommendations:
- containerName: my-rec-container
lowerBound:
cpu: 315m
memory: 262144k
target:
cpu: 587m
memory: 262144k
Uncapped target:
cpu: 587m
memory: 262144k
upperBound:
cpu: 1000m
memory: 500Mi
- Target: VPA에서 포드에 적용할 컨테이너에 대한 권장 CPU 요청 및 메모리 요청입니다.
- Uncapped Target: VPA 정의에서 상한/하한을 구성하지 않은 경우 컨테이너에 대한 권장 CPU 요청 및 메모리 요청입니다.
- lowerBound: 컨테이너에 대해 권장되는 최소 CPU 요청 및 메모리 요청입니다.
- upperBound: 컨테이너에 대해 권장되는 최대 CPU 요청 및 메모리 요청입니다.
3) HPA (Horizontal Pod Autoscaling)
HPA는 리소스 메트릭 API에서 포드당 리소스 메트릭(예: CPU, 메모리)을 가져오고 모든 대상 포드의 평균 값을 기반으로 현재 메트릭 값을 계산합니다. 현재 메트릭 값을 HPA 사양에 지정된 대상 메트릭 값과 비교하고 원하는 복제본 수를 확장하는 데 사용되는 비율을 생성합니다.
- metric-server 로부터 생성된 pod의 metric을 기반으로 replica / Deployment / statefulset 과 같은 리소스에 대해 오토 스케일링이 가능하다.
- HPA는 쿠버네티스 API리소스 및 컨트롤러로 구현됩니다.
HPA Configuration
- behavior
behavior: scaleDown: stabilizationWindowSeconds: 300 ( 기본 5분 ) policies: - type: Percent value: 10 periodSeconds: 30 - type: Pods value: 1 periodSeconds: 120 selectPolicy: Min- stabilizationWindowSeconds : 안정화 윈도우는 메트릭이 계속해서 변할 때 replica의 개수가 너무 자주 변경되지 않도록 제한하기 위해서 사용.
- 스케일링이 일어난 후, 5분동안 수집된 metric들 중에 가장 큰 수치 변화를 감지.
- 값이 0이라면, scaling 계산을 바로 하자마자 작업 시작.
- policy : percent, pods로 scale에 대한 정책 정의
- percent는 해당 시간동안에 퍼센트만큼을 증가/감소
- pods는 해당 value만큼 갯수를 증가/감소
- select policy에 의해 2개 설정중 더 작은(min)값 선택
- 축소하는 동안 last 동안 가장 안전한(가장 큰) “desiredReplicas” 번호를 선택해야 합니다
- 확장하는 동안 last 동안 가장 안전한(가장 작은) “desiredReplicas” 번호를 선택해야 합니다
- metric
- resource 정의 메트릭 : CPU, MEMORY
- type: Resource resource: name: cpu target: type: Utilization averageUtilization: 50- metric-server에서 제공하는 pod의 resource에 대한 metric이고 주로 사용
- 사용자 정의 메트릭 : 네트워크 트래픽
type: Pods pods: metric: name: packets-per-second target: type: AverageValue averageValue: 1k- metric-server가 아닌 외부의 metric solution 공급업체(prometheus) 에서 제공하는 metric
- https://github.com/kubernetes/metrics/blob/master/IMPLEMENTATIONS.md#custom-metrics-api
- Object 메트릭
type: Object object: metric: name: requests-per-second describedObject: apiVersion: networking.k8s.io/v1beta1 kind: Ingress name: main-route target: type: Value value: 2k
2. HPA custom metric 적용
HPA를 사용하게 되면, CPU, Memory 이외의 Custom Metric을 이용하여 오토스케일링을 구성하고 싶을때가 있습니다. 커스텀 메트릭을 구성하기 위해서는 Prometheus Adapter를 별도로 설치해야 합니다.- custom metric을 사용하기 위해서는 prometheus-adapter 리소스를 사용하여 custom.metrics.k8s.io/v1beta1에 사용자 지정 어플리케이션 메트릭을 노출합니다. (kubernetes v1.16 이상)
- prometheus adapter는 custom metrics를 별도의 API인 Aggregation Layer에 등록한 뒤, 원하는 모니터링 데이터를 Prometheus로부터 PromQL 형식을 통해 가져와 Custom Metrics API에 제공하는 역할을 합니다.
- Prometheus Adapter가 Prometheus에 쿼리를 요청한 후, Kubernetes API에 해당 데이터를 등록하여 HPA에 사용할 수 있게 하는 방식
설치 방법
Prometheus Adapter github 프로메테우스 공식 헬름 차트를 통하여 설치를 진행합니다. ReadMe를 참고하면 설치를 진행할수 있고,, values.yaml 파일의 수정을 통해서 설치를 진행합니다.prometheus:
url: http://prometheus-server
port: 0
image:
tag: latest
rules:
custom:
- seriesQuery: 'container_network_receive_packets_total{namespace!="",pod!=""}'
resources:
overrides:
namespace: {resource: "namespace"}
pod: {resource: "pod"}
name:
matches: "container_network_receive_packets_total"
as: "network_in"
metricsQuery: <<.Series>>{<<.LabelMatchers>>}
Custom Metric 조회
- prometheus-adapter 리소스를 사용하여 등록하면, custom.metrics.k8s.io/v1beta1애 사용자 지정 메트릭을 노출 시킵니다.
$ kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1/namespaces/test-ns/pods/test-admin-74b4578f75-qvd7j/network_in | jq .
{
"kind": "MetricValueList",
"apiVersion": "custom.metrics.k8s.io/v1beta1",
"metadata": {
"selfLink": "/apis/custom.metrics.k8s.io/v1beta1/namespaces/link-me/pods/alpha-lbw-admin-74b4578f75-qvd7j/network_in"
},
"items": [
{
"describedObject": {
"kind": "Pod",
"namespace": "test-ns",
"name": "test-admin-74b4578f75-qvd7j",
"apiVersion": "/v1"
},
"metricName": "network_in",
"timestamp": "2021-10-13T06:34:48Z",
"value": "5367472m",
"selector": null
}
]
}
3. 마치며..
쿠버네티스는 확실히 유연한 플랫폼인것 같습니다. 사용자가 지정한대로 resource 효율화를 달성하고 최적화의 개념으로 서비스를 안정적으로 운영할 수 있게 도움을 주는 것 같습니다. HPA를 아직 필자도 실서비스에 도입을 한것은 아니지만, 몇가지 MSA도입을 하게 되면 확실히 효과는 클 것으로 보고 있습니다. 나중에 도입을 하고나서 실제로 운영상에 도움이 되었는지 후기를 작성하도록 하겠습니다.4. 참고
[K8S] Kubernetes의 HPA를 활용한 오토스케일링(Auto Scaling) Discussion on Horizontal Pod Autoscaler with a demo on local k8s cluster https://haereeroo.tistory.com/22?category=1184037 Autoscaling in Kubernetes using HPA and VPA함께 보면 좋은 글
- [DevOps] k8s monitoring with Datadog
- [DevOps] k8s Log 수집 시스템 구성
- [DevOps] Nginx Rate Limit
- [DevOps] Hubot 적용기
새 글이 올라오면 Threads @wonizz.ai 에도 올립니다. 팔로우해 두면 피드에서 바로 볼 수 있습니다.