cluster-autoscalerのコードを読む (ASG一覧をどうやって取得しているか)
EKSでcluster-autoscalerを利用してASGをスケールさせているのですが、詳しい挙動を把握していなかったので調べてみました。EKSなので、今回はAWS環境に特化しています。
Karpenterについても気になっているので近々触れてみたいと考えています。
この記事では、ASG一覧をどうやって取得しているかを見ていきます。
podを割り当てるためにどのASGをスケールさせるかについても記事にしたいと思います。
cluster-autoscalerはscalInterval秒ごとに処理( RunOnce
)を実行している
for { select { case <-time.After(*scanInterval): { loopStart := time.Now() metrics.UpdateLastTime(metrics.Main, loopStart) healthCheck.UpdateLastActivity(loopStart) err := autoscaler.RunOnce(loopStart)
client-goを使って、node一覧を取得しています。
allNodes, readyNodes, typedErr := a.obtainNodeLists(a.CloudProvider)
どうやってcluster-autoscalerはターゲットとなるASGsを取得するのか
refreshInterval(1分)ごとにASG一覧を取得 (コード)
refreshIntervalはハードコーディングされているので、起動引数で変更することはできなそうです。ASGを削除してから1分以内にスケールイベントが発生するときはエラーが発生する可能性がありそうです。
func (m *AwsManager) Refresh() error { if m.lastRefresh.Add(refreshInterval).After(time.Now()) { return nil } return m.forceRefresh() }
指定したtagsを元にASG一覧を取得
tagsはASGの起動引数(--node-group-auto-discovery
)で指定しています。
e.g. --node-group-auto-discovery=asg:tag=k8s.io/cluster-autoscaler/enabled,k8s.io/cluster-autoscaler/sample-eks-cluster
cluster-autoscalerが、引数の値をparseして、asg:tag=の右の値の箇所(k8s.io...,k8s.io...
)をカンマ区切りでリスト化しています。 (コード)
aws-sdk-goを使って指定したTagを満たすASG一覧をフェッチ(コード)
tagごとにASG一覧を取得します。
err := m.DescribeTagsPages(input, func(out *autoscaling.DescribeTagsOutput, _ bool) bool { tags = append(tags, out.Tags...) // We return true while we want to be called with the next page of // results, if any. return true })
すべてのtagを満たすASGをasgNamesにセット
asgNames := []string{} asgNameOccurrences := make(map[string]int) for _, t := range tags { asgName := aws.StringValue(t.ResourceId) occurrences := asgNameOccurrences[asgName] + 1 if occurrences >= len(kvs) { asgNames = append(asgNames, asgName) } asgNameOccurrences[asgName] = occurrences } return asgNames, nil
asgNamesをasgCacheにセットします。
ASGの情報を取得するために、再度aws-sdk-goを使って、describe autoscalingを叩いています。(getAutoscalingGroupsByNames
)
func (m *asgCache) regenerate() error { ... refreshNames, err := m.buildAsgNames() ... groups, err := m.awsService.getAutoscalingGroupsByNames(refreshNames)