使用 MCP 与 A2A 设计多智能体 AI 系统——部署多智能体系统

在上一章中,我们讨论了多智能体系统的测试、调试与故障排查。我们探索了诸如幻觉(hallucination)与工具误用(tool misuse)等常见失效模式、监控与可观测性(instrumentation and observability)策略、协调失败(coordination failures)的调试技巧,以及通过冗余与优雅降级来构建韧性(resilience)的设计方法。我们全程以 MAKDO 作为具体示例来说明这些概念。

现在,是时候把 MAKDO 真正部署起来了。但把多智能体系统跑在生产环境会带来新的挑战:部署架构、服务发现、网络与安全。你如何把智能体部署到多个环境?它们如何安全通信?你如何管理凭证与访问控制?

在本章中,我们将在一个逼真的、类生产(production-like)的环境中部署 MAKDO。我们会使用 Kubernetes in Docker(KinD)创建两个 Kubernetes 集群:控制集群(control cluster) 运行 MAKDO 本身;工作集群(worker cluster) 是 MAKDO 监控与管理的目标集群。k8s-ai(一个 agent-to-agent server)运行在工作集群上,通过 Agent-to-Agent(A2A)协议为 MAKDO 提供诊断与修复问题的能力。这个架构模拟了真实生产场景:管理系统与其管理的工作负载分离运行。

我们会依次完成:搭建两个集群、把 MAKDO 组件部署到控制集群、把 k8s-ai 部署到工作集群、配置安全的跨集群通信、以及管理服务发现与访问控制。到本章结束时,你将拥有一个完整可用的多智能体系统,它能管理另一个独立的 Kubernetes 集群,并可自动检测与修复问题。

本章涵盖的关键点包括:

  • 搭建用于多智能体部署的双 KinD 集群
  • 将 MAKDO 部署到控制集群
  • 将 k8s-ai 部署到工作集群
  • 启用集群间的安全通信

技术要求

请按照以下说明操作:
github.com/PacktPublis...

搭建用于多智能体部署的双 KinD 集群(Setting up dual KinD clusters for multi-agent deployment)

让我们构建一个类生产部署:MAKDO 运行在一个集群上,并管理另一个集群。这种隔离在真实环境中非常关键,用于将管理基础设施与生产工作负载隔离开来。它可以减少爆炸半径(blast radius),并且即使 MAKDO 不可用,生产系统也能继续运行。此外,如果生产集群发生资源耗尽或类似问题,MAKDO 仍能分析并可能修复它,因为 MAKDO 不受同样问题影响。

安装 KinD 与前置依赖(Installing KinD and prerequisites)

在创建集群之前,你需要安装 Docker、kubectl 和 KinD。我们不会逐个工具讲解安装步骤(不同平台差异大且会随时间变化),而是提供一个验证脚本来检查环境是否就绪。

首先,如果你还没有克隆本书仓库,请先克隆:

scss 复制代码
git clone git@github.com:PacktPublishing/Design-Multi-Agent-AI-Systems-using-MCP-and-A2A.git

使用官方文档安装所需工具:

安装完成后,运行我们的前置依赖检查脚本来验证一切正常:

bash 复制代码
cd ch11
chmod +x check-prerequisites.sh
./check-prerequisites.sh

该脚本会检查:Docker 是否已安装并运行、kubectl 是否可用、KinD 是否已安装(建议 0.20.0 或更高版本)、磁盘空间是否充足(两个集群约需 ~10 GB)、Docker 内存分配是否至少 4 GB,以及是否存在会与本次设置冲突的 KinD 集群。

如果脚本报告缺少任何依赖,请使用上述链接安装后重新运行脚本。看到 All prerequisites met! 后,就可以开始创建集群了。

创建控制集群配置(Creating the control cluster configuration)

控制集群承载 MAKDO 智能体。它需要被配置为允许外部访问 MAKDO 的 API 端点。KinD 使用 YAML 配置文件定义集群拓扑与网络。

创建 control-cluster.yaml

yaml 复制代码
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: makdo-control
nodes:
- role: control-plane
  kubeadmConfigPatches:
  - |
    kind: InitConfiguration
    nodeRegistration:
      kubeletExtraArgs:
        node-labels: "cluster-role=control"
  extraPortMappings:
  # Port for accessing MAKDO API/dashboard if needed
  - containerPort: 30080
    hostPort: 8080
    protocol: TCP
  # Port for MAKDO health check endpoint
  - containerPort: 30090
    hostPort: 9090
    protocol: TCP

关键配置点如下:

  • namemakdo-control 标识该集群。KinD 会用这个名字创建 Docker 容器并生成 kubectl context。
  • node-labels:标签用于识别 pod 运行在哪个集群上,便于调试与监控。
  • extraPortMappings:将集群端口暴露到宿主机。8080 映射到容器端口 30080(Kubernetes NodePort 范围),9090 映射到 30090 用于健康检查。这样你可以从本地访问 MAKDO 服务,或在需要时允许工作集群访问 MAKDO。

接下来创建控制集群:

lua 复制代码
kind create cluster --config control-cluster.yaml

这通常需要 1--2 分钟。KinD 会下载 Kubernetes 节点镜像(若未缓存)、创建 Docker 容器并初始化 Kubernetes。完成后你会看到类似输出:

vbnet 复制代码
Creating cluster "makdo-control" ...
 ✓ Ensuring node image (kindest/node:v1.33.1) 🖼
 ✓ Preparing nodes 📦
 ✓ Writing configuration 📜
 ✓ Starting control-plane 🕹
 ✓ Installing CNI 🔌
 ✓ Installing StorageClass 💾
Set kubectl context to "kind-makdo-control"

示例中的 Kubernetes 版本(如 v1.33.1)取决于你安装的 KinD 版本;KinD 会自动选择兼容的 Kubernetes 版本。

验证集群:

sql 复制代码
kubectl cluster-info --context kind-makdo-control
kubectl get nodes --context kind-makdo-control

期望输出类似:

ruby 复制代码
Kubernetes control plane is running at https://127.0.0.1:60905
CoreDNS is running at https://127.0.0.1:60905/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

NAME                          STATUS   ROLES           AGE   VERSION
makdo-control-control-plane   Ready    control-plane   1m    v1.33.1

一个节点处于 Ready 状态。集群已启动,但还是空的。

创建工作集群配置(Creating the worker cluster configuration)

工作集群运行实际业务工作负载。MAKDO 监控这个集群,并在问题出现时修复它。该集群需要暴露 k8s-ai 的 MCP server,以便 MAKDO 与其通信。

创建 worker-cluster.yaml

yaml 复制代码
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: makdo-worker
nodes:
- role: control-plane
  kubeadmConfigPatches:
  - |
    kind: InitConfiguration
    nodeRegistration:
      kubeletExtraArgs:
        node-labels: "cluster-role=worker"
  extraPortMappings:
  # Port for k8s-ai MCP server
  - containerPort: 30100
    hostPort: 8100
    protocol: TCP
  # Port for exposing problematic workloads (for testing)
  - containerPort: 30200
    hostPort: 8200
    protocol: TCP

与控制集群相比,关键差异是:

  • namemakdo-worker 与控制集群区分开来。
  • node-labelscluster-role=worker 标识其为被管理集群。
  • Port 8100:映射到容器端口 30100,k8s-ai 的 A2A server 将运行在这里。MAKDO 的 Analyzer 与 Fixer 智能体将通过该端口使用 A2A 协议调用 k8s-ai。
  • Port 8200:用于测试工作负载。我们会部署一些故障 pod,供 MAKDO 检测与修复。

创建工作集群:

lua 复制代码
kind create cluster --config worker-cluster.yaml

此时你有两个独立的 Kubernetes 集群,它们以 Docker 容器形式运行:

arduino 复制代码
kind get clusters

期望输出(你也可能还有其它集群):

复制代码
makdo-control
makdo-worker

检查两个 kubectl context:

arduino 复制代码
kubectl config get-contexts | grep makdo

示例输出:

markdown 复制代码
          kind-makdo-control   kind-makdo-control   kind-makdo-control
*         kind-makdo-worker    kind-makdo-worker    kind-makdo-worker

* 表示当前激活的 context。你可以这样切换:

perl 复制代码
# Use control cluster
kubectl config use-context kind-makdo-control

# Use worker cluster
kubectl config use-context kind-makdo-worker

两个集群是隔离的。不做显式网络配置时,一个集群内的 pod 无法直接访问另一个集群的 pod。我们将在下一步完成所需配置。

配置集群网络与端口转发(Setting up cluster networking and port forwarding)

KinD 集群作为 Docker 容器运行在宿主机上。它们处于同一个 Docker 网络中,这意味着它们可以通过 Docker 网络互相访问。但集群内部的服务要对外可达,需要额外配置。

首先,找出两个集群使用的 Docker 网络:

bash 复制代码
docker network ls | grep kind

示例输出:

bash 复制代码
aadf3e99800d   kind          bridge    local

两个集群容器都连接在该 kind 网络上:

perl 复制代码
docker network inspect kind | grep -A 3 "makdo"

这会显示两个集群容器的 IP 地址。不过我们不希望硬编码 IP,而是使用前面配置好的端口映射。

在跨集群通信中,MAKDO(控制集群)需要访问 k8s-ai(工作集群)。由于两个集群运行在同一台宿主机上,MAKDO 可以通过 host.docker.internal:8100 访问 k8s-ai。这个特殊 DNS 名称会在 Docker 容器内解析到宿主机。

验证端口映射是否生效。检查映射端口上是否有服务在监听:

