Kubernetesのコードリーディングをする上で知っておくと良さそうなこと

bells17
26 min readJun 11, 2020

--

Kubernetesとその関連コードのコードリーディングをする上で知っておくと良さそうなことについて知ってる範囲で雑にまとめてみました

前提知識

前提として最低限Kubernetesをある程度触っていて

  • KubernetesはPodとかのリソースと呼ばれるものでコンテナだったりロードバランサーとかを管理するようになっていて
  • 実際にDeploymentでコンテナを立てて
  • Service/Ingressでコンテナで立てたアプリケーションを外部公開できて
  • コンテナはPodという単位でコンテナをグループ化して同一Nodeで実行されるということを知っている

くらいがわかっていればまぁ十分なんじゃないかとは思います

あとはKubernetesはGoで書かれているので

  • Goの基礎知識と
  • VSCodeやGolandなどGoのコードを読む際に宣言にジャンプできるようなエディタ

くらいがあると良いと思います

Kubernetesのコンポーネント

まずはじめにKubernetesの各種コンポーネントでどんなものがいるのかについて大まかに把握しておくと良いんじゃないかと思います

コンポーネントを把握しておくとだいたい何がどんな関係になっているのかがイメージしやすくなるのと、どこらへんのコードを読んでみようみたいなのが考えやすくなると思います

コンポーネントについては公式ドキュメントの

あたりを把握しておけば良いと思います(図がわかりやすいので、なんとなくKubernetesのコンポーネントについて把握できた気になれる)

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

上記の中で実際にコードを読むとしたらKubernetesのコアコンポーネントになると思うので候補としてはだいたい

  • kube-apiserver
  • kube-scheduler
  • kube-controller-manager
  • cloud-controller-manager
  • kubelet
  • kube-proxy

あたりになるんじゃないかと思います(あとは上記には出てこないけどkubectlとか)

あと詳細は次に書くけど(kube|cloud)-controller-managerはControllerという単位の集まりになっていて、それぞれのControllerが独立して動作するようになっているので、Controller単位で実装を読んでいける様になっている感じです
(逆に言うと例えばDeploymentを作るとどこかのNodeでPodという単位でコンテナが起動されるという全体像を把握するには関連するControllerなどのコード全体を把握しなければいけないのでややこしい)

Kubernetesの基本的なアーキテクチャ

上記でControllerという単位で独立して動作するようになっていると書きましたが、Kubernetesの多くのコンポーネントが

  • 宣言的アーキテクチャになっていて
  • Kubernetesの各種リソースでコンテナだったりのあるべき状態の宣言を行い
  • 各種Controllerがリソースのあるべき状態になるように調整を行うようになっている(Reconciliationループ)

という仕組みになっているので、これについて把握しておくと良いと思います
(kube-apiserverとかは多分別の仕組みだと思うけど)

これのイメージについては青山さんの

https://speakerdeck.com/masayaaoyama/infrastudy2-k8s?slide=43 あたりの図がわかりやすい

あたりのスライドを読むと図付きで説明してくれているのでわかりやすいです
(YouTubeの動画でいうとここらへん)

Kubernetes関連のコードを読むときはだいたいここで紹介している

  • Reconciliationループと
  • Reconciliationループによって調整されるものの(ボリュームやロードバランサーといったクラウドのリソースやコンテナランタイムなどによって起動されるコンテナなど)

について読んでいくことになるので、とりあえずReconciliationループというのがあるらしいということを知っておくとコードを読む時に何をやっているのかがイメージしやすくなると思います

kubernetes/kubernetesリポジトリの見方

kubernetesの本体というか、コアとなるコードはだいたい全てkubernetes/kubernetesリポジトリに入っているので基本的にここを読んでいくことになります

https://github.com/kubernetes/kubernetes

この中のいくつかのディレクトリについて把握しておけばとりあえずコードリーディングしていくことができると思うので、覚えておくと良いものについて説明していきます
(間違ってたら教えて下さい)

cmd

cmdディレクトリにはkube-controller-managerとかkubectlといったKubernetesの各種コンポーネントのバイナリを生成するためのエントリーポイントとなるコードが置かれてます

https://github.com/kubernetes/kubernetes/tree/master/cmd

