Open38

kube-controller-manager

ピン留めされたアイテム
bells17bells17

Index

コードリーディング用ブランチ/タグ

https://github.com/kubernetes/kubernetes/tree/v1.28.2

TODO

controller-manager

  • controller-manger

メインとなるコントローラー

アカウント/権限関連

Namespace関連

Endpoints関連

Pod関連

証明書関連

Node関連

ボリューム関連

その他

余力があったらやるコントローラー

参考資料

bells17bells17

エントリーポイント

内容について

プログラムの起動~controller群の起動まで

コマンド初期化

Run

run

デフォルトで起動されるcontroller一覧

デフォルトでdisable

  • bootstrap-signer-controller
  • token-cleaner-controller

cloud controllerが実行される設定だった場合

  • service-lb-controller
  • node-route-controller
  • cloud-node-lifecycle-controller

feature gateの設定によって起動するか否かが変わるcontroller

  • storageversion-garbage-collector-controller: APIServerIdentity(デフォルト無効)とStorageVersionAPI(デフォルト無効)が両方有効な場合
  • resourceclaim-controller: LegacyServiceAccountTokenCleanUp(デフォルト無効)が有効な場合
  • validatingadmissionpolicy-status-controller: ValidatingAdmissionPolicy(デフォルト無効)が有効な場合

デフォルト値はv1.28.2時点のもの

一部controller群起動の前に起動されるcontroller

  • serviceaccount-token-controller

その他デフォルト有効なcontroller

  • endpoints-controller
  • endpointslice-controller
  • endpointslice-mirroring-controller
  • replicationcontroller-controller
  • pod-garbage-collector-controller
  • resourcequota-controller
  • namespace-controller
  • serviceaccount-controller
  • garbage-collector-controller
  • daemonset-controller
  • job-controller
  • deployment-controller
  • replicaset-controller
  • horizontal-pod-autoscaler-controller
  • disruption-controller
  • statefulset-controller
  • cronjob-controller
  • certificatesigningrequest-signing-controller
  • certificatesigningrequest-approving-controller
  • certificatesigningrequest-cleaner-controller
  • ttl-controller
  • node-ipam-controller
  • node-lifecycle-controller
  • persistentvolume-binder-controller
  • persistentvolume-attach-detach-controller
  • persistentvolume-expander-controller
  • clusterrole-aggregation-controller
  • persistentvolumeclaim-protection-controller
  • persistentvolume-protection-controller
  • ttl-after-finished-controller
  • root-ca-certificate-publisher-controller
  • ephemeral-volume-controller
bells17bells17

serviceaccount-token-controller

内容について

serviceaccount-token-controllerは下記のような処理を行う

  • service accountに紐づくtoken(secret)の管理を行う
  • tokenに紐づくservice accountがなければtokenの削除を行い
  • service accountに紐づくtokenを必要に応じて生成して更新する

このcontrollerで更新されるリソース

  • secrets(Type が "kubernetes.io/service-account-token" のもの): tokenが更新される
  • service account: .Sercret (ObjectReference) が更新される

このcontrollerに関連するリソース

  • secrets(Type が "kubernetes.io/service-account-token" のもの)
  • service account

起動処理

startServiceAccountTokenController

serviceaccount-token-controllerは他のcontrollerより先に起動されるため startServiceAccountTokenController によって起動される

Run

syncServiceAccount

syncServiceAccountはServiceAccountsリソースを変換したデータを元に呼び出される

event handler周りの設定: https://github.com/kubernetes/kubernetes/blob/v1.28.2/pkg/controller/serviceaccount/tokens_controller.go#L89-L98

syncSecret

syncSecretはSecretsリソースを変換したデータを元に呼び出される

bells17bells17

serviceaccount-controller

内容について

serviceaccount-controllerは下記のような処理を行う

  • 作成されたNamespaceに"default" ServiceAccountを作成する
  • "default" ServiceAccountが削除された場合に再作成を行う

このcontrollerで更新されるリソース

  • ServiceAccount

このcontrollerに関連するリソース

  • ServiceAccount
  • Namespace

起動処理

startServiceAccountController

NewServiceAccountsController

ServiceAccount削除をフックするハンドラー(serviceAccountDeleted)

cache.DeletedFinalStateUnknown関連がよくわからないけど受け取ったObjectがServiceAccount相当のObjectであればQueueに対象ServiceAccountのNamespaceを追加するという処理のよう

Namespaceのハンドラー

namespaceAdded

追加されたNamespaceをQueueに加える

namespaceUpdated

更新されたNamespaceをQueueに加える

Run

runWorker ~ processNextWorkItem ~ syncHandler(syncNamespace)

syncNamespace

serviceAccountsToEnsure

c.serviceAccountsToEnsureは常に"default"のみとなる

bells17bells17

clusterrole-aggregation-controller

内容について

clusterrole-aggregation-controllerは下記のような処理を行う

名前の通りClusterRoleにはClusterRole.AggregationRuleという他のClusterRoleのRuleを自身に取り組む設定があるらしい。
具体的には ClusterRole.AggregationRule.ClusterRoleSelectors のラベルルールにマッチするClusterRoleの各種Ruleを取り込むように対象ClusterRoleRuleの更新を行う。

ClusterRole.AggregationRuleに関するドキュメントが一切見つからないんだけどなんで?

