Kubernetes NetworkPolicy 无法与 MySQL 配合使用问题排查求助
看起来你遇到的是NetworkPolicy规则生效异常的问题,我帮你梳理下核心原因和对应的解决办法:
核心问题排查
你配置的NetworkPolicy本意是允许带access=true标签的Pod访问MySQL,但应用后连不上,主要有几个关键点:
1. NodePort访问的SNAT坑
你用NodePort(172.23.0.11:30619)访问的时候,因为你的Service设置了externalTrafficPolicy: Cluster,Kubernetes会自动做SNAT——把客户端Pod的源IP换成Node的IP。这时候NetworkPolicy里的from.podSelector是匹配Pod标签的,但实际流量的源是Node的IP,根本匹配不上Pod标签规则,自然被拒绝了。
2. NetworkPolicy未明确指定端口
虽然Kubernetes允许不写ports(默认允许所有端口),但Canal这类CNI插件有时候对模糊规则的处理会有歧义,尤其当Pod只有一个端口的时候,明确指定端口能让规则更精准。
3. 测试Pod的标签是否真的正确?
别小看这个,有时候创建Pod时的标签参数可能因为格式问题没生效,得确认下测试Pod确实带了access=true标签。
一步步解决
第一步:改用ClusterIP/Service名访问(最直接)
集群内部的Pod访问Service,直接用Service名称example或者ClusterIP就行,这时候流量不会经过SNAT,源IP就是客户端Pod的IP,NetworkPolicy的标签规则能正常匹配。
把连接命令改成:
mysql -h example -P 3306 -u root -p -v
第二步:更新NetworkPolicy,明确端口
修改你的NetworkPolicy,加上允许的3306端口,同时明确指定namespace(避免跨namespace的歧义):
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: access-mysql namespace: default spec: podSelector: matchLabels: restrict: me ingress: - from: - podSelector: matchLabels: access: "true" ports: - protocol: TCP port: 3306
应用这个更新后的规则:
kubectl apply -f network-policy.yaml
第三步:确认测试Pod的标签
执行这条命令看看测试Pod的标签:
kubectl get pods clientms --show-labels
输出里必须有access=true,如果没有,重新创建测试Pod:
kubectl run clientms --rm -ti --labels="access=true" --image=mysql -- /bin/sh
第四步:检查Canal的NetworkPolicy支持(兜底排查)
如果前面都没用,得确认Canal有没有开启NetworkPolicy支持:
查看Canal的DaemonSet配置:
kubectl get daemonset canal -n kube-system -o yaml
找一下启动参数里有没有--enable-policy=true,Canal默认是开的,但如果被改过可能关了。要是没有,就更新DaemonSet加上这个参数,然后重启Canal Pod。
验证规则是否生效
改完之后,先在带标签的测试Pod里连MySQL,确认能连上。然后再创建一个不带access=true标签的Pod试试:
kubectl run clientms-deny --rm -ti --image=mysql -- /bin/sh # 执行连接命令,应该连不上,说明规则生效了 mysql -h example -P 3306 -u root -p -v
内容的提问来源于stack exchange,提问作者neonlyis