そのため、例えば”kube-controller-managerやkubeletの実装を読んでみたい”といったときはこの中にあるコードから読んでいくことになります
(kube-controller-managerならcontroller-manager.goなど)

pkg

cmdディレクトリ以下はコマンドのエントリーポイントとなるコードとその補助となる実装が大半で、メインのロジックのコードはpkgディレクトリにあります

staging/src/k8s.io/

またstaging/src/k8s.io/ディレクトリにはKubernetesの本体以外でも利用されるコードをライブラリ化して置いてあったりします(という理解であってたはず)

例えば

  • Kubernetes APIのクライアントライブラリであるclient-go
  • 各種Kubernetes APIのリソースの定義が書かれたapi

などがあります

そしてこれらはKubernetes organizationk8s-staging というタグがついているリポジトリと同期しています

確かメインはstaging/src/k8s.io/ディレクトリにあるコードで、上記の個別のリポジトリはstaging/src/k8s.io/ディレクトリのコードを同期してるんだったと思ってます
(けどあってるかあんまり自信無い)

主要なディレクトリについては以上で、kubernetes/kubernetesリポジトリをコードリーディングする際は主に今紹介した

  • cmd
  • pkg
  • staging/src/k8s.io/

の3つについて覚えておけばだいたいなんとかなると思います

ここらへんについてもっと知りたい場合は

が参考になるんじゃないかと思います

client-goについて知る

先程staging/src/k8s.io/ディレクトリについて紹介したけど、client-goには

  • Kubernetes APIに触れるためのクライアントライブラリ
  • Kubernetes ControllerでReconciliation loopを実装するための基礎実装
  • その他Kubernetes Controllerを作る上での共通のユーティリティ

などが入っており、個別の実装について詳細に理解する必要はないけれど、大まかな概要を把握しておくとKubernetesのコードを読む上で役に立ちます
(名前からどれがclient-goのどんな機能かを把握しておくと、client-goの実装を読まなくてもだいたいどんなことをしているのか想像できるようになるので、Kubernetesのコード読んでる時にclient-go関連のコードをいちいち追わなくても済むのでコードリーディングが楽になる)

Kubernetes APIに触れるためのクライアントライブラリ

クライアントライブラリとしての機能は、AWSだったりGCPのSDKのように普通にAPIなだけなので、なんとなく使い方を把握しておけば問題ないと思います

試してみるにはclient-goにexampleがいくつかあるので、その中でも”Create, Update & Delete Deployment”がDeploymentの操作をclient-go経由で行っているだけなのでわかりやすいんじゃないかと思います

Kubernetes ControllerでReconciliation loopを実装するための基礎実装

Reconciliation loopを実装するための基礎実装については

https://github.com/kubernetes/sample-controller/blob/master/docs/controller-client-go.md

のようなコンポーネントのことを指してました
これらのコンポーネントについての説明は

を読むとイメージが掴めるんじゃないかと思います

また試しに上記に挙げたsample-controllerの実装を読んでみると良いんじゃないかと思います
sample-controllerはKubernetes Controllerを自分で実装するためのサンプルになるので、Kubernetes本体のコードを読む際にも役に立つと思います

その他Kubernetes Controllerを作る上での共通のユーティリティ

共通のユーティリティについてはKubernetesのコードリーディングを始める際には半分くらいおまけだと思っていて、例えばKubernetesのControllerは冗長化する際にはアクティブ/スタンバイ形式で常に1台だけControllerが動作する仕組みになっているのですが、このアクティブ状態にあたるリーダーとなるControllerを選定するライブラリであるleaderelectionといったツールが提供されていたりします

ちなみに、このleaderelectionについて詳しく知りたい場合はponde_mさん

などが参考になると思います

Kubernetes ControllerのReconciliation loopに慣れる

ここまででKubernetesのコードを読む上で基礎知識については紹介できたと思います

これ以上については一旦自分でKubernetesのControllerを書いてみるのが、実際にKubernetesのコードを読みやすくなる上で一番手っ取り早いんじゃないかと思います

具体的にはいくつか選択肢があると思っていて

あたりかなと思っています

client-goのexampleである”Workqueue Example”を写経~書き換えて動作を確認してみる

“Workqueue Example”については実際のKubernetesのControllerの実装でやっていることと同じようなことを“Workqueue Example”のmain.go1ファイルで行っているので、学習コストも少なく一番簡単な気がします

