Skip to main content

开发 Kubernetes debug 的几种手段

· 8 min read
Softwore Developer

我们在开发 Kubernetes 遇到最大的难题就是如何调试组件,因为它涉及到的组件较多,工作流程较长,如果是较小的代码改动,我们可以通过添加单元测试、E2E 等手段进行功能验证。

但是如果遇到较大功能的功能,还是需要进行测试,乃至于进行 debug,但是存在如下几个问题:

  • 通常开发都是基于最新代码开发的,就导致版本较新;那依赖的组件版本也需要比较高才行;比如开发 Kubelet , 那依赖的 kube-apiserver 版本就需要接近最新,具体可以看 kubernetes 官网的版本匹配文档。
  • Kubernetes 组件启动通常会依赖其它服务,以及集群配置,解决起来比较麻烦。
  • 使用 IDE 进行 debug 有难度,需要解决服务依赖问题。

下面从本人的开发 debug 经验中总结了常用的两种方式,一种是通过打印日志然后部署服务来分析执行逻辑、一种是直接通过 IDE 进行 DEBUG.

要开发一个 Kubernetes 的需求,通常需要有准备工作、实现需求和测试三个步骤;

准备工作

  1. 一台 Linux 服务器,最好是安装 Ubuntu22.04 的操作系统,或者根据需求来决定需要安装什么。资源最少 8 核 CPU 16G 的内存 150G 的磁盘。
  2. Linux 服务器机器安装好最新的 golang 版本,开通 ssh 端口,修改使其可以通过 root 进行远程登录。
  3. 部署一个最新的 Kubernetes 集群,最好使用二进制启动 k8s 的核心组件,这样便于调试;单节点足够。

安装 Kubernetes 集群

这里介绍一个工具 kubeasz , 可以快速的安装出一个 kubernetes 单机集群,并且以二进制的形式启动核心组件。

我们为什么不用 kubeadm 呢?因为它启动的核心 pod 的方式是通过 static 的形式启动的,这样就导致不能进行调试,而且需要编译镜像才能进行日志调试。

安装步骤:

$ export release=3.6.5
$ wget https://github.com/lengrongfu/kubeasz/releases/download/${release}/ezdown
$ chmod +x ./ezdown
$ ./ezdown -D
$ ./ezdown -S
$ docker exec -it kubeasz ezctl start-aio
$ source ~/.bashrc
$ kubectl version

实现需求

因为 Kubernetes 大多数都是在 Linux 上运行,很多逻辑需要 Linux 操作系统下才可以编辑,通常大家的本地开机都是 MacOS ,导致不能编写 Linux 相关的逻辑。

下面我以本人经常使用的两种方案来介绍,一种是在本地开发,一种是在远程开发。

本地开发 K8s

我们在本机上启动一个 Linux 操作系统的容器,或者是用 Multipass 来启动 Ubuntu 虚拟机.

Multipass 功能很强大,就是使用比较繁琐,之前小编也用过,但是后面发现启动一个容器也够用了,就一直沿用到现在。

构建一个包含环境的镜像,首先通过如下的 Dockerfile:

FROM ubuntu:22.04
RUN apt-get update
RUN apt-get install -y openssh-server
RUN sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
RUN sed -i 's/PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config
RUN echo 'root:123456' | chpasswd

RUN apt-get install -y git vim curl wget cmake
RUN apt install software-properties-common -y
RUN add-apt-repository ppa:longsleep/golang-backports
RUN apt update
RUN apt install golang-go -y
RUN /etc/init.d/ssh start

然后进行构建:

$ docker build -t golang-env:dev -f Dockerfile .

启动容器,并且把本地的 golang 目录挂载到容器目录中,这样避免修改的代码丢失:

$ docker run  -d -p 50024:22 -v /Users/{local}/goworspace/code/src:/root/go/src golang-env:dev /usr/sbin/sshd -D

然后继续参考远程开发 k8s 部分,用本地开发的好处是可以给 Docker 配置本地的代理、可以登录 Github Copilot 等插件。

远程开发 K8s

这里我们通过连接远程 Linux 服务器或者是本地的容器来构建一个开发环境。

  1. 首先需要下载一个 jetbrains ****家最新的任意一个编辑器,打开编辑器之后不要打开项目,在编辑器首页有一个 Remote Development 的菜单。

image.png

  1. 点击 SSH 进行创建 Project 和配置;这里填写用户名、主机地址和端口

image.png

  1. 连接之后点击 + 号添加项目

image.png

  1. 之后选择好 IDE version 和 项目目录,点击右下角的 Start IDE and Connect. 按钮即可。

image.png

成功之后将打开 Golang 编辑器的界面,和在本地开发一样;剩下的就是编写代码。

测试需求

这里我们以测试 Kubelet 为例来说明,使用 kubeaze 安装的 Kubernetes 集群核心组件都是使用 systemctl 启动的,所以我们测试的时候可以使其停止,然后启动自己修改代码的服务即可。

假如我们通过打印日志的方式来进行测试, 只需要把本地代码提价到服务器上即可。然后执行 make all 或者 make all WHAT=cmd/kubelet GOFLAGS=-v 只编译指定项目。

编译生成的二进制文件在 _output/bin/ 目录下,这个是网络上通常的说法,但是很奇怪我的编译后不再这个目录下,在 ~/go/bin 目录下,可以都找找看。

然后查看下编译后的版本信息 ~/go/bin/kubelet —version .

命令行测试

  1. 通过 ps 获取 kubelet 启动命令,需要先找到启动参数。
  2. 停止之前的 kubelet 服务 systemctl stop kubelet.service
  3. 使用编译后的二进制启动以及添加默认的参数。

IDE debug

  1. 通过 ps 获取 kubelet 启动命令,需要先找到启动参数。
  2. 停止之前的 kubelet 服务 systemctl stop kubelet.service
  3. 把启动参数填写进去即可进行 Debug.

image.png