1.先决条件和环境选项
设置本文档中讨论的调试环境如下:
- 本机操作系统版本: Windows 10
- Kubernetes 集群:1.19.16
- Istio 服务网格:1.12.9
- kubectl
- Delve(Go 的调试器):1.7.1
- IntelliJ GoLand 作为 IDE
- k8s操作系统:CentOS 7.9
- docker:26.1.4
- golang:1.21.0
2.对pilot中的Dockerfile进行配置
Delve 是 Go 编程语言的官方调试器。Delve 易于调用和使用,并为 Go 提供简单、功能齐全的调试工具。要远程调试 istiod pod, 请务必对容器配置进行以下更改,以便它支持基于 Delve 的调试。
2.1 克隆istio仓库
# 克隆特定分支
git clone -b 1.12.9 https://github.com/istio/istio.git
# 进入istio目录
cd istio
# 切换分支
git checkout -b 1.12.9
2.2 配置Dockerfile文件
要将 Delve 二进制文件添加到 Docker 映像,并使用 delve 调试启动可执行文件,请对pilot/docker/Dockerfile.pilot
文件添加如下内容(加号是需要添加的内容,减号是需要删除的内容):
$ git diff pilot/docker/Dockerfile.pilot
@@ -7,6 +7,9 @@ ARG BASE_VERSION=latest
# The following section is used as base image if BASE_DISTRIBUTION=debug
FROM gcr.io/istio-release/base:${BASE_VERSION} as debug
+FROM gcr.io/istio-testing/build-tools:latest as build-env
+RUN go get github.com/go-delve/delve/cmd/dlv
+
# The following section is used as base image if BASE_DISTRIBUTION=distroless
FROM gcr.io/istio-release/distroless:${BASE_VERSION} as distroless
@@ -17,10 +20,13 @@ FROM ${BASE_DISTRIBUTION:-debug}
ARG TARGETARCH
COPY ${TARGETARCH:-amd64}/pilot-discovery /usr/local/bin/pilot-discovery
+COPY --from=build-env /gobin/dlv /usr/local/bin/dlv
+
# Copy templates for bootstrap generation.
COPY envoy_bootstrap.json /var/lib/istio/envoy/envoy_bootstrap_tmpl.json
COPY gcp_envoy_bootstrap.json /var/lib/istio/envoy/gcp_envoy_bootstrap_tmpl.json
USER 1337:1337
-
-ENTRYPOINT ["/usr/local/bin/pilot-discovery"]
+EXPOSE 40000
+ENTRYPOINT ["/usr/local/bin/dlv", "--continue", "--accept-multiclient", "--listen=:40000", "--check-go-version=false", "--headless=true", "--api-version=2", "--log=true", "--log-output=debugger,debuglineerr,gdbwire,lldbout,rpc", "exec", "/usr/local/bin/pilot-discovery", "--"]
2.3 生成docker镜像
使用以下命令从存储库根目录构建 Pilot 的调试镜像:
make DEBUG=1 docker.pilot
如果在构建镜像的过程中出现如下报错:
可以尝试在本地编译打包delve,然后复制进入镜像,具体操作如下:
2.3.1 克隆delve仓库
# 克隆特定分支(考虑到delve与go版本兼容问题,选择该版本分支)
git clone -b v1.7.1 https://github.com/go-delve/delve.git
# 进入delve目录
cd delve
# 切换分支
git checkout -b v1.7.1
2.3.2 编译delve
# 进入cmd/dlv/目录
cd cmd/dlv/
# 编译打包
go build -gcflags="all=-N -l" -o dlv .
2.3.3 复制dlv到istio特定目录
cp dlv ~/istio/out/linux_amd64/docker_build/docker.pilot/
2.3.4 修改Dockerfile.pilot文件
$ git diff pilot/docker/Dockerfile.pilot
@@ -17,10 +20,13 @@ FROM ${BASE_DISTRIBUTION:-debug}
ARG TARGETARCH
COPY ${TARGETARCH:-amd64}/pilot-discovery /usr/local/bin/pilot-discovery
+COPY dlv /usr/local/bin/dlv
+
# Copy templates for bootstrap generation.
COPY envoy_bootstrap.json /var/lib/istio/envoy/envoy_bootstrap_tmpl.json
COPY gcp_envoy_bootstrap.json /var/lib/istio/envoy/gcp_envoy_bootstrap_tmpl.json
USER 1337:1337
2.3.5 生成docker镜像
使用以下命令从存储库根目录构建 Pilot 的调试镜像:
make DEBUG=1 docker.pilot
最后生成的镜像如下:
2.4 在 Istio 部署中使用新构建的调试镜像
2.4.1 将镜像推送至指定仓库
这部分内容就不展开了,网上资料一大堆,可参考文章:自定义镜像如何推送至仓库
2.4.2 安装istio
这里使用 Istioctl 进行安装;
前往 Istio 发布版本页面下载适用于您的操作系统的安装文件, 或者自动下载并解压最新版本(Linux 或 macOS):
curl -L https://istio.io/downloadIstio | sh -
上述命令下载 Istio 的最新版本(以数字表示)。您可以在命令行中传递变量来下载特定版本或覆盖处理器架构。 例如,要下载适用于 x86_64 体系结构的 Istio 1.23.2,请运行:
curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.23.2 TARGET_ARCH=x86_64 sh -
转到 Istio 软件包目录。例如,如果软件包是 istio-1.23.2
:
cd istio-1.23.2
安装目录中包含:
samples/
中的示例应用程序bin/
目录中的istioctl
客户端二进制文件。
将 istioctl
客户端添加到您的 Path 中(Linux 或 macOS):
export PATH=$PWD/bin:$PATH
也可以写入到环境变量配置文件中:
#设置环境变量
echo 'export ISTIO_HOME=/usr/local/istio-1.14.1' >> /etc/profile
echo 'export PATH=$PATH:$ISTIO_HOME/bin' >> /etc/profile
#加载变量
source /etc/profile
用下面命令安装 Istio 默认配置档:
istioctl install
安装完成过后可以查看istiod容器:
kubectl get pods -n istio-system
2.4.3 修改istiod的部署配置
主要是修改镜像地址image
以及readOnlyRootFilesystem
,镜像地址修改为1.4.1节中上传的镜像地址,readOnlyRootFilesystem
修改为false
;
$ kubectl edit deployment istiod -n istio-system
...
`image: docker.io/0nefish/pilot:latest`
imagePullPolicy: Always
name: discovery
...
securityContext:
allowPrivilegeEscalation: true
capabilities:
drop:
- ALL
`readOnlyRootFilesystem: false`
runAsGroup: 1337
runAsNonRoot: true
runAsUser: 1337
...
更改后保存文件,k8s会自动拉取镜像替换原来的istiod容器;
通过检查日志,确保 istiod pod 已以调试模式启动;
$ kubectl get pods -n istio-system
NAME READY STATUS RESTARTS AGE
istio-egressgateway-8787466f6-pkn9b 1/1 Running 0 12d
istio-ingressgateway-7dc657bdfb-vcnw5 1/1 Running 0 12d
`istiod-7d46956dbb-77vtc` 1/1 Running 1 (6d3h ago) 6d21h
$
$ kubectl logs -n istio-system istiod-7d46956dbb-77vtc | head
2021-12-22T11:01:21Z warning layer=rpc Listening for remote connections (connections are not authenticated nor encrypted)
2021-12-22T11:01:21Z debug layer=rpc API server pid = 1
2021-12-22T11:01:21Z `info layer=debugger launching process with args: [/usr/local/bin/pilot-discovery discovery` --monitoringAddr=:15014 --log_output_level=default:info --domain cluster.local --keepaliveMaxServerConnectionAge 30m]
API server listening at: [::]:40000
2021-12-22T11:01:23Z debug layer=rpc serving JSON-RPC on new connection
2021-12-22T11:01:23Z debug layer=rpc <- RPCServer.SetApiVersion(api.SetAPIVersionIn{"APIVersion":2})
2021-12-22T11:01:23Z debug layer=rpc -> *api.SetAPIVersionOut{} error: ""
2021-12-22T11:01:23Z debug layer=rpc (async 2) <- RPCServer.Command(api.DebuggerCommand{"name":"continue","ReturnInfoLoadConfig":null})
2021-12-22T11:01:23Z debug layer=debugger continuing
3.转发调试端口
使用 Kubernetes 端口转发附加到 Kubernetes 集群中正在运行的 istiod pod 以进行调试。需要将主机端口转发到 delve 正在侦听的 pilot pod 40000 端口;
kubectl port-forward -n istio-system --address localhost deployment/istiod 40000:40000
localhost
替换为虚拟机IP地址。
4.使用IntelliJ GoLand远程调试 istiod
4.1 配置GoLand
单击 Run/Debug Configuration,然后单击“+”图标以添加新的 Go Remote Configuration。 根据 istiod pod 的运行位置指定正确的主机和端口,在当前情况下为 localhost 和 40000 的 40000 中;
4.2 启动 Debugger
在 IDE 中的代码中设置一个断点。断点将取决于要测试的功能和要调试的代码区域;
从 IDE 启动 Go Remote Debugger,如下图所示。如果端口转发工作正常,并且使用 Delve 调试配置正确构建容器,则 Debugger 将附加到 istiod 远程 pod;
4.3 命中侦听器断点
应用一些 Istio 配置。例如,可以从 bookinfo 应用程序
创建任何资源。现在,能够看到代码中的相应断点被命中,并且您可以根据需要单步调试代码。