13년차의 서버실

서버, 인프라, 홈랩 기술 블로그

[k8s] AKS 워크로드 성능 벤치마크: 노드 타입별 최적화 전략

[k8s] AKS 워크로드 성능 벤치마크: 노드 타입별 최적화 전략

AKS 성능 벤치마크를 제대로 해보면, 같은 쿠버네티스(Kubernetes, 컨테이너 오케스트레이션) 클러스터라도 노드 타입 하나 바꿨을 뿐인데 체감이 꽤 달라집니다. 저도 처음엔 “어차피 Pod(파드, 컨테이너 실행 단위)만 잘 나뉘면 되는 거 아닌가?” 싶었거든요. 근데 실제로 운영해보니까 CPU bound(연산 집약형) 워크로드, memory bound(메모리 집약형) 워크로드, burst traffic(순간 트래픽) 대응이 전부 다르게 움직이더라고요. 특히 AKS 노드 타입을 대충 고르면 비용은 비용대로 나가고, 성능은 애매한 상황이 생기는 거 있죠.

이번 글은 특정 벤치마크 수치를 과장해서 보여주는 글이 아닙니다. 대신 제가 실무와 홈랩에서 클러스터를 굴리면서 정리한 방식대로, 어떻게 AKS 성능 벤치마크를 설계하고, 어떤 워크로드에 어떤 노드 타입을 우선 검토해야 하는지, 그리고 쿠버네티스 워크로드 최적화를 어떤 순서로 접근하면 덜 삽질하는지 정리해보겠습니다. 숫자보다 중요한 건 비교 기준이거든요.

AKS 성능 벤치마크를 위한 노드 타입별 아키텍처 다이어그램

AKS 클러스터에서 일반형, 컴퓨트 최적화형, 메모리 최적화형 노드를 분리하고 워크로드를 비교 측정하는 전체 구조 예시입니다.

왜 AKS 성능 벤치마크가 중요한가

쉽게 말해, AKS는 관리형 쿠버네티스(Managed Kubernetes)라서 제어 플레인(control plane)은 편해졌지만, 노드 선택 책임까지 사라진 건 아닙니다. 오히려 운영이 쉬워진 만큼 워크로드 특성에 맞는 인프라 설계가 더 중요해졌어요.

예를 들어 이런 상황 있으셨을 겁니다.

  • 웹 API는 평소엔 한가한데 특정 시간대에 응답 지연(latency, 지연 시간)이 튑니다.
  • 배치 작업(batch job)은 CPU를 많이 먹는데, 일반형 노드에서 오래 끕니다.
  • 캐시나 분석용 애플리케이션은 메모리를 넉넉히 잡아야 하는데 OOMKilled가 납니다.
  • 오토스케일링(autoscaling)이 걸리긴 하는데 생각보다 늦게 반응합니다.

이럴 때 필요한 게 감으로 고르는 인프라가 아니라, 클라우드 네이티브 벤치마크 방식으로 실제 워크로드를 분류하고 비교하는 작업입니다. 저도 예전엔 노드 스펙만 보고 판단했다가, 정작 병목은 CPU가 아니라 스토리지 I/O 혹은 스케줄링 밀집도(bin packing)였던 적이 꽤 있었어요. 정말 여러 번 삽질했습니다 ㅎㅎ

AKS 노드 타입을 어떻게 봐야 하나

Azure K8s 성능을 볼 때는 노드를 단순히 “비싼 게 좋다”로 보면 안 됩니다. AKS 노드 타입은 대체로 다음 관점으로 나눠서 보면 훨씬 판단이 쉬워집니다.

분류 대표 성격 잘 맞는 워크로드 주의할 점
General Purpose(범용형) CPU/메모리 균형 일반 웹 서비스, API, 운영도구 특정 자원 한쪽이 치우치면 효율이 애매할 수 있음
Compute Optimized(컴퓨트 최적화형) vCPU 비중 높음 트랜스코딩, 빌드, 배치, 계산 작업 메모리 요구량이 큰 앱은 오히려 불리할 수 있음
Memory Optimized(메모리 최적화형) 메모리 비중 높음 캐시, 인메모리 DB, JVM 계열 앱 CPU 대비 비용 효율을 따로 봐야 함
GPU/특수형 가속기 탑재 AI/ML, 병렬 연산 일반 서비스에는 과한 경우가 많음