このサンプルのsyncToStdoutメソッドがReconciliation loopの調整処理であるReconcilerにあたるので、syncToStdoutメソッドを書き換えて手元のクラスターで動かしてみてってやればなんとなく雰囲気がつかめるんじゃないかと思います

またReconciliation loopは基本的に監視している特定の種類のリソースに関するイベントを検知して実行されます
この“Workqueue Example”ではPodリソースをこの箇所で監視していますが、 &v1.Pod{}podListWatcherという部分を監視したい任意のリソースに変更すれば監視対象のリソースを変更可能です

ただし、このサンプルでやっている元々のReconcilerでは、検知したPodリソースが実際にあれば名前を出力するだけというシンプルな例になるので、実際のReconcilerの実装例としては少しピンとこないかもしれないのが欠点かなとは思います

上記に挙げたsample-controllerの実装を写経~書き換えて動作を確認してみる

sample-controllerの実装についてはFooというCRDを作成することで、対応するDeploymentを作るという内容になっているようなので、実際のReconcilerの例としてはこちらの方がイメージしやすいかと思います

ただし上記に書いた通りCRDを利用していたりする関係でファイル数としては多くなってしまっているので、“Workqueue Example”に比べると少し複雑でコードを読むのは少し大変かもしれません

sample-controllerの実装を使って書き換えなどを試してみるのであれば、Reconcilerにあたる箇所はsyncHandlerメソッドとなるので、syncHandlerメソッドを書き換えて手元のクラスターで動かしてみると良いかと思います

リソース監視に関しては“Workqueue Example”と違うやり方で行っているので、このInformerとその関連箇所を別のリソースのInformerに変更する必要があります

kubebuilderが生成するサンプルコントローラーを書き換えて動作を確認してみる

kubebuilderはKubernetesコミュニティが推奨しているSDKで

  • ベースとなるCustom Controllerの生成や
  • Admission Webhookの生成
  • CRDの生成

といったKubernetesを拡張するための機能を実装するための生成・管理機能を備えたフレームワークになります

kubebuilderの実態としては

  • ベースとなるCustom Controllerの生成や
  • Admission Webhookの生成

の部分を担うcontroller-runtime

  • CRDの生成

の部分を担うcontroller-toolsを組み合わせて+αしたようなもののはずです

kubebuilderが生成するコードは、controller-runtimeをベースとしたコードとなるためKubernetes本体のコードとは異なる部分も多いですが、client-goのInformerなどのコードをあまり意識することなく

  • Reconcilerの実装
  • 特定リソースの監視の実装

などの処理に集中できるためReconciliation loopの実装については十分学ぶことができると思います

またCustom Controllerを自作する場合は、このkubebuilderか基盤となるcontroller-runtimeを使うケースが多いと思うのでCustom Controller自作の練習にも向いていると思います

kubebuilderを利用する場合にはチュートリアルが豊富なので、学習時間はかかるとは思いますが学びが多いと思います

またkubebuilderについての概要についてはeverpeaceさん

のセッションがめちゃくちゃ参考になると思います

これまでで実際にKubernetes ControllerのReconciliation loopを試す方法を3つ紹介しましたが、どれか一つでもやっておくと実際のControllerの動作イメージが具体的に湧いて良いと思います

Kubernetesで読むコードを探す

これまでの部分をやっていればKubernetesのコードを読む準備としては十分だと思うのですが、端からコードを読んでいくのも(僕は)辛いので、何かテーマを作ってコードを読んでみると良いと思います

テーマを作る際はDesign ProposalKubernetes Enhancement Proposals (KEP)を参考にすると色々なヒントが得られて良いと思います

Design ProposalKubernetes Enhancement Proposals (KEP)

はKubernetesに対する機能提案を行う際に利用されるもので、Kubernetesに関する機能追加についてはまずこれらのProposalを参考にすると良いです

Design Proposal/KEPには、それぞれの提案ごとに粒度はバラバラですが

  • 提案内容
  • モチベーションやゴール
  • 詳細設計

などが含まれており、機能追加に至った経緯やどんな風に設計されているのかがわかります

例えばContainer Storage Interface(CSI)の導入についてはここで提案されており、なぜ導入されたのかやどんな風に設計されているかが特に細かくかかれているので、コードリーディングのネタを探すきっかけになります

