해당 글에서는 EKS Autoscaling에 대해서 학습한 내용을 정리합니다.
HPA부터, KEDA, VPA, Karpenter까지 알아보겠습니다.
애플리케이션이 커지고 트래픽이 증가함에 따라, Kubernetes 클러스터의 리소스 최적화가 필요하게 됩니다. 이때 유용하게 활용되는 것이 바로 Horizontal Pod Autoscaler(HPA) 입니다.
Horizontal Pod Autoscaler(HPA) 는 Kubernetes에서 Pod의 수를 자동으로 확장하거나 축소하는 기능을 제공합니다.
HPA는 클러스터 내에서 리소스의 사용량을 모니터링하고, 설정된 목표 값에 맞게 Pod 수를 자동으로 조정합니다. HPA는 다음과 같은 방식으로 동작합니다.
메트릭 수집: HPA는 Kubernetes Metrics Server나 외부 메트릭 시스템을 사용하여 클러스터 리소스의 메트릭을 수집합니다. CPU 사용량, 메모리 사용량 등 다양한 메트릭을 모니터링할 수 있습니다.
목표 설정: 사용자는 HPA를 설정할 때 목표로 삼을 메트릭을 지정합니다. 예를 들어, CPU 사용량이 80%를 초과하면 Pod의 수를 늘리도록 설정할 수 있습니다.
스케일링 결정: HPA는 주기적으로 메트릭을 확인하고, 설정된 목표 값에 도달하면 자동으로 Pod의 수를 확장하거나 축소합니다.
HPA는 기본적으로 Deployment 또는 ReplicaSet에 적용되어 해당 리소스의 Pod 수를 자동으로 조정합니다. HPA를 설정하려면 "kubectl autoscale" 명령을 사용하여 리소스의 스케일링을 정의할 수 있습니다.
cat << EOF > php-apache.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: php-apache
spec:
selector:
matchLabels:
run: php-apache
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
---
apiVersion: v1
kind: Service
metadata:
name: php-apache
labels:
run: php-apache
spec:
ports:
- port: 80
selector:
run: php-apache
EOF
kubectl apply -f php-apache.yaml
# 확인
kubectl exec -it deploy/php-apache -- cat /var/www/html/index.php
...
HPA는 Kubernetes Metrics Server에 의존하여 리소스 메트릭을 수집합니다. 따라서 HPA를 사용하려면 먼저 Metrics Server를 클러스터에 설치해야 합니다.
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.5.0/components.yaml
HPA를 생성하려면 kubectl autoscale 명령을 사용하여, CPU 또는 메모리 사용량을 기준으로 자동으로 스케일링을 설정할 수 있습니다.
예를 들어, CPU 사용량이 50%를 초과할 경우 Pod 수를 확장하는 HPA를 생성하는 방법은 아래와 같습니다.
kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10
위 명령은 my-app이라는 Deployment의 Pod 수를 1에서 10 사이로 조정하며, CPU 사용량이 50%를 초과할 경우 Pod 수를 확장합니다.
HPA 리소스의 상태를 확인하려면 다음 명령을 사용하여 현재 설정된 HPA의 상태를 모니터링할 수 있습니다.
kubectl get hpa
이 명령은 현재 클러스터에서 실행 중인 HPA 리소스를 보여주며, 각 HPA가 관리하는 Deployment와 현재 Pod 수, CPU 사용량 등 중요한 메트릭을 확인할 수 있습니다.
K8s를 운영하며, 리소스 기반으로 AutoScaling을 하는 경우도 있겠지만, 때로는 이벤트 기반의 AutoScaling이 필요할 수 있습니다.
KEDA는 Kubernetes Event-Driven Autoscaling의 약자로, Kubernetes에서 이벤트 기반으로 애플리케이션의 스케일링을 관리하는 오픈소스 프로젝트입니다.
KEDA는 외부 이벤트나 메트릭을 기준으로 자동으로 스케일링을 수행하는데, KEDA가 지원하는 이벤트 소스로는 메시지 큐, 이벤트 스트림 또는 HTTP 요청 등이 있습니다. KEDA는 이들 이벤트 소스를 통해 클러스터 리소스의 자동 확장 및 축소를 관리하며, Kubernetes의 HPA와 잘 통합되어 작동합니다.