このcontrollerで更新されるリソース

  • ClusterRole

このcontrollerに関連するリソース

  • ClusterRole

起動処理

startClusterRoleAggregrationController

controllerContext.AvailableResources

AvailableResourcesはdiscovery APIから利用可能なリソース種別を取得して生成される

NewClusterRoleAggregation

enqueue(ハンドラーで呼び出されるやつ)

clusterRole.AggregationRule != nil なすべてClusterRoleがqueueに入れられる

Run

runWorker ~ processNextWorkItem ~ syncHandler

syncHandler(syncClusterRole)

ClusterRole.AggregationRule.ClusterRoleSelectorsのラベルセレクタールールにマッチするClusterRole一覧を取得して、それらのClusterRoleのRule(権限設定)を取り込んだRuleを対象ClusterRoleに設定する

applyClusterRoles

ClusterRoleのserver side applyの実行

updateClusterRoles

ClusterRoleのupdateの実行(server side apply)が有効でない場合

bells17bells17

namespace-controller

内容について

namespace-controllerは下記のような処理を行う

  • 対象Namespaceの Namespace.Spec.Finalizers が空では無く、また namespace.DeletionTimestamp が空のときに限定して処理が実行される
  • Namespaceの削除時に対象NamespaceのNamespacedなリソースのすべてを削除する(ただしDelete APIのあるものに限定)
  • 削除を試みた結果finalizerやその他の影響で削除できないリソースがあった場合はrequeueされ、再度削除が試みられる
  • 全リソース削除ができなかったリソースにPodが含まれる場合、Podのgraceful shutdownの設定に応じてrequeueの時間が調整されるよう(estimate)
  • 対象Namespaceの Namespace.Spec.Finalizersからnamespace-controllerのfinalizerを取り除く

上記のようにNamespaceに紐づくリソースが(ほぼ)完全に削除されるまで処理を繰り返すコントローラーとなっているよう

TODO
このコントローラーの外側でNamespace.Spec.Finalizersがどのように設定されるのかがわからないとこのコントローラーの全体像を理解するのが難しそう

このcontrollerで更新されるリソース

NamespaceとすべてのNamespacedリソース

このcontrollerに関連するリソース

NamespaceとすべてのNamespacedリソース

起動処理

startNamespaceController

startModifiedNamespaceControllerに渡すパラメータ調整などを行いつつstartModifiedNamespaceControllerを実行

startModifiedNamespaceController

NewNamespaceControllerでcontrollerを生成~Runで起動

NewNamespaceController

NamespaceControllerを生成してイベントハンドラーを設定
イベントハンドラーはAdd/Updateイベントに対してNamespaceをenqueueしてるだけ

Run

wait.UntilWithContext(ctx, nm.worker, time.Second)を実行してる

worker

queueがあれば、syncNamespaceFromKeyを調整ループとして実行

ResourcesRemainingErrorが発生した場合はestimate時間に応じたrequeueを行う

syncNamespaceFromKey

対象Namespaceが存在していればnm.namespacedResourcesDeleter.Deleteを実行する

namespacedResourcesDeleter.Delete

namespacedResourcesDeleterの設定

namespacedResourcesDeleter.Delete

updateNamespaceStatusFunc

deleteAllContent

deleteAllContentForGroupVersionResource
bells17bells17

resourcequota-controller

内容について

resourcequota-controllerは下記のような処理を行う

仕組みとしては複雑なんだけど、やってることとしてはResourceQuotaで設定されたQuotaの設定項目と、その対象となるリソースの使用量をResourceQuota.Statusに保存して、現在のリソース使用量を保存する、ということをやっている

これを実現するためにおおまかに言うと下記のようなことをやっている

  • 現在の各種ResourceQuotaの設定を取得
  • 各種ResourceQuotaの設定に基づき、QuotaMonitorというQuotaを監視するモニターを管理するマネージャーがMonitorと呼ばれる対象リソースを監視するcontrollerのようなものを起動(リソース別にgo routineを実行している感じ)
  • 各Monitorを通してリソースの変更が行われたものを取得して、対象リソース(+Namespace)に関連するResourceQuotaをqueueに追加
  • resourcequota-controller側の調整ループにより、ResourceQuotaで設定されたQuotaの設定項目と、その対象となるリソースの使用量をResourceQuota.Statusに保存して、現在のリソース使用量を保存する

その他ResourceQuotaを定期的に全件requeueしたりなどもしているが最終的にはこんな感じのことをやっている

TODO: これだけだとResourceQuotaのStatusを更新しているだけなので、おそらくkube-api-server側の組み込みAdmission ControllerでResourceQuotaの仕様状況によるValidationを行うものが入るのではないか?

多分このQuotaAdmissionがやってる

このcontrollerで更新されるリソース

  • ResourceQuota

このcontrollerに関連するリソース

  • ResourceQuota
  • ResourceQuotaで設定された監視対象となるリソース

起動処理

startResourceQuotaController

ResourceQuotaControllerの生成とRun/Syncの実行を行う

NewController

Run

quotaMonitor.Run

runProcessResourceChanges ~ processResourceChanges

qm.replenishmentFunc

worker

要約すると、渡されたworkqueueを使ってrq.syncHandlerを実行している

rq.syncHandler ~ syncResourceQuota

enqueueAll

Sync

resyncMonitors

StartMonitors

