K8s部署springboot服务,访问外部mysql

吴书松
吴书松
发布于 2025-09-04 / 8 阅读
0
0

K8s部署springboot服务,访问外部mysql

通过k8s部署一个springboot服务,如何让这个springboot服务,在pod的容器内部,能访问一台公网的mysql

方式一:使用 Service 和 Endpoint(生产环境推荐)

此方法通过创建 Service 和关联的 Endpoint 对象,将公网 MySQL 实例“映射”到 Kubernetes 集群内部。你的 Spring Boot 应用就可以像访问集群内服务一样访问外部 MySQL。

yaml

# 1. 创建一个Service,定义集群内的访问入口
apiVersion: v1
kind: Service
metadata:
  name: external-mysql-service # 这是你在集群内访问的Service名称
spec:
  ports:
  - port: 3306 # Service暴露的端口
    targetPort: 3306 # 目标端口(MySQL端口)
  type: ClusterIP # 类型为ClusterIP,仅在集群内部可访问
---
# 2. 创建一个Endpoint,指向公网MySQL的地址
apiVersion: v1
kind: Endpoints
metadata:
  name: external-mysql-service # 必须与上面Service的名称相同
subsets:
  - addresses:
      - ip: 203.0.113.100 # 替换为你的公网MySQL服务器的真实IP地址
    ports:
      - port: 3306

应用配置:在你的 Spring Boot 应用的 Deployment YAML 中,配置数据库连接字符串时使用上面定义的 Service 名称。

yaml

env:
- name: SPRING_DATASOURCE_URL
  value: jdbc:mysql://external-mysql-service:3306/your_database?useSSL=false&serverTimezone=UTC
- name: SPRING_DATASOURCE_USERNAME
  valueFrom:
    secretKeyRef:
      name: mysql-secret
      key: username
- name: SPRING_DATASOURCE_PASSWORD
  valueFrom:
    secretKeyRef:
      name: mysql-secret
      key: password

优点

  • 高灵活性:MySQL IP 变更时,只需更新 Endpoint,无需重新部署应用。

  • 透明访问:应用像访问内部服务一样访问外部数据库。

  • 便于管理:符合 Kubernetes 的服务发现模式。

方法二:使用 ExternalName Service

如果公网 MySQL 是通过域名访问的(例如云数据库),可以使用 ExternalName 类型的 Service510

yaml

apiVersion: v1
kind: Service
metadata:
  name: external-mysql-dns
spec:
  type: ExternalName
  externalName: your.mysql.public.hostname.com # 替换为你的公网MySQL域名
  ports:
  - port: 3306

你的 Spring Boot 应用就可以通过 external-mysql-dns 这个 Service 名称访问数据库了。Kubernetes 的 DNS 系统会自动将其解析为外部域名。

优点

  • 配置非常简单直观。

  • 完美支持通过域名访问的外部服务。

缺点

  • 不能指定 IP 地址,某些网络策略下可能受限。

  • 依赖外部 DNS 解析。


方法三:直接在应用配置中指定公网地址

这是最直接的方式,即在 Spring Boot 的配置文件(或通过环境变量)中直接指定公网 MySQL 的地址1

通过 Deployment 环境变量配置

yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: your-springboot-app
spec:
  template:
    spec:
      containers:
      - name: app
        image: your-springboot-image
        env:
        - name: SPRING_DATASOURCE_URL
          value: "jdbc:mysql://<公网IP或域名>:3306/your_database?useSSL=false&serverTimezone=UTC"
        - name: SPRING_DATASOURCE_USERNAME
          value: "your_username"
        - name: SPRING_DATASOURCE_PASSWORD
          value: "your_password"

优点

  • 简单快速,无需额外的 Kubernetes 对象。

缺点

  • 配置与镜像/部署耦合:如果数据库地址变更,需要修改部署配置并重新部署应用。

  • 安全性:敏感信息直接暴露在 YAML 中(尽管可以用 Secret 优化,但地址本身仍是硬编码)。


🛡️ 必不可少的辅助配置

无论采用哪种方法,以下几项配置都至关重要:

  1. 使用 Secret 管理敏感信息:永远不要在 Deployment 或 ConfigMap 中以明文方式存储数据库密码1

    bash

    kubectl create secret generic mysql-secret \
      --from-literal=username=your_username \
      --from-literal=password=your_password

    然后在 Deployment 中引用:

    yaml

    env:
    - name: SPRING_DATASOURCE_USERNAME
      valueFrom:
        secretKeyRef:
          name: mysql-secret
          key: username
    - name: SPRING_DATASOURCE_PASSWORD
      valueFrom:
        secretKeyRef:
          name: mysql-secret
          key: password
  2. 配置网络策略(NetworkPolicy):如果集群启用了网络策略,你需要确保 Pod 有出站(Egress)到公网 MySQL IP 和 3306 端口的权限15

    yaml

    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: allow-mysql-egress
    spec:
      podSelector:
        matchLabels:
          app: your-springboot-app # 指定需要访问MySQL的Pod标签
      policyTypes:
      - Egress
      egress:
      - to:
        - ipBlock:
            cidr: 203.0.113.100/32 # 替换为你的MySQL公网IP,精确到单个IP
        ports:
        - protocol: TCP
          port: 3306
  3. 确保 DNS 解析正常:如果公网 MySQL 使用域名,需确保 Pod 内的 DNS 解析器能够正确解析该公网域名。通常集群的 DNS 策略(dnsPolicy: ClusterFirst)已能处理,但在某些自定义网络环境下可能需要检查1


⚠️ 重要注意事项

  • 公网 MySQL 的白名单:务必在你的公网 MySQL 实例的防火墙或安全组设置中,将你的 Kubernetes 集群所有节点的公网 IP 地址(或者如果 Pod 使用其他出站 IP)加入到允许访问的规则(白名单)中。这是访问能够成功的关键前提。

  • 连接安全性:通过公网访问数据库,强烈建议使用 SSL/TLS 加密连接(在 JDBC URL 中启用 useSSL=true 或类似参数),避免数据明文传输。并确保数据库账号不允许来自任意主机的访问(如避免使用 'user'@'%',除非必要)。

  • 性能与延迟:公网访问必然会引入比内网更高的网络延迟,需评估你的应用是否能接受此延迟。


📌 总结与选择

  • 开发测试环境:方法三(直接配置)最快速。

  • 生产环境,MySQL有固定公网IP强烈推荐方法一(Service + Endpoint),灵活且符合K8s最佳实践。

  • 生产环境,MySQL提供公网域名(如云数据库):方法二(ExternalName)很合适。


评论