javascript 复制代码
# Control cluster ports
lsof -i :8080 2>/dev/null || echo "Port 8080: not yet in use"
lsof -i :9090 2>/dev/null || echo "Port 9090: not yet in use"

# Worker cluster ports
lsof -i :8100 2>/dev/null || echo "Port 8100: not yet in use"
lsof -i :8200 2>/dev/null || echo "Port 8200: not yet in use"

此时这些端口还未被占用,因为我们还没有部署任何服务。端口映射已配置,但只有当服务绑定到集群内端口(30080、30090、30100、30200)时才会"激活"。

检查 Docker 容器是否运行并具备这些端口映射:

perl 复制代码
docker ps --format "table {{.Names}}\t{{.Ports}}" | grep makdo

示例输出:

bash 复制代码
makdo-worker-control-plane    127.0.0.1:61462->6443/tcp, 0.0.0.0:8100->30100/tcp, 0.0.0.0:8200->30200/tcp
makdo-control-control-plane   127.0.0.1:60905->6443/tcp, 0.0.0.0:8080->30080/tcp, 0.0.0.0:9090->30090/tcp

你可以看到两个容器及其端口映射。6443 是 Kubernetes API Server;我们的自定义映射(8080→30080、8100→30100 等)已就绪,等待服务使用。

验证跨集群连通性(Verifying cross-cluster connectivity)

在部署 MAKDO 与 k8s-ai 之前,先确认两个集群健康,并具备潜在的互通条件。

检查控制集群健康状况:

sql 复制代码
kubectl cluster-info --context kind-makdo-control
kubectl get nodes --context kind-makdo-control

示例输出:

ruby 复制代码
Kubernetes control plane is running at https://127.0.0.1:60905
CoreDNS is running at https://127.0.0.1:60905/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

NAME                          STATUS   ROLES           AGE   VERSION
makdo-control-control-plane   Ready    control-plane   15m   v1.33.1

再检查工作集群:

sql 复制代码
kubectl cluster-info --context kind-makdo-worker
kubectl get nodes --context kind-makdo-worker

示例输出:

ruby 复制代码
Kubernetes control plane is running at https://127.0.0.1:61462
CoreDNS is running at https://127.0.0.1:61462/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

NAME                         STATUS   ROLES           AGE   VERSION
makdo-worker-control-plane   Ready    control-plane   12m   v1.33.1

两个集群都显示 control plane 正常运行,并且一个节点处于 Ready 状态。

测试每个集群内部的基础网络(DNS):

ini 复制代码
# Test DNS in control cluster
kubectl run dns-test --image=busybox:latest --restart=Never --rm -i --context kind-makdo-control --command -- \
    nslookup kubernetes.default.svc.cluster.local

# Test DNS in worker cluster
kubectl run dns-test --image=busybox:latest --restart=Never --rm -i --context kind-makdo-worker --command -- \
    nslookup kubernetes.default.svc.cluster.local

两者都应成功解析 Kubernetes service DNS 名称。

对于跨集群通信,MAKDO 不会直接访问工作集群中的 pod,而是通过暴露端口访问 k8s-ai 的 A2A server。我们会在 k8s-ai 部署完成后测试。现在两个集群已为下一步做好准备。

在工作集群部署测试负载(Deploying a test workload to the worker cluster)

为了验证 MAKDO 是否工作正确,我们需要一些可供其检测与修复的"故障负载"。让我们在工作集群部署一个测试命名空间,其中包含三个 pod:一个会崩溃、一个会拉取镜像失败、一个正常运行。

创建 test-workload.yaml

yaml 复制代码
apiVersion: v1
kind: Namespace
metadata:
  name: test-workload
---
# A pod that will crashloop - missing required environment variable
apiVersion: v1
kind: Pod
metadata:
  name: crashloop-pod
  namespace: test-workload
  labels:
    app: crashloop-test
spec:
  containers:
  - name: app
    image: busybox:latest
    command: ["sh", "-c"]
    args:
      - |
        if [ -z "$REQUIRED_VAR" ]; then
          echo "ERROR: REQUIRED_VAR not set"
          exit 1
        fi
        echo "Running successfully"
        sleep 3600
---
# A pod with an image that doesn't exist
apiVersion: v1
kind: Pod
metadata:
  name: imagepull-pod
  namespace: test-workload
  labels:
    app: imagepull-test
spec:
  containers:
  - name: app
    image: nonexistent-registry.example.com/fake-image:v1.0.0
    command: ["sleep", "3600"]
---
# A healthy pod for comparison
apiVersion: v1
kind: Pod
metadata:
  name: healthy-pod
  namespace: test-workload
  labels:
    app: healthy-test
spec:
  containers:
  - name: app
    image: nginx:alpine
    ports:
    - containerPort: 80

部署到工作集群:

css 复制代码
kubectl apply -f test-workload.yaml --context kind-makdo-worker

查看 pod 状态:

sql 复制代码
kubectl get pods -n test-workload --context kind-makdo-worker

示例输出:

scss 复制代码
NAME            READY   STATUS             RESTARTS      AGE
crashloop-pod   0/1     CrashLoopBackOff   7 (27s ago)   11m
healthy-pod     1/1     Running            0             11m
imagepull-pod   0/1     ImagePullBackOff   0             11m

完美!我们得到如下结果:

  • crashloop-pod:CrashLoopBackOff(因为缺少环境变量而立即退出)
  • healthy-pod:Running(nginx 正常启动)
  • imagepull-pod:ImagePullBackOff(镜像不存在)

观察 crashloop-pod 反复重启:

css 复制代码
kubectl get pods -n test-workload --context kind-makdo-worker --watch

按 Ctrl + C 结束 watch。这些失败的 pod 正是 MAKDO 的理想目标:Analyzer 会检测并分类失败类型,Fixer 可能会尝试修复。

查看 crashloop pod 的日志,确认失败原因:

css 复制代码
kubectl logs crashloop-pod -n test-workload --context kind-makdo-worker

示例输出:

vbnet 复制代码
ERROR: REQUIRED_VAR not set

工作集群现在已经具备故障工作负载。接下来,我们会把 MAKDO 部署到控制集群、把 k8s-ai 部署到工作集群,然后观察 MAKDO 如何自动检测并处理这些问题。

将 MAKDO 部署到控制集群(Deploying MAKDO to the control cluster)

现在我们已经启动了两个集群,并且工作集群中的测试工作负载处于失败状态,是时候部署 MAKDO 了。MAKDO 将以控制集群中的一个 Deployment 形式运行,并通过 k8s-ai 的 A2A server 监控工作集群。

准备 MAKDO 配置(Preparing the MAKDO configuration)

MAKDO 需要配置文件来知道要监控哪些集群、如何连接到 k8s-ai,以及如何通过 Slack 通信。我们会根据"双集群"部署方式对示例配置做适配。

细节请参考:
github.com/PacktPublis...

下面是关键配置点:

  • Clusters :只列出工作集群。MAKDO 不需要监控它自己的控制集群。kind-makdo-worker 这个 context 与 KinD 创建的 kubectl context 一致。
  • kubeconfig_path :设置为 /root/.kube/config,因为 kubeconfig 将被挂载到 MAKDO 容器内的这个路径。我们会通过 volume 挂载 kubeconfig。
  • k8s_ai.base_url :使用 host.docker.internal:8100 去访问工作集群上的 k8s-ai。这个特殊 DNS 名称在 Docker 容器内会解析到宿主机。8100 是我们为 k8s-ai 的 A2A server 映射的端口。
  • Environment variables :API key 与 token 使用 ${VAR} 语法。MAKDO 会从环境变量读取这些值,我们将通过 Kubernetes Secret 提供。
  • monitoring.check_interval:设置为 120 秒(2 分钟)。MAKDO 每两分钟轮询一次工作集群,以便快速发现问题。

接下来我们需要智能体配置文件。MAKDO 为每个智能体的 prompt 与工具配置使用独立的 YAML 文件。

创建智能体配置文件(Agent configuration files)

创建 makdo-config/coordinator.yaml

vbnet 复制代码
name: "MAKDO Coordinator"
description: |
  You are the MAKDO Coordinator, the central orchestrator for multi-cluster Kubernetes operations.

  Your responsibilities:
  1. Periodically check cluster health across all registered clusters
  2. Coordinate between Analyzer, Fixer, and Slack Bot agents
  3. Escalate critical issues to appropriate agents
  4. Maintain operational awareness of all clusters

  When asked to perform health checks:
  1. Use the Analyzer agent to assess cluster health
  2. If issues are found, use the Slack Bot to notify users
  3. For critical issues, use the Fixer agent if remediation is needed
  4. Always report status back to the Slack channel

  Be proactive, clear, and focused on cluster reliability.

model_id: "gpt-4o"

sub_agents:
  - name: "MAKDO_Analyzer"
    config_path: "src/makdo/agents/analyzer.yaml"

  - name: "MAKDO_Fixer"
    config_path: "src/makdo/agents/fixer.yaml"

  - name: "MAKDO_Slack_Bot"
    config_path: "src/makdo/agents/slack.yaml"

history:
  max_messages: 10
  summarize_after: 5

创建 makdo-config/analyzer.yaml

vbnet 复制代码
name: "MAKDO Analyzer"
description: |
  You are the MAKDO Analyzer agent. Your role is to diagnose Kubernetes cluster health issues.

  Your responsibilities:
  1. Check cluster resource health (pods, deployments, services, nodes)
  2. Identify problems like CrashLoopBackOff, ImagePullBackOff, resource exhaustion
  3. Analyze logs and events to understand root causes
  4. Provide clear diagnostic reports to the Coordinator

  When analyzing issues:
  1. Always check ALL namespaces, not just default
  2. Look at pod status, events, and logs
  3. Identify patterns across multiple failing pods
  4. Classify issues by severity (critical, warning, info)
  5. Provide actionable recommendations

  Use the k8s diagnostic tools available to you through the A2A protocol.

