.Net 6迁移后部署K8s报CrashLoopBackOff问题排查咨询
问题现象
- 基于.Net 5正常运行的代码迁移至.Net 6后,无法部署到K8s集群,Pod状态持续为
CrashLoopBackOff - 同一份代码在Visual Studio 2022本地环境可正常运行,部署到K8s Pod后立即触发崩溃
- 查看Pod日志拿到的核心报错如下:
Unhandled exception. System.IO.FileLoadException: Could not load file or assembly 'System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The located assembly's manifest definition does not match the assembly reference. (0x80131040) File name: 'System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
- 当前Dockerfile中安装.Net环境的指令如下:
RUN dnf install dotnet-sdk-6.0.106 -y RUN dnf install dotnet-runtime-6.0.6 -y
排查思路
- 先校验容器内实际运行时版本:进入故障容器执行
dotnet --list-runtimes查看已安装的所有.Net Core运行时版本,再到全局程序集缓存目录找到System.Runtime.dll,检查其实际版本、公钥Token是否和报错要求的6.0.0.0版本匹配 - 检查项目发布配置:确认发布时是否选择了框架依赖模式,发布指定的.Net版本与容器内安装的版本是否存在小版本兼容问题;同时排查项目文件中是否残留.Net 5的旧依赖引用,发布目录中是否混入了.Net 5时期编译生成的旧系统程序集
- 检查基础镜像环境冲突:确认当前使用的自定义基础镜像是否默认预装了其他版本的.Net运行时,dnf安装的6.0版本是否和预装版本产生了程序集加载优先级冲突;同时校验dnf源拉取的.Net安装包是否完整,是否存在源依赖配置错误导致安装的运行时文件缺失、被替换
- 检查Dockerfile构建逻辑:如果使用多阶段构建,确认是否把构建阶段生成的发布产物完整拷贝到了运行阶段,同时确认构建阶段使用的SDK架构、运行阶段安装的运行时架构,和K8s节点的CPU架构(x64/arm64)是否一致,跨架构部署也会触发这类程序集加载错误
解决方案
- 优先替换为官方维护的.Net 6镜像作为构建和运行的基础镜像,不要手动通过dnf安装运行时:构建阶段使用
mcr.microsoft.com/dotnet/sdk:6.0镜像完成编译发布,运行阶段使用mcr.microsoft.com/dotnet/aspnet:6.0镜像拷贝发布产物运行,官方镜像已经提前做了版本校验和依赖适配,不会出现系统核心程序集版本不匹配的问题 - 如果必须使用自定义基础镜像,先执行
dnf remove -y dotnet-*卸载镜像内预装的所有旧版本.Net相关组件,再安装对应版本的SDK和运行时,安装完成后执行dotnet --info校验,确认仅存在6.0版本的Microsoft.NETCore.App运行时,无其他版本残留 - 调整项目发布流程:发布前先执行
dotnet clean,删除项目下的bin、obj目录清理所有旧编译缓存,再重新编译发布;如果环境版本不好对齐,可以选择自包含发布模式,把运行时和程序集一起打包,不依赖容器内全局安装的.Net运行时 - 多阶段构建场景下,保证构建阶段使用的SDK大版本和运行阶段的运行时版本完全一致,不要用更高版本的SDK编译后放到低版本运行时环境中运行,同时统一构建、运行阶段的系统架构参数,避免跨架构兼容问题
内容的提问来源于stack exchange,提问作者EM K
相关产品推荐
相关产品推荐

