如何无缝替换运行Airflow作业的GKE Kubernetes集群?
GKE集群无缝替换方案(保留运行中Airflow作业)
问题描述
我需要替换现有GKE集群(而非升级),要求尽可能无缝操作。以往直接销毁旧集群再启动新集群,但本次旧集群有运行中的Airflow作业,必须等这些任务执行完成才能销毁。搜索到的资料大多围绕集群升级或服务低停机升级,关于集群替换的信息很少。
我目前的计划是:
- 创建新集群
cluster-2; - 修改所有指向旧集群的变量,让新工作负载在新集群启动;
- 待旧集群无运行任务时销毁它。
请问有没有更优的替换方案?
背景信息
- 集群运行在GKE环境;
- 因需修改GKE的不可变配置选项,必须替换集群(无法原地修改),未来可能还要执行该操作;
- 使用Pulumi管理资源,不确定Pulumi能否轻松处理此场景,希望得到相关技巧;
- 集群用于运行Airflow作业。
优化方案
你的基础思路是可行的,结合GKE、Pulumi和Airflow的特性,可以做以下优化,让替换过程更平滑、可重复:
1. 用Pulumi资源别名(Aliases)管理集群生命周期
Pulumi默认会把新集群识别为全新资源,可能误删旧集群或者导致资源混乱。通过别名可以让Pulumi将新集群关联到旧集群的资源ID,实现平滑替换:
- 在定义新GKE集群的Pulumi代码中,添加
aliases字段指向旧集群的URN:
替换成旧集群的实际URN后,Pulumi会将新集群视为旧集群的"替换版",不会自动销毁旧集群,你可以手动控制销毁时机,同时保留资源栈的一致性,方便未来重复操作。// 示例(TypeScript),其他语言同理 const cluster = new gcp.container.Cluster("cluster-2", { // 新集群配置 initialNodeCount: 3, // ...其他不可变配置 }, { aliases: [{ urn: "urn:pulumi:prod::my-airflow-stack::gcp:container/cluster:Cluster::cluster-1" }] });
2. Airflow任务的平滑调度切换
针对Airflow作业的特性,避免新旧集群任务冲突:
- 共享元数据库:确保新集群的Airflow连接到同一个元数据库(比如Cloud SQL),这样新集群可以读取任务状态,旧集群继续运行已有任务。
- 暂停旧集群的调度器:在旧集群中执行
airflow scheduler pause(或者通过Airflow UI关闭调度器),只保留执行器运行,让旧集群仅处理已启动的任务,不再接收新任务;新集群启动调度器,接管所有新任务请求。 - 隔离任务执行:如果使用CeleryExecutor,暂时断开旧集群Worker与消息队列的连接(或者让旧Worker只处理现有任务),避免新旧Worker争抢任务。
3. GKE层面的调度隔离
- 给旧集群的所有节点打上不可调度标记:
这样Kubernetes不会再将新Pod调度到旧集群,确保旧集群只运行已有的Airflow任务。kubectl cordon --context=gke_<project>_<region>_cluster-1 --all - 保留共享网络资源:让新集群复用旧集群的VPC、子网、防火墙规则等,避免因网络变更导致Airflow作业依赖的服务访问失败。
4. 自动化收尾(可选)
如果未来需要重复执行集群替换,可以自动化旧集群的销毁流程:
- 用Pulumi的
invoke功能调用GCP API,监控旧集群中运行的Airflow Pod状态,当所有Pod都进入Completed或Failed状态时,自动销毁旧集群。 - 或者在Pulumi栈中添加自定义条件,比如当旧集群的节点数缩为0时,触发销毁操作。
内容的提问来源于stack exchange,提问作者FrustratedWithFormsDesigner
相关产品推荐
相关产品推荐

