쿠버네티스는 한정된 리소스를 유연하게 사용하기 위해 Auto Scaling 기능을 지원하고 있습니다.
Auto Scaling은 각 리소스에 대한 Metric 정보을 기반으로 동작하며 데이터를 수집하기 위해선 먼저 클러스터에 Metric Server가 구성되어 있어야 합니다.
Metric Server 배포하기
메트릭 서버는 클러스터 내 존재하는 Pod의 메트릭 정보를 실시간으로 수집해서 Kubernetes API 서버에 전달하는 역할을 수행합니다.
만약 메트릭 서버가 설치되지 않았다면 아래와 같이 'Metrics API not available'과 같은 에러가 표시됩니다.
설치 방법은 간단합니다.
아래 명령어를 통해 메트릭 서버 구성요소를 배포해줍니다.
$ kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
메트릭 서버의 동작 과정은 아래와 같습니다.
설치가 완료되고 나면 정상적으로 메트릭 조회가 가능합니다.
추가로 아래 명령어를 통해 메트릭 서버가 수집한 데이터를 확인할 수 있습니다.
정상적으로 메트릭이 수집되는 것을 확인했으니 이제 본격적으로 Auto Scaling에 대해 알아보겠습니다.
Auto Scaling에는 크게 Pod Auto Scaling과 Node Auto Scaling이 있습니다.
Pod Auto Scaling
Pod는 쿠버네티스에서 생성 가능한 가장 작은 컴퓨팅 단위로 주로 컨테이너의 그룹을 의미합니다.
실제 애플리케이션이 Pod 위에서 구동되기 때문에 수요에 맞추어 Pod를 스케일링 하는 것이 굉장히 중요합니다.
스케일링은 크게 Scale In-Out(개수), Scale Up-Down(용량)이 있으며 쿠버네티스에선 각각 HPA(Horizontal Pod AutoScaling)과 VPA(Vertical Pod AutoScaling)으로 구현됩니다.
HPA(Horizontal Pod AutoScaling)
Horizontal은 '수평의' 라는 뜻으로 트래픽이 증가함에 따라 아래 그림과 같이 Pod의 개수를 늘려나가는 방식입니다.
HPA의 동작방식에 대해 살펴보겠습니다.
먼저 쿠버네티스에선 Pod의 개수를 관리할 수 있도록 ReplicaSet, Deployment, StatefulSet과 같은 오브젝트를 제공합니다.
HPA를 설정하면 Horizontal Pod AutoScaler가 레플리카셋의 크기를 조정할 수 있도록 AutoScaling 프로세스를 간헐적으로 실행하게 게 됩니다.
실행 주기는 kube-controller-manager의 --horizontal-pod-autoscaler-sync-period 파라미터 값에 따르며 default 15초입니다.
각 주기마다 컨트롤러 매니저는 정의된 메트릭에 대해 리소스 사용률을 질의합니다.
메트릭은 크게 CPU와 Memory값이 있으며 custom 메트릭을 사용할 수도 있습니다.
(참고링크: Scaling on custom metrics)
kubectl autoscale deployment php-apache `#평균 cpu 사용율` \
--cpu-percent=50 \
--min=1 `#최소값` \
--max=10 `#최댓값`
Pod의 개수는 아래 알고리즘에 의해 결정됩니다.
원하는 레플리카 수 = ceil[현재 레플리카 수 * ( 현재 메트릭 값 / 원하는 메트릭 값 )]
예를 들어 현재 CPU 메트릭 값이 200m이고 원하는 값이 100m 인 경우 200 / 100 = 2 이므로 replica 수는 2배가 됩니다.
현재 메트릭 값이 50m이라면 50 / 100 = 0.5 이므로 replica 수는 반으로 줄게 됩니다.
만약 값이 1.0에 가깝다면 스케일링이 동작하지 않으며 이 오차 범위는 --horizontal-pod-autoscaler-tolerance 플래그를 지정하여 관리할 수 있습니다.(default 0.1)
테스트를 통해 부하 발생 시 실제로 pod의 개수가 증가하는지 살펴보도록 하겠습니다.
먼저 pod를 배포해줍니다.
> deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: php-apache
spec:
selector:
matchLabels:
run: php-apache
replicas: 1
template:
metadata:
labels:
run: php-apache
spec:
containers:
- name: php-apache
image: registry.k8s.io/hpa-example
ports:
- containerPort: 80
resources:
limits:
cpu: 500m
requests:
cpu: 200m
$ kubectl apply -f deployment.yaml
deployment.apps/php-apache created
service를 배포해줍니다.
> service.yaml
apiVersion: v1
kind: Service
metadata:
name: php-apache
labels:
run: php-apache
spec:
ports:
- port: 80
selector:
run: php-apache
$ kubectl apply -f service.yaml
service/php-apache created
hpa를 배포해줍니다.
> hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: php-apache
namespace: default
spec:
maxReplicas: 10
metrics:
- resource:
name: cpu
target:
averageUtilization: 50
type: Utilization
type: Resource
minReplicas: 1
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: php-apache
$ k apply -f hpa.yaml
horizontalpodautoscaler.autoscaling/php-apache created
배포된 hpa 리소스를 보시면 타겟에 대한 메트릭 기준 값, 최소/최대 Pod 개수 등을 확인할 수 있습니다.
k get hpa -A
NAMESPACE NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
default php-apache Deployment/php-apache 0%/50% 1 10 1 10s
이제 service에 부하를 주어 hpa가 정상적으로 동작하는지 확인해보겠습니다.
아래는 loop를 돌면셔 php-apache 서비스를 호출하는 pod를 생성하는 명령어입니다.
kubectl run -i --tty load-generator --rm --image=busybox:1.28 --restart=Never -- /bin/sh -c "while sleep 0.01; do wget -q -O- http://php-apache; done"
hpa를 모니터링하면서 실제 부하가 50%를 넘어가는 것을 확인합니다.
부하가 발생하면 pod 개수가 자동으로 scale out 되는 것을 확인할 수 있습니다.
VPA(Vertical Pod AutoScaling)
HPA를 통해 Pod의 개수가 수평적으로 확장되는 것을 확인했습니다.
이제 VPA를 통해 Pod의 크기가 수직 확장되는 것을 확인해볼 차례입니다.
Vertical은 '수직의' 라는 뜻으로 트래픽이 증가함에 따라 아래 그림과 같이 Pod의 크기를 늘리는 방식입니다.
VPA의 동작방식을 알아보겠습니다.
HPA에 Horizontal Pod AutoScaler가 pod의 메트릭을 추적하고 있다면 VPA에서는 Vertical Pod AutoScaler가 pod의 메트릭을 추적합니다.
만약 pod의 리소스가 부족하다면 pod를 Restart하여 리소스를 증가시킵니다.
테스트를 통해 pod의 리소스가 VPA에 의해 실제로 변화하는지 살펴보겠습니다.
먼저 VPA는 현재 베타 기능이기 때문에 Kubernetes 클러스터에서 기본 제공되지 않습니다.
따라서 VPA의 git 저장소에서 소스코드를 직접 다운로드 받아 설치해주셔야 합니다.
$ git clone https://github.com/kubernetes/autoscaler.git
다운로드 후에는 아래 경로의 스크립트를 실행하면 필요한 오브젝트가 구성됩니다.
./autoscaler/vertical-pod-autoscaler/hack/vpa-up.sh
vpa pod를 확인하면 admission-controller, recommender, updater 총 세 개의 pod가 생성된 것을 확인할 수 있습니다.
Pod가 VPA에 의해 Recreate 되는 과정은 아래와 같으며 각 Component가 어떤 역할을 하는지 보겠습니다.
Recommender
-> Metric Server로부터 pod의 메트릭 값을 읽어들여 적합한 리소스 값을 VPA에게 recommend하는 역할
Admission Controller
-> pod의 resource.request를 수정
Updater가 기존 pod를 종료시키면 kubernetes controller가 pod를 다시 생성하며 이때 Admission Controller가 mutant webhook으로 pod request를 최적값으로 수정합니다.
Updater
Recommender가 계산한 최적값에 따라서 다시 시작해야 할 pod를 결정하는 역할
예제 애플리케이션을 통해 테스트를 진행해보겠습니다.
먼저 아래 경로에서 예제 yaml 파일을 배포합니다.
kubectl apply -f autoscaler/vertical-pod-autoscaler/examples/hamster.yaml
yaml 파일 내용을 확인해보면
1. name이 hamster인 Deployment를 target으로 참조하는 VPA와
2. name이 hamster이고 replicas가 2인 deployment를 각각 정의해두었습니다.
vpa pod를 확인해보면 target pod의 최적값을 확인할 수 있습니다.
실제 deployment에 기재된 request 값과 VPA의 최적값이 다르기 때문에 pod가 restart 되는 것을 확인합니다.
이벤트를 좀 더 자세하게 확인하고 싶다면 kubectl get events를 사용할 수 있습니다.
적용만 해놓으면 리소스를 자동으로 할당해주기 때문에 간편해보이지만 VPA는 몇가지 알려진 제약사항이 있습니다. (Github 링크)
- Whenever VPA updates the pod resources, the pod is recreated, which causes all running containers to be recreated. The pod may be recreated on a different node.
- VPA cannot guarantee that pods it evicts or deletes to apply recommendations (when configured in Auto and Recreate modes) will be successfully recreated. This can be partly addressed by using VPA together with Cluster Autoscaler.
- VPA does not update resources of pods which are not run under a controller.
- Vertical Pod Autoscaler should not be used with the Horizontal Pod Autoscaler (HPA) on CPU or memory at this moment. However, you can use VPA with HPA on custom and external metrics.
- The VPA admission controller is an admission webhook. If you add other admission webhooks to your cluster, it is important to analyze how they interact and whether they may conflict with each other. The order of admission controllers is defined by a flag on API server.
- VPA reacts to most out-of-memory events, but not in all situations.
- VPA performance has not been tested in large clusters.
- VPA recommendation might exceed available resources (e.g. Node size, available size, available quota) and cause pods to go pending. This can be partly addressed by using VPA together with Cluster Autoscaler.
- Multiple VPA resources matching the same pod have undefined behavior.
주된 내용은 pod가 restart되며 다른 노드에 pod가 생성될 수 있다는 점, HPA와 함께 사용하면 안되다는 점, 그리고 대규모 클러스터에서 완벽히 테스트되지 않았다는 점 등이 있습니다.
이 중에서 VPA, HPA를 왜 함께 사용하면 안되는지 궁금했습니다.
결국은 리소스의 평균 사용률을 기반으로 auto scaling 할 때 임계값에 도달하면 VPA와 HPA가 동시에 이벤트를 발생시켜서 충돌이 발생할 수 있다는 게 핵심인 것 같습니다.
이와 관련하여 discussion한 내용이 있는데.. 이해가 안가서 이건 차차 정리해놓아야겠네요
- https://github.com/kubernetes/autoscaler/issues/6060
- https://github.com/kubernetes/autoscaler/issues/6247
Pod Auto Scaling만으로는 쿠버네티스의 스케일링을 완벽히 수행하기에 한계가 있기 때문에 이제는 Node Auto Scaling을 알아야 합니다.
Node Auto Scaling은 쿠버네티스 Auto Scaling 2편에서 이어 작성하도록 하겠습니다.
'Kubernetes' 카테고리의 다른 글
쿠버네티스 Auto Scaling #2 (CA, Karpenter) (1) | 2024.03.11 |
---|---|
kubernetes에 metrics-server 설치하기 (0) | 2022.10.06 |
Helm 인강 정리 (0) | 2021.10.08 |
Helm Chart를 이용하여 nginx 설치하기 (0) | 2021.10.08 |
Helm이란? (0) | 2021.10.01 |