目次
1. スケジュールの制約
Kubernetes は List-Watch メカニズムを使用して各コンポーネントと連携してデータの同期を維持し、各コンポーネント間の設計により分離が実現されます。
ユーザーは、構成ファイルに従って kubectl 経由で APIServer にコマンドを送信し、Node ノード上にポッドとコンテナを作成します。
APIServer は、API 呼び出し、権限制御、リソース呼び出し、リソース ストレージのプロセスを経ていますが、実際にはアプリケーションのデプロイを開始していません。導入プロセス全体を完了するには、コントローラー マネージャー、スケジューラー、および kubelet の支援が必要です。
Kubernetes では、すべてのデプロイメント情報が etcd に書き込まれ、保存されます。実際、etcd がデプロイメント情報を保存すると、Create イベントが APIServer に送信され、APIServer は etcd によって送信されたイベントをリッスン (監視) します。他のコンポーネントも APIServer によって送信されたイベントを監視 (ウォッチ) します。
2. ポッド起動の一般的な作成プロセス
(1) ここには 3 つの List-Watch があります。つまり、Controller Manager (マスター上で実行)、Scheduler (マスター上で実行)、および kubelet (ノード上で実行) です。プロセスの開始後に APIServer によって送信されたイベントをリッスン (監視) します。
(2) ユーザーは、kubectl または他の API クライアントを通じて APIServer にリクエストを送信し、Pod オブジェクトのコピーを作成します。
(3) APIServer は Pod オブジェクトの関連メタ情報を etcd に保存しようとします。書き込み操作が完了すると、APIServer は確認情報をクライアントに返します。
(4) etcd は Pod 作成情報を受け取ると、Create イベントを APIServer に送信します。
(5) コントローラー マネージャーが APIServer 内のイベントをリッスン (https のポート 6443 経由で監視) しているため。このとき、APIServer は Create イベントを受信し、Controller Manager に送信します。
(6) Create イベントを受信した後、コントローラー マネージャーはレプリケーション コントローラーを呼び出し、ノード上に作成する必要があるコピーの数を確認します。レプリカの数が RC で定義された数よりも少なくなると、RC は自動的にレプリカを作成します。要するにコピー数を保証するController(PS:伸縮を担当)です。
(7) Controller Manager が Pod のコピーを作成した後、APIServer は Pod の詳細情報を etcd に記録します。たとえば、ポッドのコピーの数やコンテナの内容などです。
(8) 同じ etcd がイベントを通じて APIServer に Pod 作成情報を送信します。
(9) スケジューラはAPIServerを監視(Watching)しており、システムの「上位と下位を繋ぐ」役割を担っているため、「上位を繋ぐ」とは、作成されたPodイベントを受信してNodeを配置する役割を担うことになります。彼らにとって、「下位を接続する」ということは、配置作業が完了した後、ノード上の kubelet プロセスが後続の作業を引き継ぎ、ポッドのライフサイクルの「後半」を担当することを意味します。言い換えれば、スケジューラーの役割は、スケジューリング アルゴリズムとポリシーに従って、スケジュールされるポッドをクラスター内のノードにバインドすることです。
(10) スケジューラはスケジューリング完了後に Pod 情報を更新しますが、このときの情報はより豊富になります。ポッドのレプリカの数に加えて、レプリカの内容もわかります。また、どのノードにデプロイするかもわかります。そして上記のPod情報をAPI Serverに更新し、APIServerからetcdに更新して保存します。
(11) etcd は更新に成功したイベントを APIServer に送信し、APIServer もこの Pod オブジェクトのスケジューリング結果の反映を開始します。
(12) Kubelet は Node 上で実行されるプロセスであり、APIServer によって送信された Pod 更新イベントを List-Watch (Watch、https のポート 6443 経由) を通じてリッスンします。kubelet は、現在のノードで Docker を呼び出してコンテナを起動しようとし、結果として得られるポッドとコンテナのステータスを APIServer に送り返します。
(13) APIServerはPodのステータス情報をetcdに保存します。etcd が書き込み操作が正常に完了したことを確認すると、APIServer はイベントが受け入れられる関連する kubelet に確認メッセージを送信します。
注: ポッドの作成作業が完了した後も、kubelet がまだリッスンし続けるのはなぜですか? 理由は非常に簡単で、この時点で kubectl が Pod のコピー数を拡張するコマンドを発行すると、上記のプロセスが再度トリガーされ、kubelet が最新の Pod デプロイメントに応じて Node リソースを調整します。あるいは、Pod のコピー数は変わっていないものの、その中のイメージ ファイルがアップグレードされており、kubelet が自動的に最新のイメージ ファイルを取得してロードしている可能性があります。
リストウォッチ機構
1. kubectl は、Pod リソース オブジェクトのコピーを作成するリクエストを apiserver に送信し、apiserver は Pod リソース オブジェクトのコピーを作成するリクエストを etcd に書き込みます。
2. etcd が記述された後、完成した Pod コピーの作成イベントが apiserver に送信され、apiserver はライフサイクルをクライアントに直接返します。
3. 次に、Pod のコピーを作成するイベントをコントローラー マネージャーに送信します。コントローラー マネージャーは、関連するイベントに従って Pod を作成し、Pod の作成に関する情報を apiserver に送信します。作成された Pod に関する関連コンテンツ情報 (コピー数、コンテナーのコンテンツなど) が etcd に書き込まれます。
4. etcd はポッド作成イベントを apiserver に送信し、apiserver はイベントをスケジューラーに送信します。
5. スケジューラは、スケジューリング アルゴリズムを通じて Pod がどのノードに作成されるかを決定し、決定後、更新された Pod 情報を APIserver 経由で etcd に書き込みます。
6. 次に、etcd は更新 Pod イベントを apiserver に送信し、それを apiserver 経由で kubelet 監視 API サーバーに送信します。
7. kubelet はコンテナ エンジンを作成し、対話を通じて Pod とコンテナを作成し、Pod の実行ステータスとコンテナのステータスを APIserver に送信します。
8. apiserver はポッドの実行ステータスとコンテナのステータスを etcd に書き込みます。
9. etcd は確認情報を返し、apiserver を通じて kubelet に情報が書き込まれたことを伝えます。
3. K8S スケジューリングプロセス
スケジューラーは kubernetes のスケジューラーであり、その主なタスクは、定義されたポッドをクラスターのノードに割り当てることです。考慮される主な問題は次のとおりです。
●公平性: 各ノードに確実にリソースを割り当てられるようにする方法
●効率的なリソース利用: クラスター内のすべてのリソースが最大化される
●効率: スケジューリングのパフォーマンスが良好であり、多数のポッドを使用できる必要があります。可能な限り迅速にスケジュールを設定します。
● 柔軟性: ユーザーがニーズに応じてスケジュール ロジックを制御できるようにします。
Sheduler は別個のプログラムとして実行され、起動後は常に APIServer をリッスンし、spec.nodeName が空のポッドを取得し、ポッドを配置するノードを示す各ポッドのバインディングを作成します。
スケジューリングはいくつかの部分に分かれています: まず、条件を満たさないノードをフィルターで除外する (このプロセスは述語と呼ばれます)、次に通過するノードを優先度に従ってソートする (これが優先度戦略 (優先度) です)、最後に優先度を選択します。最上位ノード。中間ステップのいずれかでエラーがあった場合、エラーが直接返されます。
3.1 述語 (事前選択戦略) の一般的なアルゴリズムの使用法
●PodFitsResources: ノード上の残りのリソースがポッドによって要求されたリソースより大きいかどうか。
●PodFitsHost: ポッドで NodeName が指定されている場合、ノード名が NodeName と一致するかどうかを確認します。
●PodFitsHostPorts: ノードですでに使用されているポートがポッドによって申請されたポートと競合するかどうか。
●PodSelectorMatches: ポッドで指定されたラベルに一致しないノードをフィルターで除外します。
●NoDiskConflict: マウントされたボリュームは、両方が読み取り専用でない限り、ポッドによって指定されたボリュームと競合しません。
述語プロセス中に適切なノードがない場合、ポッドは保留状態のままになり、ノードが条件を満たすまでスケジューリングの再試行を続けます。このステップの後、条件を満たすノードが複数ある場合は、優先順位のプロセスを続行し、優先順位に従ってノードを並べ替えます。
3.2 一般的な優先オプション
優先度は一連のキーと値のペアで構成されます。キーは優先項目の名前、値はその重み (項目の重要度) です。● LeastRequestedPriority
: CPU とメモリの使用量を計算して重みが決定され、使用量が低いほど重みが高くなります。言い換えれば、この優先順位インジケーターは、リソース使用率が低いノードを優先します。
●BalancedResourceAllocation: ノード上の CPU とメモリの使用量が近いほど、重みが高くなります。これは通常、単独ではなく上記と組み合わせて使用されます。たとえば、node01 の CPU とメモリの使用量は 20:60、node02 の CPU とメモリの使用量は 50:50 です。node01 の合計使用量は、node02 よりも低いですが、node02 の CPU とメモリの使用量は近くなります。 、したがって、スケジューリング中は、node02 が優先されます。
●ImageLocalityPriority: ミラーを使用したいノードが既に存在する傾向があり、ミラーの合計サイズが大きくなるほど重みが高くなります。
このアルゴリズムは、すべての優先項目と重みを計算して、最終結果を取得します。
3.3 スケジューリングノードの指定
3.3.1 nodeName指定
●pod.spec.nodeName は、スケジューラのスケジューリング ポリシーをスキップして、指定されたノード ノードに Pod を直接スケジュールします。この一致ルールは必須の一致です。
apiVersion: v1
kind: Pod
metadata:
labels:
run: myapp-demo4
name: myapp-demo5
spec:
nodeName: node02
containers:
- image: soscscs/myapp:v1
name: myapp-demo4
ports:
- containerPort: 80
kubectl describe pod myapp-demo4
3.3.2 nodeSelector指定
●pod.spec.nodeSelector: kubernetes のラベル セレクター メカニズムを介してノードを選択します。スケジューラはラベルと一致するようにポリシーをスケジュールし、ターゲット ノードにポッドをスケジュールします。この一致ルールは必須の制約です。
//获取标签帮助
kubectl label --help
Usage:
kubectl label [--overwrite] (-f FILENAME | TYPE NAME) KEY_1=VAL_1 ... KEY_N=VAL_N [--resource-version=version] [options]
//先给node节点打上标签
kubectl label nodes node01 test=a
kubectl label nodes node02 test=b
kubectl get nodes --show-labels
//将Pod全部调度到具有 test=a 的节点
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
run: myapp-demo4
name: myapp-demo6
spec:
replicas: 5
selector:
matchLabels:
app: myapp-demo6
strategy: {
}
template:
metadata:
creationTimestamp: null
labels:
app: myapp-demo6
spec:
#nodeName: node02
nodeSelector:
test: a
containers:
- image: soscscs/myapp:v1
name: myapp-demo4
ports:
- containerPort: 80
resources: {
}
status: {
}
3.3.3 ポッド アフィニティとアンチアフィニティ
https://kubernetes.io/zh/docs/concepts/scheduling-eviction/assign-pod-node/
(1) ノードアフィニティ
pod.spec.nodeAffinity
●preferredDuringSchedulingIgnoredDuringExecution:ソフト戦略
●requiredDuringSchedulingIgnoredDuringExecution:ハード戦略
(2) ポッドアフィニティ
pod.spec.affinity.podAffinity/podAntiAffinity
●preferredDuringSchedulingIgnoredDuringExecution:ソフト戦略
●requiredDuringSchedulingIgnoredDuringExecution:ハード戦略
自分自身をポッドと考えることができます。学年の初めに学校にサインアップするときに、Zhangsan 教師が率いるクラスに通い、さまざまな教師が率いるクラスをノードとして扱いたい場合は、これを選択します。ノードアフィニティです。Zhangsan 先生のクラスに行かなければならない場合、これはハード戦略です。そして、Zhangsan 先生のクラスに行きたい、そこに行くのが最善であると言う場合、これはソフトな戦略です。
あなたに Lisi という名前のとても仲の良い友達がいて、Lisi と同じクラスになる傾向がある場合、これは Pod の親和性です。リシのクラスに行かなければならない場合、これはハード戦略です。また、行きたいがリシのクラスに行くのが最善であると言う場合、これはソフト戦略です。ソフト戦略は行かないことですが、ハード戦略は行かないことです。
キーと値の操作関係
● In: ラベルの値が特定のリストにある
● NotIn: ラベルの値が特定のリストにない
● Gt: ラベルの値が特定の値より大きい
● Lt: ラベルの値特定の値未満
● Exists: 特定の値のラベルが存在します
● DoesNotExist: ラベルが存在しません
1. ノードアフィニティハード戦略の例
apiVersion: v1
kind: Pod
metadata:
labels:
run: myapp-demo7
name: myapp-demo7
spec:
containers:
- image: soscscs/myapp:v1
name: myapp-demo7
ports:
- containerPort: 80
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: test
operator: NotIn
values:
- a
kubectl describe pod myapp-demo7
2. ノードアフィニティソフト戦略の例
apiVersion: v1
kind: Pod
metadata:
labels:
run: myapp-demo8
name: myapp-demo8
spec:
containers:
- image: soscscs/myapp:v1
name: myapp-demo7
ports:
- containerPort: 80
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: test
operator: NotIn
values:
- a
3. ハード制限とソフト制限を組み合わせて使用する
ハード戦略とソフト戦略を併用する場合、まずハード戦略を満たさなければならず、その後、ソフト戦略を満たすことができます。
apiVersion: v1
kind: Pod
metadata:
labels:
run: myapp-demo8
name: myapp-demo9
spec:
containers:
- image: soscscs/myapp:v1
name: myapp-demo7
ports:
- containerPort: 80
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: test
operator: In
values:
- a
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: class
operator: NotIn
values:
- demo1
- demo2
//修改后
apiVersion: v1
kind: Pod
metadata:
labels:
run: myapp-demo8
name: myapp-demo9
spec:
containers:
- image: soscscs/myapp:v1
name: myapp-demo7
ports:
- containerPort: 80
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: test
operator: In
values:
- b
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: class
operator: NotIn
values:
- demo1
- demo2
4. ポッド アフィニティ スケジューリングを使用して複数のポッド リソースを作成する
まず Pod を作成し、node02 ノードに指定します。
vim myapp-demo.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: myapp-demo
name: myapp-demo
spec:
nodeName: node02
containers:
- image: soscscs/myapp:v1
name: myapp-demo
ports:
- containerPort: 80
ノードのラベルを設定します。テストは同じトポロジ ドメイン内になく、クラスは同じトポロジ ドメイン内にあります。
kubectl label nodes node01 class=demo --overwrite
kubectl label nodes node02 class=demo --overwrite
デモの名前空間を作成する
kubectl create namespace demo
kubectl get ns
vim myapp-demo.yaml
vim demo9.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: myapp-demo9
name: myapp-wangwu
namespace: demo
spec:
containers:
- image: soscscs/myapp:v1
name: myapp-demo7
ports:
- containerPort: 80
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- namespaces:
- demo
topologyKey: test
labelSelector:
matchExpressions:
- key: run
operator: In
values:
- myapp-demo
すべてノードnode02上に作成されます
アフィニティロードバランシングを使用してポッドを作成する
kubectl create namespace test
//指定在node02节点上创建一个Pod并指定命名空间test
vim myapp-demo.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: myapp-demo
name: myapp-demo
namespace: test
spec:
nodeName: node02
containers:
- image: soscscs/myapp:v1
name: myapp-demo
ports:
- containerPort: 80
//根据myapp-demo.yaml创建的Pod采用亲和性实现负载均衡创建Pod
vim demo9.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: myapp-demo9
name: myapp-a
namespace: test
spec:
containers:
- image: soscscs/myapp:v1
name: myapp-demo9
ports:
- containerPort: 80
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- namespaces:
- test
topologyKey: class
labelSelector:
matchExpressions:
- key: run
operator: In
values:
- myapp-demo
ターゲット ノードで使用されるラベル run=myapp-demo に従って、ターゲット ポッドに基づいて、ノード ノードが使用するトポロジ ドメイン キーを決定し、トポロジ ドメイン キーを調べてどのノードのノード キー値を確認します。ポッド アフィニティに基づいてスケジューリング ポッドが作成される場合、ポッドはロード バランシングを使用して異なるノードに作成されます。
kubectl label nodes node01 class=ll --overwrite
kubectl label nodes node02 class=ll --overwrite
5. 反アフィニティの厳しい戦略
vim demo9.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: myapp-demo9
name: myapp-zhangsan
namespace: test
spec:
containers:
- image: soscscs/myapp:v1
name: myapp-demo9
ports:
- containerPort: 80
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- namespaces:
- test
topologyKey: test
labelSelector:
matchExpressions:
- key: run
operator: In
values:
- myapp-demo
vim demo9.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: myapp-demo9
name: myapp-d
namespace: test
spec:
containers:
- image: soscscs/myapp:v1
name: myapp-demo9
ports:
- containerPort: 80
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- namespaces:
- test
topologyKey: test
labelSelector:
matchExpressions:
- key: run
operator: In
values:
- myapp-demo
6. アンチアフィニティソフト戦略
cp demo9.yaml demo10.yaml
vim demo10.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: myapp-demo9
name: myapp-a
namespace: test
spec:
containers:
- image: soscscs/myapp:v1
name: myapp-demo9
ports:
- containerPort: 80
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
namespaces:
- test
topologyKey: class
labelSelector:
matchExpressions:
- key: run
operator: In
values:
- myapp-demo
3.3.4 汚染
Taint
ノード アフィニティは、Pod を特定のタイプのノードに引き付ける原因となる Pod の属性 (優先またはハード要件) です。一方、Taint を使用すると、ノードは特定のクラスの Pod を除外できます。
Taint と Toleration は連携して、Pod が不適切なノードに割り当てられるのを防ぎます。1 つ以上のテイントを各ノードに適用できます。つまり、これらのテイントを許容できないポッドはノードによって受け入れられません。許容が Pod に適用される場合、これらの Pod は、一致するテイントを持つノードにスケジュールできる (ただし、必ずではない) ことを意味します。
kubectl taint コマンドを使用して、Node ノードにテイントを設定します。ノードにテイントが設定されると、ポッドとの排他関係が生じます。ノード ノードは、ポッドのスケジューリングと実行を拒否し、ポッドを削除することもできます。 Node ノードの既存の汚染。ポッドは削除されました。
染色の構成形式は次のとおりです。
key=value:effect
各染色にはキーと染色のラベルとしての値があり、値は空にすることができ、effect は染色の効果を表します。
現在、テイント効果は次の 3 つのオプションをサポートしています。
● NoSchedule : k8s がこのテイントを使用してノードにポッドをスケジュールしないことを示します。
● PreferNoSchedule : k8s がこのテイントを使用してノードにポッドをスケジュールすることを回避しようとすることを示します。
● NoExecute : k8s ポッドをスケジュールすることを示します。このテイントがあるノードにはスケジュールされず、ノード上の既存のポッドは削除されます。
kubectl describe nodes | grep -i taint
//master 就是因为有 NoSchedule 污点,k8s 才不会将 Pod 调度到 master 节点上
kubectl describe nodes master
1. 染みをつける
例 1: NoSchedule を使用してノード 01 を汚染する
kubectl taint nodes node01 check=mycheck:NoSchedule
kubectl describe nodes node01
テストが汚染された後、ポッドはどのノードに作成されますか?
vim test-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: myapp-test
name: myapp-test
spec:
replicas: 5
selector:
matchLabels:
app: myapp-test
strategy: {
}
template:
metadata:
creationTimestamp: null
labels:
app: myapp-test
spec:
containers:
- image: soscscs/myapp:v1
name: myapp
ports:
- containerPort: 80
resources: {
}
status: {
}
例 2: NoExecute によるノード 01 の汚染
kubectl get pods -o wide -n test
kubectl taint nodes node01 mycheck=check:NoExecute
2. 汚れを落とす
kubectl taint nodes node01 check:NoSchedule-
kubectl describe nodes node01
kubectl taint nodes node01 mycheck-
kubectl taint nodes node01 mycheck=check:NoExecute
kubectl get pods -o wide -w
Pod のステータスを確認すると、node01 上のすべての Pod が削除されていることがわかります (注: Deployment または StatefulSet リソース タイプの場合、コピー数を維持するために、新しい Pod が他のノードに作成されます)。
3.3.5 許容範囲
汚染されたノードは、汚染の影響 (NoSchedule、PreferNoSchedule、NoExecute、および Pod) の間に相互排他的な関係を持ち、Pod はある程度までノードに対してスケジュールされません。ただし、Pod に許容値を設定することはできます。つまり、許容値を持つ Pod はテイントの存在を許容でき、テイントのあるノードにスケジュールできることになります。
示例:
kubectl taint nodes node01 mycheck=test:NoExecute
kubectl taint nodes node02 mycheck=test:NoExecute
kubectl apply -f test-deploy.yaml
kubectl get pods -owide
両方のノードにテイントが設定されると、この時点では Pod は作成されませんが、
テイントに耐えられる Pod が正常に作成されます。
示例1:
cp myapp-demo.yaml demo11.yaml
vim demo11.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: myapp-demo11
name: myapp-demo11
namespace: default
spec:
containers:
- image: soscscs/myapp:v1
name: myapp-demo11
ports:
- containerPort: 80
tolerations:
- key: mycheck
operator: Equal
value: test
effect: NoExecute
tolerationSeconds: 60
汚染を許容できるポッドをマスターノード上に作成する
示例2:
vim demo11.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: myapp-master
name: myapp-master
namespace: default
spec:
containers:
- image: soscscs/myapp:v1
name: myapp-master
ports:
- containerPort: 80
tolerations:
- key: node-role.kubernetes.io/master
operator: Exists
effect: NoSchedule
汚染を許容するためにマルチコピー Pod を作成する
示例3:
vim test-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: myapp-test
name: myapp-test
spec:
replicas: 5
selector:
matchLabels:
app: myapp-test
strategy: {
}
template:
metadata:
creationTimestamp: null
labels:
app: myapp-test
spec:
tolerations:
- key: mycheck
operator: Exists
effect: NoExecute
containers:
- image: soscscs/myapp:v1
name: myapp
ports:
- containerPort: 80
resources: {
}
status: {
}
3.3.6 その他の注意事項
(1) キー値が指定されていない場合、すべての汚染されたキーが許容されることを意味します
tolerations:
- operator: "Exists"
(2) 効果値が指定されていない場合は、すべての汚染効果を許容することを意味します。
tolerations:
- key: "key"
operator: "Exists"
(3) マスターが複数ある場合、リソースの無駄を防ぐため、次のように設定できます。
kubectl taint node Master-Name node-role.kubernetes.io/master=:PreferNoSchedule
ノードがシステム コンポーネントを更新およびアップグレードする場合、長期的なビジネスの中断を防ぐために、最初にノードに NoExecute テイントを設定して、ノード上のすべてのポッドを排除できます。
kubectl taint node node01 check=mycheck:NoExecute
このとき、他の Node リソースが足りない場合は、マスター上に一時的に PreferNoSchedule テイントを設定して、マスター上に一時的に Pod を作成できます。
kubectl taint node master node-role.kubernetes.io/master=:PreferNoSchedule
汚れを除去する前に、すべてのノード更新操作が完了するまで待ってください。
kubectl taint node node01 check=mycheck:NoExecute-
3.3.7 非常線とドレインはノード上でメンテナンス操作を実行します
ノードをスケジュール不可としてマークし、新しく作成されたポッドがこのノード上で実行できないようにします。
kubectl cordon <NODE_NAME> //该node将会变为SchedulingDisabled状态
示例:
kubectl cordon node01
kubectl get nodes
vim test-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: myapp-test
name: myapp-work
spec:
replicas: 5
selector:
matchLabels:
app: myapp-test
strategy: {
}
template:
metadata:
creationTimestamp: null
labels:
app: myapp-test
spec:
tolerations:
- key: mycheck
operator: Exists
effect: NoExecute
containers:
- image: soscscs/myapp:v1
name: myapp
ports:
- containerPort: 80
resources: {
}
status: {
}
kubectl drain
Node ノードがすべてのポッドの解放を開始し、新しいポッド プロセスを受け入れないようにすることができます。ドレインの本来の意味は水を排出することであり、問題のあるノード下のポッドを別のノード下で実行するように移動することを意味します。
kubectl drain <NODE_NAME> --ignore-daemonsets --delete-emptydir-data --force
--ignore-daemonsets
: DaemonSet によって管理される Pod を無視します。
--delete-emptydir-data
: ローカル ボリュームをマウントするポッドがある場合、ポッドは強制的に強制終了されます。
--force
:コントローラーで管理されていないPodを強制的に解放します。
kubectl drain node01 --ignore-daemonsets --delete-emptydir-data --force
注: ドレイン コマンドを実行すると、次の 2 つのことが自動的に行われます:
(1) このノードをスケジュール不可能な状態 (非常停止) に設定します
(2) ポッドを削除します (エビクト)
kubectl uncordon
ノードをスケジュール可能としてマークする
kubectl uncordon <NODE_NAME>
kubectl drain node02 --ignore-daemonsets --delete-emptydir-data --force
kubectl get nodes
kubectl uncordon node01
kubectl uncordon node02
3.4 ポッド起動フェーズ(フェーズ)
Pod が作成された後、永続的に実行されるまでの間には多くのステップがあり、エラーが発生する可能性も多いため、さまざまな状態が存在します。
一般に、ポッド プロセスには次の手順が含まれます。
(1) 特定のノードへのスケジューリング。Kubernetesは一定の優先度アルゴリズムに基づいてノードを選択し、それをノードとして使用してPodとして実行します
(2) イメージをプルします
(3) ストレージ構成などをマウントします
(4) コンテナを実行します。ヘルスチェックがある場合、そのステータスはチェックの結果に基づいて設定されます。
3.4.1 考えられる位相状態
● Pending
: APIServer が Pod リソース オブジェクトを作成し、etcd に保存されているが、スケジュールされていない (たとえば、特定のノードにスケジュールされていない) か、まだイメージのダウンロード中であることを示します。倉庫から。
● Running
: ポッドは特定のノードにスケジュールされており、ポッド内のすべてのコンテナは kubelet によって作成されています。少なくとも 1 つのコンテナーが実行中であるか、開始または再起動中です (つまり、Running 状態の Pod には正常にアクセスできない可能性があります)。
● Succeeded
: ジョブや cronjob など、一部のポッドは長時間実行されず、一定時間が経過すると、ポッド内のすべてのコンテナーが正常に終了し、再起動されません。タスクの実行結果についてのフィードバックが必要です。
● Failed
: ポッド内のすべてのコンテナが終了しており、少なくとも 1 つのコンテナが障害により終了しています。つまり、コンテナがゼロ以外のステータスで終了するか、コマンドの書き込みに問題があるなど、システムによって終了されます。
● Unknown
: 通常、kube-controller-manager が Pod と通信できないため、Pod のステータスを読み取ることができないことを示します。ポッドが配置されているノードに問題があるか、接続が失われて、ポッドのステータスが不明になります。
3.4.2 Unknown状態のPodを削除する方法
●問題のあるノードをクラスタから削除します。パブリック クラウドを使用する場合、VM が削除された後、kube-controller-manager は対応するノードを自動的に削除します。物理マシンにデプロイされたクラスターでは、管理者はノード ( kubectl delete node <node_name>
) を手動で削除する必要があります。
●ノードが正常に戻るのを受動的に待ちます。Kubelet は再度 kube-apiserver と通信してこれらの Pod の予想されるステータスを確認し、これらの Pod を削除するか実行を継続するかを決定します。
●Pod を積極的に削除し、kubectl delete pod <pod_name> --grace-period=0 --force
を実行して Pod を強制的に削除します。ただし、ポッドが実際に停止していることが明確にわかっている場合を除き、この方法は推奨されないことに注意してください (たとえば、ノードが配置されている VM または物理マシンがシャットダウンされている)。特に StatefulSet で管理されている Pod の場合、強制削除は脳の分割やデータ損失などの問題を引き起こしやすいです。
3.4.3 トラブルシューティングの手順
ポッドイベントの表示
kubectl describe TYPE NAME_PREFIX
Pod ログの表示 (失敗状態)
kubectl logs <POD_NAME> [-c Container_NAME]
Pod に入ります (ステータスは実行中ですが、サービスは提供されていません)
kubectl exec –it <POD_NAME> bash
クラスター情報の表示
kubectl get nodes
クラスターのステータスは正常であることが判明しました
kubectl cluster-info
kubelet ログを確認して確認してください
journalctl -xefu kubelet
4. まとめ
4.1 アフィニティ
ノード アフィニティ: 指定されたノード ノード ラベルを照合し、指定された条件を満たすノード ノードに Pod をスケジュールします。
ポッド アフィニティ: 指定されたポッド ラベルと一致し、指定されたポッドが配置されているノード ノードと同じトポロジ ドメイン内のノード ノードにポッドがデプロイされるようにスケジュールします。
ポッドのアンチアフィニティ: 指定されたポッド ラベルと一致し、指定されたポッドが配置されているノード ノードとは異なるトポロジ ドメイン内のノード ノードにポッドがデプロイされるようにスケジュールします。
ハード戦略: 指定された条件を満たすことが必須であり、条件を満たす Node ノードがない場合、条件を満たす Node ノードが現れるまで Pod は Pending 状態になります。
ソフト ポリシー: 必須ではありません。条件を満たすノード ノードが最初に選択され、条件を満たすノード ノードがない場合でも、ポッドはスケジューリングを完了します。
ハード ポリシーとソフト ポリシーが同時に存在する場合、ハード ポリシーを最初に満たす必要があり、その後、ハード ポリシーを満たすノード ノードの中から、ソフト ポリシーを満たすノード ノードが優先的にスケジューリングされます。
それらが同じトポロジー ドメイン内にあるかどうかを判断するにはどうすればよいでしょうか?
トポロジ ドメイン キー (topologyKey) を確認し、指定されたポッドが配置されているノード ノードと同じトポロジ ドメイン キーと値ラベルを持つ他のノード ノードがある場合、それらは同じトポロジ ドメイン内にあります。
4.2 汚染
kubectl describe nodes 节点名称 | grep Taints
kubectl taint node 节点名称 key=value:effect
3 種類の効果:
1. NoSchedule は確実にスケジュールされません
2. PreferNoSchedule はスケジュールされないよう努めます
3. NoExecute はスケジュールされず、ノード上の Pod は削除されます
汚れを取り除く:kubectl taint node 节点名称 key[:effect]-
4.3 許容差
spec:
tolerations:
- key: 键名
operator: Equal|Exists
value: 键值
effect: NoSchedule|PreferNoSchedule|NoExecute
4.4 スケジュール不可能
kubectl cordon 节点名称
kubectl uncordon 节点名称
不可调度+驱逐
kubectl drain 节点名称 --ignore-daemonsets --delete-emptydir-data --force
4.5 ポッドのライフサイクルの 5 つの状態
pending
:ポッドは作成されましたが、少なくとも 1 つのコンテナが作成されていません。これには、ポッドがノード ノードへのスケジューリング プロセスを完了していない、イメージのプル中である、ストレージ ボリュームのマウントに失敗しているなどがあります。
running
:ポッド内の少なくとも 1 つのコンテナが実行されています
succeeded
:ポッド内のすべてのコンテナは正常に終了したため、再起動されません (完了)
failed
:ポッド内のすべてのコンテナが終了し、少なくとも 1 つのコンテナが異常終了しました (エラー)
unknown
:ポッドのステータスを取得できません。通常、マスター ノードがポッドが配置されているノード ノードと通信できないことが原因です。
ポッドは、保留フェーズから開始する、事前定義されたライフ サイクルに従います。少なくとも 1 つのメイン コンテナが正常に起動すると、実行フェーズに入り、ポッド内のコンテナが失敗して終了したかどうかに応じて、成功フェーズまたは失敗フェーズに入ります。州。
4.6 トラブルシューティング方法
kubectl get pods 查看Pod状态
kubectl describe pod 查看资源的详细信息和事件
kubectl logs [-c 容器名] [--previous] 查看Pod容器的日志
kubectl exec -it [-c 容器名] 进去Pod容器查看相关状态信息
kubectl debug --target=目标Pod 临时创建Pod容器进入目标Pod进行调试
kubectl get nodes 查看Node节点状态
kubectl get cs 查看Master组件状态
kubectl cluster-info 查看集群信息
journalctl -u -f kubelet 跟踪kubelet进程日志