はじめに
これまでの連載を通して「なぜ(第1回)」「どのように(第2回)」「どこ(第3回)」にコントリビューションするのかをご理解いただけたかと思います。
今回は「Kubernetesの開発環境の構築」をテーマに、Kubernetes本体に関する開発をしたい方が、具体的にどのように開発環境を構築し、プルリクエストを投げる中身を作る準備をするのかについて解説します。「開発」にフォーカスして、「どのように」の中身を一段掘り下げた内容となっています。
なお、本稿では「開発環境構築方法」「ビルド方法」「テスト方法」の3点について、はまりポイントを避けながら進められるように、できるだけ丁寧に順番に解説していきます。ぜひお手すきの際に実機で試していただければと思います。
開発環境の構築方法
バグフィクスにせよ、機能追加にせよ、コードを変更するようなプルリクエストを投げる前には、実際に動かして動作を確認する必要があります。その際に必要となる環境について「前提」「実現方法の候補とおすすめ」「具体的な構築手順」の順に解説します。
前提
やりたいこと、揃えられるマシンリソース、好みのOSやコンテナランタイム・ディストリビューションなど、人それぞれ背景があると思います。ここでは必須なことと、問題が起こりにくい組み合わせを考慮して、前提となる環境についての情報を共有します。
おすすめの開発環境
2026年1月時点では、x86_64アーキテクチャ上のLinux上でDockerを動かす環境を整えるのが一番問題が起こりにくいため、おすすめです。昔に比べてARM等の他のアーキテクチャへの対応やDocker以外のコンテナランタイムへの対応は進んできていますが、細かいツールの対応の有無やオプションの指定が必要など、おすすめの組み合わせから外れるほど、はまる可能性が高くなります。
そのため、とりあえずワンパスはクラウド上のマシンでも良いので、おすすめの構成で一連の流れを動かした経験を持った上で、少し異なる環境に変えるにはどうすれば良いかを考えながらトライしていくと良いでしょう。
クラウド利用以外の構成のヒントとして、x86_64系のWindowsやMacをお使いの方はデュアルブートできるようにしてLinux環境を整える、(VirtualBox等の)仮想マシンとしてLinuxのゲストを立ち上げる、WSLを使う(Windowsの場合)などが選択肢になると思います。ARM系のMacの方はcolimaなどを使って頑張れる範囲は増えていますが、少し苦労するのを覚悟して取り組む必要があると思います(著者もワンパスは動かした実績はありますが、ドキュメントが充実していない印象です。逆に言うと情報を充実させることでコントリビューションできる領域かもしれません)。
ちなみに、著者はKubernetesでupstreamの開発・動作確認をする際に、x86_64上のLinuxまたはWindows上の仮想マシンとしてLinuxを動かす構成か、クラウド上でLinuxを動かす構成をメインに使っています。また、仕事の事情でRHEL系のディストリビューション(Fedora/CentOS/ RHEL等)上でDockerかPodmanを使う構成をとることが多いです。一方で、upstreamの開発においてはUbuntu系の最新版でDockerを使っている方が多い印象なので、この組み合わせの方が問題を踏みにくいかもしれないです。
必要なマシンのスペック
開発環境に求められる最低スペックは、公式の開発向けのドキュメントに記載のある通り、メモリが8GB以上、ディスクの空き領域が50GB以上となっています。やりたいこと次第で追加のリソースが必要となる可能性があるため、余力があればスペックは高めのものを確保しておくと良いです。なお、頻繁にビルドする方は、ビルド時にディスクの書き込みが大量に走るので高速なディスクがおすすめです。
あらかじめ用意しておくべきもの
ここまでの解説に従って用意したマシンとOSにあらかじめ入れておくべき物は「Go言語」「ビルド用のパッケージ」「コンテナランタイム」「kubectl」「Kubernetesのソースコード」の5点です。それぞれ、少し補足しておきます。
- Go言語: 要求されているGoのバージョンは、公式ドキュメントに記載の通り.go-versionのものです(最新版以外をビルドする場合、ビルド対象のブランチのものを確認してください)。細かいバージョン指定があるため、ディストリビューション提供のものでなくGoの公式で提供するパッケージを利用する形になると思います。
- ビルド用のパッケージ: Debian/Ubuntu系のbuild-essentialやRHEL系の“Development Tools”等が必要になります(詳細は公式ドキュメント参照)。
- コンテナランタイム: こだわりが無ければ、素直にDockerを入れるのが良いです。他を使う場合は調査して対応するようにしてください。
- Kubectl: ドキュメントをしっかり辿って読んでいくと「必要」という結論になりますが、とりあえず公式サイト等から入手してインストールしておいてください。
- Kubernetesのソースコード: githubのKubernetes/Kubernetesのレポジトリ(k/k)のソースコードをcloneして入手してください。直接クローンしても良いのですが、今後コントリビューションしていくことを考えると、第2回を参考に自分のレポジトリにforkしたものをk/kでも作っておき、これを対象に進めるのがおすすめです。
実現方法の候補とおすすめ
何を使ってデプロイするかは、やりたいことや好みによって大きく分かれるところだと思います。既存のデプロイツールと特徴を整理すると、下表のようになります。
| ツール名 | ビルドしてデプロイ | 複数ノードにデプロイ | デプロイ先デバイスの直接操作 | 備考 |
|---|---|---|---|---|
| local-up-cluster.sh | ☑️ | ☑️ | バイナリがホストで直接動作 | |
| kind | ☑️ | ☑️ | nodeはコンテナとして動作 | |
| minikube | ☑️ | △ | nodeはコンテナとして動作 ※VM、ホスト直でも可 | |
| kubeadm | ☑️ | ☑️ | ||
| kubespray | ☑️ | ☑️ |
開発の対象が本体ではなく周辺ツールで、リリース後のバージョンの利用で良ければ、minikube、kubeadm、kubespray等、普段から利用しているツールを使う方針で良いと思います。一方、リリース前の機能を試したり、Kubernetes本体の開発用途で使う場合など、ソースからビルドしてデプロイするケースでは「local-up-cluster.sh」か「kind」の2つが候補となります。
この2つを比較すると、local-up-cluster.shはバイナリがホストで直接動作するためノードのデバイスやOSは直接見えていますが、単一ノードでしか動作させられません。一方、kindはnode自体がコンテナとして動作するため複数ノードで動かせますが、デプロイ先のデバイスやOSを直接操作できない制約があります。それぞれ、メリット・デメリットがあるので、用途に応じて取捨選択して使うと良いでしょう。
また、コンテナでない複数ノードを扱うことが求められるパターン(例: graceful node shutdown(systemdを操作する必要がある)等の機能の挙動の確認)は、local-up-cluster.shやkindでは対応できません。そのような場合は、別途ビルドしたバイナリ・コンテナイメージを他のデプロイツールで構築した環境に持っていくなどの対応が必要になります。
具体的な構築手順
具体的な構築手順として「local-up-cluster.shを使った手順」と「kindを使った手順」のそれぞれを解説します。用途に応じてお好みで選んで、ぜひ試してみてください。
local-up-cluster.shを使った構築手順
Kubernetes本体のレポジトリに開発向けのスクリプトがあるので、追加でツールをインストールせずにKubernetesのクラスタ(単一ノード)をビルドすれば立ち上げることができます(公式な手順のドキュメントはこちら)。
Kubernetesのレポジトリをクローンしてきたディレクトリで初回の実行時に下記のコマンドを実行し、etcdをインストールしてパスを通しておくと(必要に応じてPATHの設定は永続化してください)、
$ sudo PATH=$PATH hack/install-etcd.sh
$ export PATH=$(pwd)/third_party/etcd:$PATH2回目以降の実行は下記のコマンドを実行するだけで、Kubernetesのクラスタが立ち上がります。$ sudo PATH=$PATH hack/local-up-cluster.shコマンドを実行したターミナルにフォアグラウンドで起動するので、停止するには[Ctrl]キー+[C]キーを押してください。kubectlなどによるクラスタの操作は別のターミナルから行います。
ちなみに、起動後の画面に出てくるメッセージの通り、KUBECONFIGのファイルは“/var/run/kubernetes/admin.kubeconfig”にあるのと、ビルドしたkubectlを使うには“./cluster/kubectl.sh”を使う必要がある(kubectlのコードを変更してなく、評価の対象でないならインストール済みのkubectlを使っても良い)点などは注意してください。
kindを使った構築手順
kindを使った方法では、まずkindのインストールが必要になります。 kindの公式ドキュメントの手順に従ってインストールをしてください。入れるものはこれだけで、ビルドもコンテナの中で行われるためで、実行環境側にgoもmakeなどのツールも入れる必要はありません(ただし、周辺コンポーネント等のビルドでいずれ必要になると想定されるので、前述の「あらかじめ用意しておくべきもの」では入れるように記述しています)。
ビルドしないでクラスタを起動するには、下記のコマンドを実行します。
$ kind create cluster停止するには下記のコマンドを実行します。非常に簡単ですね。
$ kind delete clusterそして、今回の本題となるビルドしてデプロイするには、下記のコマンドを実行します(この例ではカレントディレクトリにソースがある前提で、ソースのパスを“.”で指定しています)。
$ kind build node-image .
$ kind create cluster --image kindest/node:latestなお、kubectlはホストにインストールされているものを利用しており、ビルド・デプロイされていない点に注意してください。kubectlを変更・ビルドして試したい場合は、後述のビルド手順等を参考に別途対応してください。
【補足】自分のソースからビルドして動いていることの確認方法
ここまで読んでいただいた方の中には、自前でビルドしたKubernetesを動かすことに成功して、ある程度の達成感を得ている方もいると思います。しかし、ビルド済みのものを動かしたときと挙動が同じだと不完全燃焼で、次に何をしたら良いか迷っているかもしれません。そんな方のために、いわゆるprintf()デバッグ的なことをする方法も補足しておきます。
おすすめの手を入れる箇所は、ノードを起動したら必ず通るkubeletのコードです。例えば、下記の変更を加えると(何を変えたか曖昧な方はgit diffして差分を確認してください)、
$ sed -i 's|Starting kubelet main sync loop|Starting my cool kubelet main sync loop|' pkg/kubelet/kubelet.go例えば、kindでクラスタを起動したときのkubeletのログが、改変前のFeb 27 09:28:09 kind-control-plane kubelet[179]: I0227 09:28:09.386775 179 kubelet.go:2324] "Starting kubelet main sync loop"から、改変後のFeb 27 09:45:58 kind-control-plane kubelet[179]: I0227 09:45:58.668145 179 kubelet.go:2324] "Starting my cool kubelet main sync loop"に変わることを確認できます。一度、ここまで辿り着いた経験があれば、試したいリリース前の機能を最新版のコードから持ってきて動かしてみることも、自分がバグを踏んだ挙動をデバッグ・修正してみることも、できそうな気がしてきますよね。このように1歩ずつ経験値を増やしていくと、最後はきっと自分が本当にやりたいことを自由に実現できるようになるはずです。ぜひ、頑張ってみてください!
ビルド方法
ここまで「実現方法の候補とおすすめ」でlocal-up-cluster.shでもkindでも挙動が確認できないケースがあることや、「kindを使った構築手順」でkubectlについてはビルドされないことを解説しました。そのようなケースでは別途ビルドが必要となるため、ビルド方法についても解説しておきます。
ビルドの細かい話はdevelopment.mdとbuildのREADMEを確認すると良いのですが、細かいバイナリ単位でターゲットを指定してビルドする場合はmakeに“WHAT=”の引数をつけて実行、特定のアーキテクチャ向けの全体(コンテナイメージ・バイナリ)をビルドする場合は“make quick-release”を実行する考え方が基本になります。
そのため、例えばコンテナイメージ、kubeletのバイナリなどを差し替えてテストするためのビルドは、下記のコマンドを実行するのが良く、$ make quick-releaseまた、kubectlだけビルドしたい場合は、下記のコマンドを実行すれば良いです。$ make WHAT=cmd/kubectlテスト方法
Kubernetesはプルリクエストが来るたびにCIのシステムで自動にテストが行われており、テストが通らないとプルリクエストはマージされません。また、機能がBetaに昇格するためにはE2Eテストの追加と実行が求められ、実際にビルドしたクラスタ上で当該機能を呼び出して実行し、正しく動作することを確認しています。
そのため、他の人が作成した新しい機能を試すときはどのようなテストが追加されているかを参考にしたり、試したりするのが理解の近道です。また、自分が欲しい機能を追加する場合は必ずテストの作成が求められるため、機能を追加するにはテストの作成・実行スキルが必要になります(特にコードフリーズ直前はCIシステムが混み合い、実行されるまでに時間がかかる上にテストが失敗する度にメンテナーにも通知が飛ぶので、自分の変更差分に対するテストをローカルで実行して通ることを確認したものをプルリクエストできるようにしておくことが時短観点・心象の観点の両方から必須となります)。
さらに、他の人が開発中の機能の昇格がしばらく滞っている場合、テスト追加(特にE2Eテスト)がネックな可能性が高いです。自分が必要な機能であれば、昇格を加速するためにテストの追加を支援するなどは、コミュニティから歓迎されるコントリビューション候補の1つになります。
以降では、Kubernetesで定義されている4種類のテスト(「Unitテスト」「Integrationテスト」「E2Eテスト」「Conformanceテスト」)について、概要と動かし方を解説します。
Unitテスト
いわゆるgoのunitテストで、コードと同じディレクトリの*_test.goとして配置されています。実行方法もgoのunitテストのお作法通りになっており、テストファイルのあるディレクトリに移動して、下記のコマンドを実行します。
$ go test ./...Integrationテスト
パッケージやコンポーネントの組み合せを確認するテストです。インテグレーションテストのコードはkubernetes/test/integrationディレクトリの配下に存在します。
実行するには、下記のようにetcdをインストールした上で、make test-integrationを実行します。
$ hack/install-etcd.sh
$ make test-integrationE2Eテスト
システム全体の動作を確認するためのテストです。実際にKubernetesクラスタを起動した上でAPIを叩いて実際の処理を動かし、正しく動作していることを確認します。E2Eテストのコードはkubernetes/test/e2eディレクトリの配下に存在します。「ginkgo」というテストフレームワークで作成されており、正規表現を用いてfocusやskipを指定して特定のテストだけ実行できます。
実行するには、下記のようにkubetest2を使う方法と、hack以下のスクリプトを使う方法の2通りがあります。いずれも“--focus-regex”や“--ginkgo.focus”のような引数で正規表現で実行するテストを制限できるのがポイントで、自分で作成したテストや変更した差分が影響しそうなテスト、自分の興味の対象のテストに限定してローカル環境で試すことができます。開発観点だと、プルリクエストを投げてCIでテスト実行する前に自分のコードの正しさを確認できます。
Kubetest2を使う方法
初回のみ、下記のコマンドでkubetest2をインストールしておきます。
$ go install sigs.k8s.io/kubetest2/...@latest下記のコマンドで、すでに起動しているクラスタにテストを実行します(第2引数でnoopを指定)。
$ kubetest2 noop --test=ginkgo -- --focus-regex='Secrets'Hack以下のスクリプトを使う方法
下記のコマンドで、E2Eテストのコードとginkgoをビルドしておきます。
$ make all WHAT=test/e2e/e2e.test
$ make WHAT=ginkgo下記のコマンドで、すでに起動しているクラスタにテストを実行します(KUBERNETES_PROVIDERでlocalを指定)。
$ KUBERNETES_PROVIDER=local ./hack/ginkgo-e2e.sh --ginkgo.focus='Secrets should be able to mount in a volume'Conformanceテスト(適合性試験)
このテストはe2eテストのサブセットになっており、SIGアーキテクチャで承認されています。このテストをパスするものだけがKubernetesの認証を得ることができます。これにより、Kubernetesのクラウドプロバイダ間・ディストリビューション間の互換性が保証されています。
Conformanceテストは、キーワードとしてテスト名に [Conformance] というラベルが付けられています。E2Eテストを実行する際に [Conformance] と指定して実行するテストを絞り込むことでConformanceテストを実行できます。
まとめ
今回はKubernetesの開発環境を構築する方法を解説しました。「開発環境の構築方法」「ビルド方法」「テスト方法」の3点について、具体的な手順と参照先のドキュメントを示しながら解説しています。
この記事を通して、1人でも多くの人がKubernetesのコード開発に必要な知識を実際に手を動かすことで習得し、1つでも多くのプルリクエストを投げられ、Kubernetesのコミュニティが活性化されることに繋がればと思います。
次回は「kubernetes.io 和訳貢献」と題してお送りする予定です。お楽しみに!
- この記事のキーワード
