在 Linux 容器中收集诊断

用于诊断其他方案中 .NET 问题的相同诊断工具也适用于容器。 这些工具可以在目标进程的同一容器中运行,也可以从主机或辅助容器运行。

在容器中使用 .NET CLI 工具

这些工具适用于:✔️ .NET Core 3.1 SDK 及更高版本

所有 dotnet-* CLI 诊断工具 都可以在它们正在检查的应用程序所在的同一容器中运行时工作,但请注意这些潜在的故障点:

  • 容器内运行的工具将受到容器资源限制的约束。 如果资源限制太低,工具可能会运行缓慢或失败。 大多数工具具有适度的要求,但在dotnet-dumpdotnet-gcdump面向占用大量内存的进程时,可以使用相当大的内存和磁盘空间。 dotnet-tracedotnet-counters也可能创建大型文件,如果它们被配置为捕获大量跟踪事件或指标时序数据的话。
  • dotnet-dump 将导致一个需要 ptrace 权限的辅助进程运行。 Linux 有许多安全配置选项,可能会影响这是否成功,因此在某些情况下,可能需要调整容器的安全配置。 有关诊断安全权限的更多指导,请参阅转储常见问题解答
  • 在容器中运行工具时,可以在构建容器时提前安装它们,或者按需下载它们。 提前安装它们在需要时使操作更便捷,但会增加容器大小,并创建一个更大的攻击面,恶意行为者可能会尝试加以利用。

在挎斗容器中或从主机使用 .NET CLI 工具

dotnet-* CLI 诊断工具还支持从主机或 sidecar 容器中运行。 这在很大程度上避免了在同一容器中运行的大小、安全性和资源限制,但对工具成功通信有一些附加要求。

在使用 --process-id--name 工具命令行参数确定要检查的目标进程时,这需要:

  1. 容器必须 共享进程命名空间 ,以便 sidecar 容器中的工具可以访问目标容器中的进程。
  2. 这些工具需要访问诊断端口 Unix 域套接字,.NET 运行时会将其写入 /tmp 目录,因此 /tmp 目录必须通过卷挂载在目标和挎斗容器之间共享。 例如,可以通过让容器共享公用或 Kubernetes emptyDir 卷来完成此操作。 如果尝试使用 Sidecar 容器中的诊断工具而不共享 /tmp 目录,则会出现有关进程“运行不兼容 .NET 运行时”的错误。

如果不想共享进程命名空间和 /tmp 目录,许多工具还支持更高级 --diagnostic-port 的命令行选项。 这样,就可以直接在主机或 sidecar 的文件系统中指定目标进程的 诊断端口 的路径。 目标容器的 /tmp 目录需要映射到某个位置,以便此路径存在,但不必与主机或 sidecar /tmp 共享。

注意

即使从主机或挎斗运行诊断工具,目标进程仍可能被要求执行增加其在目标容器内资源使用量的工作。 我们发现 dotnet-dump 在收集转储时可能会导致目标进程在大量虚拟内存中翻页。 其他工具可能会造成较小的影响,尽管我们实际上没有看到这些问题。 例如, dotnet-trace 请求目标进程分配事件缓冲区,并 dotnet-counters 请求聚合指标数据的小型内存区域。 我们建议进行测试,以确保内存限制不太紧,避免运行工具时导致操作系统终止你的容器。

注意

dotnet-dump 将转储文件写入磁盘时,输出路径会根据目标进程的文件系统视图来解释。 这可能与主机或挎斗容器不同。

在容器中使用 PerfCollect

此工具适用于:✔️ .NET Core 2.1 及更高版本

PerfCollect 脚本可用于收集包含内核事件(如 CPU 示例或上下文开关)的性能跟踪。 如果在容器中使用 PerfCollect,请记住以下要求:

  • PerfCollect 需要其他功能才能运行 perf 工具。 所需的最小功能集是 PERFMONSYS_PTRACE。 某些环境需要 SYS_ADMIN。 请务必使用 必要的权限启动容器。 如果最小集不起作用,请尝试使用完整集。

  • PerfCollect 需要在其将分析的应用启动之前设置某些环境变量。 可以在 Dockerfile 中设置这些设置,也可以在 启动容器时进行设置。 由于在正常生产环境中不应设置这些变量,因此,在启动要分析的容器时添加它们是常见做法。 PerfCollect 需要的两个变量是:

    • DOTNET_PerfMapEnabled=1
    • DOTNET_EnableEventLog=1

注意

使用 .NET 7 执行应用时,除设置上述环境变量之外,还必须设置 DOTNET_EnableWriteXorExecute=0

注意

.NET 6 为用于配置 .NET 运行时行为的环境变量标准化前缀 DOTNET_ 而不是 COMPlus_。 但是,COMPlus_ 前缀仍将继续正常工作。 如果使用的是早期版本的 .NET 运行时,则环境变量仍应该使用 COMPlus_ 前缀。

在挎斗容器中使用 PerfCollect

如果要在一个容器中运行 PerfCollect 以在另一个容器中分析 .NET 进程,则体验几乎相同。 不同之处在于:

  • 必须为目标容器(不是运行 DOTNET_PerfMapEnabled 的容器)设置前面所述的环境变量(DOTNET_EnableEventLogPerfCollect)。
  • 运行 PerfCollect 的容器必须具有 SYS_ADMIN 功能(而目标容器则不必)。
  • 这两个容器必须 共享进程命名空间