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
コメント
コメントを投稿