실무에서는 Azure VM 계열로 풀어보면 범용형은 D 시리즈, 컴퓨트 최적화형은 F 시리즈, 메모리 최적화형은 E 시리즈를 먼저 비교하는 경우가 많습니다. 물론 세부 세대와 로컬 디스크 유무, 네트워크 성능, 가용 영역 배치까지 들어가면 이야기가 더 길어지지만, 첫 AKS 성능 벤치마크는 너무 복잡하게 시작하지 않는 게 좋습니다.

여기서 중요한 포인트! 벤치마크의 목적은 “최고 성능 머신 찾기”가 아니라, 내 워크로드에 가장 안정적으로 맞는 조합 찾기입니다.

벤치마크 전에 먼저 정해야 할 기준

AKS 성능 벤치마크를 시작하기 전에 저는 보통 아래 네 가지부터 적어둡니다.

  1. 측정 대상: API 서버인지, 배치 잡인지, 스트리밍 처리인지 구분합니다.
  2. 핵심 지표: 처리량(throughput), 응답 지연(latency), 재시작 횟수, CPU throttling 여부를 봅니다.
  3. 비교 조건: 동일한 리전(region), 동일한 애플리케이션 이미지, 동일한 requests/limits로 맞춥니다.
  4. 종료 조건: 어느 지점에서 “이 노드는 부적합”이라고 판단할지 기준을 세웁니다.

이걸 안 정하면 나중에 그래프는 많은데 결론이 없어요. 저도 처음엔 대시보드만 잔뜩 띄워놓고 뿌듯했는데, 정작 뭘 비교한 건지 흐려져서 다시 했던 기억이 납니다.

실전 구현: AKS 벤치마크용 클러스터와 워크로드 준비

이제 실제로 해보겠습니다. 여기서는 가장 이해하기 쉬운 방식으로, 노드 풀(node pool, 용도별 노드 그룹)을 분리하고 동일 워크로드를 각각에 붙여 비교하는 흐름으로 가보겠습니다.

1. AKS 클러스터와 기본 노드 풀 생성

RESOURCE_GROUP="rg-aks-bench"
CLUSTER_NAME="aks-bench-lab"
LOCATION="koreacentral"

az group create \
  --name $RESOURCE_GROUP \
  --location $LOCATION

az aks create \
  --resource-group $RESOURCE_GROUP \
  --name $CLUSTER_NAME \
  --node-count 1 \
  --enable-managed-identity \
  --generate-ssh-keys

az aks get-credentials \
  --resource-group $RESOURCE_GROUP \
  --name $CLUSTER_NAME

처음부터 노드를 많이 올리기보다, 기본 클러스터를 만들고 나중에 목적별 node pool을 추가하는 게 관리가 편합니다.

2. 용도별 AKS 노드 타입 추가

az aks nodepool add \
  --resource-group $RESOURCE_GROUP \
  --cluster-name $CLUSTER_NAME \
  --name gp \
  --node-count 1 \
  --node-vm-size Standard_D4s_v5

az aks nodepool add \
  --resource-group $RESOURCE_GROUP \
  --cluster-name $CLUSTER_NAME \
  --name cpu \
  --node-count 1 \
  --node-vm-size Standard_F4s_v2

az aks nodepool add \
  --resource-group $RESOURCE_GROUP \
  --cluster-name $CLUSTER_NAME \
  --name mem \
  --node-count 1 \
  --node-vm-size Standard_E4s_v5

예시는 범용형, 컴퓨트 최적화형, 메모리 최적화형을 나눈 것입니다. 실제 운영에서는 가용성, 예산, 리전 지원 여부를 같이 봐야 합니다.

AKS 노드 타입에 따라 워크로드를 분리 배치하는 구성도

서로 다른 AKS 노드 풀에 동일한 애플리케이션을 배치하고, nodeSelector로 대상을 분리하는 흐름을 보여주는 구성도입니다.

3. 테스트용 애플리케이션 배포

여기서는 가장 단순한 웹 애플리케이션 예시로 갑니다. 핵심은 애플리케이션 자체가 아니라 동일 조건으로 여러 노드 타입에 붙여 비교하는 것입니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: bench-web-gp
spec:
  replicas: 3
  selector:
    matchLabels:
      app: bench-web-gp
  template:
    metadata:
      labels:
        app: bench-web-gp
    spec:
      nodeSelector:
        agentpool: gp
      containers:
      - name: web
        image: nginx:stable
        resources:
          requests:
            cpu: "250m"
            memory: "256Mi"
          limits:
            cpu: "500m"
            memory: "512Mi"
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: bench-web-gp
spec:
  selector:
    app: bench-web-gp
  ports:
  - port: 80
    targetPort: 80
  type: ClusterIP