SyncMonitors

以下処理の流れ

QuotaMonitorのregistry

controllerFor

対象リソースのハンドラーを設定して、ハンドラー内でqm.resourceChanges というworkqueueにaddする

bells17bells17

endpoints-controller

内容について

endpoints-controllerは下記のような処理を行う

Serviceと紐づくPodに基づいてEndpointsリソースを生成する

また、ExternalName以外のServiceについてはSelectorが有る限りはEndpointsが作成されるようだった(多分)

このcontrollerで更新されるリソース

  • Endpoints

このcontrollerに関連するリソース

  • Endpoints
  • Service
  • Pod

起動処理

startEndpointController

New ~ Run実行

NewEndpointController

onServiceUpdate

queueにServiceを追加

onServiceDelete

queueにServiceを追加

addPod

Podに紐づくService一覧をqueueに追加

endpointsliceutil.GetPodServiceMemberships

Podに紐づくService一覧を取得

updatePod

Podに変更によって影響を受ける可能性のあるService一覧をqueueに追加

endpointsliceutil.GetServicesToUpdateOnPodChange

Podに変更によって影響を受ける可能性のあるService一覧を取得

deletePod

Podに紐づくService一覧をqueueに追加

endpointsliceutil.GetPodFromDeleteAction

Pod情報が取得できれば取得したものを返す

onEndpointsDelete

queueにEndpointsを追加

Run

worker ~ processNextWorkItem ~ syncService

checkLeftoverEndpoints

Endpointsに対応するサービスの削除を行うため、control planeのEndpointsを除く?Endpoints一覧をqueueに入れる

bells17bells17

endpointslice-controller

内容について

endpointslice-controllerは下記のような処理を行う

TODO 全部読んでないので間違いがあるかも

Endpointsと大体同じでExternalName以外のServiceに紐づくEndpointSliceを生成するっぽい
ただNodeのTopologyAwareHintsの利用は明確に新機能っぽい

このcontrollerで更新されるリソース

TODO 全部読んでないので他にもあるかも

  • EndpointSlice

このcontrollerに関連するリソース

  • EndpointSlice
  • Service
  • Pod
  • Node

起動処理

startEndpointSliceController

controllerの起動してるだけ

NewController

イベントハンドラーはNodeの以外はだいたいEndpointsControllerと同じような感じだったのでスキップ

addNode

updateNode

deleteNode

checkNodeTopologyDistribution

TODO reconcile読まないとわからない

Run

worker ~ processNextWorkItem ~ syncService

TODO なんやかんやあってReconcileのfinalizerでEndpointSliceを生成してるんだけど、ちょっと工程がめんどくさすぎるので後回し

bells17bells17

endpointslice-mirroring-controller

内容について

endpointslice-mirroring-controllerは下記のような処理を行う

TODO ちゃんと読んでない

このcontrollerで更新されるリソース

  • EndpointSlice

このcontrollerに関連するリソース

  • EndpointSlice
  • Endpoints
  • Service
  • Pod
  • Node

起動処理

startEndpointSliceMirroringController

controller起動してるだけ

NewController

Run

worker ~ processNextWorkItem ~ syncEndpoints

最終的にendpointslice-controllerと同じreconcilerのメソッド呼び出してEndpointSlices作ってるだけっぽいのでスキップ

bells17bells17

deployment-controller

内容について

deployment-controllerは下記のような処理を行う

Deploymentに応じたReplicaSetの作成と更新を行う。
また、ReplicaSetの状況をDeploymentのステータスなどに反映を行う。
DeploymentのRollingUpdateによる徐々に新しいPodの台数を増やす形でデプロイするといった機能もこのDeploymentコントローラーで実現している。

このcontrollerで更新されるリソース

  • Deployment
  • ReplicaSet

このcontrollerに関連するリソース

  • Deployment
  • ReplicaSet
  • Pod

起動処理

startDeploymentController

controllerを実行

NewDeploymentController

addDeployment

Deploymentをenqueue

updateDeployment

Deploymentをenqueue

deleteDeployment

Deploymentをenqueue

addReplicaSet

ReplicaSetからDeploymentを取得してenqueue

updateReplicaSet

ReplicaSetからDeploymentを取得してenqueue

deleteReplicaSet

ReplicaSetからDeploymentを取得してenqueue

deletePod

PodからReplicaSet ~ Deploymentを取得してenqueue

enqueue(enqueueDeployment)

enqueueする

Run

workerを実行

worker ~ processNextWorkItem ~ syncHandler(syncDeployment)

rolloutRolling

reconcileNewReplicaSet

NewRSNewReplicas

reconcileOldReplicaSets

rolloutRecreate

sync

Deploymentに紐づく各ReplicaSetの調整を行う

getAllReplicaSetsAndSyncRevision

必要に応じたReplicaSet/Deploymentの作成や更新を行う

getNewReplicaSet

bells17bells17

replicaset-controller

内容について

replicaset-controllerは下記のような処理を行う

ReplicaSetの状態に応じたPodの作成/削除を行う。

このcontrollerで更新されるリソース

  • ReplicaSet
  • Pod

このcontrollerに関連するリソース

  • ReplicaSet
  • Pod

起動処理

startReplicaSetController

コントローラーを起動

NewReplicaSetController

NewBaseControllerでReplicaSetControllerを生成

