如何配置Egress NetworkPolicy允许K8s API访问?解决Init容器超时故障
我之前处理过不少Calico NetworkPolicy相关的配置坑,你的情况核心是Init容器的出站流量被Policy阻断了,咱们一步步来排查修复:
先理清核心问题
你用Init容器执行kubectl get pod检查其他Pod的就绪状态,本质是Init容器需要访问Kubernetes API Server。启用Egress Policy后出现dial tcp 10.96.0.1:443: i/o timeout,说明你的Policy规则没覆盖Init容器到API Server的所有必要流量路径,或者Calico有一些容易忽略的配置细节没考虑到。
分步解决方法
1. 先确认API Server的实际可达地址
别默认只盯着ClusterIP(10.96.0.1),先在集群节点上跑一下:
kubectl cluster-info
看看输出里的Kubernetes master地址,比如可能是https://<你的节点IP>:6443。如果Init容器是通过节点IP访问API Server的,那你的Egress规则得同时放行这个地址的端口。
2. 修正Egress NetworkPolicy规则
Calico对ipBlock的处理有几个需要注意的点,比如是否包含Pod所在节点的IP,还有是否需要放行DNS流量(如果Init容器用域名访问API的话)。给你两个可靠的配置方案:
方案A:直接放行API Server的ClusterIP和节点网段
适合你明确知道API Server地址的情况:
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-init-api-access namespace: 你的命名空间 # 替换成Init容器所在的命名空间 spec: podSelector: matchLabels: app: 你的应用标签 # 匹配Init容器所在Pod的标签 policyTypes: - Egress egress: # 放行到K8s API ClusterIP的443端口 - to: - ipBlock: cidr: 10.96.0.1/32 ports: - protocol: TCP port: 443 # 放行到所有节点IP的6443端口(API Server通常也监听这个端口) - to: - ipBlock: cidr: 你的节点网段/24 # 比如192.168.0.0/24,替换成你集群的节点网段 ports: - protocol: TCP port: 6443 # 必须加:如果Init容器用kubernetes.default.svc域名访问API,得放行DNS流量 - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: kube-system podSelector: matchLabels: k8s-app: kube-dns ports: - protocol: UDP port: 53 - protocol: TCP port: 53
方案B:通过命名空间+Pod标签放行(更灵活)
如果你的API Server运行在kube-system命名空间,直接匹配它的Pod标签会更可靠,不用硬写IP:
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-init-api-access namespace: 你的命名空间 spec: podSelector: matchLabels: app: 你的应用标签 policyTypes: - Egress egress: # 放行到kube-system里的API Server Pod - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: kube-system podSelector: matchLabels: component: kube-apiserver ports: - protocol: TCP port: 443 - protocol: TCP port: 6443 # 同样,放行DNS流量 - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: kube-system podSelector: matchLabels: k8s-app: kube-dns ports: - protocol: UDP port: 53 - protocol: TCP port: 53
3. 用Calico工具验证规则是否生效
光配置还不够,得确认规则真的生效了。先查看你的Policy是否正确应用:
calicoctl get networkpolicy -n 你的命名空间
如果还是有问题,用calicoctl trace追踪流量,看看是哪个环节被阻断:
calicoctl trace pod <你的Init容器Pod名称> -n 你的命名空间 --to 10.96.0.1:443
这个命令会输出流量的完整路径,告诉你是哪个规则把流量拦住了,非常有用。
4. 检查Init容器的kubectl配置
最后确认一下Init容器里的kubectl用的是正确的API地址,默认的kubeconfig会指向kubernetes.default.svc,这个域名需要DNS解析,所以如果你的规则没放行DNS,也会出现超时错误——这也是很多人容易忽略的点。
额外提醒
如果你的集群设置了Calico NetworkPolicy的默认拒绝,一定要确保你的Policy是明确允许Init容器的必要出站流量,别只加规则却没覆盖默认拒绝的情况。
内容的提问来源于stack exchange,提问作者Igor Stepin

