Upgrade to Pro — share decks privately, control downloads, hide ads and more …

CRIの仕様とdockershimの実装について調べてみた/CRI spec & dockershim implementation

3499a1d71fa70b8ee44816ca9e7329fe?s=47 bells17
January 28, 2021

CRIの仕様とdockershimの実装について調べてみた/CRI spec & dockershim implementation

Container Runtime Meetup #3
https://runtime.connpass.com/event/198071/
で発表したスライドです

3499a1d71fa70b8ee44816ca9e7329fe?s=128

bells17

January 28, 2021
Tweet

Transcript

  1. CRIの仕様とdockershimの実装に ついて調べてみた Container Runtime Meetup #3(2021/01/28) @bells17

  2. ▶ @bells17 ▶ Software Engineer ▶ 普段やってること: + Kubernetes 関連コンポーネントの開発

    + Kubernetes as a Service開発の調査・研究 ▶ Kubernetes SIG-Docs Japanese localization reviewer ▶ Kubernetes Internal Organizer ▶ #kubenews ▶ @bells17_
  3. 今⽇話すこと ▶ CRIについて ▶ dockershimについて

  4. このセッションの⽬標 ▶ CRIの仕様の構成と内容について、”ふわっと”知ってもらう ▶ dockershimとは何か?を”ざっくりと”理解してもらう ▶ dockershimがどんなふうにDockerと通信してコンテナを起動している のか、”なんとな〜く”雰囲気を感じてもらう

  5. 注意点 ▶ コンテナランタイム超絶初⼼者枠です ▶ ついでに以下も初⼼者です + Linuxコンテナ + コンテナ周りのネットワーク ▶

    ガチでただの調べてみた系のLTです ▶ ⾼度な内容は期待しないでください!!! ▶ ⼀応dockershimのコードベースは Kubernetes v1.19ベースでのお話になります
  6. アジェンダ 1. CRIとは? 2. dockershimとは? 3. dockershimの挙動 4. まとめ

  7. CRIとは?

  8. CRIとは? ▶ CRI = Container Runtime Interface ▶ Kubernetesが定義しているコンテナランタイムと連携するための仕様が CRI

    ▶ CRIの定義はDesign Proposal(的なもの)が機能種別ごとに別れており、ま たあまり情報がまとまっていないので、結局現⾏の正しい?CRI全体の仕 様を定義をまとめたドキュメントが無くて分かりづらい ▶ ドキュメントではCRI実装のことをRuntime ShimやCRI Shimと呼んでる ▶ ちなみにまだv1ではないらしい(今はbetaっぽい)
  9. CRI定義の種別 ▶ Protocol Buffer/gRPC Server ▶ Networking Specifications ▶ Container

    Metrics ▶ Exec/Attach/PortForward Streaming Requests ▶ Container stdout/stderr logs
  10. Protocol Buffer/gRPC Server ▶ 以下の2種類のServiceに分割されている + Runtime Service: コンテナの操作に関するもの +

    Image Service: コンテナイメージの取得などに関するもの ▶ Kubeletの設定値/実装を⾒る限りRuntime ServiceとImage Serviceは 別々のランタイムを使い分けることが可能なように⾒える(詳細不明) ▶ PodSandboxというPodのベースとなるコンテナを作り、Podで定義され たその他のコンテナがSandboxコンテナが作成したネットワーク空間など をシェアしてもらうようなモデル ▶ ⼀応CRIの定義の中にLinuxコンテナだけでなく(micro)VMを使うことを想 定しているようなことも書かれている(でも詳細はほぼ書いてない) https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node/container-runtime-interface-v1.md
  11. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node/runtime-client-server.md Pod作成時のフロー

  12. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node/runtime-client-server.md Pod削除時のフロー

  13. Networking Specifications ▶ CRIのネットワーク周りに関する定義 ▶ “RunPodSandbox” RPC でPodネットワークを設定する必要がある ▶ “StopPodSandbox”

    RPC でPodネットワークを停⽌?する必要がある ▶ といったPod操作とその時のネットワークの操作に関する定義がざっくり とされている感じ ▶ CRI networking requirements/k8s networking requirementsが満たされ ている限りは、CNI/CNM/その他の実装でも何でも動くようにという感じ らしい + CRI networking requirementsは“RunPodSandbox” RPC ~といった 部分だと思われる https://github.com/kubernetes/community/blob/master/contributors/devel/sig-node/kubelet-cri-networking.md
  14. k8s networking requirements ▶ ノード上のPodが、NATなしですべてのノード上のすべてのPodと通信で きること ▶ systemdやkubeletなどノード上にあるエージェントが、そのノード上の すべてのPodと通信できること ▶

    ノードのホストネットワーク内のPodは、NATなしですべてのノード上の すべてのPodと通信できること + 注: ホストネットワークで実⾏されるPodをサポートする プラットフォームの場合(Linuxなど)は https://kubernetes.io/docs/concepts/cluster-administration/networking/
  15. Container Metrics ▶ コンテナランタイムから取得できるメトリクス情報を抽象化したもの ▶ 取得できるメトリクス情報がProtocol Bufferによって定義されている ▶ メトリクスの取得⾃体はRuntime ServiceからRPCコールで取得できる

    https://github.com/kubernetes/community/blob/master/contributors/devel/sig-node/cri-container-stats.md
  16. Exec/Attach/PortForward Streaming Requests ▶ Exec/Attach/PortForwardそれぞれのストリーミングリクエストの⽅法につ いて定義されている ▶ Exec/Attach/PortForward⾃体はRuntime Serviceに対してRPCコールで呼び 出せる

    ▶ Exec/Attach/PortForwardリクエストをShimが受け付けるとリクエストを受 け付けるサーバーを起動し、起動したサーバーのポート情報を返し、Kubelet がAPI Serverからのリクエストを返されたポートにリダイレクトする ▶ API ServerではリダイレクトされたShimの起動されたサーバーに接続を⾏い Exec/Attach/PortForwardの処理を⾏う ▶ API Server - Shim間の認証/認可はKubeletと同様に証明書などを利⽤する ▶ のような感じで書いてはあるが、Kubeletの実装は書いてる事と結構違う https://docs.google.com/document/d/1OE_QoInPlVCK9rMAx9aybRmgFiVjHpJCHI9LrfdNM_s/edit#heading=h.4yfjiw58o8d3
  17. Execなどでコンテナに接続するまでのフロー https://docs.google.com/document/d/1OE_QoInPlVCK9rMAx9aybRmgFiVjHpJCHI9LrfdNM_s/edit#heading=h.4yfjiw58o8d3

  18. Execなどでコンテナに接続するまでのフロー(実際) https://docs.google.com/document/d/1OE_QoInPlVCK9rMAx9aybRmgFiVjHpJCHI9LrfdNM_s/edit#heading=h.4yfjiw58o8d3

  19. Container stdout/stderr logs ▶ Kubernetesがコンテナのストリーミングstdout/stderrログを扱うための 仕様 ▶ KubeletがPodSandboxコンテナ起動時に /var/log/pods/<podUID>/ ディ

    レクトリを作成する ▶ CRI Shimは(Sandboxコンテナ以外の)各種コンテナを起動する際にコンテ ナのログが /var/log/pods/<podUID>/<containerName>_<instance#>.log に出⼒されるように設定を⾏う ▶ ログフォーマットは以下のようになっている必要がある + プレフィックスにRFC 3339Nano timestamp + ストリームタイプが付き + 改⾏で終わる https://github.com/kubernetes/kubernetes/blob/release-1.5/docs/proposals/kubelet-cri-logging.md
  20. dockershimとは?

  21. dockershimとは? ▶ コンテナランタイムにDockerを使⽤する際に、Kubeletが内部で起動する Docker⽤のCRI Shim実装 ▶ Kubelet内部でgoroutineとして起動される ▶ 内部は以下の3区分のアプリケーションとなっている +

    Streaming Server: kubectl execやkubectl port-forwardなどをプロキシする tcpサーバー + gRPC Server: CRIのServiceを実装したgRPC Server + Container Manager: コンテナプロセスのoom_score_adjの設定などを⾏う ▶ Kubernetes v1.22 で削除される予定となっている ▶ 主にContainer Manager周りが独⽴しておらず、その他のKubeletの処理で Container Managerなどの操作を⾏っていたりする ▶ ここらへんの保守コストが原因で削除されることになったのでは?と予想
  22. None
  23. dockershimの特徴 ▶ RunPodSandbox/StartContainerなどのRPCコールの裏側でDockerのライ ブラリを使って普通にDockerのAPI呼び出しを⾏っている ▶ なので普通にdocker create/docker startのようなdockerコマンドに変換 して読んでいくことが可能 +

    ただし、dockerコマンドで渡せる様々なオプションがどういったことを しているのかの理解は必要(誰か教えて…) ▶ そのためdockerコマンドを使ってどのようにdockershimがコンテナを作 成~起動などをしているかの勉強になる(気がしている)
  24. dockershimの挙動

  25. RunPodSandbox ▶ もし⼿元にSandboxコンテナ⽤のイメージがなければ、イメージのPullを⾏う ▶ Sandboxコンテナ⽤のdocker createのコンフィグを⽣成 ▶ docker create相当のAPIを呼び出し⽣成したコンフィグに沿ったSandboxコン テナを作成

    ▶ 作成したコンテナのPortMapping情報など(Checkpoint)をファイルに保存 ▶ docker start相当のAPIを呼び出しSandboxコンテナを起動 ▶ resolv.confを⽣成し、Sandboxコンテナに保存 ▶ ネットワークプラグインを使⽤してPod間ネットワーク?を設定 + CNIを利⽤している場合にはCNIのAddNetworkListというRPCが呼び出され るよう
  26. CreateContainer ▶ 作成するコンテナ⽤のdocker createのコンフィグを⽣成 ▶ Sandboxコンテナの情報を元にコンフィグをアップデート ▶ docker create相当のAPIを呼び出し⽣成したコンフィグに沿ってコンテナ を作成

  27. StartContainer ▶ docker start相当のAPIを呼び出し対象となるコンテナを起動 ▶ /var/log/pods/<podUID>/<containerName>_<instance#>.log パスに起動 したコンテナのログファイルのシンボリックリンクを作成

  28. Exec(Attach/PortForwardも同じ) ▶ API ServerからKubeletに /exec/{podNamespace}/{podID}/{containerName} といったWebSocketエンドポイントにGET or POSTリクエストが送られる ▶ リクエストを受けるとKubeletは以下のような処理を⾏う

    + 認証のためのトークンを発⾏ + 実際にコンテナにexecを⾏うための /exec/{token} エンドポイントを⽣成 + このエンドポイントにプロキシを⾏うプロキシサーバーを起動 + プロキシされて /exec/{token} にリクエストが送られると、内部で dockershimのExec RPCをリクエストする + dockershimのExecでは内部でdocker exec相当の処理を⾏い、コンテナ にexecを⾏う
  29. まとめ

  30. まとめ ▶ Kubernetesにはコンテナランタイムとやり取りをする仕様であるContainer Runtime Interface(CRI)がある ▶ CRIではKubernetesのPodを起動したり、コンテナにexecするためのRPCコールの定義が されている ▶ dockershimはDocker向けのCRI実装(CRI(Runtime)

    Shim) ▶ dockershimはStreaming(tcp) Server/gRPC Server/Container Managerの3つのアプリケー ションによって構成されている ▶ dockershimの中⾝はdocker cliに変換して考えられるような実装の組み合わせになっている
  31. 感想 ▶ CRIの仕様はCSIに⽐べると結構ざっくりしてるなーという印象だったのですが、CRIの様々 な仕様についてスライドにまとめていく過程でなんとなくCRIの仕様の全体像がイメージで きる感じになってきてよかったです ▶ また、dockershim側の実装についても調べることで、CRIのイメージがより具体化された なという感じでした ▶ とはいえdocker

    createで実際に指定しているオプション(コンフィグ)の具体的な設定値に ついてはまだ調べきれてないので、次はそこらへんについてまとめてみたいなと思いました
  32. 参考資料 ▶ Kubernetes v1.19: https://github.com/kubernetes/kubernetes/tree/release-1.19 ▶ CRI: the Container Runtime

    Interface: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-node/container-runtime-interface.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 (exec/attach/port-forward): 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 ▶ Client/Server container runtime: https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node/runtime-client-server.md ▶ Redefine Container Runtime Interface: https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node/container-runtime- interface-v1.md ▶ Add a new container runtime interface: https://github.com/kubernetes/kubernetes/pull/25899 ▶ Kubelet CRI support: https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/2040-kubelet-cri ▶ libnetwork design: https://github.com/moby/libnetwork/blob/master/docs/design.md ▶ Kubelet network plugin for client/server container runtimes: https://github.com/kubernetes/kubernetes/issues/28667 ▶ Cluster Networking: https://kubernetes.io/docs/concepts/cluster-administration/networking/ ▶ containernetworking/cni: https://github.com/containernetworking/cni ▶ Core Metrics in kubelet: https://github.com/kubernetes/community/blob/master/contributors/design-proposals/instrumentation/core-metrics-pipeline.md ▶ Kubernetes monitoring architecture: https://github.com/kubernetes/community/blob/master/contributors/design-proposals/instrumentation/ monitoring_architecture.md
  33. 唐突ですがKubeletについてはこの 本にまとめています書いてます ▶ 技術書典: http://bit.ly/tbf-kubelet ▶ Booth: http://bit.ly/booth-kubelet Kubeletの詳細が気になる⽅は 良ければ買ってください!

    また ▶ Kubeletの概要についてはJFT 2021 Winter ▶ Kubeletのコードがどんなふうになっているかは Kubernetes Internal #4 でそれぞれ説明してますので興味があればどうぞ!
  34. Thanks / Question? ▶ @bells17 ▶ Slide: https://speakerdeck.com/bells17 ▶ @bells17_