본문 바로가기
System Engineering/Kubernetes (쿠버네티스)

[minikube] 쿠버네티스 HPA 수평확장 이론과 실습 가이드 (요청, 제한, 매트릭서버, Horizontal Pod Autoscaler)

by 코딩하는 동현 2025. 7. 21.

쿠버네티스 HPA 설정 순서

  1. Resource Requests & Limits 설정: HPA는 Pod의 CPU/메모리 사용량을 기준으로 동작하므로, 각 컨테이너에 requests와 limits를 먼저 명시해야 합니다.
  2. 메트릭 서버(Metric Server) 활성화: 쿠버네티스 클러스터에 Metric Server를 설치해 리소스 사용량 메트릭을 수집하고 제공해야 합니다.
  3. HPA(Horizontal Pod Autoscaler) 생성: HPA 리소스를 생성해 자동 확장 정책을 적용할 수 있습니다.

리소스 요청/제한 → 메트릭 서버 설치/활성화 → HPA 생성 및 적용

각 단계가 누락되면 HPA가 정상적으로 동작하지 않으니, 반드시 위 순서대로 진행해야합니다.


Kubernetes Resource Requests & Limits

Kubernetes 환경에서 requestslimits는 애플리케이션이 클러스터 자원을 어떻게 사용할지에 대한 매우 중요한 설정입니다. 특히, 올바른 리소스 요청(requests)의 지정은 클러스터가 안정적으로 동작하고, 효율적으로 자원을 분배하는 데 결정적인 역할을 합니다.

requests(요청)

  • 리소스 요청(requests)은 컨테이너가 쾌적하게 동작하는 데 필요한 최소한의 리소스(메모리 또는 CPU)를 지정합니다.
  • 클러스터에 해당 요청량만큼의 자원이 확보되어야 스케줄러가 파드를 노드에 배치(scheduling)합니다.
  • 요청은 컨테이너 단위로 지정합니다.

request의 지정 방법

  • 작업 대상 manfiest(YAML) 파일의 컨테이너 정의에 resources.requests를 추가합니다.
resources:
  requests:
    memory: "300Mi"
    cpu: "100m"

  • memory 단위:
    • M: 메가바이트(1M = 1,000K)
    • Mi: 메비바이트(1Mi = 1,024Ki = 1,048,576 bytes) - 보통 이진 단위가 더 많이 사용됩니다.
  • cpu 단위:
    • 1: 1 vCPU (Virtual CPU)
    • 100m: 0.1 vCPU (100 millicores)

request의 의미

  • 요청값은 실제 컨테이너가 사용하게 될 리소스 양과는 무관합니다.
  • 파드가 반드시 그만큼의 리소스를 사용한다는 보장은 없습니다.
  • 요청값은 그저 스케줄러에게 “이 정도는 필요하다”는 힌트일 뿐입니다.
  • 이 요청값에 따라, 일정한 노드 자원을 이미 사용 중인 파드가 많으면 새 파드를 Pending 상태로 둘 수 있습니다.
  • 예시:
    • 각 파드가 300MiB를 요청하고, 노드에 1GiB 메모리가 할당돼 있다면 첫 3개 파드는 스케줄되고, 4번째는 Pending 상태가 됩니다.

request 지정의 장점

  • 명확한 resource 계획 : 클러스터 관리자가 각 노드의 배치 가능 파드 수를 정확하게 산정할 수 있습니다.
  • 프로덕션 환경의 필수 옵션 : requests 설정 없이는 자원 분배의 무질서로 서버 불안정, 장애가 발생할 수 있음.
  • 오토스케일러(HPA) 활용의 필수 조건: request 값이 없으면 오토스케일링이 의도대로 작동하지 않을 수 있음.

limits(제한)

  • 리소스 제한(limits)은 명시적으로 컨테이너가 절대로 사용할 수 없는 최대값을 지정합니다.
  • 마찬가지로, 컨테이너의 resources.limits에 값을 추가합니다.
