K8s Spring 应用程序无法连接到 Mysql 数据库
K8s Spring Application cannot connect to Mysql DB
我想尝试在 kubernetes 上部署我的 spring 启动应用程序。我用 microk8s(启用了 dns、存储、入口)设置了一个测试环境,它由一个 pod 运行 应用程序本身和一个带有 MySQL 数据库的 pod 组成。每个 pod 都有自己的服务,并且 运行 在同一个默认命名空间中。 yaml 文件如下所示:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
spec:
replicas: 1
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: test-app
image: myImage
ports:
- containerPort: 8080
imagePullPolicy: Always
env:
- name: SPRING_APPLICATION_JSON
valueFrom:
configMapKeyRef:
name: spring-config
key: app-config.json
申请服务:
apiVersion: v1
kind: Service
metadata:
name: myapp-service
spec:
selector:
app: myapp
ports:
- port: 8080
targetPort: 8080
Mysql部署:
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql-server
labels:
# app: mysql
app: mysql
spec:
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
volumes:
- name: mysql-persistent-volume-storage
persistentVolumeClaim:
claimName: mysql-pvc-claim
containers:
- name: mysql
image: mysql
volumeMounts:
- name: mysql-persistent-volume-storage
mountPath: /var/lib/mysql
subPath: mysql-server
env:
- name: MYSQL_ROOT_PASSWORD
value: pass_root
- name: MYSQL_USER
value: user
- name: MYSQL_PASSWORD
value: pass
- name: MYSQL_DATABASE
value: test
ports:
- containerPort: 3306
Mysql 服务:
apiVersion: v1
kind: Service
metadata:
name: db-service
spec:
selector:
app: mysql
ports:
- port: 3306
targetPort: 3306
出于某种原因,我的应用程序无法使用数据库。它抛出这个错误:
com.mysql.cj.jdbc.exceptions.CommunicationsException: 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 com.mysql.cj.jdbc.exceptions.SQLError.createCommunicationsException(SQLError.java:174) ~[mysql-connector-java-8.0.25.jar!/:8.0.25]
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:64) ~[mysql-connector-java-8.0.25.jar!/:8.0.25]
at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:833) ~[mysql-connector-java-8.0.25.jar!/:8.0.25]
at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:453) ~[mysql-connector-java-8.0.25.jar!/:8.0.25]
at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:246) ~[mysql-connector-java-8.0.25.jar!/:8.0.25]
at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:198) ~[mysql-connector-java-8.0.25.jar!/:8.0.25]
at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:121) ~[HikariCP-4.0.3.jar!/:na]
at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:364) ~[HikariCP-4.0.3.jar!/:na]
at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:206) ~[HikariCP-4.0.3.jar!/:na]
at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:476) ~[HikariCP-4.0.3.jar!/:na]
at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:561) ~[HikariCP-4.0.3.jar!/:na]
at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:115) ~[HikariCP-4.0.3.jar!/:na]
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:112) ~[HikariCP-4.0.3.jar!/:na]
.......
application.yml:
db:
datasource:
url: jdbc:mysql://ip/test
user: user
password: pass
---
spring:
datasource:
url: ${db.datasource.url}
username: ${db.datasource.user}
password: ${db.datasource.password}
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
database-platform: org.hibernate.dialect.MySQLDialect
mvc:
view:
suffix: .html
thymeleaf:
cache: false
allowPublicKeyRetrieval: true
hibernate:
show_sql: true
logging:
level:
org:
hibernate:
SQL: debug
我尝试从命名空间 运行 mysql 上的另一个 pod 访问该服务,因为它预装了 mysql-客户端,并且从主机访问。两者都可以访问数据库。我还在 pod 运行 应用程序上尝试 ping。发现服务没有问题
然后我尝试使用 NodePort 而不是 ClusterIP。什么都没有改变。
我确定凭据是正确的。
最后,我尝试在 application.yml 中删除和添加端口。
我完全卡住了,我不知道出了什么问题。任何帮助将不胜感激。
我发现您的配置存在两个问题:mysql 部署中的 username/password 与 application.yaml 中的值不匹配。
另一个是您使用 属性 而 spring 引导默认不使用,我假设您没有特殊的逻辑来处理它:“spring.data.url”应该是“spring.datasource.url”。
请注意,它应该是“spring.datasource.username”,而不是“用户”。
参考 YAML 中的 'db' 部分:一般来说,我不建议为数据库凭据设置一个单独的部分并使用变量引用它。
我想尝试在 kubernetes 上部署我的 spring 启动应用程序。我用 microk8s(启用了 dns、存储、入口)设置了一个测试环境,它由一个 pod 运行 应用程序本身和一个带有 MySQL 数据库的 pod 组成。每个 pod 都有自己的服务,并且 运行 在同一个默认命名空间中。 yaml 文件如下所示:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
spec:
replicas: 1
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: test-app
image: myImage
ports:
- containerPort: 8080
imagePullPolicy: Always
env:
- name: SPRING_APPLICATION_JSON
valueFrom:
configMapKeyRef:
name: spring-config
key: app-config.json
申请服务:
apiVersion: v1
kind: Service
metadata:
name: myapp-service
spec:
selector:
app: myapp
ports:
- port: 8080
targetPort: 8080
Mysql部署:
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql-server
labels:
# app: mysql
app: mysql
spec:
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
volumes:
- name: mysql-persistent-volume-storage
persistentVolumeClaim:
claimName: mysql-pvc-claim
containers:
- name: mysql
image: mysql
volumeMounts:
- name: mysql-persistent-volume-storage
mountPath: /var/lib/mysql
subPath: mysql-server
env:
- name: MYSQL_ROOT_PASSWORD
value: pass_root
- name: MYSQL_USER
value: user
- name: MYSQL_PASSWORD
value: pass
- name: MYSQL_DATABASE
value: test
ports:
- containerPort: 3306
Mysql 服务:
apiVersion: v1
kind: Service
metadata:
name: db-service
spec:
selector:
app: mysql
ports:
- port: 3306
targetPort: 3306
出于某种原因,我的应用程序无法使用数据库。它抛出这个错误:
com.mysql.cj.jdbc.exceptions.CommunicationsException: 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 com.mysql.cj.jdbc.exceptions.SQLError.createCommunicationsException(SQLError.java:174) ~[mysql-connector-java-8.0.25.jar!/:8.0.25]
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:64) ~[mysql-connector-java-8.0.25.jar!/:8.0.25]
at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:833) ~[mysql-connector-java-8.0.25.jar!/:8.0.25]
at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:453) ~[mysql-connector-java-8.0.25.jar!/:8.0.25]
at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:246) ~[mysql-connector-java-8.0.25.jar!/:8.0.25]
at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:198) ~[mysql-connector-java-8.0.25.jar!/:8.0.25]
at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:121) ~[HikariCP-4.0.3.jar!/:na]
at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:364) ~[HikariCP-4.0.3.jar!/:na]
at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:206) ~[HikariCP-4.0.3.jar!/:na]
at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:476) ~[HikariCP-4.0.3.jar!/:na]
at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:561) ~[HikariCP-4.0.3.jar!/:na]
at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:115) ~[HikariCP-4.0.3.jar!/:na]
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:112) ~[HikariCP-4.0.3.jar!/:na]
.......
application.yml:
db:
datasource:
url: jdbc:mysql://ip/test
user: user
password: pass
---
spring:
datasource:
url: ${db.datasource.url}
username: ${db.datasource.user}
password: ${db.datasource.password}
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
database-platform: org.hibernate.dialect.MySQLDialect
mvc:
view:
suffix: .html
thymeleaf:
cache: false
allowPublicKeyRetrieval: true
hibernate:
show_sql: true
logging:
level:
org:
hibernate:
SQL: debug
我尝试从命名空间 运行 mysql 上的另一个 pod 访问该服务,因为它预装了 mysql-客户端,并且从主机访问。两者都可以访问数据库。我还在 pod 运行 应用程序上尝试 ping。发现服务没有问题
然后我尝试使用 NodePort 而不是 ClusterIP。什么都没有改变。
我确定凭据是正确的。
最后,我尝试在 application.yml 中删除和添加端口。
我完全卡住了,我不知道出了什么问题。任何帮助将不胜感激。
我发现您的配置存在两个问题:mysql 部署中的 username/password 与 application.yaml 中的值不匹配。
另一个是您使用 属性 而 spring 引导默认不使用,我假设您没有特殊的逻辑来处理它:“spring.data.url”应该是“spring.datasource.url”。
请注意,它应该是“spring.datasource.username”,而不是“用户”。
参考 YAML 中的 'db' 部分:一般来说,我不建议为数据库凭据设置一个单独的部分并使用变量引用它。