关于 migrate-v2-to-v3
面向运维人员的迁移技能,用于将现有 kube-hetzner Terraform 配置从 v2 升级到 v3。流程强调备份状态、审慎修改配置,并在执行 apply 前检查计划中的破坏性基础设施替换。
主要功能
- 01审计 v2 配置参数
- 02映射为 v3 参数名称
- 03指导状态备份与验证
- 04检查计划中的破坏性变更
- 05提示 Kubernetes 升级选项
适用场景
- 01为现有集群准备 v3 升级
- 02查找已弃用的 v2 模块参数
- 03升级前审查资源替换风险
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mysticaltech/ terraform-hcloud-kube-hetzner --skill migrate-v2-to-v3安装后在 Claude Code 中输入/migrate-v2-to-v3确认已加载。
详细介绍
将 kube-hetzner v2 迁移到 v3
目的
安全地将现有 kube-hetzner 集群从 v2.x 迁移到 v3.x。
此技能面向实际用户的 Terraform 根目录,而非全新集群。其优先事项是保留基础设施,并让 Terraform 验证失败具有可操作性。
权威参考资料
编辑前请阅读:
docs/v2-to-v3-migration.md- 运维迁移手册docs/v3-release-evidence.md- v2.21 -> v3 升级实证MIGRATION.md- 权威的新旧变量映射表CHANGELOG.md- v3 升级说明和版本背景variables.tf- v3 输入契约和验证规则的准确内容kube.tf.example- 当前 v3 配置示例scripts/v2_to_v3_migration_assistant.py- 静态配置和计划审计docs/selinux.md- SELinux 策略、AVC 证据和按节点池设置的回退方案scripts/destroy.sh和scripts/cleanup.sh- 拆除和孤立资源清理
安全规则
- 除非用户在审查计划后明确要求,否则绝不运行
terraform apply。 - 更改模块版本前,始终备份状态。
- v3 升级计划中出现
destroy、replace或forces replacement时,绝不能忽略。 - 不允许 K3s 通道策略悄然变更。
MIGRATION.md说明,v2 的k3s_channel默认值为v1.33;v3 的默认值则为stable,同时自动 Kubernetes 升级仍默认启用。用户必须在首次 v3 应用前作出选择。 - 将对
hcloud_network、hcloud_network_subnet、hcloud_server、hcloud_load_balancer、hcloud_primary_ip、hcloud_placement_group、hcloud_volume或hcloud_firewall的替换视为阻断项,直到得到解释。 - 对生产环境的原地升级,
MIGRATION.md是面向运维人员的安全契约。其禁止销毁的 jq 门禁是权威标准;不得放宽或缩略。 - 迁移期间或之后,绝不能在列表中间重新排序或插入控制平面或 Agent 节点池。节点资源地址以索引为键;除非用户有意规划状态迁移或蓝绿重建,否则只能追加。
- 不得通过绕过验证来“修复”v3 验证错误。应修正配置。
- 对自定义网络、仅私有网络、Robot/vSwitch 或多网络集群,如果原地升级计划无法明确证明安全,优先建议采用蓝绿方案。
必需输入
确定以下信息:
- Terraform 根目录路径。
- 当前模块来源和版本。
- 目标 v3 标签。
- Kubernetes 发行版意图:保留 k3s,还是将 RKE2 重建/迁移与基础 v2 -> v3 模块升级分开规划。
- K3s 版本/通道意图:固定
k3s_version、设置k3s_channel = "v1.33",或明确接受 v3 的stable。 - 节点是否在
ssh_public_key/ssh_additional_public_keys之外配置了带外 root SSH 密钥。 - Terraform 是否能够通过 SSH 连接到所有现有节点,以运行
terraform_data.initial_readiness,包括仅私有网络、NAT 和堡垒机拓扑。 - 这是否为生产环境中的运行集群。
- 是否使用 NAT 路由器、仅私有节点、Robot/vSwitch、自动扩缩器、Cilium、Longhorn 或外部网络。
- SELinux 工作负载拒绝是否属于当前故障的一部分。如果是,请收集 AVC 证据并遵循
docs/selinux.md,而不要全局禁用 SELinux。
工作流
1. 检查当前根目录
在用户的 Terraform 根目录中运行:
terraform version
terraform providers
rg -n 'module "kube-hetzner"|source\\s*=|version\\s*=' .
查找仅适用于 v2 的输入项:
uv run python /path/to/kube-hetzner/scripts/v2_to_v3_migration_assistant.py --root .
rg -n 'kubernetes_distribution_type|k3s_token|secrets_encryption|initial_k3s_channel|install_k3s_version|initial_rke2_channel|install_rke2_version|automatically_upgrade_k3s|sys_upgrade_controller_version|additional_k3s_environment|kubeapi_port|k3s_registries|k3s_kubelet_config|k3s_audit_policy_config|k3s_audit_log_path|k3s_audit_log_maxage|k3s_audit_log_maxbackup|k3s_audit_log_maxsize|k3s_exec_server_args|k3s_exec_agent_args|k3s_global_kubelet_args|k3s_control_plane_kubelet_args|k3s_agent_kubelet_args|k3s_autoscaler_kubelet_args|subnet_amount|placement_group_disable|block_icmp_ping_in|disable_hetzner_csi|load_balancer_disable_ipv6|load_balancer_disable_public_network|use_control_plane_lb|combine_load_balancers|control_plane_lb_type|control_plane_lb_enable_public_interface|control_plane_lb_enable_public_network|lb_hostname|robot_ccm_enabled|hetzner_ccm_use_helm|enable_hetzner_ccm_helm|cilium_loadbalancer_acceleration_mode|enable_wireguard|k8s_config_updates_use_kured_sentinel|keep_disk_agents|keep_disk_cp|use_private_bastion|disable_kube_proxy|disable_network_policy|disable_selinux|k3s_prefer_bundled_bin|placement_group_compat_idx|disable_ipv4|disable_ipv6|autoscaler_disable_ipv4|autoscaler_disable_ipv6|existing_network_id|enable_x86|enable_arm|k3s_encryption_at_rest|autoscaler_labels|autoscaler_taints|extra_kustomize_' .
助手应作为首轮报告的主要来源。如果根目录使用了不常见的格式、Terragrunt、生成的 HCL 或拆分的 tfvars,则可将 rg 命令作为手动交叉检查。
2. 备份
terraform state pull > "terraform-state-before-kube-hetzner-v3-$(date +%Y%m%d%H%M%S).json"
find . -maxdepth 1 -name '*.tf' -print
如果直接编辑用户配置,请保留一份已修改 .tf 文件的副本。
3. 重写配置
完整映射请参阅 MIGRATION.md。关键转换:
- 重命名与发行版无关的输入,例如将
k3s_token改为cluster_token,将kubernetes_distribution_type改为kubernetes_distribution。 - 反转否定布尔值:
- 将
disable_kube_proxy改为enable_kube_proxy - 将
disable_network_policy改为enable_network_policy - 将
disable_selinux改为enable_selinux - 将节点池的
disable_ipv4/disable_ipv6改为enable_public_ipv4/enable_public_ipv6 - 将
autoscaler_disable_ipv4/disable_ipv6改为autoscaler_enable_public_ipv4/autoscaler_enable_public_ipv6
- 将
- 将
existing_network_id = ["123"]替换为existing_network = { id = 123 }。 - 将
enable_x86/enable_arm替换为enabled_architectures。 - 移除控制平面的
network_id;控制平面仅使用主网络。 - 移除
network_id = 0;在 v3 中,主网络应省略或设为 null。 - 对常规的就地 v2 升级,保留默认值
network_subnet_mode = "per_nodepool";此设置与已发布的 v2 子网资源相符。仅对新集群或有意更改子网拓扑时,才使用network_subnet_mode = "shared"。 - 将
placement_group_compat_idx替换为placement_group_index。 - 将
extra_kustomize_*替换为user_kustomizations。 - 移除
enable_iscsid、k3s_encryption_at_rest、autoscaler_labels和autoscaler_taints。 - 移除
hetzner_ccm_use_helm/enable_hetzner_ccm_helm;v3 始终通过 HelmChart 清单安装 Hetzner CCM。 - 重写配置时,不要调整现有节点池的顺序,也不要插入节点池。只能追加新节点池。如果用户想更改列表顺序,请停止操作,并将其作为单独的状态迁移或蓝绿设计问题处理。
4. 先确定首次应用的意图
在首次应用 v3 前,先确定以下事项:
- Kubernetes 通道策略。
MIGRATION.md说明了默认值的静默变更:v2 使用k3s_channel = "v1.33",v3 使用k3s_channel = "stable",且automatically_upgrade_kubernetes仍默认启用。让用户准确选择以下一项:- 固定
k3s_version - 设置
k3s_channel = "v1.33",以保留 v2 的次版本通道 - 明确接受跟随
stable
- 固定
- 插件版本策略。v2 中未设置或浮动的插件版本会解析为上游最新版本。v3 中未设置的插件版本会使用 kube-hetzner 审核过的确定性默认版本矩阵。升级计划可能会显示一次性的插件版本变更。若要保留浮动行为,必须显式设置为
latest。 - SSH 授权密钥策略。首次应用 v3 时,
terraform_data.ssh_authorized_keys会协调/root/.ssh/authorized_keys。默认情况下,会保留未知的带外密钥,同时撤销已从ssh_public_key或ssh_additional_public_keys中移除的模块管理密钥。只有当用户希望严格替换为恰好包含模块管理密钥时,才设置ssh_authorized_keys_exclusive = true。 - 节点可达性。
terraform_data.initial_readiness会通过 SSH 连接到每个现有控制平面节点和 Agent 节点。仅使用私有网络、NAT 或堡垒机的运维人员必须确保 Terraform 在应用前能够连接到所有节点。
已验证的 2026-07-04/05 标准在线升级,仅需切换模块源,并在首次 v3 计划中设置 k3s_channel = "v1.33"。
5. 初始化并验证
terraform fmt -recursive
terraform init -upgrade
terraform validate -no-color
tmpdir="$(mktemp -d)"
rsync -a --exclude .git --exclude .terraform --exclude .terraform-tofu ./ "$tmpdir"/
(cd "$tmpdir" && tofu init -backend=false -input=false && tofu validate -no-color)
rm -rf "$tmpdir"
terraform validate 会检查模块是否已加载。v3 的跨变量迁移防护由 terraform_data.validation_contract 强制执行,因此,保存的 terraform plan 是验证无效组合和替换风险所必需的依据。
如果验证失败,请在更改配置前查看 variables.tf 中的变量和验证块。
6. 计划
terraform plan -out=v3-upgrade.tfplan
terraform show v3-upgrade.tfplan
terraform show -json v3-upgrade.tfplan > v3-upgrade-plan.json
uv run python /path/to/kube-hetzner/scripts/v2_to_v3_migration_assistant.py --root . --plan-json v3-upgrade-plan.json --strict
严格审计器还会阻止单独分离服务器与网络,并标记已更改或未知的内联私有/公共网络配置。没有服务器替换并不能证明 IP/MAC 得到保留、来宾系统路由持续有效,或滚动发布满足仲裁安全要求。请遵循 MIGRATION.md#network-and-ssh-transition-limits;保留现有 SSH 端口,并在迁移前比较 Cilium 的有效值。
如果有 jq,请列出破坏性操作:
terraform show -json v3-upgrade.tfplan \
| jq -r '.resource_changes[]? | select(.change.actions | index("delete")) | "\(.address): \(.change.actions | join(","))"'
对于正在进行的 v2 -> v3 迁移,请运行受保护基础设施检查。Terraform 替换会显示为包含 delete 的操作列表。该检查仅输出阻止继续的资源;任何输出都意味着必须停止:
terraform show -json v3-upgrade.tfplan \
| jq -r '
.resource_changes[]?
| select(.type as $type | [
"hcloud_server",
"hcloud_network",
"hcloud_network_subnet",
"hcloud_load_balancer",
"hcloud_volume",
"hcloud_primary_ip",
"hcloud_placement_group",
"hcloud_firewall"
] | index($type))
| select(.change.actions | index("delete"))
| "\(.address): \(.type) \(.change.actions | join(","))"
'
完成 v2 重命名后,计划必须显示 hcloud_server、hcloud_network、hcloud_network_subnet、hcloud_load_balancer、hcloud_volume、hcloud_primary_ip、hcloud_placement_group 和 hcloud_firewall 的 destroy/replace 操作为零。如果列出了其中任何类型,请停止并排查,然后再执行 apply。
不要因首个 v3 计划中以下预期操作而惊慌中止:
- 因添加触发器键而重新运行一次幂等的 k3s/RKE2 kustomization
- 新增用于就绪检查、SSH authorized-key reconcile、验证器和销毁清理的
terraform_data资源 - 原地更新服务器标签,例如
kube-hetzner/os - 防火墙规则更新
7. 解读特殊情况
- 从 v2.19 之前的集群替换 NAT 路由器主 IP,可能需要在应用前迁移状态。
existing_network与vswitch_id组合使用时,不能由模块管理expose_routes_to_vswitch;请将其设为 false,或手动启用路由公开。- 仅使用私有网络的集群需要可用的 NAT/堡垒机/控制平面加入路径。
- 多网络公共 Overlay 是仅供实验室使用的预览功能。它要求设置
multinetwork_mode = "cilium_public_overlay"、enable_experimental_cilium_public_overlay = true和cni_plugin = "cilium";在实时数据平面的端到端测试通过前,不要建议在生产升级中使用。 - Tailscale 节点传输已通过静态验证并纳入计划矩阵覆盖,但 Hetzner/Tailscale 实时端到端测试仍待完成。评估时请使用
node_transport_mode = "tailscale",并单独审核计划;不要仅凭静态检查认证生产拓扑。 - Tailscale 模式会将 Kubernetes 节点 IP 保留在 Hetzner 私有地址上,并可在禁用 Tailscale 子网路由 SNAT 的情况下,公开节点私有
/32路由。单网络集群可以禁用路由通告;外部network_scope = "external"节点池必须启用路由通告和 Tailnet 自动批准。 - 外部 Agent/自动扩缩容器 Network ID 必须是正数的 Hetzner Network ID。
省略或设为 null 表示使用主 Network。在 Tailscale 模式下,活动的
Agent/自动扩缩容器节点池还必须设置
network_scope = "primary"或network_scope = "external",以便同一根目录中的外部 Network ID 能在terraform plan期间通过验证。 - 首次原地应用 v2 到 v3 升级时,不要同时添加新的可选 v3 功能,例如
cilium_gateway_api_enabled、embedded_registry_mirror、新的 Tailscale 多网络分片,或外部 Cloudflare Access/Tunnel 路由,除非操作员明确接受蓝绿/拓扑变更迁移。先完成干净升级,再通过单独审核的计划添加这些功能。 - Cloudflare Access/Tunnel 仅适用于外部访问模式。不要虚构 Cloudflare 提供商输入,也不要在迁移期间建议使用 Cloudflare Mesh/WARP 作为 kube-hetzner 节点传输方式。
- v3 默认仍启用 SELinux。对于工作负载拒绝,请使用
docs/selinux.md:收集 AVC 行,优先尝试 udica 生成的工作负载策略;只有在有可复现的 AVC 证据时,才建议上游模块策略;仅将每个节点池的selinux = false作为最后手段。 - 如果用户之后要销毁集群,请从 Terraform 根目录运行
scripts/destroy.sh。它只会针对已知的无害 ingress-LB 分离竞态自动重试 (双重 CCM 与 Terraform 所有权冲突导致的resource_already_detaching/422),然后生成只读孤立资源报告,列出未标记的主 IP、 不在状态中的自动扩缩容节点,以及名称完全匹配的托管 LB。只有在报告显示仍有遗留资源或状态已损坏后,才将scripts/cleanup.sh作为强制回退方案使用。它会将令牌所属的整个 HCloud 项目视为专用于该集群;请先审核试运行结果,并仅在有意为之时包含持久化数据。 - 自动扩缩容器创建的服务器不在 Terraform 状态中,可能阻止删除网络/子网。只有在控制平面关闭后才删除这些孤立资源;或者先将自动扩缩容器节点池缩容至
min_nodes = 0。在 Cluster Autoscaler 仍运行时提前删除,可能会导致这些服务器重新创建。 - 如果在迁移后添加 Cilium Gateway API,必须设置
cni_plugin = "cilium"和enable_kube_proxy = false。 - 如果在迁移后添加内嵌注册表镜像,请提醒用户节点之间具有相同的信任级别,关键镜像应使用摘要。
8. 报告
返回迁移报告:
## kube-hetzner v2 -> v3 migration report
- Terraform root:
- Source version:
- Target version:
- Terraform/OpenTofu version:
- hcloud provider version:
- K3s channel/version intent:
- Kubernetes distribution intent:
- Addon version intent:
- SSH authorized_keys policy:
- SELinux intent and AVC evidence, if relevant:
- Inputs changed:
- Inputs removed:
- Manual state actions:
- Validation result:
- Plan result:
- Protected hcloud delete/replace gate:
- Replacements/destroys:
- Expected first-apply actions:
- Blockers:
- Recommendation:
应用策略
仅在用户明确批准且计划报告中没有未解释的破坏性操作后,才运行:
terraform apply v3-upgrade.tfplan