1. 项目概述一个关键的版本迁移工具如果你在Kubernetes生态里用过Helm那你大概率听说过Helm 2和Helm 3。从Helm 2到Helm 3的升级远不止是版本号1那么简单它是一次架构上的重大变革。最核心的变化之一就是移除了Tiller——那个在Helm 2时代负责在集群内部署和管理应用的服务端组件。这个改动带来了巨大的安全性提升和架构简化但也留下了一个棘手的遗留问题如何将Helm 2时代部署的、由Tiller管理的应用我们称之为“release”安全、完整地迁移到Helm 3的新架构下helm/helm-2to3这个项目就是官方为解决这个“历史包袱”而生的迁移工具。它不是Helm CLI的一部分而是一个独立的插件。简单来说它的核心任务就是充当一个“数据搬运工”和“格式转换器”把Helm 2的配置、状态和已部署的应用转换成Helm 3能够识别和管理的格式。想象一下你有一个运行了多年的、由Helm 2管理的复杂微服务应用栈里面有几十个服务涉及复杂的配置和依赖关系。直接卸载Helm 2再安装Helm 3重新部署那意味着服务中断、数据丢失风险和巨大的重复劳动成本。helm-2to3就是为了避免这种灾难性场景而存在的。这个工具主要面向两类用户一是正在规划或正在进行Kubernetes集群和工具链现代化升级的运维工程师和平台团队二是接手了遗留Helm 2应用需要将其纳入新CI/CD流程或统一管理体系的开发者。它的价值在于降低迁移风险和节省迁移时间。通过自动化处理繁琐的配置转换和状态迁移它让升级过程从一个充满不确定性的“黑盒操作”变成了一个步骤清晰、可回滚的标准化流程。2. 迁移的核心挑战与2to3的设计思路要理解helm-2to3工具的价值必须先明白从Helm 2迁移到Helm 3到底难在哪里。这绝不仅仅是换个客户端命令那么简单。2.1 Helm 2与Helm 3的核心架构差异Helm 2采用的是客户端-服务器架构C/S架构客户端 (helm CLI)用户本地执行命令。服务端 (Tiller)部署在Kubernetes集群内部的一个Pod拥有较高的权限通常是cluster-admin负责接收客户端的指令与Kubernetes API Server交互实际执行应用的安装、升级、删除等操作。所有Release的元数据版本历史、状态、配置值等都存储在Tiller所在Namespace默认是kube-system的ConfigMap或Secrets中。Helm 3移除了Tiller采用了无状态的客户端直接操作架构客户端 (helm CLI)直接使用用户本地的kubeconfig文件提供的权限与Kubernetes API Server交互。权限管理完全遵循Kubernetes原生的RBAC更安全、更清晰。存储方式每个Release的元数据以Secret的形式存储在该Release自身所在的Namespace中。这种按Namespace隔离的存储方式与Kubernetes的资源模型更加契合。2.2 迁移工具必须解决的三大难题基于上述差异一个合格的迁移工具必须解决以下问题数据提取与转换如何从Tiller的ConfigMap/Secret中准确提取出Helm 2 Release的完整信息这包括Chart名称、版本、命名空间、状态、每次升级的配置值values、以及最重要的——生成当前已部署资源清单的模板渲染结果。状态无损迁移迁移的核心目标是“应用无感知”。这意味着迁移后集群中运行的所有Pod、Service、Deployment等资源必须保持原样不能有任何重启或重建。工具不能简单地调用helm install重新部署而必须在Helm 3中“重建”一个与Helm 2 Release完全同名的Release记录并且让Helm 3认为这个Release当前管理的资源就是集群中现存的那一批。清理与回滚策略迁移完成后如何安全地清理Helm 2的遗留数据Tiller及相关的ConfigMap/Secret如果在迁移过程中或迁移后发现问题是否有清晰的回滚路径是回退到Helm 2的状态还是在Helm 3内进行处理2.3helm-2to3的解决之道helm-2to3插件采用了分步、谨慎的策略来应对这些挑战。它没有试图做一个“一键迁移”的黑魔法而是将过程拆解成几个原子操作让用户拥有充分的控制权和可见性。它的核心工作流程可以概括为信息抓取 (2to3 convert)连接仍存在的Tiller或直接读取其遗留的存储数据获取目标Release的详细信息。本地转换 (2to3 convert)在本地生成Helm 3兼容的Release元数据文件并模拟Helm 3的安装过程但不实际对集群做任何修改。这一步是纯粹的“计算”和“准备”。实际迁移 (2to3 move)使用上一步准备好的数据在Helm 3中创建Release记录并将其与集群中现有的资源进行“关联”。清理确认 (2to3 cleanup)在验证Helm 3下的Release工作正常后手动清理Helm 2的残留数据。这种分步设计降低了单点故障的风险允许用户在每一步进行验证符合运维上的“变更可控”原则。3. 工具安装与前置环境检查工欲善其事必先利其器。在开始迁移之前必须确保环境准备就绪。3.1 安装helm-2to3插件helm-2to3通过Helm的插件机制安装。确保你已安装Helm 3版本3.0以上。# 最直接的安装方式从官方仓库安装 helm plugin install https://github.com/helm/helm-2to3 # 安装后验证 helm 2to3 --help如果看到2to3命令的帮助信息说明安装成功。你也可以通过helm plugin list查看已安装的插件。注意插件的安装实际上是将二进制文件下载到$(helm home)/plugins/helm-2to3目录。在某些网络环境下可能需要配置代理或从镜像站下载。请确保你的网络能够正常访问GitHub。3.2 迁移前的关键环境检查清单在运行任何迁移命令之前请务必完成以下检查。我见过太多迁移失败是因为前置条件不满足。Kubernetes集群访问权限确保kubectl可以正常访问你的集群并且上下文context设置正确。执行kubectl cluster-info和kubectl get nodes确认连接正常。重要你用于执行迁移的kubeconfig用户必须对目标Namespace拥有足够的权限能够创建Secret用于存储Helm 3的Release以及读取原有的Tiller存储资源。Helm 2 Tiller状态确认如果你的集群中Tiller还在运行先确认其状态和版本。kubectl get pod -n kube-system -l apphelm,nametiller kubectl get deployment -n kube-system tiller-deploy记下Tiller的版本通过Pod镜像标签或Deployment描述查看。这有助于理解Helm 2 Release的存储格式。决策点Tiller是否还在运行这会影响2to3 convert命令的连接方式。如果Tiller已删除但数据还在工具可以通过--tiller-out-cluster标志直接读取存储数据。Helm 2 Release清单与状态审计使用Helm 2客户端如果你还保留着列出所有Release并仔细检查它们的状态。# 假设你的Helm 2客户端命令是helm2 helm2 list --tiller-namespacekube-system --all重点关注状态不是DEPLOYED的Release例如FAILED、PENDING_UPGRADE、DELETED的。这些状态异常的Release可能会在迁移时引发问题可能需要先进行修复或清理。记录下你需要迁移的Release的精确名称和所在Namespace。Release名称在迁移后无法更改。目标Namespace资源盘点对于每个待迁移的Release查看其Namespace下现有的Kubernetes资源。kubectl get all,secret,configmap,pvc -n release-namespace这既是迁移前的备份参考也能帮你确认迁移后资源是否被意外修改。备份备份备份虽然2to3设计为非破坏性操作但任何涉及生产环境的变更都必须备份。备份Tiller的存储数据位于kube-system命名空间下的ConfigMap和Secret标签包含OWNERTILLER。kubectl get configmap,secret -n kube-system -l OWNERTILLER -o yaml tiller-backup.yaml备份目标Namespace下关键资源如StatefulSet、PersistentVolumeClaim的清单。考虑为整个Namespace创建一个快照如果使用了Velero等工具。完成这些检查后你已经对迁移环境有了清晰的画像可以开始谨慎地执行迁移了。4. 分步迁移实操详解我们将迁移一个名为my-app部署在default命名空间的Helm 2 Release到Helm 3。假设Tiller仍在kube-system命名空间中运行。4.1 第一步转换与模拟 (2to3 convert)这是迁移的核心准备步骤。convert命令会做两件关键事1) 获取Helm 2 Release的完整数据2) 在本地生成Helm 3所需的文件并模拟安装。# 基本转换命令 helm 2to3 convert my-app # 更推荐使用详细参数提高可控性 helm 2to3 convert my-app \ --tiller-namespace kube-system \ # Tiller所在的命名空间 --release-name my-app \ # Helm 2的Release名称 --release-namespace default \ # Release部署的命名空间 --dry-run # 强烈建议先加此参数进行试运行命令参数解析与实操心得--tiller-namespace如果Tiller不在默认的kube-system里必须指定。--dry-run这是你最好的朋友。它不会向集群写入任何内容只会在本地模拟并输出将要执行的操作和生成的Helm 3 Release内容。请务必先运行dry-run仔细检查输出检查转换后的Chart名称和版本是否正确。检查生成的values.yaml是否包含了所有你自定义的配置。检查工具是否成功识别出了所有由该Release管理的Kubernetes资源。--delete-v2-releases千万不要在第一次convert时就加上这个参数它会在转换成功后立即删除Helm 2的Release记录。我们应在最终确认迁移完全成功后再手动清理。执行dry-run后如果没有报错并且输出内容符合预期就可以移除--dry-run参数执行真正的转换helm 2to3 convert my-app --tiller-namespace kube-system执行成功后你会在本地看到类似这样的输出表明Helm 3的Release配置已准备就绪但尚未在集群中创建。Release \my-app\ will be converted from Helm 2 to Helm 3. [Convert] Release \my-app\ will be converted [Convert] Release \my-app\ converted successfully此时在Helm 3的配置目录下通常是~/.cache/helm或~/.local/share/helm会生成一个临时目录里面包含了为这个Release准备的所有Helm 3元数据。你可以用helm ls -n default查看此时还看不到my-app因为convert只做了本地准备。4.2 第二步实际迁移与关联 (2to3 move)move命令是真正将Helm 3的Release记录写入集群并将其与现有资源关联的关键一步。helm 2to3 move my-app \ --release-name my-app \ --release-namespace default \ --dry-run # 同样先试运行move命令做了什么读取上一步convert生成的本地数据。在目标Namespacedefault下创建一个类型为helm.sh/release.v1的Secret。这个Secret的内容就是Helm 3格式的Release元数据。最关键的一步它会获取当前集群中该Namespace下的所有资源并通过标签选择器ownerhelm, statusdeployed等或注解尝试找出哪些资源是属于原Helm 2 Releasemy-app的。然后它会为这些资源打上Helm 3的标签如app.kubernetes.io/managed-byHelm从而完成“所有权”的转移。试运行无误后执行真正的movehelm 2to3 move my-app成功后会输出[Move] Release \my-app\ will be moved from Helm 2 to Helm 3. [Move] Release \my-app\ moved successfully to Helm 3.立刻进行验证# 使用Helm 3查看Release helm list -n default # 应该能看到状态为deployed的my-app # 查看Release的详情和状态 helm status my-app -n default # 检查输出的RESOURCES部分是否列出了所有预期的Kubernetes资源。 # 尝试一个无害的操作例如获取历史如果之前有升级 helm history my-app -n default # 或者获取当前部署的values helm get values my-app -n default如果helm status显示的资源列表与你迁移前盘点的一致并且所有Pod都运行正常那么恭喜你核心迁移已经成功了。Helm 3现在认为它完全掌控着my-app这个应用。4.3 第三步清理与收尾 (2to3 cleanup)在确认Helm 3下的Release工作完全正常可能经过一段时间的观察或执行一次简单的helm upgrade --dry-run测试后就可以清理Helm 2的遗留数据了。# 清理指定Release在Helm 2中的记录 helm 2to3 cleanup my-app \ --name my-app \ --tiller-namespace kube-system \ --dry-run # 先看它会删什么 # 确认无误后执行 helm 2to3 cleanup my-app --tiller-namespace kube-systemcleanup命令做了什么它会在Tiller的存储kube-system命名空间下的ConfigMap/Secret中删除与my-app这个Release相关的所有记录。这步操作是不可逆的。执行后Helm 2客户端将再也看不到这个Release。最终清理删除Tiller本身当所有重要的Release都迁移完毕并验证无误后就可以安全地移除Tiller了。# 如果你是用helm init安装的Tiller可以用helm 2来删除 helm2 reset --tiller-namespace kube-system --force # 或者直接用kubectl删除其Deployment和Service kubectl delete deployment tiller-deploy -n kube-system kubectl delete service tiller-deploy -n kube-system # 最后清理可能残留的RBAC资源ServiceAccount, ClusterRoleBinding等 kubectl delete serviceaccount tiller -n kube-system kubectl delete clusterrolebinding tiller-cluster-rule # 注意RBAC资源名称可能因安装方式而异请根据实际情况调整。至此针对单个Release的完整迁移流程就结束了。你的应用已经平滑地从Helm 2的体系转移到了Helm 3的体系下。5. 复杂场景与疑难问题排查在实际生产迁移中你几乎不可能只遇到像上面那样一帆风顺的简单场景。下面分享几种我遇到过的典型复杂情况及其处理思路。5.1 场景一Tiller已删除但Release数据仍在这是很常见的情况团队可能先移除了Tiller但忘了迁移Release。此时2to3 convert无法连接Tiller服务。解决方案使用--tiller-out-cluster模式。这个模式允许插件直接读取Tiller存储在Kubernetes里的数据而不需要Tiller进程。# 首先确认Tiller存储Secret/ConfigMap还存在 kubectl get secret -n kube-system -l OWNERTILLER,NAMEmy-app # 使用离线模式转换 helm 2to3 convert my-app \ --tiller-out-cluster \ --tiller-namespace kube-system \ --release-storage secret # 或 configmap取决于Helm 2的存储后端关键参数是--tiller-out-cluster和--release-storage。你需要知道Helm 2当时用的是Secret还是ConfigMap存储Helm 2后期版本默认是Secret。如果不确定可以两种都试试或者去kube-system命名空间下查看哪种资源包含你的Release名称。5.2 场景二Release状态异常FAILED, PENDING_UPGRADE迁移一个状态不是DEPLOYED的Release会非常危险因为其记录的期望状态可能与集群实际状态严重不符。处理建议优先修复Helm 2 Release如果可能尝试在Helm 2环境下解决问题。例如对于PENDING_UPGRADE可以尝试helm2 rollback或helm2 upgrade --force。对于FAILED需要先查明失败原因看是否能通过再次helm2 upgrade恢复。作为最后手段在Helm 3中重新安装如果无法修复且该应用可以接受短暂中断最安全的方法是记录下当前Helm 2 Release的所有配置值helm2 get values。手动记录或导出该应用创建的所有重要资源特别是PersistentVolumeClaim等有状态资源。使用Helm 3用相同的Chart和配置值在一个新的、不同的Release名称下进行安装。安装时可以手动指向已有的PVC等资源避免数据丢失。这种方法放弃了迁移历史版本但保证了结果的可控性。绝对不要强行用2to3迁移一个状态异常的Release这很可能导致Helm 3试图“纠正”集群状态引发不可预知的资源变更或删除。5.3 场景三自定义Chart或Hook导致迁移后行为不一致Helm 2和Helm 3在渲染Chart模板时有一些细微差别尤其是在处理_helpers.tpl、范围scope和内置对象方面。此外Helm 3对Hook的执行逻辑也有调整。排查与验证详细对比dry-run输出在convert和move的dry-run阶段仔细检查工具模拟生成的Kubernetes资源清单。与你从Helm 2获取的当前清单helm2 get manifest进行逐行对比。差异点可能就是问题所在。重点检查Hooks如果Chart中定义了pre-install,post-upgrade等Hooks需要特别注意。Helm 3的Hook资源会带有helm.sh/hook注解。确保迁移后这些Hook资源的逻辑仍然符合预期。有时可能需要手动为这些资源添加Helm 3的标签。测试升级流程迁移完成后立即执行一次helm upgrade --dry-run。这是检验Helm 3是否真正理解当前部署状态的“试金石”。如果dry-run显示要创建或删除大量资源说明迁移可能有问题需要停止并检查。5.4 常见错误与排查表错误信息/现象可能原因排查步骤与解决方案Error: release: \my-release\ not found1. Release名称拼写错误。2. Tiller命名空间指定错误。3. Release确实不存在于Helm 2中。1.helm2 list --all确认名称和命名空间。2. 检查--tiller-namespace参数是否正确。3. 检查Tiller存储中是否有对应Secret/ConfigMap。Error: context deadline exceeded网络问题或API Server响应慢导致连接Tiller或K8s API超时。1. 检查kubectl命令是否流畅。2. 增加超时时间--tiller-connection-timeout 300。3. 在集群网络状况好时重试。Error: conversion failed: ...Release数据损坏或格式无法识别。1. 尝试用--tiller-out-cluster模式绕过Tiller直接读取存储。2. 手动检查对应的Secret/ConfigMap数据是否完整可读。3. 考虑从备份恢复Helm 2数据或采用“重新安装”方案。move成功后helm status显示资源为空或不全Helm 3未能正确关联所有现有资源。1. 检查资源是否具有Helm 2的标签如heritageTiller。2. 手动为缺失的资源添加Helm 3管理标签kubectl label resource-type name app.kubernetes.io/managed-byHelm。3. 这是一个危险信号需谨慎处理可能需回退。迁移后执行helm upgrade试图删除重要资源Helm 3计算出的期望状态与集群实际状态不一致。通常是因为Chart模板在Helm2/3下渲染结果不同或迁移时状态捕获不全。1.立即停止不要执行实际的upgrade。2. 对比helm get manifest迁移后和集群实际资源。3. 使用helm template命令分别用Helm2和Helm3渲染Chart找出模板差异。4. 最坏情况在Helm 3中回滚/删除Release采用手动重建方式。6. 迁移策略与最佳实践总结基于多次迁移经验我总结出以下策略能让整个过程更平稳。1. 制定分批次迁移计划不要试图一次性迁移所有Release。按优先级排序先易后难先迁移那些状态为DEPLOYED、Chart来源清晰如稳定的第三方Chart、无复杂Hook的简单应用。先非核心后核心先迁移开发、测试环境的Release积累经验后再处理生产环境的核心应用。按命名空间或团队划分可以按命名空间逐个清理方便责任划分和进度跟踪。2. 建立完整的验证闭环为每个迁移的Release建立一个检查表[ ]convert --dry-run输出无异常配置值正确。[ ]move --dry-run输出显示能正确关联资源。[ ]move实际执行后helm list和helm status显示正常。[ ]helm get manifest与集群中实际资源一致。[ ] 执行helm upgrade --dry-run显示“没有更改”或仅预期内的更改。[ ] 应用功能验证通过业务测试或健康检查。[ ] 观察一段时间如24小时后确认无异常。[ ] 执行cleanup删除Helm 2数据。3. 准备好回滚方案回滚不是失败而是负责的表现。明确每一步的回滚方法如果在move之后发现问题可以使用helm uninstall删除Helm 3的Release注意这可能会删除资源如果资源关联正确uninstall会删除资源。务必先确认。更安全的做法是手动删除Helm 3创建的Secret并恢复资源的原有标签。如果问题复杂考虑放弃迁移确保Helm 2的数据未清理并恢复原有的运维流程直到找到根本解决方案。4. 沟通与文档迁移不仅是技术活也是沟通活。确保相关团队开发、测试、运维知晓迁移窗口期和潜在风险。详细记录每个应用的迁移状态、遇到的问题和最终解决方案这份文档对未来处理类似问题和新成员 onboarding 都极具价值。最后helm-2to3是一个强大的工具但它不是魔法。它的成功极度依赖于你对Helm 2和Helm 3原理的理解以及对迁移过程严谨、耐心的把控。把它当作一个可靠的“辅助”而不是“全自动解决方案”。每一次--dry-run的仔细检查每一次迁移后的验证都是对你生产环境稳定性的负责。当最后一个Helm 2 Release被成功迁移Tiller被最终移除时你会感受到架构整洁和统一管理带来的那份踏实感。