ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

混合云K8s部署平台实战:网络、调度与自动化运维全解析

混合云K8s部署平台实战:网络、调度与自动化运维全解析 1. 选型阶段为什么不能简单做“两套K8s各管各的”很多团队一听到“混合架构”第一反应是云上一套K8s机房一套K8s两边各管各的中间靠同步任务把数据对一下不就行了我一开始也这么想。直到真的深挖需求才发现这套思路在业务规模小、环境边界清晰的时候没什么问题但当你要做的是一个“部署平台”而不是“两个独立的部署入口”时事情就完全不一样了。1.1 混合架构真正要解决的三个问题我当时面对的存量环境是这样的核心数据库和部分合规要求高的服务跑在自有机房新业务、前端应用、AI训练任务跑在云上。表面上只是“资源位置不同”实际上牵出三个必须解决的问题。第一是资源统一调度。业务方不关心资源在哪他们只关心“我的服务有没有地方跑、能不能按时发布”。如果两套集群完全隔离发布时就要人肉判断“这个服务该发到哪里”一旦某个环境资源紧张想临时借调另一边的算力根本做不到。我想要的是一份声明式配置让调度器根据资源现状决定跑在哪哪怕跨云上云下。第二是网络连通性。云上和机房之间虽然有专线但K8s的Pod网络、Service网络、DNS解析默认都是以“单集群单网段”为前提设计的。两套独立集群之间服务互相调用要绕外部域名、要过防火墙、要配额外的负载均衡链路长了故障点也多了。第三是部署一致性与发布流程的统一。异构环境最大的痛点不是“跑不起来”而是“同一个版本在云上能跑在机房跑不起来”。镜像构建、配置渲染、发布策略、回滚机制都需要同一套逻辑来驱动否则测试环境验证过的版本上了生产照样出事。想清楚这三点之后结论就很明确我需要的是一个“能把云上和机房看成同一片资源池”的K8s部署平台而不是两个独立环境。1.2 “一套集群跨节点”与“多集群统一纳管”的取舍这个阶段我调研了两个主流方向。方向一是把云上节点和机房节点放进同一个K8s集群靠节点标签区分区域。这个方案的好处是调度最自然Service、DNS、监控全部天然统一业务方完全无感。缺点是要求云上VPC和机房网络在二层或三层打通且集群的控制面必须放在网络质量最好的一侧。如果两台节点之间的延时超过几十毫秒kubelet与kube-apiserver的心跳、etcd的读写都会变得很不稳定。方向二是多集群管理也就是机房和云上各自维护集群由上层平台统一接入、统一分发应用。这个方案隔离性好、爆炸半径小但代价是Service之间的互相调用又绕回“跨集群网络”的问题而且发布、监控、日志都需要额外的聚合层。我最终的选择是“混合起来用”核心在线业务用一套跨节点集群把机房和云上节点统统纳进来保证服务调用的低延迟和统一调度而一些需要独立管控、合规隔离的任务类业务放在单独集群里由上层自动化平台统一发布。这个折衷方案在当时的业务体量下是性价比最高的。1.3 为什么我没有选KubeEdge那类边缘方案调研中有人提过KubeEdge和OpenYurt理由是它们天然支持“云上中心 远端节点”的混合形态。我专门搭了个demo试了试最后放弃了原因是它们的核心场景是“边缘节点”假设的是弱网、断连、离线自治而机房和云之间明明是稳定专线根本不需要那套复杂的边缘消息通道。KubeEdge引入的CloudCore、EdgeCore组件每台节点都要多养一个进程控制面链路多了一跳排障的时候多一层黑盒。相比直接CNI打通网络的方案它带来的优势在我这个场景里几乎用不上维护成本却实实在在增加了。所以我的建议是混合架构的技术选型不要为了“听起来符合云原生”而选择复杂方案先问清楚自己的网络条件和延迟预算。2. 网络打通云上VPC与机房专线之间的几个硬坑网络是整个混合架构的底座这一步做不好后面所有自动化和调度都是空中楼阁。我在这里踩的坑比后面任何一部分都多所以单独拿出来讲。2.1 跨地域节点对CNI的要求第一个要做的决策是选CNI插件。混合集群和普通单机房集群不一样它要求CNI能处理多网段、多路由域而且最好支持IP路由的自动学习。Flannel在这个场景里基本可以直接排除。它默认用VXLAN或host-gateway的方式做OverlayVXLAN模式下所有跨节点流量都要封装性能损耗明显host-gateway模式虽然性能好但要求所有节点在同一个二层网络云上VPC和机房网络明显不满足。我对比之后选定的是Calico。它用BGP协议在节点间交换路由信息不需要所有节点二层互通只要三层路由能到达就行正好匹配“云上VPC 机房专线”的网络格局。Cilium我也测过eBPF的转发性能确实强但那套内核依赖和运维配套在当时的内部环境里还不够成熟。如果你的内核版本足够新、团队对eBPF有经验Cilium是很不错的选择否则Calico是最稳妥的。2.2 我踩过的MTU坑专线上的传输黑洞这是我在混合集群里踩过最莫名其妙的一个坑值得所有做跨地域K8s的人注意。Calico默认IPIP模式会把Pod流量封装在IPIP隧道里。云上VPC的MTU一般是1500机房内网有时候是1500有时候是9000。隧道封装之后报文头变大如果链路里有一段MTU限制比较小就会出现一个极其隐蔽的问题小包能通大包不通ping通了但ssh卡住HTTP能连上但页面加载到一半就断。我一开始以为是防火墙规则问题排查了半天。最后是在一条专线设备上抓包才发现ICMP返回的Fragmentation Needed报文被专线设备丢弃了形成了典型的PMTU黑洞。解决办法是把Calico IPIP隧道的MTU手动调小到1400左右保证封装后的报文不会超过专线允许的最大值。这个数字最好由实际链路决定先用ping -M do -s 逐步测出链路最大MTU再减去隧道头开销得到的就是CNI应该配置的MTU。2.3 Service网段与Pod网段的冲突问题混合架构里经常出现一种低级但致命的错误云上VPC网段、机房内网网段、K8s Pod网段、Service网段四者之间出现重叠。比如机房内网用了172.16.0.0/16你给K8s Service规划网段的时候也顺手写了172.16.0.0/16那么当Pod要访问Service地址时报文可能被路由到内网设备直接石沉大海。更麻烦的是这种冲突往往不会在部署早期暴露因为大部分流量都在集群内部一旦接入某个需要从Pod直连机房内部系统的服务问题就立刻炸开。所以集群网络规划务必在动手之前完成。我最后定下的分配思路是机房内网与云上VPC统一分配段互不重叠Pod网段单独划一个大段按可用区/节点池再切分Service网段单独划一段避开所有真实网络。这个规范写成文档发给所有相关团队当成上线前置检查项之一。2.4 ClusterIP与外部负载均衡之间的路由细节混合集群里节点分布在不同地域当Service类型是NodePort或LoadBalancer时访问路径很容易踩坑。机房节点的公网入口和云上负载均衡是两套体系同一个Service在云上节点暴露的NodePort端口与机房节点上是相同的但外部流量只通过云上LB进入机房侧的健康检查路径也要单独打通不然LB会把机房节点标成不健康流量全部压到云上节点。我把这个逻辑用拓扑图梳理之后才意识到混合集群的负载均衡不能只看“Service能不能访问”还要看“每个节点在负载均衡视角里是不是健康的”。这个点如果你不主动处理等流量上来才发现某一边节点全被摘除就晚了。3. GitOps与流水线自动化部署平台真正的主干网络通了之后整个平台的价值就开始体现在“自动化”上。我的核心思路是所有部署行为不是“点按钮触发”而是以Git仓库为唯一事实来源通过GitOps让集群状态自动收敛到期望状态。3.1 为什么选GitOps而不是传统CI/CD“一键部署”团队里之前用过Jenkins UI点按钮的方式做得多了问题就很明显每次发布运维要手动选分支、填参数、点构建压力一大就会点错而且整个流程没有版本痕迹出问题只能靠聊天记录追溯“当时点了什么参数”。GitOps把思路倒转过来部署动作不是“执行一条命令”而是“提交一次代码变更”。你要发布什么版本、改了什么环境变量、升级到什么镜像tag全部通过Git提交记录来体现。集群里的AgentArgoCD持续对比Git仓库里的期望状态和集群里的实际状态一旦发现偏差立即自动同步。这个模式的好处不仅是“自动”更重要的是“可审计”和“可回滚”。发布到一半发现异常我不需要重新构建、不需要找历史参数只要把Git回退到上一个commitAgent会自动把集群拉回旧版本。3.2 自动化流水线的实际设计我最后落地的流水线分四段CI阶段代码推送到GitLab/GitHub后触发自动构建生成镜像并推送到私有镜像仓库。镜像tag使用commit SHA保证不可变、可追溯。清单生成阶段根据Git仓库中的Helm Chart和values文件渲染出每个环境、每个集群的目标清单。GitOps同步阶段ArgoCD Agent监听Git仓库变化自动同步到对应的K8s集群。发布策略阶段对重要服务配置Argo Rollouts实现金丝雀发布和滚动发布的可控灰度。这里最关键的设计是“一个镜像 多环境values参数”。测试环境、预发环境、生产环境共用同一个镜像只是通过不同的values文件注入环境差异。这样能保证“测试通过 生产大概率没问题”消除“环境不一致”这个经典事故源。3.3 Helm values的分层管理实践多环境管理我一开始用Kustomize后来转向Helm。原因很简单Kustomize适合做“小补丁”但混合架构下有大量环境差异比如云上集群需要StorageClass指定云盘机房集群需要指定本机存储用了很多“通用补丁”之后很难看清楚每个环境真正的全貌。Helm的做法更直白一个Chart描述应用本身values目录下按“环境/集群”分层放参数覆盖文件。目录结构大概是charts/ ├── my-service/ │ ├── Chart.yaml │ ├── templates/ │ └── values.yaml # 默认参数 └── envs/ ├── dev/ │ ├── values.yaml # 开发环境覆盖 │ └── secrets.yaml ├── prod-cloud/ │ └── values.yaml # 云上生产 └── prod-onprem/ └── values.yaml # 机房生产ArgoCD同步时只需要为每个环境创建对应的Application资源指定Chart路径和values文件路径即可。整个发布过程非常清晰开发改代码GitOps负责剩下的一切。4. 节点池、污点与异构资源让部署调度有的放矢混合集群的节点类型很多云上虚拟机、裸金属服务器、GPU服务器、高内存机器。如果调度器一视同仁地分发Pod很快就会发现有些Pod被调度到配置不够的节点上直接OOM有些GPU任务跑到纯CPU节点上一直启动失败。所以节点分组和调度约束是必须提前设计好的。4.1 节点标签与污点的设计思路我给节点打了几类标签具体如下标签键取值示例用途topology.kubernetes.io/zonecloud-az-a/onprem-rack1标识节点物理位置node-poolgeneral/gpu-a100/highmem标识节点规格池node-rolecompute/infra区分业务节点与基础设施节点同时给特定节点加上污点Taint防止默认调度器把普通业务Pod调度到不适合的节点上。比如GPU节点加nvidia.com/gputrue:NoSchedule只有声明了GPU资源需求的Pod才允许调度过去基础设施节点加node-roleinfra:NoSchedule只运行监控、日志这类系统组件。这类配置的价值在实际故障中体现最大。某次机房一侧的两台机器同时宕机业务Pod被重新调度时调度器因为有污点约束没有把任务错误地塞到GPU节点上避免了大规模启动失败。4.2 CPU与内存资源限制的教训混合架构下节点规格差异大资源requests和limits如果不合理调度器很难做出正确决策。我遇到最常见的两种情况 一是requests设置过小Pod被调度到小规格节点上运行一段时间后因内存超卖被OOMKilled服务反复重启 二是requests设置过大集群明明还有很多剩余资源调度器却认为无处可去导致资源浪费。我在这个平台上线初期调整过一轮方法是先给每种服务规范“基础requests”然后通过压测数据逐步上调最后定下不同服务类型各自的资源水位参考。这套参数不是一次就能定准的需要长期观察和调整但一定要有否则调度器就是个瞎子。4.3 GPU资源调度的实际操作混合架构里GPU资源最金贵也最容易起冲突。我的平台上GPU节点都在云上机房侧没有GPU所以调度约束必须保证GPU任务只能落到特定云上节点。底层实现其实简单节点上安装NVIDIA device plugin之后K8s就能识别nvidia.com/gpu这个资源。调度约束靠的是前面说的污点和节点选择器。部署GPU任务时在Pod模板里声明resources: limits: nvidia.com/gpu: 1 nodeSelector: node-pool: gpu-a100 tolerations: - key: nvidia.com/gpu operator: Exists effect: NoSchedule实测下来这套配置本身很稳定。真正的坑在于GPU任务排队和超卖。因为K8s默认不支持“GPU显存配额”只能做到整卡分配如果一个团队只需要8GB显存但一张卡有80GB剩下72GB就闲置了。后来我们引入了MIG切分方案把A100按显存切分成多个实例才把利用率提上去。但这需要底层驱动和硬件支持不是所有卡都能切接入之前一定要先验证。5. 多集群高可用与故障转移平台稳定性的最后防线自动部署平台跑起来之后下一个必须考虑的问题是万一某个集群整体挂了业务怎么办尤其混合架构里涉及机房节点和云上节点任何一个区域的故障都不能让所有服务全军覆没。5.1 三台Master的高可用配置经验很多面试题都会问“K8s三台Master怎么保证高可用”但实际落地是完全不同的工程量。控制面高可用的本质是多个kube-apiserver实例前面要有一套负载均衡etcd要能容忍少数节点故障。我用KubeKey搭建的时候走的正是这个架构。KubeKey会自动部署三节点etcd和多个master副本。关键是要在外面再架一套负载均衡把访问kube-apiserver的流量分发到三台master上。这套LB如果是自建的需要再部署Keepalived加VIP或使用云上的负载均衡器总之要让kubelet和kubectl永远走同一个稳定入口。不要裸连某一台master的IP一旦那台master重启整个集群的控制面就断了。5.2 多集群之间的应用分发我之前说过核心在线业务放在一套混合集群里但容灾场景下这套集群也有整体故障的风险所以又单独维护了一个备用集群。两个集群间的应用分发用的是ArgoCD的ApplicationSet机制同一个Git仓库会被同步到多个集群只需要为每个集群维护一个Application即可。这个设计的额外好处是新集群接入平台非常快只要把新集群的kubeconfig导入ArgoCD定义好对应环境目录平台自动开始同步不需要人工重复配置。集群数量多了以后这种“声明式接入”的能力比想象中重要得多。5.3 故障转移时真正难的不是Pod是数据我实测做了几次故障演练发现Pod拉起是最简单的部分。真正复杂的是有状态服务尤其是数据库。云上和机房之间的存储是完全隔离的跨环境迁移意味着数据要重新同步耗时取决于数据量根本不是几分钟能搞定的。所以在混合架构平台里我对有状态服务的容灾策略是存量数据库继续留在原位置通过平台外的双向同步链路保持数据一致平台只负责把无状态应用在故障时切到备用集群等数据同步追上之后再把有状态服务切过来。这个策略牺牲了一部分“全自动”但换来了更可控的风险边界。6. 监控与日志混合集群运维的“眼睛”自动化部署平台上线之后如果没有一套能覆盖所有节点的监控体系你再怎么自动化也是盲人摸象。这一块我用的组合是Prometheus Alertmanager Grafana日志采集走Loki。6.1 Prometheus监控K8s的部署要点我用kube-prometheus-stack Helm Chart部署监控栈。与单集群部署不同的是混合集群里必须确认以下几点监控组件要能发现所有节点。cAdvisor指标来自每个kubelet只要kube-apiserver可达Prometheus就能通过ServiceMonitor自动发现不需要为每个节点单独配置。网络指标采集要覆盖跨节点路径。我额外部署了Node exporter并在每个节点上抓取网络接口的吞吐和丢包数据方便定位是云上链路还是机房链路出了问题。告警要按区域区分。机房节点的网络中断与云上节点的网络中断处理方式和影响面完全不同。我给告警规则都加上了每个节点的zone标签保证告警消息里能直接看出地域信息。6.2 日志统一收集的细节混合集群的日志采集我用了Loki Promtail。Promtail以DaemonSet方式跑在每个节点上采集容器标准输出和文件日志。这里遇到的问题是云上节点默认系统日志审计策略与机房节点不同只采集应用日志还好一旦要采集系统日志和审计日志格式和内容都对不上。我最后统一了所有节点的采集路径并做了一个简单的日志字段标准化把环境标签、集群名称、节点名称都加进去这样在Grafana里可以按任意维度过滤排查问题效率提升非常明显。6.3 告警规则设置的几点心得告警规则我踩过几个坑简单说三条。一是不要因为怕噪音就关掉关键告警。我最初把节点内存使用率告警阈值调得过高结果某次内存缓慢增长直到OOMPrometheus一直没触发业务挂了一半才被人发现。宁可规则多一些、信息全一些也好过“完全静默”。二是告警要带上处置建议。Alertmanager的通知模板里加上“先看什么指标、再查什么Logs”值班的人不用翻文档就能开始处理。这个东西一开始做的时候觉得费事实际命中的时候就知道有多值钱。三是避免“告警风暴”。某个区域网络抖动时节点NotReady、Pod驱逐、应用延迟升高三个规则会一起触发。我给这些规则设置了不同的持续时间和优先级比如节点NotReady持续5分钟后才告警Pod重启3次以上才告警把噪音压到一个可控的水平。7. 踩坑复盘那些让平台“差点翻车”的细节最后专门写一部分复盘记录那些在项目推进过程中容易被忽视但一旦踩中就会让人怀疑人生的细节。都是真实遇到的问题。7.1 依赖拓扑导致的容器启动顺序混乱有状态服务依赖数据库数据库依赖初始化任务初始化任务又依赖配置中心。在K8s里多个Workload之间的启动顺序是不受控的全靠容器本身的“重试直至成功”逻辑来兜底。我一开始没给服务写初始化容器和readinessProbe的正确顺序导致平台刚上线时经常出现“A服务连不上B服务”的启动报错。解决办法是每个服务必须配好readinessProbe且依赖服务的InitContainer要先行完成一次“连通性探测”。这段逻辑写起来不复杂但不提前做的话每次重启集群都是一次手忙脚乱的救火。7.2 kubeconfig证书过期导致的“平台失联”混合架构让K8s集群数量变多之后kubeconfig的管理就成了隐藏风险。集群证书默认有效期一年到期后如果平台侧的kubeconfig没有同步更新ArgoCD、监控系统都会失去集群的连接表现出来就是“整个平台突然什么都操作不了”。这个问题我对其重视程度极高后续直接把证书轮转加进了自动化任务每天检查集群证书剩余时间不足30天自动告警并触发轮转流程。不做这一步的话下一个“证书过期事故”一定会发生在你最不想它发生的时刻。7.3 网络策略误伤跨区域访问在混合集群里如果启用了NetworkPolicy要格外小心跨区域的规则。我遇到过一个问题开发环境在云上开发人员通过跳板机进入机房集群调试结果NetworkPolicy默认拒绝所有非白名单来源跳板机的IP不在规则里连接全部被拒排查了一个多小时才找到原因。在网络策略的规划上建议先观察一段时间实际访问关系再渐进式收拢白名单。不要一开始就严格限制否则很容易在调整过程中误伤正常业务反而引发事故。7.4 给后来者的建议总结如果让我重新做一遍我会在项目初期就定好三件事网络规划文档先于集群建设把所有网段、路由、MTU、专线情况画清楚再动手一个应用一个分支的自动化清单把CI、GitOps、监控、日志从第一天就纳入统一管理不要等集群跑起来再补定期做故障演练尤其是跨区域节点宕机的模拟很多问题只会在演练时暴露出来。混合架构本身不是一个“新东西”它更多的是一套取舍和精细化工程网络怎么通、调度怎么控、发布怎么做、故障怎么恢复每一步都可以用标准K8s能力实现但需要你针对自己的业务场景做出正确的选择。这也是做基础设施平台最有意思的部分。
返回列表