使用 Core Profile 快速开始
本指南将带你完成 Kagenti Operator 的 core profile 上最小可行的端到端部署——这是默认的安装形态,支持 agent enrollment 和动态发现,但不包含 identity sidecar、Keycloak 或 mesh mTLS。它是验证 operator 安装是否成功、并在逐步叠加 secure profile 之前熟悉 AgentRuntime 自定义资源的最快方式。
该场景是一个 weather agent:它通过调用用于获取实时数据的 weather MCP tool 和一个大语言模型来生成回复,回答类似 “What is the weather in New York?” 这样的问题。请求流程如下:
client ──A2A message/send──▶ weather-agent ──OpenAI chat API──▶ InferenceService (qwen36-27b-gguf)
│
└──────────MCP──────────▶ weather-tool-mcp
在 core profile 下,没有认证或传输安全——下面的每一步都只是集群内的普通 HTTP 调用。关于安全版本(Bearer-token 请求、SPIRE mTLS、每个 agent 一个 AuthBridge sidecar),请在完成本指南后继续阅读 使用 Secure Profile 演示。
前提条件
-
已安装 Kagenti Operator,且其 Kagenti operand 已完成 reconciliation——请参见 安装。
-
具备目标集群的 kubectl 访问权限。
-
一个演示命名空间。本指南使用 team1:
kubectl create namespace team1
-
一个提供 OpenAI 兼容 chat API 的 InferenceService,且可在集群内访问。本指南使用名为 qwen36-27b-gguf 的 InferenceService。任何 chat 模型都可以;如果模型支持 tool calling,agent 效果会更好。
找到你的模型 endpoint 和名称
agent 通过三个环境变量连接模型——LLM_API_BASE、LLM_API_KEY 和 LLM_MODEL。请从你的 InferenceService 中解析它们:
# The predictor Service exposes the OpenAI-compatible API in-cluster.
# Base URL pattern: http://<isvc-name>-predictor.<namespace>.svc.cluster.local/v1
kubectl get svc -n <model-namespace> | grep <isvc-name>-predictor
# The model id to send as "model" — list what the endpoint serves:
kubectl run modelq --rm -i --restart=Never -n <model-namespace> \
--image=docker.io/alaudadockerhub/curl:8.1.2 --command -- \
curl -sS http://<isvc-name>-predictor.<model-namespace>.svc.cluster.local/v1/models
对于部署在 models 命名空间中的 qwen36-27b-gguf InferenceService,解析结果如下:
INFO
在本指南的其余部分,请将示例中的 InferenceService 名称、命名空间和 model id 替换为你自己的值。如果模型是 reasoning 模型,响应的前几个 token 会是 reasoning 内容——请像下面这样保持 agent 的 token budget 不受限制,以免最终答案被截断。
MCP(Model Context Protocol)server 提供 agent 要调用的 get_weather tool。请部署它并通过 Service 暴露出来。在 core profile 下,tool 以普通 Deployment 方式运行(单容器、无 sidecar);在 secure profile 下也会继续沿用相同布局,因为 operand 默认值为 spec.featureGates.injectTools: false。
kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: weather-tool
namespace: team1
labels:
app.kubernetes.io/name: weather-tool
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: weather-tool
template:
metadata:
labels:
app.kubernetes.io/name: weather-tool
spec:
containers:
- name: mcp
image: docker.io/alaudadockerhub/weather_tool:v0.1.0-rc.1
imagePullPolicy: IfNotPresent
env:
- name: PORT
value: "8000"
- name: HOST
value: 0.0.0.0
- name: UV_CACHE_DIR
value: /app/.cache/uv
ports:
- containerPort: 8000
volumeMounts:
- mountPath: /app/.cache
name: cache
volumes:
- name: cache
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: weather-tool-mcp
namespace: team1
spec:
selector:
app.kubernetes.io/name: weather-tool
ports:
- name: http
port: 8000
targetPort: 8000
EOF
- MCP server 镜像已镜像到
docker.io/alaudadockerhub。在离线集群中,请使用重新分发到你平台 registry 中的副本。
- 该 Service 供 agent 访问,地址为
http://weather-tool-mcp.team1.svc.cluster.local:8000/mcp。operator 不会 自动为你创建这个 Service,因此需要你显式定义它,并选择 tool 的 pod。
等待 tool 就绪:
kubectl rollout status deploy/weather-tool -n team1
kubectl get pod -n team1 -l app.kubernetes.io/name=weather-tool
# NAME READY STATUS RESTARTS AGE
# weather-tool-XXXXXXXXXX-YYYYY 1/1 Running 0 1m
READY 1/1 表示该 tool 正在以单容器方式运行。
步骤 2:部署 agent
agent 只需要在其 Deployment 上添加一个 protocol.kagenti.io/a2a 标签——controller 会应用 kagenti.io/type,计算 config hash,并在启用 identity stack 时触发 sidecar 注入。protocol 标签还会告诉 AgentCard sync controller 该 agent 使用哪种 protocol,从而启用自动发现。
kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: weather-agent
namespace: team1
labels:
app.kubernetes.io/name: weather-agent
protocol.kagenti.io/a2a: ""
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: weather-agent
template:
metadata:
labels:
app.kubernetes.io/name: weather-agent
spec:
containers:
- name: agent
image: docker.io/alaudadockerhub/weather_service:v0.1.0-rc.1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8000
env:
- name: PORT
value: "8000"
- name: UV_CACHE_DIR
value: /app/.cache/uv
- name: MCP_URL
value: http://weather-tool-mcp.team1.svc.cluster.local:8000/mcp
- name: LLM_API_BASE
value: http://qwen36-27b-gguf-predictor.models.svc.cluster.local/v1
- name: LLM_API_KEY
value: dummy
- name: LLM_MODEL
value: qwen36-27b-gguf
---
apiVersion: v1
kind: Service
metadata:
name: weather-agent
namespace: team1
spec:
selector:
app.kubernetes.io/name: weather-agent
ports:
- name: http
port: 8000
targetPort: 8000
---
apiVersion: agent.kagenti.dev/v1alpha1
kind: AgentRuntime
metadata:
name: weather-agent-runtime
namespace: team1
spec:
type: agent
targetRef:
apiVersion: apps/v1
kind: Deployment
name: weather-agent
EOF
protocol.kagenti.io/a2a: "" 将该 Deployment 标记为 A2A agent。它会启用 AgentCard 的自动创建;ValidatingAdmissionPolicy 会禁止直接设置 kagenti.io/type,因此 enrollment 必须通过 AgentRuntime 进行。
- agent 镜像已镜像到
docker.io/alaudadockerhub。请使用 v0.1.0 或更高版本——这些版本会从环境变量中读取 HOST/PORT,这在 secure profile 下是必需的(AuthBridge sidecar 会重映射应用端口)。
MCP_URL —— 步骤 1 中的 MCP tool endpoint(Service 名称加上 /mcp 路径)。
LLM_API_BASE —— 你的 InferenceService predictor 的 OpenAI 兼容 base URL(.../v1)。
LLM_MODEL —— 由 InferenceService 提供的 model id。
agent 的 Service 以 Deployment 名称命名(weather-agent);AgentRuntime controller 会解析它,以便获取用于发现的 Agent Card。
创建 AgentRuntime 后,controller 将执行以下操作:
- 解析
targetRef 并验证 Deployment 是否存在。
- 应用
kagenti.io/type: agent 和 app.kubernetes.io/managed-by: kagenti-operator 标签。
- 计算 config hash,并将其作为
kagenti.io/config-hash 注解设置到 pod template 上,从而触发 rolling update。
步骤 3:检查状态
# AgentRuntime status — only the agent has one in this pattern
kubectl get agentruntime -n team1
# NAME TYPE TARGET READY AGE
# weather-agent-runtime agent weather-agent True 1m
# Conditions (core profile: MTLSReady is False with reason SPIREUnavailable — expected)
kubectl get agentruntime weather-agent-runtime -n team1 \
-o jsonpath='{range .status.conditions[*]}{.type}={.status}{"\n"}{end}'
# TargetResolved=True
# IstioMeshEnrolled=True
# MTLSReady=False
# ConfigResolved=True
# Ready=True
# Labels applied by the operator
kubectl get deployment weather-agent -n team1 --show-labels
# Pods: agent 1/1, tool 1/1 — no sidecars in the core profile
kubectl get pods -n team1
# NAME READY STATUS RESTARTS AGE
# weather-agent-XXXXXXXXX-YYYYY 1/1 Running 0 1m
# weather-tool-XXXXXXXXX-YYYYY 1/1 Running 0 6m
# The AgentCard is created and synced automatically
kubectl get agentcards -n team1
# NAME PROTOCOL KIND TARGET AGENT SYNCED AGE
# weather-agent-deployment-card a2a Deployment weather-agent Weather Assistant True 1m
SYNCED=True 且 AGENT 列已填充(此处为 Weather Assistant)表示 sync controller 已获取到该 agent 的 A2A card——动态发现已正常工作。
步骤 4:发送查询(端到端测试)
从一个临时的集群内 pod 向 agent 发送 A2A message/send 请求,使用 agent 的内部 Service DNS 名称:
kubectl run curl-wq --rm -i --restart=Never -n team1 \
--image=docker.io/alaudadockerhub/curl:8.1.2 --command -- \
curl -sS -X POST http://weather-agent.team1.svc.cluster.local:8000/ \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":"76CD6BA3-16AA-4CED-8E0E-19156B8C5886","method":"message/send","params":{"message":{"role":"user","parts":[{"kind":"text","text":"What is the weather in NY?"}],"messageId":"DF05857B-98B7-4414-BD63-19E16E684E39"}}}'
agent 会调用模型,模型再调用 weather MCP tool,最终 agent 返回一个已完成的 A2A task:
{
"id": "76CD6BA3-16AA-4CED-8E0E-19156B8C5886",
"jsonrpc": "2.0",
"result": {
"artifacts": [
{
"parts": [
{
"kind": "text",
"text": "The current weather in New York is 66.4°F with clear skies. The wind speed is 4.4."
}
]
}
],
"kind": "task",
"status": { "state": "completed" }
}
}
完整响应中的 history 数组展示了 tool-calling 流程(assistant → tools → assistant),其中包含由 weather MCP server 返回的 ToolMessage。
INFO
reasoning 模型会先用前几个 token “思考”,再给出最终答案,因此第一次请求可能会明显慢于非 reasoning 模型。后续请求会更快。
你可以在日志中观察交互过程:
# Agent logs
kubectl logs -f -l app.kubernetes.io/name=weather-agent -n team1
# MCP tool logs (in another terminal)
kubectl logs -f -l app.kubernetes.io/name=weather-tool -n team1
更新和删除 AgentRuntime
平台配置变更(集群级或命名空间级 ConfigMap)会触发 rolling update,以便 pod 获取新设置。直接编辑 AgentRuntime 的 spec 本身不会强制重启——新值只会在创建 pod 时生效。
删除 AgentRuntime 会执行优雅清理:controller 会移除 kagenti.io/type 标签和 kagenti.io/config-hash 注解(从而触发 rolling update,使任何已注入的 pod 被替换),并移除 app.kubernetes.io/managed-by 标签。
kubectl delete agentruntime weather-agent-runtime -n team1
清理
kubectl delete namespace team1
下一步
你刚刚体验的 core profile 不包含认证或传输安全。要逐步加入这些能力:
- 安装 Secure-Profile Dependencies — SPIRE、Keycloak、Istio ambient。
- 启用 Secure Profile — 切换 operand feature gate。
- 使用 Secure Profile 演示 — 用同样的 weather 场景重新演示,在 agent 上加上 AuthBridge sidecar、每个 workload 一个 SPIRE SVID,以及 Bearer-token 认证请求。
- 高级演示:在 tool 上使用 AuthBridge 和 Token Exchange — 也为 tool 添加 AuthBridge,在 agent 和 tool 之间使用 RFC 8693 token exchange。
故障排查