僕の場合上記のCSIの提案を読んだときは、ネタ探しのために読んだわけではなかったのですが、設計などが超細かく書かれていたのでCSIに関するコードを読む際に全体像がかなりイメージしやすくなったので、そういった意味でも読みたいコードが見つかった場合にコードを読む前に関連する提案がないか探してみるのがオススメです

余談ですがDesign Proposal/KEPなどの流れはどうやら以下のような流れになってるらしいです
(聞いたり調べた話をつなげ合わせただけなので合ってる確証は無し)

  • 機能開発に関するはすべてissueで行っていた
  • issueでUmbrella Issueという機能開発のベースとなるissueを作って管理する(kubernetes/kubernetesで”umbrella”とissueを検索するとissueのタイトルのはじめに”umbrella”って書いてあるやつが結構出てくる)
  • Design Proposalに移行
  • KEPに移行

Kubernetesのコードを読む

読みたい箇所が決まったら実際にコードを読んでいくと思いますがだいたい2パターンくらい読み方があるのかなと思っていて

  • cloud-controller-managerなどのエントリーポイントを1から読んでいく
  • xxx controllerなど特定の処理を行うメインロジックを見つけて読んでいく

あたりかなと思っています

cloud-controller-managerなどのエントリーポイントを1から読んでいく

こちらのやり方に関してはやり方としては簡単でkubernetes/kubernetesリポジトリのcmdディレクトリから読みたいコードを探して読むだけになります

例えばcloud-controller-managerの場合、その中で動いているServiceControllerに絞ってコードリーディングしたログが

になります

この記事のようなServiceControllerを読む前には事前に

といった公式ドキュメントに加えて

というDesign Proposalなどを読んだりしてからcloud-controller-managerのコードを読んだりしてました

xxx controllerなど特定の処理を行うメインロジックを見つけて読んでいく

これはDesign Proposal/KEPなどから興味のある機能などを見つけて、その関連コードを追っていくような読み方です

自分の経験でいうと、Kubernetetes本体にはまだ入っていない機能ではあるのですが、CSIがその一つで、以下のような流れでコードを読んでました

CSIが結構大きめの仕組みなのでかなり遠回りしてますが、だいたいこんな感じでDesign Proposal/KEPから読むコードを探したりしてます

ちなみにCSIに関して調べてわかったことは以前Kubernetes Meetup Tokyoでも発表したので興味があれば見てみてください
https://youtu.be/m4SpEzKN-RM?t=2527

https://speakerdeck.com/bells17/kubernetes-and-csi

ここまででだいたいKubernetesのコードを読む前に知っておいた方が良いこと~実際にコード読む際にこんなふうに読んでいくとよみやすいんじゃないかみたいなことが紹介できたと思います

以下ではKubernetesのコミュニティだったりなど、コードリーディングとは直接関係無いけれど知っておくと便利そうなことについてまとめてみます

Kubernetesのコミュニティについて

コードリーディングとは直接関係無いけれど、Kubernetesのコミュニティの構造についてなんとなく知っておくと何をどういう人達が開発しているのかが把握しやすいです

Kubernetesの開発はこのコミュニティで行われていて

https://docs.google.com/presentation/d/18LcwvqyNn74HgqIk7O-ChgfSsJAqDIYm7obguEXto4Q/edit#slide=id.g608b283008_0_11

のようなグループの種類があるのですが、個人的に重要なのはSIGsで、例えば

  • kubernetes.ioなどのドキュメントについては sig-docs
  • kubeletなどのノードに関するものは sig-node
  • Kubernetesとクラウドとの連携する仕組みについては sig-cloud-provider
  • Kubernetesとストレージを連携するには sig-storage
  • Kubernetesとロードバランサーやネットワークの連携を行ったりは sig-network

といった風に担当領域毎にSIGが別れています

これらのSIGの情報はkubernetes/communityリポジトリで管理されていて、リポジトリトップにある sig-xxx というディレクトリで各SIGのメンバー構成や定期MTGなどの情報が乗っています

sig-storageの例: https://github.com/kubernetes/community/tree/master/sig-storage

SIGについての詳細は

あたりを見るとイメージしやすい気がする

Kubernetes Slack

