K8S의 Autoscaling은 2가지 형태로 제공된다.
- Horizontal Pod Autoscaler (HPA) : Deployment 또는 replica set에서 Pod를 확장한다. K8S API resource와 controller로 구현되고 Conteroller manager는 각각의 HPA 정의에 지정된 메트릭에 대해 리소스 사용률을 쿼리한다.
리소스 메트릭 API(Pod당 리소스 메트릭) 또는 사용자 지정 메트릭 API에서 메트릭 정보를 가져온다. clarkshim.tistory.com/128
- Cluster Autoscaler (CA) : Kubernets 클러스터 크기를 자동으로 조정하여 모든 Pod가 실행될 Node는 있으나 불필요한 Node는 없도록 하는 구성 요소
ㅁ Install Kube-Ops-View
- Henning Jacobs로 부터 kube-ops-view 설치
- kube-ops-view는 클러스터 설정을 시각적으로 이해하는데 도움이 되는 kubernets cluster에 대한 비주얼적인 방법을 제공한다.
ㅇ Helm으로 저장소를 업데이트 한 후, LoadBalancer 서비스 유형을 사용하고 Cluster에서 Node 및 Pod정보를 읽기 위한 읽기 전용 서비스 계정을 위한 RBAC을 생성하여 kube-ops-view를 설치한다.
helm install kube-ops-view \ stable\kube-ops-view \ --set service.type=LoadBalancer \ --set rbac.create=True
잠시 기다리면 위의 url로 접속하여 정상적으로 kube-ops-view가 아래와 같이 보여진다.
해당 이미지의 설명은 아래와 같다. (IP는 무시하고 위치별 항목이 무엇인지만 확인하면 된다.)
ㅁ Configure Horizontal Pod Autoscaler (HPA)
HPA를 구성하기 위해 Metrics Server를 배포한다. Metric Server는 Kubernetes에 내장되어 있는 Autoscaling 파이프라인으로 확장 가능하고 효율적인 컨테이너 리소스 메트릭 소스이다.
다음을 사용하여 배포한다.
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.4.1/components.yaml
정상적으로 설치가 되면 아래와 같이 메트릭 서버의 상태가 확인이 가능하다.
ㅁ Deploy Sample App
TCP Port 80으로 한 서비스를 노출 시키는 애플리케이션을 디플로이한다.
이 애플리케이션은 php-apache image에 기반한 Custom-built image이고 index.php page는 계산을 수행하여 CPU 부하를 발생한다.
kubectl create deployment php-apache --image=us.gcr.io/k8s-artifacts-prod/hpa-example kubectl set resources deploy php-apache --requests=cpu=200m kubectl expose deploy php-apache --port 80 kubectl get pod -l app=php-apache
ㅇ HPA가 할당된 컨테이너 리소스의 50%가 초과하면 확장되도록 설정한다.
kubectl autoscale deployment php-apache `#The target average CPU utilization` \ --cpu-percent=50 \ --min=1 `#The lower limit for the number of pods that can be set by the autoscaler` \ --max=10 `#The upper limit for the number of pods that can be set by the autoscaler`
kubectl get hpa에서 보는것 처럼 0~50%로 설저되어 있으며 MINPODS 1, MAXPODS 10으로 설정되어 있는것을 볼 수 있다.
새로운 터미널(Cloud9에서)을 띄워 다음 커맨드로 부하를 발생 시킨다.
kubectl --generator=run-pod/v1 run -i --tty load-generator --imnage=busybox /bin/sh
http://php-apache에 대해서 while loop를 발생 시킨다.
기존의 탭에서 kubectl get hpa -w 로 부하및 Replica의 상태를 모니터링한다.
kubectl get hpa -w
ctrl+c 로 테스트 수행 쉘을 멈추면 HPA가 replicas를 줄이는 것을 확인할 수 있다.
ㅁ Cluster Autoscaler(CA) 구성
AWS Cluster Autoscaler는 Auto Scaling Groups과 Integration되어 제공된다. deployment를 위해서는 4가지 다른 옵션과 같이 제공된다.
- One Auto Scaling group
- Multiple Auto Scaling group
- Auto-Discovery
- Control-Plane Node Setup
최소, 최대 및 원하는 용량을 설정하여 Auto Scaling 그룹의 크기를 구성한다. 클러스터를 만들 때 이런한 설정을 3으로 했으며 아래는 어떻게 구성되어 있는지 볼 수 있다. 클러스터 이름을 다르게 설정했다면 Value = 'ekx ~~ ' 부분을 자신이 만든 클러스터 이름으로 변경해서 조회한다.
aws autoscaling \ describe-auto-scaling-groups \ --query "AutoScalingGroups[? Tags[? (Key=='eks:cluster-name') && Value=='eks-newelite-eksctl']].[AutoScalingGroupName, MinSize, MaxSize,DesiredCapacity]" \ --output table
ㅇ 다음으로는 MAXIMUM CAPACITY를 4로 조절한다.
# we need the ASG name export ASG_NAME=$(aws autoscaling describe-auto-scaling-groups --query "AutoScalingGroups[? Tags[? (Key=='eks:cluster-name') && Value=='eks-newelite-eksctl']].AutoScalingGroupName" --output text) # increase max capacity up to 4 aws autoscaling \ update-auto-scaling-group \ --auto-scaling-group-name ${ASG_NAME} \ --min-size 3 \ --desired-capacity 3 \ --max-size 4 # Check new values aws autoscaling \ describe-auto-scaling-groups \ --query "AutoScalingGroups[? Tags[? (Key=='eks:cluster-name') && Value=='eks-newelite-eksctl']].[AutoScalingGroupName, MinSize, MaxSize,DesiredCapacity]" \ --output table
ㅇ 서비스 어카운트를 위한 IAM role 설정
현 클러스트 환경의 서비스 어카운트를 위한 IAM roles을 설정한다.
eksctl utils associate-iam-oidc-provider \ --cluster eks-newelite-eksctl \ --approve
CA Pod가 Auto Scaling Group과 상호 작용할 수 있도록 서비스 계정에 대한 IAM 정책을 만든다.
mkdir ~/environment/cluster-autoscaler cat <<EoF > ~/environment/cluster-autoscaler/k8s-asg-policy.json { "Version": "2012-10-17", "Statement": [ { "Action": [ "autoscaling:DescribeAutoScalingGroups", "autoscaling:DescribeAutoScalingInstances", "autoscaling:DescribeLaunchConfigurations", "autoscaling:DescribeTags", "autoscaling:SetDesiredCapacity", "autoscaling:TerminateInstanceInAutoScalingGroup", "ec2:DescribeLaunchTemplateVersions" ], "Resource": "*", "Effect": "Allow" } ] } EoF aws iam create-policy \ --policy-name k8s-asg-policy \ --policy-document file://~/environment/cluster-autoscaler/k8s-asg-policy.json
ㅇ 마지막으로 cluster-autoscaler 서비스 어카운트를 위해 kube-system namespace에 IAM 역할을 생성한다.
eksctl create iamserviceaccount \ --name cluster-autoscaler \ --namespace kube-system \ --cluster eks-newelite-eksctl \ --attach-policy-arn "arn:aws:iam::${ACCOUNT_ID}:policy/k8s-asg-policy" \ --approve \ --override-existing-serviceaccounts
IAM 역할에 대한 Annotation이 제대로 적용되었는지 확인해 본다.
kubectl -n kube-system describe sa cluster-autoscaler
ㅇ Cluster Autoscaler (CA) 배포
다음과 같은 명령어로 Cluster Autoscaler를 cluster에 배포한다.
kubectl apply -f https://www.eksworkshop.com/beginner/080_scaling/deploy_ca.files/cluster-autoscaler-autodiscover.yaml
아래는 cluster-autoscaler-autodiscover.yaml 내용이다.
# --- # apiVersion: v1 # kind: ServiceAccount # metadata: # labels: # k8s-addon: cluster-autoscaler.addons.k8s.io # k8s-app: cluster-autoscaler # name: cluster-autoscaler # namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: cluster-autoscaler labels: k8s-addon: cluster-autoscaler.addons.k8s.io k8s-app: cluster-autoscaler rules: - apiGroups: [""] resources: ["events", "endpoints"] verbs: ["create", "patch"] - apiGroups: [""] resources: ["pods/eviction"] verbs: ["create"] - apiGroups: [""] resources: ["pods/status"] verbs: ["update"] - apiGroups: [""] resources: ["endpoints"] resourceNames: ["cluster-autoscaler"] verbs: ["get", "update"] - apiGroups: [""] resources: ["nodes"] verbs: ["watch", "list", "get", "update"] - apiGroups: [""] resources: - "pods" - "services" - "replicationcontrollers" - "persistentvolumeclaims" - "persistentvolumes" verbs: ["watch", "list", "get"] - apiGroups: ["extensions"] resources: ["replicasets", "daemonsets"] verbs: ["watch", "list", "get"] - apiGroups: ["policy"] resources: ["poddisruptionbudgets"] verbs: ["watch", "list"] - apiGroups: ["apps"] resources: ["statefulsets", "replicasets", "daemonsets"] verbs: ["watch", "list", "get"] - apiGroups: ["storage.k8s.io"] resources: ["storageclasses", "csinodes"] verbs: ["watch", "list", "get"] - apiGroups: ["batch", "extensions"] resources: ["jobs"] verbs: ["get", "list", "watch", "patch"] - apiGroups: ["coordination.k8s.io"] resources: ["leases"] verbs: ["create"] - apiGroups: ["coordination.k8s.io"] resourceNames: ["cluster-autoscaler"] resources: ["leases"] verbs: ["get", "update"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: cluster-autoscaler namespace: kube-system labels: k8s-addon: cluster-autoscaler.addons.k8s.io k8s-app: cluster-autoscaler rules: - apiGroups: [""] resources: ["configmaps"] verbs: ["create","list","watch"] - apiGroups: [""] resources: ["configmaps"] resourceNames: ["cluster-autoscaler-status", "cluster-autoscaler-priority-expander"] verbs: ["delete", "get", "update", "watch"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: cluster-autoscaler labels: k8s-addon: cluster-autoscaler.addons.k8s.io k8s-app: cluster-autoscaler roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-autoscaler subjects: - kind: ServiceAccount name: cluster-autoscaler namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: cluster-autoscaler namespace: kube-system labels: k8s-addon: cluster-autoscaler.addons.k8s.io k8s-app: cluster-autoscaler roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: cluster-autoscaler subjects: - kind: ServiceAccount name: cluster-autoscaler namespace: kube-system --- apiVersion: apps/v1 kind: Deployment metadata: name: cluster-autoscaler namespace: kube-system labels: app: cluster-autoscaler spec: replicas: 1 selector: matchLabels: app: cluster-autoscaler template: metadata: labels: app: cluster-autoscaler annotations: prometheus.io/scrape: 'true' prometheus.io/port: '8085' spec: serviceAccountName: cluster-autoscaler containers: - image: k8s.gcr.io/cluster-autoscaler:v1.14.7 name: cluster-autoscaler resources: limits: cpu: 100m memory: 300Mi requests: cpu: 100m memory: 300Mi command: - ./cluster-autoscaler - --v=4 - --stderrthreshold=info - --cloud-provider=aws - --skip-nodes-with-local-storage=false - --expander=least-waste - --node-group-auto-discovery=asg:tag=k8s.io/cluster-autoscaler/enabled,k8s.io/cluster-autoscaler/eksworkshop-eksctl - --balance-similar-node-groups - --skip-nodes-with-system-pods=false volumeMounts: - name: ssl-certs mountPath: /etc/ssl/certs/ca-certificates.crt readOnly: true imagePullPolicy: "Always" volumes: - name: ssl-certs hostPath: path: "/etc/ssl/certs/ca-bundle.crt"
CA가 자신의 Pod를 실행중인 노드를 제거하지 못하도록 방지하기 위해 다음 명령을 사용하여 deployment에 cluster-autoscaler.kubernetes.io/safe-to-evict annotation을 추가한다.
kubectl -n kube-system \ annotate deployment.apps/cluster-autoscaler \ cluster-autoscaler.kubernetes.io/safe-to-evict="false"
마지막으로 autoscaler image를 업데이트 한다.
# we need to retrieve the latest docker image available for our EKS version export K8S_VERSION=$(kubectl version --short | grep 'Server Version:' | sed 's/[^0-9.]*\([0-9.]*\).*/\1/' | cut -d. -f1,2) export AUTOSCALER_VERSION=$(curl -s "https://api.github.com/repos/kubernetes/autoscaler/releases" | grep '"tag_name":' | sed -s 's/.*-\([0-9][0-9\.]*\).*/\1/' | grep -m1 ${K8S_VERSION}) kubectl -n kube-system \ set image deployment.apps/cluster-autoscaler \ cluster-autoscaler=us.gcr.io/k8s-artifacts-prod/autoscaling/cluster-autoscaler:v${AUTOSCALER_VERSION}
최종적으로 로그 확인을 한다.
kubectl -n kube-system logs -f deployment/cluster-autoscaler
ㅁ CA를 통한 Cluster Scale
ㅇ Deploy a Sample App
Pod의 ReplicaSet이 1로 설정된 샘플 nginx 애플리케이션을 Deploy 한다.
cat <<EoF> ~/environment/cluster-autoscaler/nginx.yaml apiVersion: apps/v1 kind: Deployment metadata: name: nginx-to-scaleout spec: replicas: 1 selector: matchLabels: app: nginx template: metadata: labels: service: nginx app: nginx spec: containers: - image: nginx name: nginx-to-scaleout resources: limits: cpu: 500m memory: 512Mi requests: cpu: 500m memory: 512Mi EoF kubectl apply -f ~/environment/cluster-autoscaler/nginx.yaml kubectl get deployment/nginx-to-scaleout
ㅇ replicaset 을 10으로 scale-out 한다.
kubectl scale --replicas=10 deployment/nginx-to-scaleout
cluster-autoscaler log를 확인
kubectl -n kube-system logs -f deployment/cluster-autoscaler
kubectl을 사용하여 nodes의 증가 상태를 확인한다.
아래는 테스트 완료 후 전체 내용을 삭제하는 shell 이다.
kubectl delete -f ~/environment/cluster-autoscaler/nginx.yaml kubectl delete -f https://www.eksworkshop.com/beginner/080_scaling/deploy_ca.files/cluster-autoscaler-autodiscover.yaml eksctl delete iamserviceaccount \ --name cluster-autoscaler \ --namespace kube-system \ --cluster eks-newelite-eksctl \ --wait aws iam delete-policy \ --policy-arn arn:aws:iam::${ACCOUNT_ID}:policy/k8s-asg-policy export ASG_NAME=$(aws autoscaling describe-auto-scaling-groups --query "AutoScalingGroups[? Tags[? (Key=='eks:cluster-name') && Value=='eks-newelite-eksctl']].AutoScalingGroupName" --output text) aws autoscaling \ update-auto-scaling-group \ --auto-scaling-group-name ${ASG_NAME} \ --min-size 3 \ --desired-capacity 3 \ --max-size 3 kubectl delete hpa,svc php-apache kubectl delete deployment php-apache kubectl delete pod load-generator cd ~/environment rm -rf ~/environment/cluster-autoscaler kubectl delete -f https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.4.1/components.yaml kubectl delete ns metrics helm uninstall kube-ops-view unset ASG_NAME unset AUTOSCALER_VERSION unset K8S_VERSION
'AWS EKS 실습 > EKS Beginner' 카테고리의 다른 글
Kubernetes access 관리를 위한 IAM Groups 사용 (1) | 2021.02.25 |
---|---|
Intro to RBAC (0) | 2021.02.24 |
HEALTH CHECKS 실습 (Liveness Probe/Readiness Probe) (0) | 2021.02.22 |
Helm으로 nginx 설치 (0) | 2021.02.19 |
Sample Application 배포 (0) | 2021.02.18 |