July Tech Festa 2021 winter https://youtu.be/HNtRBkP4LZ8 で発表を行った資料になります。 Kubernnetesの中で各Worker Nodeでのコンテナ管理を行うKubeletがどんなふうに動作しているのかについてお話しています。
Kubeletから読み解くKubernetesのコンテナ管理の裏側July Tech Festa(2021/01/24)@bells17
View Slide
▶ @bells17▶ Software Engineer▶ IDC Frontier inc.▶ 普段やってること:+ Kubernetes 関連コンポーネントの開発+ Kubernetes as a Service開発の調査・研究▶ Kubernetes SIG-Docs Japanese localization reviewer▶ Kubernetes Internal Organizer▶ #kubenews▶ @bells17_
今⽇話すこと▶ Kubernetesの概要▶ Kubernetes Core Componentについて▶ Kubeletの動作について▶ dockershimの動作とCRIについて
注意点▶ Kubernetes v1.19ベースでのお話になります▶ あくまでKubeletの実装を追った結果での理解の説明になるので、ところどころ間違いが含まれている可能性があります
Kubelet本体についてのより詳しい詳細はこの本に書いてます▶ 技術書典: http://bit.ly/tbf-kubelet▶ Booth: http://bit.ly/booth-kubeletKubeletの詳細が気になる⽅は良ければ買ってください!またKubernetes Internal #4ではKubeletの実装が、コードレベルでどうなっているかについて説明してます https://youtu.be/gWS38gSiDZ0
アジェンダ1. そもそもKubernetesとは?2. Kubernetesコントローラー3. Kubernetes Core Component4. Kubeletとは?5. dockershimについて6. CRIについて7. Kubeletのメイン処理8. その他のアプリケーション9. 実際にPodからコンテナが作られる様⼦を(ふわっと)⾒てみよう10. まとめ
そもそもKubernetesとは?
Kubernetes とは?▶ Kubernetesはコンテナオーケストレーターの1つ▶ etcd/control plane/worker nodeによって構成されたクラスターを構築し、様々なコンテナをKubernetes上のnodeで動作させたり、動作させてるコンテナとネットワークをいい感じに連携できるようにすることができる▶ デプロイするコンテナなどをmanifestファイルで宣⾔的に記述することで、宣⾔した状態になるようにKubernetesがいい感じに調整処理を⾏ってくれる▶ Googleが内部で運⽤していたコンテナ基盤であるBorgをOSS向けに作り直したコンテナオーケストレーター▶ また、KubernetesはCloud Native Computing Foundation(CNCF)に寄贈されており、CNCFのGraduatedプロジェクトとしてコミュニティベースで管理されている
manifestをKubernetesに適⽤することで宣⾔されたmanifestの通りにコンテナが作成される
Kubernetesコントローラー
https://github.com/kubernetes/website/blob/fb6364da0afd19e8a9515aaae2de9bc74a0a6abd/static/images/docs/components-of-kubernetes.png
基本パターン▶ Managerプロセス全体の中で1つ、または複数のコントローラーが実⾏される▶ コントローラーは1つにつき、1種類のKubernetesリソースのみに対する調整ループ(Reconciliation Loop)が実⾏される+ 調整ループ: リソースのあるべき状態(Desired State)と実際の状態(Actual State)を⽐較~あるべき状態になるように調整処理を⾏うもの+ なので、2種類のリソースに対しては、最低2コントローラー以上があるのが基本
調整ループ▶ 主に以下の2種類の⽅法で実⾏される+ Event Handlers: 監視対象のKubernetes Resourceの更新といった、なんらかのイベントを元に実⾏される+ 無限ループによる定期実⾏: 設定値に基づいて数秒毎などの間隔で定期実⾏が⾏われる
https://github.com/kubernetes/sample-controller/blob/master/docs/images/client-go-controller-interaction.jpeg
▶ Kubernetesのコードリーディングをする上で知っておくと良さそうなことこういったKubernetesコントローラー実装周りについてはコードリーディングについての記事の中で書いたので良ければ⾒てください
Kubernetes Core Component
Core Component▶ etcd: API Serverのバックエンドで使⽤されている分散型のKVS▶ Control Plane▶ API Server: KubernetesのAPIリクエストを処理するサーバー▶ Kube Controller Manager: Kubernetesの様々なリソースのためのロジックを動かす様々なコントローラーを動作させるマネージャー▶ Cloud Controller Manager: Kubernetesとクラウド(実⾏基盤)を連携するためのコントローラーを動作させるマネージャー▶ Scheduler: PodをどのWorker Nodeに配置するかを決める▶ Worker Node▶ Kubelet: Worker Nodeで実⾏するコンテナを管理するアプリケーション▶ Kube Proxy: Serviceリソースに基づくネットワーク設定を⾏うアプリケーション
▶ Cloud Controller Manager Deep DiveCloud Controller Managerについては以下のスライドでまとめてあるので参考にしてください
Kubeletとは?
Kubeletとは?▶ コンテナランタイムと連携しWorker Nodeで動かすコンテナとその関連リソースを管理する▶ Static PodをMirror PodとしてAPI Serverに登録する▶ Kubeletを動かしているサーバーをKubernetesクラスターのWorker Nodeとして登録する▶ Healthcheckや各種メトリクス情報などを公開するServerを起動▶ コンテナへのPortForward/ContainerLog/Execなどのエンドポイントもある▶ dockershimを使う場合はdockershimサーバーの起動もKubeletの機能の(あくまで)概要としてはこのくらい
Kubeletのアーキテクチャ▶ KubeletはGo⾔語のgoroutineとチャネルによる⾮同期処理によるアーキテクチャとなっている▶ goroutineとチャネルを使⽤して、Kubelet内部で数⼗のアプリケーションが並⾏で動作しており、チャネルを通したイベントの送受信を通した、イベント駆動モデルで処理が⾏われていく
Kubeletとは?▶ コンテナランタイムと連携しWorker Nodeで動かすコンテナとその関連リソースを管理する▶ Static PodをMirror PodとしてAPI Serverに登録する▶ Kubeletを動かしているサーバーをKubernetesクラスターのWorker Nodeとして登録する▶ Healthcheckや各種メトリクス情報などを公開するWeb Serverを起動▶ コンテナへのPortForward/ContainerLog/Execなどのエンドポイントもある▶ dockershimを使う場合はdockershimサーバーの起動もKubeletの機能の(あくまで)概要としてはこのくらい特にここらへんの実装が超巨⼤
Kubeletの中では数多くのコンポーネント動いており、数⼗〜数百以上のgoroutineが同時に動き、チャネルを通じてイベントを処理する
▶ Startup/Liveness/Readinessの各Probeはgoroutineによって制御される▶ そのため、例えば1ノードで同じPodが100動いており、Startup/Liveness/ReadinessそれぞれのProbeが設定されていた場合には、100*3で300のgoroutineがそれぞれで動くことになる▶ configMapAndSecretChangeDetectionStrategyがデフォルト(=watch)の場合は、Podに設定されたSecret/ConfigMapの数だけgoroutineによる対象のSecret/ConfigMapの変更監視を⾏うReflectorが起動する▶ etc中には動的に起動されるgoroutineもいくつか存在する
dockershimについて
dockershim▶ KubernetesにはContainer Runtime Interface(CRI)というコンテナランタイムとのやり取りをする仕様が存在する▶ しかしDockerにはCRIを満たした実装が存在しないため、CRIを通してDockerの操作を⾏うためにdockershimが使⽤される▶ そのため、dockershimはdockerのためのCRI実装とも⾔える▶ dockershimはKubeletに内蔵されていて、dockershim⽤にサーバーを⽴ち上げ、KubeletはUNIXドメインソケットなどを介してdockershimサーバーと通信を⾏う
dockershimが⽴ち上げるプロセス▶ gRPC Server: CRIのgRPCサーバー▶ Streaming Server: kubectl execやkubectl port-forwardなどを処理するtcpサーバーAPI Server → kubelet → Streaming Server → コンテナのようにプロキシされていく▶ Container Manager: コンテナプロセスのoom_score_adjの設定などを⾏う
CRIについて
CRI▶ CRIは以下の2種類のgRPC Serviceに分類できる▶ Runtime Service: コンテナの操作に関するもの▶ Image Service: コンテナイメージの取得などに関わるもの▶ Runtime ServiceとImage Serviceは別々のランタイムを使い分けることが可能なよう(実装を⾒る限り)▶ PodSandboxというPodのベースとなるコンテナを作り、他のコンテナとネットワーク空間などをシェアする▶ kubectl execやkubectl port-fowardなどの通信の仕様についてもCRIで定義されている
その他のアプリケーション
kubeletのメイン処理以外にも例えばこういったアプリケーションも同時に動いている
Server▶ Healthz Server: ヘルスチェック⽤のエンドポイントだけを提供するサーバー▶ Kubelet Server: 以下のようなエンドポイントを持ったサーバーを起動▶ Podのログやexec、port-forwardなどを⾏うproxyエンドポイント▶ 各種メトリクス⽤のエンドポイント▶ Pod情報を返すエンドポイント▶ pprof⽤のエンドポイント▶ etc
その他のアプリケーション▶ syncNodeStatus: nodeリソースの登録とステータス更新を⾏う▶ NodeLeaseController: NodeLeaseリソースの登録・更新を⾏う▶ dynamicKubeletConfigController: ConfigMapから動的にKubeletのConfigをダウンロードして、⼿元のConfigをアップデート~Kubeletプロセスを停⽌する(停⽌することでsystemdなどにより再起動)ことで、Kubelet Configを動的に更新するコントローラー▶ Plugin Manager: プラグインディレクトリにソケットファイルが作られた際に、作られたソケットファイルと通信を⾏い、CSI Driver/DevicePluginを登録~管理するManager▶ clientCertificateManager: KubernetesのCertificateSigningRequestを利⽤してKubeletが使う証明書の⽣成~更新を⾏う
KubeletのPluginWatcher
Kubelet Plugin Watcher
Kubelet ~ CSI Drier間の通信
Kubeletのメイン処理
実際にPodからコンテナが作られる様⼦を(ふわっと)⾒てみよう
API Serverからのイベント受信まで
メインループからのPodの処理フロー
Podの起動処理
RuntimeManagerのPodの起動処理
こんな感じでKubeletではgoroutineやチャネルを使い様々なコンポーネントがイベント駆動で動作します
まとめ
まとめ▶ Kubeletがコンテナを管理するメインプロセスの⼤まかな動作や仕組みについて解説しました▶ dockershimとCRIについても簡単に解説しました▶ また、Kubeletのメインとなるコンテナ管理やdockershim以外にも⽴ち上げているWebServerやその他のアプリケーションについても⼀部紹介しました
感想▶ OSSで単体のアプリケーションとして読んだコードとしてはKubeletが今までで⼀番⼤きく、goroutineとチャネルを使って様々なアプリケーションを1つのプロセスで⾮同期に管理する仕組みは⼤まかでも把握するのがかなり⼤変でした▶ ただKubeletはコンテナやコンテナと紐づくPodリソース、Volumeなどの関連するファイルなど状態を⾃分⾃⾝で管理しなければ⾏けないものが⼤量にあるためある程度仕⽅ないのかなという印象です▶ 1つのGoのアプリケーションの中で⼤量のgoroutineとチャネルを起動~管理している実装を初めてちゃんと読んだので、かなりGoの勉強になりました▶ CRIの実装としてはdockershimが内部で直接Dockerのコマンドをライブラリ越しに叩いているようなものなので、コンテナ管理をどのようにしているかのイメージがしやすかったです▶ とはいえDockerのネットワークやCGroupなどまだまだわかっていない領域も多いので、そこらへんはこれからの課題かなと思いました
参考資料▶ Kubernetes v1.19: https://github.com/kubernetes/kubernetes/tree/release-1.19▶ Control Topology Management Policies on a node: https://kubernetes.io/docs/tasks/administer-cluster/topology-manager▶ Control CPU Management Policies on the Node: https://kubernetes.io/docs/tasks/administer-cluster/cpu-management-policies/▶ Configure Quality of Service for Pods: https://kubernetes.io/docs/tasks/configure-pod-container/quality-service-pod/▶ Certificate Signing Requests: https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/▶ Dynamic Kubelet Configuration: https://kubernetes.io/blog/2018/07/11/dynamic-kubelet-configuration/▶ Reconfigure a Node's Kubelet in a Live Cluster: https://kubernetes.io/docs/tasks/administer-cluster/reconfigure-kubelet/▶ CRI: the Container Runtime Interface: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-node/container-runtime-interface.md▶ Redefine Container Runtime Interface: https://github.com/kubernetes/kubernetes/blob/release-1.5/docs/proposals/container-runtime-interface-v1.md▶ Container Runtime Interface (CRI) Networking Specifications: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-node/kubelet-cri-networking.md▶ Container Runtime Interface: Container Metrics: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-node/cri-container-stats.md▶ CRI Streaming Requests: https://docs.google.com/document/d/1OE_QoInPlVCK9rMAx9aybRmgFiVjHpJCHI9LrfdNM_s/edit#heading=h.4yfjiw58o8d3▶ CRI: Log management for container stdout/stderr streams: https://github.com/kubernetes/kubernetes/blob/release-1.5/docs/proposals/kubelet-cri-logging.md▶ Pod Shared PID Namespace: https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/495-pod-pid-namespace/README.md▶ Client/Server container runtime: https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node/runtime-client-server.md▶ Introducing Container Runtime Interface (CRI) in Kubernetes: https://kubernetes.io/blog/2016/12/container-runtime-interface-cri-in-kubernetes/▶ docker update: https://docs.docker.com/engine/reference/commandline/update/▶ docker container create: https://docs.docker.com/engine/reference/commandline/container_create/
まとめ資料▶ Zenn scrap: https://zenn.dev/bells17/scraps/c351f36a94e72f74c3c8▶ Miro board: https://miro.com/app/board/o9J_lbLT0xU=/
Thanks / Question?▶ @bells17▶ Slide: https://speakerdeck.com/bells17▶ @bells17_