AKS集群中Calico网络策略IPBlock排除规则未生效问题咨询
我完全理解你的困扰:你在AKS 1.29.2集群(搭配Calico网络策略)里配置了一条出口规则,本意是允许Pod访问互联网,但阻断所有RFC1918私网网段的流量。可实际测试时,prodbindms Pod依然能连通同集群内属于RFC1918范围的Service IP;而一旦移除ipBlock规则,这个访问就会被拒绝——显然你的排除规则没按预期生效。
下面我帮你分析可能的原因,并给出对应的解决方案:
可能的原因分析
Calico对Service ClusterIP的特殊处理
当Pod访问Service的ClusterIP时,kube-proxy会通过iptables或eBPF把流量转发到后端Pod。Calico在匹配网络策略时,可能会用转发后的后端Pod IP而非原始ClusterIP来做规则校验。如果后端Pod IP确实在你排除的RFC1918网段里,但流量还是被允许了,大概率是Calico对ipBlock except规则的处理在这种场景下出了异常。Calico版本兼容性问题
AKS 1.29.2对应的Calico版本可能存在ipBlock except规则的bug,导致多网段排除逻辑失效。你可以通过这条命令查看Calico节点的镜像版本:kubectl get pods -n kube-system -l k8s-app=calico-node -o jsonpath='{.items[0].spec.containers[0].image}'规则匹配优先级的误解
Kubernetes网络策略的egress规则是逻辑或关系,只要有一条规则匹配就会允许流量。如果Calico错误地把ClusterIP流量判定为符合0.0.0.0/0的允许范围,且没触发except排除,就会导致流量被放行。
解决方案建议
1. 用Calico工具直接测试规则匹配
先通过calicoctl验证流量是否真的被规则允许,这能帮你快速定位问题:
# 替换成你的Pod名称和目标Service IP calicoctl network policy test -n production \ --src-pod=<prodbindms-pod-name> \ --dst-ip=172.20.217.17 \ --dst-port=8080 \ --protocol=tcp
如果结果显示Allowed,说明Calico确实认为该流量符合允许规则,需要调整策略写法;如果显示Denied,那可能存在其他隐含规则或流量路径绕过了你的策略。
2. 替换except写法,直接允许公网网段
避免使用0.0.0.0/0 except的写法,改为直接列出所有非RFC1918的公网CIDR。虽然写法繁琐,但能避开Calico对except规则的处理异常:
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: egress-allow namespace: production spec: egress: - ports: - port: 53 protocol: UDP to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: kube-system podSelector: matchLabels: k8s-app: kube-dns # 允许所有非RFC1918的公网网段 - to: - ipBlock: cidr: 0.0.0.0/5 - ipBlock: cidr: 8.0.0.0/7 - ipBlock: cidr: 11.0.0.0/8 - ipBlock: cidr: 12.0.0.0/6 - ipBlock: cidr: 16.0.0.0/4 - ipBlock: cidr: 32.0.0.0/3 - ipBlock: cidr: 64.0.0.0/2 - ipBlock: cidr: 128.0.0.0/3 - ipBlock: cidr: 160.0.0.0/5 - ipBlock: cidr: 168.0.0.0/6 - ipBlock: cidr: 172.32.0.0/11 - ipBlock: cidr: 176.0.0.0/12 - ipBlock: cidr: 192.0.0.0/10 - ipBlock: cidr: 192.169.0.0/16 - ipBlock: cidr: 192.170.0.0/15 - ipBlock: cidr: 192.172.0.0/14 - ipBlock: cidr: 192.176.0.0/12 - ipBlock: cidr: 192.192.0.0/10 - ipBlock: cidr: 193.0.0.0/8 - ipBlock: cidr: 194.0.0.0/8 - ipBlock: cidr: 195.0.0.0/8 - ipBlock: cidr: 196.0.0.0/8 - ipBlock: cidr: 197.0.0.0/8 - ipBlock: cidr: 198.0.0.0/9 - ipBlock: cidr: 198.128.0.0/11 - ipBlock: cidr: 198.160.0.0/13 - ipBlock: cidr: 198.168.0.0/14 - ipBlock: cidr: 198.172.0.0/15 - ipBlock: cidr: 198.174.0.0/16 - ipBlock: cidr: 198.175.0.0/16 - ipBlock: cidr: 199.0.0.0/8 - ipBlock: cidr: 200.0.0.0/7 - ipBlock: cidr: 208.0.0.0/4 podSelector: matchLabels: app.kubernetes.io/name: prodbindms policyTypes: - Egress
3. 用Calico原生策略添加明确拒绝规则
如果你要严格阻断所有RFC1918流量(包括集群内部),可以使用Calico专属的NetworkPolicy(projectcalico.org/v3版本),它支持更灵活的拒绝规则:
apiVersion: projectcalico.org/v3 kind: NetworkPolicy metadata: name: egress-deny-rfc1918 namespace: production spec: selector: app.kubernetes.io/name == 'prodbindms' types: - Egress egress: - action: Deny destination: nets: - 10.0.0.0/8 - 172.16.0.0/12 - 192.168.0.0/16 - action: Allow destination: ports: - port: 53 protocol: UDP selector: k8s-app == 'kube-dns' && kubernetes.io/metadata.name == 'kube-system' - action: Allow destination: nets: - 0.0.0.0/0 notNets: - 10.0.0.0/8 - 172.16.0.0/12 - 192.168.0.0/16
4. 查看Calico日志定位问题
通过Calico节点的日志,你可以看到流量具体匹配了哪条规则,帮助你精准排查:
# 替换成你的Calico节点Pod名称和prodbindms Pod的IP kubectl exec -n kube-system <calico-node-pod> -- grep "<prodbindms-pod-ip>" /var/log/calico/calico-node.log
日志里会清晰显示流量的匹配规则ID和结果,让你快速找到问题根源。
备注:内容来源于stack exchange,提问作者mrityunjay