KubernetesはSlackのワークスペースがあるので入っておくと色々と質問しやすいので入っておくと良いと思います

入っておくと良いチャンネルは以下のようなチャンネルかなと思います

日本コミュニティ

  • #jp-users: 日本コミュニティのメインはこのチャンネルっぽいので、とりあえず日本コミュニティでどのチャンネルで聞いたりすればいいかわからないときはここで聞くのが良いと思う
  • #jp-events: Kubernetesのイベント関連の情報告知用のチャンネルで、ここを定期的にウォッチしておけばKubernetes関連のイベントはだいたい把握できる
  • #jp-dev: 日本コミュニティのKubernetesのコントリビューター用のチャンネルでKubernetesの実装とかに関する質問を日本語でしたい場合はこのチャンネルでするのが良いんじゃないかと思ってる
  • #jp-users-novice: 日本コミュニティ向けのKubernetes初心者向けチャンネルで、Kubernetes初心者の人でも気軽に質問や相談をするためのチャンネル
  • #jp-mentoring: Kubernetes Community関連の相談をしたり、Kubernetes アップストリームトレーニングなどのサポートに利用される日本コミュニティ向けのチャンネルのよう

日本コミュニティ以外のおすすめチャンネル

  • #kubernetes-novice: グローバルなKubernetes初心者向けのチャンネルで、英語で質問するのに抵抗ないのならこっちでKubernetesの質問をするのも良い
  • #office-hour: 月1回開催されるKubernetes Office Hour用の質問チャンネル。YouTubeの配信とこのチャンネルを使ってリアルタイムにKubernetesの利用者向けの色んな質問について答えてくれる。オフィスアワーの詳細はここに書いてある
  • #meet-our-contributors: 月1回開催されるMeet Our Contributors用の質問チャンネル。YouTubeの配信とこのチャンネルを使ってリアルタイムにKubernetesの開発者向けの色んな質問について答えてくれる。詳細はここに書いてある
  • #sig-xxx: 自分の興味があったり詳しく質問をしたい領域については各sigのチャンネルだと詳細な質問がしやすいと思う

Kubernetesにコントリビュートする

Kubernetesにコントリビュートする際にはドキュメントの日本語翻訳が一番参加しやすいんじゃないかと思ってます

Kubernetes公式ドキュメントの日本語翻訳はSlackの#kubernetes-docs-jaチャンネルで行っていて、特に最近は初めてのコントリビューター向けの小さめのissueをたくさん作ってくれているので、Kubernetesにコントリビュートしてみたい人は参加しやすいと思います

コントリビュートするのに必要なことはKubernetesコントリビューターチートシートにまとまっていて、日本語訳されているのでそんなに困ることは無いと思います

唯一ハマりそうなところはCLAのサインで、Kubernetes関連のリポジトリにコントリビュートする際はCLAというものにサインして、サインしたemailでGithubにcommitする必要があります

CLAについては

のでここらへんを参考にすれば解決できると思います
(もしそれでもハマる場合にはSlackの日本コミュニティのチャンネルとかで聞いてもらえれば誰かしらフォローしてくれると思います)

Contributor Workshop

コントリビューター向けの情報としてKubeConなどでContributor Workshopというのが開催されたりするので、このときの資料や動画が参考になる
(というか上で書いてたことの大半が書かれてるので実質これみるだけでいいのかも)

Kubernetes Contributor Summit San Diego 2019のContributor Workshop資料などはこれ

Kubernetesアップストリームトレーニング

日本でも不定期に?上記のContributor WorkshopをベースにしたKubernetesアップストリームトレーニングが開催されているようで、過去の開催されたKubernetesアップストリームトレーニングはこんな内容で開催されたらしい

もう締め切られてしまったけどちょうど明日開催のKubeFest Tokyo 2020でもKubernetesアップストリームトレーニングが開催予定で僕も初めて参加するので楽しみ

まとめ

Kubernetesのコードリーディングをする際に知っておくと良さそうなことについて思いつく範囲で一通り書いてみた

Contributor Workshopの資料みたら自分で書いたことだいたい書いてある気がしたけど、自分なりに思いつくことをまとめられたので書き出してみて良かったのかなと思う

でも書いてみたら意外とコンテンツの量が多くて大変だった

--

--