之前有很多同学提到如何做容器调试,特别是k8s环境下的容器调试,今天就讲讲我是如何调试的。大家都知道在vs自带的创建项目模板里勾选docker即可通过F5启动docker容器调试。但是对于启动在k8s则不是那么清楚。其实两者原理上是一样的。
目录:
一、通过Dapr实现一个简单的基于.net的微服务电商系统
二、通过Dapr实现一个简单的基于.net的微服务电商系统(二)——通讯框架讲解
三、通过Dapr实现一个简单的基于.net的微服务电商系统(三)——一步一步教你如何撸Dapr
四、通过Dapr实现一个简单的基于.net的微服务电商系统(四)——一步一步教你如何撸Dapr之订阅发布
五、通过Dapr实现一个简单的基于.net的微服务电商系统(五)——一步一步教你如何撸Dapr之状态管理
六、通过Dapr实现一个简单的基于.net的微服务电商系统(六)——一步一步教你如何撸Dapr之Actor服务
七、通过Dapr实现一个简单的基于.net的微服务电商系统(七)——一步一步教你如何撸Dapr之服务限流
八、通过Dapr实现一个简单的基于.net的微服务电商系统(八)——一步一步教你如何撸Dapr之链路追踪
九、通过Dapr实现一个简单的基于.net的微服务电商系统(九)——一步一步教你如何撸Dapr之OAuth2授权 && 百度版Oauth2
十、通过Dapr实现一个简单的基于.net的微服务电商系统(十)——一步一步教你如何撸Dapr之绑定
十一、通过Dapr实现一个简单的基于.net的微服务电商系统(十一)——一步一步教你如何撸Dapr之自动扩/缩容
十二、通过Dapr实现一个简单的基于.net的微服务电商系统(十二)——istio+dapr构建多运行时服务网格
十三、通过Dapr实现一个简单的基于.net的微服务电商系统(十三)——istio+dapr构建多运行时服务网格之生产环境部署
十四、通过Dapr实现一个简单的基于.net的微服务电商系统(十四)——开发环境容器调试小技巧
附录:(如果你觉得对你有用,请给个star)
一、电商Demo地址
首选我们看看在普通项目上vs是如何附加到容器的,我们打开一个新webapi项目,勾选启用docker,选择Linux环境,创建之后默认F5就会以容器的方式启动调试模式。我们打开输出->来源选择“容器工具”,可以看到下面的日志输出:
1 ========== 容器必备项检查 ==========
2 正在验证是否安装了 Docker Desktop...
3 安装了 Docker Desktop。
4 ========== 正在验证 Docker Desktop 是否正在运行... ==========
5 正在验证 Docker Desktop 是否正在运行...
6 Docker Desktop 正在运行。
7 ========== 正在验证 Docker OS ==========
8 正在验证 Docker Desktop 的操作系统模式是否匹配项目的目标操作系统...
9 Docker Desktop 的操作系统模式与项目的目标操作系统匹配。
10 ========== 拉取所需的映像 ==========
11 正在检查缺少的 Docker 映像...
12 正在拉取 Docker 映像。要取消此下载,请关闭命令提示符窗口。
13 docker pull mcr.microsoft.com/dotnet/aspnet:5.0
14 Docker 映像准备就绪。
15 ========== 正在为 WebApplication5 预热容器 ==========
16 正在启动容器...
17 docker build -f "C:\Users\Administrator\source\repos\WebApplication5\WebApplication5\Dockerfile" --force-rm -t webapplication5:dev --target base --label "com.microsoft.created-by=visual-studio" --label "com.microsoft.visual-studio.project-name=WebApplication5" "C:\Users\Administrator\source\repos\WebApplication5"
18 #1 [internal] load build definition from Dockerfile
19 #1 sha256:6cebd8ea57035d67289d428d4ab12b9bd9f7b854cece45a6c8c5896f3e584db4
20 #1 transferring dockerfile: 768B done
21 #1 DONE 1.1s
22
23 #2 [internal] load .dockerignore
24 #2 sha256:ae3807db44f6e2063162c294384e0741768014999eb51b124c29f912625db9d3
25 #2 transferring context: 382B done
26 #2 DONE 1.4s
27
28 #3 [internal] load metadata for mcr.microsoft.com/dotnet/aspnet:5.0
29 #3 sha256:3b35130338ebb888f84ec0aa58f64d182f10a676a625072200f5903996d93690
30 #3 DONE 0.0s
31
32 #4 [base 1/2] FROM mcr.microsoft.com/dotnet/aspnet:5.0
33 #4 sha256:31acc33a1535ed7869167d21032ed94a0e9b41bbf02055dc5f04524507860176
34 #4 DONE 3.9s
35
36 #5 [base 2/2] WORKDIR /app
37 #5 sha256:56abde746b4f39a24525b2b730b2dfb6d9688bcf704d367c86a4753aefff33f6
38 #5 DONE 3.7s
39
40 #6 exporting to image
41 #6 sha256:e8c613e07b0b7ff33893b694f7759a10d42e180f2b4dc349fb57dc6b71dcab00
42 #6 exporting layers
43 #6 exporting layers 0.7s done
44 #6 writing image sha256:406f8da6d5c71bdc01379b493d135e99801857a3c4bdfc9b5898bbda0a62d8a4 0.1s done
45 #6 naming to docker.io/library/webapplication5:dev 0.1s done
46 #6 DONE 1.1s
47 C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe -NonInteractive -NoProfile -WindowStyle Hidden -ExecutionPolicy RemoteSigned -File "C:\Users\Administrator\AppData\Local\Temp\GetVsDbg.ps1" -Version vs2017u5 -RuntimeID linux-x64 -InstallPath "C:\Users\Administrator\vsdbg\vs2017u5"
48 Info: Using vsdbg version '17.0.10413.12'
49 Info: Using Runtime ID 'linux-x64'
50 Info: C:\Users\Administrator\vsdbg\vs2017u5 exists, deleting.
51 Info: Successfully installed vsdbg at 'C:\Users\Administrator\vsdbg\vs2017u5'
52 C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe -NonInteractive -NoProfile -WindowStyle Hidden -ExecutionPolicy RemoteSigned -File "C:\Users\Administrator\AppData\Local\Temp\GetVsDbg.ps1" -Version vs2017u5 -RuntimeID linux-musl-x64 -InstallPath "C:\Users\Administrator\vsdbg\vs2017u5\linux-musl-x64"
53 Info: Using vsdbg version '17.0.10413.12'
54 Info: Using Runtime ID 'linux-musl-x64'
55 Info: Successfully installed vsdbg at 'C:\Users\Administrator\vsdbg\vs2017u5\linux-musl-x64'
56 docker run -dt -v "C:\Users\Administrator\vsdbg\vs2017u5:/remote_debugger:rw" -v "C:\Users\Administrator\source\repos\WebApplication5\WebApplication5:/app" -v "C:\Users\Administrator\source\repos\WebApplication5:/src/" -v "C:\Users\Administrator\.nuget\packages\:/root/.nuget/fallbackpackages" -e "DOTNET_USE_POLLING_FILE_WATCHER=1" -e "ASPNETCORE_LOGGING__CONSOLE__DISABLECOLORS=true" -e "ASPNETCORE_ENVIRONMENT=Development" -e "NUGET_PACKAGES=/root/.nuget/fallbackpackages" -e "NUGET_FALLBACK_PACKAGES=/root/.nuget/fallbackpackages" -P --name WebApplication5 --entrypoint tail webapplication5:dev -f /dev/null
57 339a0e69705f04043b704fd4fc3a361c652c73caa95dbb1d1c14f9c4b4af596d
58 已成功启动容器。
59 ========== 已完成 ==========
这里面检几个比较重要的点来说:
1、17行,通过dockerfile创建了一个镜像
2、47行执行了GetVsDbg.ps1,这是一个powershell脚本,通过这个会在将debug工具下载到51行对应的vs2017u5这个文件夹内(重要)
3、56行,通过挂载文件的方式我们将debug工具以及nuget包通过-v的方式挂载到了镜像内(重要)
通过以上三点即可知道一个容器环境要调试其实主要就是靠这几点就能实现,所以不管是不是k8s,本质都是容器。现在我们来看看在k8s里我们如何实现调试的,还是以电商系统为例,我们拿accountservice作为调试目标。首先我们需要构造accountservice的调试版本的镜像。这个镜像其实就是一个空的aspnet镜像,dockerfile如下:
FROM mcr.microsoft.com/dotnet/aspnet:5.0
WORKDIR /app
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
ENTRYPOINT ["dotnet", "Host.dll"]
其实主要就是增加了一个ENTRYPOINT指定镜像启动时调用host.dll。也就是我们accountservice的那个host。接着我们将这个dockerfile打包成镜像:docker build . -t accountservice:debug 。然后我们将accountservice的Deployment作如下修改:
apiVersion: apps/v1
kind: Deployment
metadata:
name: accountservice
namespace: dapreshop
labels:
app: accountservice
spec:
replicas: 1
selector:
matchLabels:
app: accountservice
minReadySeconds: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
template:
metadata:
labels:
app: accountservice
annotations:
dapr.io/enabled: "true"
dapr.io/app-id: "accountservice"
dapr.io/app-port: "80"
dapr.io/config: "zipkin"
spec:
containers:
- name: web
image: accountservice:debug
imagePullPolicy: Never
ports:
- containerPort: 80
volumeMounts:
- mountPath: /app
name: v1
- mountPath: /remote_debugger:rw
name: v2
volumes:
- name: v1
hostPath:
path: /run/desktop/mnt/host/e/Oxygen-Dapr.EshopSample/Services/AccountService/Host/bin/Debug/net5.0
- name: v2
hostPath:
path: /run/desktop/mnt/host/c/Users/Administrator/vsdbg/vs2017u5
注意红字部分,首先我们替换了镜像,其次我们将accountservice的host下的bin/debug下的dll挂载到了/app目录。第三我们将vsdbg工具挂载到了容器调试工具里。这里/run/desktop/mnt/host/是指docker的wsl2映射到我系统里的路径。因为docker for windwos在wsl2里是一个子系统,所以必须通过这个路径来映射我们常规的cdef盘路径。好了,现在我们将我们的解决方案右键重新生成一次,然后apply 一下我们的yaml文件。并再次观察我们的pod,可以看到debug版本的accountservice已经正确的runnging了。
好了,现在我们在vs里,选择菜单栏->调试->附加到进程,打开附加到进程窗口,连接类型选择Docker(Linux容器),连接目标选择查找。弹出查找框,会自动将本地计算机的容器实例展示出来,这个时候查找到我们的accountservice容器,选择确定
tips:查找名称的小技巧:所有k8s运行的容器都是以k8s_开头接着是我们在deployment里申明的containers.name,然后是deployment的name。在后面就是生成pod的随机串组成的key,这个可以不用关心。所以我们需要找到k8s_web_accountservice开头的容器即可
tips:远程附加小技巧:docker cli主机可以附加到远程调试,调试和本地差不多,唯一区别就是我们需要在远程服务器挂载调试工具和debug生成的dll,这个可以copy过去也可以通过k8s的storageclass+nfs等方式挂载到局域网共享目录,这里就不展开了。
接着选择这个容器后选择我们容器内的host进程,点击附加,调试选择托管
接着就和普通调试没区别了,我们打开admin.dapreshop,默认login页面会调用/accountservice/accountquery/CheckRoleBasedAccessControler,检查系统初始化,就打断点在这个方法上,再刷新一下页面,即可看到断点命中成功了。