Kubernetes3 Advent Calendar 2019の17日目の記事となります。
qiita.com
今回はDeploymentリソースが作成されてから、実際にNode上でPodのコンテナが起動されるまでの流れをざっくり整理したいと思います。
自分の理解を深めるため、kubernetes自体のソースコード(kubernetes v1.16.4)を取り上げつつ整理します。
Deploymentが作成されてからの流れ
Deploymentリソースの登録
kubectlまたは何かしらのクライアントによって、kube-apiコンポーネントを介してDeploymentリソースを登録します。 kube-apiによって、登録されたDeploymentリソースはetcdに登録されます。
DeploymentリソースによってReplicaSetの作成
Deploymentリソースの制御を行うDeploymentコントローラーが、Deploymentリソースの作成を検知します。 Deploymentが管理するReplicaSetリソースの存在を確認し、Pod Templateのハッシュ値に一致するラベルを持つReplicaSetがない場合、Deploymentコントローラーが新規にReplicaSetリソースを作成します。
このとき、replicasの値はDeploymentリソースで指定されている値となります。
ReplicaSetによって指定した数のPodの作成
ReplicaSetコントローラーがクラスター内のReplicaSetリソースをチェックしていて、ReplicaSetリソースが管理しているPodが、replicasの値(理想状態)に一致しているかをチェックします。この理想状態に一致していない場合、Podの数をreplicasの数だけ稼働させるように、Podの作成・削除を行います。
- ReplicaSetによるレプリカPodの作成処理 https://github.com/kubernetes/kubernetes/blob/v1.16.4/pkg/controller/replicaset/replica_set.go#L466-L511
今回はPodの作成の場合のみ考えます。 ReplicaSetコントローラーによって作成されたPodリソースは、etcdに初期状態で登録されます。ここでいう初期状態とは、PodがまだどのNodeにも割り当てられておらず、起動もしていない状態を意味します。
Podの作成 この時点では pod.Spec.NodeNameが割り当てられていないままPodリソースが作成されます。 https://github.com/kubernetes/kubernetes/blob/v1.16.4///pkg/controller/controller_utils.go#L578
r.createPodsの第1引数は空文字のためNodeNameの指定なし https://github.com/kubernetes/kubernetes/blob/v1.16.4///pkg/controller/controller_utils.go#L520
kube-schedulerによるPodのNodeへの割り当て
前項で初期状態のPodが作成されましたが、このPodを稼働させるために、どのNodeで稼働させるかを決めなくてはなりません。ここでMaster上で稼働しているkube-schedulerが、その割り当ての役割を担います。
kube-schedulerは、まず割り当て対象となるNodeのフィルタリングを行います。Podのリソース要求を満たすのに十分なリソースを持つNodeを候補として洗い出します。 その後、候補となったNodeに対してスコア付を行います。スコアが高いNodeを対象とします。このスコア付の処理は、かなり複雑なのでこの記事では省略します。
Podのスケジューリング処理 https://github.com/kubernetes/kubernetes/blob/v1.16.4/pkg/scheduler/scheduler.go#L515-L676
Podの割り当て対象となるNodeの洗い出し https://github.com/kubernetes/kubernetes/blob/v1.16.4/pkg/scheduler/scheduler.go#L337-L347
kubernetesの公式ドキュメントの方にkube-schedulerの記事があり、先日こちらの日本語訳のページを行いましたので紹介します。こちらを読んでいただけるとおおまかな流れが少しでもわかるかと思います。 kubernetes.io
割り当て対象のNodeが決まると、kube-schedulerは、PodのNodeNameという値に、このNodeの名前を設定します。
注意するのは、kube-schedulerは、あくまでもPodのNodeへの割り当てを決めるのみで、実際にPodを稼働させません。
kubeletによるPodのコンテナーの起動
ここで、Podに対してNodeが割り当てられ、稼働させる準備ができました。まだ稼働していません。 各Node上で稼働しているkubeletというコンポーネントが、Pod内のコンテナーの起動処理を担います。
Podリソースのボリュームのマウント設定や、initContainersなどの設定はkubeletによって行われます。
kubeletは、etcdのリソースを確認して、自分自身のNodeに割り当てられているが、まだ稼働していないPodを探します。 もし稼働されていないPodがあったら、このPodを稼働させます。
Deploymentによって指定されたreplicasの数だけ、同様にPodを稼働させていきます。
最後に
これでDeploymentリソースが作られてからPodが稼働するまでの流れをざっくりと説明しました。 ソースコードもかなり量が多く、全部追いきれなかったため、後々詳細を読んでこちらの記事に追記していく予定です。