-
[Kubernetes] HPA 알아보기 ( Horizontal Pod Autoscaler )Kubernetes 2024. 2. 16. 22:56728x90반응형
- 목차
들어가며.
이번 글에서는 Kubernetes 의 HPA (Horizontal Pod Autoscaler) 에 대해서 알아보는 시간을 가지려고 합니다.
ReplicaSet 또는 Deployment 로 여러 개의 Pod 를 손쉽게 운용할 수 있습니다.
이는 HA 의 관점에서 안정적으로 Pod 를 일정 갯수만큼 유지시키는 Kubernetes 의 기능인데요.
이들은 반드시 일정 갯수라는 제한이 있기 때문에 리소스의 부하 상태에 따라 유연히 Scale In/Out 이 불가능합니다.
Kubernetes 에서는 이러한 관점에서 Autoscaler 를 제공합니다.
HPA 세팅하기.
HPA 는 CPU 또는 메모리의 상황에 따라서 유연하게 Pod 가 Scale In/Out 됩니다.
실제로 테스트를 통해서 Kubernetes HPA 가 어떻게 동작하는지 알아보려고 합니다.
그러기 위해서 각종 환경 세팅을 먼저 진행하겠습니다.
Kubernetes 설치하기.
아래 링크는 KinD 를 통해서 간단히 로컬 환경에 Kubernetes 를 설치할 수 있는 내용의 사이트입니다.
https://westlife0615.tistory.com/407
https://westlife0615.tistory.com/472
위 내용대로 KinD 를 통해 Kubernetes 를 설치하게 되면, 아래 이미지와 같이 Node 를 위한 Docker Container 들과
각종 Pod 들이 생성됩니다.
NodeJS 앱 생성하기.
HPA 대상의 Pod 로써 NodeJS 웹서버를 사용하겠습니다.
app.js
아래 스크립트는 간단한 app.js 예시입니다.
For Loop 를 1백만번을 순회하여 CPU 사용량을 강제로 높이도록 설계하였습니다.
cat <<EOF> /tmp/app.js var http = require('http'); http.createServer(function (req, res) { for (var i = 0; i < 1000000; i++) { if (i % 100000 == 0) console.log(i) } res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World!'); }).listen(3000); EOF
Dockerfile.
cat <<EOF> /tmp/Dockerfile FROM node:14 WORKDIR /usr/src/app COPY app.js ./ RUN npm install EXPOSE 3000 CMD ["node", "app.js"] EOF
build Docker Image.
docker build -t test-nodejs:1 -f /tmp/Dockerfile /tmp/
KinD Load Docker Image.
kind load docker-image test-nodejs:1 --name test-cluster
test-nodejs.Yaml
아래 yaml 파일은 test-nodejs 를 위한 Deployment 와 Service 에 대한 스펙을 정의한 YAML 파일입니다.
cat <<EOF> /tmp/test-nodejs.yaml apiVersion: apps/v1 kind: Deployment metadata: name: test-nodejs spec: replicas: 1 selector: matchLabels: app: test-nodejs template: metadata: labels: app: test-nodejs spec: containers: - name: test-nodejs image: test-nodejs:1 ports: - containerPort: 3000 imagePullPolicy: Never resources: limits: cpu: 100m memory: 100Mi requests: cpu: 100m memory: 100Mi --- apiVersion: v1 kind: Service metadata: name: test-nodejs spec: selector: app: test-nodejs ports: - protocol: TCP port: 3000 targetPort: 3000 EOF
kubectl apply -f /tmp/test-nodejs.yaml
Auto Scaling 테스트하기.
위 과정을 마치게되면 test-nodejs 라는 이름의 Pod 가 생성됩니다.
test-nodejs Deployment 를 만들 때에 replicas 를 1로 설정하였기 때문에 아래와 같이 1개의 Pod 가 생성됩니다.
kubectl get pod
NAME READY STATUS RESTARTS AGE test-nodejs-7cdf98d548-m22mk 1/1 Running 0 2m48s
이제 본격적으로 Pod 의 CPU 사용량을 늘려보도록 하겠습니다.
먼저 Http Request 를 전송하기 위해 test-nodejs Service 를 port-forward 하겠습니다.
kubectl -n default port-forward service/test-nodejs 3000:3000
Forwarding from 127.0.0.1:3000 -> 3000 Forwarding from [::1]:3000 -> 3000
그리고 부하를 높이기 위해서 HTTP 요청 트래픽을 높입니다.
for i in {0..100000} do curl http://localhost:3000 done
저는 Pod 의 top 명령어를 통해서 Pod 의 CPU 사용량을 확인했구요.
아래 결과처럼 70% 이상까지 CPU 가 사용됨을 확인하였습니다.
kubectl exec --stdin --tty test-nodejs-7cdf98d548-m22mk -- top
top - 01:13:05 up 39 min, 0 users, load average: 4.59, 1.72, 1.08 Tasks: 2 total, 1 running, 1 sleeping, 0 stopped, 0 zombie %Cpu(s): 11.0 us, 6.1 sy, 0.0 ni, 81.1 id, 0.0 wa, 0.0 hi, 1.8 si, 0.0 st MiB Mem : 32052.2 total, 26445.3 free, 2639.4 used, 2967.4 buff/cache MiB Swap: 4096.0 total, 4096.0 free, 0.0 used. 28775.2 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1 root 20 0 613928 73632 27776 S 72.7 0.2 1:05.95 node 16 root 20 0 5960 2688 2304 R 0.0 0.0 0:00.02 top
Load Balancing 확인하기.
CPU 사용량은 70%까지 상승합니다.
이 경우에 Replicas 의 갯수를 늘려주어 부하를 분산하고 CPU 사용량을 줄일 수 있습니다.
test-nodejs Deployment 의 replicas 를 4개로 늘려주어 Pod 를 4개로 변경하였습니다.
그 이후에 부하 분산으로 인해서 CPU 사용량을 15% 까지 감소합니다.
HPA 적용하기.
먼저 Pod 의 CPU 사용량을 특정하기 위한 Metrics Server 를 활성화시켜야합니다.
cat <<EOF> /tmp/metrics-server.yaml apiVersion: v1 kind: ServiceAccount metadata: labels: k8s-app: metrics-server name: metrics-server namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: k8s-app: metrics-server rbac.authorization.k8s.io/aggregate-to-admin: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-view: "true" name: system:aggregated-metrics-reader rules: - apiGroups: - metrics.k8s.io resources: - pods - nodes verbs: - get - list - watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: k8s-app: metrics-server name: system:metrics-server rules: - apiGroups: - "" resources: - nodes/metrics verbs: - get - apiGroups: - "" resources: - pods - nodes verbs: - get - list - watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: k8s-app: metrics-server name: metrics-server-auth-reader namespace: kube-system roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: extension-apiserver-authentication-reader subjects: - kind: ServiceAccount name: metrics-server namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: k8s-app: metrics-server name: metrics-server:system:auth-delegator roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: system:auth-delegator subjects: - kind: ServiceAccount name: metrics-server namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: k8s-app: metrics-server name: system:metrics-server roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: system:metrics-server subjects: - kind: ServiceAccount name: metrics-server namespace: kube-system --- apiVersion: v1 kind: Service metadata: labels: k8s-app: metrics-server name: metrics-server namespace: kube-system spec: ports: - name: https port: 443 protocol: TCP targetPort: https selector: k8s-app: metrics-server --- apiVersion: apps/v1 kind: Deployment metadata: labels: k8s-app: metrics-server name: metrics-server namespace: kube-system spec: selector: matchLabels: k8s-app: metrics-server strategy: rollingUpdate: maxUnavailable: 0 template: metadata: labels: k8s-app: metrics-server spec: containers: - args: - --cert-dir=/tmp - --secure-port=10250 - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname - --kubelet-use-node-status-port - --metric-resolution=15s - --kubelet-insecure-tls image: registry.k8s.io/metrics-server/metrics-server:v0.7.0 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 3 httpGet: path: /livez port: https scheme: HTTPS periodSeconds: 10 name: metrics-server ports: - containerPort: 10250 name: https protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /readyz port: https scheme: HTTPS initialDelaySeconds: 20 periodSeconds: 10 resources: requests: cpu: 100m memory: 200Mi securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true runAsUser: 1000 seccompProfile: type: RuntimeDefault volumeMounts: - mountPath: /tmp name: tmp-dir nodeSelector: kubernetes.io/os: linux priorityClassName: system-cluster-critical serviceAccountName: metrics-server volumes: - emptyDir: {} name: tmp-dir --- apiVersion: apiregistration.k8s.io/v1 kind: APIService metadata: labels: k8s-app: metrics-server name: v1beta1.metrics.k8s.io spec: group: metrics.k8s.io groupPriorityMinimum: 100 insecureSkipTLSVerify: true service: name: metrics-server namespace: kube-system version: v1beta1 versionPriority: 100 EOF kubectl apply -f /tmp/metrics-server.yaml
이제 HPA 를 적용합니다.
Pod 하나가 CPU 사용량이 50% 를 초과하게 되면 최소 1개부터 10까지 Pod 가 증가합니다.
cat <<EOF> /tmp/hpa.yaml apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: test-nodejs spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: test-nodejs minReplicas: 1 maxReplicas: 10 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 50 EOF
kubectl create -f /tmp/hpa.yaml
생성된 HPA 는 아래와 같이 표현되며,
Target 으로 설정된 Deployment 또는 ReplicaSet 의 CPU 사용량에 따라 Pod 가 증가합니다.
그리고 CPU 사용량이 줄어들고 시간이 소요되면 다시 원래의 Min Pod 사이즈만큼 복구됩니다.
반응형'Kubernetes' 카테고리의 다른 글
[Kubernetes] LoadBalancer 타입 Service 이해하기 (0) 2024.06.01 [Kubernetes] last-applied-configuration annotation 알아보기 (0) 2024.04.20 [Kubernetes] QoS 알아보기 (Quality of Service) (0) 2024.02.04 [KinD] KinD Cluster 로 Docker Image 업로드하기 (kind load docker-image) (0) 2024.02.03 Kubernetes Deployment 알아보기 (4) 2024.01.09