数据库/中间件部署
数据库和中间件是有状态应用的典型代表,部署这些应用需要特殊考虑数据持久性、网络标识和启动顺序等问题。Kubernetes 提供了 StatefulSet、PersistentVolume 等资源来支持有状态应用的部署。
有状态应用架构
graph LR
API[(API Server)] --> MYSQL1
API --> PG1
API --> REDIS1
API --> KAFKA1
API --> RMQ1
MYSQL1 --> PV1
MYSQL2 --> PV2
MYSQL3 --> PV3
PG1 --> PGP1
PG2 --> PGP2
REDIS1 --> REDISPV1
REDIS2 --> REDISPV2
REDIS3 --> REDISPV3
RMQ1 --> RMQPV1
RMQ2 --> RMQPV2
RMQ3 --> RMQPV3
subgraph "K8s Cluster"
subgraph "Control Plane"
API
ETCD[(etcd)]
end
subgraph "Databases and Middleware"
subgraph "MySQL Cluster"
MYSQL1("MySQL-0")
MYSQL2("MySQL-1")
MYSQL3("MySQL-2")
end
subgraph "PostgreSQL Cluster"
PG1("PostgreSQL-0")
PG2("PostgreSQL-1")
end
subgraph "Redis Cluster"
REDIS1("Redis-0")
REDIS2("Redis-1")
REDIS3("Redis-2")
end
subgraph "Kafka Cluster"
KAFKA1("Kafka-0")
KAFKA2("Kafka-1")
KAFKA3("Kafka-2")
end
subgraph "RabbitMQ Cluster"
RMQ1("RabbitMQ-0")
RMQ2("RabbitMQ-1")
RMQ3("RabbitMQ-2")
end
end
subgraph "Storage Layer"
PV1("PV-MySQL-0")
PV2("PV-MySQL-1")
PV3("PV-MySQL-2")
PGP1("PV-PostgreSQL-0")
PGP2("PV-PostgreSQL-1")
REDISPV1("PV-Redis-0")
REDISPV2("PV-Redis-1")
REDISPV3("PV-Redis-2")
RMQPV1("PV-RabbitMQ-0")
RMQPV2("PV-RabbitMQ-1")
RMQPV3("PV-RabbitMQ-2")
end
end
数据库/中间件部署详解
关系型数据库 (MySQL/PostgreSQL)
关系型数据库需要持久化存储和稳定的网络标识,适合使用 StatefulSet 部署。
- 使用 PersistentVolume 保证数据持久性
- 通过 Headless Service 提供稳定的网络标识
- 配置主从复制或集群模式实现高可用
- 使用 Secret 管理数据库凭证
缓存/消息中间件 (Redis/Kafka/RabbitMQ)
中间件通常需要特定的配置和集群模式,也适合使用 StatefulSet 部署。
- Redis: 配置主从复制或集群模式
- Kafka: 保证分区和副本的持久性
- RabbitMQ: 设置镜像队列确保高可用
- 所有中间件都需要持久化存储
数据库与中间件对比
| 应用类型 | 数据特点 | 部署要求 | 典型用途 |
|---|---|---|---|
| MySQL | 关系型数据,ACID特性 | 主从复制,高可用 | 事务处理,数据存储 |
| PostgreSQL | 关系型数据,扩展性强 | 主从复制,读写分离 | 复杂查询,数据分析 |
| Redis | 键值存储,内存为主 | 主从复制,集群模式 | 缓存,会话存储 |
| Kafka | 分布式消息队列 | 分区复制,持久化 | 实时数据流处理 |
| RabbitMQ | 消息队列,多种协议 | 镜像队列,集群 | 异步消息传递 |
MySQL 部署示例
# MySQL StatefulSet 示例
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
serviceName: mysql
replicas: 3
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:8.0
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: password
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
volumeClaimTemplates:
- metadata:
name: mysql-persistent-storage
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 20Gi
# MySQL Headless Service
apiVersion: v1
kind: Service
metadata:
name: mysql
labels:
app: mysql
spec:
ports:
- port: 3306
name: mysql
clusterIP: None
selector:
app: mysql
PostgreSQL 部署示例
# PostgreSQL StatefulSet 示例
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgresql
spec:
serviceName: postgresql
replicas: 2
selector:
matchLabels:
app: postgresql
template:
metadata:
labels:
app: postgresql
spec:
containers:
- name: postgresql
image: postgres:13
env:
- name: POSTGRES_DB
value: "mydb"
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: postgresql-secret
key: user
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgresql-secret
key: password
ports:
- containerPort: 5432
name: postgresql
volumeMounts:
- name: postgresql-persistent-storage
mountPath: /var/lib/postgresql/data
volumeClaimTemplates:
- metadata:
name: postgresql-persistent-storage
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 30Gi
Redis 部署示例
# Redis 集群 StatefulSet 示例
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
spec:
serviceName: redis
replicas: 6
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:6.2-alpine
command:
- redis-server
- /etc/redis/redis.conf
ports:
- containerPort: 6379
name: redis
volumeMounts:
- name: redis-config
mountPath: /etc/redis
- name: redis-persistent-storage
mountPath: /data
volumes:
- name: redis-config
configMap:
name: redis-config
volumeClaimTemplates:
- metadata:
name: redis-persistent-storage
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 10Gi
Kafka 部署示例
# Kafka StatefulSet 示例
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: kafka
spec:
serviceName: kafka
replicas: 3
selector:
matchLabels:
app: kafka
template:
metadata:
labels:
app: kafka
spec:
containers:
- name: kafka
image: confluentinc/cp-kafka:latest
ports:
- containerPort: 9092
name: kafka
env:
- name: KAFKA_BROKER_ID
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: KAFKA_ZOOKEEPER_CONNECT
value: "zookeeper:2181"
- name: KAFKA_ADVERTISED_LISTENERS
value: "PLAINTEXT://$(HOSTNAME).kafka:9092"
volumeMounts:
- name: kafka-persistent-storage
mountPath: /var/lib/kafka/data
volumeClaimTemplates:
- metadata:
name: kafka-persistent-storage
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 50Gi
数据库/中间件部署策略
MySQL 部署策略
MySQL 作为关系型数据库,需要考虑数据一致性、高可用性、备份恢复等关键问题。
- 使用 StatefulSet 确保 Pod 有序部署和稳定的网络标识
- 配置主从复制或组复制实现高可用
- 使用 PersistentVolume 确保数据持久存储
- 配置合适的资源限制和请求
- 设置定期备份和监控告警
PostgreSQL 部署策略
PostgreSQL 是功能强大的开源关系型数据库,支持复杂查询和扩展功能。
- 利用 StatefulSet 的特性部署主从架构
- 配置流复制实现数据同步
- 使用专用存储确保 I/O 性能
- 配置连接池优化性能
- 定期执行维护任务(VACUUM, ANALYZE 等)
Redis 部署策略
Redis 作为高性能缓存和数据结构存储,支持多种部署模式。
- 主从模式:实现读写分离和高可用
- 哨兵模式:自动故障转移
- 集群模式:数据分片和高可用
- 持久化策略:RDB 和 AOF 配置
- 内存管理:配置合适的 maxmemory 和淘汰策略
Kafka & RabbitMQ 部署策略
消息中间件需要高吞吐量和可靠的消息传递。
- Kafka: 配置副本因子确保数据可靠性
- Kafka: 调整分区数量平衡性能和吞吐量
- RabbitMQ: 配置镜像队列确保高可用
- 持久化消息存储防止数据丢失
- 监控消费者滞后(Consumer Lag)
有状态应用部署最佳实践
存储最佳实践
- 使用 PersistentVolume 和 PersistentVolumeClaim
- 选择合适的存储类型和访问模式
- 配置存储类 (StorageClass) 以实现动态供应
- 定期备份和恢复策略
网络最佳实践
- 使用 Headless Service 保持稳定的网络标识
- 配置正确的 Pod 亲和性和反亲和性
- 设置合理的健康检查探针
- 使用 NetworkPolicy 控制访问
常见部署问题与解决方案
| 问题 | 原因 | 解决方案 |
|---|---|---|
| Pod 无法启动 | PVC 绑定失败 | 检查 StorageClass 是否可用,PV 是否足够 |
| 数据丢失 | 存储卷配置错误 | 使用 volumeClaimTemplates 确保数据持久化 |
| 网络连接失败 | Headless Service 配置错误 | 确保 Service 配置正确,Pod 间网络通畅 |
| 启动顺序问题 | 缺少启动顺序控制 | 使用 init containers 或自定义启动脚本 |
| 性能问题 | 存储性能不足 | 使用高性能存储,优化 I/O 配置 |
数据库/中间件运维要点
监控与告警
- 数据库性能指标:连接数、查询延迟、QPS、TPS
- 存储空间使用率:磁盘空间、I/O 延迟
- 缓存命中率:Redis 命中率、内存使用
- 消息队列:队列长度、消费者滞后、吞吐量
- 集群健康状态:节点可用性、副本同步状态
备份与恢复
- 定期执行逻辑备份(mysqldump, pg_dump)
- 配置物理备份(WAL 归档、快照备份)
- 测试恢复流程确保备份有效性
- 配置备份保留策略
- 考虑跨区域备份以防灾难
安全配置
| 应用类型 | 安全配置要点 | 实施方法 |
|---|---|---|
| MySQL/PostgreSQL | 认证、授权、加密传输 | 使用 Secret 管理凭证,启用 SSL/TLS,配置角色权限 |
| Redis | 访问控制、网络隔离 | 设置密码认证,使用 NetworkPolicy 限制访问 |
| Kafka | SSL/TLS、SASL 认证 | 配置加密通信,启用用户认证和授权 |
| RabbitMQ | 用户管理、TLS 加密 | 创建专用用户,配置 SSL 证书,限制权限 |
部署验证
# 检查 StatefulSet 状态
kubectl get statefulsets
# 查看 Pod 状态
kubectl get pods -l app=mysql
# 检查持久化卷
kubectl get pvc -l app=mysql
# 测试数据库连接
kubectl run -it --rm debug --image=mysql:8.0 --restart=Never -- mysql -h mysql-0.mysql -uroot -p