Kubernetes 클러스터 성능 최적화를 위한 모범 사례
적절한 크기의 리소스, 오토스케일링, 효율적인 네트워킹, 스토리지 선택, 안정적인 관측 가능성으로 Kubernetes 성능을 최적화하세요.
Kubernetes 클러스터 성능 최적화를 위한 모범 사례
Kubernetes 클러스터 성능 문제는 일반적으로 느린 롤아웃, 대기 중인 Pod, 시끄러운 이웃(noisy neighbor), 또는 예상치 못한 클라우드 비용으로 나타납니다. 해결책은 단 하나의 마법 같은 설정이 아닙니다. 정확한 리소스 크기 조정, 수요에 맞는 스케일링 규칙, 그리고 압력이 시작되는 지점을 파악할 수 있는 충분한 관측 가능성이 필요합니다.
이 체크리스트를 사용하여 추측 없이 클러스터를 튜닝하세요.
요청(Requests)과 제한(Limits)부터 시작하세요
스케줄러는 CPU와 메모리 requests를 사용하여 Pod가 배치될 위치를 결정합니다. 요청이 너무 낮으면 노드가 실제보다 더 비어 보여 워크로드가 리소스를 두고 경쟁하게 됩니다. 요청이 너무 높으면 스케줄러가 용량을 낭비하고 Pod가 대기 상태로 남을 수 있습니다.
실제 사용 데이터를 기반으로 요청을 설정하세요. 예를 들어, API 컨테이너가 정상 트래픽 중에 약 300밀리코어를 사용하고 배포 준비 중에 700밀리코어 근처로 피크를 친다면, 다음과 같이 시작할 수 있습니다:
resources:
requests:
cpu: "300m"
memory: "512Mi"
limits:
memory: "1Gi"
CPU 제한에 주의하세요. 엄격한 CPU 제한은 노드에 여유 CPU가 있더라도 지연 시간에 민감한 서비스를 제한할 수 있습니다. 메모리 제한은 여전히 유용합니다. 메모리 제한을 초과하는 컨테이너는 전체 노드가 메모리 압박 상태에 빠지기 전에 종료될 수 있기 때문입니다.
명확한 신호로 오토스케일링 사용하기
Horizontal Pod Autoscaler는 메트릭이 사용자 수요를 추적할 때 잘 작동합니다. CPU는 간단한 무상태 서비스에 충분할 수 있지만, 큐 깊이, 요청 속도 또는 사용자 정의 애플리케이션 메트릭이 더 나은 스케일링 신호를 제공하는 경우가 많습니다.
kubectl autoscale deployment api \
--cpu-percent=70 \
--min=3 \
--max=20
Cluster Autoscaler, Karpenter 또는 클라우드 제공업체의 노드 오토스케일링 계층은 Pod가 오랫동안 대기 상태로 남기 전에 노드를 추가할 여유가 있어야 합니다. 노드 그룹이 워크로드에 필요한 인스턴스 크기, 영역, GPU 요구 사항 또는 테인트(taint)를 포함하는지 확인하세요.
스케줄링을 예측 가능하게 유지하기
중요한 Pod가 과부하되거나 부적합한 노드에 배치되면 성능이 저하됩니다. 트래픽이 많은 서비스에는 토폴로지 분산 제약 조건(topology spread constraints)을, 하드웨어별 워크로드에는 노드 선호도(node affinity)를, 좁은 범위의 Pod만 실행해야 하는 노드에는 테인트(taint)를 사용하세요.
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app: api
이렇게 하면 클러스터에 더 나은 배치 옵션이 있을 때 복제본이 하나의 노드에 쌓이는 것을 방지할 수 있습니다.
실제로 문제가 되는 네트워킹 튜닝하기
대부분의 클러스터는 이국적인 네트워크 튜닝이 필요하지 않습니다. 느린 경로를 찾는 것부터 시작하세요: DNS 조회 시간, 서비스 메시 오버헤드, 영역 간 트래픽, 과부하된 인그레스, 또는 Pod-데이터베이스 지연 시간.
유용한 확인 사항은 다음과 같습니다:
kubectl top pods -A
kubectl get endpointslices -A
kubectl describe ingress <name>
대화형 서비스의 경우 Pod와 주요 종속성을 동일한 리전에, 가능하면 동일한 영역에 유지하세요. 서비스 메시를 사용하는 경우, 메시 변경 사항을 광범위하게 롤아웃하기 전에 하나의 워크로드에 대해 사이드카 주입 유무에 따른 p95 및 p99 지연 시간을 측정하세요.
워크로드에 맞는 스토리지 선택하기
스토리지 선택은 데이터베이스, 큐 및 CI 워크로드의 성능을 좌우할 수 있습니다. 용량뿐만 아니라 지연 시간, IOPS, 처리량 및 장애 동작을 기반으로 볼륨을 선택하세요.
예를 들어, PostgreSQL Pod는 예측 가능한 지연 시간과 명확한 백업 동작을 가진 영구 볼륨 클래스가 필요합니다. 빌드 캐시는 처리량에 더 신경을 쓰고 재빌드를 허용할 수 있습니다. 무상태 웹 서비스는 실제 이유가 없는 한 영구 볼륨을 완전히 피해야 합니다.
다음 증상을 주시하세요:
- 볼륨이 느리게 연결되어 Pod가
ContainerCreating상태에서 멈춤. - CPU는 정상인데 애플리케이션 지연 시간이 증가.
- 노드 디스크 압박으로 Pod가 축출됨.
- 볼륨이 하나의 영역에 묶여 StatefulSet이 차단됨.
변경하기 전에 클러스터 관찰하기
기준 메트릭 없이 최적화하는 것은 단순한 혼란일 뿐입니다. 최소한 CPU, 메모리, 재시작, 대기 중인 Pod, 노드 압박 조건, API 서버 지연 시간 및 워크로드 p95 지연 시간을 추적하세요.
kubectl get nodes
kubectl describe node <node-name>
kubectl get pods -A --field-selector=status.phase=Pending
kubectl top nodes
Prometheus를 실행 중이라면 지속적인 노드 압박, 높은 재시작 비율, 최대 복제본에서의 HPA, 중요 배포에서 사용 불가능한 복제본에 대한 알림을 추가하세요.
결론
워크로드에서부터 Kubernetes를 최적화하세요. 요청 크기를 적절히 조정하고, 불필요한 CPU 제한을 피하며, 수요 신호에 따라 스케일링하고, 복제본을 분산시키며, 워크로드에 맞는 스토리지를 선택하세요. 그런 다음 각 변경 후 측정하여 클러스터가 더 빨라졌는지, 더 저렴해졌는지, 아니면 단순히 달라졌는지 확인하세요.