-
12. 애플리케이션 스케줄링과 라이프사이클 관리 (2)24년 11월 이전/데브옵스(DevOps)를 위한 쿠버네티스 마스터 2021. 8. 20. 20:48반응형
이 문서는 인프런 강의 "데브옵스를 위한 쿠버네티스 마스터"을 듣고 작성되었습니다. 최대한 요약해서 강의 내용을 최소로 하는데 목표를 두고 있어서, 더 친절하고 정확한 내용을 원하신다면 강의를 구매하시는 것을 추천드립니다. => 강의 링크
컨테이너 리소스 요청과 제한하는 방법
이번 절은
GCP
에서 진행한다.k8s
에서 컨테이너 생성 시 CPU, 메모리를 요청 및 제한할 수 있다.- request : 최소 스펙 요청 사항
- limit : 최대 리소스 제한
CPU는 다음 단위를 사용한다.
- m (0.1 = 100m)
메모리는 다음 단위를 사용한다.
- Ti (1024 ^ 4)
- Gi (1024 ^ 3)
- Mi (1024 ^ 2)
- Ki (1024)
- T (1000 ^ 4)
- G (1000 ^ 3)
- M (1000 ^ 2)
- K (1000)
이제 한 번 리소스를 요청/제한에서 컨테이너를 만들어보자. 다음과 같이 만들 것이다.
- request
- cpu: 1m
- memory: 200Mi
- limit
- cpu: 2m
- memory: 400Mi
다음과 같이
container-limit-request.yaml
을 만들어보자.src/ch12/k8s/container-limit-request.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx ports: - containerPort: 80 resources: requests: cpu: "1m" memory: "200Mi" limits: cpu: "2m" memory: "400Mi"
요청은
Pod
의 다음 필드로 할 수 있다.- spec.resources.requests.cpu
- spec.resources.requests.resource
제한은
Pod
의 다음 필드로 할 수 있다.- spec.resources.limits.cpu
- spec.resources.limits.resource
이제 다음 명령어로 리소스를 생성한다.
$ kubectl create -f container-limit-request.yaml deployment.apps/nginx-deployment created $ kubectl get pod -w NAME READY STATUS RESTARTS AGE ... nginx-deployment-7fdbdd879d-gtlzp 1/1 Running 0 74s nginx-deployment-7fdbdd879d-m55nv 1/1 Running 0 74s nginx-deployment-7fdbdd879d-s28ch 1/1 Running 0 74s
이제
describe
명령어를 실행하여Pod
에서 리소스 요청/제한이 잘 되었는지 확인해보자.$ kubectl describe pod nginx Name: nginx-deployment-7fdbdd879d-gtlzp ... Containers: nginx: ... Limits: cpu: 2m memory: 400Mi Requests: cpu: 1m memory: 200Mi ...
그리고
GKE
같은 클라우드 프로바이더에서 제공하는 쿠버네티스 클러스터에는top
명령어를 사용하여 리소스 요청/제한 사항을 확인할 수 있다. (0m이 뜨는 이유는 왜인지 모르겠다..)$ kubectl top pod NAME CPU(cores) MEMORY(bytes) nginx-deployment-7fdbdd879d-gtlzp 0m 3Mi nginx-deployment-7fdbdd879d-m55nv 0m 3Mi nginx-deployment-7fdbdd879d-s28ch 0m 3Mi
LimitRange
이번 절은
VM
에서 진행한다.LimitRange
는Namespace
에서Pod
혹은Container
,PersistentVolumeClaim
별로 리소스를 제한하는 "정책"이다. 다음과 같은 제약 조건을 제공한다.- Namespace 별 Pod 혹은 Container 별 CPU, Memory 사용량을 지정한다.
- Namespace 별 StorageClass 별 최소 및 최대 스토리지 요청을 지정한다.
- Namespace 별 리소스에 대한 request, limit 사이의 비율을 지정한다.
- Namespace 별 컴퓨팅 리소스에 대한 기본 request/limit 설정하고, 런타임에 있는 컨테이너에 자동으로 설정한다.
이번 절에서는
Container
에 대한 리소스를 제한하는 정책만을 다룬다.먼저 공통적으로 필요한 부분을 작업해보자.
k8s
설정을 변경해주어야 한다./etc/kubernetes/manifests/kube-apiserver.yaml
을 다음과 같이 수정한다.apiVersion: v1 kind: Pod metadata: annotations: kubeadm.kubernetes.io/kube-apiserver.advertise-address.endpoint: 10.0.2.15:6443 creationTimestamp: null labels: component: kube-apiserver tier: control-plane name: kube-apiserver namespace: kube-system spec: containers: - command: - kube-apiserver - --advertise-address=10.0.2.15 - --allow-privileged=true - --authorization-mode=Node,RBAC - --client-ca-file=/etc/kubernetes/pki/ca.crt # 수정 (, LimitRanger) 추가 - --enable-admission-plugins=NodeRestriction,LimitRanger - --enable-bootstrap-token-auth=true - --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt - --etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt - --etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key - --etcd-servers=https://127.0.0.1:2379 - --insecure-port=0
그 후 얼마 정도 시간이 지나서
get
명령어를 사용해서 결과가 나오면 설정이 잘 변경된 것이다.$ kubectl get pod NAME READY STATUS RESTARTS AGE mongodb 1/1 Running 1 8d
이제
Namespace
를 생성한다. 다음 명령어를 사용한다.$ kubectl create namespace cpu-constraints
아니면 다음과 같이
cpu-constraints-ns.yaml
을 만들고kubectl create -f <file>
로 리소스를 생성해도 좋다.src/ch12/k8s/cpu-constraints-ns.yaml
apiVersion: v1 kind: Namespace metadata: creationTimestamp: null name: cpu-constraints spec: {} status: {}
그 후 이제
LimitRange
를 만들어보자. 위에 생성한Namespace
에 CPU를 200m에서 800m까지의 제한 정책을 둘 것이다. 다음과 같이cpu-constraints-lr.yaml
을 생성한다.src/ch12/k8s/cpu-constraints-lr.yaml
apiVersion: v1 kind: LimitRange metadata: name: cpu-constraints-lr namespace: cpu-constraints spec: limits: - max: cpu: "800m" min: cpu: "200m" type: Container
그 후 터미널에 다음을 입력하여 리소스를 생성한다.
$ kubectl create -f cpu-constraints-lr.yaml limitrange/cpu-constraints-lr created
이제 다음 명령어를 이용해서 리소스 제한 정책이 잘 만들어졌는지 확인하자.
$ kubectl get limitranges cpu-constraints-lr --output=yaml -n cpu-constraints apiVersion: v1 kind: LimitRange metadata: creationTimestamp: "2021-08-19T11:35:59Z" name: cpu-constraints-lr namespace: cpu-constraints resourceVersion: "55564" uid: a69c11c3-b2fc-427a-b19d-948f613ba6f1 spec: limits: - default: cpu: 800m defaultRequest: cpu: 800m max: cpu: 800m min: cpu: 200m type: Container
기본 값을 지정하지 않더라도 자동으로 만들어진다는 것을 확인할 수 있다. 이제 해당 범위에 맞는
Pod
을 생성해보자.cpu-constraints-pod-1.yaml
을 다음과 같이 생성한다.src/ch12/k8s/cpu-constraints-pod-1.yaml
apiVersion: v1 kind: Pod metadata: name: constraints-cpu-demo1 namespace: cpu-constraints spec: containers: - name: constraints-cpu-demo1 image: nginx resources: limits: cpu: "800m" requests: cpu: "500m"
이제 리소스를 생성하면 잘 만들어지는 것을 확인할 수 있다.
$ kubectl create -f cpu-constraints-pod-1.yaml pod/constraints-cpu-demo1 created $ kubectl get pod -w -n cpu-constraints NAME READY STATUS RESTARTS AGE constraints-cpu-demo1 1/1 Running 0 16s
이번엔 CPU "limit"이
LimitRange
의 "max"보다 크게 설정하는Pod
을 만들어본다.cpu-constraints-pod-2.yaml
를 다음과 같이 작성한다.src/ch12/k8s/cpu-constraints-pod-2.yaml
apiVersion: v1 kind: Pod metadata: name: constraints-cpu-demo2 namespace: cpu-constraints spec: containers: - name: constraints-cpu-demo2 image: nginx resources: limits: cpu: "1.5" requests: cpu: "500m"
max가 800인데 1.5를 제한을 걸었다. 리소스를 생성해보자.
$ kubectl create -f cpu-constraints-pod-2.yaml Error from server (Forbidden): error when creating "cpu-constraints-pod-2.yaml": pods "constraints-cpu-demo2" is forbidden: maximum cpu usage per Container is 800m, but limit is 1500m
limits > max
조건이 성립되기 때문에 생성되지 않는다. 이번엔Pod
의 리소스 "request"가LimitRange
에 설정한 "min"보다 낮은 리소스를 요청하면 어떻게 될까?cpu-constraints-pod-3.yaml
를 다음곽 같이 작성한다.src/ch12/k8s/cpu-constraints-pod-3.yaml
apiVersion: v1 kind: Pod metadata: name: constraints-cpu-demo3 namespace: cpu-constraints spec: containers: - name: constraints-cpu-demo3 image: nginx resources: limits: cpu: "800" requests: cpu: "100m"
다음 명령어를 이용해서 리소스를 생성한다.
$ kubectl create -f cpu-constraints-pod-3.yaml Error from server (Forbidden): error when creating "cpu-constraints-pod-3.yaml": pods "constraints-cpu-demo3" is forbidden: [minimum cpu usage per Container is 200m, but request is 100m, maximum cpu usage per Container is 800m, but limit is 800]
이것도 만들어지지 않는다.
requests < min
조건이 성립하기 때문이다. 즉,min <= requests <= limit <= max
라는 조건이 성립되어야 잘 만들어진다는 것을 알 수 있다.ResourceQuota
이번 절은
VM
환경에서 진행된다.ResourceQuota
는Namespace
별 만들 수 있는 총 리소스의 양을 제한한다.Namespace
당 1개씩 지정할 수 있다. cpu, memory. storage 뿐 아니라Pod
,Deployment
같은 오브젝트 개수까지 제한이 가능하다.먼저
Namespace
를 생성한다.mem-cpu-ns.yaml
을 다음과 같이 작성한다.apiVersion: v1 kind: Namespace metadata: creationTimestamp: null name: mem-cpu-demo spec: {} status: {}
그리고 다음 멸령어로 리소스를 생성한다.
$ kubectl create -f mem-cpu-ns.yaml namespace/mem-cpu-demo created
그 후
ResourceQuota
를 만들면 된다.mem-cpu-rq.yaml
을 다음과 같이 작성한다.apiVersion: v1 kind: ResourceQuota metadata: name: mem-cpu-demo-rq namespace: mem-cpu-demo spec: hard: requests.cpu: "1" requests.memory: 1Gi limits.cpu: "2" limits.memory: 2Gi
위
ResourceQuata
는 cpu는 request는 1까지, limit은 2까지, memory는 request는 1Gi, limit은 2Gi 까지 생성할 수 있다. 리소스를 생성해보자.$ kubectl create -f mem-cpu-rq.yaml resourcequota/mem-cpu-demo-rq created
describe
명령어로 한 번 확인해보자.$ kubectl describe resourcequota mem-cpu-demo-rq -n mem-cpu-demo Name: mem-cpu-demo-rq Namespace: mem-cpu-demo Resource Used Hard -------- ---- ---- limits.cpu 0 2 limits.memory 0 2Gi requests.cpu 0 1 requests.memory 0 1Gi
자 이제
Pod
을 1개 만들어보자.mem-cpu-pod-1.yaml
을 다음과 같이 작성한다.src/ch12/k8s/mem-cpu-pod-1.yaml
apiVersion: v1 kind: Pod metadata: name: mem-cpu-demo-1 namespace: mem-cpu-demo spec: containers: - name: mem-cpu-demo-1 image: nginx resources: limits: memory: "800Mi" cpu: "800m" requests: memory: "600Mi" cpu: "400m"
리소스 생성을 위해 다음 명령어를 입력한다.
$ kubectl create -f mem-cpu-pod-1.yaml pod/mem-cpu-demo-1 created
그 후
ResourceQuota
를 다시 한 번 확인해서 리소스를 얼마나 사용했는지 확인해보자.$ kubectl describe resourcequota mem-cpu-demo-rq -n mem-cpu-demo Name: mem-cpu-demo-rq Namespace: mem-cpu-demo Resource Used Hard -------- ---- ---- limits.cpu 800m 2 limits.memory 800Mi 2Gi requests.cpu 400m 1 requests.memory 600Mi 1Gi
리소스를 얼마나 사용한지 확인할 수 있다. 이제 새로운
Pod
을 하나 더 만들어보자.mem-cpu-pod-2.yaml
을 다음과 같이 작성한다.src/ch12/k8s/mem-cpu-pod-2.yaml
apiVersion: v1 kind: Pod metadata: name: mem-cpu-demo-2 namespace: mem-cpu-demo spec: containers: - name: mem-cpu-demo-2 image: nginx resources: limits: memory: "1Gi" cpu: "800m" requests: memory: "700Mi" cpu: "400m"
위의 리소스를 생성하면 cpu request는 0.8, limit은 1.6, memory request는 1.3Gi, limit은 1.8Gi가 된다. 하지만, memory request가
ResourceQuota
에 총 제한량보다 커지니까 이 리소스는 만들어지지 않을 것이다. 다음 명령어를 입력해보자.$ kubectl create -f mem-cpu-pod-2.yaml Error from server (Forbidden): error when creating "mem-cpu-pod-2.yaml": pods "mem-cpu-demo-2" is forbidden: exceeded quota: mem-cpu-demo-rq, requested: requests.memory=700Mi, used: requests.memory=600Mi, limited: requests.memory=1Gi
역시 예상대로 리소스가 만들어지지 않는 다는 것을 확인할 수 있다.
DaemonSet
이번 절에서는
GCP
에서 진행한다.DaemonSet
은ReplicaSet
과 거의 유사하다.ReplicaSet
은Pod
가 임의의Node
에서 생성된다면,DaemonSet
은 각Node
에 1개씩 배치된다. 보통은HostPath
로 설정된Volume
과 함께 사용되어Node
의 리소스를 모니터링하는데 사용된다.자 이제
DaemonSet
을 한 번 만들어보자.daemonset.yaml
을 다음과 같이 생성한다.apiVersion: apps/v1 kind: DaemonSet metadata: name: nginx labels: name: nginx spec: selector: matchLabels: name: nginx template: metadata: labels: name: nginx spec: tolerations: - key: node-role.kubernetes.io/master operator: Exists effect: NoSchedule containers: - name: nginx image: nginx terminationGracePeriodSeconds: 30
ReplicaSet
과 거의 유사하다. 몇 가지 추가사항이 있는데Pod.spec.tolerations
설정이 필요하다. 각 키와 효과는 다음과 같다.- node.kubernetes.io/not-ready
- effect: NoExecute
- version: 1.13+
- description: 네트워크 파티션과 같은 노드 문제가 발생해도 데몬셋 파드는 축출되지 않는다.
- node.kubernetes.io/unreachable
- effect: NoExecute
- version: 1.13+
- description: 네트워크 파티션과 같은 노드 문제가 발생해도 데몬셋 파드는 축출되지 않는다.
- node.kubernetes.io/disk-pressure
- effect: NoSchedule
- version: 1.8+
- description: 데몬셋 파드는 기본 스케줄러에서 디스크-압박(disk-pressure) 속성을 허용한다.
- node.kubernetes.io/memory-pressure
- effect: NoSchedule
- version: 1.8+
- description: 데몬셋 파드는 기본 스케줄러에서 메모리-압박(memory-pressure) 속성을 허용한다.
- node.kubernetes.io/unschedulable
- effect: NoSchedule
- version: 1.12+
- description: 데몬셋 파드는 기본 스케줄러의 스케줄할 수 없는(unschedulable) 속성을 극복한다.
- node.kubernetes.io/network-unavailable
- effect: NoSchedule
- version: 1.12+
- description: 호스트 네트워크를 사용하는 데몬셋 파드는 기본 스케줄러에 의해 이용할 수 없는 네트워크(network-unavailable) 속성을 극복한다.
그리고
Pod.spec.terminationGracePeriodSeconds
속성도 추가된다. 이제 리소스를 생성해보자. 다음 명령어를 입력한다.$ kubectl create -f daemonset.yaml daemonset.apps/nginx created
실제
kubectl get pod -o wide
명령어를 이용하면, 어디 노드에Pod
이 구성되었는지 확인할 수 있다. 다음 명령어를 입력해보자.$ kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES # 각 기 다른 노드에 생성된 것을 확인할 수 있다. nginx-2v72b 1/1 Running 0 24s 10.20.0.47 gke-gurumee-gke-default-pool-d6d0240d-xvwr <none> <none> nginx-nhtvq 1/1 Running 0 24s 10.20.2.26 gke-gurumee-gke-default-pool-d6d0240d-sj3x <none> <none> nginx-pnjq4 1/1 Running 0 24s 10.20.1.10 gke-gurumee-gke-default-pool-d6d0240d-f439 <none> <none>
각기 다른 노드에 구성됨을 확인할 수 있다.
Static Pod
이번 절은
VM
에서 진행된다.Static Pod
은kubectl
명령어로 생성하는 것이 아닌kubelet
이 관리하는Pod
을 의미한다. 대표적으로kube-system
에 존재하는Pod
들이 바로 그들인다.$ kubectl get pod -n kube-system NAME READY STATUS RESTARTS AGE coredns-558bd4d5db-5z4jv 1/1 Running 13 48d coredns-558bd4d5db-z45ck 1/1 Running 10 37d etcd-master 1/1 Running 16 48d kube-apiserver-master 1/1 Running 1 23h kube-controller-manager-master 1/1 Running 17 48d kube-proxy-hvpz5 1/1 Running 17 48d kube-proxy-kdtb5 1/1 Running 15 48d kube-proxy-qthkm 1/1 Running 13 48d kube-scheduler-master 1/1 Running 17 48d weave-net-46bsq 2/2 Running 29 48d weave-net-fgxbv 2/2 Running 29 48d weave-net-qr5v6 2/2 Running 34 48d
또한 이들은
kubectl
로 삭제할 수 없다. 한 번Static Pod
을 한 번 만들어보자.kubelet
이 실행될 때 옵션으로 경로를 주면 하위 경로에 존재하는Static Pod
리소스들은 생성된다.기본 경로는
/etc/kubernetes/manifests/
다. 한 번 해당 경로에는 어떤 리소스가 있는지 확인해보자.# sudo 권한 획득 $ ls /etc/kubernetes/manifests/ etcd.yaml kube-controller-manager.yaml kube-apiserver.yaml kube-scheduler.yaml
여기다 우리 리소스를 추가하자. 다음 명령어를 입력한다.
# 파일 생성 $ sudo tee /etc/kubernetes/manifests/staticpod.yaml <<EOF apiVersion: v1 kind: Pod metadata: name: static-pod spec: containers: - name: static-pod image: nginx EOF
소스 코드는 여기 링크 로 확인할 수 있다. 한 번
get pod
명령어를 실행해보자.$ kubectl get pod -w NAME READY STATUS RESTARTS AGE static-pod-master 0/1 ContainerCreating 0 11s static-pod-master 1/1 Running 0 15s
우리는 리소스를 생성하지 않았음에도
Pod
이 생성되었다. 주목할 점은static-pod
뒤에-master
가 붙었다는 것이다.kube-system
네임스페이스 아래에도 이런Pod
들이 있었다.$ kubectl get pod -n kube-system | grep master etcd-master 1/1 Running 16 48d kube-apiserver-master 1/1 Running 1 23h kube-controller-manager-master 1/1 Running 17 48d kube-scheduler-master 1/1 Running 17 48d
그렇다 바로
/etc/kubernetes/manifests/
에 있던 리소스들로 인해서 위의Pod
들이 생성된 것이다. 이렇게 생성된Static Pod
은kubectl
로 지울 수 없다.$ kubectl delete all --all pod "static-pod-master" deleted service "kubernetes" deleted $ kubectl get pod -w NAME READY STATUS RESTARTS AGE static-pod-master 1/1 Running 0 4s
지우는 방법은
/etc/kubernetes/manifests/
경로에서 리소스 파일을 삭제하는 것 뿐이다.$ sudo rm /etc/kubernetes/manifests/staticpod.yaml $ kubectl get pod No resources found in default namespace.
수동 스케줄링
이번 절은
GCP
에서 진행한다. 수동 스케줄링은 자신이 원하는Node
에Pod
들을 배치할 수 있는 기능이다. 2가지 방법이 있다.첫 번째 방법은
Node
의 이름을 지정하는 것이다. 먼저scheduling-1.yaml
을 다음과 같이 생성한다.src/ch12/k8s/scheduling-1.yaml
apiVersion: v1 kind: Pod metadata: name: scheduling-1 spec: containers: - name: scheduling-1 image: nginx # node 이름 nodeName: gke-gurumee-gke-default-pool-d6d0240d-sj3x
그 후 다음 명령어를 입력하여 리소스를 생성한다.
$ kubectl create -f scheduling-1.yaml pod/scheduling-1 created
kubectl get pod -o wide
명령어를 입력하면 어떤 노드에 생성되는지 확인할 수 있다. 우리가nodeName
에 지정한Node
에 생성됨을 확인할 수 있다.$ kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES scheduling-1 1/1 Running 0 7s 10.20.2.27 gke-gurumee-gke-default-pool-d6d0240d-sj3x <none> <none>
두 번째 방법은
Node
의 레이블을 지정하는 것이다.scheduling-2.yaml
을 다음과 같이 생성한다.src/ch12/k8s/scheduling-2.yaml
apiVersion: v1 kind: Pod metadata: name: scheduling-2 spec: containers: - name: scheduling-2 image: nginx # node 이름 nodeSelector: gpu: "true"
nodeSelector
에 원하는Node
의 레이블 값을 달면 된다. 이제 다음 명령어를 입력하여 리소스를 생성한다.$ kubectl create -f scheduling-2.yaml pod/scheduling-2 created $ kubectl get pod -w NAME READY STATUS RESTARTS AGE scheduling-1 1/1 Running 0 2m26s scheduling-2 0/1 Pending 0 9s
아무리 기다려도
scheduling-2
는 생성되지 않는다. 왜냐하면 현재GKE
클러스터Node
중gpu=true
인 레이블이 없기 때문이다.$ kubectl get nodes -L gpu NAME STATUS ROLES AGE VERSION GPU gke-gurumee-gke-default-pool-d6d0240d-f439 Ready <none> 9d v1.20.8-gke.900 gke-gurumee-gke-default-pool-d6d0240d-sj3x Ready <none> 9d v1.20.8-gke.900 gke-gurumee-gke-default-pool-d6d0240d-xvwr Ready <none> 9d v1.20.8-gke.900
위 3개의 노드 중 마음 가는 아무거나 레이블을 붙여준다.
$ kubectl label node gke-gurumee-gke-default-pool-d6d0240d-xvwr gpu="true" $ kubectl get nodes -L gpu NAME STATUS ROLES AGE VERSION GPU gke-gurumee-gke-default-pool-d6d0240d-f439 Ready <none> 9d v1.20.8-gke.900 gke-gurumee-gke-default-pool-d6d0240d-sj3x Ready <none> 9d v1.20.8-gke.900 gke-gurumee-gke-default-pool-d6d0240d-xvwr Ready <none> 9d v1.20.8-gke.900 true
이제 다시
kubectl get pod -o wide
명령어를 입력하면,gpu=true
레이블을 준Node
에Pod
이 배치됨을 확인할 수 있다.$ kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES scheduling-1 1/1 Running 0 5m41s 10.20.2.27 gke-gurumee-gke-default-pool-d6d0240d-sj3x <none> <none> scheduling-2 1/1 Running 0 3m24s 10.20.0.48 gke-gurumee-gke-default-pool-d6d0240d-xvwr <none> <none>
오토 스케일링
k8s
에서 오토 스케일링이 필요한 경우가 있다. 총 3가지 유형이 있다.- HPA: Pod 자체를 복체하여 처리할 수 있는 Pod의 개수를 늘림.
- VPA: 리소스를 증가시켜 Pod의 사용 가능한 리소스를 늘림
- CA: 클러스터를 자체를 늘림
이 중
HPA
만이 기본적으로 제공되는 오토 스케일링 방법이며 나머지 2개는 클라우드 프로바이더 별 제공할 수도 있고 안 할수도 있다. 여기서는HPA
만을 다룬다. 이번 절은GKE
에서 다룬다.실습을 진행해보자. 먼저 다음과 같이
hpa.yaml
을 만든다.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
Deployment
와Service
를 생성하며,php-apache
라는 웹 서비스를 구축하게 된다. 다음 명령어를 이용해 리소스를 생성해보자.$ kubectl create -f hpa.yaml deployment.apps/php-apache created service/php-apache created
자 이제
HPA
를 생성하자.$ kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10 horizontalpodautoscaler.autoscaling/php-apache autoscaled $ kubectl get hpa NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE php-apache Deployment/php-apache <unknown>/50% 1 10 1 20s
보면 "TARGET"이 50%이고 "MIN"이 1개, "MAX"가 10개, 현재 "REPLICA"는 1개로 되있음을 확인할 수 있다. 이제 무한히
php-apache
서비스를 호출하는Pod
을 만들어보자.$ 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"
그리고
HPA
와Deployment
를 관찰해보자.$ kubectl get hpa -w NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE php-apache Deployment/php-apache <unknown>/50% 1 10 1 72s php-apache Deployment/php-apache 250%/50% 1 10 1 79s php-apache Deployment/php-apache 250%/50% 1 10 4 80s php-apache Deployment/php-apache 250%/50% 1 10 5 96s $ kubectl get deployment php-apache NAME READY UP-TO-DATE AVAILABLE AGE php-apache 5/5 5 5 115s
"TARGET"이 250%가 되면서 "REPLICA" 개수가 계속 증가한다. 위는 내가 중간에 끊어서 명령어를 실행했기 때문에 5개밖에 안찍혔지만 실제로는 7개까지
Pod
이 늘어났다. 이제 호출하는Pod
을 삭제해보자.$ kubectl delete pod load-generator pod "load-generator" deletedkubectl delete pod load-generator pod "load-generator" deleted
이제 다시
HPA
와Deployment
를 관찰한다.$ kubectl get hpa -w NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE php-apache Deployment/php-apache 60%/50% 1 10 5 2m33s php-apache Deployment/php-apache 67%/50% 1 10 5 2m38s php-apache Deployment/php-apache 67%/50% 1 10 7 2m52s php-apache Deployment/php-apache 14%/50% 1 10 7 3m9s php-apache Deployment/php-apache 0%/50% 1 10 7 3m39s php-apache Deployment/php-apache 0%/50% 1 10 7 8m5s php-apache Deployment/php-apache 0%/50% 1 10 2 8m20s php-apache Deployment/php-apache 0%/50% 1 10 2 8m36s php-apache Deployment/php-apache 0%/50% 1 10 1 8m51s $ kubectl get deployment php-apache NAME READY UP-TO-DATE AVAILABLE AGE php-apache 1/1 1 1 9m13s
증가할 때는 진짜 빠르게
Pod
개수를 오토 스케일링했는데 내려갈 때는 매우 천천히 개수가 준다. 아무래도 실제 서비스에는 이런 저런 상황으로 부하가 왔다 갔다 할 수 있으니 그것까지 고려해서 개수를 조정하는 듯 하다.HPA
말고VPA
,CA
를 하기 위해서는 각 클라우드 프로바이더에서 제공하는지 확인하고 해당 방법을 래퍼런스를 통해서 찾아야 한다.GKE
에서VPA
,CA
하는 방법은 아래 명령어들을 참고하라.vpa
$ gcloud container clusters create CLUSTER_NAME \ --enable-vertical-pod-autoscaling --cluster-version=VERSION
ca
$ gcloud container clusters create example-cluster \ --num-nodes 2 \ --zone us-central1-a \ --node-locations us-central1-a,us-central1-b,us-central1-f \ --enable-autoscaling --min-nodes 1 --max-nodes 4
728x90'레거시 > 데브옵스(DevOps)를 위한 쿠버네티스 마스터' 카테고리의 다른 글
14. 서비스 매시 환경 모니터링 도구 istio 시작하기 (0) 2021.08.31 13. 리소스 로깅과 모니터링 (0) 2021.08.30 11. 애플리케이션 스케줄링과 라이프사이클 관리 (1) (0) 2021.08.17 10. 쿠버네티스 핵심 개념 (5) (0) 2021.08.14 09. 쿠버네티스 핵심 개념 (4) (0) 2021.08.05