本ドキュメントではKubernetesやその関連プロジェクトに対してContributionを開始したい人向けに、それに向けてどのような流れを踏んで行けば良いかを自身の経験ベースで記載している。
ここに記載している内容が必ずしも正解という訳ではないため、必要に応じて実施内容は取捨選択すること。
Kubernetesおよび関連プロジェクトに対してContributionを開始できること。
- Kubernetesおよび関連プロジェクトのコードを読んでどのような処理が行われているかを理解できる
- あるべき状態にプロジェクトのコードを修正できる
Kubernetesの基本的な動作やコンポーネントを理解しており、Kubernetesおよび関連プロジェクトにコードベースのPRを出してみたい人。
- Kubernetesのコンポーネントおよび役割の概要を説明できる
Reconcile Loop
とは何か概要を説明できる
使用するエディタは好みで良いが、特にコードリーディングをする上でコード内で使用されている関数やメソッド、構造体定義を参照したくなる場面が多いためVSCode
などコードジャンプを利用できるものを強く推奨。
Kubernetesの実装はGo言語が基本となるため、最低限の文法知識は必須。
ただし時間をかけ過ぎる必要はないので、どんなに長くても2週間以内にはこのステップを終わらせる。
※この後のステップで不明な文法に出会ったら都度調べたりサンプルコードを書いて知識を補完するというやり方が効率的
特にKubernetesでは以下の文法が頻出するので意識して学習すると良い。
interface
goroutine
channel
Kubernetes関連プロジェクトではUnitテストにGo標準のtesting
パッケージが用いられることもあるため、testing
パッケージを用いた基本的なテストコードの書き方は押さえておく。
ただし深掘りし過ぎる必要はなく、ネット検索すればいくらでも例は出てくるのでそれをなぞる程度で良い。
因みにe2eテストではGinkgo
/Gomega
といったテストフレームワーク(2.3
)が用いられるケースが多い。
基礎学習としてController
に関するコードリーディングや実装を経験することで、KubernetesのコアとなるReconcile
や、kube-apiserver
に対するCRUDの仕組みを習得する。
この知識はController
に限らず様々なKubernetesコンポーネントの実装理解に活用できるものなのでこのステップで押さえておくと良い。
特に2.1
、2.2
および2.4
については以下書籍に沿って行うのがスムーズ。
必要な知識を体系的かつ効率的に習得ことができるのを踏まえれば2,000円という価格は安い。
Controllerとは、管理対象とするなんらかのリソースの状態を、Kubernetesリソースとして定義したあるべき状態に維持する(=Reconcile Loop
を実現する)コンポーネント。
代表的な例としてKubernetes上でReplicaSet
を用いて複数Pod
を管理する例が挙げられる。(kube-controller-manager
に含まれるReplicaSetController
により実現)
sample-controller
(Controller
のリファレンス実装)のコードリーディングを通じてclient-goと呼ばれるパッケージを用いたプリミティブなController
の実装方式を理解する。
特にここで登場するClientset
,Informer
,EventHandler
,Queue
と言ったコンポーネントは実際のKubernetesのコアコンポーネントの実装でも用いられる重要コンポーネントであるため、利用方法やそれらを用いたReconcile
の実現方式に関する知識をこのステップで押さえておくと良い。
※コードリーディングを行う際のポイントは3.6
参照。
書籍を用意できるようであれば実践入門 Kubernetesカスタムコントローラーへの道の2、3章に沿って進めるのが理想的だが、用意が難しい場合は参考に挙げたサイトを参考にコードリーディングを行うと良い。
最終的に以下のようなイメージでsample-controller
が動作するところまで理解できれば良い。
Kubebuilder
(SDK)によるController
の実装を経験することで、Controller-Runtimeと呼ばれるライブラリを用いたController
の実装方式を理解する。
特にController-Runtime
ではclient-go
を用いるケースと比較してReconcile
を実現するための低レイヤのロジックが抽象化されているため違いを意識しながら進めると良い。
また、kubernetes-sigs
や3rd-Party
として提供されるController
はController-Runtime
を用いて実装されているケースが多いため、ここで使い方を理解しておくと実際のコードリーディングにおいて役立つ。
書籍を用意できるようであれば実践入門 Kubernetesカスタムコントローラーへの道の4、5章に沿って進めるのが理想的だが、用意が難しい場合は参考に挙げたサイトを参考に、シンプルで良いのでなんらかの機能を持ったController
を実装する。
最終的に以下のようなイメージでController
が動作するところまで理解できれば良い。
Kubernetes関連プロジェクトでは主にe2eテストにてGinkgo
/Gomega
というテストフレームワークおよびenvtest
と呼ばれるパッケージ(テスト用にkube-apiserver
とetcd
を再現)がよく用いられる。
Contributionを行う際にはソースコード本体に加えテストコードの記載や修正を行う必要があるためこのステップで理解しておく。
全てのテストケースを網羅する必要はないので2.2
で作成したController
に対してテストコードを書いてみると良い。
Controller-Runtime
ではclient-go
を用いる場合と比較して低レイヤのロジックが抽象化されるため、抽象化された部分が具体的にどのように実装されているかをコードリーディングから理解する。
例としてkubebuilder
で初期化したプロジェクトのReconcile
メソッドがどのような流れで呼び出されるかを追ってみると良い。
Controller-Runtime
に関する理解が深まるのに加えコードリーディング自体にも慣れることができるため、Controller-Runtime
の利用方法を理解したこの時点で実施することを強く推奨。
※コードリーディングを行う際のポイントは3.6
参照。
最終的に以下のようなイメージでController
が起動しReconcile
が動作するところまで理解できれば良い。
kubernetes-sigs
や3rd-Party
として提供されるController
ではWebhook
の機能が合わせて提供されることが多いため、2.2
で作成したコントローラーに対してWebhook
を実装し、実装方法を理解しておくと良い。
※必要になったタイミングで補完するでも良い。
Contributionを行うモチベーションとしては大きく以下2つ。
- ① OSS利用上の課題/問題の解決
- 実際に業務等で特定のOSSを利用している中で発見した課題/問題に対してコードの修正を行う
- 具体的なユースケースに基づいたContributionが行える
- 自身で課題/問題の発見を行う必要がある
- ② OSS貢献という実績作り
- 既存で上がっているissueに対してコードの修正を行う
- Contributionという実績・経験が目的
- 課題/問題を自分で見つける必要がない
一般的に①の考え方は理想的である反面、自分で対応すべき課題/問題を見つける必要があり最初のContributionとしては難易度が高くなりがち。(もちろん課題/問題がすでに見つかっているようであれば最初から①で進めても良い)
②についてはContributionという行為自体が目的になってしまってはいるが、①と比較して着手しやすく将来的に①を目指す場合にも良いステップになるため、以降では初めてのContributionとして②を前提に解説する。
Kubernetes関連のプロジェクトにContributeする際には一定のルールがあるため以下にざっと目を通しておくと良い。
ただし読んで100%理解しようとすると難しいので詳細は必要になった時に都度参照するのが良い。
CLA(The Contributor License Agreement)についてはPRを出す際に必須となるためここでサインアップしておく。
また、各種イベント開催に伴いUpstream Trainingが開催されることもあり、一度参加しておくとContributionの大まかな流れが掴みやすい。
タイミングが合えば参加しておくと良い。
Contributionを行うにあたりターゲットとするプロジェクトを選択する。
あらかじめターゲットが定まっていれば良いが、定まっていない場合は以下の観点を参考にすると良い。
ターゲット選定時の観点
- プロジェクトがアクティブであること
- 非アクティブなブロジェクトだとPRを出しても対応してもらえない可能性がある
- 数ヶ月以内にCommitが行われているか
- 数ヶ月以内にissueやPRの更新があるか
- 複数のPRが長期間確認待ちで止まっていないか
- 非アクティブなブロジェクトだとPRを出しても対応してもらえない可能性がある
- 競争相手(=アクティブなContributor)が多すぎないか
- 競争相手が多すぎると良いissueを担当できない可能性がある
- assignされていないissueがあるか
- Contributor数はどの程度か
- 競争相手が多すぎると良いissueを担当できない可能性がある
- プロジェクトの利用イメージが持てること
- 得体の知れないプロジェクトに対するContributionは難しい
- プロジェクトのREADMEなどを見てなんとなくどんなプロジェクトか理解できるか
- 利用したことがあるプロジェクトだとベター
- 得体の知れないプロジェクトに対するContributionは難しい
- issueを見た時に問題のイメージの湧くものがあるか
- 現在上がっているissueからターゲットを決めてコード修正を行うことになる
- 挙がっているissueを眺めてみてなんとなくイメージが湧くか
- イメージが湧かなそうであれば難易度が高すぎる可能性もあるため他のプロジェクトを選ぶことも検討する
- 現在上がっているissueからターゲットを決めてコード修正を行うことになる
- 実装イメージが持てるか
- 実装イメージがなんとなくでもあるとコードリーディングがとてもスムーズ
- なんとなくで良いので「この辺りで
Reconcile
を行っていそう」などイメージが持てるか
- なんとなくで良いので「この辺りで
- 実装イメージがなんとなくでもあるとコードリーディングがとてもスムーズ
Controller-Runtime
を用いて実装されているプロジェクト- ここまでの流れを追っていると
Controller-Runtime
を用いて実装されたプロジェクトは比較的実装を読み解きやすいはず
- ここまでの流れを追っていると
ターゲットを決めたらまずは実際に動かして基本動作を確認する。
Quick Start等がプロジェクトのdocs
に含まれているケースが多いのでそれらを参照しながら進める。
また、動作確認はログを見ながら行うと実装イメージがつきやすい。
3.3
のステップを経てissue一覧を確認し、対応できそうなものをターゲットとして選択する。
issueを選択したら実際に問題となっている事象を再現させてみて問題を具体的に理解する。
- バグ修正から手をつける
- バグ修正は比較的部分的なコード修正で完結できる可能性が高い
- issueはバグ報告以外のものもあるため
kind/bug
といったラベルを参考にすると良い
- 再現手順やあるべき姿が明確に示されている(もしくは読み取れる)ものを選ぶ
対象プロジェクトのソースコードをローカルにcloneしたらビルドする手順を確認し、実際に動作させてみる。
実際にコードを修正した後の動作確認はソースコードをビルドしてから行うことになるのに加え、デバッグにも役立つためこのステップでやり方を押さえておくと良い。
ローカルにcloneしたソースコードを読み進める。
- メインの機能を中心に読み進める
- ターゲットのissueに関する流れを追う
主な目的はメイン機能や特定のissueについてコードの流れを追うことでありコードを隅々まで理解することではない。
最終的にコードを読むことは必要だが、全てをコードだけから理解しようとしなくても良い。
- 深追いしすぎない
- 目的を果たす上で全てのロジックを完全に理解する必要はない
- メソッドの中でメソッドが呼ばれて・・・を追い続けているとキリがないため、ある程度何をやってるか掴めたところで止める
- よく分からないところは飛ばして必要になったら改めて理解するというのも手
- 既存のドキュメントを活用する
- 概念的な説明や機能についてはドキュメントに書いてある場合がある
- 「頑張ってコード読んだら実はドキュメントに書いてありました」はよくあること
- メジャーなコンポーネントについてはネット検索すると情報が得られる場合もある
- デバッグする
- ロジックがコードから追いきれなければ実際にプロジェクトのソースコードにデバッグコードを仕込んで動作させてみる
- デバッグの結果からコードのロジックを理解する
- 副次的効果としてプロジェクトコードに手を入れることへの抵抗が薄れる
- 仮説を立てる
- 既存の情報や出力されたログなどからなんとなくで良いので仮説を立ててコードを読む
- 仮説が間違っている可能性もあるがなんとなくの指針ができることでコードが読み進めやすくなる
- PoCコードを書く
- コードを読んでいて文法上よくわからない箇所があれば、その文法を用いたPoCコードを書いて動かしてみる
- 目的意識がある状態なのでGo言語の文法知識補完が行いやすい
- スクラップメモを残しながらコードを読む
- コードを読み進めて行くうちに全体の流れや現在地が分からなくなることがある
- 形式は問わないが読み進めた箇所までの流れを追えるようなメモを残しながらコードを読み進めると良い
- 余裕があればスクラップメモを元に
2.4
のようなフロー図を書いてみると全体を俯瞰出来てより理解が深まる
なんとなく修正の見込みが経ったら対象のissueに自分自身をアサインし(/assign
)、
コードを修正してプロジェクトにPRを出す。
修正に伴い気になることがあればissueのコメントで起票者に確認すると良い。
また、プロジェクト内でContributionガイドが提供されているケースも多いのでPRを出す際はそちらにも目を通しておく。
ここまでの流れを経験しているとController
以外のScheduler
やkubelet
と言ったコンポーネントについても既存知識をベースに読み進めることができるはず。
特に2.1
のsample-controller
で登場したClientset
,Informer
,EventHandler
,Queue
と言った知識はほぼそのまま流用できる。
(例)
ここまでの流れを終えると冒頭で設定した「Kubernetesおよび関連プロジェクトに対してContributionを開始できること。」というゴールは概ね達成できているはず。
以下参考リンクでは本ドキュメントで取り上げなかった観点についても触れられているので必要に応じて参照すること。
特に動画「OSSへの貢献をはじめたきっかけ、貢献で得たもの、やりたい人へのアドバイス」でも言われている
「最初の一歩」を踏み出すと後はどんどん先に進める傾向にある
という点は経験上間違いないので最初の1回は粘り強く取り組むと良い。