You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Minikube中Kubernetes应用无法连接MySQL的问题求助

Kubernetes环境下User-Service无法连接MySQL的排查与解决

问题场景

在Minikube的Kubernetes环境中部署mysql-service和user-service后,user-service抛出MySQL连接失败错误,但相同配置在Docker Compose环境中可正常运行。

错误日志

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:175) ~[mysql-connector-j-8.0.33.jar!/:8.0.33]
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:64) ~[mysql-connector-j-8.0.33.jar!/:8.0.33]
at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:825) ~[mysql-connector-j-8.0.33.jar!/:8.0.33]
at com.mysql.cj.jdbc.ConnectionImpl.(ConnectionImpl.java:446) ~[mysql-connector-j-8.0.33.jar!/:8.0.33]
at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:239) ~[mysql-connector-j-8.0.33.jar!/:8.0.33]
at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:188) ~[mysql-connector-j-8.0.33.jar!/:8.0.33]
at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:138) ~[HikariCP-5.0.1.jar!/:na]
at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:359) ~[HikariCP-5.0.1.jar!/:na]
at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:201) ~[HikariCP-5.0.1.jar!/:na]
at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:470) ~[HikariCP-5.0.1.jar!/:na]
at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:561) ~[HikariCP-5.0.1.jar!/:na]
at com.zaxxer.hikari.pool.HikariPool.(HikariPool.java:100) ~[HikariCP-5.0.1.jar!/:na]
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:112) ~[HikariCP-5.0.1.jar!/:na]
at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) ~[hibernate-core-6.2.6.Final.jar!/:6.2.6.Final]
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:316) ~[hibernate-core-6.2.6.Final.jar!/:6.2.6.Final]

配置文件

docker-compose.yml

version: "3"

services:

  mysqldb-docker:
    image: mysql:8.0
    container_name: mysqldb
    networks:
      - app-mysql
    environment:
      - MYSQL_ROOT_PASSWORD=root
      - MYSQL_DATABASE=flight_booking
    ports:
      - "3306:3306"
    volumes:
      - ./db:/var/lib/mysql

  user-service:
    image: user-service:1.0
    build:
      context: ./UserService
    container_name: user-service
    ports:
      - "8081:8080"
    networks:
      - app-mysql
    depends_on:
      - mysqldb-docker
    environment:
      - SPRING_DATASOURCE_DB_HOST=mysqldb-docker
      - SPRING_DATASOURCE_URL=jdbc:mysql://mysqldb-service:3306/flight_booking?createDatabaseIfNotExist=true
      - SPRING_DATASOURCE_USERNAME=root
      - SPRING_DATASOURCE_PASSWORD=root

# Volumes
volumes:
  mysqldb-docker:

networks:
  app-mysql:

mysqldb-deployment.yaml

# mysqldb-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysqldb-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysqldb
  template:
    metadata:
      labels:
        app: mysqldb
    spec:
      containers:
        - name: mysqldb
          image: mysql:8.0
          ports:
            - containerPort: 3306
              name: mysqldb
          env:
            - name: MYSQL_ROOT_PASSWORD
              value: root
            - name: MYSQL_DATABASE
              value: flight_booking
          volumeMounts:
            - name: mysqldb-persistent-storage  # Reference the PVC name
              mountPath: /var/lib/mysql
      volumes:
        - name: mysqldb-persistent-storage  # Define the volume name
          persistentVolumeClaim:
            claimName: mysqldb-pvc  # Reference the PVC name you created earlier

mysqldb-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: mysqldb-service
spec:
  selector:
    app: mysqldb
  ports:
    - port: 3306

mysqldb-pv.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: mysqldb-pv
spec:
  capacity:
    storage: 5Gi  # Set the desired storage size
  accessModes:
    - ReadWriteOnce  # Adjust based on your use case
  persistentVolumeReclaimPolicy: Retain
  storageClassName: standard  # Set the appropriate storage class
  hostPath:
    path: /path/to/host/mysqldb-data  # Adjust the host path to your desired location

mysqldb-pvc.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysqldb-pvc
spec:
  accessModes:
    - ReadWriteOnce  # Must match the access mode in the PV
  resources:
    requests:
      storage: 5Gi  # Must match the storage size in the PV

