Closed8

kube-apiserverをデバッグ実行する

zoetrozoetro

kube-apiserverの挙動を知るために、デバッガーでステップ実行しながら処理を追いかけたくなることがたまにあります。
今回はdelveを使ってkube-apiserverをデバッグ実行してみたいと思います。

zoetrozoetro

まずは、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です。

zoetrozoetro

次に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
zoetrozoetro

適当なディレクトリを作って、そこに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
zoetrozoetro

次にKubernetesクラスタを立ち上げます。
Kubernetesクラスタを立ち上げる方法はいろいろありますが、今回は以下のツールを利用して、etcdとkube-apiserverだけをサクッと立ち上げます。

https://github.com/hhiroshell/boat

zoetrozoetro

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して使ってください。

zoetrozoetro

次に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
zoetrozoetro

次にVS Codeでデバッグ実行してみます。

VS Codeには、Go Pluginのインストールが必要です。
https://marketplace.visualstudio.com/items?itemName=golang.Go

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

こんな感じで、実行中の変数の内容を確認したり、ステップ実行できれば成功です。

このスクラップは2022/10/07にクローズされました