이 YAML은 `gp`, `cpu`, `mem` 용으로 이름과 `nodeSelector`만 바꿔서 각각 하나씩 배포하면 됩니다. 실제로 해보니까 여기서 가장 많이 틀리는 게 라벨명이더라고요. AKS 노드 풀 라벨은 환경에 따라 꼭 확인해보는 게 안전합니다.

4. 리소스 사용량과 이벤트 확인

kubectl get nodes --show-labels
kubectl get pods -o wide
kubectl top nodes
kubectl top pods
kubectl describe pod <pod-name>

이 단계에서 확인할 건 세 가지입니다.

  • Pod가 의도한 node pool에 올라갔는지
  • CPU throttling 징후가 있는지
  • 메모리 압박이나 재시작이 있는지

5. 부하 테스트 실행

HTTP 워크로드라면 외부 부하 도구를 붙여도 되고, 간단히 클러스터 내부에서 반복 요청을 보내도 됩니다.

kubectl run loadtest --rm -it \
  --image=busybox \
  --restart=Never -- /bin/sh

while true; do
  wget -q -O- http://bench-web-gp; 
  sleep 0.2;
done

물론 이건 아주 가벼운 예시입니다. 실제 AKS 성능 벤치마크라면 동시성(concurrency), 지속 시간(duration), 오류율(error rate)을 더 정교하게 잡아야 합니다. 그래도 첫 비교는 이렇게 작게 시작하는 게 좋습니다. 처음부터 너무 큰 도구를 붙이면 원인 분석이 더 어려워지거든요.

쿠버네티스 워크로드 최적화에서 놓치기 쉬운 포인트

노드 타입만 바꾸면 끝일 것 같지만, 실은 워크로드 정의가 더 중요할 때가 많습니다.

체크 항목 왜 중요한가 실무 팁
requests/limits 스케줄링과 throttling에 직접 영향 너무 보수적으로 잡으면 밀집도가 떨어집니다
HPA 트래픽 대응 자동화 CPU만 보지 말고 메모리나 커스텀 메트릭도 검토합니다
Pod 분산 장애 도메인 분리 anti-affinity와 topology spread를 함께 봅니다
스토리지 특성 상태 저장 앱의 체감 성능 좌우 디스크 병목이면 노드 변경 효과가 작을 수 있습니다

예를 들어 CPU가 부족한 줄 알고 컴퓨트 최적화 노드로 옮겼는데, 알고 보니 컨테이너 `limits`가 너무 타이트해서 throttling만 심했던 경우도 있습니다. 저도 이거 한 번 당하고 나서는, 무조건 애플리케이션 정의와 노드 타입을 같이 봅니다.

⚠️ 실제로 겪었던 트러블슈팅

여기서는 제가 자주 봤던 문제를 정리해볼게요.

1. Pod가 원하는 노드에 안 올라가는 문제

대부분 `nodeSelector`, `taint/toleration`, 리소스 부족 셋 중 하나입니다.

kubectl describe pod <pod-name>

`Events`를 보면 대개 이유가 나옵니다. 처음엔 저도 스케줄러가 이상한 줄 알았는데, 실제로는 라벨 오타가 제일 흔했어요.

2. 벤치마크 결과가 들쭉날쭉한 문제

이건 생각보다 흔합니다. 원인은 보통 아래 쪽입니다.

  • 테스트 시간대가 다름
  • 이미지 풀(image pull) 시간이 섞임
  • 오토스케일링 반응 시간이 포함됨
  • 클러스터 내부의 다른 작업이 간섭함

그래서 저는 AKS 성능 벤치마크할 때 최소한 워밍업 구간과 실측 구간을 분리합니다. 이거 안 하면 첫 요청 지연이 평균값을 망치더라고요.

3. 메모리 최적화 노드인데 성능 향상이 애매한 문제

메모리를 많이 준다고 모든 앱이 빨라지진 않습니다. 애플리케이션이 실제로 heap(힙), cache(캐시), page cache를 활용하는 구조인지 봐야 합니다. 단순한 stateless API라면 메모리보다 CPU 클럭이나 네트워크 특성이 더 체감될 때가 많습니다.

4. 비용은 늘었는데 개선 폭이 작은 문제