user-service-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: user-service-deployment
spec:
  replicas: 1  # Set the desired number of replicas
  selector:
    matchLabels:
      app: user-service
  template:
    metadata:
      labels:
        app: user-service
    spec:
      containers:
        - name: user-service
          image: sweetyrv/flight_booking:user-service
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 8081
          env:
            - name: MYSQL_DATABASE
              value: flight_booking
            - name: MYSQL_ROOT_PASSWORD
              value: root
            - name: SPRING_DATASOURCE_DB_HOST
              value: mysqldb-service
            - name: SPRING_DATASOURCE_URL
              value: jdbc:mysql://mysqldb-service:3306/flight_booking?createDatabaseIfNotExist=true
            - name: SPRING_DATASOURCE_USERNAME
              value: root
            - name: SPRING_DATASOURCE_PASSWORD
              value: root

user-service-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: user-service
spec:
  selector:
    app: user-service
  ports:
    - protocol: TCP
      port: 8081
      targetPort: 8081

已排查项

  • 网络策略:确认无限制Pod间通信的策略
  • 主机名解析:在user-service Pod内可正常解析mysqldb-service
  • MySQL服务器配置:Docker环境中配置正常,K8s中使用相同镜像参数

问题分析与解决建议

1. MySQL初始化完成前User-Service尝试连接

Kubernetes的Pod启动顺序控制不等待服务就绪,而Docker Compose环境中MySQL启动速度可能更快,或者隐含了就绪等待逻辑。

  • 解决:给user-service添加启动等待机制,比如在启动脚本中使用wait-for-it.sh工具,等待mysqldb-service:3306端口可访问后再启动应用;或者在Spring Boot配置中添加连接重试:
    spring.datasource.hikari.connection-timeout=30000
    spring.datasource.hikari.maximum-pool-size=10
    spring.datasource.hikari.idle-timeout=600000
    spring.datasource.hikari.max-lifetime=1800000
    spring.datasource.hikari.validation-timeout=5000
    spring.datasource.hikari.connection-test-query=SELECT 1
    
    同时给MySQL Deployment添加readinessProbe,确保服务就绪后才被Service关联:
    # 在mysqldb-deployment的containers下添加
    readinessProbe:
      tcpSocket:
        port: 3306
      initialDelaySeconds: 15
      periodSeconds: 10
    

2. MySQL远程连接权限限制

MySQL 8.0默认仅允许root@localhost登录,K8s中User-Service从其他Pod连接,需要授权root@%访问权限。

  • 解决:进入MySQL Pod执行授权命令:
    kubectl exec -it $(kubectl get pods -l app=mysqldb -o jsonpath='{.items[0].metadata.name}') -- mysql -uroot -proot
    mysql> GRANT ALL PRIVILEGES ON flight_booking.* TO 'root'@'%' WITH GRANT OPTION;
    mysql> FLUSH PRIVILEGES;
    
    或者通过ConfigMap挂载初始化脚本,实现自动授权:
    # 创建mysql-init-config ConfigMap
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: mysql-init-config
    data:
      init.sql: |
        GRANT ALL PRIVILEGES ON flight_booking.* TO 'root'@'%' WITH GRANT OPTION;
        FLUSH PRIVILEGES;
    
    修改mysqldb-deployment.yaml,挂载该ConfigMap到MySQL初始化目录:
    # 在containers的volumeMounts中添加
    - name: init-script
      mountPath: /docker-entrypoint-initdb.d
    # 在volumes中添加
    - name: init-script
      configMap:
        name: mysql-init-config
    

3. PV/PVC挂载权限问题

Minikube节点内的hostPath路径如果不存在或权限不足,会导致MySQL无法写入数据,启动异常。

  • 解决:进入Minikube节点创建路径并设置权限:
    minikube ssh
    sudo mkdir -p /path/to/host/mysqldb-data
    sudo chmod 777 /path/to/host/mysqldb-data
    
    或者改用Minikube动态存储,删除手动创建的PV,直接使用PVC,Minikube会自动分配符合要求的存储。

4. JDBC URL参数缺失

MySQL 8.0需要指定时区参数,否则可能引发连接失败。

  • 解决:修改JDBC URL为:
    jdbc:mysql://mysqldb-service:3306/flight_booking?createDatabaseIfNotExist=true&serverTimezone=UTC&useSSL=false
    

5. 服务端点验证

确认mysqldb-service正确关联到mysqldb Pod,执行以下命令检查:

kubectl get svc mysqldb-service
kubectl describe svc mysqldb-service
kubectl get endpoints mysqldb-service

确保Endpoints中存在mysqldb Pod的IP地址。

内容的提问来源于stack exchange,提问作者Varshini

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 05:20:57