kube-apiserverをデバッグ実行する
kube-apiserverの挙動を知るために、デバッガーでステップ実行しながら処理を追いかけたくなることがたまにあります。
今回はdelveを使ってkube-apiserverをデバッグ実行してみたいと思います。
まずは、kube-apiserverをビルドします。
一般に配布されているkube-apiserverはビルド時に最適化がおこなわれているため、デバッグ実行の際にソースコードとの対応付けができません。
そこで最適化を無効化してビルドする必要があります。
まずはKubernetesのソースコードを持ってきて、デバッグしたいバージョンのタグに切り替えます。
$ git clone git@github.com:kubernetes/kubernetes.git
$ cd kubernetes
$ git checkout v1.25.0
次にkube-apiserverをデバッグビルドします。
$ make WHAT=cmd/kube-apiserver DBG=1
ビルドしたバイナリのオプションを確認してみます
$ go version -m _output/local/go/bin/kube-apiserver
この中に-gcflags=" all=-N -l"
というオプションが含まれていればOKです。
次にetcdとkubectlを取得します。
今回はsetup-envtestというツールを使います。
$ go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest
$ setup-envtest use 1.25
Version: 1.25.0
OS/Arch: linux/amd64
Path: /home/zoetro/.local/share/kubebuilder-envtest/k8s/1.25.0-linux-amd64
適当なディレクトリを作って、そこにkube-apiserver, etcd, kubectlをコピーします。
$ mkdir ./bin
$ cp /home/zoetro/go/src/github.com/kubernetes/kubernetes/_output/local/go/bin/kube-apiserver
$ cp /home/zoetro/.local/share/kubebuilder-envtest/k8s/1.25.0-linux-amd64/etcd ./bin
$ cp /home/zoetro/.local/share/kubebuilder-envtest/k8s/1.25.0-linux-amd64/kubectl ./bin
次にKubernetesクラスタを立ち上げます。
Kubernetesクラスタを立ち上げる方法はいろいろありますが、今回は以下のツールを利用して、etcdとkube-apiserverだけをサクッと立ち上げます。
kube-apiserverやetcdを置いたディレクトリをKUBEBUILDER_ASSETS
という環境変数にセットします。
$ KUBEBUILDER_ASSETS=$(pwd)/bin
$ export KUBEBUILDER_ASSETS
kube-boatをインストールし、起動します。
$ go install github.com/hhiroshell/kube-boat@latest
$ kube-boat start
※ go installでインストールしたkube-boatが動かない場合があるので、その場合はgit cloneしたものをgo buildして使ってください。
次にdelveを使ってkube-apiserverにアタッチしてみます。
まずはdelveをインストールします。
$ go install github.com/go-delve/delve/cmd/dlv@latest
kube-apiserverのプロセスIDを確認します。
$ pgrep kube-apiserver
16802
アタッチしてみましょう。
$ dlv attach 16802
Type 'help' for list of commands.
(dlv)
ソースコードのパスを見てみます。
(dlv) sources apiserver.go
/home/zoetro/go/src/github.com/kubernetes/kubernetes/_output/local/go/src/k8s.io/kubernetes/cmd/kube-apiserver/apiserver.go
/home/zoetro/go/src/github.com/kubernetes/kubernetes/_output/local/go/src/k8s.io/kubernetes/pkg/registry/admissionregistration/rest/storage_apiserver.go
/home/zoetro/go/src/github.com/kubernetes/kubernetes/_output/local/go/src/k8s.io/kubernetes/vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/apiserver.go
/home/zoetro/go/src/github.com/kubernetes/kubernetes/_output/local/go/src/k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/server/genericapiserver.go
/home/zoetro/go/src/github.com/kubernetes/kubernetes/_output/local/go/src/k8s.io/kubernetes/vendor/k8s.io/kube-aggregator/pkg/apiserver/apiserver.go
delveを終了します。
(dlv) exit
Would you like to kill the process? [Y/n] n
次にVS Codeでデバッグ実行してみます。
VS Codeには、Go Pluginのインストールが必要です。
VS Codeのメニューから「Run」→「Start Debugging」を選択します。
サイドバーのTo customize Run and Debug create a launch.json file
のをクリックします。
Go: Attach to local process
を選択し、launch.jsonのprocessIdにkube-apiserverのプロセスIDを設定します。
{
"version": "0.2.0",
"configurations": [
{
"name": "Attach to Process",
"type": "go",
"request": "attach",
"mode": "local",
"processId": 16802
}
]
}
Attachボタンを押してkube-apiserverにアタッチします。
次にVS CodeでKubernetesのソースコードを開き、ブレイクポイントを張ります。
このとき、./_output/local/go/src/k8s.io/kubernetes/
の下にあるソースを開いてください。
例えば、リソースの作成時に呼び出されるハンドラ関数にブレイクポイントを張りたいのであれば以下のファイルを開きます。
kubernetes/_output/local/go/src/k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/endpoints/handlers/create.go
そして適当にPodをつくってみます。
$ kube-boat kubeconfig
$ kubectl run ubuntu --image=ubuntu:20.04
こんな感じで、実行中の変数の内容を確認したり、ステップ実行できれば成功です。