Cloud Controller Manager Deep Dive

3499a1d71fa70b8ee44816ca9e7329fe?s=47 bells17
September 09, 2020

Cloud Controller Manager Deep Dive

Cloud Native Days Tokyo 2020(#CMDT2020)で発表したCloud Controller Managerに関するセッションです

https://event.cloudnativedays.jp/cndt2020/talks/32

3499a1d71fa70b8ee44816ca9e7329fe?s=128

bells17

September 09, 2020
Tweet

Transcript

  1. Cloud Controller Manager Deep Dive Cloud Native Days 2020(2020/09/09) @bells17

  2. ▶ Daiki Hayakawa / @bells17 ▶ Software Engineer ▶ 主に

    Kubernetes 関連コンポーネントの開発など ▶ Kubernetes #sig-docs-ja-reviews ▶ CNBF実⾏委員 ▶ @bells17_
  3. 今⽇話すこと ▶ Cloud Controller Managerの概要 ▶ Cloud Controller Managerの導⼊背景 ▶

    Cloud Controller Managerの実装と動作するコントローラーについて ▶ Cloud Providerの概要と実装⽅法について
  4. 注意点 ▶ 内容としてはCloud Controller ManagerのDeep Diveセッションを想定 してます + なのでKubernetesそのものの説明は、ある程度知っている前提で
 話すと思います

    ▶ コードべースはv1.17です(release-1.17タグ) + ちょっと古いけど最新版もそんなにロジック変わらないはず(たぶん)
  5. アジェンダ 1. Cloud Controller Managerとは? 2. Kubernetes アーキテクチャのおさらい 3. Cloud

    Controller ManagerのDesign Proposal 4. Cloud Controller Managerの実装の概要 5. Kubernetes Componentの実装 6. Cloud Controller Managerが起動するコントローラー群 7. Cloud Provider 8. まとめ
  6. Cloud Controller Managerとは?

  7. Cloud Controller Manager ▶ Kube Controller ManagerなどKubernetesのコアコンポーネントから
 クラウドプラットフォームに関するロジックを分離させたコンポーネント + クラウドプラットフォーム:

    AWSとかOpenStackみたいなk8sを動作
 させてるIaaS環境というイメージが近い ▶ 追加されたk8sノードの初期化処理や、Serviceのtype: LoadBalancerに対 応したL4ロードバランサーの構築をしたりといった、k8sが利⽤している
 クラウド環境との連携を⾏うことができる ▶ 対応するクラウド環境と連携させるためのCloud Provider実装を組み込ん でビルドする必要がある + 公式やクラウドプラットフォームがサポートしているCloud Provider実 装があれば⾃前での実装は不要
  8. Kubernetesアーキテクチャのおさらい

  9. https://github.com/kubernetes/website/blob/fb6364da0afd19e8a9515aaae2de9bc74a0a6abd/static/images/docs/components-of-kubernetes.png

  10. None
  11. Cloud Controller Managerの
 Design Proposal

  12. https://github.com/kubernetes/enhancements/blob/435a1c5c1468f363ecb6437d4a160551ee7a9d3c/keps/0001-kubernetes-enhancement-proposal-process.md

  13. Design Proposalの要約(動機) ▶ 当時各Cloud Providerの実装のアップデートがKubernetesのライフサイ クルに依存しているという問題があった + Kubernetesのリリースサイクルは3ヶ⽉に1度 ▶ そのためCloud

    Provider実装をKubernetesのコアから外部に移⾏したい + Cloud Provider⾃⾝がリリースサイクルを管理できるようになる
  14. Design Proposalの要約(変更内容) ▶ 当時はKubernetesの複数のコンポーネントがCloud Providerの実装に
 依存していた ▶ 依存コンポーネントは + kube-controller-manager

    + kubelet + kube-apiserver ▶ これらのリファクタリングを⾏いつつ、Cloud Provider実装に依存する 箇所をCloud Controller Managerに処理を切り出す
  15. 結果的に変化したこと ▶ 外部化することで、Kubernetes公式のサポート外環境でもクラウドと の連携が可能になった + Kubernetesが提供するインターフェイスに沿った実装を組み込め ば、任意のクラウド環境向けのCloud Controller Managerが実装可能 になったため

    ▶ 各種コンポーネントのバイナリに含まれていたCloud Provider向けの 実装が削減されたため、その分バイナリサイズが⼩さくなった
  16. https://kubernetes.slack.com/archives/C718BPBQ8/p1566870958006200 実際に約70MBほどサイズが減ったらしい

  17. Cloud Controller Managerの実装の概要

  18. None
  19. アーキテクチャ ▶ 4種類のコントローラー起動 + Node + Node Lifecycle + Service

    + Route ▶ 各コントローラーはそれぞれでイベントハンドリングを⾏い、必要に 応じて組み込んだCloud Providerのメソッドを呼び出す ▶ クラウドプラットフォームとの直接のやり取りはすべてCloud Provider を経由して⾏う ▶ Cloud Providerはインターフェイスが定義されていて、独⾃実装する場 合はインターフェイスを満たしたものを実装する
  20. Kubernetes Componentの実装

  21. None
  22. 基本パターン ▶ Managerプロセス全体の中で1つ、または複数のコントローラーが実⾏ される ▶ コントローラーは1つにつき、1種類のKubernetesリソースのみに対す る調整ループ(Reconciliation Loop)が実⾏される + 調整ループ:

    リソースのあるべき状態(Desired State)と実際の状態 (Actual State)を⽐較~あるべき状態になるように調整処理を⾏うもの + なので、2種類のリソースに対しては、最低2コントローラー以上が
 あるのが基本
  23. 調整ループ ▶ 主に以下の2種類の⽅法で実⾏される + Event Handlers: 監視対象のKubernetes Resourceの更新といった、 なんらかのイベントを元に実⾏される +

    無限ループによる定期実⾏: 設定値に基づいて数秒毎などの間隔で定 期実⾏が⾏われる
  24. https://github.com/kubernetes/sample-controller/blob/master/docs/images/client-go-controller-interaction.jpeg

  25. None
  26. None
  27. ▶ Kubernetesのコードリーディングをする上で知っておくと良さそうなこと こういったKubernetes Componentの実装周りについてはコード リーディングについての記事の中で書いたので良ければ⾒てください

  28. Cloud Controller Managerが起動する コントローラー群

  29. ServiceController(1) ▶ Serviceのtype: LoadBalancerの設定に基づきクラウド環境のL4ロード バランサーの構築・設定を⾏うコントローラー ▶ 以下の2種類のメソッドによりL4ロードバランサーのDesired Stateを実 現する +

    worker: Kubernetes Component実装の基本パターンのEvent Handlersパターンによるイベント駆動 + Serviceリソースのイベントをハンドリングして調整ループを実⾏ + LBの作成/更新/削除処理を⾏う + nodeSyncLoop: 100秒毎に実⾏され、各Service type: LoadBalancer に対応する、クラウド側のロードバランサーに紐付けるノード⼀覧の
 更新処理を⾏う
  30. ServiceController(2) ▶ LBに紐付けが⾏われるノードは以下の条件にマッチするもの + Ready状態のノードであること + unschedulableではないノードであること + kubectl cordon

    コマンドを使うとunschedulableとなり、Podがスケ ジュールされなくなる + "LegacyNodeRoleBehavior" feature gateがONの場合 + 以下のラベルが無いノードであること + "node-role.kubernetes.io/master" + "ServiceNodeExclusion" feature gateがONの場合 + 以下のラベルが無いノードであること + “node.kubernetes.io/exclude-from-external-load-balancers" + "alpha.service-controller.kubernetes.io/exclude-balancer"
  31. ServiceController(3) ▶ 個⼈的に気になっている点 + LBの作成/削除を⾏うのは基本的にworker側の調整ループで⾏う想定と なっている + nodeSyncLoopではCloud ProviderのLB設定をアップデートするメソッ ド(UpdateLoadBalancer)を呼び出すのみ

    + そのため、クラウド側で該当のLBの削除などを⾏っても、該当LBに紐づ くServiceリソースの変更イベントが無い限りはLBが⾃動で再構築され るといったことは⾏われない + Cloud Provider側のUpdateLoadBalancerでLBの有無を確認し、無けれ ば再⽣成する処理を⾏えば対応可能ではあるが、そういった実装になっ ているCloud Providerは把握している範囲では存在しない
  32. NodeController(1) ▶ k8sの各ノードの初期化処理を⾏うコントローラー ▶ NodeリソースのCreate/Updateイベントをハンドリングして調整ループ を実⾏ ▶ `node.cloudprovider.kubernetes.io/uninitialized`というtaintが
 付与されているノードを初期化処理が⾏われていないノードとみなして 実⾏対象にする

    ▶ `node.cloudprovider.kubernetes.io/uninitialized` taintはkubeletを `--cloud-provider=external`フラグ付きで起動すると付与される
  33. NodeController(2) ▶ 以下の処理を⾏う + NodeオブジェクトにIPアドレス情報を設定 + NodeオブジェクトのラベルにNodeが動いているマシン情報
 (e.g. インスタンスタイプ)やゾーン、リージョン情報の設定 ▶

    上記が完了すると`node.cloudprovider.kubernetes.io/uninitialized` taintの除去を⾏う
  34. NodeLifeCycleController ▶ k8sの各ノードの状態チェックを⾏うコントローラー ▶ 設定値のNodeMonitorPeriod秒毎に調整ループを⾏う ▶ 処理としては全ノードに対して以下のようなことを⾏う + ノードのステータスが”Ready”かチェックを⾏う +

    “Ready”ではない場合、ノードがシャットダウンしているかチェック を⾏い、シャットダウン状態であれば `node.cloudprovider.kubernetes.io/shutdown` taintを付与する + シャットダウン状態のノードのステータスが”Ready”に復帰すれば taintを除去する + “Ready”でもないし、シャットダウン状態でもないのであれば、イン スタンスが存在するのかのチェックを⾏い、存在しなければノードの 削除を⾏う
  35. RouteController ▶ k8sの各ノードのPodCIDRの経路情報の設定を⾏うコントローラー ▶ 設定値のRouteReconciliationPeriod秒毎に調整ループを⾏う ▶ 前提としてClusterCIDRが未設定のクラスターのとき動作するように なってるっぽい ▶ 処理としては以下のようなことを⾏っているっぽい

    + VPCなどの経路設定情報を取得 + 各ノードのPodCIDRの経路設定が⾏われているか確認を⾏い、まだ
 ⾏われていなければ経路情報の設定を⾏う + すでに使われていない古い経路情報が残っていれば、それらの削除を ⾏う + もし経路設定に失敗しているノードがあれば、該当ノードのネット ワークコンディションを失敗状態にする
  36. ▶ KubernetesのCloud Controller Managerについて ▶ KubernetesのServiceControllerの実装 Cloud Controller Managerのコントローラーに関する記事は 以下の記事でも書いたので興味があればチェックしてみてください

  37. Cloud Provider

  38. Cloud Provider ▶ Cloud Controller Managerに組み込んで実⾏される ▶ Goで定義されたインターフェイスのメソッドを実装して組み込むこと で、独⾃のCloud Provider実装をCloud

    Controller Managerから利⽤す ることができる ▶ Goのインターフェイスであるcloudprovider.Intrefaceは https:// github.com/kubernetes/cloud-provider/blob/release-1.17/cloud.go に ある
  39. None
  40. 独⾃のCloud Providerを実装する ▶ 独⾃のCloud Providerを実装する場合に⾏うのは以下のようにする + cloudprovider.Intrefaceを満たすCloud Providerを実装 + “k8s.io/kubernetes/cmd/cloud-controller-manager/

    app”.NewCloudControllerManagerCommand().Execute()を実⾏する コマンドを作成する + 上記コマンドでメイン処理実⾏前に予め以下を⾏うようにする + ⾃作したCloud Providerの登録処理 + 実⾏するCloud Providerの指定 ▶ PodとしてCloud Controller Managerを実⾏する際には適切なRBACや tolerationsなどの設定を⾏う必要あり
  41. 注意点 ▶ Cloud Controller ManagerはCSIなどのように、どの機能を実装すると こう動作する、といった仕様が明確ではない ▶ そのため、Cloud Controller Managerの実装を直接読む、他のCloud

    Provider実装を参考に実装するといった対応が必要になってくる
  42. Digitaloceanのコマンド例(コメントを削ったものです)

  43. Cloud Providerの登録処理はinit()を使って⾃動で⾏うことが多い

  44. メソッドの実装はこんな感じに⾃分たちに必要なものだけ⾏う

  45. まとめ

  46. まとめ ▶ Cloud Controller Managerの動作とその実装について紹介しました ▶ Kubernetesの裏側で動作するコンポーネントがどんなふうに動作しているのかの理解を深 めるきっかけになればと思います ▶ 実際にCloud

    Providerを組み込んだCloud Controller Managerを⾃作してみると Kubernetesに対する理解が深まって⾯⽩いかなと思います
  47. 参考資料 ▶ Kubernetes Components https://kubernetes.io/docs/concepts/overview/components/ ▶ Cloud Controller Manager https://kubernetes.io/docs/concepts/architecture/cloud-controller/

    ▶ Developing Cloud Controller Manager https://kubernetes.io/docs/tasks/administer-cluster/developing-cloud-controller-manager/ ▶ Controllers https://kubernetes.io/docs/concepts/architecture/controller/ ▶ Nodes https://kubernetes.io/docs/concepts/architecture/nodes/ ▶ client-go under the hood https://github.com/kubernetes/sample-controller/blob/master/docs/controller-client-go.md ▶ Kubernetes Source Code: https://github.com/kubernetes/kubernetes/blob/release-1.17 ▶ Cloudprovider.Interface https://github.com/kubernetes/cloud-provider/blob/release-1.17/cloud.go ▶ Refactor Cloud Provider out of Kubernetes Core https://github.com/kubernetes/community/blob/1922998843eb61d13eb41d6303e36e5e206a1cee/ contributors/design-proposals/cloud-provider/cloud-provider-refactoring.md ▶ Kubernetes Enhancement Proposal Process https://github.com/kubernetes/enhancements/blob/435a1c5c1468f363ecb6437d4a160551ee7a9d3c/keps/ 0001-kubernetes-enhancement-proposal-process.md ▶ KEP Template https://github.com/kubernetes/enhancements/tree/435a1c5c1468f363ecb6437d4a160551ee7a9d3c/keps/NNNN-kep-template ▶ digitalocean-cloud-controller-manager: https://github.com/digitalocean/digitalocean-cloud-controller-manager ▶ Kubernetesのコードリーディングをする上で知っておくと良さそうなこと https://bit.ly/2BY8FzM ▶ KubernetesのCloud Controller Managerについて https://bit.ly/2DW1oBP ▶ KubernetesのServiceControllerの実装 http://bit.ly/2SCjm0C
  48. Thanks / Question? ▶ Daiki Hayakawa, @bells17 ▶ Slide: https://speakerdeck.com/bells17

    ▶ Blog: https://medium.com/@bells17 ▶ @bells17_