NewBaseController

Run

worker ~ processNextWorkItem ~ syncHandler(syncReplicaSet)

manageReplicas

bells17bells17

replicationcontroller-controller

内容について

replicationcontroller-controllerは下記のような処理を行う

TODO ReplicationManagerはReplicaSet Controllerを利用して処理を実行しているようなので、処理内容の差がよくわからない

このcontrollerで更新されるリソース

  • ReplicaSet
  • Pod

このcontrollerに関連するリソース

  • ReplicaSet
  • Pod

起動処理

bells17bells17

pod-garbage-collector-controller

内容について

pod-garbage-collector-controllerは下記のような処理を行う

一定間隔で実行されて、すでに終了してるけど何らかの理由で削除されずに残っているPodを削除する

このcontrollerで更新されるリソース

  • Pod

このcontrollerに関連するリソース

  • Pod
  • Node

起動処理

startPodGCController

controllerを起動

NewPodGC

NewPodGCInternalを実行

NewPodGCInternal

PodGCControllerを生成

Run

go wait.UntilWithContext(ctx, gcc.gc, gcc.gcCheckPeriod)を実行

gc

  • gcTerminated
  • gcTerminating
  • gcOrphaned
  • gcUnscheduledTerminating

の4つの処理を全てのpodとnodeを使って実行

gcTerminated

terminatedなステータスのPodに対して、必要ならPodステータスをfailedの設定してPodを削除する

gcTerminating

terminatedなステータスのPodに対して、実行していたnodeを取得してnodeがnot readyかout of service状態であればPodを削除する

gcOrphaned

存在しないNodeに割り当てられているPodの"DisruptionTarget" ConditionをTrueに設定してPodを削除する

gcUnscheduledTerminating

nodeにスケジュールされてないけどDeletionTimestampが設定されている削除予定Podを削除する

bells17bells17

daemonset-controller

内容について

daemonset-controllerは下記のような処理を行う

DaemonSetに応じて対象となる各Nodeに配置するPodを作成、管理する。
その際ControllerRevisionというリソースを使用して状態の管理を行いつつPodの作成などを行う。

このcontrollerで更新されるリソース

  • DaemonSet
  • ControllerRevision
  • Pod

このcontrollerに関連するリソース

  • DaemonSet
  • ControllerRevision
  • Pod
  • Node

起動処理

startDaemonSetController

controllerを起動

NewDaemonSetsController

controllerを生成

Run

runWorker & dsc.failedPodsBackoff.GCを起動

runWorker ~ processNextWorkItem ~ syncHandler(syncDaemonSet)

dsc.failedPodsBackoff.GC

DaemonSetのPodのBackOff処理に利用されるdsc.failedPodsBackoffの内、不要になったデータの削除を行う

bells17bells17

persistentvolume-binder-controller

内容について

persistentvolume-binder-controllerは下記のような処理を行う

主にPVCとPVの紐づけ処理を行う。
場合によってはPVのプロビジョニングも行う。

このcontrollerで更新されるリソース

  • PVC
  • PV

このcontrollerに関連するリソース

  • PVC
  • PV
  • StorageClass
  • Pod
  • Node

起動処理

ProbeControllerVolumePlugins

Probe用にVolumePlugin(普通にkubeletでVolumeの操作をするプラグイン)

startPersistentVolumeBinderController

volume pluginを生成してcontrollerを起動

NewController

Run

resync

volumeWorkerとclaimWorker向けのデータをenqueueする

volumeWorker

updateVolume

syncVolume

claimWorker

updateClaim

syncClaimを実行
syncUnboundClaim
syncBoundClaim

"pv.kubernetes.io/bind-completed" Annotationがある場合にはこちらが実行されるが、このAnnotationは1度はbind処理が実行されている場合に設定されるようなので、1度はsyncUnboundClaimがすでに実行されている状態となるよう。
なのでPVの作成依頼などはすでに行われており、PVのbindが完全に完了していないケースなどで呼び出されて"Bound"になったりしたかをチェックするためにある感じ?

bells17bells17

persistentvolume-attach-detach-controller

内容について

persistentvolume-attach-detach-controllerは下記のような処理を行う

PVCやPV、Podなどの状態を元にPodのスケジュール対象NodeにPVのアタッチ/デタッチを行う。
アタッチ/デタッチの具体的な処理方法はVolume Pluginの実装に依存しており、例えばCSI DriverであればVolumeAttachmentの作成/削除を行い、実際のアタッチ/デタッチはCSI Driver側で行うなどをする

参考資料
https://speakerdeck.com/bells17/introduction-to-csi?slide=36

このcontrollerで更新されるリソース

  • AttachDetachVolume
  • Node

このcontrollerに関連するリソース

  • AttachDetachVolume
  • Node
  • PVC
  • PV
  • Pod
  • CSINode
  • CSIDriver

起動処理

startAttachDetachController

controllerを起動

NewAttachDetachController

controllerを生成

Run

adc.reconciler.Run(reconciliationLoopFunc)

