有状态容器管理
有状态容器(数据库、缓存)与无状态容器(Web、API)管理差异大,下面介绍方法。
有状态 vs 无状态
对比
| 维度 | 无状态 | 有状态 |
|---|---|---|
| 数据持久化 | 不需要 | 必须 |
| 水平扩展 | 简单 | 复杂 |
| 故障恢复 | 快速 | 需数据恢复 |
| 身份标识 | 无 | 有(节点 ID) |
| 示例 | Web、API | DB、Redis、Kafka |
数据持久化
Volume 配置
YAML
services:
mysql:
image: mysql:8.0
volumes:
- db-data:/var/lib/mysql # 持久化数据
volumes:
db-data:
driver: local
备份策略
Bash
# 定期备份
docker exec mysql mysqldump -uroot -p123456 --all-databases > backup.sql
# 恢复到新卷
docker volume create db-restored
docker run --rm -v db-restored:/data -v $(pwd):/backup alpine \
tar xzf /backup/db-data.tar.gz -C /data
数据一致性
主从复制
YAML
# MySQL 主从
services:
master:
image: mysql:8.0
command: >
--server-id=1
--log-bin=mysql-bin
--binlog-format=ROW
slave:
image: mysql:8.0
command: >
--server-id=2
--relay-log=relay-bin
depends_on:
- master
集群模式
YAML
# Redis Cluster
services:
redis-node1:
image: redis:7
command: redis-server --cluster-enabled yes --cluster-config-file nodes.conf
redis-node2:
image: redis:7
command: redis-server --cluster-enabled yes --cluster-config-file nodes.conf
身份标识
StatefulSet (K8s)
YAML
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
serviceName: mysql
replicas: 3
template:
spec:
containers:
- name: mysql
image: mysql:8.0
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10Gi
StatefulSet 保证 Pod 名称有序(mysql-0, mysql-1, mysql-2),每个 Pod 有独立 PVC。
节点 ID
Bash
# 有状态容器需要稳定标识
# MySQL: server-id
# Redis: node-id
# Kafka: broker.id
# 配置固定 ID
docker run -d \
-e MYSQL_SERVER_ID=1 \
mysql:8.0
扩缩容
无状态容器
Bash
# 简单扩展
docker compose up -d --scale app=5
# 负载均衡自动分发
有状态容器
Bash
# 复杂扩展(需重新分片)
# MySQL: 添加从节点
# Redis: 重新分配 slot
# Kafka: 重新分配 partition
# 需要手动或工具介入
故障恢复
无状态容器
Bash
# 快速重建
docker compose up -d --force-recreate app
# 无数据丢失
有状态容器
Bash
# 从备份恢复
docker volume create db-restored
# 恢复数据...
# 或从副本同步
# MySQL: CHANGE MASTER TO...
# Redis: REPLICAOF
要点总结
- 无状态容器易于扩展,有状态容器需要数据持久化和一致性管理
- Volume 实现有状态容器数据持久化,删除容器数据不丢失
- 主从复制和集群模式实现数据高可用
- StatefulSet 保证有状态容器身份标识稳定有序
- 有状态容器扩缩容需要重新分片,比无状态复杂
📝 发现内容有误?点击此处直接编辑