model_id: "gpt-4o"

tools:
  - name: "kubernetes_resource_health"
    type: "a2a"
    endpoint: "http://host.docker.internal:8100"
    description: "Check health of Kubernetes resources (pods, deployments, services, nodes)"

  - name: "kubernetes_diagnose_issue"
    type: "a2a"
    endpoint: "http://host.docker.internal:8100"
    description: "Diagnose specific Kubernetes issues by analyzing events, logs, and resource state"

history:
  max_messages: 8
  summarize_after: 4

创建 makdo-config/fixer.yaml

vbnet 复制代码
name: "MAKDO Fixer"
description: |
  You are the MAKDO Fixer agent. Your role is to remediate Kubernetes cluster issues safely.

  Your responsibilities:
  1. Apply fixes for diagnosed issues from the Analyzer
  2. Always prioritize safety and avoid destructive actions
  3. Request approval for critical operations
  4. Verify fixes were successful after applying

  Common remediation actions:
  - Restart failing pods
  - Update pod configurations to fix missing env vars
  - Scale deployments
  - Apply configuration changes

  CRITICAL SAFETY RULES:
  1. Never delete resources without explicit approval
  2. Always verify before applying changes
  3. If unsure, ask for human approval
  4. Test fixes on non-production resources first when possible

  Use the k8s remediation tools available through the A2A protocol.

model_id: "gpt-4o"

tools:
  - name: "kubernetes_apply_fix"
    type: "a2a"
    endpoint: "http://host.docker.internal:8100"
    description: "Apply fixes to Kubernetes resources (restart pods, update configs, scale)"

  - name: "kubernetes_verify_fix"
    type: "a2a"
    endpoint: "http://host.docker.internal:8100"
    description: "Verify that applied fixes resolved the issue"

history:
  max_messages: 6
  summarize_after: 3

创建 makdo-config/slack.yaml

vbnet 复制代码
name: "MAKDO Slack Bot"
description: |
  You are the MAKDO Slack Bot agent. Your role is to communicate with users via Slack.

  Your responsibilities:
  1. Post cluster health reports to the #makdo-devops channel
  2. Alert users to critical issues
  3. Provide status updates on ongoing operations
  4. Respond to user questions about cluster health

  Message formatting:
  - Use clear, concise language
  - Highlight critical issues with appropriate urgency
  - Include relevant details (pod names, namespaces, error messages)
  - Provide actionable next steps when possible

  Always post to #makdo-devops channel unless told otherwise.

model_id: "gpt-4o"

mcp_servers:
  slack:
    command: "npx"
    args: ["@korotovsky/slack-mcp-server"]
    env:
      SLACK_BOT_TOKEN: "${AI6_BOT_TOKEN}"
      SLACK_TEAM_ID: "${SLACK_TEAM_ID}"

history:
  max_messages: 5
  summarize_after: 3

这些配置文件定义了每个智能体的行为、工具以及通信方式。Analyzer 与 Fixer 使用指向 k8s-ai 的 A2A 工具;Slack_Bot 使用一个 MCP server 来集成 Slack。

为 API Key 创建 Kubernetes Secrets(Creating Kubernetes secrets for API keys)

MAKDO 需要 OpenAI 的 API key(用于运行基于 LLM 的智能体)以及 Slack 的 token(用于发消息)。我们会把它们存成控制集群中的 Kubernetes Secret。

首先,创建一个包含 API key 的 .env 文件:

ini 复制代码
cat > .env <<EOF
OPENAI_API_KEY=sk-...your-key-here...
AI6_BOT_TOKEN=xoxb-...your-slack-bot-token...
AI6_APP_TOKEN=xapp-...your-slack-app-token...
SLACK_TEAM_ID=T...your-team-id...
EOF

把占位符替换成你自己的 key。若你还没有这些 key,可从以下位置获取:

  • OpenAI API key:在 platform.openai.com/api-keys 获取
  • Slack tokens:在 api.slack.com/apps 创建 Slack app,配置 bot token scopes(chat:writechannels:read)以及用于 socket mode 的 app-level token
  • Slack Team ID:在 Slack 工作区设置里查看 Workspace ID

在控制集群中创建 Secret:

bash 复制代码
# Switch to control cluster
kubectl config use-context kind-makdo-control

# Load environment variables
set -a
source .env
set +a

# Create secret
kubectl create secret generic makdo-secrets \
  --from-literal=openai-api-key="$OPENAI_API_KEY" \
  --from-literal=slack-bot-token="$AI6_BOT_TOKEN" \
  --from-literal=slack-app-token="$AI6_APP_TOKEN" \
  --from-literal=slack-team-id="$SLACK_TEAM_ID" \
  -n default

验证 secret 创建成功:

arduino 复制代码
kubectl get secret makdo-secrets -n default

输出如下:

复制代码
NAME            TYPE     DATA   AGE
makdo-secrets   Opaque   4      5s

Secret 已创建。值被隐藏无需担心------这正是 secret 的目的。你可以通过查看 key 是否存在来进一步确认:

sql 复制代码
kubectl describe secret makdo-secrets -n default

输出如下:

makefile 复制代码
Name:         makdo-secrets
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
openai-api-key:    51 bytes
slack-app-token:   53 bytes
slack-bot-token:   56 bytes
slack-team-id:     11 bytes

Secret 已就绪。我们会在 MAKDO 的 Deployment 中把它们挂成环境变量。

创建 kubeconfig ConfigMap(Creating the kubeconfig ConfigMap)

MAKDO 需要访问工作集群的 kubeconfig 文件才能管理它。我们会创建一个包含 kubeconfig 的 ConfigMap 并挂载到 MAKDO pod 中。注意:在生产环境中,出于安全考虑,更推荐用 Secret 来存放 kubeconfig。

提取工作集群 kubeconfig 并创建 ConfigMap:

sql 复制代码
# Create kubeconfig ConfigMap from your local kubeconfig
kubectl create configmap makdo-kubeconfig \
  --from-file=config=$HOME/.kube/config \
  --context kind-makdo-control

这个 ConfigMap 会被挂载到 MAKDO 容器内的 /root/.kube,使其能够访问控制集群与工作集群。

验证 ConfigMap 创建成功:

sql 复制代码
kubectl get configmap makdo-kubeconfig --context kind-makdo-control

输出如下:

复制代码
NAME               DATA   AGE
makdo-kubeconfig   1      5s

kubeconfig 已可供 MAKDO 连接工作集群使用。

将 MAKDO 作为 Kubernetes Deployment 部署(Deploying MAKDO as a Kubernetes deployment)

MAKDO 将以一个副本(one replica)的 Deployment 方式运行。Deployment 能在 pod 崩溃时自动重启,并且便于通过滚动更新发布新版本或新配置。

部署清单见:
github.com/PacktPublis...

关键 Deployment 配置包括:

  • ConfigMap :包含 makdo.yaml 配置文件,使我们无需重建镜像即可更新配置。

  • replicas: 1:单实例 MAKDO。多副本会导致重复健康检查与协调冲突。生产环境建议使用 leader election,确保有 standby 实例可接管。

  • imagePullPolicy: Never:我们会在本地构建 MAKDO 镜像并加载到 KinD,不从镜像仓库拉取。

  • env :从 makdo-secrets secret 注入环境变量,覆盖配置中的 ${VAR} 占位符。

  • volumeMounts:挂载两个卷:

    • /app/config:来自 ConfigMap 的 MAKDO 配置
    • /root/.kube:来自 ConfigMap 的 kubeconfig,用于访问两个集群
  • resources:CPU/内存限制防止 MAKDO 占用过多资源。对 Python 进程与 LLM 调用来说,512 Mi 到 1 Gi 通常合理。

  • volumes:挂载两个 ConfigMap:

    • makdo-config:包含 MAKDO 配置
    • makdo-kubeconfig:包含 kubeconfig

在部署之前,我们需要先构建 MAKDO 的 Docker 镜像并加载到控制集群。

构建并加载 MAKDO 镜像(Building and loading the MAKDO image)

MAKDO 需要打包成 Docker 镜像。我们会创建一个 Dockerfile,安装依赖并启动 MAKDO 主进程。

创建 makdo/Dockerfile

bash 复制代码
FROM python:3.13-slim

