在 Kubernetes 中部署结合 ShardingSphere-JDBC(客户端分片模式)和 MySQL Operator 的架构,需要分别部署这两个核心组件,并进行集成配置。以下是一个详细的安装部署指南:
核心组件理解
- ShardingSphere-JDBC:
- 工作在 应用层,是一个 JDBC 驱动扩展。
- 应用 直接依赖 ShardingSphere-JDBC Jar 包。
- 分片、读写分离、加密等逻辑由 应用代码执行。
- 不需要 独立部署的 Proxy 服务。
- MySQL Operator:
- 用于在 K8s 上自动化管理 MySQL 集群(如主从复制、Group Replication/InnoDB Cluster)。
- 提供 高可用、备份恢复、扩缩容 能力。
- 常见 Operator:Oracle MySQL Operator、Presslabs MySQL Operator (vitess-operator 也支持 MySQL,但更复杂)。
部署步骤详解
阶段 1:部署 MySQL Operator 与 MySQL 集群
这里以 Presslabs MySQL Operator (mysql-operator) 为例,因其流行度较高且支持 Group Replication。
-
添加 Helm Repo & 安装 Operator:
helm repo add presslabs https://presslabs.github.io/charts helm repo update # 安装 Operator CRD 和 Controller helm install my-mysql-operator presslabs/mysql-operator -n mysql-operator --create-namespace
-
创建 MySQL 集群 (InnoDB Cluster):
- 创建命名空间 (如
mysql
):kubectl create ns mysql
- 创建
mysql-cluster.yaml
:apiVersion: mysql.presslabs.org/v1alpha1 kind: MysqlCluster metadata: name: my-shard-cluster # 集群名,后续在 JDBC URL 中引用 namespace: mysql spec: secretName: mysql-root-secret # 包含 root 密码的 Secret replicas: 3 # 3 节点 Group Replication (最小推荐) podSpec: image: percona:8.0 # 或 mysql:8.0, mariadb:10.11 resources: requests: cpu: 500m memory: 1Gi volumeSpec: persistentVolumeClaim: accessModes: [ "ReadWriteOnce" ] storageClassName: "standard" # 替换为你的 StorageClass resources: requests: storage: 10Gi mysqlConf: innodbBufferPoolSize: 512M # 根据内存调整
- 创建 root 密码 Secret:
kubectl create secret generic mysql-root-secret -n mysql \ --from-literal=password=your-strong-password-here
- 部署集群:
kubectl apply -f mysql-cluster.yaml -n mysql
- 等待集群就绪:
关键 Service:kubectl get mysqlcluster/my-shard-cluster -n mysql -w # 查看 Pods kubectl get pods -n mysql -l mysql.presslabs.org/cluster=my-shard-cluster -w # 查看 Service (用于连接) kubectl get svc -n mysql -l mysql.presslabs.org/cluster=my-shard-cluster
my-shard-cluster-mysql-primary
(或-master
): 主节点 (读写)my-shard-cluster-mysql-replicas
(或-readonly
): 只读副本 (负载均衡)my-shard-cluster-mysql
: 所有节点的服务 (常用于 Operator 管理)
- 创建命名空间 (如
阶段 2:准备 ShardingSphere-JDBC 配置
核心:创建 config-sharding.yaml
文件
# config-sharding.yaml
dataSources:
ds_0: # 数据源名称 (逻辑名,可自定义)
dataSourceClassName: com.zaxxer.hikari.HikariDataSource # 推荐使用 HikariCP
driverClassName: com.mysql.cj.jdbc.Driver
jdbcUrl: "jdbc:mysql://my-shard-cluster-mysql-primary.mysql.svc.cluster.local:3306/db0?useSSL=false&allowPublicKeyRetrieval=true&characterEncoding=utf8" # 指向 MySQL 集群主节点 Service
username: root
password: your-strong-password-here # 强烈建议使用 Secret 注入
# 如果你的分片策略需要多个物理库 (如分库分表),在此处定义 ds_1, ds_2...
# ds_1:
# ... (指向另一个 MySQL 集群或同一个集群的不同 schema)
rules:
- !SHARDING
tables:
t_order: # 逻辑表名
actualDataNodes: ds_0.t_order_${0..3} # 物理表:ds_0 库中的 t_order_0 到 t_order_3
tableStrategy:
standard:
shardingColumn: order_id
shardingAlgorithmName: t_order_inline
# ... 定义其他需要分片的表
shardingAlgorithms:
t_order_inline:
type: INLINE
props:
algorithm-expression: t_order_${order_id % 4} # 分片算法:按 order_id 取模分4表
# ... 定义其他分片算法
# 绑定表(可选,优化关联查询)
bindingTables:
- t_order, t_order_item
# 广播表(可选,所有库都有全量数据)
broadcastTables:
- t_config
重要说明:
jdbcUrl
: 指向 MySQL Operator 创建的primary/master
Service (my-shard-cluster-mysql-primary.mysql.svc.cluster.local:3306
)。这是写入节点。username
/password
: 使用 MySQL root 用户或为应用创建专用用户。务必通过 K8s Secret 注入密码!actualDataNodes
: 定义逻辑表映射到的物理库和表。如果只分表不分库,数据源 (ds_0
) 只有一个,指向主库。- 分片算法 (
shardingAlgorithms
): 根据业务需求配置 (取模、范围、哈希、自定义等)。 - 读写分离 (可选):
- 在
dataSources
中定义主库 (writeDataSourceName
)。 - 定义只读数据源 (
readDataSourceNames
) 列表,指向replicas/readonly
Service (my-shard-cluster-mysql-replicas.mysql.svc.cluster.local:3306
)。 - 在
rules
中添加!READWRITE_SPLITTING
规则。ShardingSphere-JDBC 会根据 SQL 类型自动路由读写。
- 在
阶段 3:集成 ShardingSphere-JDBC 到应用
-
应用依赖:
- 在应用的
pom.xml
(Maven) 或build.gradle
(Gradle) 中添加 ShardingSphere-JDBC 核心依赖:<!-- ShardingSphere JDBC 核心 --> <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>shardingsphere-jdbc-core</artifactId> <version>5.3.0</version> <!-- 使用最新稳定版 --> </dependency> <!-- MySQL Connector/J --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> <!-- 与 MySQL 服务器版本匹配 --> </dependency> <!-- HikariCP (推荐) --> <dependency> <groupId>com.zaxxer</groupId> <artifactId>HikariCP</artifactId> <version>5.0.1</version> </dependency>
- 在应用的
-
配置加载:
- 方案 A (推荐 - ConfigMap + 文件系统):
- 将
config-sharding.yaml
创建为 ConfigMap:kubectl create configmap shardingsphere-config -n your-app-namespace --from-file=config-sharding.yaml
- 在应用 Deployment 中将此 ConfigMap 挂载到容器内的某个路径 (如
/etc/shardingsphere/config-sharding.yaml
)。 - 修改应用代码,从该文件路径加载 ShardingSphere 配置:
String configFile = "/etc/shardingsphere/config-sharding.yaml"; DataSource dataSource = YamlShardingSphereDataSourceFactory.createDataSource(new File(configFile));
- 将
- 方案 B (嵌入式 - 环境变量/启动参数):
- 将
config-sharding.yaml
的内容转换为 YAML 字符串 或 Properties。 - 通过 ConfigMap 设置成环境变量或命令行参数。
- 在应用启动时读取环境变量/参数,构建
Map<String, DataSource>
和ShardingSphereRuleConfiguration
,使用ShardingSphereDataSourceFactory.createDataSource(...)
创建DataSource
。(更复杂)。
- 将
- 方案 A (推荐 - ConfigMap + 文件系统):
-
数据库密码安全:
- 绝对不要 将明文密码写在
config-sharding.yaml
或代码中! - 在
config-sharding.yaml
的password
字段使用占位符 (如${MYSQL_DS_PASSWORD}
)。 - 创建一个 K8s Secret 存储数据库密码:
kubectl create secret generic app-db-secret -n your-app-namespace \ --from-literal=ds-password=your-actual-db-password
- 在应用的 Deployment 中,将该 Secret 的值注入为环境变量:
env: - name: MYSQL_DS_PASSWORD valueFrom: secretKeyRef: name: app-db-secret key: ds-password
- 应用启动时,ShardingSphere-JDBC 会自动解析
${MYSQL_DS_PASSWORD}
并使用环境变量的值填充。
- 绝对不要 将明文密码写在
-
使用 DataSource:
- 将 ShardingSphere 创建的
DataSource
注入到你的应用框架 (如 Spring Boot 的DataSource
Bean) 或直接在你的 DAO/JDBC 代码中使用。 - 应用代码几乎无需修改,像使用普通 JDBC
DataSource
一样操作数据库。ShardingSphere-JDBC 在底层透明处理分片、路由等逻辑。
- 将 ShardingSphere 创建的
阶段 4:部署应用
- 构建应用容器镜像 (包含应用代码、JDK、ShardingSphere JDBC 依赖)。
- 创建应用 Deployment:
apiVersion: apps/v1 kind: Deployment metadata: name: your-sharding-app namespace: your-app-namespace spec: replicas: 2 selector: matchLabels: app: your-sharding-app template: metadata: labels: app: your-sharding-app spec: containers: - name: app image: your-registry/your-sharding-app:latest env: - name: MYSQL_DS_PASSWORD # 注入数据库密码 valueFrom: secretKeyRef: name: app-db-secret key: ds-password volumeMounts: - name: shardingsphere-config mountPath: /etc/shardingsphere # 挂载 ConfigMap readOnly: true volumes: - name: shardingsphere-config configMap: name: shardingsphere-config # 引用之前创建的 ConfigMap # ... (根据需要添加 Service, Ingress 等)
- 应用 Service/Ingress: 创建 Service 暴露应用端口,如果需要外部访问,创建 Ingress。
阶段 5:验证与测试
-
检查 Pod 状态:
kubectl get pods -n mysql # MySQL 集群状态 kubectl get pods -n your-app-namespace # 应用状态 kubectl logs -f <your-app-pod-name> -n your-app-namespace # 查看应用日志,注意 ShardingSphere 初始化日志
-
连接 MySQL 主节点验证数据分布:
kubectl run -it --rm mysql-client -n mysql --image=mysql:8.0 -- \ mysql -h my-shard-cluster-mysql-primary.mysql.svc.cluster.local -uroot -p'your-root-password' > USE db0; > SHOW TABLES; # 应看到 t_order_0, t_order_1, t_order_2, t_order_3 等物理表 > SELECT * FROM t_order_0; # 检查数据是否按预期分布在不同的物理表
-
执行应用功能测试:
- 通过应用 API 或 UI 执行 CRUD 操作。
- 观察应用日志中 ShardingSphere 的 SQL 路由日志 (需开启相应日志级别)。
- 验证数据是否正确写入预期的物理分片表。
- 如果配置了读写分离,验证读操作是否路由到了只读副本 (
replicas
Service)。
关键注意事项
- 版本兼容性:
- 确保 ShardingSphere-JDBC、MySQL Connector/J、MySQL Server、MySQL Operator 版本相互兼容。查阅官方文档。
- 分片键选择:
- 选择业务意义明确、分布均匀的列作为分片键 (如
user_id
,order_id
)。避免热点。
- 选择业务意义明确、分布均匀的列作为分片键 (如
- 事务:
- 跨分片的分布式事务是复杂问题。ShardingSphere 支持 XA (2PC) 和 BASE (Seata) 事务,但都有性能或复杂度开销。尽量设计业务,让单个事务内的操作落在同一个分片内 (同一库)。
- DDL 管理:
- ShardingSphere-JDBC 不自动同步 DDL 到所有物理表。创建/修改表结构需要在所有物理库/表上手动执行,或通过工具同步。谨慎操作。
- 连接池配置:
- 在
config-sharding.yaml
的dataSource
部分,可以配置HikariCP
(或Druid
) 的连接池参数 (如maximumPoolSize
,connectionTimeout
),优化数据库连接管理。
- 在
- 监控:
- MySQL Operator 监控: 部署 Prometheus Operator 并配置监控 MySQL 集群 (如使用 mysqld-exporter)。
- ShardingSphere-JDBC 监控: 启用 ShardingSphere 的 Metrics (支持 Prometheus) 或使用其自带的治理中心功能。监控 SQL 执行、连接池、路由情况。
- 应用监控: 使用应用性能监控 (APM) 工具 (如 SkyWalking, Pinpoint) 追踪 SQL 性能。
- 备份恢复:
- 利用 MySQL Operator 提供的备份功能 (通常基于 Percona XtraBackup) 定期备份集群。测试恢复流程。
- 高可用与故障转移:
- MySQL Operator 通常能自动处理主节点故障转移。确保应用配置的
jdbcUrl
指向的是稳定的 Service (primary/master
),而不是具体的 Pod IP。Operator 会在故障转移后更新 Service 指向新的主节点。 - 应用本身也需要部署多个副本 (
replicas > 1
) 并通过 Service 负载均衡,实现应用层高可用。
- MySQL Operator 通常能自动处理主节点故障转移。确保应用配置的
- 资源规划:
- 根据业务负载,合理设置 MySQL Pod 和 应用 Pod 的 CPU/Memory Requests/Limits。
- 为 PersistentVolume 预留足够空间并监控使用情况。
总结
在 Kubernetes 上部署 ShardingSphere-JDBC + MySQL Operator 的架构,核心在于:
- 独立部署 MySQL 集群:使用 Operator (如 Presslabs) 在 K8s 上自动化部署和管理高可用的 MySQL InnoDB Cluster。
- 应用集成 ShardingSphere-JDBC:
- 应用直接引入 ShardingSphere-JDBC 依赖。
- 将精心设计的
config-sharding.yaml
(分片规则 + 指向 MySQL 主节点 Service 的 JDBC URL) 通过 ConfigMap 挂载到应用容器。 - 使用 Secret 安全地管理数据库密码并通过环境变量注入。
- 应用启动时加载该 YAML 配置文件创建 ShardingSphere
DataSource
。
- 透明分片:应用代码像使用普通 JDBC 一样操作数据库,ShardingSphere-JDBC 在底层透明处理分片逻辑。
这种架构结合了 Kubernetes 的容器编排、Operator 的数据库自动化管理能力和 ShardingSphere-JDBC 强大的数据分片扩展能力,非常适合需要在云原生环境下构建大规模、高性能、可扩展的数据库应用的场景。务必做好详细的规划、测试和监控。