
로컬 환경인 Minikube에서 쿠버네티스의 핵심 기능 중 하나인 HPA(Horizontal Pod Autoscaler)가 실제로 어떻게 동작하는지를 확인하기 위해, k6를 이용해 트래픽 부하를 주고, Prometheus 와 Grafana로 모니터링하며 Pod가 자동으로 확장되는 과정을 정리해본다.
1. 환경 세팅: Minikube
먼저 맥북의 자원을 효율적으로 사용하기 위해 Docker 드라이버를 사용하여 minikube를 시작한다.
Minikube 설치 및 시작
brew install minikube
# Docker 데스크탑 설정에서 CPU 4, Memory 8GB 이상으로 설정 권장
minikube start --driver=docker --cpus=4 --memory=8192mb
2. 모니터링 구축: Prometheus & Grafana
쿠버네티스의 상태를 한눈에 파악하기 위해 kube-prometheus-stack을 설치한다.
brew install helm
# 리포지토리 추가 및 업데이트
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
# Prometheus Stack 설치 (수집+시각화+알림 패키지)
helm install my-release prometheus-community/kube-prometheus-stack
Grafana 접속
설치가 완료되면 포트 포워딩을 통해 대시보드에 접속한다.
# Grafana 서비스 이름 확인
kubectl get svc -l "app.kubernetes.io/name=grafana"
# 포트 포워딩 (3000번 포트)
kubectl port-forward svc/my-release-grafana 3000:80
- ID: admin
- Password: 초기 비밀번호는 아래 명령어로 확인 가능하다.
kubectl get secret --namespace default my-release-grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo
3. 테스트용 앱 배포 및 HPA 설정
부하를 테스트할 앱으로 CPU를 의도적으로 많이 소모하는 php-apache를 사용
# 앱 배포
kubectl apply -f https://k8s.io/examples/application/php-apache.yaml
# HPA 설정: CPU 사용량이 50%를 넘으면 Pod를 최대 10개까지 증설
kubectl autoscale deployment php-apache --cpu=50% --min=1 --max=10
4. 부하 테스트: k6 활용
이제 k6를 설치하고 자바스크립트 기반의 테스트 스크립트를 작성하여 트래픽을 쏴보자
brew install k6
import http from 'k6/http';
import { sleep } from 'k6';
export const options = {
stages: [
{ duration: '30s', target: 50 }, // 30초 동안 사용자 50명까지 증가
{ duration: '1m', target: 100 }, // 1분 동안 100명 유지 (Peak 부하)
{ duration: '30s', target: 0 }, // 종료 시점까지 서서히 감소
],
};
export default function () {
http.get('http://localhost:8080'); // 포트 포워딩 주소
sleep(0.1);
}
테스트를 실행하기 전에 Host PC에서 트래픽을 보낼 수 있게 포트 포워딩은 까먹지 말자
kubectl port-forward svc/php-apache 8080:80
# 실행
k6 run script.js
5. 트러블슈팅: 왜 HPA가 작동하지 않을까?
분명 위 스크립트를 바탕으로 부하를 강하게 줬는데도 kubectl get hpa 를 쳤을 때 TARGETS 값이 <unknown>으로 뜨고 Pod가 늘어나지 않았다.
확인 결과 쿠버네티스는 자체적으로 각 Pod의 자원 사용량을 알지 못해, metrics-server 애드온이 켜져 있어야만 HPA가 "아, 지금 CPU가 50%를 넘었구나!"라고 인지하고 스케일 아웃을 진행한다.
# metrics-server 활성화
minikube addons enable metrics-server
# 정상 작동 확인
kubectl get pods -n kube-system | grep metrics-server
변화 확인
| 상태 | kubectl get hpa 결과(TARGETS) | 비고 |
| 애드온 추가 전 | <unkown> / 50% | HPA가 자원량을 몰라 멍하니 있음 |
| 애드온 추가 후 | 85% / 50% | 사용량 감지 즉시 Pod 개수 증가 시작 |
6. 파드가 늘어났는데도 왜 여전히 느릴까?
metrics-server를 켜서 파드가 정상적으로 5개로 늘어나는 것을 확인했는데도 다음 그림과 같이 20초 이상의 지연 시간과 타임아웃이 발생했다. 이것에 대한 원인을 분석해본 결과 다음과 같았다.
- kubectl port-forward는 대규모 트래픽용이 아니다.
우리가 localhost:8080 으로 쏘고 있는 트래픽은 사실 매우 좁은 통로를 지나고 있다. port-forward는 개발자가 디버깅 용도로 쓰라고 만든 임시 통로이다.- 병목 현상: 이 통로는 100 VU(Virtual User) 같은 대량의 동시 접속을 처리하도록 설계되지 않았다. Pod가 아무리 많아도 맥북과 Minikube 사이를 잇는 이 통로에서 트래픽이 다 막힌것이다.
- 해결책: 실제 minikube service php-apache --url 명령어로 나오는 실제 IP와 포트로 직접 트래픽을 쏘거나, Ingress를 통해 접근해야한다.
- HPA는 사후 처방이다. (Scaling Lag)
HPA가 파드를 늘리는 과정을 시간순으로 복기해보면 다음과 같다.- 트래픽 폭주 발생 (0초)
- 기존 파드가 응답 지연 시작 (5~10초)
- Metrics-server가 부하 감지 (30초~1분)
- HPA가 증설 결정 및 파드 생성 (1분~1분 30초)
- 새 파드가 Ready 상태가 되어 트래픽 분산 (2분 내외)
→ 우리의 테스트는 보통 2~3분 내외로 끝난다. 즉, 새 파드들이 일을 시작하려고 할 때 이미 테스트는 끝물이거나, 기존 통로가 이미 포화 상태에 빠진 뒤여서 Pod가 늘어나도 트래픽 분산이 정상적으로 이뤄지지 않은것으로 보인다.