reconcile

  1. actual stateとdesired stateを比較して、すでに不要なvolumeのattachがあればdetachを実行する
    - detachの内容は使用されているボリューム種別に紐づくVolume Pluginに依存しており、例えばCSI DriverであればVolumeAttachmentを削除するなどを行う
    - その上でactual stateとdesired stateの更新を行う
    -
    https://github.com/kubernetes/kubernetes/blob/v1.28.2/pkg/controller/volume/attachdetach/reconciler/reconciler.go#L168-L296

  2. actual stateとdesired stateを比較して、不要になったvolumeのattachを実行する

  1. 更新内容に応じてNodeの Status.VolumesAttached の更新を行う

sync

adc.desiredStateOfWorldPopulator.Run(populatorLoopFunc)

desiredStateOfWorldPopulator内のキャッシュデータの更新を行っている感じ

最終的にはProcessPodVolumesという関数でdesiredStateOfWorldPopulatorのキャッシュに追加/削除するを判断してる

adc.pvcWorker(syncPVCByKey)

desiredStateOfWorldPopulator内のキャッシュデータの更新を行っている感じ

bells17bells17

persistentvolume-expander-controller

内容について

persistentvolume-expander-controllerは下記のような処理を行う

PVCのボリュームサイズ拡張に応じてVolume Pluginを用いて実ボリュームのリサイズを行い、その結果をPVのサイズに反映する。
なおCSI DriverについてはVolume Pluginが対応していなかったので、CSI Driverとsidecar側で勝手にやるんだと思われる。

このcontrollerで更新されるリソース

  • PV

このcontrollerに関連するリソース

  • PVC
  • PV

起動処理

startVolumeExpandController

controllerを起動

NewExpandController

Run

runWorker(syncHandler)

expand

VolumePluginを用いてボリューム拡張を行い、その結果をPVに反映する

bells17bells17

persistentvolumeclaim-protection-controller

内容について

persistentvolumeclaim-protection-controllerは下記のような処理を行う

PVCに "kubernetes.io/pvc-protection" finalizerをつけて削除保護を行い、PVC削除時にPVCに紐付けられたPVを使用しているPodがあるかどうかを持ってfinalizerのON/OFFを行いPVCの削除タイミングをコントロールする。

このcontrollerで更新されるリソース

  • PVC

このcontrollerに関連するリソース

  • PVC
  • Pod

起動処理

startPVCProtectionController

controllerを起動

NewPVCProtectionController

controllerを生成

Run

processPVCを実行

processPVC

bells17bells17

persistentvolume-protection-controller

内容について

persistentvolume-protection-controllerは下記のような処理を行う

persistentvolumeclaim-protection-controllerのPV版
PVが"Bound"ステータスか否かに応じて"kubernetes.io/pv-protection"Annotationのつけ外しを行いPVの削除保護を行う

このcontrollerで更新されるリソース

  • PV

このcontrollerに関連するリソース

  • PV

起動処理

startPVProtectionController

controllerを起動

NewPVProtectionController

controllerを生成

Run

中身はpersistentvolumeclaim-protection-controllerと大体一緒
使用中の判断をPVの場合は"Bound"ステータスかどうかで判断してる
また、finalizerのキー名は"kubernetes.io/pv-protection"

bells17bells17

ephemeral-volume-controller

内容について

ephemeral-volume-controllerは下記のような処理を行う

Podにephemeral volumeが設定されていた場合、ephemeral volume用のPVCを作成する。
ephemeral volumeはPVCにPodのowner referenceが設定されるようなので、Pod owner referenceの有無を持ってephemeralかどうかを判断してるのかも。

このcontrollerで更新されるリソース

  • PVC

このcontrollerに関連するリソース

  • Pod
  • PVC

起動処理

startEphemeralVolumeController

controllerを起動

Run

bells17bells17

node-ipam-controller

内容について

node-ipam-controllerは下記のような処理を行う

TODO 主にCloud Controller Managerから起動されるcontrollerのようなので一旦スキップ

このcontrollerで更新されるリソース

TODO

このcontrollerに関連するリソース

TODO

前提

このコントローラーはデフォルトでは起動されない

また、externalなCloud Controller Managerを利用している場合はCloud Controller Managerから起動される

起動処理

startNodeIpamController

controllerを起動

bells17bells17

node-lifecycle-controller

内容について

node-lifecycle-controllerは下記のような処理を行う

  • Nodeのコンディション状態などが正しくkubeletによって更新されているかを確認して、更新されていなかったら更新する(kubeletが停止したりしたケースを想定してる?)
  • Nodeのコンディションなどが変更された場合のPodの際スケジュールのためのPodのステータス更新や削除

といったことを行っている。
なので"NoExecute"なTaintが出た際にPodを再スケジュールさせるのはこのコントローラーのおかげのよう。

このcontrollerで更新されるリソース

  • Node
  • Pod

このcontrollerに関連するリソース

  • Node
  • Pod

前提

依然は同名のコントローラーだったものが"cloud-node-lifecycle-controller"と名前を変えたっぽい感じ?なので下記とは別物となる

https://speakerdeck.com/bells17/cloud-controller-manager-deep-dive?slide=18

起動処理

startNodeLifecycleController

controllerを起動

NewNodeLifecycleController

controllerを生成

Run

nc.taintManager.Run

channelという概念を使用しているが、複数のworkerを同時に実行管理するためのものだと思われる。
要約するとNodeとPodのイベントをハンドリングしており、ハンドリングするとNode内で実行しているPodがNode/Podの変更に伴い、対象PodのTolerationが対象Nodeの"NoExecute"なTaintの条件を満たしているのかの検証を行い、満たしていなければPodのステータスに"DisruptionTarget"コンディションを設定して、Podの削除を行う。

