Go 通过 client-go 操作 NetworkPolicy 对象而非底层规则,需构造 networkingv1.NetworkPolicy 结构体并调用 Create(),注意 PodSelector 非空、PolicyTypes 显式指定、RBAC 权限完备及策略叠加逻辑。

Go 不能直接操作 NetworkPolicy 的底层规则,只能通过 client-go 提交、更新或删除 Kubernetes API 中的 NetworkPolicy 对象;真正生效靠 CNI 插件(如 Calico/Cilium/Terway),不是 Go 程序自己写 iptables 或 eBPF。
用 client-go 创建 NetworkPolicy 对象
核心是构造 networkingv1.NetworkPolicy 结构体并调用 clientset.NetworkingV1().NetworkPolicies(namespace).Create()。不要手动拼 YAML 字符串或解析 JSON——client-go 提供类型安全的对象构造方式。
- 必须使用
scheme.Scheme获取apiVersion,而不是硬编码"networking.k8s.io/v1",否则在旧集群(如 v1beta1)会失败 -
PodSelector不能为空,若想匹配命名空间内所有 Pod,用空metav1.LabelSelector{} -
PolicyTypes必须显式指定"Ingress"或"Egress",否则默认只启用 Ingress,Egress 规则会被忽略 - 跨命名空间引用(如
namespaceSelector)必须确保目标命名空间有对应标签,且策略本身定义在被保护 Pod 所在的命名空间中
RBAC 权限配置容易漏掉的点
Go 程序运行时使用的 ServiceAccount 必须有对应权限,否则 Create() 会返回 403 Forbidden 错误,常见于本地调试时用 kubectl proxy 或 kubeconfig 直连但没配 RBAC。
- 最小权限是
networkpolicies/{create,update,patch,delete},作用域为具体命名空间或集群范围 - 如果策略要引用其他命名空间的 Pod(如用
namespaceSelector),还需namespaces/get权限,否则from规则校验失败 - 用
kubectl auth can-i --list检查当前用户/SA 是否具备权限,比看文档更快定位问题
避免用 Go 解析或生成 YAML
很多初学者习惯把 YAML 写死在代码里,再用 yaml.Unmarshal() 转成结构体,这既脆弱又难调试。client-go 原生支持对象构造,更可靠。
立即学习“go语言免费学习笔记(深入)”;
- YAML 中字段名大小写、缩进、空格错误会导致
Unmarshal失败,而结构体赋值编译期就能发现 typo - 动态构建策略(如根据传入 label 动态设置
podSelector)用结构体更自然,不用字符串拼接 - 若必须从文件加载,用
runtime.DefaultUnstructuredConverter+unstructured.Unstructured,而非直转 struct,避免版本不兼容
策略叠加和默认行为的实际影响
多个 NetworkPolicy 可同时作用于同一组 Pod,它们之间是“允许并集”,不是“拒绝优先”。这点在 Go 控制器自动管理策略时特别关键——重复创建策略不会报错,但可能意外放行流量。
- 控制器每次更新策略应使用
Patch()或先Get()再Update(),避免因并发写入导致策略残留 - 没有显式定义
Egress规则时,policyTypes不含Egress,出站流量不受限制——这不是 bug,是设计如此 - 集群是否启用默认拒绝(default-deny)由 CNI 插件决定,Go 程序无法控制;它只负责提交你声明的策略
真正难的不是写 Go 代码,而是理解 NetworkPolicy 是声明式资源:你提交的是“期望状态”,生效依赖 CNI 插件实时同步、节点上 Felix 或 Cilium-agent 正确注入规则、内核模块(如 eBPF)就绪。任何一环断开,Create() 成功了,策略也不起作用。


