KEDA는 다음과 같은 기능을 제공합니다.
이벤트 기반 스케일링: HPA는 CPU 사용량이나 메모리 사용량을 기반으로 스케일링을 하지만, KEDA는 큐 메시지의 수, 외부 이벤트(예: Kafka, Azure Queue, AWS SQS 등)에 따라 스케일링할 수 있습니다.
Custom Metrics: KEDA는 Kubernetes Custom Metrics API와 연동되어, 애플리케이션의 요구 사항에 맞는 다양한 메트릭을 사용하여 리소스를 자동으로 확장하거나 축소할 수 있습니다.
자동 스케일링: KEDA는 스케일링 트리거에 따라 자동으로 Pod 수를 조정하고, Kubernetes의 리소스 요구 사항을 관리합니다.
이번 실습에서는 Azure Queue를 사용하여 KEDA로 이벤트 기반 Autoscaling을 설정하는 방법을 살펴보겠습니다.
먼저, KEDA를 Kubernetes 클러스터에 설치해야 합니다. KEDA는 Helm을 사용하여 쉽게 설치할 수 있습니다.
# Helm 차트 레포지토리 추가
helm repo add kedacore https://kedacore.github.io/charts
# KEDA 설치
helm install keda kedacore/keda
KEDA는 다양한 이벤트 소스를 지원하지만, 여기서는 Azure Queue를 예로 들어 실습을 진행하겠습니다. Azure Storage Queue를 사용하여 큐의 길이에 따라 Pod 수를 스케일링합니다.
Azure에서 Storage Queue를 생성하고, 연결 문자열을 얻습니다.
Kubernetes 클러스터에 Azure Queue에 대한 정보를 설정합니다.
kubectl create secret generic azure-queue-secret \
--from-literal=azurestorageconnectionstring="Your_Azure_Connection_String"
KEDA는 ScaledObject 리소스를 사용하여 스케일링 트리거를 정의합니다. 여기서는 Azure Queue의 길이에 따라 자동으로 Pod 수를 확장하거나 축소하는 설정을 진행합니다.
apiVersion: keda.k8s.io/v1alpha1
kind: ScaledObject
metadata:
name: my-app-scaledobject
namespace: default
spec:
scaleTargetRef:
name: my-app-deployment
triggers:
- type: azure-queue
metadata:
queueName: my-queue
queueLength: "5"
authenticationRef:
name: azure-queue-secret
위 설정은 Azure Queue의 my-queue 큐 길이가 5개 이상일 경우 my-app-deployment의 Pod 수를 확장하도록 KEDA를 설정하는 예시입니다.
ScaledObject를 Kubernetes에 적용한 후, 자동으로 스케일링되는지 확인할 수 있습니다.
kubectl apply -f scaledobject.yaml
kubectl get hpa
KEDA는 Azure Queue의 길이를 모니터링하면서, 큐에 메시지가 5개 이상 쌓일 경우 자동으로 Pod 수를 확장합니다.
두 오토스케일링 방법의 차이점은 다음과 같습니다.

VPA는 Pod의 리소스를 수평적으로 확장하는 HPA와는 달리, 수직적으로 리소스를 조정합니다. 즉, Pod의 수를 변경하는 것이 아니라 Pod에 할당된 리소스(예: CPU, 메모리)의 양을 조정합니다.
VPA는 Pod의 리소스를 모니터링하고, 실제 리소스 사용량을 기반으로 적정 리소스를 자동으로 계산하여 리소스를 할당합니다. VPA는 다음과 같은 방식으로 동작합니다.