nc.doNodeProcessingPassWorker

nc.doNodeProcessingPassWorker は2つの処理を行う

  1. 各Nodeの現在のコンディションやSpec.Unschedulableに応じたTaintの設定を行う
  • 具体的には下記のTaintについてのつけ外しを行う
    1. "node.kubernetes.io/not-ready"
    2. "node.kubernetes.io/memory-pressure"
    3. "node.kubernetes.io/disk-pressure"
    4. "node.kubernetes.io/network-unavailable"
    5. "node.kubernetes.io/pid-pressure"
    6. "node.kubernetes.io/unschedulable"
  1. "kubernetes.io/os"と"kubernetes.io/arch"ラベルの設定を行う(それぞれ"beta.kubernetes.io/os"と"beta.kubernetes.io/arch"という古いラベルの値を新しいラベルにマイグレーションしてる)

nc.doPodProcessingWorker

nc.nodeHealthMapというNodeの状態キャッシュ内にあるNode.Status.Conditionsが全て"Ready"コンディションが"True"であるかを確認して、"Ready"じゃなかったりしたものがあればPodの"Ready"コンディションを"False"にする

nc.doNoExecuteTaintingPass

状況に応じて"node.kubernetes.io/not-ready"や"node.kubernetes.io/unreachable"TaintをNodeに設定するよう

nc.monitorNodeHealth

  • nc.nodeHealthMapというNodeの状態キャッシュの更新
  • NodeのTaintの(一部?)更新

などを行っているようだった
他のworkerでもNodeのTaintなどの制御をしてるのになんでここでもわざわざやってるのかよくわからんかった

コメントによると下記とのこと
(各コンディションはkubelet側でもチェックされるはずと思ってたのでそれは正しそうだった)

monitorNodeHealthは、ノードのヘルスがkubeletによって常に更新されていることを確認し、更新されていない場合は "NodeReady==ConditionUnknown "をポストします。

bells17bells17

ttl-controller

内容について

ttl-controllerは下記のような処理を行う

"node.alpha.kubernetes.io/ttl" AnnotationというConfigMapやSecretの更新を行うタイミングをNodeに提案するための時間情報をNodeに設定するコントローラーのよう

なぜ"node.alpha.kubernetes.io/ttl" Annotationが必要なのかは不明

このcontrollerで更新されるリソース

  • Node

このcontrollerに関連するリソース

  • Node

起動処理

startTTLController

controllerを起動

NewTTLController

controllerを生成

Run

"node.alpha.kubernetes.io/ttl" AnnotationというConfigMapやSecretの更新を行うタイミングをNodeに提案するための時間情報をNodeに設定する

bells17bells17
bells17bells17

root-ca-certificate-publisher-controller

内容について

root-ca-certificate-publisher-controllerは下記のような処理を行う

各Namespaceに"kube-root-ca.crt"というConfigMapを作成して、"ca.crt"というキー名にrootCAデータを設定するcontroller

このcontrollerで更新されるリソース

  • ConfigMap

このcontrollerに関連するリソース

  • ConfigMap

起動処理

startRootCACertPublisher

controllerを起動

NewPublisher

controllerを生成

Run

各Namespaceに"kube-root-ca.crt"というConfigMapを作成して、"ca.crt"というキー名にrootCAデータを設定する

bells17bells17

certificatesigningrequest-signing-controller

内容について

certificatesigningrequest-signing-controllerは下記のような処理を行う

CertificateSigningRequestリソースが作られたら、Status.Certificateに生成した証明書データを設定する。

このcontrollerで更新されるリソース

  • CertificateSigningRequest

このcontrollerに関連するリソース

  • CertificateSigningRequest

起動処理

startCSRSigningController

起動時オプションなどを確認して、必要に応じてcontrollerを起動

NewKubeAPIServerClientCSRSigningController

controllerを生成

NewCSRSigningController

Run

c.dynamicCertReloader.Runとc.certificateController.Runを実行

c.dynamicCertReloader.Run

ローカルの証明書ファイルとプライベートキーを監視して、変更があればそれを読み込んでCertificateSigningRequestに設定する証明書データ作成の元データを更新する。

c.certificateController.Run

CertificateSigningRequestリソースが作られたら、Status.Certificateに生成した証明書データを設定する。

bells17bells17

certificatesigningrequest-approving-controller

内容について

certificatesigningrequest-approving-controllerは下記のような処理を行う
CertificateSigningRequestをチェックして、問題なければSubjectAccessReviewsを作成してCertificateSigningRequestのStatusに成功結果のコンディションを設定するcontroller

approve/denied自体はkubectlで下記のように行う

$ kubectl certificate (approve|denied) <certificate-signing-request-name>

https://kubernetes.io/docs/tasks/tls/managing-tls-in-a-cluster/

https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/

このcontrollerで更新されるリソース

  • CertificateSigningRequest
  • SubjectAccessReviews

このcontrollerに関連するリソース

  • CertificateSigningRequest
  • SubjectAccessReviews

起動処理

startCSRApprovingController

controllerを起動

NewCSRApprovingController

controllerを生成
ベースとなるcontrollerはcertificatesigningrequest-signing-controllerと同じ

handle

