Kubernetes调试环境搭建


K8s MacBook本地debug环境搭建

1. K8s集群部署

可以在本地通过https://github.com/flannel-io/flannel

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

查看系统pod运行情况

kubectl get pods -n kube-system

 部署测试服务,验证集群状态

[root@k8s-master kubernetes]# kubectl create deployment nginx --image=nginx
deployment.apps/nginx created
[root@k8s
-master kubernetes]# kubectl expose deployment nginx --port=80 --type=NodePort service/nginx exposed
[root@k8s
-master kubernetes]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.1.0.1 443/TCP 25h nginx NodePort 10.1.167.250 80:30700/TCP 25h [root@k8s-master kubernetes]# curl 10.1.167.250 <head> Welcome to nginx!

选装部署dashboard,dashboard其实对本地开发调试用处不大,可选择安装

安装dashboard:(https://github.com/kubernetes/dashboard)

2.调试环境(开发环境默认已安装)

我们使用Goland+delve进行远程调试

需要调试的组件运行的节点需要安装Go环境,注意Go版本和Kubernetes的对应关系,我们本次演示以当前最新版本1.23版本的kube-apiserver进行调试

1.23需要Go版本为1.17+

我们在kube-apiserver所在的节点192.168.1.121安装Go1.17.5

[root@k8s-master app]# wget https://go.dev/dl/go1.17.5.linux-amd64.tar.gz
[root@k8s-master app]# tar zxf go1.17.5.linux-amd64.tar.gz

# add env
[root@k8s-master app]# vim /etc/profile

#追加
#add go
export GOROOT=/app/go
export PATH=$PATH:$GOROOT/bin
export GOPATH=/root/go
export PATH=$PATH:$GOPATH/bin

[root@k8s-master app]# source /etc/profile

#验证版本
[root@k8s-master app]# go version
go version go1.17.5 linux/amd64

 安装delve

参考:https://github.com/go-delve/delve/tree/master/Documentation/installation

# Install the latest release:
$ go install github.com/go-delve/delve/cmd/dlv@latest

# Install at tree head:
$ go install github.com/go-delve/delve/cmd/dlv@master

# Install at a specific version or pseudo-version:
$ go install github.com/go-delve/delve/cmd/dlv@v1.7.3
$ go install github.com/go-delve/delve/cmd/dlv@v1.7.4-0.20211208103735-2f13672765fe

kubeadm创建的集群中的控制组件是static pod,所以我们只要把配置文件移动到别的目录,对应的static pod就会自己销毁,于是我们可以用移除配置文件的方式停止集群中的kube-apiserver

#进入kubeadm 默认的配置路径
[root@k8s-master ~]# cd /etc/kubernetes

#新建static pod配置备份目录
[root@k8s-master ~]# mkdir manifests-down
[root@k8s-master kubernetes]# mv ./manifests/kube-apiserver.yaml ./manifests
#看到apiserver组件对应的pod已经停止
[root@k8s-master kubernetes]# kubectl get po --all-namespaces

本地编译K8s源码,本地环境MacBook Pro为darwin,因此需要交叉编译出Linux amd64对应的apiserver二级制文件

参考编译命令:

make all GOGCFLAGS="-N -l" GOLDFLAGS=""

需要添加:GOLDFLAGS=""  不然无法支持远程调试,报错为:

could not launch process: could not open debug info
解决方案参考:https://github.com/kubernetes/kubernetes/issues/77527

编译好的目录结构如图所示:

把编译好的二进制文件上传至master机器192.168.1.121 

 scp ./_output/local/bin/linux/amd64/kube-apiserver root@192.168.1.121:/etc/kubernetes/mycode

从manifests-down/kube-apiserver.yaml 获取启动配置信息

cd manifests-down/kube-apiserver.yaml

配置示例:

apiVersion: v1
kind: Pod
metadata:
  annotations:
    kubeadm.kubernetes.io/kube-apiserver.advertise-address.endpoint: 192.168.1.121:6443
  creationTimestamp: null
  labels:
    component: kube-apiserver
    tier: control-plane
  name: kube-apiserver
  namespace: kube-system
spec:
  containers:
  - command:
    - kube-apiserver
    - --advertise-address=192.168.1.121
    - --allow-privileged=true
    - --authorization-mode=Node,RBAC
    - --client-ca-file=/etc/kubernetes/pki/ca.crt
    - --enable-admission-plugins=NodeRestriction
    - --enable-bootstrap-token-auth=true
    - --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt
    - --etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt
    - --etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key
    - --etcd-servers=https://127.0.0.1:2379
    - --kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt
    - --kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key
    - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
    - --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt
    - --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client.key
    - --requestheader-allowed-names=front-proxy-client
    - --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt
    - --requestheader-extra-headers-prefix=X-Remote-Extra-
    - --requestheader-group-headers=X-Remote-Group
    - --requestheader-username-headers=X-Remote-User
    - --secure-port=6443
    - --service-account-issuer=https://kubernetes.default.svc.cluster.local
    - --service-account-key-file=/etc/kubernetes/pki/sa.pub
    - --service-account-signing-key-file=/etc/kubernetes/pki/sa.key
    - --service-cluster-ip-range=10.1.0.0/16
    - --tls-cert-file=/etc/kubernetes/pki/apiserver.crt
    - --tls-private-key-file=/etc/kubernetes/pki/apiserver.key
    image: k8s.gcr.io/kube-apiserver:v1.23.1
    imagePullPolicy: IfNotPresent
    livenessProbe:
      failureThreshold: 8
      httpGet:
        host: 192.168.1.121
        path: /livez
        port: 6443
        scheme: HTTPS
      initialDelaySeconds: 10
      periodSeconds: 10
      timeoutSeconds: 15
    name: kube-apiserver
    readinessProbe:
      failureThreshold: 3
      httpGet:
        host: 192.168.1.121
        path: /readyz
        port: 6443
        scheme: HTTPS
      periodSeconds: 1
      timeoutSeconds: 15
    resources:
      requests:
        cpu: 250m
    startupProbe:
      failureThreshold: 24
      httpGet:
        host: 192.168.1.121
        path: /livez
        port: 6443
        scheme: HTTPS
      initialDelaySeconds: 10
      periodSeconds: 10
      timeoutSeconds: 15
    volumeMounts:
    - mountPath: /etc/ssl/certs
      name: ca-certs
      readOnly: true
    - mountPath: /etc/pki
      name: etc-pki
      readOnly: true
    - mountPath: /etc/kubernetes/pki
      name: k8s-certs
      readOnly: true
  hostNetwork: true
  priorityClassName: system-node-critical
  securityContext:
    seccompProfile:
      type: RuntimeDefault
  volumes:
  - hostPath:
      path: /etc/ssl/certs
      type: DirectoryOrCreate
    name: ca-certs
  - hostPath:
      path: /etc/pki
      type: DirectoryOrCreate
    name: etc-pki
  - hostPath:
      path: /etc/kubernetes/pki
      type: DirectoryOrCreate
    name: k8s-certs
status: {}

拼接后的启动命令,用默认的2345端口

dlv exec --listen=:2345 --headless=true --api-version=2 ./kube-apiserver -- --advertise-address=192.168.1.121 --allow-privileged=true --authorization-mode=Node,RBAC --client-ca-file=/etc/kubernetes/pki/ca.crt --enable-admission-plugins=NodeRestriction --enable-bootstrap-token-auth=true --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt --etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt --etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key --etcd-servers=https://127.0.0.1:2379 --kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt --kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client.key --requestheader-allowed-names=front-proxy-client --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt --requestheader-extra-headers-prefix=X-Remote-Extra- --requestheader-group-headers=X-Remote-Group --requestheader-username-headers=X-Remote-User --secure-port=6443 --service-account-issuer=https://kubernetes.default.svc.cluster.local --service-account-key-file=/etc/kubernetes/pki/sa.pub --service-account-signing-key-file=/etc/kubernetes/pki/sa.key --service-cluster-ip-range=10.1.0.0/16 --tls-cert-file=/etc/kubernetes/pki/apiserver.crt --tls-private-key-file=/etc/kubernetes/pki/apiserver.key

参数过长,可以写入一个启动脚本文件kube-apiserver-start.sh 保存起来方便使用

启动脚本:

chmod +x kube-apiserver-start.sh
./kube-apiserver-start.sh

切换到本地的Goland 添加远程调试参数

在apiserver的main方法 添加断点,启动debug,已经阻塞在断点处,开始进行远程debug