[AWS] EKS에서 트래픽 유발해서 HPA 스케일링 확인하기(with ECR)
EKS를 사용하면 컨트롤 플레인(마스터 노드)를 AWS가 관리해 줍니다. 사용자는 워커 노드에만 집중할 수 있습니다. 컴퓨팅 자원의 유연한 사용도 알아서 조정해 줍니다.
HPA(horizontal pod autoscaler)가 있는데 노드(EC2 인스턴스) 속 특정 응용 프로그램을 실행하는 파드(pod)가 사용하는 컴퓨팅 자원의 사용량이 지정한 임계값을 넘어서면(ex. CPU 사용률 50% 이상) 새로운 파드를 생성하라고 Deployment에 요청을 주어 새로운 파드를 생성하게 돕습니다. 그렇게 파드는 둘이 되고 워크로드가 분산되어 부하를 줄일 수 있습니다.
쉽게 말해 노드 속 파드들의 수를 늘릴지 줄일지 판단하는 역할을 하는 것이 HPA입니다.
EKS의 HPA에 임계값을 지정하고, 일부러 부하를 발생시켜 파드들이 증가되는 것을 터미널로 확인해 보겠습니다.
도커를 사용할 것이고, 로컬에 있는 이미지를 ECR의 프라이빗 리포지토리에 적재한 것을 사용할 겁니다.
1. CLI 연결 & 데모 파일로 EKS 설치
다음 글의 1~2번까지 진행해주시면 됩니다.
https://hgk5722.tistory.com/568
데모 파일로 EKS 설치까지 완료해 줍니다.
2. 매트릭(metric) 파드 설치
왜 필요한가)
매트릭 서버는 클러스터 내 리소스 사용량을 모니터링 하는 역할을 수행하고, 이러한 메트릭 데이터를 기반으로 쿠버네티스의 HPA는 동작하기 때문에, metrics-server가 설치되지 않으면 HPA는 Pod의 리소스 사용 정보를 얻을 수 없습니다.
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
가장 최신 버전으로 다운 받아줍니다.
잘 배포 되었는지 확인해 봅니다.
kubectl get deployment metrics-server -n kube-system
설치한 다음 명령어를 바로 입력하면 READY 0/1이 나올 수 있습니다. 10초 정도 지난 후에 다시 해보면 1/1로 되돌아옵니다.
# 확인해 볼 것
kubectl top nodes
3. demo-flask-backend 설치, ECR 생성
1) 파일 생성
파일들을 현재 디렉토리에 생성해줍니다.
# flask-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-flask-backend
spec:
replicas: 1
selector:
matchLabels:
app: demo-flask-backend
template:
metadata:
labels:
app: demo-flask-backend
spec:
containers:
- name: demo-flask-backend
image: ${ACCOUNT_ID}.dkr.ecr.ap-northeast-2.amazonaws.com/demo-flask-backend:latest
imagePullPolicy: Always
ports:
- containerPort: 5000
resources:
requests:
cpu: 100m
limits:
cpu: 500m
imagePullSecrets:
- name: ecr-secret
# flask-service.yaml
apiVersion: v1
kind: Service
metadata:
name: demo-flask-backend
spec:
selector:
app: demo-flask-backend
ports:
- protocol: TCP
port: 80
targetPort: 5000
# hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: demo-flask-backend-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: demo-flask-backend
minReplicas: 1
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50
평균 cpu 이용량을 50%로 설정하고 파드의 수는 1~10로 지정합니다. 이렇게 파일로 만들지 않고 명령어로도 지정할 수 있습니다.
2) Dockerfile 생성
# Dockerfile
# Python 3.8 기반의 이미지를 사용 (아키텍처 명시)
FROM --platform=linux/amd64 python:3.8-slim
# 작업 디렉터리 설정
WORKDIR /app
# 필요한 패키지 설치
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
RUN pip install --upgrade pip
# 애플리케이션 코드 복사
COPY . .
ENV FLASK_APP=app.py
# Flask 애플리케이션 실행
CMD ["flask", "run", "--host=0.0.0.0"]
윈도우나 맥 어느 곳에서 해도 포맷의 일치를 위해 운영체제는 리눅스 아키텍처는 amd64로 지정했습니다.
# requirements.txt
Flask==2.1.0
Werkzeug==2.0.1
# app.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return "Hello, World!"
if __name__ == '__main__':
app.run(host='0.0.0.0')
flask 서버 실행을 위한 app.py도 같이 만들어 줍니다.
3) ACCOUNT_ID 설정
콘솔에서 자신의 계정 ID를 찾아 복사해줍니다.
export ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
echo ${ACCOUNT_ID}
ECR에서 레포지토리 주소가 계정ID가 들어가기 때문에 설정해 주셔야 합니다.
그렇지 않다면 flask-deployment.yaml 파일의 파란 부분을 변경해주셔야 합니다.
4) 도커 데스크탑 실행
도커 파일로 만든 이미지를 ECR에 올려야합니다. 이미지 빌드를 해야하기 때문에 도커 데스크탑을 실행해 주세요.
https://www.docker.com/products/docker-desktop/
Docker daemon이 실행되어야 이미지 빌드가 가능하기 때문에 필요합니다.
5) ECR 리포지토리 생성
aws ecr create-repository --repository-name demo-flask-backend --region ap-northeast-2
이름은 "demo-flask-backend" 리전은 서울입니다.
콘솔에서도 프라이빗으로 리포지토리 생성을 확인할 수 있습니다.
6) 도커 이미지 빌드
도커 데스크탑에서 이미지가 빌드된 걸 확인할 수 있습니다.
7) AWS ECR 로그인
aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin $ACCOUNT_ID.dkr.ecr.ap-northeast-2.amazonaws.com
ap-northeast-2로 진행했습니다. 리전이 다르면 수정해주세요.
8) 이미지 태깅, 이미지 푸시
docker tag demo-flask-backend:latest $ACCOUNT_ID.dkr.ecr.ap-northeast-2.amazonaws.com/demo-flask-backend:latest
docker push $ACCOUNT_ID.dkr.ecr.ap-northeast-2.amazonaws.com/demo-flask-backend:latest
빌드한 이미지를 ECR 리포지토리에 맞게 태깅합니다. 그리고 리포지토리로 푸시하면 이미지가 올라갑니다.
4. 디플로이먼트 적용
kubectl apply -f flask-deployment.yaml
주의)
만일 문제가 발생했다면 ACCOUNT_ID가 안되는 경우일 수 있습니다. kubectl apply는 ${ACCOUNT_ID}를 실제 값으로 변환하지 못한다고 합니다.
방법은 2가지 인데 flask-deployment.yaml 파일에 계정ID를 직접 넣는 방법(위에서 설명드렸습니다)과 다른 명령어를 실행하는 방법이 있습니다.
일단 기존의 안되는 디플로이먼트는 제거해줍니다.
kubectl delete deployment demo-flask-backend
envsubst < flask-deployment.yaml | kubectl apply -f -
YAML 파일의 ${ACCOUNT_ID}를 실제 계정 ID로 대체한 후 실행하는 명령어입니다.
이렇게 pod가 READY 1/1 상태가 되어야 합니다.
여기까지 하면 쿠버네티스에 flask 어플리케이션을 배포한 것이 됩니다.
마지막으로 hpa 파일도 실행시켜 상세 설정을 적용해 줍니다.
kubectl apply -f hpa.yaml
kubectl get hpa
5. 부하를 발생시켜 HPA가 오토스케일링하도록 유도하기
1) 모니터링 창 만들기
별도의 터미널 창을 하나더 생성합니다.
모니터링 명령어를 입력해줍니다.
watch -n 1 "kubectl get hpa && echo '' && kubectl get pods"
50%를 기준으로 최소 파드는 1개 최대는 10개 처음 실행했으니 지금 레플리카는 1개입니다.
디플로이먼트를 내부 또는 외부에서 접속할 수 있게 노출시켜줍니다.
kubectl expose deployment demo-flask-backend --port=5000 --target-port=5000
2) 부하 주기
모니터링 터미널이 아닌 다른 터미널 창에 다음의 명령어를 입력합니다.
kubectl run -i --tty load-generator --rm --image=busybox --restart=Never -- /bin/sh -c "while sleep 0.01; do wget -q -O- http://demo-flask-backend:5000; done"
적당히 지났으면 control + c로 종료해 줍시다.
0.01 초 단위로 부하를 주는 모습입니다. 영상은 중간부터 촬영했는데 2개인 파드가 3개가 됩니다(REPLICAS에는 반영이 조금 늦습니다)
파드 조정의 기본값이 5분이기 때문에 부하 주는 작업을 멈춰도 3개를 유지하다 시간이 지나면 다시 1개로 돌아옵니다.
시간이 지나니까 파드를 정리하는 모습입니다. STATUS가 Terminating으로 변경되었습니다. REPLICAS도 1로 돌아왔고, TARGETS도 1%로 돌아왔습니다.
1번 부터 지금까지 이 장면 보려고 달렸습니다. 이제 삭제하겠습니다.
6. 모든 리소스 삭제하기
eksctl delete cluster --name eks-demo --region ap-northeast-2
삭제하는 데 시간이 좀 걸립니다.
참, ECR은 위의 명령어로 삭제되지 않으니 콘솔에서 따로 삭제하셔야 합니다.