0%

Remote Debugging Go Code with Visual Studio Code

当了解一些大型项目的代码逻辑时,如kubernetes,跟着调试器跟踪代码学习,是很好的方式。当项目部署在远程环境时,在本机进行开发,很自然对Remote Debug有迫切需求,这也是和调试一般golang程序最主要的诉求区别点,本文将通过两个实际例子,来介绍如何Remote Debug。

dlv远程调试的原理

vscode支持丰富的插件,dlv插件可以帮助我们调试golang代码,基本使用方法详见 delve官网,以及我之前的一篇文档通过delve(dlv)调试golang程序。dlv远程调试的基本原理是,在服务端启动dlv server,客户端vscode去连接dlv server

远程调试的步骤

主要参考了Debugging Go code using VS Code,现将步骤整理如下:

环境安装

Local安装Golang

参考Golang官网安装步骤Getting Started

Local和Remote端安装dlv工具

1
2
3
4
go get -u github.com/go-delve/delve/cmd/dlv

验证dlv版本
dlv version

本地代码版本切换到和目标端一致

以一个服务uhost-scheduler为例, 线上和本地都保持为1.0.10版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@yg-man-uhost-set9-01 bin]# /data/uframework/uhost_server -v
option = a value =
option = i value = 0
option = s value =
option = v value = true
option = z value =

Version: 1.0.10
Git branch: from_pxu_bugfix
Git commit: 3f997fe
Git user.name patrick
Git user.email xusen_qi@163.com
Go version: go_version_go1.8.1_darwin/amd64
Build time: 2019-09-02T20:26:58+0800

##在Remote端启动dlv server
启动命令如下

1
2
3
dlv --listen=":50000" --headless=true --log --api-version=2 exec /data/uframework/uhost_server \
> -- --z=172.23.0.77:2181,172.23.0.78:2181,172.23.0.79:2181,172.23.0.80:2181,172.23.0.81:2181 \
> --a=uhost-scheduler --s=set9 --i=0

参数说明:

  • -l, –listen string Debugging server listen address. (default “127.0.0.1:0”)
  • –headless Run debug server only, in headless mode.
  • –log Enable debugging server logging.

更多参数说明详见dlv

在Local端的调试

dlv命令行的调试

访问dlv server的IP:Port,可以调试,类似于gdb

1
2
3
4
➜  ~ dlv connect 172.23.0.159:50000
Type 'help' for list of commands.
(dlv) break main.main
Breakpoint 1 set at 0x823deb for main.main() ./go/src/uhost-go/uhost_server.go:31

在VS Code里的调试

但命令行里,没有图形界面直观和方便,所以更推荐在VS Code里的调试

  1. 保持VS Code打开的代码,和Remote端的代码或二进制包一致
  2. 在本地主机中配置远程调试的参数,会在当前项目下的.vscode目录产生一个launch.json文件
  1. 配置Remote端的IP和Port
1
2
3
4
5
6
7
8
9
10
11
{
"name": "Remote uhost-scheduler",
"type": "go",
"request": "attach",
"mode": "remote",
"remotePath": "/Users/patrick.xu/go/src/uhost-go",
"port": 50000,
"host": "172.23.0.159",
"showLog": true,
"trace": "log"
}
  1. 运行Debug,可以像本地一样调试,如加断点、条件断点、单步调试等。

本地VS Code界面

Remote端页面

Remote-Debug-Go-Code-with-Visual-Studio-Code.md

条件断点

k8s scheduler的远程调试

k8s里有很多单独的服务,如kube-apiserver、kube-proxy、kube-scheduler等,每个都可以作为单独的调试代码。最近在看kube-scheduler的代码,所以这里以它为例。

High level Kubernetes architecture diagram showing a cluster with a master and two worker nodes
Source: https://x-team.com/blog/introduction-kubernetes-architecture

k8s环境的搭建

k8s环境通过kubeadm搭建在远程的4台虚机上,1台master和3台node,具体的搭建步骤见kubeadm部署single control-plane k8s集群

停止kube-scheduler服务

我们需要dlv拉起kube-scheduler服务,但是kubeadm部署的kube-scheduler被kill掉后
,会自动拉起来,占用10251的端口,影响调试。

这里对对配置文件改名,防止自动拉起kube-scheduler
mv /etc/kubernetes/scheduler.conf /etc/kubernetes/scheduler_191223.conf

dlv server

dlv server启动后,监听40000端口

1
2
3
4
5
dlv --listen=":40000" --headless=true --log --api-version=2 exec /data/k8s/kube-scheduler \
-- --authentication-kubeconfig=/etc/kubernetes/scheduler_191223.conf \
--authorization-kubeconfig=/etc/kubernetes/scheduler_191223.conf \
--bind-address=127.0.0.1 --kubeconfig=/etc/kubernetes/scheduler_191223.conf \
--leader-elect=true

注意:本地是从公网访问虚机的40000端口,如果防火墙有打开的话,要关掉。

本地调试kube-scheduler

与之前步骤一样

  1. 代码与线上一致;如果不一致,重新编译新的版本推到线上,重新拉起服务
1
2
3
4
5
6
7
8
9
10
➜  kube-scheduler git:(b3cbbae) ✗ pwd
/Users/patrick.xu/go/src/k8s.io/kubernetes/cmd/kube-scheduler
➜ kube-scheduler git:(b3cbbae) CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build
➜ kube-scheduler git:(b3cbbae) ✗ ll
total 106208
-rw-r--r-- 1 patrick.xu staff 1.1K Dec 11 20:11 BUILD
-rw-r--r-- 1 patrick.xu staff 144B Dec 11 20:11 OWNERS
drwxr-xr-x 7 patrick.xu staff 224B Dec 11 20:11 app
-rwxr-xr-x 1 patrick.xu staff 52M Dec 18 01:31 kube-scheduler
-rw-r--r-- 1 patrick.xu staff 1.3K Dec 11 20:11 scheduler.go
  1. 配置文件launch.json的内容
1
2
3
4
5
6
7
8
9
10
11
{
"name": "Remote k8s server",
"type": "go",
"request": "attach",
"showLog": true,
"mode": "remote",
"remotePath": "/Users/patrick.xu/go/src/k8s.io",
"port": 40000,
"host": "152.32.173.26",
"trace": "log"
}

3.运行Debug,这时可以像可以像本地一样调试,如加断点、单步调试等。

本地VS Code远程调试kube-scheduler界面

Remote端kube-scheduler输出,看到打断点和调试的日志

后面就是结合创建pod,去分析具体的调度逻辑了。

参考链接

  1. delve官网
  2. Debugging Go code using VS Code
  3. 使用vscode远程调试golang
  4. 通过delve(dlv)调试golang程序