k8sスケジューリングの方法
k8sでは、Podのスケーリングは以下の2つの方法で行います。
- Affinity:Podのスケジューリング時に特定のNodeを選択する方法
- 特徴:Podに選択権を持つ
- TaintsとTolerations:Nodeに属性(Taints)を付け、Podにも属性(Tolerations)を付け、属性の比較でスケジューリングする方法
- 特徴:Nodeにも選択権を持てる
TaintsとTolerations
TaintsとTolerationsについて、公式ドキュメントでは、以下のように説明しています。
Taints and tolerations work together to ensure that pods are not scheduled onto inappropriate nodes. One or more taints are applied to a node; this marks that the node should not accept any pods that do not tolerate the taints.
簡単にイメージすると:
- Nodeにロック(Taints)を付ける
- Podに鍵(Tolerations)を渡す
- 鍵が正しいPodのみがNodeにスケジューリングできる
そのため、Taintsを持っているNodeは、正しいTolerationsを持っているPodしかスケジューリングされないです。
また、Node Affinityはスケジューリング時にのみ作用するに対して、TaintsとTolerationsは随時適用されます。
即ち、スケジューリング済みのPodでも、随時TaintsとTolerationsをチェックし、Podのスケジューリングを動的に実施されます。
TaintsとTolerationsの情報構成
TaintsとTolerationsは以下の情報で構成されています。
<Key>=<Value>:<Effect>
-
= :TaintsはKey-Value形式のデータ -
:TaintsとTolerationsがマッチしない時の挙動
<Effect>
は以下の3種類があります
- PreferNoSchedule:可能な限りスケジューリングしない
- NoSchedule:スケジューリングしない(スケジューリング済みのPodはそのままにする)
- スケジューリング時のみ考慮すればいい
- NoExecute:スケジューリング許可しない(スケジューリング済みのPodは追い出される)
- スケジューリング後も、影響を与えられる
- 追い出すタイミングはPodの
spec.terminationGracePeriodSeconds
でコントロールできる
※注意:スケジューリング時の動作はTaintsの
NodeへTaintsの付与と削除
KubernetesのNodeはmanifestで定義するものではないため、Taintsの付与はkubectlコマンドで実施します。
使用するコマンドは kubectl taint
です
Taints付与例:
# foo=bar:NoExecute のtaintを<nodeName> Nodeに付ける
kubectl taint node <nodeName> foo=bar:NoExecute
# 特定ラベルを持つすべてのNodeにfoo=bar:NoExecute のtaintを付ける
kubectl taint node -l <nodeLabelkey>=<nodeLabelValue> foo=bar:NoExecute
Taints削除例:
# <Key>がfooのTaintを削除
kubectl taint node <nodeName> foo-
# <Key>がfooで、<Effect>がNoScheduleのTaintを削除
kubectl taint node <nodeName> foo:<NoSchedule>
Taints確認:
Node詳細情報確認コマンド(kubectl describe)で、Taints情報も確認でいます
# Node詳細情報確認
kubectl describe node <nodeName>
複数Taintsを持つNode
Nodeが複数Taintsを持っている場合、PodのTolerationsがすべてNodeのTaintsにマッチする場合のみ、スケジューリングされます。
Taintsの応用
Taintsはよく障害時Podの自動退避手段として使用されます。
GKEの場合、Nodeの状態に応じて、リアルタイムでNodeにNoExecuteのTaintsが付けられます。
例えば、cordonを実施したNodeにnode.kubernetes.io/unschedulable:NoSchedule
のTaintsがリアルタイムで付けられます。
PodのTolerations
Podのspec.tolerations[]
で、Tolerationsを設定することが可能です。
また、Tolerationsの設定では、以下のoperator(演算子)が使えます。
- Equal
- Exists
Tolerations例:
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
tolerations: # PodのTolerations指定、複数指定可能:複数鍵を持っているイメージ
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoSchedule"
- key: "key2"
operator: "Exists"
effect: "NoExecute"
TaintsとTolerations判断
PodのTolerationsとNodeのTaintsのマッチ判断は、公式情報で以下のように述べています。
A toleration “matches” a taint if the keys are the same and the effects are the same, and:
- the operator is Exists (in which case no value should be specified), or
- the operator is Equal and the values are equal.
即ち、スケジューリングされる条件は以下です。
- Taintsの
と同じ はTolerationsがすべて持っていて、かつ も同じ - operatorの設定のよる判断
- Equal:Tolerationsの
がTaintsの と同じの場合のみ、マッチと判断 - Exists:
が同じでなくても、マッチと判断
- Equal:Tolerationsの
Tolerations特例「operator: "Exists"」
ここで、以下の特例を覚えておきましょう
Taintsを無視して、どこでもスケジューリング可能のTolerations条件:operator: "Exists"
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
tolerations:
- operator: "Exists" # この条件は万能キーになる、どのNodeでもスケジューリング可能
Tolerations特例「effect指定なし」
Tolerationsにeffect指定しない場合、Taintsと同じと判断されます。
NoExecuteとtolerationSeconds
TolerationsのEffectが"NoExecute"の場合のみ、TolerationsとTaintsがマッチしても、一定時間しか稼働させない設定ができます。
指定時間を0やマイナス数値にする場合、即時追い出すようになります。
例:
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoExecute"
tolerationSeconds: 3000 # TolerationsとTaintsがマッチしても、3000秒の稼働しか許容しない
この設定は、よくTaintsとTolerationsがマッチしても、NoExecuteの場合はPodを追い出すために使われます。(時間を0に設定)
※即ち、どんなPodでも追い出すようにする。
最後に
今回の内容を理解するのに、結構手間がかかりました。
できるだけ分かりやすく書いてみました。
お役に立つと嬉しいです。
ここまで読んでいただいて、お疲れ様でした。
コメント