为 Agent 配置默认拒绝的网络,仅允许访问指定模型和工具 API,减少误访问内部服务及数据外传的风险。
本例创建一个 Cube Pod,只允许它向指定域名发送
/v1/ 下的 GET 请求,并验证其他方法和路径被拒绝。功能说明
ZeroProxy 根据 Pod 标签选择访问策略,默认拒绝未授权的业务请求,集群 DNS 单独放行。应用沿用原地址,无需设置
HTTP_PROXY。ZeroProxy 随集群默认安装。使用时,仍需配置命名空间标签和 Pod 注解;已有 Pod 需重建。
配置 | 作用 |
命名空间标签 zeroproxy.io/managed=true | 对该命名空间启用准入管理,未声明注入的新 Pod 会被拒绝 |
Pod 注解 zeroproxy.io/inject: "true" | 创建 Pod 时注入网络代理 |
Pod 标签与 ZeroProxyPolicy | 选择该任务可以访问的目标和接口 |
默认拒绝主要约束 Agent 主动发起的业务访问,Cube 负责沙箱运行环境隔离,ZeroProxy 负责本文的业务网络访问控制。
开始前准备
1. 已 创建 Agent 集群和节点池,Cube 节点就绪,使用 Linux amd64、Kubernetes 1.29 及以上,并启用原生 Sidecar。示例参考 Chart
0.4.7,其他版本需核对策略字段。2. 确认 ZeroProxy Controller 和 Webhook 就绪;两个 Webhook 副本需要至少两个可调度节点。
3. 准备独立测试命名空间和可查看日志的 HTTP 服务,先确认服务能正常响应
GET /v1/ping。4. 将示例域名
api.example.com、IPv4 地址 203.0.113.10/32 和端口替换为实际值。HTTP 测试不要携带敏感数据;HTTPS 配置见后文。5. 通过 访问配置 连接目标集群。需要管理测试命名空间、策略和 Pod,以及查看日志、执行容器命令的权限。
由管理员检查
platformDenyCIDRs,确认已包含需要禁止访问的内部网段。可以通过以下只读命令检查组件:
kubectl get crd zeroproxypolicies.zeroproxy.iokubectl get deployment -A -o custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,IMAGES:.spec.template.spec.containers[*].image'kubectl get runtimeclass cube
找到 ZeroProxy Controller 和 Webhook 的名称及命名空间,例如
kube-system。查不到时,检查集群连接和查询权限。将查询到的名称填入下面的命令。如果两个组件不在同一命名空间,分别查询。
export ZEROPROXY_NAMESPACE='<实际命名空间>'export ZEROPROXY_CONTROLLER='<Controller Deployment 名称>'export ZEROPROXY_WEBHOOK='<Webhook Deployment 名称>'kubectl -n "$ZEROPROXY_NAMESPACE" get deployment "$ZEROPROXY_CONTROLLER" "$ZEROPROXY_WEBHOOK"
开始测试前记录组件的实际镜像与策略字段:
kubectl -n "$ZEROPROXY_NAMESPACE" get deployment "$ZEROPROXY_CONTROLLER" "$ZEROPROXY_WEBHOOK" -o jsonkubectl explain zeroproxypolicy.spec --api-version=zeroproxy.io/v1alpha1
核对
configTOML、network.allowTCP,以及后文使用的 network.infrastructureTCP、caSecretRef。字段有差异时按组件版本调整;Chart 与镜像版本号不可直接比较。第一步:准备默认拒绝的命名空间
在目标集群控制台的 YAML 创建入口提交以下资源。控制台跳转至关联 TKE 集群时,先核对集群 ID。
apiVersion: v1kind: Namespacemetadata:name: agent-network-demolabels:zeroproxy.io/managed: "true"
先不创建访问策略,以验证默认拒绝。请使用新命名空间,避免影响现有业务:旧 Pod 不会自动注入代理,未声明注入的新 Pod 会被拒绝创建。
第二步:创建使用 Cube 和网络代理的 Pod
在控制台通过 YAML 创建以下 Pod。测试镜像需能从节点拉取;若使用私有镜像仓库,在该命名空间准备镜像拉取凭证并添加
imagePullSecrets。apiVersion: v1kind: Podmetadata:name: agent-network-demonamespace: agent-network-demolabels:app: agent-network-demotenant: demoannotations:zeroproxy.io/inject: "true"spec:runtimeClassName: cubeautomountServiceAccountToken: falsednsPolicy: ClusterFirstnodeSelector:kubernetes.io/arch: amd64securityContext:runAsNonRoot: truerunAsUser: 1000containers:- name: appimage: curlimages/curl:8.10.1command: ["sh", "-c", "sleep 3600"]securityContext:allowPrivilegeEscalation: falsecapabilities:drop: ["ALL"]resources:requests:cpu: 10mmemory: 32Milimits:cpu: 100mmemory: 64Mi
接入自己的 Agent 时,替换镜像、命令和资源规格。使用 Deployment 时,标签和注解放在
spec.template.metadata,运行时与安全配置放在 spec.template.spec。在
initContainers 中确认代理 zeroproxy-sidecar 的 restartPolicy 为 Always:kubectl -n agent-network-demo get pod agent-network-demo -o yamlkubectl -n agent-network-demo exec agent-network-demo -c zeroproxy-sidecar -- zeroproxy-sidecar status
确认代理
ready=true、error=null,且 desiredRevision 与 loadedRevision 一致。Pod 就绪不代表目标已放行。先从业务容器访问已确认可用的测试目标:
kubectl -n agent-network-demo exec agent-network-demo -c app -- \\curl -i --connect-timeout 5 --max-time 10 http://api.example.com/v1/ping
预期请求被拒绝。保留响应、代理和目标日志,供放行后对比;连接失败本身不能证明策略生效。
第三步:只放行需要的接口
在控制台的自定义资源 YAML 创建入口提交以下 ZeroProxyPolicy,将域名和 IP 替换为准备好的实际值:
apiVersion: zeroproxy.io/v1alpha1kind: ZeroProxyPolicymetadata:name: allow-agent-toolnamespace: agent-network-demospec:podSelector:matchLabels:app: agent-network-demotenant: democonfigTOML: |[[policies.sources]]source = "inline"default_decision = "deny"[[policies.sources.rules]]name = "allow-tool-read"priority = 100decision = "allow"resources = [{ hosts = ["api.example.com"], ports = [80], path_prefix = "/v1/" }]methods = ["GET"]network:allowTCP:- cidr: 203.0.113.10/32ports: [80]
allowTCP 放行目标 IP 和端口,configTOML 限定域名、GET 方法及 /v1/ 路径前缀,必须同时满足。目标位于平台禁止的内部网段时,由管理员确认后,在
spec.network 下增加与 allowTCP 同级的 infrastructureTCP。只填写受信目标的单个 IPv4 地址和端口,不放行整个网段。infrastructureTCP:- cidr: REPLACE_WITH_TRUSTED_SERVICE_IPV4/32ports: [8080]
域名、方法和路径限制仍生效。普通公网目标无需此项。
域名对应多个 IPv4 地址时逐项配置,地址变化后更新
allowTCP;当前不会自动更新 IP 白名单。策略与 Pod 放在同一命名空间,标签须全部匹配。每个 Pod 仅匹配一份策略;无匹配或匹配多份都会关闭业务出口。
访问集群内的 Service
访问集群内 Service 时,除 ZeroProxy 规则外,还要检查 NetworkPolicy。前者控制域名、方法和路径,后者控制 Pod 之间的连接,两者独立生效。
先检查两端策略、Service 后端和代理日志:
kubectl -n agent-network-demo get networkpolicykubectl -n '<目标服务命名空间>' get networkpolicykubectl -n '<目标服务命名空间>' get service '<Service 名称>' -o yamlkubectl -n '<目标服务命名空间>' get pods --show-labelskubectl -n '<目标服务命名空间>' get endpointslices \\-l kubernetes.io/service-name='<Service 名称>' -o widekubectl -n agent-network-demo logs agent-network-demo -c zeroproxy-sidecar --tail=100
以下示例访问
agent-tools 中标签为 app: tool-api、监听 TCP 8080 的后端。请按实际服务替换命名空间、标签和端口,并核对 Service 选择器及 ZeroProxy 的目标配置。客户端受出站隔离时,添加以下授权:
apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata:name: allow-agent-tool-egressnamespace: agent-network-demospec:podSelector:matchLabels:app: agent-network-demotenant: demopolicyTypes: [Egress]egress:- to:- namespaceSelector:matchLabels:kubernetes.io/metadata.name: agent-toolspodSelector:matchLabels:app: tool-apiports:- protocol: TCPport: 8080
两个选择器须放在同一项中,限定目标命名空间及 Pod 标签。后端重建后,只要标签和端口不变,无需修改规则。
添加 Egress 策略会隔离选中 Pod 的出站流量。保留业务所需授权,尤其是 DNS;ZeroProxy 的 DNS 放行不能替代 NetworkPolicy 授权。
下面的 DNS 规则适用于
kube-system 中标签为 k8s-app: kube-dns 的 CoreDNS。先用 kubectl -n kube-system get pods -l k8s-app=kube-dns --show-labels 确认。使用 NodeLocal DNS 或其他部署方式时,由管理员按实际流量路径配置。apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata:name: allow-agent-dnsnamespace: agent-network-demospec:podSelector:matchLabels:app: agent-network-demotenant: demopolicyTypes: [Egress]egress:- to:- namespaceSelector:matchLabels:kubernetes.io/metadata.name: kube-systempodSelector:matchLabels:k8s-app: kube-dnsports:- protocol: UDPport: 53- protocol: TCPport: 53
如果服务端也受入站隔离,在
agent-tools 命名空间添加对应的入站规则:apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata:name: allow-agent-tool-ingressnamespace: agent-toolsspec:podSelector:matchLabels:app: tool-apipolicyTypes: [Ingress]ingress:- from:- namespaceSelector:matchLabels:kubernetes.io/metadata.name: agent-network-demopodSelector:matchLabels:app: agent-network-demotenant: demoports:- protocol: TCPport: 8080
服务端没有入站隔离时,无需添加此规则,以免影响其他调用方。NetworkPolicy 的允许规则会叠加,不会撤销已有权限或覆盖其他平台安全策略;由管理员确认后提交。更多说明见 Kubernetes NetworkPolicy。
配置完成后,按第四步验证允许、拒绝和撤销后的请求。连接失败时,按文末“常见问题”排查。
第四步:验证允许和拒绝都生效
策略保存后,等待代理加载对应版本:
kubectl -n agent-network-demo get pod agent-network-demo \\-o jsonpath='{.metadata.annotations.zeroproxy\\.io/desired-revision}{"\\n"}'kubectl -n agent-network-demo exec agent-network-demo -c zeroproxy-sidecar -- zeroproxy-sidecar status
等待
loadedRevision 与 Pod 注解版本一致,且 ready=true、error=null,再发起请求。# 允许:指定域名、GET 方法和 /v1/ 路径kubectl -n agent-network-demo exec agent-network-demo -c app -- \\curl -i --connect-timeout 5 --max-time 10 http://api.example.com/v1/ping# 拒绝:方法不匹配kubectl -n agent-network-demo exec agent-network-demo -c app -- \\curl -i --connect-timeout 5 --max-time 10 -X POST http://api.example.com/v1/ping# 拒绝:路径不匹配kubectl -n agent-network-demo exec agent-network-demo -c app -- \\curl -i --connect-timeout 5 --max-time 10 http://api.example.com/admin/
检查项 | 预期结果 | 核对方式 |
放行前访问测试目标 | 被拒绝 | 代理处于默认拒绝状态,目标服务未收到请求 |
放行后 GET /v1/ping | 收到目标应用的正常响应 | 核对状态码、响应内容和服务端访问日志 |
POST /v1/ping | 代理返回 HTTP 403 | 目标服务未收到该请求 |
GET /admin/ | 代理返回 HTTP 403 | 目标服务未收到该请求 |
检查 HTTP 状态码,不能只看 curl 退出码。超时、DNS 错误或 502 按文末方法排查;403 需结合代理拒绝原因及目标日志确认。
接入真实 Agent
模型、知识库等 HTTPS 服务:仅把端口改为 443 不够。代理检查加密请求时需要管理员配置签发证书使用的 CA,并在策略中设置
caSecretRef。业务容器需要信任代理 CA;不得使用 --insecure 绕过验证。证书固定或独立 truststore 的客户端需单独适配。模型接口使用 POST:按真实接口配置方法和路径,例如模型服务所需的 POST 路径;不要直接照搬本例的只读 GET 策略。请求体条件不在当前支持范围内。
多租户任务:不同租户使用独立命名空间及相应的 Kubernetes 权限。标签用于选择策略,不能代替租户权限隔离。策略、标签绑定和业务凭证由管理员管理。
已有 Agent:修改工作负载模板后滚动重建,逐个确认代理已注入并加载策略。仅修改命名空间标签不会接管已有 Pod。
HTTPS 接入时,由管理员在业务命名空间创建含
ca.pem、ca-key.pem 的专用 Secret,并将其名称填入策略的 spec.caSecretRef;请求规则和 allowTCP 都需包含 443 端口。组件将公共 CA 放到业务容器的 /etc/zeroproxy-trust/ca.pem,并注入 SSL_CERT_FILE、REQUESTS_CA_BUNDLE、NODE_EXTRA_CA_CERTS。CA 私钥仅供代理使用,业务容器不得挂载该 Secret。使用 curl 验证时添加 --cacert /etc/zeroproxy-trust/ca.pem,并重复允许与拒绝两类请求检查。
一次实测结果
使用 ZeroProxy
0.4.10、Cube 客户端和独立 HTTP Service 验证,服务监听 TCP 8080。配置或操作 | 实测结果 |
未配置代理允许规则 | GET 返回 403,代理记录默认拒绝 |
代理允许,但服务端入站未授权 | GET 返回 502 |
补齐后端连接和 DNS 授权 | GET /v1/ping 返回 200,POST 和 /admin/ 返回 403 |
后端 Pod 重建、IP 改变 | 保留标签和端口,未修改规则,GET 仍返回 200 |
撤销代理允许规则 | GET 恢复为 403 |
每次变更均确认代理加载版本一致后再发起请求。漏配 DNS 时,代理记录过上游域名解析失败;客户端的
curl --resolve 不能代替代理的 DNS 授权。本次验证覆盖 HTTP 与标签选择器,未覆盖 HTTPS、其他网络插件和所有 DNS 部署。测试资源已清理,原有集群策略保留。