resources:
  requests:
    memory: "300Mi"
    cpu: "100m"
  limits:
    memory: "500Mi"
    cpu: "200m"

 

memory limit

  • 컨테이너가 memory limit을 초과하면 즉시 Kubernetes가 해당 컨테이너를 강제 종료(OOMKilled)합니다.
  • 파드 객체는 살아 있으나, 컨테이너는 자동으로 재시작됩니다(CrashLoopBackOff 상태 등).
  • 이는 클러스터 전체 자원 보호에 효과적이나, 반복되는 재기동 현상이 발생할 수 있습니다.

cpu limit

  • 컨테이너가 cpu limit을 초과하면, 프로세스가 실제 그 이상을 사용하지 못하도록 리눅스 커널(cgroups)이 CPU 리소스를 강제로 제한합니다.
  • 컨테이너가 죽지는 않고, CPU 사용률이 'clamp'(throttle, 제한)되는 것임.
  • 따라서 수행 속도가 늦어질 수 있으나, 서비스는 계속 유지됩니다.

requests와 limits의 관계와 활용 팁

  • requests ≤ limits가 반드시 지켜져야 합니다. 요청값이 제한값보다 크면 에러.
  • 실제 운영환경에서는 requests는 꼭, limits는 상황에 맞게 지정합니다.
  • limits의 대표적 활용: 메모리 누수와 같은 예외 상황이 아주 드물게 발생할 때, 컨테이너만 재시작되는 안전망으로 활용.

실습과 과정 내 예시

requests 단계별 적용

  1. 파드 정의에서 requests 추가(예: 1,500Mi로 높게 지정).
  2. 여러 개의 레플리카를 선언:
    • 해당 리소스가 충분하다면 정상적으로 여러 파드가 동작.
    • 남은 클러스터 리소스보다 요청량이 많으면 Pending 상태로 전환, “insufficient memory/CPU” 에러 확인 가능.

limits 단계별 적용

  1. limit을 아주 작게(예: memory 4Mi) 잡으면, 파드는 OOMKilled 및 CrashLoopBackOff 상태를 반복.
  2. 컨테이너는 죽었다가 재시작되며, 파드는 살아있음.
  3. kubectl get pod, kubectl describe pod 명령으로 상태 변화와 Termination 사유(OOMKilled 등) 확인.

동작의 원리: 리눅스 cgroups

  • 실제 자원 제한 및 강제종료 동작은 컨테이너 런타임(예: Docker)이 리눅스 커널의 cgroups(control groups) 기능을 이용해 수행합니다.
  • cgroups는 2000년대 중반 Google이 설계해 2008년경부터 메인 커널에 적용된 자원 제한 핵심 기능입니다.
  • 프로세스별 CPU, 메모리, 디스크, 네트워크 등 자원 사용량을 시스템 단에서 강제 제어합니다.

요약

  • requests는 반드시, limits는 필요 시에만: 운영환경에서 requests 미설정은 추천하지 않음.
  • request 값 산정은 경험과 프로파일링이 필요: 실제 컨테이너 코드의 요구사양, 과거 실행 기록 등을 바탕으로 근거 있는 추정 필요.
  • 클러스터 자원 상황과 시스템 파드 요청량도 감안: 시스템 파드(CoreDNS 등)도 자원 요청이 있으므로, 전체 합계 관리 필요.
  • microservice 환경에서는 컨테이너 손실에 대한 대응이 구조적으로 되어 있어야 하며, limits를 통한 컨테이너 강제 종료도 문제되지 않도록 설계.

클러스터 자원 분배의 핵심 개념인 requests/limits의 튼튼한 이해와, 실제 스케줄링/제한시의 동작 방식 체험을 통해 안정적이고 효율적인 Kubernetes 환경을 구축할 수 있습니다.


Kubernetes Metrics Server와 Dashboard

