1.why
kubernetes是使用go語言編寫的竹祷,對于很多同學(xué)來說介蛉,可能對這種語言機制不甚熟悉。掌握調(diào)試方法溶褪,一方面能夠精準(zhǔn)定位問題,另一方面對學(xué)習(xí)相關(guān)語言也有反向促進機制践险。摩刀不誤砍柴功猿妈。只要有源碼吹菱,任何問題都是可以解決的,剩下的只是時間問題彭则。
2.準(zhǔn)備工作
- 安裝delve
delve是目前最方便用于調(diào)試golang的工具鳍刷,安裝delve有兩種方法:
- 使用go命令:
go get -u github.com/derekparker/delve/cmd/dlv
- 使用源碼
https://github.com/derekparker/delve
make install
2.編譯kubernetes組件
- 通過make help查看如何編譯帶調(diào)試信息的kubernetes組件
[newcent@localhost kubernetes-1.9.2]$ make help
--------------------------------------------------------------------------------
all
# Build code.
#
# Args:
# WHAT: Directory names to build. If any of these directories has a 'main'
# package, the build will produce executable files under _output/go/bin.
# If not specified, "everything" will be built.
# GOFLAGS: Extra flags to pass to 'go' when building.
# GOLDFLAGS: Extra linking flags passed to 'go' when building.
# GOGCFLAGS: Additional go compile flags passed to 'go' when building.
#
# Example:
# make
# make all
# make all WHAT=cmd/kubelet GOFLAGS=-v
# make all GOGCFLAGS="-N -l"
# Note: Use the -N -l options to disable compiler optimizations an inlining.
# Using these build options allows you to subsequently use source
# debugging tools like delve.
---------------------------------------------------------------------------------
......
- 使用make all GOGCFLAGS="-N -l"編譯kubernetes組件
3.調(diào)試kubelet
- 將編譯kubelet拷貝到相應(yīng)的node上
- 在node上通過dlv啟動kubelet
dlv exec ./kubelet --headless -l 192.168.122.12:1234 -- --logtostderr=true --v=0 --allow-privileged=false --address=0.0.0.0 --hostname-override=node1 --pod-infra-container-image=gcr.io/google_ctainers/pause-amd64:3.0 --kubeconfig=/etc/kubernetes/kubelet.kubeconfig --cgroup-driver=systemd
--headless -l 192.168.122.12:1234指定啟動一個調(diào)試server端,因為編譯kubernetes組件往往不會在node上編譯俯抖,node上也沒有相應(yīng)的源碼输瓜,通過這一機制,可以在編譯節(jié)點上啟動dlv client芬萍,調(diào)試相關(guān)代碼尤揣。
- 在編譯節(jié)點上連接server端
[newcent@localhost kubernetes-1.9.2]$ dlv connect 192.168.122.12:1234
Type 'help' for list of commands.
(dlv) b main.main
Breakpoint 1 set at 0x394496b for main.main() ./_output/local/go/src/k8s.io/kubernetes/cmd/kubelet/kubelet.go:44
(dlv) c
> main.main() ./_output/local/go/src/k8s.io/kubernetes/cmd/kubelet/kubelet.go:44 (hits goroutine(1):1 total:1) (PC: 0x394496b)
Warning: debugging optimized function
Warning: listing may not match stale executable
39: func die(err error) {
40: fmt.Fprintf(os.Stderr, "error: %v\n", err)
41: os.Exit(1)
42: }
43:
=> 44: func main() {
45: // construct KubeletFlags object and register command line flags mapping
46: kubeletFlags := options.NewKubeletFlags()
47: kubeletFlags.AddFlags(pflag.CommandLine)
48:
49: fmt.Printf("args: %s\n", os.Args[0])
(dlv)
4.delve使用方法(附)
命令 | 描述 |
---|---|
args | 打印函數(shù)參數(shù) |
break | 設(shè)置斷點 |
brekpoints | 打印活躍斷點 |
clear | 刪除斷點 |
check? | 在當(dāng)前位置創(chuàng)建一個檢查點 |
checkpoints | 打印存在的檢查點 |
clear-checkpoint | 刪除檢查點 |
clearall | 刪除多個斷點 |
condition | 設(shè)置條件斷點 |
config柬祠? | 改變配置參數(shù) |
continue | 繼續(xù)執(zhí)行 |
disassemble | 反匯編器 |
exit | 退出調(diào)式 |
frame北戏? | 在不同的幀上執(zhí)行命令 |
funcs | 打印函數(shù)列表 |
goroutine | 展示當(dāng)前協(xié)程 |
help | 打印幫助文檔 |
list | 展示源代碼 |
locals | 打印局部變量 |
next | 跳到下一行源代碼 |
on? | 當(dāng)斷點被命中后執(zhí)行一個命令 |
打印表達式 | |
regs | 打印CPU寄存器內(nèi)容 |
restart | 從checkpoint或事件開始重啟進程 |
rewind漫蛔? | 回退知道斷點或程序終止 |
set | 改變一個變量的值 |
source | 執(zhí)行一個包含delve命令列表的文件 |
stack | 打印調(diào)用棧 |
step | 單步執(zhí)行 |
step-instruction | 單個CPU指令執(zhí)行 |
stepout | 跳出當(dāng)前函數(shù) |
thread | 切換至某個具體的函數(shù) |
threads | 打印每一個所跟蹤的線程信息 |
trace | 設(shè)置一個跟蹤點 |
types | 打出類型列表 |
vars嗜愈? | 打印封裝變量 |