handleを呼ぶ部分まではcertificatesigningrequest-signing-controllerと同じなのでスキップ
CertificateSigningRequestをチェックして、問題なければSubjectAccessReviewsを作成してCertificateSigningRequestのStatusに成功結果のコンディションを設定

bells17bells17

certificatesigningrequest-cleaner-controller

内容について

certificatesigningrequest-cleaner-controllerは下記のような処理を行う

下記のCertificateSigningRequestを削除するcontroller

  • 承認済み or 拒否済み or 証明書の発行に失敗した or 承認も拒否もされなかったもので古くなったもの
  • 承認済みだけど証明書が失効したもの

このcontrollerで更新されるリソース

  • CertificateSigningRequest

このcontrollerに関連するリソース

  • CertificateSigningRequest

起動処理

startCSRCleanerController

controllerを起動

NewCSRCleanerController

controllerを生成

Run

下記のCertificateSigningRequestを削除する

bells17bells17

storageversion-garbage-collector-controller

内容について

storageversion-garbage-collector-controllerは下記のような処理を行う

controller名にgarbage collectorと入っているが

  • 各StorageVersionsリソースのStatus.StorageVersionsから自身のものがあれば除外する。
  • 各StorageVersionsリソースのStatus.StorageVersionsから無効なものがあれば除外する。
  • Status.StorageVersionsが存在しなければ、そのStorageVersionsは削除する。

といった処理を行うようなので、どちらかというと異常値なデータを除去するといった感じの処理を行うcontrollerな印象

TODO そもそもStorageVersionsリソースがどのように作られるのか?そもそもStorageVersionsリソースとは何かということを知らないとわからない部分がある

このcontrollerで更新されるリソース

  • StorageVersion

このcontrollerに関連するリソース

  • StorageVersion

起動処理

startStorageVersionGCController

controllerを起動

NewStorageVersionGC

Run

runLeaseWorker

各StorageVersionsリソースのStatus.StorageVersionsから自身のものがあれば除外する。
その結果Status.StorageVersionsが存在しなければ、そのStorageVersionsは削除する。

TODO そもそもStatus.StorageVersionsはどこで設定されるのかがわからない

runStorageVersionWorker

各StorageVersionsリソースのStatus.StorageVersionsから無効なものがあれば除外する。
ここでいう無効なものというのは、各Status.StorageVersionsのAPIServerIDに一致するLeaseリソースを取得して、そのLeaseリソースの"apiserver.kubernetes.io/identity"ラベルの値が"kube-apiserver"ではなかったものを無効とみなすよう。

TODO StorageVersionsはkube-apiserverのみによって作成されるから、それ以外は無効ということ?

bells17bells17

resourceclaim-controller

内容について

resourceclaim-controllerは下記のような処理を行う

ResourceClaimsに関するKEP

要はCPUとメモリ(+Storageも?)以外の専用ハードウェアなど様々なリソースに対するコントローラーを行うための共通インターフェイスとしてのリソースという感じかな?

https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/3063-dynamic-resource-allocation

図があった

ざっくりこんな感じ?

  • ResourceClaimsは紐づくdriverによって管理するリソースの要求・管理を行うリソース
  • ResourceClaims.Status.ReservedFor は複数Podを紐付けられるので、driverの設定次第でこのリソースを複数Podでシェアすることが可能
  • PodSchedulingContextsは(ResourceClaimsを使用する)Podが使用するNodeを紐付ける(なんでPodのnodeNameじゃない?)
  • PodからResourceClaimsが作られて、driverによってResourceClaimsの実体が設定されて、schedulerでNodeが設定されたらPodSchedulingContextsが作られて、ResourceClaims.Status.ReservedForによってPodと紐付けられて、ResourceClaimsを要求するPodが無くなったらResourceClaimsを削除する、みたいな感じ?

おおまかにいうと初めっからCSI Driver方式で実装されたvolume pluginみたいなもんかな?
これ以上詳細についてはscheduler pluginとdriverのインターフェイスや実装例をみないとなんとも言えない感じかな

このcontrollerで更新されるリソース

  • ResourceClaims
  • PodSchedulingContexts

このcontrollerに関連するリソース

  • ResourceClaims
  • PodSchedulingContexts

起動処理

startResourceClaimController

NewController

Run

データに合わせてsyncPodかsyncClaimを実行する

syncPod

主にPodのSpec.ResourceClaimsからResourceClaimを作成したり、PodSchedulingContextsを設定したりといった感じ

syncClaim

主に不要になったResourceClaimを削除したりといった感じ

bells17bells17

validatingadmissionpolicy-status-controller

内容について

validatingadmissionpolicy-status-controllerは下記のような処理を行う

validatingadmissionはPolicyが下記のCommon Expression Language(CEL)でルールを記述することが可能になった。

https://github.com/google/cel-go

このcontrollerでは、このCELの文法が正しいかをチェックするcontrollerとなっている。
バリデーションエラーになったポリシーをValidatingAdmissionPolicyのStatus.TypeChecking.ExpressionWarningsに設定するという処理を行う。

このcontrollerで更新されるリソース

  • ValidatingAdmissionPolicy

このcontrollerに関連するリソース

  • ValidatingAdmissionPolicy

起動処理

startValidatingAdmissionPolicyStatusController

NewController

Run

bells17bells17

horizontal-pod-autoscaler-controller

内容について