# Install system dependencies
RUN apt-get update && apt-get install -y \
    curl \
    git \
    kubectl \
    && rm -rf /var/lib/apt/lists/*

# Install Node.js for Slack MCP server
RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
    && apt-get install -y nodejs \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /app

# Copy MAKDO source from the book repository
# Adjust path based on where you cloned the book repo
COPY ../../packt/Design-Multi-Agent-AI-Systems-Using-MCP-and-A2A/ch09/makdo/src ./src
COPY ../../packt/Design-Multi-Agent-AI-Systems-Using-MCP-and-A2A/ch09/makdo/pyproject.toml .

# Install MAKDO dependencies
RUN pip install --no-cache-dir ai-six==0.14.4 pyyaml python-dotenv requests

# Create required directories
RUN mkdir -p /app/config /app/logs

# Set Python to run unbuffered so logs appear immediately
ENV PYTHONUNBUFFERED=1

# Run MAKDO main entry point
CMD ["python", "-m", "src.makdo.main"]

该 Dockerfile 使用 Python 3.13。这个版本对所有依赖都有预构建的二进制 wheel,因此无需编译。我们安装 kubectl 用于访问 Kubernetes 集群,并安装 Node.js 用于 Slack MCP server。Python 依赖(ai-sixpyyamlpython-dotenvrequests)会直接从 wheel 安装,无需额外构建工具。

构建镜像:

bash 复制代码
cd ch11/makdo
docker build -t makdo:latest .

这会花几分钟下载基础镜像并安装依赖。若构建失败提示找不到 MAKDO 源码,请确认 src 目录路径正确。

构建完成后,把镜像加载到控制集群:

lua 复制代码
kind load docker-image makdo:latest --name makdo-control

这会把镜像从本地 Docker 传到 KinD 集群的内部镜像缓存。输出类似:

vbnet 复制代码
Image: "makdo:latest" with ID "sha256:..." not yet present on node "makdo-control-control-plane", loading...

验证镜像可用:

perl 复制代码
docker exec -it makdo-control-control-plane crictl images | grep makdo

你应该能看到 makdo 镜像。现在可以部署了。

应用 deployment:

css 复制代码
kubectl apply -f deployment.yaml --context kind-makdo-control

输出如下:

bash 复制代码
configmap/makdo-config created
deployment.apps/makdo created

检查 deployment 状态:

sql 复制代码
kubectl get deployment makdo --context kind-makdo-control

输出如下:

vbnet 复制代码
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
makdo   1/1     1            1           15s

MAKDO 已运行,且一个副本处于就绪状态。

配置 MAKDO 连接工作集群(Configuring MAKDO to connect to the worker cluster)

MAKDO 需要 kubeconfig 文件来访问工作集群,并需要 k8s-ai 的 session token 来使用 A2A 工具。kubeconfig 已通过宿主机挂载完成。现在我们需要确保 MAKDO 能与 k8s-ai 建立会话。

不过 k8s-ai 还没有部署。我们将在下一节部署它。现在先验证 MAKDO 能启动,并能通过 kubectl 访问工作集群。

查看 MAKDO pod 日志:

css 复制代码
kubectl logs -l app=makdo --context kind-makdo-control --tail=50

你很可能会看到 k8s-ai 不可达的错误,这是预期行为。重点是要看到 MAKDO 成功启动的日志,例如:

yaml 复制代码
2025-11-02 10:15:32,123 - makdo - INFO - Starting MAKDO - Multi-Agent Kubernetes DevOps System
2025-11-02 10:15:32,456 - makdo - INFO - Coordinator and sub-agents created successfully
2025-11-02 10:15:32,500 - makdo - INFO - Setting up tool call monitoring...
2025-11-02 10:15:32,550 - makdo - INFO - ✅ Tool call monitoring enabled for all agents
2025-11-02 10:15:32,600 - makdo - INFO - Getting kubeconfig for context: kind-makdo-worker

如果你看到 kubectlkubeconfig 相关错误,说明 kubeconfig ConfigMap 可能缺失或不正确。请确认你已经用本地 kubeconfig 创建了 makdo-kubeconfig ConfigMap。

要在 MAKDO pod 内验证 kubectl 访问工作集群,可以运行:

sql 复制代码
kubectl exec -it deployment/makdo --context kind-makdo-control -- kubectl get nodes --context kind-makdo-worker

它会在 MAKDO 容器内运行 kubectl 来查询工作集群。输出如下:

复制代码
NAME                         STATUS   ROLES           AGE   VERSION
makdo-worker-control-plane   Ready    control-plane   45m   v1.33.1

成功!MAKDO 可以访问工作集群。等我们部署好 k8s-ai 后,A2A 连接也会正常工作。

验证 MAKDO 部署与日志(Verifying MAKDO deployment and logs)

验证 MAKDO 健康并准备好监控工作集群。检查 pod 状态:

ini 复制代码
kubectl get pods -l app=makdo --context kind-makdo-control

输出如下:

sql 复制代码
NAME                     READY   STATUS    RESTARTS   AGE
makdo-7c9f8b6d5d-x2k4j   1/1     Running   0          2m

pod 正在运行。检查资源使用情况:

css 复制代码
kubectl top pod -l app=makdo --context kind-makdo-control

输出可能如下(需要 metrics-server,KinD 中可能不可用):

vbscript 复制代码
Error from server (ServiceUnavailable): the server is currently unable to handle the request (get pods.metrics.k8s.io)

没关系,KinD 默认不包含 metrics-server。我们可以从 pod spec 查看资源限制:

ini 复制代码
kubectl describe pod -l app=makdo --context kind-makdo-control | grep -A 5 "Limits"

输出如下:

yaml 复制代码
    Limits:
      cpu:     500m
      memory:  1Gi
    Requests:
      cpu:        250m
      memory:     512Mi

资源配置正确。再检查 MAKDO 的日志是否有异常:

css 复制代码
kubectl logs -l app=makdo --context kind-makdo-control --tail=100

重点关注这些指标:

  • Coordinator started:Starting MAKDO - Multi-Agent Kubernetes DevOps System
  • Sub-agents created:Coordinator and sub-agents created successfully
  • Attempting k8s-ai session:Creating k8s-ai session for kind-makdo-worker...
  • Health check loop started:Starting health check loop

你会看到 k8s-ai 连接失败的错误,这是因为 k8s-ai 还没部署。关键是 MAKDO 没有崩溃并能正常启动。

如果 MAKDO 发生 crash-loop,常见原因包括:

  • 缺少 secrets :确认 makdo-secrets 存在并包含所有 key:

    sql 复制代码
    kubectl get secret makdo-secrets --context kind-makdo-control
  • 缺少 kubeconfig ConfigMap :确认已在部署前创建 makdo-kubeconfig

  • Python 错误:日志中如果出现 import error 或缺依赖,可能需要重建镜像。

要实时跟踪 MAKDO 行为,可以使用:

css 复制代码
kubectl logs -l app=makdo --context kind-makdo-control --follow

按 Ctrl + C 停止。MAKDO 已部署完成,并在等待 k8s-ai。下一节我们会把 k8s-ai 部署到工作集群,这样 MAKDO 就能开始真正监控与修复了。

将 k8s-ai 部署到工作集群(Deploying k8s-ai to the worker cluster)

现在 MAKDO 已在控制集群中运行,我们需要把 k8s-ai 部署到工作集群。k8s-ai 通过 A2A 协议暴露 Kubernetes 诊断能力,使 MAKDO 的 Analyzer 与 Fixer 智能体能够检查集群健康状况并执行修复动作。我们将把 k8s-ai 容器化,将其作为 Kubernetes 服务部署,并对外暴露,以便 MAKDO 能够跨集群与其通信。

构建 k8s-ai Docker 镜像(Building the k8s-ai Docker image)

k8s-ai 需要在工作集群中以容器方式运行。我们将创建一个 Dockerfile,把 k8s-ai 与所有依赖打包,安装 kubectl 以访问集群,并把它配置为 A2A server 运行。

创建 k8s-ai/Dockerfile

bash 复制代码
FROM python:3.13-slim

# Install system dependencies
RUN apt-get update && apt-get install -y \
    curl \
    git \
    && rm -rf /var/lib/apt/lists/*

# Install kubectl
RUN curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/arm64/kubectl" && \
    install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl && \
    rm kubectl

WORKDIR /app

# Copy k8s-ai source
COPY k8s_ai ./k8s_ai
COPY pyproject.toml .

# Install k8s-ai and dependencies
RUN pip install --no-cache-dir -e .

# Create directory for API keys
RUN mkdir -p /app/data

# Expose A2A server port and Admin API port
EXPOSE 9999 9998

# Run k8s-ai server in A2A mode
CMD ["k8s-ai-server", "--host", "0.0.0.0", "--port", "9999", "--admin-port", "9998"]

上面这段代码的关键点如下:

  • 基础镜像Python 3.12-slim 提供一个最小化的 Python 环境。
  • kubectl 安装:k8s-ai 通过执行 kubectl 命令与集群交互。我们下载最新稳定版并安装。
  • 源码 :复制 k8s_ai 包与 pyproject.toml 文件。使用 pip install -e . 以 editable 方式安装 k8s-ai。
  • 数据目录/app/data 用于存储认证所需的 API key(keys.json)。
  • 端口9999 用于 A2A 协议 server,9998 用于 Admin API(创建 session 时使用)。
  • CMD :使用参数启动 k8s-ai-server,绑定到所有网卡(0.0.0.0),以便容器外部可访问。

k8s-ai 的源码位于主 k8s-ai 仓库中。把它复制到 ch11/k8s-ai 目录:

bash 复制代码
# From the k8s-ai repository root
cp -r k8s_ai /path/to/Design-Multi-Agent-AI-Systems-Using-MCP-and-A2A/ch11/k8s-ai/
cp pyproject.toml /path/to/Design-Multi-Agent-AI-Systems-Using-MCP-and-A2A/ch11/k8s-ai/

构建镜像:

bash 复制代码
cd ch11/k8s-ai
docker build -t k8s-ai:latest .

这会花几分钟下载基础镜像并安装依赖。完成后,验证镜像:

perl 复制代码
docker images | grep k8s-ai

输出如下:

复制代码
k8s-ai      latest    abc123def456   2 minutes ago   450MB

镜像已构建完成,可以部署到工作集群。

创建 k8s-ai 部署清单(Creating k8s-ai deployment manifests)

k8s-ai 需要若干 Kubernetes 资源才能运行:一个拥有访问集群权限的 ServiceAccount、一个运行容器的 Deployment、以及一个对外暴露的 Service。我们将使用 RBAC(role-based access control) 为 k8s-ai 授予只读的集群访问权限。

k8s-ai 的部署清单在这里:
github.com/PacktPublis...

关键配置点包括:

  • ServiceAccount 与 RBAC :k8s-ai 的 service account 通过 ClusterRole k8s-ai-reader 获得只读权限。这允许 k8s-ai 执行 kubectl get/list/watch,但禁止任何修改操作。ClusterRoleBindingServiceAccount 绑定到 ClusterRole
  • API keys secret :包含 keys.json(从你的 .env 文件来的 API key)。MAKDO 的 Analyzer 与 Fixer 将使用该 key 进行认证。该 key 以 ${K8S_AI_API_KEY} 占位符形式出现,应用清单时会从环境变量替换。
  • Deployment :以 imagePullPolicy: Never 运行一个副本的 k8s-ai(KinD 使用本地镜像)。容器从 Secret 获取 OpenAI API key。资源限制防止 k8s-ai 过度消耗内存/CPU。
  • 健康探针 :liveness probe 通过请求 /.well-known/agent.json 检查 k8s-ai 是否响应;readiness probe 确保 pod 在对外提供服务前已就绪。
  • Service :使用 NodePort 类型暴露 k8s-ai。30100 映射到 A2A server(9999),30099 映射到 Admin API(9998)。回想一下 worker-cluster.yaml:端口 30100 会映射到宿主机端口 8100,使控制集群能通过 http://host.docker.internal:8100 访问 k8s-ai。

接下来,我们看看如何部署刚构建好的 k8s-ai 镜像。

将 k8s-ai 部署到工作集群(Deploying k8s-ai to the worker cluster)

镜像构建完成且清单准备就绪后,我们就可以把 k8s-ai 部署到工作集群。首先把镜像加载进工作集群,创建所需的 secrets,然后应用部署。

把 k8s-ai 镜像加载到工作集群:

lua 复制代码
kind load docker-image k8s-ai:latest --name makdo-worker

输出如下:

vbnet 复制代码
Image: "k8s-ai:latest" with ID "sha256:1fe7b6c86eb2..." not yet present on node "makdo-worker-control-plane", loading...

这会把镜像从本地 Docker 传到工作集群的内部镜像缓存。没有这一步的话,pod 会因为 KinD 默认无法访问外部镜像仓库而出现 ImagePullBackOff

创建 OpenAI API key secret。k8s-ai 需要它来调用 LLM 做自然语言处理:

ini 复制代码
kubectl create secret generic k8s-ai-secrets \
  --from-literal=openai-api-key="${OPENAI_API_KEY}" \
  --context kind-makdo-worker

验证 secret 创建成功:

sql 复制代码
kubectl get secret k8s-ai-secrets --context kind-makdo-worker

输出如下:

复制代码
NAME              TYPE     DATA   AGE
k8s-ai-secrets    Opaque   1      5s

在部署前,请确保你在 ch11 目录下有一个包含必要凭据的 .env 文件。复制示例文件:

bash 复制代码
cd ch11
cp .env.example .env

编辑 .env 并设置你的凭据。

  • K8S_AI_API_KEY 设为 test-key(用于开发)。
  • 生产环境中,可运行 k8s-ai-server --generate-key 生成 key,并赋值给 K8S_AI_API_KEY
  • OPENAI_API_KEY 设为你的 OpenAI API key。
  • 只有在使用 Slack bot 时才需要 Slack 凭据。

.env 文件已在 .gitignore 中,因此你的 secrets 不会被提交。

现在,使用 envsubst 替换环境变量并应用部署清单:

bash 复制代码
cd k8s-ai
export $(grep -v '^#' ../.env | xargs)
envsubst < deployment.yaml | kubectl apply -f - --context kind-makdo-worker

输出如下:

bash 复制代码
serviceaccount/k8s-ai created
clusterrole.rbac.authorization.k8s.io/k8s-ai-reader created
clusterrolebinding.rbac.authorization.k8s.io/k8s-ai-reader-binding created
secret/k8s-ai-api-keys created
deployment.apps/k8s-ai created
service/k8s-ai created

共创建了 6 个资源:ServiceAccountClusterRoleClusterRoleBindingSecret(API keys)、DeploymentService。检查 pod 状态:

ini 复制代码
kubectl get pods -l app=k8s-ai --context kind-makdo-worker

输出如下:

sql 复制代码
NAME                      READY   STATUS    RESTARTS   AGE
k8s-ai-7b9c8d6f5d-x2k4j   1/1     Running   0          45s

pod 已运行。如果看到 ImagePullBackOff,请确认已经用 kind load 加载镜像。如果看到 CrashLoopBackOff,检查日志定位错误(通常是缺少 OpenAI API key)。

检查 service:

sql 复制代码
kubectl get svc k8s-ai --context kind-makdo-worker

输出如下:

scss 复制代码
NAME     TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)             AGE
k8s-ai   NodePort   10.96.145.123   <none>    9999:30100/TCP,9998:30099/TCP   1m

service 暴露了两个 node port:30100 给 A2A server,30099 给 Admin API。由于我们在 worker-cluster.yaml 里配置了 extraPortMappings,这些端口会在宿主机上分别对应 localhost:8100localhost:8099

对外暴露 k8s-ai 以实现跨集群访问(Exposing the k8s-ai service for cross-cluster access)

k8s-ai 已在工作集群中运行,但控制集群中的 MAKDO 需要访问它。在我们的 KinD 环境里,跨集群通信通过 Docker 宿主机网络进行。工作集群的 node port 30100 通过我们之前配置的 extraPortMappings 映射到了宿主机端口 8100

从控制集群视角看,工作集群可以通过 host.docker.internal:8100 访问。该特殊 DNS 名会解析到 Docker 宿主机 IP,使得一个 KinD 集群中的容器可以访问另一个集群中暴露到宿主机的服务。

验证网络是否正常。首先检查 k8s-ai 的 agent card endpoint 是否能响应:

bash 复制代码
curl http://localhost:8100/.well-known/agent.json

输出如下(为便于阅读已格式化):

json 复制代码
{
  "name": "k8s-ai Diagnostic Agent",
  "description": "Kubernetes AI diagnostic agent with read-only cluster analysis with session-based cluster management",
  "url": "http://0.0.0.0:9999/",
  "version": "2.0.0",
  "capabilities": {
    "streaming": false
  },
  "skills": [
    {
      "id": "kubernetes_diagnostics",
      "name": "Kubernetes Diagnostics",
      "description": "Perform read-only Kubernetes cluster diagnostics, troubleshooting, and health analysis with detailed insights",
      "tags": ["kubernetes", "diagnostics", "troubleshooting", "monitoring", "health"]
    }
  ]
}

agent card 说明 k8s-ai 正在响应。现在,通过 Admin API 创建 session 来测试认证。Admin API 需要 .env 里的 API key:

arduino 复制代码
curl -X POST http://localhost:8099/sessions \
  -H "Authorization: Bearer test-key" \
  -H "Content-Type: application/json" \
  -d '{
    "cluster_name": "makdo-worker",
    "ttl_hours": 24
  }'

如果你尚未配置 ServiceAccount 属性,这一步可能会返回认证错误。没关系------这里只是验证 endpoint 是否可达。下一小节我们会测试完整的 session 创建流程。

这里的关键点是:MAKDO 智能体会使用 http://host.docker.internal:8100 访问 k8s-ai 的 A2A server。这一点已经在 MAKDO 的 coordinator.yaml 里配置好了:

yaml 复制代码
a2a_servers:
  - name: "kind-makdo-worker"
    url: "http://host.docker.internal:8100"
    timeout: 30.0
    api_key: "test-key"

网络已经就绪。MAKDO 现在可以跨集群与 k8s-ai 通信了。

验证 k8s-ai 部署(Verifying k8s-ai deployment)

部署 k8s-ai 后,验证各组件是否正常运行且服务可访问。

检查 pod 状态(Check pod status)

首先,确认 k8s-ai pod 在工作集群中运行:

ini 复制代码
kubectl get pods -l app=k8s-ai --context kind-makdo-worker -o wide

期望输出:

sql 复制代码
NAME                      READY   STATUS    RESTARTS   AGE   IP           NODE
k8s-ai-75558cb559-n8jl9   1/1     Running   0          20m   10.244.0.5   makdo-worker-control-plane

pod 应显示 1/1 Running 且无重启。

验证 pod 健康状态(Verify pod health)

检查 pod 的详细状态与健康探针:

ini 复制代码
kubectl describe pod -l app=k8s-ai --context kind-makdo-worker | grep -A 5 "Conditions:"

期望输出:

python 复制代码
Conditions:
  Type                        Status
  PodReadyToStartContainers   True
  Initialized                 True
  Ready                       True
  ContainersReady             True
  PodScheduled                True

所有条件都应为 True,表示已通过 liveness/readiness probe。

查看服务端日志(Check server logs)

查看 k8s-ai 日志确认两个 server 都已启动:

css 复制代码
kubectl logs -l app=k8s-ai --context kind-makdo-worker --tail=50

查找类似的健康探针访问日志,说明 A2A endpoint 正常响应:

vbnet 复制代码
INFO:     10.244.0.1:41262 - "GET /.well-known/agent.json HTTP/1.1" 200 OK

Kubernetes 定期的 health probe 请求即表明该服务健康。

测试 A2A endpoint(Test the A2A endpoint)

验证从集群外部可访问 agent card:

bash 复制代码
curl -s http://localhost:8100/.well-known/agent.json | python3 -m json.tool | head -30

期望响应(截断):

json 复制代码
{
    "capabilities": {
        "streaming": false
    },
    "defaultInputModes": [
        "text/plain"
    ],
    "defaultOutputModes": [
        "text/plain"
    ],
    "description": "Kubernetes AI diagnostic agent with read-only cluster analysis with session-based cluster management",
    "name": "k8s-ai Diagnostic Agent",
    "preferredTransport": "JSONRPC",
    "protocolVersion": "0.3.0",
    "security": [
        {
            "BearerAuth": []
        }
    ],
    "securitySchemes": {
        "BearerAuth": {
            "scheme": "bearer",
            "type": "http"
        }
    ],
    "skills": [
        {
            "description": "Perform read-only Kubernetes cluster diagnostics...",

这确认了:

  • A2A server 在 pod 内的 9999 端口运行
  • NodePort service 把 30100 映射到容器端口
  • 宿主机端口映射(8100 → 30100)允许外部访问
  • agent card 符合 A2A 协议规范
  • bearer token 认证已启用

验证 service 配置(Verify service configuration)

检查 k8s-ai service 的配置:

arduino 复制代码
kubectl get svc k8s-ai --context kind-makdo-worker -o yaml | grep -A 10 "spec:"

期望输出:

yaml 复制代码
spec:
  ports:
  - name: a2a
    nodePort: 30100
    port: 9999
    protocol: TCP
    targetPort: 9999
  - name: admin
    nodePort: 30099
    port: 9998
    protocol: TCP
    targetPort: 9998
  selector:
    app: k8s-ai
  type: NodePort

这表明 A2A 端口(9999)和 Admin API 端口(9998)都通过 NodePort 暴露。

k8s-ai 已验证完成并在运行,工作集群现在已经有一个可供 MAKDO 跨集群调用的诊断智能体。

测试 k8s-ai Admin API 与 session 管理(Testing the k8s-ai Admin API and session management)

k8s-ai Admin API 提供 session 管理能力,让 MAKDO 可以创建与工作集群交互的隔离 session。每个 session 都有独立 kubeconfig 与过期时间。

暴露 Admin API 端口(Exposing the Admin API port)

默认情况下,工作集群配置暴露了 A2A 端口(8100),但不一定暴露 Admin API 端口。把 worker-cluster.yaml 更新为包含 8099

yaml 复制代码
# ch11/worker-cluster.yaml
extraPortMappings:
  # Port for k8s-ai A2A server
  - containerPort: 30100
    hostPort: 8100
    protocol: TCP
  # Port for k8s-ai Admin API
  - containerPort: 30099
    hostPort: 8099
    protocol: TCP

如果你已经创建了 worker 集群,需要用更新后的配置重新创建:

sql 复制代码
kind delete cluster --name makdo-worker
kind create cluster --config worker-cluster.yaml

然后按前面的步骤重新部署 k8s-ai。

创建 session(Creating a session)

创建 session 需要提供工作集群 kubeconfig。先导出工作集群 kubeconfig:

css 复制代码
kubectl config view --context kind-makdo-worker --minify --flatten > /tmp/makdo-worker-kubeconfig.yaml

创建 session 请求 JSON 文件:

python 复制代码
import json

# Read kubeconfig
with open('/tmp/makdo-worker-kubeconfig.yaml', 'r') as f:
    kubeconfig = f.read()

# Create session request
request = {
    "cluster_name": "makdo-worker",
    "ttl_hours": 24,
    "kubeconfig": kubeconfig
}

# Write to file
with open('/tmp/session-request.json', 'w') as f:
    json.dump(request, f)

print("Session request created")

现在通过 Admin API 创建 session:

arduino 复制代码
curl -s -X POST 'http://localhost:8099/sessions' \
  -H 'Authorization: Bearer test-key' \
  -H 'Content-Type: application/json' \
  -d '@/tmp/session-request.json' | python3 -m json.tool

期望响应:

json 复制代码
{
    "success": true,
    "session_token": "k8s-ai-session--qSTOZ0ggxnL-w5mMmMNboUBz0GVIGXvxkxfjYY5ND0",
    "cluster_name": "makdo-worker",
    "api_server": "https://127.0.0.1:65089",
    "namespace": "default",
    "connectivity_status": "connected",
    "expires_at": "2025-11-10T04:37:27.297559Z",
    "error": null
}

session_tokenk8s-ai-session--...)将用于对 A2A endpoint 的请求进行认证。

列出活跃 session(Listing active sessions)

查看所有活跃 session:

rust 复制代码
curl -s 'http://localhost:8099/sessions' \
  -H 'Authorization: Bearer test-key' | python3 -m json.tool

期望响应:

json 复制代码
{
    "total_sessions": 1,
    "sessions": [
        {
            "session_token": "k8s-ai-session--qSTOZ0ggxnL-w5mMmMNboUBz0GVIGXvxkxfjYY5ND0",
            "cluster_name": "makdo-worker",
            "api_server": "https://127.0.0.1:65089",
            "namespace": "default",
            "created_at": "2025-11-09T04:37:27.297568Z",
            "expires_at": "2025-11-10T04:37:27.297559Z",
            "is_expired": false
        }
    ]
}

下面看看如何删除一个 session。

删除 session(Deleting a session)

在 session 过期前手动删除:

bash 复制代码
SESSION_TOKEN="k8s-ai-session--qSTOZ0ggxnL-w5mMmMNboUBz0GVIGXvxkxfjYY5ND0"

curl -s -X DELETE "http://localhost:8099/sessions/${SESSION_TOKEN}" \
  -H 'Authorization: Bearer test-key' | python3 -m json.tool

期望响应:

json 复制代码
{
    "success": true,
    "message": "Session deleted successfully"
}

接下来看看如何使用 A2A protocol 搭配 session。

在 A2A 协议中使用 session(Using sessions with the A2A protocol)

MAKDO 会在对 k8s-ai 发起 A2A 请求时使用 session token。token 会通过 Authorization header 传递,同时在方法参数里携带 session 相关信息:

vbnet 复制代码
curl -s -X POST 'http://localhost:8100/' \
  -H 'Authorization: Bearer test-key' \
  -H 'Content-Type: application/json' \
  -d '{
    "jsonrpc": "2.0",
    "method": "kubernetes_diagnose_issue",
    "params": {
      "session_token": "'"${SESSION_TOKEN}"'",
      "issue_description": "Check pod health in default namespace"
    },
    "id": 1
  }'

这种基于 session 的方式带来若干好处:

  • 隔离性:每个 MAKDO 实例都能有自己的 session,互不干扰
  • 安全性:session 自动过期,限制访问窗口
  • 灵活性:不同 session 可针对不同 namespace 或集群
  • 可审计性:session 的创建与使用会记录日志,便于安全审计

到这里,Admin API 已测试通过且可用,k8s-ai 也已经准备好跨集群接收来自 MAKDO 的诊断请求。

启用集群间的安全通信(Enabling secure communication between clusters)

在控制集群中部署了 MAKDO、在工作集群中部署了 k8s-ai 之后,我们需要确保两者之间的通信是安全的。本节涵盖服务发现、网络、访问控制,以及已经就位的安全机制,并演示这些机制在 KinD 环境中如何工作。

服务发现与网络(Service discovery and networking)

在多集群部署中,智能体需要跨越集群边界发现并彼此通信。我们的部署使用显式配置宿主机网络来实现跨集群通信。

MAKDO 如何发现 k8s-ai(How MAKDO discovers k8s-ai)

MAKDO 使用静态配置来发现 k8s-ai 服务。查看配置:

arduino 复制代码
kubectl get configmap makdo-config --context kind-makdo-control \
  -o jsonpath='{.data.makdo.yaml}' | grep -A 5 "k8s_ai:"

期望输出如下:

makefile 复制代码
k8s_ai:
  base_url: "http://host.docker.internal:8100"
  admin_api_url: "http://host.docker.internal:8100/admin"

关键网络组件包括:

  • host.docker.internal:一个特殊 DNS 名,在容器内部解析到 Docker 宿主机
  • 端口 8100 :从工作集群的 NodePort 30100 映射到宿主机端口 8100
  • 端口 8099 :从 Admin API 的 NodePort 30099 映射出来

跟踪一次请求路径(Tracing a request path)

我们来跟踪一次诊断请求是如何从 MAKDO 流向 k8s-ai 的:

MAKDO Pod(控制集群)

http://host.docker.internal:8100

Docker 宿主机网络

localhost:8100

工作集群节点(Docker 容器)

↓ NodePort 30100

k8s-ai Service(工作集群)

↓ ClusterIP:9999

k8s-ai Pod(工作集群)

验证每一步:

bash 复制代码
# 1. 检查 MAKDO 是否能解析 host.docker.internal
kubectl exec deployment/makdo --context kind-makdo-control -- \
  python3 -c "import socket; print(f'host.docker.internal resolves to: {socket.gethostbyname("host.docker.internal")}')"

# 2. 检查宿主机能否访问 8100 端口
curl -s http://localhost:8100/.well-known/agent.json | python3 -m json.tool | head -10

# 3. 检查工作集群中的 NodePort service
kubectl get svc k8s-ai --context kind-makdo-worker -o yaml | grep -A 5 "nodePort: 30100"

# 4. 检查 k8s-ai pod 是否在接收流量
kubectl logs deployment/k8s-ai --context kind-makdo-worker --tail=5

在生产系统中,这种跨网络调用链可能会为对延迟敏感的操作增加显著时延。为此,可以引入延迟预算(latency budget) 并进行显式监控与管理。

为了访问 k8s-ai server,我们首先需要发现它。不同用例下有若干常见模式。下面来看看。

服务发现模式(Service discovery patterns)

我们的部署演示了静态配置的服务发现。生产环境中还包括:

  • 基于 DNS 的发现(DNS-based discovery) :使用 Kubernetes DNS 发现集群内服务:
makefile 复制代码
# 同一集群内的服务
k8s_ai:
  base_url: "http://k8s-ai.default.svc.cluster.local:9999"
  • 服务网格发现(Service mesh discovery) :使用 Istio 或 Linkerd 等服务网格:
yaml 复制代码
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
  name: k8s-ai-external
spec:
  hosts:
  - k8s-ai.worker-cluster.global
  location: MESH_EXTERNAL
  ports:
  - number: 9999
    name: a2a
    protocol: HTTP
  resolution: DNS
  endpoints:
  - address: k8s-ai.worker-cluster.svc.cluster.local
  • 动态服务注册表(Dynamic service registry) :使用 Consul 等服务注册中心:
ini 复制代码
import consul

# 注册 k8s-ai 服务
client = consul.Consul()
client.agent.service.register(
    name='k8s-ai',
    service_id='k8s-ai-worker-1',
    address='k8s-ai.worker-cluster',
    port=9999,
    tags=['a2a', 'diagnostics']
)

# 发现服务
services = client.health.service('k8s-ai', passing=True)
for service in services:
    print(f"Found k8s-ai at {service['Service']['Address']}:{service['Service']['Port']}")

下面我们考虑暴露 k8s-ai server 的不同网络方式。

跨集群网络方案(Cross-cluster networking approaches)

不同环境需要不同的网络策略:

KinD(当前方案)
  • 使用 Docker 宿主机网络(host.docker.internal
  • NodePort service + extraPortMappings
  • 简单,适合本地开发:
yaml 复制代码
extraPortMappings:
- containerPort: 30100
  hostPort: 8100
云厂商(AWS / GCP / Azure)
  • 使用 LoadBalancer service + 公网 IP
  • 或使用 VPC Peering 的私网互联
  • 或用 Transit Gateway 做多集群连通:
yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: k8s-ai
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
    service.beta.kubernetes.io/aws-load-balancer-internal: "true"
spec:
  type: LoadBalancer
  selector:
    app: k8s-ai
  ports:
  - port: 9999
    targetPort: 9999
多集群服务网格(Multi-cluster service mesh)
  • 跨集群自动可发现
  • 集群间双向 TLS(mTLS)
  • 流量治理与可观测性:
yaml 复制代码
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  values:
    global:
      multiCluster:
        clusterName: worker-cluster
      network: network1

对分布式系统来说,端到端连通性测试非常重要。

端到端连通性测试(Testing end-to-end connectivity)

验证从 MAKDO 到 k8s-ai 的完整连通性:

bash 复制代码
# 创建一个测试 session
kubectl config view --context kind-makdo-worker --minify --flatten > /tmp/test-conn.yaml

python3 << 'EOF'
import json

with open('/tmp/test-conn.yaml', 'r') as f:
    kubeconfig = f.read()

request = {
    "cluster_name": "connectivity-test",
    "ttl_hours": 1,
    "kubeconfig": kubeconfig
}

with open('/tmp/test-conn.json', 'w') as f:
    json.dump(request, f)
EOF

# 通过 Admin API 创建 session
RESPONSE=$(curl -s -X POST 'http://localhost:8099/sessions' \
  -H 'Authorization: Bearer test-key' \
  -H 'Content-Type: application/json' \
  -d '@/tmp/test-conn.json')

echo $RESPONSE | python3 -m json.tool

# 提取 session token
SESSION_TOKEN=$(echo $RESPONSE | python3 -c "import sys, json; print(json.load(sys.stdin)['session_token'])")

echo "Session token: ${SESSION_TOKEN}"

接着,测试 MAKDO(运行在控制集群中)是否能通过同一路径访问该 endpoint:

bash 复制代码
# 从宿主机测试(模拟 MAKDO 的视角)
curl -s 'http://localhost:8100/.well-known/agent.json' \
  -H 'Authorization: Bearer test-key' | python3 -m json.tool | head -15

命令输出(截断)显示 agent card:

json 复制代码
{
    "capabilities": {
        "streaming": false
    },
    "defaultInputModes": [
        "text/plain"
    ],
    "defaultOutputModes": [
        "text/plain"
    ],
    "description": "Kubernetes AI diagnostic agent with read-only cluster analysis with session-based cluster management",
    "name": "k8s-ai Diagnostic Agent",

这确认了完整路径:MAKDO → Docker 宿主机 → 工作集群 → k8s-ai pod

工业级系统必须提供纵深防御(defense in depth) 以满足安全要求。下面看看 MAKDO 与 k8s-ai 已经提供了什么。

理解安全架构(Understanding the security architecture)

我们的部署实现了多层安全:

  • API key 认证:MAKDO 与 k8s-ai 都使用 bearer token 认证
  • 基于 session 的访问:k8s-ai 使用带过期时间的临时 session
  • RBAC:k8s-ai 在工作集群中只有只读权限
  • 网络隔离:通信只通过特定端口流动且可控
  • secret 管理 :凭据存放于 Kubernetes Secrets 与 .env 文件

这遵循安全最佳实践,尽量降低远程访问、数据外泄、权限提升、横向移动与敏感信息暴露的风险。

API key 认证(API key authentication)

API key 认证是为远程服务提供安全访问的常见方式。我们看看 k8s-ai 是如何实现的。

k8s-ai 认证(k8s-ai authentication)

k8s-ai 的 A2A endpoint 与 Admin API 都需要 bearer token 认证。API keys 存放在部署期间创建的 Kubernetes secret 中。

查看已存储的 API keys:

ini 复制代码
kubectl get secret k8s-ai-api-keys --context kind-makdo-worker \
  -o jsonpath='{.data.keys.json}' | base64 -d | python3 -m json.tool

期望输出:

json 复制代码
{
    "api_keys": [
        {
            "key": "test-key",
            "name": "MAKDO Client",
            "created": "2025-01-01T00:00:00"
        }
    ]
}

不带凭据发起请求测试认证:

rust 复制代码
curl -s 'http://localhost:8099/sessions' | python3 -m json.tool

期望响应:

json 复制代码
{
    "detail": "Not authenticated"
}

再用有效凭据测试:

rust 复制代码
curl -s 'http://localhost:8099/sessions' \
  -H 'Authorization: Bearer test-key' | python3 -m json.tool

这会返回活跃 session 列表,证明认证生效。

MAKDO 配置(MAKDO configuration)

MAKDO 在其配置里存储 k8s-ai API key。检查 MAKDO ConfigMap:

arduino 复制代码
kubectl get configmap makdo-config --context kind-makdo-control \
  -o jsonpath='{.data.makdo.yaml}' | grep -A 3 "a2a_servers:"

期望输出展示 API key 配置:

yaml 复制代码
a2a_servers:
  - name: "kind-makdo-worker"
    url: "http://host.docker.internal:8100"
    timeout: 30.0
    api_key: "test-key"

在生产环境中,请记住:API keys 应使用强随机值(而不是 test-key),定期轮换,存放在专门的密钥管理系统中(例如 HashiCorp Vault、AWS Secrets Manager 等),并且绝不能提交到版本控制系统。

基于 session 的安全(Session-based security)

k8s-ai 项目实现了基于 session 的访问控制,在 API key 之外增加了一层安全。session 生命周期包括:

  • 创建(Creation) :MAKDO 通过 Admin API 创建 session,并提供 kubeconfig
  • 使用(Usage) :所有诊断操作都使用 session token
  • 过期(Expiration) :session 在 TTL 后自动过期
  • 清理(Cleanup) :过期 session 自动移除

下面演示 session 安全性。

创建一个短 TTL session:

python 复制代码
# 导出 kubeconfig
kubectl config view --context kind-makdo-worker --minify --flatten > /tmp/test-kubeconfig.yaml

# 创建 1 分钟 TTL session
python3 << 'EOF'
import json

with open('/tmp/test-kubeconfig.yaml', 'r') as f:
    kubeconfig = f.read()

request = {
    "cluster_name": "test-session",
    "ttl_hours": 0.0167,  # 1 minute = 1/60 hours
    "kubeconfig": kubeconfig
}

with open('/tmp/short-session.json', 'w') as f:
    json.dump(request, f)
EOF

curl -s -X POST 'http://localhost:8099/sessions' \
  -H 'Authorization: Bearer test-key' \
  -H 'Content-Type: application/json' \
  -d '@/tmp/short-session.json' | python3 -m json.tool

响应里包含 expires_at 时间戳。过期后 session 会失效:

vbnet 复制代码
# 等待 90 秒
sleep 90

# 尝试使用已过期 session
SESSION_TOKEN=" < token-from-creation-response >"

curl -s -X POST 'http://localhost:8100/' \
  -H 'Authorization: Bearer test-key' \
  -H 'Content-Type: application/json' \
  -d '{
    "jsonrpc": "2.0",
    "method": "kubernetes_diagnose_issue",
    "params": {
      "session_token": "'"${SESSION_TOKEN}"'",
      "issue_description": "test"
    },
    "id": 1
  }'

期望响应表明 session 已过期:

css 复制代码
{
    "jsonrpc": "2.0",
    "error": {
        "code": -32002,
        "message": "Session not found or expired"
    },
    "id": 1
}

这种限时访问降低了凭据泄露后的影响面。

RBAC 与最小权限(RBAC and least privilege)

k8s-ai 在工作集群中以最小权限运行。

检查 RBAC 配置(Inspecting RBAC configuration)

查看分配给 k8s-ai 的 ClusterRole:

sql 复制代码
kubectl get clusterrole k8s-ai-reader --context kind-makdo-worker -o yaml

关键权限如下:

makefile 复制代码
rules:
- apiGroups: [""]
  resources: ["pods", "pods/log", "services", "nodes", "namespaces", "events"]
  verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
  resources: ["deployments", "replicasets", "statefulsets", "daemonsets"]
  verbs: ["get", "list", "watch"]
- apiGroups: ["batch"]
  resources: ["jobs", "cronjobs"]
  verbs: ["get", "list", "watch"]

注意这里只有只读动词:getlistwatch。没有 createupdatedeletepatch

测试权限边界(Testing permission boundaries)

验证 k8s-ai 无法修改资源:

ini 复制代码
# 取一个 pod 名
POD_NAME=$(kubectl get pods --context kind-makdo-worker -o jsonpath='{.items[0].metadata.name}')

# 使用 k8s-ai 的 service account 尝试删除
kubectl delete pod ${POD_NAME} --context kind-makdo-worker \
  --as=system:serviceaccount:default:k8s-ai

期望报错:

vbnet 复制代码
Error from server (Forbidden): pods "k8s-ai-f77d65f7d-p6lkk" is forbidden:
User "system:serviceaccount:default:k8s-ai" cannot delete resource "pods"
in API group "" in the namespace "default"

这说明即使攻击者获得 k8s-ai 的访问权限,也无法修改或删除集群资源。

KinD 中的网络分段(Network segmentation in KinD)

虽然 KinD 集群运行在同一个 Docker 网络上,我们仍通过端口映射与服务配置来控制通信。

端口映射安全(Port mapping security)

查看暴露的端口:

css 复制代码
docker ps --filter name=makdo-control-plane --format "table {{.Names}}\t{{.Ports}}"
docker ps --filter name=makdo-worker-control-plane --format "table {{.Names}}\t{{.Ports}}"

输出展示受控暴露:

ruby 复制代码
NAMES                           PORTS
makdo-control-control-plane     127.0.0.1:xxx->6443/tcp, 0.0.0.0:9000->30000/tcp
makdo-worker-control-plane      127.0.0.1:xxx->6443/tcp, 0.0.0.0:8099->30099/tcp, 0.0.0.0:8100->30100/tcp

关键观察点:

  • Kubernetes API :绑定在 127.0.0.1(仅本机可访问,不对外暴露)
  • 应用端口 :绑定在 0.0.0.0(宿主机可访问,模拟外部访问)
  • 仅暴露指定端口:并非所有容器端口都被暴露

这展示了如何在 KinD 环境中管理 Kubernetes 的连通性与网络,同时保持隔离。下面我们来测试一下。

测试网络隔离(Testing network isolation)

尝试从宿主机直接访问 Kubernetes API(应该失败):

bash 复制代码
# 获取工作集群 API server 地址
WORKER_API=$(kubectl config view --context kind-makdo-worker --minify \
  -o jsonpath='{.clusters[0].cluster.server}')

echo "Worker API: ${WORKER_API}"

# 无正确凭据访问(应失败)
curl -k "${WORKER_API}/api/v1/namespaces"

由于认证要求,我们会得到预期错误:

json 复制代码
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "Unauthorized",
  "reason": "Unauthorized",
  "code": 401
}

Kubernetes API 受到保护,只有持有正确 kubeconfig 凭据才能访问。

生产环境安全增强(Production security enhancements)

对于超出 KinD 的生产部署,还应实现以下额外安全措施:

  • TLS/SSL 加密:本地(KinD)中 MAKDO 与 k8s-ai 的通信是 HTTP;生产中要为两端启用 TLS:
yaml 复制代码
# k8s-ai with TLS
containers:
- name: k8s-ai
  env:
  - name: TLS_CERT_FILE
    value: "/certs/tls.crt"
  - name: TLS_KEY_FILE
    value: "/certs/tls.key"
  volumeMounts:
  - name: tls-certs
    mountPath: /certs
    readOnly: true
volumes:
- name: tls-certs
  secret:
    secretName: k8s-ai-tls

使用 cert-manager 或云厂商证书管理服务。

  • NetworkPolicy:限制 pod-to-pod 通信:
yaml 复制代码
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: k8s-ai-network-policy
spec:
  podSelector:
    matchLabels:
      app: k8s-ai
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: makdo-namespace
    ports:
    - protocol: TCP
      port: 9999
  • Pod 安全标准(Pod security standards) :强制安全上下文:
yaml 复制代码
securityContext:
  runAsNonRoot: true
  runAsUser: 1000
  fsGroup: 1000
  seccompProfile:
    type: RuntimeDefault
  capabilities:
    drop:
    - ALL
  • Secrets 管理:用外部 secret manager 替换 Kubernetes secrets:
yaml 复制代码
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: k8s-ai-secrets
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: vault-backend
    kind: SecretStore
  target:
    name: k8s-ai-secrets
  data:
  - secretKey: api-key
    remoteRef:
      key: k8s-ai/api-key
  • 审计日志(Audit logging) :启用全面日志:
python 复制代码
# In k8s-ai code
import logging

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)

# Log all authentication attempts
def authenticate(request):
    logger.info(f"Authentication attempt from {request.client.host}")
    # ... authentication logic
  • 限流(Rate limiting) :防止滥用:
yaml 复制代码
apiVersion: v1
kind: ConfigMap
metadata:
  name: k8s-ai-rate-limits
data:
  rate_limits.yaml: |
    limits:
      - key: ip
        rate: 100
        per: minute
      - key: api_key
        rate: 1000
        per: hour

这里的经验是:要维持一个紧凑且安全的生产环境并不简单,必须采用多种措施。

下面是一份上线前安全检查清单:

  • 所有通信均使用 TLS/SSL 加密
  • API keys 强随机、定期轮换
  • secrets 使用外部管理(Vault、AWS Secrets Manager 等)
  • RBAC 遵循最小权限
  • NetworkPolicies 限制不必要通信
  • Pod security context 强制非 root 运行
  • 审计日志记录所有访问尝试
  • 限流防止滥用
  • 镜像做漏洞扫描
  • 依赖更新并打好安全补丁
  • 出站(egress)过滤以降低外泄风险

KinD 部署演示的安全架构提供了坚实基础,但生产环境仍需要这些额外的加固措施。

总结(Summary)

在本章中,我们使用 KinD 在两个 Kubernetes 集群上部署了一个完整的多智能体系统,展示了分布式 AI 智能体架构的真实世界模式。我们首先通过正确的网络与端口映射建立双集群,然后把 MAKDO(含四个专用智能体与用于 memory、Slack 通信的 MCP servers)部署到控制集群。接着在工作集群中部署 k8s-ai 作为诊断智能体,配置了只读 RBAC 权限,同时暴露 A2A 协议 endpoint 与用于 session 管理的 Admin API。整个部署过程中,我们实现了多层安全:API key 认证、自动过期的 session 访问控制、以及通过受控端口暴露与服务边界实现的网络隔离。

我们构建的架构将编排与决策的控制智能体与具备直接集群访问能力的执行型工作智能体分离。通信通过基于 HTTP 的 JSON-RPC A2A 协议完成,并在 KinD 环境中通过 host.docker.internal 进行静态服务发现。我们演示了如何跨集群跟踪请求路径、测试认证与授权机制、验证 RBAC 权限以阻止未授权修改,以及通过 Kubernetes Secrets 与环境变量安全地管理 secrets。部署还展示了跨集群网络的实践路径:从适用于本地开发的 NodePort 方案,到生产环境可选的服务网格与动态服务注册表等更复杂方案。

虽然这个基于 KinD 的部署非常适合用来理解多智能体系统架构,但要迁移到生产仍需要额外考量:包括全链路 TLS 加密、更强的 API key 与轮换策略、外部 secrets 管理、完善的监控与日志、高可用配置以及自动化部署流水线。本章展示的模式与实践可以从本地开发扩展到跨云厂商、私有化和混合云的企业级生产系统。

在下一章(也是最后一章)中,我们将探讨多智能体 AI 系统的未来与即将塑造这些架构演进的新趋势。

相关推荐
DigitalOcean2 小时前
GPU对比:MI350X、MI325X、MI300X、H200、H100
llm·aigc
数据智能老司机3 小时前
使用 MCP 与 A2A 设计多智能体 AI 系统——与 Model Context Protocol(MCP)生态系统集成
llm·agent
数据智能老司机4 小时前
使用 MCP 与 A2A 设计多智能体 AI 系统——构建一个基于工具的智能体 AI 框架
llm·agent
TechFind4 小时前
用 OpenClaw 搭建企业微信 AI Agent:从零到自动化客服只需 30 分钟
人工智能·agent
数据智能老司机4 小时前
使用 MCP 与 A2A 设计多智能体 AI 系统——理解 AI 智能体如何工作
llm·agent
Baihai_IDP8 小时前
回头看 RLHF、PPO、DPO、GRPO 与 RLVR 的发展路径
人工智能·llm·强化学习
智泊AI8 小时前
一口气讲清:AI Agent 八大核心概念,建议收藏!
llm
Sailing8 小时前
LLM 调用从 60s 卡死降到 3s!彻底绕过 tiktoken 网络阻塞(LangChain.js 必看)
前端·langchain·llm
松灵机器人1 天前
【养个小龙虾】让小龙虾帮我控制七轴臂
agent