AWSのKubernetesで オートスケール~EC2のオートスケールもやっちゃう~
AWSのKubernetesで オートスケール~EC2のオートスケールもやっちゃう~:
今回はEKSでオートスケールに挑戦します。
サービスを保守・運用していく中で、リソースが枯渇してサービスの継続が困難になることは避けたいです。
KubernetesではPod(コンテナ)にリソースを割り当てることができ、リソースが不足すると自動でPodを増やす機能があります。
Horizontal Pod Autoscaler
ただEC2インスタンスのリソースが不足した場合は、Podのオートスケールは機能しません。(リソースがないから。。。)
なので、EC2インスタンスのオートスケールも必要になってきます。
cluster-autoscalerという機能を使ってEC2インスタンスのオートスケールも設定します。
これを設定することで、リソースが必要なときのみEC2インスタンスを作成し、リソースが不要になった場合はEC2インスタンスを自動で削除します。
README通りにやっていきます。
RBACマニフェストを作成します。
マニフェストファイルをデプロイしてinitコマンドを実行します。
これでHelmのインストールは完了です。
Metrics Serverのインストールはhelmコマンドで一発でできます。
OK!
https://github.com/kubernetes-incubator/metrics-server
https://eksworkshop.com/scaling/deploy_hpa/
https://kubernetes.io/docs/tasks/debug-application-cluster/core-metrics-pipeline/#metrics-server
まずはcluster autoscalerに割り当てるポリシーを記載した
次にcluster-autoscalerという名前のRoleを作成します。
cluster autoscalerが自動でAutoScalingGroupを見つけるために、AutoScalingGroupにタグを付与します。
Nameが
もう1つ設定します。をご自身の環境のクラスタ名に読み替えて設定してください。Valueは不要です。
まずはymlファイルをダウンロードします。
cluster-autoscaler-one-asg.yamlファイルの中を3箇所変更します。
Deploymentのspecのmetadataにannotationsを追加します。これを追加することでAutoScalintGroupの操作をする権限をPodに付与します。kube2iamの機能になります。
commandの引数の
これはAutoScalingGroupのミニマムとマックスを手動で設定する場合です。今回はAutoScalingGroupにタグを付与したため、自動で設定されます。
EC2インスタンスとKubernetes APIが通信するときに使用するcrtファイルを変更します。OSにAmazon Linux 2を使っている方は、
めちゃめちゃハマりましたが、ちゃんとドキュメントには書いてました。ドキュメント大事。
これで準備できました!
デプロイしましょう!
エラーログが出ていなかったら成功です!
それではサンプルアプリをデプロイしてオートスケールを試してみましょう!
下記のymlファイルをデプロイするとDeployment, Service, HorizontalPodAutoscalerが作られます。
作ったPodに対してGolangで負荷をかけてみます!
(Golangよく分かんないよという方はkubectl execでPodに接続し て
では負荷をかけます。
素晴らしい。。。
スクショ忘れましたが、EC2インスタンスの数もAutoScalingGroupのMaxまで増えました!
EKS最高!
EKSで何でもできるので、お仕事ください!w
https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler
https://medium.com/@alejandro.millan.frias/cluster-autoscaler-in-amazon-eks-d9f787176519
https://qiita.com/os1ma/items/7b48decb71d0c1f9ea3e#%E3%83%AF%E3%83%BC%E3%82%AB%E3%83%BC%E3%82%B0%E3%83%AB%E3%83%BC%E3%83%97%E3%81%AE%E7%99%BB%E9%8C%B2
はじめに
今回はEKSでオートスケールに挑戦します。サービスを保守・運用していく中で、リソースが枯渇してサービスの継続が困難になることは避けたいです。
KubernetesではPod(コンテナ)にリソースを割り当てることができ、リソースが不足すると自動でPodを増やす機能があります。
Horizontal Pod Autoscaler
ただEC2インスタンスのリソースが不足した場合は、Podのオートスケールは機能しません。(リソースがないから。。。)
なので、EC2インスタンスのオートスケールも必要になってきます。
cluster-autoscalerという機能を使ってEC2インスタンスのオートスケールも設定します。
これを設定することで、リソースが必要なときのみEC2インスタンスを作成し、リソースが不要になった場合はEC2インスタンスを自動で削除します。
Architecture
- cluster autoscaler
EC2インスタンスのオートスケールを担当する機能です。 - kube2iam
PodからAWSリソースを操作するためのIAM権限の管理をするツール。
cluster autoscalerを動かすためのIAM Roleをkube2iamを使って管理します。
kube2iamのデプロイは本記事では説明しません。AWSのKubernetesでサービスを公開する最高の方法~ALB,ACM,Route53の自動作成~こちらを参考にしてください。 - Metrics Server
クラスタのリソース使用量を集計してくれるツール。Podがオートスケールするために必要。前まではheapsterというツールだったが、HeapsterはKubernetes 1.11でDeprecateされた。 - Helm
Kubernetesのパッケージマネージャーです。
Metrics Serverをインストールするのに使用します。
やっていく
前提
- EKS Clusterが構築済みであること
構築されていない方はeksctlコマンドを使ってみてください!
Install Helm
README通りにやっていきます。$ curl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get > get_helm.sh $ chmod +x get_helm.sh $./get_helm.sh
cat <<EoF > ./rbac.yaml --- apiVersion: v1 kind: ServiceAccount metadata: name: tiller namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: name: tiller roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: tiller namespace: kube-system EoF
$ kubectl apply -f ~/environment/rbac.yaml $ helm init --service-account tiller
Install Metrics Server
Metrics Serverのインストールはhelmコマンドで一発でできます。$ helm install stable/metrics-server \ --name metrics-server \ --version 2.0.4 \ --namespace kube-system
https://github.com/kubernetes-incubator/metrics-server
https://eksworkshop.com/scaling/deploy_hpa/
https://kubernetes.io/docs/tasks/debug-application-cluster/core-metrics-pipeline/#metrics-server
cluster autoscaler
Create IAM Role
まずはcluster autoscalerに割り当てるポリシーを記載したclusterAutoscale-iam-policy.json
ファイルを作成します。{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "autoscaling:DescribeAutoScalingGroups", "autoscaling:DescribeAutoScalingInstances", "autoscaling:DescribeTags", "autoscaling:DescribeLaunchConfigurations", "autoscaling:SetDesiredCapacity", "autoscaling:TerminateInstanceInAutoScalingGroup" ], "Resource": "*" } ] }
export NODE_INSTANCE_ROLE_ARN=$(aws iam list-roles --query "Roles[?contains(RoleName,\`NodeInstanceRole\`)].[Arn][]" --output text) cat << EOF | jq > config/pod-role-trust-policy.json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "ec2.amazonaws.com" }, "Action": "sts:AssumeRole" }, { "Effect": "Allow", "Principal": { "AWS": "${NODE_INSTANCE_ROLE_ARN}" }, "Action": "sts:AssumeRole" } ] } EOF $ aws iam create-role \ --role-name cluster-autoscaler \ --assume-role-policy-document file://pod-role-trust-policy.json $ CLUSTER_AUTOSCALER_ARN=$(aws iam create-policy --policy-name clusterAutoscaler-iam-policy --policy-document file://clusterAutoscale-iam-policy.json --query "Policy.[Arn]" --output text) $ aws iam attach-role-policy --role-name cluster-autoscaler --policy-arn $CLUSTER_AUTOSCALER_ARN
AutoScalingGroupにタグを付与
cluster autoscalerが自動でAutoScalingGroupを見つけるために、AutoScalingGroupにタグを付与します。Nameが
k8s.io/cluster-autoscaler/enabled
でValueはtrue
にします。もう1つ設定します。をご自身の環境のクラスタ名に読み替えて設定してください。Valueは不要です。
k8s.io/cluster-autoscaler/<Your Cluster Name>
cluster autoscalerのデプロイ
まずはymlファイルをダウンロードします。$ wget https://raw.githubusercontent.com/kubernetes/autoscaler/master/cluster-autoscaler/cloudprovider/aws/examples/cluster-autoscaler-one-asg.yaml
Deploymentのspecのmetadataにannotationsを追加します。これを追加することでAutoScalintGroupの操作をする権限をPodに付与します。kube2iamの機能になります。
<Arn of cluster-autoscaler Role>
は IAMロールの作成で作成したcluster-autoscalerロールのArnです。spec: replicas: 1 selector: matchLabels: app: cluster-autoscaler template: metadata: labels: app: cluster-autoscaler annotations: iam.amazonaws.com/role: <Arn of cluster-autoscaler Role>
--nodes
をコメントアウトします。これはAutoScalingGroupのミニマムとマックスを手動で設定する場合です。今回はAutoScalingGroupにタグを付与したため、自動で設定されます。
command: - ./cluster-autoscaler - --v=4 - --stderrthreshold=info - --cloud-provider=aws - --skip-nodes-with-local-storage=false # - --nodes=1:5:NODEGROUP_NAME
/etc/ssl/certs/ca-bundle.crt
を記述してください。めちゃめちゃハマりましたが、ちゃんとドキュメントには書いてました。ドキュメント大事。
volumes: - name: ssl-certs hostPath: # path: "/etc/ssl/certs/ca-certificates.crt" path: "/etc/ssl/certs/ca-bundle.crt"
デプロイしましょう!
$ kubectl apply -f cluster-autoscaler-one-asg.yaml
$ kubectl logs -n kube-system cluster-autoscaler-XXXXX
試してみる
それではサンプルアプリをデプロイしてオートスケールを試してみましょう!下記のymlファイルをデプロイするとDeployment, Service, HorizontalPodAutoscalerが作られます。
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: nginx-test labels: name: nginx-test namespace: default spec: replicas: 1 selector: matchLabels: name: nginx-test template: metadata: labels: name: nginx-test spec: containers: - name: nginx-test image: nginx:stable-alpine ports: - name: nginx-port containerPort: 80 resources: requests: cpu: 100m memory: 30Mi limits: cpu: 100m memory: 30Mi dnsConfig: nameservers: - 8.8.8.8 --- kind: Service apiVersion: v1 metadata: name: nginx-test labels: name: nginx-test namespace: default spec: selector: name: nginx-test ports: - name: nginx-port port: 80 targetPort: 80 protocol: TCP type: "NodePort" --- apiVersion: autoscaling/v2beta1 kind: HorizontalPodAutoscaler metadata: name: nginx-test-scale namespace: default spec: scaleTargetRef: # ここでautoscale対象となるscaled resource objectを指定 apiVersion: extensions/v1beta1 kind: Deployment name: nginx-test minReplicas: 1 # 最小レプリカ数 maxReplicas: 10 # 最大レプリカ数 metrics: - type: Resource resource: name: cpu targetAverageUtilization: 5 # CPU使用率が常に5%になるように指定
(Golangよく分かんないよという方はkubectl execでPodに接続し て
yes > /dev/null
コマンドでも負荷かけれます。)package main import ( "net/http" "sync" "log" "time" ) func main() { url := "http://192.168.100.100:30534/" // アクセスするURLだよ! maxConnection := make(chan bool,1000) // 同時に並列する数をしていできるよ!(第二引数) wg := &sync.WaitGroup{} // 並列処理が終わるまでSleepしてくれる便利なやつだよ! count := 0 // いくつアクセスが成功したかをアカウントするよ! start := time.Now() // 処理にかかった時間を測定するよ! for maxRequest := 0; maxRequest < 50000; maxRequest ++{ // 10000回リクエストを送るよ! wg.Add(1) // wg.add(1)とすると並列処理が一つ動いていることを便利な奴に教えるよ! maxConnection <- true // ここは並列する数を抑制する奴だよ!詳しくはググって! go func() { // go func(){/*処理*/}とやると並列処理を開始してくれるよ! defer wg.Done() // wg.Done()を呼ぶと並列処理が一つ終わったことを便利な奴に教えるよ! resp, err := http.Get(url) // GETリクエストでアクセスするよ! if err != nil { // err ってのはエラーの時にエラーの内容が入ってくるよ! return // 回線が狭かったりするとここでエラーが帰ってくるよ! } defer resp.Body.Close() // 関数が終了するとなんかクローズするよ!(おまじない的な) count++ // アクセスが成功したことをカウントするよ! <-maxConnection // ここは並列する数を抑制する奴だよ!詳しくはググって! }() } wg.Wait() // ここは便利な奴が並列処理が終わるのを待つよ! end := time.Now() // 処理にかかった時間を測定するよ! log.Printf("%d 回のリクエストに成功しました!\n", count) // 成功したリクエストの数を表示してくれるよ! log.Printf("%f 秒処理に時間がかかりました!\n",(end.Sub(start)).Seconds()) //何秒かかったかを表示するよ! }
$ go run stress.go
素晴らしい。。。
スクショ忘れましたが、EC2インスタンスの数もAutoScalingGroupのMaxまで増えました!
まとめ
EKS最高!EKSで何でもできるので、お仕事ください!w
References
https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscalerhttps://medium.com/@alejandro.millan.frias/cluster-autoscaler-in-amazon-eks-d9f787176519
https://qiita.com/os1ma/items/7b48decb71d0c1f9ea3e#%E3%83%AF%E3%83%BC%E3%82%AB%E3%83%BC%E3%82%B0%E3%83%AB%E3%83%BC%E3%83%97%E3%81%AE%E7%99%BB%E9%8C%B2
コメント
コメントを投稿