이건 가장 뼈아픈 케이스죠. 그래서 AKS 성능 벤치마크 결과는 반드시 성능/비용 관점으로 같이 봐야 합니다. 절대 성능만 보고 결정하면 운영비가 금방 불어나니까요.

AKS 성능 벤치마크 결과를 시각화한 대시보드 이미지

CPU 사용률, 메모리 사용량, Pod 재시작, 응답 지연을 한 화면에서 비교하는 벤치마크 대시보드 예시입니다.

검증: 어떤 결과를 보면 의미 있는가

결과 검증은 단순 평균보다 분포를 보는 게 좋습니다. 특히 웹 서비스는 p95 latency(p95 지연 시간), 오류율, 재시작 여부가 중요합니다.

  1. 범용형 노드에서 안정적이지만 피크 구간에서 지연이 튀는지 봅니다.
  2. 컴퓨트 최적화형에서 CPU 사용률은 낮아졌는지, 처리량은 늘었는지 봅니다.
  3. 메모리 최적화형에서 OOMKilled가 줄고 캐시 적중 효과가 있는지 확인합니다.
  4. 같은 성능을 더 적은 노드 수로 낼 수 있는지도 함께 봅니다.

제가 직접 해보니, 정답이 하나로 고정되기보다 워크로드 특성에 따라 꽤 명확하게 갈리더라고요.

  • 일반 웹/API는 범용형에서 시작해도 충분한 경우가 많습니다.
  • 빌드, 계산, 배치성 작업은 컴퓨트 최적화형이 먼저 후보가 됩니다.
  • 캐시, JVM, 데이터 집약형 앱은 메모리 최적화형 검토 우선순위가 올라갑니다.

결론적으로 Azure K8s 성능은 노드 스펙 하나가 아니라, 워크로드 패턴과 리소스 설정, 스케일 전략의 합으로 결정됩니다.

정리: AKS 노드 타입 선택 전략

마지막으로 실무에서 바로 써먹기 좋은 방식으로 정리해보겠습니다.

  1. 기준 워크로드를 하나 정합니다. 가장 중요한 서비스부터입니다.
  2. 범용형 node pool을 기준선으로 삼습니다.
  3. 같은 앱을 컴퓨트 최적화형, 메모리 최적화형에 각각 배치합니다.
  4. `requests/limits`, HPA, 분산 정책을 동일하게 맞춥니다.
  5. 처리량, p95 지연, 재시작, 비용 관점을 같이 봅니다.
  6. 결과가 좋으면 그때 운영 표준으로 가져갑니다.

이 순서대로 하면 적어도 “왜 느린지 모르겠는데 일단 큰 VM으로 바꾸자” 같은 결정을 줄일 수 있습니다. 사실 저도 예전엔 그렇게 했었는데요, 나중에 보면 대부분 비효율이었어요.

혹시 지금 AKS에서 특정 워크로드가 계속 애매하게 느리다면, 이번엔 감으로 바꾸지 말고 AKS 성능 벤치마크 기준부터 잡아보세요. 그 다음에야 AKS 노드 타입 선택이 훨씬 쉬워집니다. 다음 글에서는 Cluster Autoscaler(클러스터 오토스케일러)와 HPA를 같이 묶어서, 실제 트래픽 변동 환경에서 어떻게 튜닝하는지 이어서 다뤄보겠습니다. 이전 글에서 다뤘던 Ingress(인그레스, 외부 트래픽 진입점) 최적화 내용과 연결해서 보셔도 흐름이 잘 이어질 겁니다.

AKS 노드 타입 선택 기준과 최적화 전략 요약 인포그래픽

범용형, 컴퓨트 최적화형, 메모리 최적화형 노드의 추천 워크로드와 판단 기준을 한눈에 요약한 인포그래픽입니다.

FAQ: 자주 묻는 질문

AKS 성능 벤치마크는 운영 환경에서 바로 해야 하나요?

가능하면 운영과 유사한 별도 환경에서 먼저 하시는 걸 권합니다. 운영에서 바로 하면 다른 변수 때문에 결과 해석이 어려워져요.

노드 타입만 바꾸면 성능 문제가 해결되나요?

아닙니다. `requests/limits`, 애플리케이션 구조, 스토리지, 네트워크까지 같이 봐야 합니다.

처음 시작할 때 가장 무난한 방법은 뭔가요?

범용형을 기준선으로 잡고, CPU 중심 워크로드와 메모리 중심 워크로드를 분리해 비교해보는 게 가장 안전합니다.