CampusMeet

[AutoScaling] 다양한 AutoScaling 전략

dong_seok 2024. 9. 19. 16:42
1. AutoScaling
2. HPA
3. CA

 

1. AutoScaling

AutoScaling이 효율적이라는 이야기를 듣고 적용하려고 알아보니, 생각보다 종류가 다양했습니다. 제가 조사한 것 외에도 여러 세부적인 AutoScaling 방식이 존재했습니다. 하지만 이번에는 일반적으로 많이 사용되며, 제가 프로젝트에 적용할 AutoScaling 방식들에 대해 간단히 설명하고 넘어가겠습니다.

  • 수직적 스케일링:
    • VPA (Vertical Pod Autoscaler) 활용
    • Pod의 리소스를 감시하여, Pod의 리소스가 부족한 경우 Pod를 Restart하며 Pod의 리소스를 증가
    • 수직적 증가 (Scale Up) , 수직적 감소 (Scale Down)
    • Stateless App에 적합
    • 초기에는 노드의 CPU와 메모리를 증가시키는 방식으로 대응
  • 수평적 오토스케일링:
    • Horizontal Pod Autoscaler (HPA) 활용
    • Pod의 리소스를 감시하여, Pod의 리소스가 부족한 경우 Controller의 replicas를 증가시켜, Pod의 수를 증가
    • 수평적 증가 (Scale Out) , 수평적 감소 (Scale In)
    • Stateful App에 적합
    • CPU, 메모리 사용률 기반으로 백엔드 컨테이너 복제본 수 자동 조절
  • 클러스터 오토스케일링:
    • Cluster Autoscaler (CA) 활용
    • 리소스 사용량에 따라 노드 수를 자동으로 증가시키는 설정
    • 단, 초기에는 비용 효율성을 위해 신중하게 접근

 

처음에는 VPA와 HPA를 모두 적용하려 했지만, 두 가지를 동시에 사용할 경우 시스템이 어떤 기준을 우선 적용해야 할지 혼란이 생길 수 있다는 점을 알게 되었습니다. 또한, 둘 다 적용했을 때 충돌이 발생할 가능성도 있어 일반적으로 한 가지만 사용하는 것이 더 보편적이었습니다. 서버의 자원이 충분하지 않고, 애플리케이션이 Stateful하다는 점을 고려했을 때, HPA를 적용하는 것이 더 적합하다고 판단했습니다. 이에 HPA와 함께 CA도 적용해보기로 결정했습니다.

 

2. HPA

apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
  name: hoseo-meet-web-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: hoseo-meet-web
  minReplicas: 1
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      targetAverageUtilization: 50

 

 

오류의 원인을 파악해보니 더이상 사용되지 않는 API 버전이었고 새로운 API 버전에서 사용하는 메트릭 구조가 달랐기 때문에 생긴 오류였습니다. API 버전은 "kubectl api-versions | grep autoscaling" 으로 확인할 수 있습니다. 따라서 오류사항들에 맞게 yaml 파일을 아래와같이 수정해주었더니 정상적으로 리소스가 생성되었습니다.

 

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: hoseo-meet-web-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: hoseo-meet-web
  minReplicas: 1
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50

 

오토스케일링이 정상적으로 되는지 확인해보기로 했습니다.

 

 

 

이 명령어의 결과에서 TARGETS 열이 <unknown>/50%로 표시되고 있는데, 이는 메트릭 데이터를 아직 수집하지 못했음을 의미합니다.

하단 명령어로 메트릭 서버가 작동중인지 확인해주었습니다.

 

kubectl get pods -n kube-system | grep metrics-server

 

 

서버가 정상작동인걸 확인했으니 원인은 다른곳에 있는것으로 예상됩니다. 그래서 하단 명령어로 HPA의 상세 정보와 최근 스케일링 이벤트를 확인해보았습니다.

 

kubectl describe hpa hoseo-meet-web-hpa

 

출력을 보니 주요 이슈가 CPU 리소스 request이 설정되지 않았다는 것을 알게 되었습니다. HPA가 제대로 작동하려면 컨테이너에 리소스 요청이 명시되어 있어야 합니다. 따라서 이전 "dev-api-deployment.yaml" 파일의 hoseo-meet-web 에 대한 CPU request를 설정해주고 다시 확인해보았습니다.

 

 

 

