이 섹션의 다중 페이지 출력 화면임. 여기를 클릭하여 프린트.
애플리케이션 실행
- 1: 디플로이먼트(Deployment)로 스테이트리스 애플리케이션 실행하기
- 2: 단일 인스턴스 스테이트풀 애플리케이션 실행하기
- 3: 스테이트풀셋(StatefulSet) 삭제하기
- 4: Horizontal Pod Autoscaler
- 5: Horizontal Pod Autoscaler 연습
- 6: 파드 내에서 쿠버네티스 API에 접근
1 - 디플로이먼트(Deployment)로 스테이트리스 애플리케이션 실행하기
이 페이지에서는 쿠버네티스 디플로이먼트 오브젝트를 사용하여 애플리케이션을 실행하는 방법을 설명한다.
목적
- nginx 디플로이먼트 생성하기
- kubectl을 사용하여 디플로이먼트 정보 나열하기
- 디플로이먼트 업데이트하기
시작하기 전에
쿠버네티스 클러스터가 필요하고, kubectl 커맨드-라인 툴이 클러스터와 통신할 수 있도록 설정되어 있어야 한다. 이 튜토리얼은 컨트롤 플레인 호스트가 아닌 노드가 적어도 2개 포함된 클러스터에서 실행하는 것을 추천한다. 만약, 아직 클러스터를 가지고 있지 않다면, minikube를 사용해서 생성하거나 다음의 쿠버네티스 플레이그라운드 중 하나를 사용할 수 있다.
쿠버네티스 서버의 버전은 다음과 같거나 더 높아야 함. 버전: v1.9. 버전 확인을 위해서, 다음 커맨드를 실행kubectl version
.
nginx 디플로이먼트 생성하고 탐색하기
쿠버네티스 디플로이먼트 오브젝트를 생성하여 애플리케이션을 실행할 수 있으며, 디플로이먼트에 대한 명세를 YAML 파일에 기술할 수 있다. 예를 들어 이 YAML 파일은 nginx:1.14.2 도커 이미지를 실행하는 디플로이먼트에 대한 명세를 담고 있다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2 # tells deployment to run 2 pods matching the template
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
-
YAML 파일을 기반으로 디플로이먼트를 생성한다.
kubectl apply -f https://k8s.io/examples/application/deployment.yaml
-
디플로이먼트에 대한 정보를 살펴본다.
kubectl describe deployment nginx-deployment
출력은 다음과 유사하다.
Name: nginx-deployment Namespace: default CreationTimestamp: Tue, 30 Aug 2016 18:11:37 -0700 Labels: app=nginx Annotations: deployment.kubernetes.io/revision=1 Selector: app=nginx Replicas: 2 desired | 2 updated | 2 total | 2 available | 0 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 1 max unavailable, 1 max surge Pod Template: Labels: app=nginx Containers: nginx: Image: nginx:1.14.2 Port: 80/TCP Environment: <none> Mounts: <none> Volumes: <none> Conditions: Type Status Reason ---- ------ ------ Available True MinimumReplicasAvailable Progressing True NewReplicaSetAvailable OldReplicaSets: <none> NewReplicaSet: nginx-deployment-1771418926 (2/2 replicas created) No events.
-
디플로이먼트에 의해 생성된 파드를 나열한다.
kubectl get pods -l app=nginx
출력은 다음과 유사하다.
NAME READY STATUS RESTARTS AGE nginx-deployment-1771418926-7o5ns 1/1 Running 0 16h nginx-deployment-1771418926-r18az 1/1 Running 0 16h
-
파드에 대한 정보를 살펴본다.
kubectl describe pod <pod-name>
<pod-name>
은 파드 중 하나의 이름이다.
디플로이먼트 업데이트하기
새 YAML 파일을 적용하여 디플로이먼트를 업데이트할 수 있다. 이 YAML 파일은 nginx 1.16.1을 사용하도록 디플로이먼트를 업데이트해야 함을 명시하고 있다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.16.1 # Update the version of nginx from 1.14.2 to 1.16.1
ports:
- containerPort: 80
-
새 YAML 파일을 적용한다.
kubectl apply -f https://k8s.io/examples/application/deployment-update.yaml
-
디플로이먼트가 새 이름으로 파드를 생성하고 이전 파드를 삭제하는 것을 확인한다.
kubectl get pods -l app=nginx
레플리카 수를 늘려 애플리케이션 확장하기
새 YAML 파일을 적용하여 디플로이먼트의 파드 수를 늘릴 수 있다.
이 YAML 파일은 replicas
를 4로 설정하여 디플로이먼트에
4개의 파드가 있어야 함을 명시하고 있다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 4 # Update the replicas from 2 to 4
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
-
새 YAML 파일을 적용한다.
kubectl apply -f https://k8s.io/examples/application/deployment-scale.yaml
-
디플로이먼트에 4개의 파드가 있는지 확인한다.
kubectl get pods -l app=nginx
출력은 다음과 유사하다.
NAME READY STATUS RESTARTS AGE nginx-deployment-148880595-4zdqq 1/1 Running 0 25s nginx-deployment-148880595-6zgi1 1/1 Running 0 25s nginx-deployment-148880595-fxcez 1/1 Running 0 2m nginx-deployment-148880595-rwovn 1/1 Running 0 2m
디플로이먼트 삭제하기
이름으로 디플로이먼트를 삭제한다.
kubectl delete deployment nginx-deployment
ReplicationControllers -- 예전 방식
애플리케이션을 복제하여 생성하는 기본적인 방법은 내부적으로 레플리카셋(ReplicaSet)을 활용하는 디플로이먼트를 사용하는 것이다. 쿠버네티스에 디플로이먼트 및 레플리카셋이 도입되기 전에는 레플리케이션컨트롤러(ReplicationController)를 사용하여 복제 애플리케이션을 구성했었다.
다음 내용
- 디플로이먼트 오브젝트에 대해 더 배워보기
2 - 단일 인스턴스 스테이트풀 애플리케이션 실행하기
이 페이지에서는 쿠버네티스 클러스터에서 퍼시스턴트볼륨(PersistentVolume)과 디플로이먼트(Deployment)를 사용하여, 단일 인스턴스 스테이트풀 애플리케이션을 실행하는 방법을 보인다. 해당 애플리케이션은 MySQL이다.
목적
- 사용자 환경의 디스크를 참조하는 퍼시스턴트볼륨 생성하기
- MySQL 디플로이먼트 생성하기
- 알려진 DNS 이름으로 클러스터의 다른 파드에 MySQL 서비스 노출하기
시작하기 전에
-
쿠버네티스 클러스터가 필요하고, kubectl 커맨드-라인 툴이 클러스터와 통신할 수 있도록 설정되어 있어야 한다. 이 튜토리얼은 컨트롤 플레인 호스트가 아닌 노드가 적어도 2개 포함된 클러스터에서 실행하는 것을 추천한다. 만약, 아직 클러스터를 가지고 있지 않다면, minikube를 사용해서 생성하거나 다음의 쿠버네티스 플레이그라운드 중 하나를 사용할 수 있다.
버전 확인을 위해서, 다음 커맨드를 실행kubectl version
. -
여기에서 사용된 퍼시스턴트볼륨클레임을 만족하기 위하여, 기본 스토리지클래스나 정적으로(statically) 프로비저닝 된 퍼시스턴트볼륨을 갖는 퍼시스턴트 볼륨 프로비저너가 필요하다.
MySQL 배포하기
쿠버네티스 디플로이먼트를 생성하고 퍼시스턴트볼륨클레임(PersistentVolumeClaim)을 사용하는 기존 퍼시스턴트볼륨에 연결하여 스테이트풀 애플리케이션을 실행할 수 있다. 예를 들어, 다음 YAML 파일은 MySQL을 실행하고 퍼시스턴트볼륨클레임을 참조하는 디플로이먼트를 기술한다. 이 파일은 /var/lib/mysql에 대한 볼륨 마운트를 정의한 후에, 20G의 볼륨을 요청하는 퍼시트턴트볼륨클레임을 생성한다. 이 클레임은 요구 사항에 적합한 기존 볼륨이나 동적 프로비저너에 의해서 충족된다.
참고: config yaml 파일에 정의된 비밀번호는 안전하지 않다. 더 안전한 해결방법을 위해 쿠버네티스 시크릿 을 보자
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
ports:
- port: 3306
selector:
app: mysql
clusterIP: None
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
spec:
selector:
matchLabels:
app: mysql
strategy:
type: Recreate
template:
metadata:
labels:
app: mysql
spec:
containers:
- image: mysql:5.6
name: mysql
env:
# Use secret in real usage
- name: MYSQL_ROOT_PASSWORD
value: password
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
volumes:
- name: mysql-persistent-storage
persistentVolumeClaim:
claimName: mysql-pv-claim
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-pv-volume
labels:
type: local
spec:
storageClassName: manual
capacity:
storage: 20Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/mnt/data"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pv-claim
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
-
YAML 파일의 PV와 PVC를 배포한다.
kubectl apply -f https://k8s.io/examples/application/mysql/mysql-pv.yaml
-
YAML 파일의 다른 오브젝트들을 배포한다.
kubectl apply -f https://k8s.io/examples/application/mysql/mysql-deployment.yaml
-
디플로이먼트에 관한 정보를 확인한다.
kubectl describe deployment mysql
출력은 다음과 유사하다.
Name: mysql Namespace: default CreationTimestamp: Tue, 01 Nov 2016 11:18:45 -0700 Labels: app=mysql Annotations: deployment.kubernetes.io/revision=1 Selector: app=mysql Replicas: 1 desired | 1 updated | 1 total | 0 available | 1 unavailable StrategyType: Recreate MinReadySeconds: 0 Pod Template: Labels: app=mysql Containers: mysql: Image: mysql:5.6 Port: 3306/TCP Environment: MYSQL_ROOT_PASSWORD: password Mounts: /var/lib/mysql from mysql-persistent-storage (rw) Volumes: mysql-persistent-storage: Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace) ClaimName: mysql-pv-claim ReadOnly: false Conditions: Type Status Reason ---- ------ ------ Available False MinimumReplicasUnavailable Progressing True ReplicaSetUpdated OldReplicaSets: <none> NewReplicaSet: mysql-63082529 (1/1 replicas created) Events: FirstSeen LastSeen Count From SubobjectPath Type Reason Message --------- -------- ----- ---- ------------- -------- ------ ------- 33s 33s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set mysql-63082529 to 1
-
디플로이먼트로 생성된 파드를 나열한다.
kubectl get pods -l app=mysql
출력은 다음과 유사하다.
NAME READY STATUS RESTARTS AGE mysql-63082529-2z3ki 1/1 Running 0 3m
-
퍼시스턴트볼륨클레임을 살펴본다.
kubectl describe pvc mysql-pv-claim
출력은 다음과 유사하다.
Name: mysql-pv-claim Namespace: default StorageClass: Status: Bound Volume: mysql-pv-volume Labels: <none> Annotations: pv.kubernetes.io/bind-completed=yes pv.kubernetes.io/bound-by-controller=yes Capacity: 20Gi Access Modes: RWO Events: <none>
MySQL 인스턴스 접근하기
이전의 YAML 파일은 클러스터의 다른 파드가 데이터베이스에
접근할 수 있는 서비스를 생성한다. clusterIP: None
서비스 옵션을 사용하면 서비스의 DNS 이름을 직접 파드의 IP 주소로
해석하도록 처리한다. 이 방법은 서비스에서 연결되는 파드가 오직 하나 뿐이고,
파드의 수를 더 늘릴 필요가 없는 경우에 가장 적합하다.
서버에 접속하기 위하여 MySQL 클라이언트를 실행한다.
kubectl run -it --rm --image=mysql:5.6 --restart=Never mysql-client -- mysql -h mysql -ppassword
이 명령어는 MySQL 클라이언트를 실행하는 파드를 클러스터에 생성하고, 서비스를 통하여 서버에 연결한다. 연결된다면, 스테이트풀 MySQL 데이터베이스가 실행 중임을 알 수 있다.
Waiting for pod default/mysql-client-274442439-zyp6i to be running, status is Pending, pod ready: false
If you don't see a command prompt, try pressing enter.
mysql>
업데이트하기
kubectl apply
명령을 사용하여 기존과 동일한 방식으로 디플로이먼트의
이미지나 다른 부분을 변경할 수 있다. 스테이트풀 애플리케이션과 관련하여 몇 가지
주의 사항이 있다.
- 애플리케이션을 스케일링하지 않는다. 이 설정은 단일 인스턴스 애플리케이션 전용이다. 기본적인 퍼시스턴트볼륨은 하나의 파드에서만 마운트할 수 있다. 클러스터 형태의 스테이트풀 애플리케이션에 대해서는 스테이트풀셋을 보자.
- 디플로이먼트 구성 YAML 파일에서
strategy:
type: Recreate
를 사용한다. 이는 쿠버네티스가 롤링 업데이트를 사용하지 않도록 지시한다. 동시에 두 개 이상의 파드를 생성할 수 없으므로, 롤링 업데이트는 일어나지 않게 된다.Recreate
전략을 사용하면 변경된 구성으로 새로운 파드를 생성하기에 앞서 기존의 파드를 중단한다.
디플로이먼트 삭제하기
이름으로 배포된 오브젝트를 삭제한다.
kubectl delete deployment,svc mysql
kubectl delete pvc mysql-pv-claim
kubectl delete pv mysql-pv-volume
퍼시스턴트볼륨을 수동으로 프로비저닝한 경우라면, 동일하게 수동으로 삭제하고 기본 리소스도 해제해야 한다. 동적 프로비저너를 사용한 경우, 퍼시스턴트볼륨클레임이 삭제되었을 때에 퍼시스턴트볼륨 또한 자동으로 삭제된다. 일부 동적 프로비저너(EBS 와 PD와 같은)는 퍼시스턴트볼륨을 삭제할 때에 기본 리소스도 해제한다.
다음 내용
-
디플로이먼트 오브젝트에 대해 더 배워 보기
-
애플리케이션 배포하기에 대해 더 배워보기
3 - 스테이트풀셋(StatefulSet) 삭제하기
이 작업은 스테이트풀셋을 삭제하는 방법을 설명한다.
시작하기 전에
- 이 작업은 클러스터에 스테이트풀셋으로 표시되는 애플리케이션이 있다고 가정한다.
스테이트풀셋 삭제
쿠버네티스에서 다른 리소스를 삭제하는 것과 같은 방식으로 스테이트풀셋을 삭제할 수 있다. kubectl delete
명령어를 사용하고 파일 또는 이름으로 스테이트풀셋을 지정하자.
kubectl delete -f <file.yaml>
kubectl delete statefulsets <statefulset-name>
스테이트풀셋 자체를 삭제한 후 연결된 헤드리스 서비스는 별도로 삭제해야 할 수도 있다.
kubectl delete service <service-name>
kubectl을 통해 스테이트풀셋을 삭제하면, 스테이트풀셋의 크기가 0으로 설정되고 이로 인해 스테이트풀셋에 포함된 모든 파드가 삭제된다. 파드가 아닌 스테이트풀셋만 삭제하려면, --cascade=orphan
옵션을 사용한다.
예시는 다음과 같다.
kubectl delete -f <file.yaml> --cascade=orphan
kubectl delete
에 --cascade=orphan
를 사용하면 스테이트풀셋 오브젝트가 삭제된 후에도 스테이트풀셋에 의해 관리된 파드는 남게 된다. 만약 파드가 app=myapp
레이블을 갖고 있다면, 다음과 같이 파드를 삭제할 수 있다.
kubectl delete pods -l app=myapp
퍼시스턴트볼륨(PersistentVolume)
스테이트풀셋의 파드들을 삭제하는 것이 연결된 볼륨을 삭제하는 것은 아니다. 이것은 볼륨을 삭제하기 전에 볼륨에서 데이터를 복사할 수 있는 기회를 준다. 파드가 종료된 후 PVC를 삭제하면 스토리지 클래스와 반환 정책에 따라 백업 퍼시스턴트볼륨 삭제가 트리거될 수 있다. 클레임 삭제 후 볼륨에 접근할 수 있다고 가정하면 안된다.
스테이트풀셋의 완벽한 삭제
연결된 파드를 포함해서 스테이트풀셋의 모든 것을 삭제하기 위해 다음과 같이 일련의 명령을 실행한다.
grace=$(kubectl get pods <stateful-set-pod> --template '{{.spec.terminationGracePeriodSeconds}}')
kubectl delete statefulset -l app=myapp
sleep $grace
kubectl delete pvc -l app=myapp
위의 예에서 파드에는 app=myapp
라는 레이블이 있다. 사용자에게 적절한 레이블로 대체하자.
스테이트풀셋 파드의 강제 삭제
스테이트풀셋의 일부 파드가 오랫동안 'Terminating' 또는 'Unknown' 상태에 있는 경우, apiserver에 수동적으로 개입하여 파드를 강제 삭제할 수도 있다. 이것은 잠재적으로 위험한 작업이다. 자세한 설명은 스테이트풀셋 파드 강제 삭제하기를 참고한다.
다음 내용
스테이트풀셋 파드 강제 삭제하기에 대해 더 알아보기.
4 - Horizontal Pod Autoscaler
Horizontal Pod Autoscaler는 CPU 사용량 (또는 사용자 정의 메트릭, 아니면 다른 애플리케이션 지원 메트릭)을 관찰하여 레플리케이션 컨트롤러(ReplicationController), 디플로이먼트(Deployment), 레플리카셋(ReplicaSet) 또는 스테이트풀셋(StatefulSet)의 파드 개수를 자동으로 스케일한다. Horizontal Pod Autoscaler는 크기를 조정할 수 없는 오브젝트(예: 데몬셋(DaemonSet))에는 적용되지 않는다.
Horizontal Pod Autoscaler는 쿠버네티스 API 리소스 및 컨트롤러로 구현된다. 리소스는 컨트롤러의 동작을 결정한다. 컨트롤러는 평균 CPU 사용률, 평균 메모리 사용률 또는 다른 커스텀 메트릭과 같은 관찰 대상 메트릭이 사용자가 지정한 목표값과 일치하도록 레플리케이션 컨트롤러 또는 디플로이먼트에서 레플리카 개수를 주기적으로 조정한다.
Horizontal Pod Autoscaler는 어떻게 작동하는가?
Horizontal Pod Autoscaler는 컨트롤러
관리자의 --horizontal-pod-autoscaler-sync-period
플래그(기본값은
15초)에 의해 제어되는 주기를 가진 컨트롤 루프로 구현된다.
각 주기 동안 컨트롤러 관리자는 각 HorizontalPodAutoscaler 정의에 지정된 메트릭에 대해 리소스 사용률을 질의한다. 컨트롤러 관리자는 리소스 메트릭 API(파드 단위 리소스 메트릭 용) 또는 사용자 지정 메트릭 API(다른 모든 메트릭 용)에서 메트릭을 가져온다.
-
파드 단위 리소스 메트릭(예 : CPU)의 경우 컨트롤러는 HorizontalPodAutoscaler가 대상으로하는 각 파드에 대한 리소스 메트릭 API에서 메트릭을 가져온다. 그런 다음, 목표 사용률 값이 설정되면, 컨트롤러는 각 파드의 컨테이너에 대한 동등한 자원 요청을 퍼센트 단위로 하여 사용률 값을 계산한다. 대상 원시 값이 설정된 경우 원시 메트릭 값이 직접 사용된다. 그리고, 컨트롤러는 모든 대상 파드에서 사용된 사용률의 평균 또는 원시 값(지정된 대상 유형에 따라 다름)을 가져와서 원하는 레플리카의 개수를 스케일하는데 사용되는 비율을 생성한다.
파드의 컨테이너 중 일부에 적절한 리소스 요청이 설정되지 않은 경우, 파드의 CPU 사용률은 정의되지 않으며, 따라서 오토스케일러는 해당 메트릭에 대해 아무런 조치도 취하지 않는다. 오토스케일링 알고리즘의 작동 방식에 대한 자세한 내용은 아래 알고리즘 세부 정보 섹션을 참조하기 바란다.
-
파드 단위 사용자 정의 메트릭의 경우, 컨트롤러는 사용률 값이 아닌 원시 값을 사용한다는 점을 제외하고는 파드 단위 리소스 메트릭과 유사하게 작동한다.
-
오브젝트 메트릭 및 외부 메트릭의 경우, 문제의 오브젝트를 표현하는 단일 메트릭을 가져온다. 이 메트릭은 목표 값과 비교되어 위와 같은 비율을 생성한다.
autoscaling/v2beta2
API 버전에서는, 비교가 이루어지기 전에 해당 값을 파드의 개수로 선택적으로 나눌 수 있다.
HorizontalPodAutoscaler는 보통 일련의 API 집합(metrics.k8s.io
,
custom.metrics.k8s.io
, external.metrics.k8s.io
)에서 메트릭을 가져온다. metrics.k8s.io
API는 대개 별도로
시작해야 하는 메트릭-서버에 의해 제공된다. 가이드는
메트릭-서버를
참조한다. HorizontalPodAutoscaler는 힙스터(Heapster)에서 직접 메트릭을 가져올 수도 있다.
Kubernetes v1.11 [deprecated]
힙스터에서 메트릭 가져오기는 Kubernetes 1.11에서 사용 중단(deprecated)됨.
자세한 사항은 메트릭 API를 위한 지원을 참조한다.
오토스케일러는 스케일 하위 리소스를 사용하여 상응하는 확장 가능 컨트롤러(예: 레플리케이션 컨트롤러, 디플로이먼트, 레플리케이션 셋)에 접근한다. 스케일은 레플리카의 개수를 동적으로 설정하고 각 현재 상태를 검사 할 수 있게 해주는 인터페이스이다. 하위 리소스 스케일에 대한 자세한 내용은 여기에서 확인할 수 있다.
알고리즘 세부 정보
가장 기본적인 관점에서, Horizontal Pod Autoscaler 컨트롤러는 원하는(desired) 메트릭 값과 현재(current) 메트릭 값 사이의 비율로 작동한다.
원하는 레플리카 수 = ceil[현재 레플리카 수 * ( 현재 메트릭 값 / 원하는 메트릭 값 )]
예를 들어 현재 메트릭 값이 200m
이고 원하는 값이
100m
인 경우 200.0 / 100.0 == 2.0
이므로 복제본 수가 두 배가
된다. 만약 현재 값이 50m
이면, 50.0 / 100.0 == 0.5
이므로
복제본 수를 반으로 줄일 것이다. 비율이 1.0(0.1을 기본값으로 사용하는
-horizontal-pod-autoscaler-tolerance
플래그를 사용하여
전역적으로 구성 가능한 허용 오차 내)에 충분히 가깝다면 스케일링을 건너 뛸 것이다.
targetAverageValue
또는 targetAverageUtilization
가 지정되면,
currentMetricValue
는 HorizontalPodAutoscaler의 스케일 목표
안에 있는 모든 파드에서 주어진 메트릭의 평균을 취하여 계산된다.
허용치를 확인하고 최종 값을 결정하기 전에, 파드
준비 상태와 누락된 메트릭을 고려한다.
삭제 타임 스탬프가 설정된 모든 파드(즉, 종료 중인 파드) 및 실패한 파드는 모두 폐기된다.
특정 파드에 메트릭이 누락된 경우, 나중을 위해 처리를 미뤄두는데, 이와 같이 누락된 메트릭이 있는 모든 파드는 최종 스케일 량을 조정하는데 사용된다.
CPU를 스케일할 때, 어떤 파드라도 아직 준비가 안되었거나 (즉, 여전히 초기화 중인 경우) * 또는 * 파드의 최신 메트릭 포인트가 준비되기 전이라면, 마찬가지로 해당 파드는 나중에 처리된다.
기술적 제약으로 인해, HorizontalPodAutoscaler 컨트롤러는
특정 CPU 메트릭을 나중에 사용할지 말지 결정할 때, 파드가 준비되는
시작 시간을 정확하게 알 수 없다. 대신, 파드가 아직 준비되지
않았고 시작 이후 짧은 시간 내에 파드가 준비되지 않은 상태로
전환된다면, 해당 파드를 "아직 준비되지 않음(not yet ready)"으로 간주한다.
이 값은 --horizontal-pod-autoscaler-initial-readiness-delay
플래그로 설정되며, 기본값은 30초
이다. 일단 파드가 준비되고 시작된 후 구성 가능한 시간 이내이면,
준비를 위한 어떠한 전환이라도 이를 시작 시간으로 간주한다. 이
값은 --horizontal-pod-autoscaler-cpu-initialization-period
플래그로 설정되며
기본값은 5분이다.
현재 메트릭 값 / 원하는 메트릭 값
기본 스케일 비율은 나중에
사용하기로 되어 있거나 위에서 폐기되지 않은 남아있는 파드를 사용하여 계산된다.
누락된 메트릭이 있는 경우, 파드가 스케일 다운의 경우 원하는 값의 100%를 소비하고 스케일 업의 경우 0%를 소비한다고 가정하여 평균을 보다 보수적으로 재계산한다. 이것은 잠재적인 스케일의 크기를 약화시킨다.
또한 아직-준비되지-않은 파드가 있는 경우 누락된 메트릭이나 아직-준비되지-않은 파드를 고려하지 않고 스케일 업했을 경우, 아직-준비되지-않은 파드가 원하는 메트릭의 0%를 소비한다고 보수적으로 가정하고 스케일 확장의 크기를 약화시킨다.
아직-준비되지-않은 파드나 누락된 메트릭을 고려한 후에 사용 비율을 다시 계산한다. 새 비율이 스케일 방향을 바꾸거나, 허용 오차 내에 있으면 스케일링을 건너뛴다. 그렇지 않으면, 새 비율을 사용하여 스케일한다.
평균 사용량에 대한 원래 값은 새로운 사용 비율이 사용되는 경우에도 아직-준비되지-않은 파드 또는 누락된 메트릭에 대한 고려없이 HorizontalPodAutoscaler 상태를 통해 다시 보고된다.
HorizontalPodAutoscaler에 여러 메트릭이 지정된 경우, 이 계산은
각 메트릭에 대해 수행된 다음 원하는 레플리카 수 중 가장
큰 값이 선택된다. 이러한 메트릭 중 어떠한 것도 원하는
레플리카 수로 변환할 수 없는 경우(예 : 메트릭 API에서 메트릭을
가져오는 중 오류 발생) 스케일을 건너뛴다.
이는 하나 이상의 메트릭이
현재 값보다 높은 desiredReplicas
을 제공하는 경우
HPA가 여전히 확장할 수 있음을 의미한다.
마지막으로, HPA가 목표를 스케일하기 직전에 스케일 권장 사항이
기록된다. 컨트롤러는 구성 가능한 창(window) 내에서 가장 높은 권장
사항을 선택하도록 해당 창 내의 모든 권장 사항을 고려한다. 이 값은 --horizontal-pod-autoscaler-downscale-stabilization
플래그를 사용하여 설정할 수 있고, 기본값은 5분이다.
즉, 스케일 다운이 점진적으로 발생하여 급격히 변동하는 메트릭 값의
영향을 완만하게 한다.
API 오브젝트
Horizontal Pod Autoscaler는 쿠버네티스 autoscaling
API 그룹의 API 리소스이다.
CPU에 대한 오토스케일링 지원만 포함하는 안정된 버전은
autoscaling/v1
API 버전에서 찾을 수 있다.
메모리 및 사용자 정의 메트릭에 대한 스케일링 지원을 포함하는 베타 버전은
autoscaling/v2beta2
에서 확인할 수 있다. autoscaling/v2beta2
에서 소개된
새로운 필드는 autoscaling/v1
로 작업할 때 어노테이션으로 보존된다.
HorizontalPodAutoscaler API 오브젝트 생성시 지정된 이름이 유효한 DNS 서브도메인 이름인지 확인해야 한다. API 오브젝트에 대한 자세한 내용은 HorizontalPodAutoscaler 오브젝트에서 찾을 수 있다.
kubectl에서 Horizontal Pod Autoscaler 지원
Horizontal Pod Autoscaler는 모든 API 리소스와 마찬가지로 kubectl
에 의해 표준 방식으로 지원된다.
kubectl create
커맨드를 사용하여 새로운 오토스케일러를 만들 수 있다.
kubectl get hpa
로 오토스케일러 목록을 조회할 수 있고, kubectl describe hpa
로 세부 사항을 확인할 수 있다.
마지막으로 kubectl delete hpa
를 사용하여 오토스케일러를 삭제할 수 있다.
또한 Horizontal Pod Autoscaler를 생성할 수 있는 kubectl autoscale
이라는 특별한 명령이 있다.
예를 들어 kubectl autoscale rs foo --min=2 --max=5 --cpu-percent=80
을
실행하면 레플리케이션 셋 foo 에 대한 오토스케일러가 생성되고, 목표 CPU 사용률은 80 %
,
그리고 2와 5 사이의 레플리카 개수로 설정된다.
kubectl autoscale
에 대한 자세한 문서는 여기에서 찾을 수 있다.
롤링 업데이트 중 오토스케일링
쿠버네티스는 디플로이먼트에 대한 롤링 업데이트를 지원한다.
이 경우, 디플로이먼트가 기저 레플리카셋을 알아서 관리한다.
디플로이먼트에 오토스케일링을 설정하려면,
각 디플로이먼트에 대한 HorizontalPodAutoscaler를 생성한다.
HorizontalPodAutoscaler는 디플로이먼트의 replicas
필드를 관리한다.
디플로이먼트 컨트롤러는 기저 레플리카셋에 replicas
값을 적용하여
롤아웃 과정 중/이후에 적절한 숫자까지 늘어나도록 한다.
오토스케일된 레플리카가 있는 스테이트풀셋의 롤링 업데이트를 수행하면, 스테이트풀셋이 직접 파드의 숫자를 관리한다(즉, 레플리카셋과 같은 중간 리소스가 없다).
쿨-다운 / 지연에 대한 지원
Horizontal Pod Autoscaler를 사용하여 레플리카 그룹의 스케일을 관리할 때, 평가된 메트릭의 동적인 특징 때문에 레플리카 수가 자주 변동할 수 있다. 이것은 때로는 스래싱 (thrashing) 이라고도 한다.
v1.6 부터 클러스터 운영자는 kube-controller-manager
컴포넌트의 플래그로
노출된 글로벌 HPA 설정을 튜닝하여 이 문제를 완화할 수 있다.
v1.12부터는 새로운 알고리즘 업데이트가 업스케일 지연에 대한 필요성을 제거하였다.
--horizontal-pod-autoscaler-downscale-delay
: 다운스케일이 안정화되기까지의 시간 간격을 지정한다. Horizontal Pod Autoscaler는 이전의 권장하는 크기를 기억하고, 이 시간 간격에서의 가장 큰 크기에서만 작동한다. 기본값은 5분(5m0s
)이다.
리소스 메트릭 지원
모든 HPA 대상은 스케일링 대상에서 파드의 리소스 사용량을 기준으로 스케일링할 수 있다.
파드의 명세를 정의할 때는 cpu
및 memory
와 같은 리소스 요청을
지정해야 한다. 이것은 리소스 사용률을 결정하는 데 사용되며 HPA 컨트롤러에서 대상을
스케일링하거나 축소하는 데 사용한다. 리소스 사용률 기반 스케일링을 사용하려면 다음과 같은 메트릭 소스를
지정해야 한다.
type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
이 메트릭을 사용하면 HPA 컨트롤러는 스케일링 대상에서 파드의 평균 사용률을 60%로 유지한다. 사용률은 파드의 요청된 리소스에 대한 현재 리소스 사용량 간의 비율이다. 사용률 계산 및 평균 산출 방법에 대한 자세한 내용은 알고리즘을 참조한다.
컨테이너 리소스 메트릭
Kubernetes v1.20 [alpha]
HorizontalPodAutoscaler
는 대상 리소스를 스케일링하기 위해 HPA가 파드 집합에서 개별 컨테이너의
리소스 사용량을 추적할 수 있는 컨테이너 메트릭 소스도 지원한다.
이를 통해 특정 파드에서 가장 중요한 컨테이너의 스케일링 임계값을 구성할 수 있다.
예를 들어 웹 애플리케이션 프로그램과 로깅 사이드카가 있는 경우 사이드카 컨테이너와 해당 리소스 사용을 무시하고
웹 애플리케이션의 리소스 사용을 기준으로 스케일링할 수 있다.
대상 리소스를 다른 컨테이너 세트를 사용하여 새 파드 명세를 갖도록 수정하는 경우 새로 추가된 컨테이너도 스케일링에 사용해야 한다면 HPA 사양을 수정해야 한다. 메트릭 소스에 지정된 컨테이너가 없거나 파드의 하위 집합에만 있는 경우 해당 파드는 무시되고 권장 사항이 다시 계산된다. 계산에 대한 자세한 내용은 알고리즘을 을 참조한다. 컨테이너 리소스를 오토스케일링에 사용하려면 다음과 같이 메트릭 소스를 정의한다.
type: ContainerResource
containerResource:
name: cpu
container: application
target:
type: Utilization
averageUtilization: 60
위의 예에서 HPA 컨트롤러는 모든 파드의 application
컨테이너에 있는 CPU의 평균 사용률이
60%가 되도록 대상을 조정한다.
HorizontalPodAutoscaler가 추적하는 컨테이너의 이름을 변경하는 경우 특정 순서로 변경을 수행하여 변경 사항이 적용되는 동안 스케일링을 계속 사용할 수 있고 효율적으로 유지할 수 있다. 컨테이너를 정의하는 리소스(예: 배포)를 업데이트하기 전에 연결된 HPA를 업데이트하여 새 컨테이너 이름과 이전 컨테이너 이름을 모두 추적해야 한다. 이러한 방식으로 HPA는 업데이트 프로세스 전반에 걸쳐 스케일링 권장 사항을 계산할 수 있다.
컨테이너 이름 변경을 워크로드 리소스로 롤아웃한 후에는 HPA 사양에서 이전 컨테이너 이름을 제거하여 정리한다.
멀티 메트릭을 위한 지원
Kubernetes 1.6은 멀티 메트릭을 기반으로 스케일링을 지원한다. autoscaling/v2beta2
API
버전을 사용하여 Horizontal Pod Autoscaler가 스케일을 조정할 멀티 메트릭을 지정할 수 있다. 그런 다음 Horizontal Pod
Autoscaler 컨트롤러가 각 메트릭을 평가하고, 해당 메트릭을 기반으로 새 스케일을 제안한다.
제안된 스케일 중 가장 큰 것이 새로운 스케일로 사용된다.
사용자 정의 메트릭을 위한 지원
쿠버네티스 1.6에서는 Horizontal Pod Autoscaler에서 사용자 정의 메트릭을 사용할 수 있도록 지원한다.
autoscaling/v2beta2
API에서 사용할 Horizontal Pod Autoscaler에 대한 사용자 정의 메트릭을 추가 할 수 있다.
그리고 쿠버네티스는 새 사용자 정의 메트릭 API에 질의하여 적절한 사용자 정의 메트릭의 값을 가져온다.
요구 사항은 메트릭을 위한 지원을 참조한다.
메트릭 API를 위한 지원
기본적으로 HorizontalPodAutoscaler 컨트롤러는 일련의 API에서 메트릭을 검색한다. 이러한 API에 접속하려면 클러스터 관리자는 다음을 확인해야 한다.
-
API 애그리게이션 레이어 활성화
-
해당 API 등록:
-
리소스 메트릭의 경우, 일반적으로 이것은 메트릭-서버가 제공하는
metrics.k8s.io
API이다. 클러스터 애드온으로 시작할 수 있다. -
사용자 정의 메트릭의 경우, 이것은
custom.metrics.k8s.io
API이다. 메트릭 솔루션 공급 업체에서 제공하는 "어댑터" API 서버에서 제공한다. 메트릭 파이프라인 또는 알려진 솔루션 목록으로 확인한다. 직접 작성하고 싶다면 샘플을 확인한다. -
외부 메트릭의 경우, 이것은
external.metrics.k8s.io
API이다. 위에 제공된 사용자 정의 메트릭 어댑터에서 제공될 수 있다.
-
-
--horizontal-pod-autoscaler-use-rest-clients
는true
이거나 설정되지 않음. 이것을 false로 설정하면 더 이상 사용되지 않는 힙스터 기반 오토스케일링으로 전환된다.
이런 다양한 메트릭 경로와 각각의 다른 점에 대한 상세 내용은 관련 디자인 제안서인 HPA V2, custom.metrics.k8s.io, external.metrics.k8s.io를 참조한다.
어떻게 사용하는지에 대한 예시는 커스텀 메트릭 사용하는 작업 과정과 외부 메트릭스 사용하는 작업 과정을 참조한다.
구성가능한 스케일링 동작 지원
v1.18
부터 v2beta2
API는 HPA behavior
필드를 통해
스케일링 동작을 구성할 수 있다.
동작은 behavior
필드 아래의 scaleUp
또는 scaleDown
섹션에서 스케일링 업과 다운을 위해 별도로 지정된다. 안정화 윈도우는
스케일링 대상에서 레플리카 수의 플래핑(flapping)을 방지하는
양방향에 대해 지정할 수 있다. 마찬가지로 스케일링 정책을 지정하면
스케일링 중 레플리카 변경 속도를 제어할 수 있다.
스케일링 정책
스펙의 behavior
섹션에 하나 이상의 스케일링 폴리시를 지정할 수 있다.
폴리시가 여러 개 지정된 경우 가장 많은 양의 변경을
허용하는 정책이 기본적으로 선택된 폴리시이다. 다음 예시는 스케일 다운 중 이
동작을 보여준다.
behavior:
scaleDown:
policies:
- type: Pods
value: 4
periodSeconds: 60
- type: Percent
value: 10
periodSeconds: 60
periodSeconds
는 폴리시가 참(true)으로 유지되어야 하는 기간을 나타낸다.
첫 번째 정책은 (파드들) 이 1분 내에 최대 4개의 레플리카를 스케일 다운할 수 있도록 허용한다.
두 번째 정책은 비율 로 현재 레플리카의 최대 10%를 1분 내에 스케일 다운할 수 있도록 허용한다.
기본적으로 가장 많은 변경을 허용하는 정책이 선택되기에 두 번째 정책은 파드의 레플리카 수가 40개를 초과하는 경우에만 사용된다. 레플리카가 40개 이하인 경우 첫 번째 정책이 적용된다. 예를 들어 80개의 레플리카가 있고 대상을 10개의 레플리카로 축소해야 하는 경우 첫 번째 단계에서 8개의 레플리카가 스케일 다운 된다. 레플리카의 수가 72개일 때 다음 반복에서 파드의 10%는 7.2 이지만, 숫자는 8로 올림된다. 오토스케일러 컨트롤러의 각 루프에서 변경될 파드의 수는 현재 레플리카의 수에 따라 재계산된다. 레플리카의 수가 40 미만으로 떨어지면 첫 번째 폴리시 (파드들) 가 적용되고 한번에 4개의 레플리카가 줄어든다.
확장 방향에 대해 selectPolicy
필드를 확인하여 폴리시 선택을 변경할 수 있다.
레플리카의 수를 최소로 변경할 수 있는 폴리시를 선택하는 최소(Min)
로 값을 설정한다.
값을 Disabled
로 설정하면 해당 방향으로 스케일링이 완전히
비활성화 된다.
안정화 윈도우
안정화 윈도우는 스케일링에 사용되는 메트릭이 계속 변동할 때 레플리카의 플래핑을
다시 제한하기 위해 사용된다. 안정화 윈도우는 스케일링을 방지하기 위해 과거부터
계산된 의도한 상태를 고려하는 오토스케일링 알고리즘에 의해 사용된다.
다음의 예시에서 scaleDown
에 대해 안정화 윈도우가 지정되어있다.
scaleDown:
stabilizationWindowSeconds: 300
메트릭이 대상을 축소해야하는 것을 나타내는 경우 알고리즘은 이전에 계산된 의도한 상태를 살펴보고 지정된 간격의 최고 값을 사용한다. 위의 예시에서 지난 5분 동안 모든 의도한 상태가 고려된다.
기본 동작
사용자 지정 스케일링을 사용하려면 일부 필드를 지정해야 한다. 사용자 정의해야 하는 값만 지정할 수 있다. 이러한 사용자 지정 값은 기본값과 병합된다. 기본값은 HPA 알고리즘의 기존 동작과 일치한다.
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 100
periodSeconds: 15
scaleUp:
stabilizationWindowSeconds: 0
policies:
- type: Percent
value: 100
periodSeconds: 15
- type: Pods
value: 4
periodSeconds: 15
selectPolicy: Max
안정화 윈도우의 스케일링 다운의 경우 300 초 (또는 제공된
경우--horizontal-pod-autoscaler-downscale-stabilization
플래그의 값)이다. 스케일링 다운에서는 현재
실행 중인 레플리카의 100%를 제거할 수 있는 단일 정책만 있으며, 이는 스케일링
대상을 최소 허용 레플리카로 축소할 수 있음을 의미한다.
스케일링 업에는 안정화 윈도우가 없다. 메트릭이 대상을 스케일 업해야 한다고 표시된다면 대상이 즉시 스케일 업된다.
두 가지 폴리시가 있다. HPA가 정상 상태에 도달 할 때까지 15초 마다
4개의 파드 또는 현재 실행 중인 레플리카의 100% 가 추가된다.
예시: 다운스케일 안정화 윈도우 변경
사용자 지정 다운스케일 안정화 윈도우를 1분 동안 제공하기 위해 다음 동작이 HPA에 추가된다.
behavior:
scaleDown:
stabilizationWindowSeconds: 60
예시: 스케일 다운 비율 제한
HPA에 의해 파드가 제거되는 속도를 분당 10%로 제한하기 위해 다음 동작이 HPA에 추가된다.
behavior:
scaleDown:
policies:
- type: Percent
value: 10
periodSeconds: 60
마지막으로 5개의 파드를 드롭하기 위해 다른 폴리시를 추가하고, 최소 선택
전략을 추가할 수 있다.
분당 5개 이하의 파드가 제거되지 않도록, 고정 크기가 5인 두 번째 축소
정책을 추가하고, selectPolicy
를 최소로 설정하면 된다. selectPolicy
를 Min
으로 설정하면
자동 스케일러가 가장 적은 수의 파드에 영향을 주는 정책을 선택함을 의미한다.
behavior:
scaleDown:
policies:
- type: Percent
value: 10
periodSeconds: 60
- type: Pods
value: 5
periodSeconds: 60
selectPolicy: Min
예시: 스케일 다운 비활성화
selectPolicy
의 Disabled
값은 주어진 방향으로의 스케일링을 끈다.
따라서 다운 스케일링을 방지하기 위해 다음 폴리시가 사용된다.
behavior:
scaleDown:
selectPolicy: Disabled
암시적 유지 관리 모드 비활성화
HPA 구성 자체를 변경할 필요없이 대상에 대한
HPA를 암시적으로 비활성화할 수 있다. 대상의 의도한
레플리카 수가 0으로 설정되고, HPA의 최소 레플리카 수가 0 보다 크면, 대상의
의도한 레플리카 수 또는 HPA의 최소 레플리카 수를 수동으로 조정하여
다시 활성화할 때까지 HPA는 대상 조정을
중지한다(그리고 ScalingActive
조건 자체를 false
로 설정).
다음 내용
- 디자인 문서: Horizontal Pod Autoscaling.
- kubectl 오토스케일 커맨드: kubectl autoscale.
- Horizontal Pod Autoscaler의 사용 예제.
5 - Horizontal Pod Autoscaler 연습
Horizontal Pod Autoscaler는 CPU 사용량(또는 베타 지원의 다른 애플리케이션 지원 메트릭)을 관찰하여 레플리케이션 컨트롤러, 디플로이먼트, 레플리카셋(ReplicaSet) 또는 스테이트풀셋(StatefulSet)의 파드 개수를 자동으로 스케일한다.
이 문서는 php-apache 서버를 대상으로 Horizontal Pod Autoscaler를 동작해보는 예제이다. Horizontal Pod Autoscaler 동작과 관련된 더 많은 정보를 위해서는 Horizontal Pod Autoscaler 사용자 가이드를 참고하기 바란다.
시작하기 전에
이 예제는 버전 1.2 또는 이상의 쿠버네티스 클러스터와 kubectl을 필요로 한다. 메트릭 서버 모니터링을 클러스터에 배포하여 메트릭 API를 통해 메트릭을 제공해야 한다. Horizontal Pod Autoscaler가 메트릭을 수집할때 해당 API를 사용한다. 메트릭-서버를 배포하는 방법에 대해 배우려면, 메트릭-서버 문서를 참고한다.
Horizontal Pod Autoscaler에 다양한 자원 메트릭을 적용하고자 하는 경우, 버전 1.6 또는 이상의 쿠버네티스 클러스터와 kubectl를 사용해야 한다. 사용자 정의 메트릭을 사용하기 위해서는, 클러스터가 사용자 정의 메트릭 API를 제공하는 API 서버와 통신할 수 있어야 한다. 마지막으로 쿠버네티스 오브젝트와 관련이 없는 메트릭을 사용하는 경우, 버전 1.10 또는 이상의 쿠버네티스 클러스터와 kubectl을 사용해야 하며, 외부 메트릭 API와 통신이 가능해야 한다. 자세한 사항은 Horizontal Pod Autoscaler 사용자 가이드를 참고하길 바란다.
php-apache 서버 구동 및 노출
Horizontal Pod Autoscaler 시연을 위해 php-apache 이미지를 맞춤 제작한 Docker 이미지를 사용한다. Dockerfile은 다음과 같다.
FROM php:5-apache
COPY index.php /var/www/html/index.php
RUN chmod a+rx index.php
index.php는 CPU 과부하 연산을 수행한다.
<?php
$x = 0.0001;
for ($i = 0; $i <= 1000000; $i++) {
$x += sqrt($x);
}
echo "OK!";
?>
첫 번째 단계로, 다음 구성을 사용해서 실행 중인 이미지의 디플로이먼트를 시작하고 서비스로 노출시킨다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: php-apache
spec:
selector:
matchLabels:
run: php-apache
replicas: 1
template:
metadata:
labels:
run: php-apache
spec:
containers:
- name: php-apache
image: k8s.gcr.io/hpa-example
ports:
- containerPort: 80
resources:
limits:
cpu: 500m
requests:
cpu: 200m
---
apiVersion: v1
kind: Service
metadata:
name: php-apache
labels:
run: php-apache
spec:
ports:
- port: 80
selector:
run: php-apache
다음의 명령어를 실행한다.
kubectl apply -f https://k8s.io/examples/application/php-apache.yaml
deployment.apps/php-apache created
service/php-apache created
Horizontal Pod Autoscaler 생성
이제 서비스가 동작중이므로, kubectl autoscale를 사용하여 오토스케일러를 생성한다. 다음 명령어는 첫 번째 단계에서 만든 php-apache 디플로이먼트 파드의 개수를 1부터 10 사이로 유지하는 Horizontal Pod Autoscaler를 생성한다. 간단히 얘기하면, HPA는 (디플로이먼트를 통한) 평균 CPU 사용량을 50%로 유지하기 위하여 레플리카의 개수를 늘리고 줄인다. (kubectl run으로 각 파드는 200 밀리코어까지 요청할 수 있고, 따라서 여기서 말하는 평균 CPU 사용은 100 밀리코어를 말한다). 이에 대한 자세한 알고리즘은 여기를 참고하기 바란다.
kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10
horizontalpodautoscaler.autoscaling/php-apache autoscaled
실행 중인 오토스케일러의 현재 상태를 확인해본다.
kubectl get hpa
NAME REFERENCE TARGET MINPODS MAXPODS REPLICAS AGE
php-apache Deployment/php-apache/scale 0% / 50% 1 10 1 18s
아직 서버로 어떠한 요청도 하지 않았기 때문에, 현재 CPU 소비는 0%임을 확인할 수 있다 (TARGET
은 디플로이먼트에 의해 제어되는 파드들의 평균을 나타낸다).
부하 증가
이번에는 부하가 증가함에 따라 오토스케일러가 어떻게 반응하는지를 살펴볼 것이다. 먼저 컨테이너를 하나 실행하고, php-apache 서비스에 무한루프의 쿼리를 전송한다(다른 터미널을 열어 수행하기 바란다).
kubectl run -i --tty load-generator --rm --image=busybox --restart=Never -- /bin/sh -c "while sleep 0.01; do wget -q -O- http://php-apache; done"
실행 후, 약 1분 정도 후에 CPU 부하가 올라가는 것을 볼 수 있다.
kubectl get hpa
NAME REFERENCE TARGET MINPODS MAXPODS REPLICAS AGE
php-apache Deployment/php-apache/scale 305% / 50% 1 10 1 3m
CPU 소비가 305%까지 증가하였다. 결과적으로, 디플로이먼트의 레플리카 개수는 7개까지 증가하였다.
kubectl get deployment php-apache
NAME READY UP-TO-DATE AVAILABLE AGE
php-apache 7/7 7 7 19m
부하 중지
본 예제를 마무리하기 위해 부하를 중단시킨다.
busybox
컨테이너를 띄운 터미널에서,
<Ctrl> + C
로 부하 발생을 중단시킨다.
그런 다음 (몇 분 후에) 결과를 확인한다.
kubectl get hpa
NAME REFERENCE TARGET MINPODS MAXPODS REPLICAS AGE
php-apache Deployment/php-apache/scale 0% / 50% 1 10 1 11m
kubectl get deployment php-apache
NAME READY UP-TO-DATE AVAILABLE AGE
php-apache 1/1 1 1 27m
CPU 사용량은 0으로 떨어졌고, HPA는 레플리카의 개수를 1로 낮췄다.
다양한 메트릭 및 사용자 정의 메트릭을 기초로한 오토스케일링
php-apache
디플로이먼트를 오토스케일링할 때,
autoscaling/v2beta2
API 버전을 사용하여 추가적인 메트릭을 제공할 수 있다.
첫 번째로, autoscaling/v2beta2
형식으로 HorizontalPodAutoscaler YAML 파일을 생성한다.
kubectl get hpa php-apache -o yaml > /tmp/hpa-v2.yaml
에디터로 /tmp/hpa-v2.yaml
파일을 열면, 다음과 같은 YAML을 확인할 수 있다.
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: php-apache
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: php-apache
minReplicas: 1
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50
status:
observedGeneration: 1
lastScaleTime: <some-time>
currentReplicas: 1
desiredReplicas: 1
currentMetrics:
- type: Resource
resource:
name: cpu
current:
averageUtilization: 0
averageValue: 0
targetCPUUtilizationPercentage
필드가 metrics
배열로 대체되었다.
CPU 사용량 메트릭은 resource metric 으로 파드 컨테이너 자원의 백분율로 표현된다.
CPU 외에 다른 메트릭을 지정할 수 있는데, 기본적으로 지원되는 다른 메트릭은 메모리뿐이다.
이 자원들은 한 클러스터에서 다른 클러스터로 이름을 변경할 수 없으며,
metrics.k8s.io
API가 가용한 경우 언제든지 사용할 수 있어야 한다.
또한, Utilization
대신 AverageValue
의 target
타입을,
그리고 target.averageUtilization
대신 target.averageValue
로 설정하여
자원 메트릭을 퍼센트 대신 값으로 명시할 수 있다.
파드 메트릭과 오브젝트 메트릭 두 가지의 사용자 정의 메트릭 이 있다. 파드 메트릭과 오브젝트 메트릭. 이 메트릭은 클러스터에 특화된 이름을 가지고 있으며, 더 고급화된 클러스터 모니터링 설정이 필요하다.
이러한 대체 메트릭 타입중 첫 번째는 파드 메트릭 이다. 이 메트릭은 파드들을 설명하고, 파드들간의 평균을 내며, 대상 값과 비교하여 레플리카 개수를 결정한다.
이것들은 AverageValue
의 target
만을 지원한다는 것을 제외하면,
자원 메트릭과 매우 유사하게 동작한다.
파드 메트릭은 이처럼 메트릭 블록을 사용하여 정의된다.
type: Pods
pods:
metric:
name: packets-per-second
target:
type: AverageValue
averageValue: 1k
두 번째 대체 메트릭 타입은 오브젝트 메트릭 이다.
이 메트릭은 파드를 기술하는 대신에 동일한 네임스페이스 내에 다른 오브젝트를 표현한다.
이 메트릭은 반드시 오브젝트로부터 가져올 필요는 없다. 단지 오브젝트를 기술할 뿐이다.
오브젝트 메트릭은 Value
과 AverageValue
의 target
타입을 지원한다.
Value
를 사용할 경우 대상은 API로부터 반환되는 메트릭과 직접 비교된다.
AverageValue
를 사용할 경우, 대상 값과 비교되기 이전에 사용자 정의 메트릭 API로부터 반환된 값은 파드의 개수로 나눠진다.
다음은 requests-per-second
메트릭을 YAML로 기술한 예제이다.
type: Object
object:
metric:
name: requests-per-second
describedObject:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
name: main-route
target:
type: Value
value: 2k
이러한 메트릭 블록을 여러 개 제공하면, HorizontalPodAutoscaler는 각 메트릭을 차례로 고려한다. HorizontalPodAutoscaler는 각 메트릭에 대해 제안된 레플리카 개수를 계산하고, 그중 가장 높은 레플리카 개수를 선정한다.
예를 들어, 네트워크 트래픽 메트릭을 수집하는 모니터링 시스템이 있는 경우,
kubectl edit
명령어를 이용하여 다음과 같이 정의를 업데이트 할 수 있다.
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: php-apache
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: php-apache
minReplicas: 1
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50
- type: Pods
pods:
metric:
name: packets-per-second
target:
type: AverageValue
averageValue: 1k
- type: Object
object:
metric:
name: requests-per-second
describedObject:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
name: main-route
target:
type: Value
value: 10k
status:
observedGeneration: 1
lastScaleTime: <some-time>
currentReplicas: 1
desiredReplicas: 1
currentMetrics:
- type: Resource
resource:
name: cpu
current:
averageUtilization: 0
averageValue: 0
- type: Object
object:
metric:
name: requests-per-second
describedObject:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
name: main-route
current:
value: 10k
이후, HorizontalPodAutoscaler는 각 파드가 요청 된 약 50%의 CPU 사용률을 소모하는지, 초당 1000 패킷을 처리하는지, 메인-루트 인그레스 뒤의 모든 파드들이 초당 10000 요청을 처리하는지 확인한다.
보다 구체적인 메트릭을 기초로한 오토스케일링
많은 메트릭 파이프라인들을 사용하면 이름 또는 labels 이라 불리는 추가적인 식별자로 메트릭을 설명할 수 있다.
그리고, 모든 비 자원 메트릭 타입(파드, 오브젝트 그리고 아래 기술된 외부 타입)에 대해,
메트릭 파이프라인으로 전달되는 추가 레이블 셀렉터를 지정할 수 있다.
예를 들면, verb
레이블로 http_requests
메트릭을 수집하는 경우,
다음과 같이 메트릭 블록을 지정하여 GET 요청에 대해 크기를 조정할 수 있다.
type: Object
object:
metric:
name: http_requests
selector: {matchLabels: {verb: GET}}
이 셀렉터는 쿠버네티스의 레이블 셀렉터와 동일한 문법이다.
모니터링 파이프라인은 네임과 셀렉터가 여러 시리즈와 일치하는 경우,
해당 여러 시리즈를 단일 값으로 축소하는 방법을 결정한다.
셀렉터는 부가적인 속성이며,
대상 오브젝트(Pods
타입의 대상 파드, Object
타입으로 기술된 오브젝트)가 아닌 메트릭을 선택할 수 없다.
쿠버네티스 오브젝트와 관련이 없는 메트릭을 기초로한 오토스케일링
쿠버네티스 위에서 동작하는 애플리케이션은, 쿠버네티스 클러스터의 어떤 오브젝트와도 관련이 없는 메트릭에 기반하여 오토스케일링을 할 수도 있다. 예로, 쿠버네티스 네임스페이스와 관련이 없는 서비스를 기초로한 메트릭을 들 수 있다. 쿠버네티스 버전 1.10 포함 이후 버전에서, 외부 메트릭 을 사용하여 이러한 유스케이스를 해결할 수 있다.
외부 메트릭 사용시, 먼저 모니터링 시스템에 대한 이해가 있어야 한다.
이 설치는 사용자 정의 메트릭과 유사하다.
외부 메트릭을 사용하면 모니터링 시스템의 사용 가능한 메트릭에 기반하여 클러스터를 오토스케일링 할 수 있다.
위의 예제처럼 name
과 selector
를 갖는 metric
블록을 명시하고,
Object
대신에 External
메트릭 타입을 사용한다.
만일 여러 개의 시계열이 metricSelector
와 일치하면, HorizontalPodAutoscaler가 값의 합을 사용한다.
외부 메트릭들은 Value
와 AverageValue
대상 타입을 모두 지원하고,
Object
타입을 사용할 때와 똑같이 동작한다.
예를 들면 애플리케이션이 호스팅 된 대기열 서비스에서 작업을 처리하는 경우, 다음과 같이 HorizontalPodAutoscaler 매니퍼스트에 30개의 미해결 태스크 당 한 개의 워커를 지정하도록 추가할 수 있다.
- type: External
external:
metric:
name: queue_messages_ready
selector: "queue=worker_tasks"
target:
type: AverageValue
averageValue: 30
가능하다면, 외부 메트릭 대신 사용자 정의 메트릭 대상 타입을 사용하길 권장한다. 왜냐하면, 클러스터 관리자가 사용자 정의 메트릭 API를 보안관점에서 더 쉽게 보호할 수 있기 때문이다. 외부 메트릭 API는 잠재적으로 어떠한 메트릭에도 접근할 수 있기에, 클러스터 관리자는 API를 노출시킬때 신중해야 한다.
부록: Horizontal Pod Autoscaler 상태 조건
HorizontalPodAutoscaler의 autoscaling/v2beta2
형식을 사용하면,
HorizontalPodAutoscaler에서 쿠버네티스가 설정한 상태 조건 을 확인할 수 있다.
이 상태 조건들은 HorizontalPodAutoscaler가 스케일을 할 수 있는지,
어떤 방식으로든 제한되어 있는지 여부를 나타낸다.
이 조건은 status.conditions
에 나타난다.
HorizontalPodAutoscaler에 영향을 주는 조건을 보기 위해 kubectl describe hpa
를 사용할 수 있다.
kubectl describe hpa cm-test
Name: cm-test
Namespace: prom
Labels: <none>
Annotations: <none>
CreationTimestamp: Fri, 16 Jun 2017 18:09:22 +0000
Reference: ReplicationController/cm-test
Metrics: ( current / target )
"http_requests" on pods: 66m / 500m
Min replicas: 1
Max replicas: 4
ReplicationController pods: 1 current / 1 desired
Conditions:
Type Status Reason Message
---- ------ ------ -------
AbleToScale True ReadyForNewScale the last scale time was sufficiently old as to warrant a new scale
ScalingActive True ValidMetricFound the HPA was able to successfully calculate a replica count from pods metric http_requests
ScalingLimited False DesiredWithinRange the desired replica count is within the acceptable range
Events:
이 HorizontalPodAutoscaler 경우, 건강 상태의 여러 조건들을 볼 수 있다.
첫 번째 AbleToScale
는 HPA가 스케일을 가져오고 업데이트할 수 있는지,
백 오프 관련 조건으로 스케일링이 방지되는지 여부를 나타낸다.
두 번째 ScalingActive
는 HPA가 활성화되어있는지(즉 대상 레플리카 개수가 0이 아닌지),
원하는 스케일을 계산할 수 있는지 여부를 나타낸다. 만약 False
인 경우,
일반적으로 메트릭을 가져오는데 문제가 있다.
마지막으로, 마지막 조건인 ScalingLimited
는
원하는 스케일 한도가 HorizontalPodAutoscaler의 최대/최소값으로 제한돼있음을 나타낸다.
이는 HorizontalPodAutoscaler에서 레플리카의 개수 제한을 최대/최소값으로 올리거나 낮추려는 것이다.
부록: 수량
HorizontalPodAutoscaler와 메트릭 API에서 모든 메트릭은
쿠버네티스에서 사용하는
수량 숫자 표기법을 사용한다.
예를 들면, 10500m
수량은 10진법 10.5
으로 쓰인다.
메트릭 API들은 가능한 경우 접미사 없이 정수를 반환하며,
일반적으로 수량을 밀리단위로 반환한다.
10진수로 표현했을때, 1
과 1500m
또는 1
과 1.5
로 메트릭 값을 나타낼 수 있다.
부록: 다른 가능한 시나리오
명시적으로 오토스케일러 만들기
HorizontalPodAutoscaler를 생성하기 위해 kubectl autoscale
명령어를 사용하지 않고,
명시적으로 다음 파일을 사용하여 만들 수 있다.
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: php-apache
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: php-apache
minReplicas: 1
maxReplicas: 10
targetCPUUtilizationPercentage: 50
다음 명령어를 실행하여 오토스케일러를 생성할 것이다.
kubectl create -f https://k8s.io/examples/application/hpa/php-apache.yaml
horizontalpodautoscaler.autoscaling/php-apache created
6 - 파드 내에서 쿠버네티스 API에 접근
이 페이지는 파드 내에서 쿠버네티스 API에 접근하는 방법을 보여준다.
시작하기 전에
쿠버네티스 클러스터가 필요하고, kubectl 커맨드-라인 툴이 클러스터와 통신할 수 있도록 설정되어 있어야 한다. 이 튜토리얼은 컨트롤 플레인 호스트가 아닌 노드가 적어도 2개 포함된 클러스터에서 실행하는 것을 추천한다. 만약, 아직 클러스터를 가지고 있지 않다면, minikube를 사용해서 생성하거나 다음의 쿠버네티스 플레이그라운드 중 하나를 사용할 수 있다.
파드 내에서 API에 접근
파드 내에서 API에 접근할 때, API 서버를 찾아 인증하는 것은 위에서 설명한 외부 클라이언트 사례와 약간 다르다.
파드에서 쿠버네티스 API를 사용하는 가장 쉬운 방법은 공식 클라이언트 라이브러리 중 하나를 사용하는 것이다. 이러한 라이브러리는 API 서버를 자동으로 감지하고 인증할 수 있다.
공식 클라이언트 라이브러리 사용
파드 내에서, 쿠버네티스 API에 연결하는 권장 방법은 다음과 같다.
-
Go 클라이언트의 경우, 공식 Go 클라이언트 라이브러리를 사용한다.
rest.InClusterConfig()
기능은 API 호스트 검색과 인증을 자동으로 처리한다. 여기 예제를 참고한다. -
Python 클라이언트의 경우, 공식 Python 클라이언트 라이브러리를 사용한다.
config.load_incluster_config()
기능은 API 호스트 검색과 인증을 자동으로 처리한다. 여기 예제를 참고한다. -
사용할 수 있는 다른 라이브러리가 많이 있다. 클라이언트 라이브러리 페이지를 참고한다.
각각의 경우, 파드의 서비스 어카운트 자격 증명은 API 서버와 안전하게 통신하는 데 사용된다.
REST API에 직접 접근
파드에서 실행되는 동안, 쿠버네티스 apiserver는 default
네임스페이스에서 kubernetes
라는
서비스를 통해 접근할 수 있다. 따라서, 파드는 kubernetes.default.svc
호스트 이름을 사용하여 API 서버를 쿼리할 수 있다. 공식 클라이언트 라이브러리는
이를 자동으로 수행한다.
API 서버를 인증하는 권장 방법은 서비스 어카운트
자격 증명을 사용하는 것이다. 기본적으로, 파드는
서비스 어카운트와 연결되어 있으며, 해당 서비스 어카운트에 대한 자격 증명(토큰)은
해당 파드에 있는 각 컨테이너의 파일시스템 트리의
/var/run/secrets/kubernetes.io/serviceaccount/token
에 있다.
사용 가능한 경우, 인증서 번들은 각 컨테이너의
파일시스템 트리의 /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
에 배치되며,
API 서버의 제공 인증서를 확인하는 데 사용해야 한다.
마지막으로, 네임스페이스가 지정된 API 작업에 사용되는 기본 네임스페이스는 각 컨테이너의
/var/run/secrets/kubernetes.io/serviceaccount/namespace
에 있는 파일에 배치된다.
kubectl 프록시 사용
공식 클라이언트 라이브러리 없이 API를 쿼리하려면, 파드에서
새 사이드카 컨테이너의 명령으로
kubectl proxy
를 실행할 수 있다. 이런 식으로, kubectl proxy
는
API를 인증하고 이를 파드의 localhost
인터페이스에 노출시켜서, 파드의
다른 컨테이너가 직접 사용할 수 있도록 한다.
프록시를 사용하지 않고 접근
인증 토큰을 API 서버에 직접 전달하여 kubectl 프록시 사용을 피할 수 있다. 내부 인증서는 연결을 보호한다.
# 내부 API 서버 호스트 이름을 가리킨다
APISERVER=https://kubernetes.default.svc
# 서비스어카운트(ServiceAccount) 토큰 경로
SERVICEACCOUNT=/var/run/secrets/kubernetes.io/serviceaccount
# 이 파드의 네임스페이스를 읽는다
NAMESPACE=$(cat ${SERVICEACCOUNT}/namespace)
# 서비스어카운트 베어러 토큰을 읽는다
TOKEN=$(cat ${SERVICEACCOUNT}/token)
# 내부 인증 기관(CA)을 참조한다
CACERT=${SERVICEACCOUNT}/ca.crt
# TOKEN으로 API를 탐색한다
curl --cacert ${CACERT} --header "Authorization: Bearer ${TOKEN}" -X GET ${APISERVER}/api
출력은 다음과 비슷하다.
{
"kind": "APIVersions",
"versions": [
"v1"
],
"serverAddressByClientCIDRs": [
{
"clientCIDR": "0.0.0.0/0",
"serverAddress": "10.0.1.149:443"
}
]
}