horizontal-pod-autoscaler-controllerは下記のような処理を行う

HPAの設定に基づいて /scale サブリソースを提供しているリソースのスケールを行う。
replica数の調整方法も/scale サブリソースのエンドポイントを使用しているので、自動で色々計算して kubectl scaleを実行してる感じ。

https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#scale-subresource

replica数の計算方法はHPAの Spec.Metricsに設定したメトリクスデータを元に行う。

このcontrollerで更新されるリソース

このcontrollerに関連するリソース

起動処理

startHPAController

startHPAControllerWithRESTClient

startHPAControllerWithMetricsClient

NewHorizontalController

Run

reconcileAutoscalerを実行する

reconcileAutoscaler

bells17bells17

job-controller

内容について

job-controllerは下記のような処理を行う

Jobリソースに基づいてPodを作成して、実行管理を行う

このcontrollerで更新されるリソース

  • Job
  • Pod

このcontrollerに関連するリソース

  • Job
  • Pod

起動処理

startJobController

NewController

newControllerWithClock

Run

jm.worker

なんやかんやでJobリソースからPodを作成して実行管理する
TODO 長すぎるので詳細は省略

jm.orphanWorker

"batch.kubernetes.io/job-tracking" finalizerを持つPodの内、Jobとのowner referenceが正しく設定されていないPodから"batch.kubernetes.io/job-tracking" finalizerを取り除く

bells17bells17

disruption-controller

内容について

disruption-controllerは下記のような処理を行う

PodDisruptionBudget(PDB)に紐づくPodの内

  • ReplicationController
  • Deployment
  • ReplicaSet
  • StatefulSet
  • その他 /scale サブリソースを持つリソース

上記のいずれかによって管理されているPodの件数とPDBの設定を比較して、起動する必要のあるPod情報などを計算してPDBのステータスに保存するcontroller
その際、上記によって管理されていないPodについては除外して計算される

TODO 周辺の"DisruptionTarget"コンディションの扱いについて知らないと適切な理解ができなさそう

このcontrollerで更新されるリソース

  • PodDisruptionBudget
  • Pod

このcontrollerに関連するリソース

  • PodDisruptionBudget
  • Pod

起動処理

startDisruptionController

NewDisruptionController

NewDisruptionControllerInternal

Run

worker

PodDisruptionBudget(PDB)に紐づくPodの内

  • ReplicationController
  • Deployment
  • ReplicaSet
  • StatefulSet
  • その他 /scale サブリソースを持つリソース

上記のいずれかによって管理されているPodの件数とPDBの設定を比較して、起動する必要のあるPod情報などを計算してPDBのステータスに保存する
その際、上記によって管理されていないPodについては除外して計算される

recheckWorker

worker用のqueueをenqueueするだけ

stalePodDisruptionWorker

"DisruptionTarget"コンディションが"True"に設定されたPodの内、一定時間以上を経過したPodの"DisruptionTarget"コンディションを"False"に設定する、という感じ?
つまりPDBを待たずに終了する対象にする的な感じ?

bells17bells17

cronjob-controller

内容について

cronjob-controllerは下記のような処理を行う

CronJobリソース設定に基づくJobリソースの作成とcron式から次回の実行時間を計算してenqueするcontroller
なのでcron式に対応した定期処理の実行はworkqueueのenqueueによって実現されていたことになる

このcontrollerで更新されるリソース

  • CronJob
  • Job

このcontrollerに関連するリソース

  • CronJob
  • Job

起動処理

startCronJobController

NewControllerV2

Run

bells17bells17

garbage-collector-controller

内容について

garbage-collector-controllerは下記のような処理を行う

TODO ぶっちゃけよくわからん

https://kubernetes.io/docs/concepts/architecture/garbage-collection/

このcontrollerで更新されるリソース

  • "delete", "list", "watch" 全てのAPIを持つリソース全部?

このcontrollerに関連するリソース

  • "delete", "list", "watch" 全てのAPIを持つリソース全部?

前提

デフォルトでは起動しなさそう

起動処理

startGarbageCollectorController

NewGarbageCollector

Run

gc.dependencyGraphBuilder.Run

runProcessGraphChanges ~ processGraphChanges

これぶっちゃけよくわからんかった

gc.runAttemptToDeleteWorker ~ processAttemptToDeleteWorker

これぶっちゃけよくわからんかった

gc.runAttemptToOrphanWorker ~ processAttemptToOrphanWorker

自信ないんだけど、やってることとしてはownerのdependenciesからownerのowner referenceを取り除くということをやってるっぽい
このownerもdependenciesにも"node"というstructが使われてるんだけど、もしかしてこれってNodeリソースのことでは無くて単純なリソースの親子関係を示すものでしかない感じ?

Sync

"delete", "list", "watch" 全てのAPIを持つリソースを削除可能対象のリソースとしてmonitorによる監視を開始する

bells17bells17

statefulset-controller

内容について

statefulset-controllerは下記のような処理を行う

StatefulSetリソースの設定に基づくPodやPVCを作成~管理する。

このcontrollerで更新されるリソース

  • StatefulSet
  • ControllerRevisions
  • PVC
  • Pod

このcontrollerに関連するリソース

  • StatefulSet
  • ControllerRevisions
  • PVC
  • Pod

起動処理

startStatefulSetController

NewStatefulSetController

Run