hpa가 정상적으로 작동하는걸 확인하였으니 부하 테스트를 통해 오토스케일링이 정상 작동하는지까지 확인해보도록 하겠습니다.

 

ab -c 200 -n 2000 -t 30 https://www.campus-meet.shop/docs

 

Apache Bench 를 사용한 웹 서버 성능 테스트를 진행해 보았습니다. 200명의 사용자가 동시에 총 2000개의 요청을 보낸다는 명령어입니다. 테스트 결과 정상적으로 REPLICAS가 늘어나면서 HPA가 정상적으로 작동하는 모습을 볼 수 있었습니다. 하지만 이러한 테스트에는 단일 경로에 대해서만 수행되므로, 전체 애플리케이션의 성능을 테스트 하기에는 무리가 있다는 단점이 있었습니다. 따라서 별도의 테스트 스크립트를 만들어 테스트를 진행해보았습니다. 

 

#!/bin/bash

BASE_URL="https://www.campus-meet.shop"
DURATION=300  # 5분 동안 테스트
MAX_CONCURRENT_USERS=1000
SURGE_DURATION=60  # 트래픽 급증 지속 시간 (초)

# 엔드포인트 목록
ENDPOINTS=(
    "/api/chat"
    "/api/v1/auth/me"
    "/api/v1/auth/verify-email"
    "/docs"
)

start_time=$(date +%s)
end_time=$((start_time + DURATION))

run_test() {
    local concurrent=$1
    local endpoint=$2
    ab -c $concurrent -n $((concurrent * 2)) -t 30 "${BASE_URL}${endpoint}" > /dev/null 2>&1 &
}

get_current_users() {
    local current_time=$1
    local elapsed_time=$((current_time - start_time))
    local cycle=$((elapsed_time / SURGE_DURATION))
    
    if [ $((cycle % 2)) -eq 0 ]; then
        echo $MAX_CONCURRENT_USERS
    else
        echo $((MAX_CONCURRENT_USERS / 10))
    fi
}

while [ $(date +%s) -lt $end_time ]; do
    current_time=$(date +%s)
    current_users=$(get_current_users $current_time)

    for endpoint in "${ENDPOINTS[@]}"; do
        users_per_endpoint=$((current_users / ${#ENDPOINTS[@]}))
        run_test $users_per_endpoint $endpoint
    done

    echo "Current time: $(date), Active users: $current_users"
    sleep 15
done

wait
echo "Load test completed."

 

해당 스크립트를 사용하면 엔드포인트 목록에 내가 원하는 엔드포인트들을 대상으로 과부하 테스트를 진행할 수 있기때문에 앱의 전체적인 성능을 테스트하기에 더 적합했습니다. 마찬가지로 HPA는 잘 작동하였으나 deployment cpu requests 나 HPA의 averageUtilization 의 정확한 값은 추후 서비스를 배포한후 모니터링을 하며 수정해가는게 맞다고 판단하여 우선은 현재 서버 사양인 vCPU 2EA, RAM 4GB에 평균적인 값들로 배치해 두기로 하였습니다.

 

3. CA

현재 부여받은 권한으로는 CA가 불가능하여 가볍게 설명만 하고 넘어가도록 하겠습니다. CA(Cluster Autoscaler)는 Kubernetes 클러스터의 크기를 자동으로 조정하여 리소스 사용을 최적화합니다. 리소스 부족으로 인해 스케줄링 되지 못한 파드가 있을 때 클러스터를 확장합니다. 반대로, 클러스터 내 노드 중 일부가 지속적으로 낮은 리소스 사용률을 보이면 해당 노드를 축소하여 리소스 낭비를 방지합니다. 주의할점은 CA 의 동작을 위해서는 pod의 requests과 limits이 반드시 정의되어 있어야한다는 것입니다. 따라서 CA를 사용하기 위해서는 반드시 선행적으로 HPA가 설정되어 있어야 한다는점을 반드시 유의해야 합니다.

 

 

 

참고자료

https://guide.ncloud-docs.com/docs/nks-nks-1-6

https://guide.ncloud-docs.com/docs/nks-nks-1-7#Helm%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0