Metrics Server

Metrics Server는 Kubernetes 클러스터 내 리소스 사용량(예: CPU, 메모리 등)을 수집하는 경량형 모니터링 컴포넌트입니다.

  • NodePod의 실시간 리소스 사용량 정보를 수집
  • Horizontal Pod Autoscaler, kubectl top, Dashboard 등의 기능이 동작하는 데 핵심 데이터 제공
  • CPU, Memory 등의 사용 중인 리소스(usage)만 제공하며, 디스크 I/O나 네트워크는 수집하지 않음

설치 및 활성화 (Minikube 기준)

Minikube에서는 Add-on 방식으로 간단하게 활성화 가능하며, 명령어는 다음과 같습니다.

minikube addons enable metrics-server

 

활성화 여부 확인:

minikube addons list
kubectl get all -n kube-system

 

활성화된 이후에도 바로 사용이 불가능하며, 보통 1분 이상의 측정 시간

이 필요합니다.

이 시간 동안 메트릭이 수집되어야 kubectl top pod 또는 kubectl top node 명령어가 정상적으로 작동합니다..

주요 명령어

  • kubectl top pod: 각 파드의 실시간 CPU, 메모리 사용량 확인
  • kubectl top node: 각 노드의 전체 리소스 사용량 요약 확인

이 정보는 요청(request)제한(limit) 값을 설정할 때의 기준점으로 사용될 수 있습니다.


Kubernetes Dashboard

Dashboard는 Kubernetes 리소스를 브라우저 기반 GUI 환경에서 시각적으로 관리할 수 있는 웹 애플리케이션이다.

기능

  • 클러스터 자원(Pod, Node, Service 등)의 현황 확인
  • 배포(Deployments), 롤링 업데이트, 로그 보기, 수동 확장 등 다양한 운영 작업 가능
  • kubectl CLI 없이 Kubernetes 리소스를 직접 조작 가능

설치 및 실행 (Minikube 기준)

역시 Add-on 방식으로 제공되며, 다음의 명령어로 활성화 가능함:

minikube addons enable dashboard

실행:

minikube dashboard

이 명령은 로컬 프록시서버를 실행시켜 브라우저에서 localhost 주소를 통해 Dashboard를 접속할 수 있게 함.

내부 동작

  • Dashboard는 Minikube VM 내의 Pod로 실행되며, 외부 연결을 위해 프록시가 자동 생성됨
  • 별도의 NodePort 설정 없이도 Dashboard에 접속 가능


Kubernetes Horizontal Pod Autoscaler(HPA)

  • Horizontal Pod Autoscaler(HPA)는 Kubernetes에서 애플리케이션의 부하에 맞춰 파드(Pod) 개수를 자동으로 늘리거나 줄여주는 기능이다. 즉, 미리 지정한 CPU/메모리 등의 리소스 사용량을 기준으로 Pod 인스턴스 수를 조정하여, 시스템의 확장성과 안정성을 높인다.
  • Horizontal scaling(수평 확장): 동일한 Pod 인스턴스 개수 증가
  • Vertical scaling(수직 확장): 노드의 리소스를 증설하는 방법

어떤 파드를 스케일링할 수 있는가?

어떤 파드든 복제(replication)는 가능하지만, 실제로 안전하게 스케일링하려면 Pod 내부의 소프트웨어가 "복제에 적합하게" 설계되어야 한다.

  • Stateless 서비스: 같은 Pod가 여러 개 동시에 떠 있어도 시스템이 정상 동작함(예: API Gateway, Position Tracker)
  • Stateful 서비스: 데이터 동기화·Lock·중복 문제 등으로 단순 복제 어려움(예: 자체 데이터를 파일로 갖는 Position Simulator, DB Pod 등)

Pod 복제 전, 애플리케이션의 구조∙상태관리 방식을 반드시 검토해야 한다.

