通過 Dapr 實現一個簡單的基於 dotnet 的微服務電商系統 -十四-——開發環境容器調試小技巧

  之前有很多同學提到如何做容器調試,特別是 k8s 環境下的容器調試,今天就講講我是如何調試的。大家都知道在 vs 自帶的創建項目模板裏勾選 docker 即可通過 F5 啓動 docker 容器調試。但是對於啓動在 k8s 則不是那麼清楚。其實兩者原理上是一樣的。

附錄:(如果你覺得對你有用,請給個 star)
一、電商 Demo 地址:https://github.com/sd797994/Oxygen-Dapr.EshopSample

二、通訊框架地址:https://github.com/sd797994/Oxygen-Dapr

  首選我們看看在普通項目上 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-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,檢查系統初始化,就打斷點在這個方法上,再刷新一下頁面,即可看到斷點命中成功了。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/fkYkmDWFCdw5pHO3rnj3gw