2021年の re:invent にて GA となったことが発表された、Karpenter について調べてみたのでその共有となります。
公式HP: https://karpenter.sh/
リポジトリ: https://github.com/aws/karpenter
Karpenter とは
AWS がホストしているオープンソースのクラスターオートスケーラーです。目的は Cluster Autoscaler と同様で、Kubernetes のノードが足りなくなったら足して、不要になったら削除するというのを実現します。
現状 AWS のみサポートされていますが、他のクラウドプロバイダーでも動くように設計されているようです。
Karpenter の特徴
https://karpenter.sh/v0.6.4/concepts/
高速なプロビジョニング
Karpenter は起動したノードに pod をバインドします。そのため、kube-scheduler によるノードの選定などを待たずに高速で pod を起動することができます。
柔軟なリソース選択
スケジュールできない pod 全体でどれだけリソースが必要なのかを計算した上で、最適なインスタンスタイプを選択してくれます。
またこれを実現するために、Auto Scaling Group のようなノードグループを使わず、Karpenter によって起動されたノードは直接管理されます。
機能について
https://karpenter.sh/v0.6.4/provisioner/
Karpenter では、Provisioner を使って振る舞いを設定していきます。
apiVersion: karpenter.sh/v1alpha5 kind: Provisioner metadata: name: default spec: # If nil, the feature is disabled, nodes will never expire ttlSecondsUntilExpired: 2592000 # 30 Days = 60 * 60 * 24 * 30 Seconds; # If nil, the feature is disabled, nodes will never scale down due to low utilization ttlSecondsAfterEmpty: 30 # Provisioned nodes will have these taints # Taints may prevent pods from scheduling if they are not tolerated taints: - key: example.com/special-taint effect: NoSchedule # Labels are arbitrary key-values that are applied to all nodes labels: billing-team: my-team # Requirements that constrain the parameters of provisioned nodes. # These requirements are combined with pod.spec.affinity.nodeAffinity rules. # Operators { In, NotIn } are supported to enable including or excluding values requirements: - key: "node.kubernetes.io/instance-type" operator: In values: ["m5.large", "m5.2xlarge"] - key: "topology.kubernetes.io/zone" operator: In values: ["us-west-2a", "us-west-2b"] - key: "kubernetes.io/arch" operator: In values: ["arm64", "amd64"] - key: "karpenter.sh/capacity-type" operator: In values: ["spot", "on-demand"] # Resource limits constrain the total size of the cluster. # Limits prevent Karpenter from creating new instances once the limit is exceeded. limits: resources: cpu: "1000" memory: 1000Gi
Provisionerで設定できることは以下のようなことです。
- 選択できるインスタンスタイプ、Availability Zone、スポット/オンデマンドなどの制限
- プロビジョニングするノードへの
taints
の付与 - ノードの TTL の設定
1.指定秒数を経過した場合、ノードを終了します
2.ノードから pod が無くなってからの秒数を設定することも可能です - リソース数の上限設定
1.全インスタンスの CPU、メモリの合計値に制限をかけることができます
2.ただし、実装として制限を超えた場合に新しいノードのプロビジョニングを止めるものとなっています
その他
karpenter.sh/do-not-evict
というアノテーションが pod に入っている場合、ノードの削除要求があっても無視されます
→ 長時間かかるようなバッチ処理で最後まで動き切って欲しいケースなどで有効- Provisioner によって
taint
が設定され pod がそれを許容できない場合、プロビジョニングを中止します
→ ノードは立つけど pod がスケジュールされない or そもそもノードが立たないのかは実験が必要そうです - Provisioner を複数設定する場合は、排他的な設定になるように設計することが推奨されています
→ pod が複数の Provisioner の条件に当てはまる場合、使用する Provisioner はランダムに選択されます - Karpenter がノード管理をしているので、例えば Kubernetes クラスタを削除したときにノードが残ります
所感
- 体感ですが Cluster Autoscaler よりも立ち上がりが早いと感じました
- ノードグループに囚われずインスタンスタイプが変わるのがクラウド使っている感ありました
- 事前にノードを増やしておくような設定ができると良いなと思いました
- pod 増やせばノードも増えて万事解決
ハンズオンした際に使った Terraform はこちらになります。