Kubernetes部署的Spring Boot应用无法连接外部AWS RDS MySQL
问题描述
将Spring Boot应用部署到Kubernetes集群后,无法连接AWS RDS上的外部MySQL,使用了ExternalName Service进行配置,相关配置、错误日志及Service信息如下:
配置文件
MySQL ExternalName Service(mysql.yml)
apiVersion: v1 kind: Service metadata: name: mysql spec: type: ExternalName externalName: mysql.ap-northeast-2.rds.amazonaws.com ports: - port: 3306
应用部署配置(app-dev.yml)
apiVersion: v1 kind: Service metadata: name: app-dev spec: type: NodePort ports: - nodePort: 30000 port: 80 protocol: TCP targetPort: 8080 selector: app: app-dev --- apiVersion: apps/v1 kind: Deployment metadata: name: app-dev labels: app: app-dev spec: replicas: 1 selector: matchLabels: app: app-dev template: metadata: labels: app: app-dev spec: containers: - name: app-dev image: registry.ap-northeast-2.compute.amazonaws.com:5000/app/app-dev:1 env: - name: SPRING_PROFILES_ACTIVE value: dev - name: SPRING_DATASOURCE_URL # 尝试过mysql.default, default.mysql, mysql.default.svc.cluster.local. value: jdbc:mysql://mysql.default:3306/db?serverTimezone=UTC&characterEncoding=UTF-8 imagePullPolicy: Always ports: - containerPort: 8080 nodeSelector: app: app-dev
错误日志
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server. at com.mysql.cj.jdbc.exceptions.SQLError.createCommunicationsException(SQLError.java:174) at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:64) at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:836) at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:456) at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:246) at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:197) at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:138) at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:358) at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:206) at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:477) at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:560) at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:115) at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:112) at org.springframework.jdbc.datasource.DataSourceUtils.fetchConnection(DataSourceUtils.java:158) at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:116) at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:79) ... 60 common frames omitted Caused by: com.mysql.cj.exceptions.CJCommunicationsException: Communications link failure The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server. at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:64) at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:500) at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:481) at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:61) at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:105) at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:151) at com.mysql.cj.exceptions.ExceptionFactory.createCommunicationsException(ExceptionFactory.java:167) at com.mysql.cj.protocol.a.NativeSocketConnection.connect(NativeSocketConnection.java:91) at com.mysql.cj.NativeSession.connect(NativeSession.java:144) at com.mysql.cj.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:956) at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:826) ... 73 common frames omitted Caused by: java.net.UnknownHostException: mysql.default: Name or service not known at java.base/java.net.Inet6AddressImpl.lookupAllHostAddr(Native Method) at java.base/java.net.InetAddress$PlatformNameService.lookupAllHostAddr(InetAddress.java:932) at java.base/java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1517) at java.base/java.net.InetAddress$NameServiceAddresses.get(InetAddress.java:851) at java.base/java.net.InetAddress.getAllByName0(InetAddress.java:1507) at java.base/java.net.InetAddress.getAllByName(InetAddress.java:1366) at java.base/java.net.InetAddress.getAllByName(InetAddress.java:1300) at com.mysql.cj.protocol.StandardSocketFactory.connect(StandardSocketFactory.java:132) at com.mysql.cj.protocol.a.NativeSocketConnection.connect(NativeSocketConnection.java:65) ... 76 common frames omitted
MySQL Service描述
# kubectl -n default describe service mysql Name: mysql Namespace: default Labels: <none> Annotations: <none> Selector: <none> Type: ExternalName IP Families: <none> IP: IPs: <none> External Name: mysql.ap-northeast-2.rds.amazonaws.com Port: <unset> 3306/TCP TargetPort: 3306/TCP Endpoints: <none> Session Affinity: None Events: <none>
解决方案与排查步骤
从错误日志的java.net.UnknownHostException: mysql.default: Name or service not known可知,核心问题是容器无法解析ExternalName Service的域名,以下是具体排查和修复步骤:
1. 修正数据库连接URL的域名格式
Kubernetes内部Service的标准域名格式为{{service-name}}.{{namespace}}.svc.cluster.local,你的ExternalName Service在default命名空间,正确的连接地址应为:
jdbc:mysql://mysql.default.svc.cluster.local:3306/db?serverTimezone=UTC&characterEncoding=UTF-8
如果应用和Service在同一命名空间,直接用mysql:3306即可,Kubernetes会自动解析同命名空间的Service。
2. 验证ExternalName Service的DNS解析
进入应用容器内部,执行以下命令确认是否能正确解析到RDS的IP:
# 同命名空间下直接解析service名 kubectl exec -it <你的应用Pod名称> -- nslookup mysql # 或使用完整域名 kubectl exec -it <你的应用Pod名称> -- nslookup mysql.default.svc.cluster.local
如果解析失败,需检查:
- Kubernetes集群的CoreDNS/ClusterDNS组件是否正常运行
- 集群所在VPC的DNS配置是否允许外部域名解析
3. 检查AWS RDS的网络访问控制
即使DNS解析正常,还需确认:
- RDS安全组是否允许Kubernetes集群节点的IP段访问3306端口
- RDS与Kubernetes集群是否在同一VPC,或通过VPC peering连通(优先使用内网访问)
- RDS数据库用户是否授权从应用所在IP段连接(例如
GRANT ALL ON db.* TO 'user'@'%' IDENTIFIED BY 'password';)
4. 简化测试:直接使用RDS域名连接
如果ExternalName Service的解析存在问题,可以先跳过它,直接在SPRING_DATASOURCE_URL中使用RDS原始域名:
jdbc:mysql://mysql.ap-northeast-2.rds.amazonaws.com:3306/db?serverTimezone=UTC&characterEncoding=UTF-8
如果能正常连接,说明问题出在ExternalName Service的配置或集群DNS解析上;如果仍无法连接,重点排查RDS的网络权限和数据库用户配置。
内容的提问来源于stack exchange,提问作者s4ng
相关产品推荐
相关产品推荐

