Study/K8s

KEDA를 통한 이벤트 기반 Pod Auto-Scaling

Omoknooni 2024. 7. 24. 12:56

KEDA

Kubernetes Event-Driven Autoscaler, 이벤트 기반 오토스케일링을 지원하는 컴포넌트

기존의 Kubernetes 클러스터 환경에서 pod의 Auto Scaling의 경우, HPA가 있었다.

하지만, 이 HPA는 CPU나 메모리 Metric을 기반으로 밖에 pod를 Scaling할 수밖에 없었다.

이에 따라 외부 서비스 Metric (DB, Queue, CSP 서비스 등)을 기반의 이벤트 기반 pod Auto Scaler인 KEDA가 등장하게 되었다. 

 

공식 Docs에 따르면 KEDA는 현재 68종류의 이벤트 소스와의 연동을 지원한다.

 

 

KEDA는 HPA와 같이 동작하며, HPA를 보조하는 역할로 볼 수 있다.

KEDA가 연결된 이벤트 소스로부터 특정 이벤트를 감지하면, HPA의 값을 업데이트해서 HPA가 auto scaling을 수행하는 구조라고 설명할 수 있다.

 

 

이 KEDA를 사용해 deployment를 AWS SQS queue의 메시지 갯수를 Metric으로 하여 Auto Scaling하는 실습을 진행해보도록 한다.

 

KEDA 실습

Event Source 준비

이번 실습에서는 AWS SQS Queue를 Event source로 할 것이므로, Queue와 cluster에서 이 queue에 접근할 Credential을 먼저 생성해주어야한다.

# SQS Queue 생성
aws sqs create-queue --queue-name [queue명]

# queue에 접근할 policy
cat << EOF > keda-test-policy.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "sqs:GetQueueAttributes",
      "Resource": "arn:aws:sqs:<region>:<account-id>:my-queue"
    }
  ]
}
EOF

# policy 생성
aws iam create-policy --policy-name [policy명] --policy-document file://keda-test-policy.json

# user 생성 및 policy 연결

 

 

그리고 Scale할 대상인 Deployment도 하나 생성해준다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80

 

KEDA 설치

KEDA는 Helm을 통해 패키지로 설치할 수 있다.

helm repo add kedacore https://kedacore.github.io/charts
helm repo update

helm install keda kedacore/keda -n keda

 

3개의 Deployment가 구동되는 것을 볼 수 있으며, 각각의 역할은 아래와 같다.

  • Operator : 워크로드의 스케일링을 담당, KEDA의 핵심 컴포넌트
  • Metrics-apiserver : KEDA가 수집한 외부 메트릭을 HPA가 사용할 수 있도록하는 메트릭 서버
  • Admission Webhooks : 클러스터의 Admission Webhook으로 동작, KEDA 리소스의 유효성 검사

TriggerAuthentication 생성

KEDA는 TriggerAuthenticationScaledObject라는 주요 오브젝트가 존재한다.

TriggerAuthentication에서는 이벤트 소스가 인증 등의 절차가 필요한 경우, 인증을 하기 위한 오브젝트로 볼 수 있다.

먼저 앞서 생성한 Credential을 담은 Secret 오브젝트를 먼저 생성해준다.

kubectl create secret generic aws-credentials \
--from-literal=aws_access_key_id=<your-access-key-id> \
--from-literal=aws_secret_access_key=<your-secret-access-key>

(직접적인 Credential 삽입으로 생성하는 Secret은 권장되지 않는 방법이다. 어디까지나 실습을 위한 것임을 유의)

 

다음으로 이 Secret값을 바탕으로 이벤트 소스 인증용 TriggerAuthentication 오브젝트를 생성해준다.

apiVersion: keda.sh/v1alpha1
kind: TriggerAuthentication
metadata:
  name: keda-aws-credentials
  namespace: default
spec:
  secretTargetRef:
    - parameter: awsAccessKeyID
      name: aws-credentials
      key: aws_access_key_id
    - parameter: awsSecretAccessKey
      name: aws-credentials
      key: aws_secret_access_key

 

 

ScaledObject 생성

ScaledObject에서는 object를 통해 Scaling할 대상과 Scale 작업이 트리거될 규칙을 선언한다. KEDA의 핵심 파츠

앞서 생성한 TriggerAuthentication도 triggers에 연결해준다.

apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: sqs-queue-scaler
  namespace: default
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: [Scale 대상 deployment명]
  minReplicaCount: 1
  maxReplicaCount: 5
  triggers:
  - type: aws-sqs-queue
    metadata:
      queueURL: [queue URL]
      awsRegion: [region]
      queueLength: "5" # 메시지 갯수가 5 이상일 때 스케일링, pod하나당 최대 5개의 메시지를 처리가능하다고 설정
    authenticationRef:
      name: keda-aws-credentials

 

ScaledObject의 대표적인 field는 아래와 같다.

  • scaleTargetRef : scale될 대상 (deployment, statefulset 등)
  • minReplicaCount / maxReplicaCount : scale될 대상 replicaset의 최대/최소 값
  • pollingInterval : trigger 조건을 체크할 주기
  • cooldownPeriod : trigger가 비활성화되었을때, scale-in 되기까지 대기 시간
  • triggers : Scale을 발생시킬 조건
    • type : 트리거 이벤트 소스의 타입, KEDA는 약 60종류 이상의 이벤트 소스 타입을 제공한다.
    • authenticationRef : 이벤트 Scaler에 인증하기위한 TriggerAuthentication

 

이렇게 ScaledObject를 생성하면 HPA도 같이 생성되는 것을 볼 수 있다.

 

 

Scaling test

이제 queue에 메시지를 넣고 실제 trigger에 설정한 대로 Scaling이 되는 지 확인해본다.

먼저, queue에 메시지를 3개만 넣어본다.

aws sqs send-message --queue-url [queue URL] --message-body "Test message1"

 

trigger 조건에 미치지 못했으므로 아직 Scaling되지 않은 것을 볼 수 있다.

즉, 아직 하나의 pod가 3개의 메시지를 충분히 처리할 수 있다는 것이다.

 

이어서 3개를 더 넣어본다.

 

queue에 6개의 메시지가 쌓이고, Threshold로 설정한 5가 넘었기에, 새로 하나가 Scaling되는 것을 볼 수 있다.

이제 여기서 queue에 메시지가 10(5*2)개가 넘으면 하나 더 Scaling된다는 것도 생각할 수 있다. 

 

그리고 queue에 메시지를 비우게 되면 다시 Scale-in 하는 것을 볼 수 있다.

실제로 줄어드는 것은 hpa가 인식한 시점 부터 5분 이후가 된다. (cooldownPeriod의 기본값 : 300s)