Kubernetes MCP服务器:构建AI友好的K8s可编程接口
1. 项目概述:当Kubernetes遇见MCP
最近在琢磨怎么把Kubernetes集群的管理和监控做得更“丝滑”一些,尤其是在需要和各类AI助手、自动化工具打交道的时候。传统的kubectl命令行虽然强大,但它的输出是给人看的,对于程序来说,解析起来总有点费劲。就在这个当口,我发现了alexei-led/k8s-mcp-server这个项目。简单来说,它就是一个为Kubernetes量身定制的MCP(Model Context Protocol)服务器。
MCP这个协议,你可能在跟Claude、Cursor这类AI工具集成时听说过。它本质上定义了一套标准,让AI模型能够安全、结构化地访问外部工具、数据和功能。而这个k8s-mcp-server项目,就是架在Kubernetes API和MCP客户端(比如一个AI助手)之间的一座桥。它把Kubernetes里那些复杂的资源对象、状态信息,翻译成了MCP协议能理解的“语言”——主要是结构化的JSON数据,并通过SSE(Server-Sent Events)或HTTP长轮询提供实时更新。
对我而言,这个项目的核心价值在于**“可编程的K8s操作界面”**。它解决的痛点很明确:当你希望一个自动化脚本、一个聊天机器人或者一个低代码平台去查询集群状态、执行简单运维操作(如扩缩容、查看日志)时,你不再需要去费力地解析kubectl get pods -o json那一大坨输出,或者自己去处理K8s Go Client那略显繁琐的认证和连接。你只需要让工具去“问”这个MCP服务器,它就会返回干净、标准的数据。这特别适合构建一些智能运维看板、自动化巡检工具,或者为团队提供一个更友好的、对话式的集群管理入口。无论你是运维工程师、平台开发者,还是对K8s自动化感兴趣的极客,这个项目都提供了一个非常有意思的切入点。
2. 核心架构与设计思路拆解
2.1 为什么是MCP?协议选型的深层考量
在决定为Kubernetes构建一个外部接口时,可选方案其实不少:直接暴露K8s API(风险高)、自己写一套RESTful API(工作量大)、或者用GraphQL包装(灵活但复杂)。k8s-mcp-server选择MCP,我认为是经过深思熟虑的,主要基于以下几点:
首先是生态契合度。MCP协议的设计初衷就是为AI模型提供扩展能力,而当前AI在运维(AIOps)、代码辅助领域的应用正是热点。使用MCP,意味着这个服务器可以“即插即用”地接入任何支持MCP协议的客户端,比如Claude Desktop、Cursor,以及未来可能出现的更多AI原生工具。这比要求每个工具都去适配K8s API要容易得多。
其次是协议本身的优势。MCP强调资源(Resources)和工具(Tools)两个核心概念,这与Kubernetes的“一切皆资源”哲学不谋而合。Pod、Deployment、Service这些K8s资源,可以很自然地映射为MCP的“只读资源”;而像“执行命令”、“查看日志”这类操作,则可以映射为MCP的“工具”。协议内置的结构化数据格式(JSON)和实时更新机制(SSE),完美匹配了监控集群状态变化(如Pod重启、事件发生)的需求。
最后是安全与标准化。MCP协议规范了认证、传输和边界,服务器作为代理,可以集中实现访问控制、审计日志和速率限制,避免客户端直接接触敏感的K8s API Server证书。它提供的是一个受控的、功能子集化的视图和操作集,安全性比直接暴露API高出一个层级。
2.2 项目整体架构与数据流
这个项目的架构非常清晰,是一个典型的三层模型:
- MCP客户端层:例如Claude Desktop。用户在这里用自然语言提出请求,如“列出default命名空间下所有运行异常的Pod”。
- k8s-mcp-server层(核心):这是项目本体。它同时扮演了两个角色:
- MCP服务器:监听来自客户端的连接,解析MCP协议请求(如
resources/list,tools/call)。 - Kubernetes客户端:使用
kubeconfig或ServiceAccount与真实的K8s API Server建立连接。
- MCP服务器:监听来自客户端的连接,解析MCP协议请求(如
- Kubernetes集群层:实际的容器编排平台。
数据流向是这样的:客户端请求 -> MCP协议封装 ->k8s-mcp-server接收并解码 -> 转换为对应的K8s API调用(如调用Client-go的List方法)-> 获取K8s API响应 -> 将响应数据格式化为MCP协议规定的JSON结构 -> 返回给客户端。
这个设计的关键在于适配器模式。服务器内部需要实现一系列“适配器”,将K8s的资源类型和操作,一一映射到MCP的资源定义和工具定义上。比如,一个Pod资源适配器需要知道如何获取Pod列表、单个Pod的详情,并将其字段转换为MCP资源表示。
注意:这种架构意味着
k8s-mcp-server的性能和稳定性成为关键。它需要高效地处理并发请求,管理好与K8s API Server的连接池,并且自身不能有内存泄漏等严重问题,否则会成为整个链路中的瓶颈。
3. 核心功能模块深度解析
3.1 资源(Resources)暴露:只读视角下的K8s世界
MCP中的“资源”是只读的、可订阅的数据源。k8s-mcp-server目前主要暴露了Kubernetes中最核心的几种资源,这也是运维中最常查询的对象。
Pod资源:这是最细粒度的资源。服务器不仅暴露Pod的基本信息(名称、状态、IP、节点),还会通过适配器逻辑,关联并嵌入一些关键信息,比如Pod所属的OwnerReference(例如,它是由哪个Deployment创建的),以及当前容器使用的镜像详情。这对于安全扫描和合规检查非常有用,AI助手可以直接回答“这个Pod用的是哪个版本的镜像?有没有高危漏洞?”
Deployment与StatefulSet资源:代表了应用的工作负载。暴露的信息包括期望的副本数(replicas)、当前就绪副本数(readyReplicas)、更新策略以及版本历史。这允许客户端查询“我的应用部署状态健康吗?”、“滚动更新进行到哪一步了?”
Service与Ingress资源:代表了网络访问层。暴露ClusterIP、端口、选择器(Selector)以及Ingress规则。这对于理解服务间如何通信、外部流量如何路由至关重要。
Node资源:代表了集群的物理或虚拟基础设施。暴露CPU/内存的容量(Capacity)与可分配量(Allocatable)、当前负载(通过kubectl describe node中的条件Condition转化)、以及节点上的标签和污点(Taint)。这是进行容量规划和故障排查的基础。
事件的实时推送:这是MCP协议SSE能力的绝佳用例。服务器可以订阅Kubernetes的Event资源,并将Warning级别的事件,或者与特定资源相关的事件,实时推送给订阅的客户端。想象一下,AI助手可以突然告诉你:“注意,pod-abc刚刚因为OOMKilled重启了。”这比定期轮询日志高效得多。
3.2 工具(Tools)实现:有限但关键的写操作
MCP的“工具”允许客户端执行动作。出于安全考虑,k8s-mcp-server暴露的写操作工具一定是受限的、非破坏性的。目前常见的工具可能包括:
获取Pod日志(get-pod-logs):这是一个高频工具。它接收namespace和podName作为参数,可能还支持containerName(多容器Pod)和tailLines(获取最近多少行)。服务器内部会调用K8s API的Pod log接口,将日志流返回给客户端。这里的关键处理是日志大小限制和流式传输,避免一次性拉取巨量日志拖垮服务器或客户端。
在Pod中执行命令(exec-into-pod):这是一个需要谨慎对待的工具。它允许在指定Pod的容器内执行一条命令(如/bin/sh -c ‘ls -la’)。服务器必须严格验证命令的安全性,通常只允许白名单内的命令(如基本的诊断命令ls,cat,ps),并且必须有超时机制。实现上,它需要处理WebSocket流,将客户端的输入转发到容器,并将容器的输出返回。
查看资源描述(describe-resource):虽然资源读取可以获取结构化信息,但kubectl describe格式的人类可读性总结(包括事件汇总)仍有价值。这个工具可以模拟describe的输出,提供一个更友好的文本摘要。
扩缩容Deployment(scale-deployment):这是一个典型的写操作。它接收namespace、deploymentName和replicas参数。服务器在调用K8s API前,必须进行严格的权限校验和参数验证(比如,副本数不能设为负数,也不能超过某个安全上限)。
实操心得:工具的实现是安全边界所在。在部署时,一定要通过Kubernetes的RBAC,给
k8s-mcp-server使用的ServiceAccount分配最小必要权限。例如,对于日志和exec工具,可能只需要get,list,watchPod以及createPod的exec和log子资源权限,绝不应该给予delete或update所有资源的权限。
4. 部署与配置实战指南
4.1 环境准备与安装部署
假设我们已经在一个开发或测试Kubernetes集群中操作。部署k8s-mcp-server最推荐的方式自然是使用Helm Chart(如果项目提供)或直接应用Kubernetes清单文件。
首先,我们需要处理认证问题。为服务器创建一个专用的ServiceAccount和对应的RBAC角色绑定是最佳实践。
# rbac.yaml apiVersion: v1 kind: ServiceAccount metadata: name: mcp-server namespace: mcp-system # 建议单独命名空间 --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: mcp-server-reader rules: - apiGroups: [""] resources: ["pods", "pods/log", "pods/exec", "services", "nodes", "events"] verbs: ["get", "list", "watch"] - apiGroups: ["apps"] resources: ["deployments", "statefulsets"] verbs: ["get", "list", "watch"] - apiGroups: ["networking.k8s.io"] resources: ["ingresses"] verbs: ["get", "list", "watch"] # 注意:这里仅为示例,需根据实际暴露的工具细化权限,例如scale操作需要`update` deployment。 --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: mcp-server-binding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: mcp-server-reader subjects: - kind: ServiceAccount name: mcp-server namespace: mcp-system然后,部署服务器本身。这里以简单的Deployment为例:
# deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: k8s-mcp-server namespace: mcp-system spec: replicas: 2 # 建议至少2个实例以实现高可用 selector: matchLabels: app: k8s-mcp-server template: metadata: labels: app: k8s-mcp-server spec: serviceAccountName: mcp-server containers: - name: server image: ghcr.io/alexei-led/k8s-mcp-server:latest # 请替换为实际镜像地址 ports: - containerPort: 8080 # MCP协议默认端口 env: - name: KUBERNETES_NAMESPACE # 可限定服务器可访问的命名空间,留空为集群范围 value: "" - name: LOG_LEVEL value: "INFO" resources: requests: memory: "128Mi" cpu: "100m" limits: memory: "256Mi" cpu: "500m" livenessProbe: httpGet: path: /healthz # 假设服务器提供健康检查端点 port: 8080 initialDelaySeconds: 30 periodSeconds: 10 readinessProbe: httpGet: path: /ready port: 8080 initialDelaySeconds: 5 periodSeconds: 5 --- apiVersion: v1 kind: Service metadata: name: k8s-mcp-server namespace: mcp-system spec: selector: app: k8s-mcp-server ports: - port: 8080 targetPort: 8080 type: ClusterIP # 内部访问,如需外部客户端连接可考虑NodePort或Ingress应用这些配置:kubectl apply -f rbac.yaml -f deployment.yaml。部署完成后,服务器将在集群内部通过Servicek8s-mcp-server.mcp-system.svc.cluster.local:8080可达。
4.2 客户端连接与配置详解
服务器跑起来了,接下来是如何让MCP客户端(如Claude Desktop)连接它。MCP连接通常需要一个配置文件(如claude_desktop_config.json),其中定义了服务器的传输方式(Transport)和认证信息。
由于我们的服务器部署在K8s集群内,客户端在集群外,最常用的方式是通过SSH隧道或Kubernetes端口转发来建立安全连接。这里以更通用的“Command Transport”为例,它允许通过执行一个本地命令来启动服务器连接。
配置Claude Desktop连接示例:
{ "mcpServers": { "k8s-cluster-1": { "command": "kubectl", "args": [ "port-forward", "-n", "mcp-system", "service/k8s-mcp-server", "8080:8080", "--context=my-cluster-context" ], "env": { "KUBECONFIG": "/path/to/your/kubeconfig" } } } }这个配置告诉Claude Desktop:当需要连接名为k8s-cluster-1的MCP服务器时,去执行kubectl port-forward命令,将本地的8080端口转发到集群内服务的8080端口。kubectl会处理好与API Server的认证,我们只需要在本地有正确的kubeconfig即可。
另一种更稳定的方式是让k8s-mcp-server通过Ingress或LoadBalancer Service暴露一个HTTPS端点,并配置TLS证书和Bearer Token认证。然后在MCP配置中使用http或https传输方式,直接连接这个URL,并在请求头中携带Token。这种方式更适合于需要常连接或客户端位于不同网络环境的场景。
{ "mcpServers": { "k8s-prod": { "url": "https://mcp-server.yourcompany.com", "headers": { "Authorization": "Bearer YOUR_SECRET_TOKEN_HERE" } } } }注意事项:无论哪种方式,安全都是重中之重。Token需要足够复杂并定期轮换;HTTPS是必须的;如果使用端口转发,要意识到
kubectl进程本身如果被入侵的风险。生产环境务必结合网络策略、API网关等进一步加固。
5. 高级特性与定制化开发
5.1 扩展服务器:添加自定义资源与工具
k8s-mcp-server的魅力在于它的可扩展性。假设你的集群里跑着Cert-Manager的Certificate资源,或者Prometheus的ServiceMonitor,你希望AI助手也能查询它们。这就需要你进行定制化开发。
项目代码结构通常清晰,会有pkg/resources和pkg/tools这样的包。添加一个新资源,你需要:
- 定义资源结构:在
resources包下创建一个新的Go文件,例如certificate.go。 - 实现资源接口:通常需要实现
List()和Get()方法。在List()中,使用Kubernetes动态客户端(Dynamic Client)或特定资源的typed client来列出指定命名空间或全集群的该资源对象。 - 数据转换:将K8s资源对象转换为MCP协议定义的
Resource结构。这包括设置唯一的URI(如k8s://cert-manager.io/certificates/default/my-cert)、正确的MIME类型(application/json)以及内容体。 - 注册资源:在服务器的初始化函数中,将你新定义的资源适配器注册到资源管理器(Resource Manager)中。
添加新工具的过程类似,在tools包下实现对应的工具处理函数,该函数接收MCP协议传入的参数,调用K8s API执行操作,并返回结果。
5.2 性能优化与生产就绪考量
当从概念验证走向生产环境时,有几个关键点需要关注:
连接管理与资源消耗:每个MCP客户端(如每个Claude Desktop实例)都会与服务器建立一个或多个长连接(用于SSE)。服务器需要高效地管理这些连接,避免goroutine泄漏。同时,服务器对K8s API Server的查询要尽量使用Watch而非频繁的List,以减少API Server压力并获取实时更新。
缓存策略:对于变化不频繁的资源,如Node信息、Namespace列表,可以在服务器内存中设置短期缓存(例如30秒),并在缓存过期或接收到对应资源的Watch事件时失效更新。这能显著降低响应延迟和API Server负载。
可观测性:必须为服务器集成完善的日志、指标(Metrics)和分布式追踪。日志要结构化(JSON格式),记录请求ID、客户端信息、操作类型和耗时。指标方面,需要暴露Prometheus格式的指标,如:
mcp_requests_total:按资源类型、工具名称、状态码分类的请求计数器。mcp_request_duration_seconds:请求耗时的直方图。mcp_active_connections:当前活跃的客户端连接数。k8s_api_call_duration_seconds:底层K8s API调用的耗时。
这些指标是设置告警(如错误率升高、P99延迟飙升)和容量规划的基础。
高可用与滚动更新:如前所述,Deployment至少需要2个副本。需要配置Pod反亲和性,让副本分散在不同节点上。在更新服务器镜像时,使用RollingUpdate策略,并确保readinessProbe配置正确,让流量能够平滑迁移。
6. 典型应用场景与实战案例
6.1 场景一:AI辅助的日常运维与故障排查
这是最直接的应用。开发人员或初级运维在遇到问题时,可以直接向集成了k8s-mcp-server的AI助手提问。
- 提问:“我的服务
user-api在prod命名空间下响应很慢,帮我看看相关Pod的状态和最近的事件。” - AI助手(通过MCP服务器):
- 调用
resources/list获取prod命名空间下所有Pod,过滤出标签包含app=user-api的Pod。 - 检查这些Pod的状态(
Running,CrashLoopBackOff等)、就绪状态和资源请求/限制。 - 调用
resources/list获取与这些Pod相关的近期事件(Event资源),特别是Warning类型。 - 综合信息后回答:“发现
user-api-7c6bd8f8b-abcde这个Pod处于Pending状态,原因是Insufficient memory。同时,user-api-7c6bd8f8b-fghij这个Pod最近重启了3次,事件显示是OOMKilled。建议检查Pod的内存请求配置,并查看节点资源水位。”
- 调用
这个过程中,用户无需记忆kubectl命令语法,也无需在多个终端窗口间切换查看不同资源,所有信息被AI整合后以对话形式呈现,效率大幅提升。
6.2 场景二:自动化巡检报告生成
你可以编写一个脚本或轻量级应用,作为MCP客户端,定期(如每天凌晨)连接k8s-mcp-server,执行一系列检查,并生成报告。
脚本逻辑可以这样:
- 连接MCP服务器。
- 获取所有Node资源,检查其
ReadyCondition是否为True,并检查内存/CPU压力。 - 获取所有Namespace下的Pod资源,统计状态非
Running/Succeeded的Pod列表。 - 获取所有Deployment资源,检查
readyReplicas是否等于replicas。 - 获取最近1小时内的
Warning级别事件。 - 将以上信息整理成HTML或Markdown格式的报告,通过邮件或即时通讯工具发送给运维团队。
由于MCP提供了结构化的数据,编写这样的巡检脚本比用kubectl加jq或go-template解析要简单和稳定得多。
6.3 场景三:低代码/无代码平台的后台引擎
如果你在构建一个内部开发者平台(IDP)或运维门户,希望提供一个图形化界面让用户查看自己的应用状态、日志甚至执行一些简单命令,k8s-mcp-server可以作为一个完美的后台引擎。
前端界面通过WebSocket或HTTP长轮询与一个定制化的MCP客户端通信,这个客户端再与k8s-mcp-server交互。界面上一个“查看日志”的按钮,背后就是调用get-pod-logs工具;一个资源拓扑图,背后是不断通过resources/list和SSE更新来获取Pod、Service等数据并计算其关系。
这样做的好处是,业务逻辑和K8s API的复杂性被封装在了MCP服务器里。前端开发者无需学习K8s Client-go,只需要按照MCP协议收发JSON消息即可。平台的权限控制也可以在MCP服务器层面统一实现。
7. 常见问题、故障排查与安全实践
7.1 连接与认证问题排查表
| 问题现象 | 可能原因 | 排查步骤 |
|---|---|---|
| MCP客户端无法连接服务器,提示“连接被拒绝”或“超时”。 | 1. 服务器Pod未正常运行。 2. Service配置错误或网络策略阻隔。 3. kubectl port-forward命令参数错误或本地kubeconfig无效。 | 1.kubectl get pods -n mcp-system检查Pod状态是否为Running。2. kubectl describe svc -n mcp-system检查Service端口映射。3. 手动执行 kubectl port-forward ...命令看是否能成功建立隧道。4. 检查客户端配置中的命令、参数和上下文(context)是否正确。 |
| 连接成功,但客户端提示“未授权”或“权限不足”。 | 1. ServiceAccount权限(RBAC)配置不足。 2. MCP服务器配置了Token认证,但客户端未提供或Token错误。 | 1.kubectl auth can-i --as=system:serviceaccount:mcp-system:mcp-server list pods等命令测试权限。2. 检查服务器日志,看是否有明确的权限拒绝错误。 3. 核对客户端配置中的认证Token或Header。 |
| 可以列出资源,但调用工具(如查看日志)失败。 | 1. 对该工具所需的特定子资源(如pods/log)缺乏权限。2. Pod或容器不存在。 3. 服务器端工具实现有Bug。 | 1. 使用kubectl auth can-i检查对pods/log,pods/exec等子资源的权限。2. 用 kubectl手动执行相同操作,确认目标资源存在且可访问。3. 查看服务器端日志,获取详细的错误信息。 |
7.2 性能与稳定性问题
- 服务器内存持续增长:可能是Watch连接或客户端连接未正确关闭导致的内存泄漏。检查服务器代码中
Watch接口返回的watch.Interface和HTTP连接是否在上下文取消或客户端断开时被正确清理。使用pprof工具分析内存使用情况。 - 响应缓慢:首先通过服务器指标确认是MCP层慢还是底层K8s API调用慢。如果是后者,考虑:
- 为不常变化的资源(如Node)增加缓存。
- 检查K8s API Server和etcd的负载。
- 优化List查询,使用
FieldSelector和Limit减少返回数据量。
- SSE事件流中断:网络不稳定或客户端处理不及时可能导致SSE连接中断。服务器端应实现重连机制和心跳保活。客户端也需要处理连接断开后的自动重连。
7.3 安全加固最佳实践
- 最小权限原则(再次强调):为
k8s-mcp-server的ServiceAccount配置的ClusterRole,必须精确到resources和verbs,只授予它暴露出来的资源和工具所必需的最小权限。定期审计这些权限。 - 网络隔离:使用Kubernetes NetworkPolicy,限制只有特定的客户端Pod或来自管理网段的流量才能访问
k8s-mcp-server的Service。避免将其暴露在公网。 - 传输加密与认证:
- 内部通信:确保服务器与K8s API Server之间的通信是加密的(默认通常是)。
- 外部通信:如果通过Ingress/负载均衡器暴露,必须使用HTTPS(TLS)。客户端认证使用强Token(如JWT),并考虑实现Token的自动轮换。
- 审计日志:确保服务器记录所有工具调用(特别是写操作如
exec,scale)的详细审计日志,包括调用者标识(可从MCP连接信息或认证Token中提取)、时间、操作对象和参数。这些日志应发送到集中的日志系统(如Loki或Elasticsearch)长期存储。 - 输入验证与沙箱:对于
exec-into-pod这样的危险工具,服务器端必须对传入的命令进行严格的白名单验证,禁止执行rm -rf /、wget、curl | bash等危险命令。可以考虑在服务器层面实现一个简单的命令解析器,只允许通过预定义的安全命令模板。
在我自己的测试和生产沙箱环境中部署使用了一段时间后,最大的体会是,k8s-mcp-server这类项目代表了一种趋势:将复杂基础设施的能力,通过一个标准、友好的协议“服务化”。它降低了使用门槛,激发了新的交互方式(如自然语言运维),但同时也把安全设计和长期维护的责任带到了新的层面。它不是kubectl的替代品,而是一个强大的补充和扩展。如果你正在构建面向开发者的平台,或者单纯想用更酷的方式管理你的集群,花时间研究并定制它,会是非常值得的投资。下一步,我打算尝试把它与集群的监控数据(如Prometheus指标)进一步集成,让AI助手不仅能“看到”资源状态,还能“分析”性能趋势,那将会更加有趣。
