通过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 优化,但地址本身仍是硬编码)。
🛡️ 必不可少的辅助配置
无论采用哪种方法,以下几项配置都至关重要:
使用 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配置网络策略(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确保 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)很合适。