この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは。EKS Workshop
で実際に手を動かしながら機能を学んでいます。
やはり手を動かしながら学べるので本当に楽しいですよね。
さて今回はEKS Workshopでも取り扱っていた 「Horizontal Pod Autoscaler (HPA)」と「Cluster Autoscaler (CA)」を 実際に試してみたのでブログに書いてみました。
Horizontal Pod Autoscaler (HPA) を試してみる
さてまずはHPAから試していきます。
HPAはKubernetesのリソースの1つで、CPU使用率、API Objectのメトリクスなどをモニタリングし、
スケーリングが必要になったタイミングで、Replication ControllerやDeploymentなどのPod数をスケーリングします。
DaemonSetのようにスケールしないしない物に関してはHPAの対象とすることはできません。
概要を抑えたところで実際に手を動かしていきましょう。
環境
- Kubernetes: 1.14
- helm: 3.0.0
- eksctl: 0.10.2
1. クラスタの作成
eksctlを使って東京リージョンにさくさくっと作り上げます。
$ export AWS_DEFAULT_REGION=ap-northeast-1
$ eksctl create cluster \
--name=eksworkshop-hpa \
--nodes=3 \
--node-type=t3.small
2. Metrics Serverのインストール
HPAがスケーリングの指示をするにあたって、メトリクスを収集する必要があります。
Kubernetesでは一般的には
Metrics Server
を使用します。
今回はMetrics ServerをHelmを使用してデプロイします。
またこちらの手順
でHelmを使用せずにデプロイすることもできます。
$ helm install stable/metrics-server \
--generate-name \
--namespace kube-system
NAME: metrics-server-1574319962
LAST DEPLOYED: Thu Nov 21 16:06:04 2019
NAMESPACE: kube-system
STATUS: deployed
REVISION: 1
NOTES:
The metric server has been deployed.
In a few minutes you should be able to list metrics using the following
command:
kubectl get --raw "/apis/metrics.k8s.io/v1beta1/nodes"
こちらもEKSクラスタと同様にサクッとデプロイができました。
表示されたコマンドを実行して問題なく動作しているかの確認をします。
$ kubectl get apiservice v1beta1.metrics.k8s.io -o yaml
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
creationTimestamp: "2019-11-21T07:06:04Z"
labels:
app: metrics-server
chart: metrics-server-2.8.8
~~~
一部表示を端折っていますが問題なさそうですね。
3. サンプルアプリケーションのデプロイ
GETリクエストに対して「ok!」とレスポンスを返すアプリケーションを元にDeploymentの作成とServiceで公開します。
$ kubectl run php-apache --image=k8s.gcr.io/hpa-example --requests=cpu=200m --expose --port=80
service/php-apache created
deployment.apps/php-apache created
4. HPAのデプロイ
次にkubectl autoscale
を実行してHPAをデプロイします。
先ほど作成したDeploymentで稼働しているPodのCPU使用率が平均して50%になるようにスケーリングを行います。
$ kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10
HPAの状況を確認してみます。
アプリケーションに対して負荷をかけていない状態なのでメトリクスは0%/50%
でRelicas
も1になっています。
$ kubectl get hpa -w
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
php-apache Deployment/php-apache 0%/50% 1 10 1 3m32s
5. スケーリングさせる
別途Busyboxを用意してそこから先ほど作成したアプリケーションに対して負荷をかけます。
$ while true; do wget -q -O - http://php-apache; done
OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!
アプリケーションはOK!
とレスポンスを返すので問題なく動作してますね。
この時HPAの状態を確認してみましょう。
$ kubectl get hpa -w
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
php-apache Deployment/php-apache 271%/50% 1 10 1 5m
スケールアウトできておらず、1つのPodにかなりの負荷がかかっています。
この状態から暫く時間が経ってからもう一度確認します。
$ kubectl get hpa -w
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
php-apache Deployment/php-apache 47%/50% 1 10 10 8m8s
十分にスケールされてCPU負荷も50%付近を保っています。
ここでBusyboxからのリクエストを停止させます。
$ kubectl get hpa -w
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
php-apache Deployment/php-apache 0%/50% 1 10 10 10m
この状態から数分経過した後に、Pod数が1つに戻ります。
$ kubectl get hpa -w
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
php-apache Deployment/php-apache 0%/50% 1 10 1 15m
thrashing
と呼ばれる、スケール管理時にメトリクスによって頻繁なレプリカ数の変化が発生する可能性があります。
Kubernetesではこれを防ぐためにHPAでスケールインするまでの待機時間を設定することができ、
これにより設定されているためにスケールインに関しては大きく時間がかかっています。
6. クラスタの削除
HPAの動作がわかったところでEKSクラスタを削除していきます。
$ eksctl delete cluster \
--name=eksworkshop-hpa
Cluster Autoscaler(CA)を試す
次にCAを試していきます。今回はEKSWorkshopの手順とかなり違う順序でやっていますのでご了承ください。
HPAとは違いノードをスケールさせます。
またメトリクスもCPU使用率とかではなくpending状態のPodに基づいてスケールします。EKSの場合だとクラスタのメトリクスを元にASGに対して指示を出すことで実現します。
環境
- Kubernetes: 1.14
- eksctl: 0.10.2
1. クラスタの作成
eksctlを使って東京リージョンにさくさくっと作り上げます。
$ export AWS_DEFAULT_REGION=ap-northeast-1
$ eksctl create cluster \
--name=eksworkshop-eksctl \
--nodes=3 \
--node-type=t3.small
2. ASGの更新
eksctlで作成したASGを探して最小、最大量の変更を行います。
$ aws autoscaling update-auto-scaling-group \
--auto-scaling-group-name <ASG NAME> \
--min-size 2 \
--max-size 8
3. IAM Policyの作成
クラスタからAutoScalingの状態を変更確認できるように、IAMロールにポリシーを付与します。 なのでまず初めにポリシーファイルを作成します。
asg-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"autoscaling:DescribeAutoScalingGroups",
"autoscaling:DescribeAutoScalingInstances",
"autoscaling:SetDesiredCapacity",
"autoscaling:TerminateInstanceInAutoScalingGroup",
"autoscaling:DescribeTags"
],
"Resource": "*"
}
]
}
次にそのファイルを元にIAM Roleにアタッチします。
$ STACK_NAME=$(eksctl get nodegroup --cluster eksworkshop-eksctl -o json | jq -r '.[].StackName')
$ INSTANCE_PROFILE_ARN=$(aws cloudformation describe-stacks --stack-name $STACK_NAME | jq -r '.Stacks[].Outputs[] | select(.OutputKey=="InstanceProfileARN") | .OutputValue')
$ ROLE_NAME=$(aws cloudformation describe-stacks --stack-name $STACK_NAME | jq -r '.Stacks[].Outputs[] | select(.OutputKey=="InstanceRoleARN") | .OutputValue' | cut -f2 -d/)
$ aws iam put-role-policy --role-name $ROLE_NAME --policy-name ASG-Policy-For-Worker --policy-document file://asg-policy.json
4. CAのデプロイ
CA用のServiceAccountの作成とDeploymentを作成します。
EKSWorkshop用に準備されたマニュフェストはありますが、一部変更が必要なので変更します。
少しわかりづらい記載で申し訳ないですが、<ASG NAME>
の部分を実際のASGの名前に書き換えてください。
$ curl -O https://eksworkshop.com/scaling/deploy_ca.files/cluster_autoscaler.yml
$ sed -i "s/<AUTOSCALING GROUP NAME>/<ASG NAME>/" cluster_autoscaler.yml
$ sed -i "s/us-west-2/ap-northeast-1/" cluster_autoscaler.yml
最後に出来上がったマニュフェストをデプロイします。
$ kubectl apply -f cluster_autoscaler.yml
5. スケールさせる
Nginxを使用したPodで、replicasの値を1にしたDeploymentをデプロイします。
まずはマニュフェストを記載していきます。
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
これをデプロイします。
$ kubectl apply -f nginx.yaml
この段階ではPod数が1つなので当然pendingも発生しておらずワーカーノードのスケールも発生していません。
$ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-to-scaleout 1/1 1 1 11s
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-to-scaleout-84f9cdbd84-tsptk 1/1 Running 0 41s
ワーカーノードのスケールを発生させるためにDeploymentsのPod数をスケールさせます。
$ kubectl scale --replicas=10 deployment/nginx-to-scaleout
この段階でPodがpending状態になっていることが確認できます。
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-to-scaleout-84f9cdbd84-2tb9x 1/1 Running 0 32s
nginx-to-scaleout-84f9cdbd84-8vvp7 1/1 Running 0 32s
nginx-to-scaleout-84f9cdbd84-8w6fh 1/1 Running 0 32s
nginx-to-scaleout-84f9cdbd84-kxx6p 1/1 Running 0 32s
nginx-to-scaleout-84f9cdbd84-lkwth 1/1 Running 0 32s
nginx-to-scaleout-84f9cdbd84-m2jfq 1/1 Running 0 32s
nginx-to-scaleout-84f9cdbd84-rzvqr 1/1 Running 0 32s
nginx-to-scaleout-84f9cdbd84-tsptk 1/1 Running 0 3m11s
nginx-to-scaleout-84f9cdbd84-w4hj7 0/1 Pending 0 32s
nginx-to-scaleout-84f9cdbd84-xmgvb 1/1 Running 0 32s
ワーカーノードのスケーリングが終わり4台に増えた段階でpendingが解消されることも確認できました。
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
ip-192-168-19-201.ap-northeast-1.compute.internal Ready <none> 33m v1.14.7-eks-1861c5
ip-192-168-48-242.ap-northeast-1.compute.internal Ready <none> 17m v1.14.7-eks-1861c5
ip-192-168-58-249.ap-northeast-1.compute.internal Ready <none> 33m v1.14.7-eks-1861c5
ip-192-168-77-50.ap-northeast-1.compute.internal Ready <none> 33m v1.14.7-eks-1861c5
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-to-scaleout-84f9cdbd84-2tb9x 1/1 Running 0 2m43s
nginx-to-scaleout-84f9cdbd84-8vvp7 1/1 Running 0 2m43s
nginx-to-scaleout-84f9cdbd84-8w6fh 1/1 Running 0 2m43s
nginx-to-scaleout-84f9cdbd84-kxx6p 1/1 Running 0 2m43s
nginx-to-scaleout-84f9cdbd84-lkwth 1/1 Running 0 2m43s
nginx-to-scaleout-84f9cdbd84-m2jfq 1/1 Running 0 2m43s
nginx-to-scaleout-84f9cdbd84-rzvqr 1/1 Running 0 2m43s
nginx-to-scaleout-84f9cdbd84-tsptk 1/1 Running 0 5m22s
nginx-to-scaleout-84f9cdbd84-w4hj7 1/1 Running 0 2m43s
nginx-to-scaleout-84f9cdbd84-xmgvb 1/1 Running 0 2m43s
Cluster AutoscalerでもHPAと同様に、スケーリングを行なった後の待機時間が設定されているのでそれが終わるまでノード数は減っていきません。
6. クラスタの削除
まずアタッチしたポリシーを削除してからクラスタを削除します。
$ aws iam delete-role-policy \
--role-name $ROLE_NAME \
--policy-name ASG-Policy-For-Worker
$ eksctl delete cluster \
--name=eksworkshop-eksctl
さいごに
kubectlを実際に実行しながら進めるのでEKSWorkshopはEKSを理解するのに非常に良いチュートリアルです。 お手すきの際に実際にお試しください