未开启Istio注入的MySQL客户端无法连接K8s中带Istio注入的MySQL Pod
该问题核心由Istio默认启用的双向TLS(mTLS)认证策略导致:当目标MySQL Pod注入Istio sidecar后,Istio默认要求所有访问该Pod的流量必须携带Istio签发的证书完成双向身份校验,未注入sidecar的MySQL客户端Job没有对应证书,无法完成TLS握手,因此连接被拒绝。
方案1:调整目标MySQL服务的mTLS模式为PERMISSIVE(推荐,改动最小)
PERMISSIVE模式下,MySQL服务端同时支持带mTLS认证的加密流量和不带认证的明文流量,无需修改Job配置,也不会影响其他带Istio sidecar的客户端正常访问。
在MySQL所在命名空间下创建如下PeerAuthentication资源即可:apiVersion: security.istio.io/v1beta1 kind: PeerAuthentication metadata: name: mysql-mtls-permissive namespace: <替换为MySQL所在的命名空间> spec: selector: matchLabels: app.kubernetes.io/name: mysql # 替换为你的MySQL Pod的实际匹配标签 mtls: mode: PERMISSIVE配置提交后等待1-2分钟生效,即可正常连接。
方案2:为Job配置Istio sidecar优雅退出(符合Istio安全最佳实践)
之前不为Job开启Istio注入的核心诉求是避免sidecar常驻导致Job无法正常终止,可通过主动触发sidecar退出的逻辑解决该问题,同时保留严格mTLS的安全能力:
- 移除Job的
istio-injection: false标签,开启sidecar注入 - 在Job的业务逻辑末尾调用Istio sidecar的本地退出接口,示例配置如下:
apiVersion: batch/v1 kind: Job metadata: name: mysql-client-job namespace: <替换为Job所在命名空间> spec: template: metadata: annotations: sidecar.istio.io/inject: "true" # 可选:确保sidecar启动完成后再运行业务逻辑 proxy.istio.io/config: '{ "holdApplicationUntilProxyStarts": true }' spec: containers: - name: mysql-client image: mysql:5.7 command: ["/bin/sh", "-c"] args: - | # 你的实际MySQL执行逻辑 mysql -h mysql.<MySQL命名空间>.svc.cluster.local -uroot -p${MYSQL_ROOT_PASSWORD} -e "show databases;" # 业务逻辑执行完成后,调用sidecar退出接口 curl -X POST http://localhost:15020/quitquitquit restartPolicy: Never backoffLimit: 2若MySQL客户端镜像没有内置curl,可替换为wget命令,或在镜像中预先安装curl工具。
- 移除Job的
方案3:跳过MySQL端口的Istio流量拦截(仅建议临时调试使用)
为MySQL Pod的sidecar添加入站端口排除注解,让3306端口的流量直接透传到MySQL容器,不经过Istio的mTLS校验:
在MySQL Deployment的Pod模板annotations中添加如下配置:traffic.sidecar.istio.io/excludeInboundPorts: "3306"该方案会让MySQL端口失去Istio的流量治理、加密、监控能力,不推荐生产环境长期使用。
优先选择方案1,对现有业务侵入最小,同时保留Istio对其他服务的治理能力;如果对内部通信安全要求较高,需要保持严格mTLS模式,选择方案2,符合Istio官方最佳实践。
内容的提问来源于stack exchange,提问作者Phil Chae