HPA 동작 원리

  • 트리거 기준: 주로 CPU 사용률, 혹은 메모리/커스텀 메트릭 등
  • 설정 방법: Deployment(또는 ReplicaSet)과 연동
  • 기본 메트릭: CPU 사용률(퍼센트 값), 이는 deployment에 선언한 requests치를 기준으로 상대값 계산
  • 메트릭 수집: Metrics Server 또는 Prometheus 연동

예시

  • CPU 요청: 50millicores
  • HPA 트리거: 400%(=200millicores 초과 시 오토스케일링)
  • minReplicas: 1, maxReplicas: 4

HPA 실습 절차

준비 사항

  • 클러스터에서 Metrics Server가 동작 중이어야 한다
  • 오토스케일 적용 대상 Deployment 준비(ex: api-gateway)

HPA 오브젝트 생성 1 (명령어 방식)

kubectl autoscale deployment api-gateway --cpu-percent=400 --min=1 --max=4

이렇게 하면 api-gateway의 평균 CPU 사용량이 요청치의 400% (즉 50*4=200millicores) 이상으로 오르면 파드가 자동으로 scale up.

HPA 오브젝트 생성 2 (YAML로 정의)

apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: api-gateway
  namespace: default
spec:
  maxReplicas: 4
  minReplicas: 1
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: api-gateway
  targetCPUUtilizationPercentage: 400

  • 직접 YAML 파일로 관리하면 IaC와 소스 관리에 유리하다.
  • 자동 생성된 hpa object를 YAML로 export하여 소스에 반영할 수 있다.

HPA 동작 확인

  • kubectl get hpa
  • kubectl describe hpa api-gateway
  • kubectl top pod 를 통해 실제 CPU 사용량 모니터링
  • (부하 발생 후) 지정 범위 초과 → 파드 개수 자동 증가
  • 트리거 조건 미달 시 수 분 후 자동 감소


Kubernetes Readiness Probes

Kubernetes 클러스터에서 Horizontal Pod Autoscaler(HPA)를 설정하면, CPU 사용률과 같은 지표에 따라 Pod의 수가 자동으로 늘어나거나 줄어듭니다. 이때 발생할 수 있는 중요한 문제는 다음과 같습니다:

  • 새로운 Pod가 생성되고 컨테이너가 실행 상태(Running)로 전환되는 즉시, 해당 Pod로 트래픽이 라우팅됩니다.
  • 그러나 컨테이너 내부 애플리케이션(예: Spring Boot)은 실제로 준비(ready)가 될 때까지 20~60초 정도 소요될 수 있습니다.
  • 즉, 컨테이너는 프로세스는 살아있으나 실제 서비스 요청을 처리할 준비가 안되어 있을 수 있습니다.
  • 이 상태에서 외부 서비스나 사용자가 해당 Pod에 요청을 보내면, 요청이 지연되거나 실패(HTTP 502 등)로 이어집니다.
  • 오토스케일이 자주 일어날수록 여러 사용자가 무작위로 에러를 경험하게 되어 서비스 품질이 크게 저하될 수 있습니다.
  1. Pod 상태 확인 및 수동 스케일링
    • 초기 상태에서는 각 Pod가 정상적으로 작동합니다.
    • kubectl scale이나 Deployment 파일에서 replica 수를 늘려 수동으로 Pod 개수를 조정해도 마찬가지 문제(비동기 준비)가 발생합니다.
    • curl로 지속적으로 API Gateway를 호출하는 스크립트를 사용해 요청 성공/실패를 모니터링할 수 있습니다.
    • Pod가 증가하면 상당 시간 동안 다수의 요청이 실패하는 현상(HTTP 502 등)이 나타납니다.
    • 이는 서비스 오브젝트(Service)의 로드밸런싱이 새롭게 생성된 아직 준비되지 않은 Pod로도 분산되기 때문입니다.
  2. Kubernetes Readiness Probe의 도입
    • Readiness Probe는 Kubernetes가 "이 Pod는 트래픽을 받을 준비가 됐다"고 판단하는 기준을 지정합니다.
    • 이 Probe가 성공 상태를 반환할 때까진 서비스 오브젝트가 해당 Pod로 트래픽을 보내지 않습니다.
    • 즉, 실제로 컨테이너 내부 애플리케이션이 완전히 기동되기 전까지 사용자 요청이 해당 Pod로 분배되지 않으므로, 요청 실패 현상이 근본적으로 차단됩니다.

