リソース定義@Karpenter¶
はじめに¶
本サイトにつきまして、以下をご認識のほど宜しくお願いいたします。
01. EC2NodeClass¶
EC2NodeClassとは¶
NodePool内のNodeに対して、AWS固有の仕様を設定する。
ClusterスコープなKubernetesリソースであるため、Namespaceは設定できない。
Terraformのaws_launch_template
ブロックと競合する。
amiFamily¶
AWS AMIの種類を設定する。
apiVersion: karpenter.k8s.aws/v1beta1
kind: EC2NodeClass
metadata:
name: foo-node-class
spec:
# 最適化 Amazon Linux 2 を指定する
amiFamily: AL2
amiSelectorTerms¶
EC2 NodeのAMIを設定する。
AMIのバージョンを固定したい場合に役立つ。
設定しない場合、Karpenterは最適化AMIを自動的に選択する。
apiVersion: karpenter.k8s.aws/v1beta1
kind: EC2NodeClass
metadata:
name: foo-node-class
spec:
amiSelectorTerms:
- name: ami-*****
blockDeviceMappings¶
プロビジョニングするEC2 Nodeのブロックデバイスを設定する。
100
Gi以上のルートボリュームのデバイスパス (/dev/xvda
) を設定しないと、ボリューム不足でNodeをプロビジョニングできず、エラーになってしまう。
apiVersion: karpenter.k8s.aws/v1beta1
kind: EC2NodeClass
metadata:
name: foo-node-class
spec:
blockDeviceMappings:
- deviceName: /dev/xvda
ebs:
volumeSize: 100Gi
volumeType: gp3
encrypted: true
detailedMonitoring¶
EC2 NodeのCloudWatchによる監視を設定する。
metadataOptions¶
EC2 Nodeのメタデータへのアクセスを制御する。
apiVersion: karpenter.k8s.aws/v1beta1
kind: EC2NodeClass
metadata:
name: foo-node-class
spec:
metadataOptions:
httpEndpoint: enabled
httpProtocolIPv6: disabled
httpPutResponseHopLimit: 2
httpTokens: required
instanceProfile¶
IAMロールの代わりに使用するIAMインスタンスプロファイル名を設定する。
プライベートなEKS Cluster (アウトバウンド通信を禁止している) の場合、IAMロールの代わりにIAMインスタンスプロファイルを使用する。
apiVersion: karpenter.k8s.aws/v1beta1
kind: EC2NodeClass
metadata:
name: foo-node-class
spec:
instanceProfile: foo-instance-profile
role¶
IAMプロファイル名の代わりに使用するIAMロールを設定する。
プライベートなEKS Cluster (アウトバウンド通信を禁止している) の場合、IAMロールの代わりにIAMインスタンスプロファイルを使用する。
apiVersion: karpenter.k8s.aws/v1beta1
kind: EC2NodeClass
metadata:
name: foo-node-class
spec:
role: foo-node-role
securityGroupSelectorTerms¶
EC2 Nodeに紐づけるセキュリティグループを動的に検出するために、クラスターセキュリティグループのリソースを設定する。
apiVersion: karpenter.k8s.aws/v1beta1
kind: EC2NodeClass
metadata:
name: foo-node-class
spec:
securityGroupSelectorTerms:
- tags:
Name: foo-private-sg
subnetSelectorTerms¶
EC2 Nodeをプロビジョニングするサブネットを動的に検出するために、サブネットのリソースを設定する。
apiVersion: karpenter.k8s.aws/v1beta1
kind: EC2NodeClass
metadata:
name: foo-node-class
spec:
subnetSelectorTerms:
- tags:
Name: foo-private-subnet
status¶
karpenter-controllerがEC2 Nodeを作成するために取得した情報を自動的に設定する。
apiVersion: karpenter.k8s.aws/v1beta1
kind: EC2NodeClass
metadata:
name: foo-node-class
status:
amis:
- id: ami-*****
name: foo-ami
requirements:
- key: kubernetes.io/arch
operator: In
values:
- arm64
- key: karpenter.k8s.aws/instance-gpu-count
operator: DoesNotExist
- key: karpenter.k8s.aws/instance-accelerator-count
operator: DoesNotExist
instanceProfile: foo-cluster-*****
securityGroups:
- id: sg-*****
name: foo-cluster*****
subnets:
- id: subnet-*****
zone: ap-northeast-1c
- id: subnet-*****
zone: ap-northeast-1d
- id: subnet-*****
zone: ap-northeast-1a
tags¶
▼ tags¶
NodePool配下のEC2 Node、またこれに紐づくAWSリソース (例:EBSボリュームなど) に挿入するタグを設定する。
なお、NodePool配下のEC2 Nodeは起動テンプレートから作成するが、起動テンプレート自体はEC2 Nodeの作成後に削除するようになっている。
▼ デフォルトのタグ¶
KarpenterがEC2 Nodeにデフォルトで挿入するタグは上書きしないように、設定しない。
apiVersion: karpenter.k8s.aws/v1beta1
kind: EC2NodeClass
metadata:
name: foo-node-class
spec:
tags:
# AWSはKarpenterがプロビジョニングしたAWSリソースにタグを挿入する
aws:ec2:fleet-id: fleet-*****
aws:ec2launchtemplate:id: lt-*****
aws:ec2launchtemplate:version: 1
aws:eks:cluster-name: foo-cluster
# Karpenterは、カスタムリソースとEC2の状態を紐づけるためのタグを挿入する
karpenter.sh/managed-by: foo-cluster
karpenter.sh/nodeclaim: foo-claim-*****
karpenter.sh/nodepool: foo-nodepool
karpenter.k8s.aws/ec2nodeclass: foo-node-class
karpenter.k8s.aws/cluster: foo-cluster
# AWS EKSにとってはセルフマネージドNodeになるため、KarpenterはセルフマネージドNodeとして認識されるようにタグを挿入してくれる
kubernetes.io/cluster/foo-cluster: owned
▼ ユーザー定義のタグ¶
EC2 Nodeに挿入するユーザー定義のタグを設定できる。
apiVersion: karpenter.k8s.aws/v1beta1
kind: EC2NodeClass
metadata:
name: foo-node-class
spec:
tags:
Env: prd
ManagedBy: https://github.com/hiroki-hasegawa/foo-karpenter.git
# Karpenterが管理することがわかりやすいように、接尾辞は "karpenter" とする
Name: bar-cluster-foo-karpenter
karpenter.sh/discovery: foo-cluster
▼ IRSA用IAMロールの条件と一致させる¶
ここで挿入するタグと、AWS IAMポリシーの条件で指定するタグと一致させる必要がある。
{
"Statement": [
{
"Action": "ec2:RunInstances",
"Condition": {
"StringEquals": {
# KarpenterのEC2NodeClassで挿入した起動テンプレートのタグを指定する
"ec2:ResourceTag/karpenter.sh/discovery": [
"foo-cluster",
]
}
},
"Effect": "Allow",
"Resource": "arn:aws:ec2:*:<アカウントID>:launch-template/*",
"Sid": ""
},
...
"Version": "2012-10-17"
]
}
もちろん、Karpenter以外の方法 (例:Terraformなど) で挿入したタグを使用しても良い。
userData¶
プロビジョニングするEC2 Nodeのユーザーデータを設定する。
02. NodePool¶
NodePoolとは¶
NodePool内のNodeに対して、クラウドプロバイダーに依らない仕様を設定する。
EC2 Nodeのグループ (例:AWS EKS Nodeグループ、Google Cloud Nodeプールなど) に合わせて、複数作成すると良い。
ClusterスコープなKubernetesリソースであるため、Namespaceは設定できない。
disruption¶
▼ consolidationPolicy¶
Node統合の条件を設定する。
apiVersion: karpenter.sh/v1beta1
kind: NodePool
metadata:
name: foo-nodepool
spec:
disruption:
consolidationPolicy: WhenUnderutilized
▼ consolidateAfter¶
EC2 NodeからPodが全て退避した後にEC2 Nodeを削除するまでの待機時間を設定する。
apiVersion: karpenter.sh/v1beta1
kind: NodePool
metadata:
name: foo-nodepool
spec:
disruption:
consolidateAfter: 30s
▼ expireAfter¶
EC2 Nodeを削除し、再作成するまでの期間を設定する。
EC2 Nodeを定期的に再作成することにより、最適なスペックを再設定するため、脆弱性抑制やコスト削減につながる。
apiVersion: karpenter.sh/v1beta1
kind: NodePool
metadata:
name: foo-nodepool
spec:
disruption:
expireAfter: 720h
limits¶
プロビジョニングするEC2 Nodeが持つハードウェアリソース (CPU、メモリ) の上限を設定する。
Karpenter配下のEC2 Nodeのハードウェアリソースがこれを超過した場合に、既存のNodeを削除しないと、新しいものをプロビジョニングできない。
apiVersion: karpenter.sh/v1beta1
kind: NodePool
metadata:
name: foo-nodepool
spec:
limits:
cpu: 1000m
memory: 1024Mi
weight¶
複数のProvisionerがある場合に、このProvisionerの優先順位の高さを設定する。
デフォルトでは、重みが0
である。
apiVersion: karpenter.sh/v1beta1
kind: NodePool
metadata:
name: foo-nodepool
spec:
weight: 10
02-02. .template.metadata¶
annotations¶
EC2 Nodeに付与するアノテーションを設定する。
apiVersion: karpenter.sh/v1beta1
kind: NodePool
metadata:
name: foo-nodepool
spec:
template:
metadata:
annotations:
example.com/owner: my-team
02-03. .template.spec¶
kubelet¶
kubeletのKubeletConfiguration
オプションにパラメーターを渡す。
apiVersion: karpenter.sh/v1beta1
kind: NodePool
metadata:
name: foo-nodepool
spec:
template:
spec:
kubelet:
clusterDNS:
- 10.0.1.100
containerRuntime: containerd
systemReserved:
cpu: 100m
memory: 100Mi
ephemeral-storage: 1Gi
kubeReserved:
cpu: 200m
memory: 100Mi
ephemeral-storage: 3Gi
evictionHard:
memory.available: 5%
nodefs.available: 10%
nodefs.inodesFree: 10%
evictionSoft:
memory.available: 500Mi
nodefs.available: 15%
nodefs.inodesFree: 15%
evictionSoftGracePeriod:
memory.available: 1m
nodefs.available: 1m30s
nodefs.inodesFree: 2m
evictionMaxPodGracePeriod: 60
imageGCHighThresholdPercent: 85
imageGCLowThresholdPercent: 80
cpuCFSQuota: true
podsPerCore: 2
maxPods: 20
▼ labels¶
EC2 Nodeに付与するラベルを設定する。
apiVersion: karpenter.sh/v1beta1
kind: NodePool
metadata:
name: foo-nodepool
spec:
template:
metadata:
labels:
# Karpenterの管理するEC2 Nodeにラベルを挿入する
node.kubernetes.io/nodetype: foo
nodeClassRef¶
Provisionerで使用するEC2 NodeClass名を設定する。
apiVersion: karpenter.sh/v1beta1
kind: NodePool
metadata:
name: foo-nodepool
spec:
template:
spec:
nodeClassRef:
name: foo-node-class
requirements¶
▼ requirementsとは¶
プロビジョニングするEC2 Nodeのハードウェアリソースを制限する。
制限しなかった項目は、Karpenterがよしなに設定値を選ぶ。
*実装例*
apiVersion: karpenter.sh/v1beta1
kind: NodePool
metadata:
name: foo-nodepool
spec:
template:
spec:
requirements:
- key: karpenter.k8s.aws/instance-category
operator: In
values:
- c
- m
- r
- key: karpenter.k8s.aws/instance-cpu
operator: In
values:
- 4
- 8
- 16
- 32
- key: karpenter.k8s.aws/instance-hypervisor
operator: In
values:
- nitro
- key: karpenter.k8s.aws/instance-generation
operator: Gt
values:
- 2
- 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
*実装例*
apiVersion: karpenter.sh/v1beta1
kind: NodePool
metadata:
name: foo-nodepool
spec:
template:
spec:
requirements:
- key: kubernetes.io/arch
operator: In
# ARM製よりAMD製に対応したベースイメージの方が多いので、AMD製を指定する
values:
- amd64
- key: karpenter.k8s.aws/instance-family
operator: In
# ハードウェアリソース要求量が瞬間的に増える場合、T系を指定する
values:
- t3
- key: karpenter.k8s.aws/instance-size
operator: In
values:
- medium
- large
- xlarge
# オンデマンドインスタンスを指定する
- key: kubernetes.io/os
operator: In
values:
- linux
- key: karpenter.sh/capacity-type
operator: In
values:
# オンデマンドインスタンス
- on-demand
▼ 指定できるキー名¶
startupTaints¶
apiVersion: karpenter.sh/v1beta1
kind: NodePool
metadata:
name: foo-nodepool
spec:
template:
spec:
startupTaints:
- key: example.com/another-taint
effect: NoSchedule
taints¶
apiVersion: karpenter.sh/v1beta1
kind: NodePool
metadata:
name: foo-nodepool
spec:
template:
spec:
taints:
- key: example.com/special-taint
effect: NoSchedule
03. グローバル設定用ConfigMap¶
aws.interruptionQueueName¶
割り込み処理を有効化する場合に、AWS SQSの名前を設定する。
別途、AWS SQSを作成し、KarpenterにAWS SQSへの権限を付与しておく必要がある。
apiVersion: v1
kind: ConfigMap
metadata:
name: karpenter-global-settings
namespace: karpenter
data:
aws.interruptionQueueName: foo-queue
aws.clusterName¶
apiVersion: v1
kind: ConfigMap
metadata:
name: karpenter-global-settings
namespace: karpenter
data:
aws.clusterName: foo-cluster
aws.clusterEndpoint¶
AWS EKS Clusterのkube-apiserverのURLを設定する。
apiVersion: v1
kind: ConfigMap
metadata:
name: karpenter-global-settings
namespace: karpenter
data:
aws.clusterEndpoint: https://*****.gr7.ap-northeast-1.eks.amazonaws.com
batchMaxDuration¶
apiVersion: v1
kind: ConfigMap
metadata:
name: karpenter-global-settings
namespace: karpenter
data:
batchMaxDuration: 10s
batchIdleDuration¶
apiVersion: v1
kind: ConfigMap
metadata:
name: karpenter-global-settings
namespace: karpenter
data:
batchIdleDuration: 1s
04. ロギング設定用のConfigMap¶
zap-logger-config¶
ロギングを設定する。
zapパッケージを使用しているため、設定値の種類はzapパッケージのものである。
apiVersion: v1
kind: ConfigMap
metadata:
name: config-logging
data:
zap-logger-config: |
{
"level": "debug",
"development": "false",
"disableStacktrace": "true",
"disableCaller": "true",
"sampling": {
"initial": 100,
"thereafter": 100
},
"outputPaths": ["stdout"],
"errorOutputPaths": ["stderr"],
# 見やすいログ形式にする
"encoding": "console",
"encoderConfig": {
"timeKey": "time",
"levelKey": "level",
"nameKey": "logger",
"callerKey": "caller",
"messageKey": "message",
"stacktraceKey": "stacktrace",
"levelEncoder": "capital",
"timeEncoder": "iso8601"
}
}
loglevel.controller¶
記入中...
apiVersion: v1
kind: ConfigMap
metadata:
name: config-logging
data:
loglevel.controller: debug
loglevel.webhook¶
記入中...
apiVersion: v1
kind: ConfigMap
metadata:
name: config-logging
data:
loglevel.webhook: error
05. Podの.metadata.annotations
キー¶
karpenter.sh/do-not-disrupt¶
長時間実行するPodの場合、完了前にKarpenterがNodeを終了しないようにする必要がある。
karpenter.sh/do-not-disrupt
キーを設定すると、Podの終了を待機できる。
apiVersion: apps/v1
kind: Deployment
spec:
template:
metadata:
annotations:
karpenter.sh/do-not-disrupt: true