7. Ingress를 통한 트래픽 분산
Ingress 활성화하고, 다음 yaml 파일을 생성한 후 터널을 열어둔다.
minikube addons enable ingress
# 파일 이름 예시: ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: php-apache-ingress
spec:
# Nginx Ingress Controller를 사용하겠다는 설정입니다.
ingressClassName: nginx
spec:
rules:
- host: fake.test # 브라우저나 k6에서 접속할 가짜 도메인
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: php-apache # 아까 확인한 서비스 이름과 똑같아야 함
port:
number: 80
# 쿠버네티스에 배포
kubectl apply -f ingress.yaml
맥북에서 가짜 도메인 인식시키기
현재 쿠버네티스 안에서 fake.test라는 문은 생겼지만, Host 맥북은 그 주소가 어디인지 모르기에 이걸 연결해줘야한다.
# 터미널에서 명령어 입력
sudo vi /etc/hosts
# 파일 맨 아래에 다음 내용 추가
127.0.0.1 fake.test
Ingress tunnel 열기
맥북은 보안상 Ingress가 기본적으로 닫혀 있어 별도의 명령어를 열고 아래 명령어를 계속 켜두면된다.
minikube tunnel
Ingress로 변경 후 테스트 결과
Ingress 추가 후 테스트를 해본 결과 이전과의 결과를 비교하면 다음 표로 나타낼 수 있다.
| 항목 | Port-forward | Ingress | 의미 |
| 에러율 | 6~8% | 0.00% | 타임아웃 없이 모든 요청을 다 받아냈다. |
| 처리량 | 약 300회 | 1,005회 (3배 이상) | 시스템이 3배 이상의 일을 소화함 |
| 중간값 | 20초 이상 | 415ms (0.4초) | 대다수 사용자가 매우 쾌적함을 느낄 수 있음 |
| 평균 응답 | 24초 | 7.09초 | 전체적으로 시스템 안정성 대폭 개선 |
위 표를 볼때 Ingress에서 중간값은 0.4초인데 반해 평균 응답이 7초인 이유는 다음과 같다.
- 초반: 테스트 직후, 파드가 1개일 때는 트래픽 감당을 못 해 응답 시간이 치솟음
- 중반: HPA가 작동해서 파드가 5~10개로 늘어난 시점부터는 응답 속도가 0.4초로 뚝 떨어졌다.
→ 시스템이 스스로 판단하고 확장해서 안정을 찾았다.
그리고 추가적으로 kubectl get hpa -w 결과를 바탕으로 트래픽이 줄어들며 자원을 다시 반납하는 것까지 확인할 수 있었다.


'코딩 > k8s' 카테고리의 다른 글
| [K8s] K8s 환경에서 Python 애플리케이션 모니터링 구축 (0) | 2026.04.16 |
|---|---|
| [K8s] 메모리 고갈로 인한 OOMKilled 테스팅 (0) | 2026.04.06 |
| [Kubernetes] k8s namespace 와 kubectl 명령어 (0) | 2025.11.24 |