리소스 사용량 모니터링: VPA는 Kubernetes Metrics Server나 다른 메트릭 수집 도구를 사용하여 Pod의 리소스 사용량(CPU, 메모리 등)을 모니터링합니다.
리소스 요구사항 계산: VPA는 리소스 사용 패턴을 기반으로 Pod가 필요한 리소스 양을 예측하고, 이를 기반으로 Pod의 리소스 요청을 자동으로 조정합니다.
리소스 조정: 리소스 사용량이 설정된 한계를 초과하거나 미치지 못하는 경우, VPA는 Pod에 할당된 리소스를 수정합니다. Pod를 재시작하여 새로운 리소스 설정을 적용할 수도 있습니다.
Kubernetes 클러스터에서 VPA를 사용하기 위해서는 Vertical Pod Autoscaler 리소스를 생성해야 합니다.
VPA를 Kubernetes 클러스터에 설치하려면, 먼저 VPA 관련 리소스를 배포해야 합니다.
# VPA CRDs와 리소스를 배포
kubectl apply -f https://github.com/kubernetes/autoscaler/releases/download/release-1.21.0/vertical-pod-autoscaler-crd.yaml
kubectl apply -f https://github.com/kubernetes/autoscaler/releases/download/release-1.21.0/vertical-pod-autoscaler-rbac.yaml
VPA를 적용할 리소스를 정의하는 VerticalPodAutoscaler 리소스를 생성합니다.
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: my-app-vpa
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
updatePolicy:
updateMode: "Auto"
위 YAML 파일에서 updateMode는 리소스가 자동으로 조정되도록 설정합니다. VPA는 my-app Deployment의 리소스를 자동으로 조정하고, 리소스 변경을 적용합니다.
VPA 리소스를 적용한 후에는 VPA의 상태를 확인하여 리소스가 자동으로 변경되는지 모니터링할 수 있습니다.
kubectl get vpa
위 명령을 통해 VPA가 정상적으로 작동하는지, 어떤 리소스가 어떻게 변경되었는지 확인할 수 있습니다.
Karpenter는 Kubernetes 환경에서 클러스터의 리소스를 자동으로 관리하고 최적화하는 오픈소스로 주로 노드 자동 스케일링을 제공합니다.
Karpenter는 자동화된 노드 프로비저닝과 최적화된 리소스 관리를 목표로 작동합니다.
주요 동작 원리는 다음과 같습니다
리소스 수요에 따른 노드 생성: Karpenter는 클러스터 내에서 리소스가 부족하거나 새로운 Pod를 스케줄해야 할 때, 그에 맞는 노드를 자동으로 생성합니다. 예를 들어, 새로운 Pod가 특정 리소스를 요구할 경우, Karpenter는 클러스터 내에서 해당 요구 사항을 충족할 수 있는 노드를 빠르게 생성합니다.
리소스 최적화: Karpenter는 클러스터의 노드 리소스를 동적으로 관리합니다. 노드가 과잉 프로비저닝되어 있을 경우, Karpenter는 불필요한 노드를 자동으로 삭제하여 리소스를 최적화합니다. 반대로 리소스가 부족하면, 필요한 자원을 즉시 추가합니다.
유연한 프로비저닝: Karpenter는 노드 프로비저닝에 있어 유연성을 제공합니다. 예를 들어, 특정 인스턴스 유형이나 크기를 지정하는 것 외에도, Karpenter는 클라우드 제공자의 리소스를 자동으로 최적화하여 리소스의 과잉 또는 부족을 방지합니다.
자동 리소스 삭제: 클러스터의 리소스가 더 이상 필요 없을 때, Karpenter는 자동으로 리소스를 삭제하여 비용을 절감합니다. 사용자가 필요하지 않은 리소스가 남아있지 않도록 보장합니다.
Karpenter를 설정하는 과정은 매우 간단하고 직관적입니다. Karpenter는 Kubernetes와 긴밀하게 통합되어 있으며, 클라우드 제공자의 리소스를 효율적으로 관리할 수 있도록 돕습니다. Karpenter를 Kubernetes 클러스터에 설정하는 방법은 다음과 같습니다.
Karpenter를 설치하려면 Helm을 사용하여 Kubernetes에 배포합니다. Helm 차트를 사용하면 손쉽게 Karpenter를 배포하고 관리할 수 있습니다.
# Karpenter Helm 차트 레포지토리 추가
helm repo add karpenter https://charts.karpenter.sh
# Helm 차트를 사용하여 Karpenter 설치
helm install karpenter karpenter/karpenter --namespace karpenter --create-namespace
Karpenter는 Provisioner 리소스를 사용하여 클러스터의 리소스를 프로비저닝합니다. 이 리소스는 클러스터의 노드 풀을 관리하는 방식과 리소스 요구 사항을 정의합니다.
apiVersion: karpenter.sh/v1alpha5
kind: Provisioner
metadata:
name: default
spec:
requirements:
- key: "node.kubernetes.io/instance-type"
operator: In
values: ["t3.medium", "t3.large"]
provider:
instanceProfile: "KarpenterNodeInstanceProfile"
subnetSelector:
karpenter.sh/cluster: default
securityGroupSelector:
karpenter.sh/cluster: default
위 YAML 파일에서 Provisioner는 Karpenter가 사용할 인스턴스 유형, 보안 그룹, 서브넷 등을 정의합니다.