Readiness Probe 설정 방법

YAML 예시

아래는 일반적인 HTTP 기반 Readiness Probe의 예시입니다. 이 코드는 각 애플리케이션의 Deployment YAML 파일의 container 섹션에 추가됩니다.

readinessProbe:
  httpGet:
    path: /
    port: 8080
  initialDelaySeconds: 5        # (옵션) 최초 호출 지연
  periodSeconds: 10             # (옵션) 호출 주기, Default=10

  • httpGet: 컨테이너 내부에서 지정한 엔드포인트로 HTTP GET 요청을 보냄. 이 URL에서 정상 응답(2xx/3xx)이 오면 준비 완료로 간주.
  • path: 헬스 체크를 수행할 엔드포인트.
  • port: 컨테이너가 노출하는 내부 포트(예: 8080).
  • 기타 파라미터(initialDelaySeconds, periodSeconds)로 세밀한 조정 가능.

비 HTTP 서버용

  • exec: 임의의 쉘 명령 실행 결과로 헬스 체크
  • tcpSocket: 포트 오픈 여부만 체크

Kubernetes Liveness Probes

  • Liveness Probe는 애플리케이션 전체 수명 동안 주기적으로 상태를 확인하고, Probe가 반복적으로 실패하면 Kubernetes가 해당 Pod를 강제 재시작합니다.
  • Readiness와 Liveness는 설정 방식이 유사하지만, 목적이 다릅니다:
    • Readiness: 서비스 진입 전 준비 여부 판별(트래픽 분배 제어)
    • Liveness: 서비스 도중 비정상 상태 감지 후 자동 치유(재기동)

Liveness Probe 설정 방법

Liveness Probe는 주로 다음 세 가지 방식 중 하나를 사용해 상태를 체크할 수 있습니다:

  • 컨테이너 내부에 HTTP 서버가 구동 중일 때 특정 경로로 주기적 GET 요청을 보내 상태를 점검합니다.
  • HTTP 상태 코드 200~399를 정상으로 간주하며, 이외는 실패로 처리합니다.

예:

livenessProbe:
  httpGet:
    path: /healthz
    port: 8080
    httpHeaders:
      - name: Custom-Header
        value: Awesome
  initialDelaySeconds: 3     # Pod 시작 후 3초 뒤부터 체크 시작
  periodSeconds: 3           # 3초마다 체크
  timeoutSeconds: 1          # 체크 응답 시간 제한 (옵션)
  failureThreshold: 3        # 연속 실패 허용 횟수

동작 방식

  • kubelet이 설정된 주기에 맞추어 Liveness Probe를 실행합니다.
  • Probe가 실패하면, kubelet은 컨테이너를 종료(SIGTERM 후 SIGKILL)하고, Pod spec의 restartPolicy에 따라 컨테이너를 재시작합니다.
  • 이를 통해 교착(deadlock), 무한루프, 외부 서비스 장애 등으로 인해 정상 작동하지 않는 컨테이너를 복구할 수 있습니다.

결론 및 권장 사항

  • Kubernetes 환경에서 무중단 배포, 오토스케일링 등 안정적인 서비스 제공을 위해 모든 컨테이너에 Readiness Probe 설정을 강력히 권장합니다.
  • liveness probe는 애플리케이션의 특성이나 장애 패턴에 따라 선택적으로 적용하는 것이 좋습니다.

반응형

댓글