一、项目背景
传统运维的痛点与挑战
- 管理分散:不同中间件( Kafka和Elasticsearch)都有独立的管理台,运维逻辑分散,难以形成统一规范。
- 成本高昂:运维操作与各自的管理台强绑定,SRE 需要学习不同工具,操作复杂,维护成本高。
- 黑屏操作依赖:很多关键运维操作需要依赖 kubectl apply 等黑屏命令,操作门槛高,风险大。
Kubernetes与Operator的优势
Kubernetes(K8s)和 Operator 提供了一套通用的运维管理机制,将中间件运维操作抽象成 Kubernetes CR(Custom Resource)对象,由 Operator 负责具体的运维执行。这种模式具备以下优势:
标准化:运维操作可以以 CR 为中心进行统一管理。
自动化:减少了人工干预,降低了人为失误的风险。
可视化:可以通过 UI 平台降低运维复杂度。
平台建设的核心目标
基于上述背景,我们决定建设一个统一的中间件运维平台,目标包括:
二、建设历程
平台架构概览
在展开详细的建设内容前,我们先看看整体的架构设计。本架构图展示了白屏化运维平台的核心组成和各层之间的交互关系,帮助我们更直观地理解平台的整体运作逻辑和功能分布。
运维平台层的核心作用
运维平台层是整个白屏化运维平台的中枢大脑,承上启下,连接用户层与 Kubernetes 集群层,同时对接外部系统,确保运维操作的标准化、自动化和可审计。它的架构图如下:
运维平台层的核心作用.jpeg" />
运维平台的具体作用包括:
多云管理服务
- 统一托管来自不同云厂商的 Kubernetes 集群,确保多云环境下的资源可视化和统一调度。
- 为大规模中间件部署提供基础支撑,保障平台跨云高可用性。
K8s 通用资源管理服务
- 统一管理 Kubernetes 中常见的资源,包括 Node(打标、污点管理)、PV(云盘释放)、PVC(生命周期管理)、SVC(服务暴露与管理)、Pod(日志查看、终端登录、CPU BURST)。
- 减少对黑屏命令的依赖,降低运维风险,提高操作效率。
YAML 管理服务
- 版本管理:提供 YAML 文件的版本控制功能,支持版本新增、修改、回滚 和 差异对比(Diff)。
- 变更可审计:所有 YAML 配置的变更都会被详细记录,确保每次配置变更都可追溯。
- 配置可视化:提供可视化 YAML 编辑界面,降低操作错误率。
操作审计服务
- 平台操作审计:对平台内所有运维操作进行详细记录,确保操作可追溯。
- 对接 DCheck:将审计数据传送至 DCheck 和NOC事件中心,进行合规性检查和安全监控,保障操作安全性和可控性。
运维平台层不仅是各类运维操作的执行中枢,更是数据流通的核心枢纽,负责将用户的运维请求转化为 Kubernetes 资源变更操作,同时记录和审计所有操作,确保系统的安全性和可追溯性。
接下来,我们将深入剖析这些核心服务,看看它们是如何在实际场景中解决痛点、提升效率的。
多云管理:跨云资源托管,告别kubeconfig切换地狱
故事背景
“Kubeconfig 切换地狱,谁用谁知道。”
小卡作为一名资深 SRE,每天都要在多个 Kubernetes 集群之间穿梭,管理不同环境下的资源。这些集群来自不同的云厂商,运行在不同的 Kubernetes 版本上,甚至还有不同的认证和网络策略。
- 传统方式:每个 Kubernetes 集群都需要一个对应的 kubeconfig 文件,存储在本地的 ~/.kube 目录中。
- 上下文切换:每次操作前,需要执行kubectl --kubeconfig=/path/to/kubeconfig,或者使用 kubectl config use-context 切换上下文。
- 风险高:当集群数量增多时,小卡根本记不清当前所操作的集群是 kubeconfig1 还是 kubeconfig2。有时候,为了省事,直接用 cp kubeconfig1 config,再去执行 kubectl 命令,完全忘记当前上下文对应哪个集群。
- 灾难场景:一不小心,将生产集群当成测试集群,直接执行了 kubectl delete pods --all,后果不堪设想。
痛点分析
多 kubeconfig 文件管理混乱
- 每个集群一个 kubeconfig,本地目录下文件堆积如山,管理成本高。
- 使用 kubectl config use-context 切换上下文,容易混淆当前所在的集群。
操作风险高
- 一旦操作上下文错误,轻则资源误删,重则导致生产事故。
- 缺乏有效的权限隔离和审计,无法追踪到具体的操作人和上下文。
跨云兼容性问题
- 每个云厂商的 Kubernetes 集群可能存在不同的 API 版本和兼容性问题。
- 手动管理多个 Kubernetes 版本的集群,风险和维护成本极高。
访问性能瓶颈
- Kubernetes API 请求频繁直接访问集群,容易导致延迟和性能瓶颈。
- 每次查询都需要访问 Kubernetes API,缺乏高效的缓存机制。
解决方案
根据运维同学的痛点,我们计划构建一个多云 Kubernetes 集群管理平台,实现跨云环境资源的统一托管、可视化管理与快速访问,避免 kubeconfig 切换带来的混乱和风险。效果图如下:
目标和行动拆解:
截至目前,平台已跨云托管了30+套Kubernetes集群。
中间件运维:Kafka 扩容,从黑屏脚本到白屏可视化
故事背景
“Kafka 扩容——一个让人捏把汗的运维操作”
凌晨三点,运维小卡的手机突然爆炸式震动起来,屏幕上跳出无数条报警消息:“Kafka 集群负载过高,CPU 使用率接近 100%!”
小卡揉了揉惺忪的睡眼,坐在电脑前打开黑屏终端,迅速敲下一连串熟练的命令:
kubectl --kubeconfig=k8s-xxx-prd get kafka
他屏住呼吸,盯着屏幕上的滚动字符,一行一行地检查 Kafka 集群状态,判断哪些节点资源吃紧,哪些副本需要扩容。然而,每次操作都让他倍感焦虑——“这可是生产环境啊,万一一行命令敲错,就要上新闻头条了!”
- 第一步:修改 YAML,spec.replicas +1。
- 第二步:轮询所有 Pod 状态,检查是否都变为 Running。
- 第三步:调用 Cruise-Control API,触发数据迁移。
- 第四步:轮询数据迁移状态,直到所有分区完成重新分配。
四步流程,看似简单,但每一步都需要小卡屏息凝神,稍有差错,就可能导致数据丢失,甚至集群崩溃。
“这种凌晨抢救场面,为什么不能更简单一点?”
小卡心里忍不住嘀咕。
传统 Kafka 扩容黑屏脚本
在中间件运维场景中,Kafka 集群扩容是一项典型的复杂运维任务。这不仅仅是一个简单的「增加节点」操作,还涉及到集群状态监控、资源调度、数据迁移等多个环节。
传统方式下,SRE 需要通过黑屏脚本完成扩容任务,整个过程不仅繁琐,还充满了不确定性。
以下是一个 Kafka 集群扩容的典型黑屏脚本示例:
#!/bin/bash# 设置 kubeconfig
export KUBECONFIG=/path/to/kubeconfig# 1. 检查 Kafka 集群状态
echo "Step 1: 查询 Kafka 集群状态"
kubectl get kafka -n kafka-namespace# 2. 扩容 Kafka 集群副本数
echo "Step 2: 扩容 Kafka 集群"
kubectl patch kafka my-cluster -n kafka-namespace --type='merge' -p '{"spec":{"kafka":{"replicas":5}}}'# 3. 轮询 Kafka Pod 状态
echo "Step 3: 检查所有 Kafka Pod 是否 Running"
while true; doREADY_PODS=$(kubectl get pods -n kafka-namespace -l app.kubernetes.io/name=kafka -o jsonpath='{.items[*].status.phase}' | grep -o "Running" | wc -l)TOTAL_PODS=5echo "Running Pods: $READY_PODS / $TOTAL_PODS"if [ "$READY_PODS" -eq "$TOTAL_PODS" ]; thenecho "所有 Kafka Pod 已经就绪"breakfisleep 5
done# 4. 触发数据迁移
echo "Step 4: 开始数据迁移"
curl -X POST "http://cruise-control.kafka-namespace.svc.cluster.local:9090/kafkacruisecontrol/rebalance" -d "dryrun=false"# 5. 轮询数据迁移状态
echo "Step 5: 等待数据迁移完成"
while true; doSTATUS=$(curl -s "http://cruise-control.kafka-namespace.svc.cluster.local:9090/kafkacruisecontrol/user_tasks" | grep "COMPLETED")if [ -n "$STATUS" ]; thenecho "数据迁移完成"breakfisleep 10
doneecho "Kafka 集群扩容完成!"
可以看到,传统脚本有以下几个痛点:
多步骤手动介入
- 每个步骤都需要依赖脚本执行。
- 出错后排查困难,且很难进行流程回滚。
缺乏可视化
- 集群状态、Pod 变化、数据迁移进度全靠日志和命令行输出。
- 无法直观了解整体扩容进度。
风险高
- 在生产环境中执行此类脚本,如果操作不当,可能导致服务中断或数据丢失。
- 错误信息分散在多个命令输出中,难以快速定位问题。
不可审计
- 操作记录分散,无法进行完整的审计与回溯。
白屏化平台的 Kafka 扩容
目标:将 Kafka 扩容的整个过程标准化、可视化、自动化,降低操作风险,提升执行效率。
从此,凌晨三点的 Kafka 扩容,变成了这样的场景:
- 打开平台:登录运维平台,进入 Kafka 集群运维界面。
- 点击扩容:输入副本数,点击 “一键扩容”。
- 实时监控:平台自动执行扩容,Pod 状态、资源分配、数据迁移一目了然。
- 完成审计:所有操作都记录在日志中,可随时回溯。
“10 分钟,Kafka 扩容完成,小卡又可以安心地回床上睡觉了。”,如下图:
目前,Kafka和ES在运维中都面临相似的痛点。为解决这些问题,大部分通用的中间件运维操作已被统一收敛至平台。
截至目前,平台已累计托管300+个中间件集群(Kafka: 120+,ES: 180+),完成100+个中间件的运维操作(Kafka: 60+,ES: 40+),累计执行430+次白屏化运维操作(Kafka: 210+次,ES: 220+次),覆盖扩缩容、升降配、数据迁移、重启、重建等常见运维场景,极大提升了运维效率与操作稳定性。
Node管理:从黑屏脚本到白屏化平台
故事背景
“凌晨三点,ES集群扩容需求紧急上线。”
运维小哥小吴接到告警电话,ES集群节点资源已接近饱和,业务性能明显下降。扩容节点,是当务之急。
然而,扩容并不是简单地加几台机器那么轻松。Node打标是扩容的关键前置步骤,如果节点没有正确打标,Pod将无法被调度到对应的资源池,扩容将直接失败。
在过去,Node 资源调度和打标是一项高风险、高强度的任务。需要依赖脚本在黑屏终端中逐台节点检查 CPU、内存、磁盘类型、可用区 等指标,然后筛选出符合条件的节点进行打标和调度。
如果某个细节疏忽——比如忘记检查污点、磁盘挂载数量超标,轻则导致扩容失败,重则影响整个业务链路。
传统黑屏脚本分析
在传统的 Node 筛选脚本中,我们依赖 kubectl 命令逐个检查节点的各类资源指标,并进行节点筛选。以下是小吴编写的一个典型的黑屏脚本示例:
public class ESNodeSelectorTest {public static void main(String[] args) {//cpu核心数int needCpu = 9;//内存容量Gint needMemory = 33;//磁盘类型DiskType needDiskType = DiskType.efficiency;//可用区Zone zone = Zone.cn_shanghai_m;//标签String label = null;//集群名称String clusterName = null;//开始自动筛选selectNode(label,zone,needCpu,needMemory,needDiskType,clusterName);}public static void selectNode(String label,Zone zone,int needCpu,int needMemory,DiskType diskType,String clusterName){String getNodes = "kubectl get node -l ";String segment;if(label!=null){getNodes += label;}else {if (zone != null) {segment = "topology.kubernetes.io/zone=" + zone.name().replaceAll("_", "-");getNodes += segment;}}String nodes = executeCommand("/bin/bash", "-c", getNodes);String[] nodeList = nodes.split("\n");String describeNode;int lineCount = 0;for (int i = 1; i < nodeList.length; i++) {String node = nodeList[i].split(" ",2)[0];if(lineCount>4){lineCount = 0;System.out.println();}lineCount++;System.out.print(node);if(isMaster(node)){continue;}describeNode = "kubectl describe node " + node +" | grep 'Taints\\|cpu \\|memory ";//...太多了...省略...}}}public static String executeCommand(String... command){try {Process process = Runtime.getRuntime().exec(command);//...}catch (Exception e){throw new RuntimeException("kubectl apply exception:",e);}}
}
可以看到,传统方式有以下几个痛点:
操作复杂
- 需要编写和维护复杂的脚本。
- 每次执行都需要逐节点检查,耗时长,效率低。
高风险
- 稍有疏忽(如忘记检查污点、CPU 余量计算错误)可能导致资源分配失败。
- 整个过程缺乏可视化,排查问题难度大。
响应慢
- 在业务高峰期,这种人工节点筛选方式无法快速响应突发需求。
白屏化平台的 Node 管理
目标:
将 Node 资源管理的整个流程标准化、自动化和可视化。
设计思路:
1.指标可视化
- 在白屏界面上展示 Node 的 CPU 分配/使用率、内存分配/使用率、磁盘类型、标签、污点等关键指标。
2.多维度筛选
- 支持通过标签、污点、CPU/内存余量、磁盘类型、可用区等维度快速筛选节点。
3.批量打标与调度
- 支持批量打标和污点管理,减少人工操作的复杂性。
4.资源状态实时更新
- 实时展示节点资源的可用性,避免资源分配冲突。
在大促扩容场景中,平台已累计完成了 280+ 台 Node 的打标与调度。原本1小时+的 Node 筛选和打标操作,现在只需要 3 分钟 。
PV云盘管理:打破孤盘与繁琐操作的枷锁
故事背景
“集群删了,PV 留下了,云盘成了‘孤儿’。”
一次运维例会中,小宋提到这样一个现象:当中间件集群被释放后,原先挂载的 PV 和云厂商的云盘并不会自动删除。更让人头疼的是,云厂商云盘的标签只有两个关键字段,这里以某云为例:
- k8s.yun.com : true
- createdby: alibabacloud-csi-plugin
当集群被销毁,这些标签几乎无法追溯到云盘的真正使用方。出于风险考虑,这些云盘被闲置着,无人敢于释放,久而久之,闲置云盘成堆,云成本居高不下。如下图:
痛点分析
云盘归属无法追溯
手动释放繁琐
- 集群节点释放后,通常 PVC 资源会被删除,但 PV 依然保留。
- 运维团队需要借助机器人或定期巡检手动查找闲置 PV。
- 每次释放云盘都需要手动在云厂商管理台完成,流程繁琐,耗时长。
流程缺乏闭环
- 云盘释放 → 成本中心审批 → 云厂商控制台删除 PV,整个流程需要跨平台、跨系统完成,且容易出错。
解决方案
目标:实现 PV 云盘资源的可视化、自动化管理,打通从 Kubernetes 到云厂商的全链路操作流程。如下图所示:
目标和行动拆解:
截止目前,平台已累计释放了 675+ 块闲置云盘,每月节省云成本约 15+万元。操作时间从15 分钟+缩短到 1 分钟。且所有操作均可审计与回溯,保障了运维安全性。
CPU Burst 管理:关键时刻的“应急电源”
故事背景
“高峰期 CPU 100%,服务卡成 PPT?”
一次业务高峰来临,ES 集群的 CPU 使用率迅速飙升到 100%,多个关键服务开始响应迟缓,甚至部分 Pod 被强制驱逐。运维同学小宋看着监控大屏上的红色告警,不禁捏了一把汗。
在传统运维方式下,CPU 资源一旦达到极限,唯一的解决方案就是扩容,但扩容并非瞬时可完成的操作,往往需要排查资源、调度 Pod、重启服务,甚至等待新节点的资源分配。而这些步骤,在高并发、高压力场景下,每一秒的延迟都是用户体验的巨大损失。
痛点分析
资源调度滞后
- CPU 资源短缺时,传统调度往往依赖于扩容,响应时间较长。
- 在高并发场景下,调度效率决定了系统的生死。
临时应急难
- 当 CPU 达到瓶颈,传统 Kubernetes 无法临时突破 CPU 限制,服务只能停滞或被驱逐。
解决方案
目标:在高压场景下,通过 CPU Burst 管理功能,允许关键 Pod 在短时间内突破 CPU Limit 限制,保障服务稳定性和业务连续性。如下所示:
截止目前, CPU Burst 已在 10+ 套 Kubernetes 集群 和 30+ 套 ES 集群 中启用。在高并发场景下,有效解决了 CPU受限和CPU使用率瓶颈问题,提升了服务稳定性。
YAML 管理服务:让配置变更安全、可控、可回滚
故事背景
“一行 YAML,毁灭一个集群。”
在 Kubernetes 的运维场景中,YAML 配置文件是所有资源操作的核心。无论是 Pod 调度、Service 暴露,还是 ConfigMap 更新,所有的操作都离不开 YAML 文件。
但 YAML 配置管理往往充满风险:
- 一行配置错误:可能导致整个服务不可用。
- 版本混乱:配置文件缺乏版本管理,一旦出错,回滚难度极大。
- 缺乏审计:每次变更是谁做的,变更了哪些内容,几乎没有清晰的记录。
- 人工操作:黑屏模式下,直接通过 kubectl apply 修改 YAML,出错率极高。
“运维人员常说:‘YAML 是 Kubernetes 的灵魂,但也是运维事故的导火索。’”
痛点分析
版本管理缺失
- 没有完整的 YAML 文件版本历史记录。
- 配置错误难以回滚,出错后很难快速恢复。
变更审计不透明
- 谁修改了配置?
- 修改了哪些内容?
- 修改的原因是什么?
- 缺乏详细的审计日志,责任难以追溯。
手工变更风险高
- 直接使用 kubectl apply 进行 YAML 修改,存在人为输入错误的风险。
- 缺少可视化的配置变更比对工具,难以进行精确的差异分析。
变更回滚复杂
- 配置变更失败后,回滚通常需要手动恢复之前的版本。
- 缺乏自动化的回滚机制,出错后容易引发连锁反应。
解决方案
目标:通过YAML 管理服务,将 Kubernetes YAML 配置的版本管理、变更审计、回滚机制 和 可视化管理 集中整合到平台中,降低人为操作风险,提升变更效率和安全性。如下所示:
三、项目收益总结
经过三期建设,白屏化运维平台已从概念验证逐步发展成为覆盖全场景运维的高效工具,取得了显著的成果和收益,主要体现在以下几个方面:
运维标准化与规范化
- 统一运维流程:通过平台白屏化界面,规范了 Kafka、ES、Node、PV、PVC、SVC、Pod 等核心运维场景,减少了操作流程的随意性。
- 最佳实践沉淀:在每个运维场景中,平台积累并固化了标准化的运维流程与策略,降低了运维操作的失误率。
- 减少人为依赖:降低了对资深运维人员的依赖,新手 SRE 也可以在平台指引下完成复杂运维操作。
运维效率显著提升
-
操作效率:
Node 打标与污点管理从 1小时+ 缩短至 3分钟。
PV 云盘释放从 15分钟+ 缩短至 1分钟。 -
高效应急响应:在 CPU Burst 管理的支持下,有效缓解高并发场景下的 CPU受限和CPU使用率瓶颈问题,保障业务连续性。
-
批量化管理:支持 Node、PV、PVC、SVC、Pod等资源的批量管理,减少重复性操作,提高资源调度效率。
成本优化与资源利用最大化
- 资源回收:累计释放 675+ 块闲置云盘,月均节省云成本 15+万元。
- 资源高效分配:通过 Node 筛选与 PV优化管理,有效提升了资源利用率,避免资源浪费。
- 跨云资源托管:统一管理来自不同云厂商的 Kubernetes 集群,避免因平台差异导致的资源闲置。
安全性与可审计性提升
业务稳定性与可扩展性
四、经验总结与反思
在三期的建设和落地过程中,我们积累了宝贵的经验,也发现了一些可以优化和提升的空间。以下是关键经验和反思:
以标准化为核心
技术与流程的深度结合
强化审计与合规
- 全链路审计:所有操作均有详细的审计记录,确保运维行为可追溯、可还原。
- 合规检查:对接 DCheck 系统,实时进行合规检查,避免风险隐患。
面向未来的架构设计
遇到的挑战
- 与KubeOne平台无法融合:KubeOne平台主要面向无状态服务的运维,而白屏化平台主要面向有状态服务的运维,二者无法融合。
- 多场景运维复杂度:不同中间件和 Kubernetes 资源类型的运维逻辑存在差异,初期难以统一抽象。
- 持续优化测试流程:部分场景的测试覆盖率还有待提升,未来需持续加强单元测试和集成测试。
五、未来展望
白屏化运维平台的未来,将持续以“标准化、可视化、智能化”为核心,不断拓展运维场景,降低运维门槛,提升运维效率与安全性。
- 扩展更多 Kubernetes 运维场景:实现更多 Kubernetes 资源(如Deployment、StatefulSet、 Ingress、ConfigMap、Secret)和自定义资源(DMQ、Pulsar、ZK)的白屏化运维支持。
- 引入智能化运维:基于案例匹配、数据挖掘或总结最佳实践,实现故障自愈、资源动态调度和智能告警。
- 持续优化用户体验:通过用户反馈持续改进平台功能,优化运维操作流程,降低运维心智负担。
- 加强多云资源管理能力:支持更多云厂商 Kubernetes 集群的接入,提升平台的多云资源管理能力。
文 / 初澜
关注得物技术,每周更新技术干货
要是觉得文章对你有帮助的话,欢迎评论转发点赞~
未经得物技术许可严禁转载,否则依法追究法律责任。