存储最佳实践
学习目标
- 掌握生产环境的存储配置最佳实践
- 了解存储安全和权限管理
- 学会存储监控和故障排查
核心实践
1. 存储类规划
推荐的 StorageClass 分层:
┌─────────────────────────────────────────┐
│ 存储类分层 │
│ │
│ ┌─────────────────────────────────────┐│
│ │ fast-ssd(高性能) ││
│ │ - io2/gp3 SSD ││
│ │ - 数据库、关键应用 ││
│ │ - 成本:高 ││
│ └─────────────────────────────────────┘│
│ │
│ ┌─────────────────────────────────────┐│
│ │ standard(标准) ││
│ │ - gp3/standard 磁盘 ││
│ │ - 一般应用 ││
│ │ - 成本:中 ││
│ └─────────────────────────────────────┘│
│ │
│ ┌─────────────────────────────────────┐│
│ │ cold-storage(冷存储) ││
│ │ - st1/standard HDD ││
│ │ - 日志、归档 ││
│ │ - 成本:低 ││
│ └─────────────────────────────────────┘│
└─────────────────────────────────────────┘
# 生产环境 StorageClass 定义
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-ssd
annotations:
storageclass.kubernetes.io/is-default-class: "false"
provisioner: ebs.csi.aws.com
parameters:
type: io2
iops: "10000"
fsType: ext4
encrypted: "true"
reclaimPolicy: Retain # 生产环境用 Retain
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: standard
annotations:
storageclass.kubernetes.io/is-default-class: "true" # 设为默认
provisioner: ebs.csi.aws.com
parameters:
type: gp3
fsType: ext4
encrypted: "true"
reclaimPolicy: Retain
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
2. 访问模式选择
选择原则:
ReadWriteOnce (RWO):
✓ 数据库(MySQL、PostgreSQL)
✓ 单实例应用
✓ 块存储默认支持
ReadWriteMany (RWX):
✓ 共享文件存储
✓ CMS 媒体文件
✓ 多 Pod 需要读写同一目录
✗ 不适合数据库
ReadOnlyMany (ROX):
✓ 配置文件共享
✓ 静态资源
✓ 只读数据
ReadWriteOncePod (RWOP):
✓ 严格单 Pod 访问
✓ K8s 1.22+ 支持
✓ 最强一致性保证
3. 容量规划
容量规划公式:
总容量 = 数据量 + 增长预留 + 日志空间
示例(数据库):
当前数据:50GB
年增长:30%
预留空间:20%
日志空间:10GB
总容量 = 50GB + 50GB×30%×2年 + 50GB×20% + 10GB
= 50GB + 30GB + 10GB + 10GB
= 100GB
建议:
- 初始不要分配过大
- 使用 allowVolumeExpansion: true
- 监控使用率,及时扩容
4. 安全配置
# 加密存储
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: encrypted-sc
provisioner: ebs.csi.aws.com
parameters:
type: gp3
encrypted: "true" # 启用加密
kmsKeyId: "arn:aws:kms:..." # 指定 KMS 密钥
---
# RBAC 控制 PVC 创建权限
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pvc-creator
rules:
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["create", "get", "list", "watch"]
---
# NetworkPolicy 限制存储访问(NFS 场景)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: nfs-access
spec:
podSelector:
matchLabels:
app: nfs-client
policyTypes:
- Egress
egress:
- to:
- ipBlock:
cidr: 10.0.0.0/24 # NFS 服务器网段
ports:
- port: 2049 # NFS 端口
5. 监控和告警
# Prometheus 监控规则
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: storage-alerts
spec:
groups:
- name: storage
rules:
# PVC 使用率告警
- alert: PVCUsageHigh
expr: |
kubelet_volume_stats_used_bytes / kubelet_volume_stats_capacity_bytes > 0.85
for: 5m
labels:
severity: warning
annotations:
summary: "PVC {{ $labels.persistentvolumeclaim }} 使用率超过 85%"
# PVC 使用率严重告警
- alert: PVCUsageCritical
expr: |
kubelet_volume_stats_used_bytes / kubelet_volume_stats_capacity_bytes > 0.95
for: 5m
labels:
severity: critical
annotations:
summary: "PVC {{ $labels.persistentvolumeclaim }} 使用率超过 95%"
# PV 状态异常
- alert: PVStatusAbnormal
expr: kube_persistentvolume_status_phase{phase=~"Failed|Released"} > 0
for: 1m
labels:
severity: warning
# 查看 PVC 使用率
kubectl top pvc
# 查看 PV 状态
kubectl get pv
# 查看存储相关事件
kubectl get events --field-selector reason=FailedMount
6. 备份策略
备份层次:
┌─────────────────────────────────────────┐
│ 备份策略 │
│ │
│ ┌─────────────────────────────────────┐│
│ │ L1: VolumeSnapshot(快照) ││
│ │ - 频率:每小时/每天 ││
│ │ - 保留:7-30 天 ││
│ │ - 用途:快速恢复 ││
│ └─────────────────────────────────────┘│
│ │
│ ┌─────────────────────────────────────┐│
│ │ L2: 应用级备份 ││
│ │ - mysqldump / pg_dump ││
│ │ - 频率:每天 ││
│ │ - 保留:90 天 ││
│ │ - 用途:逻辑恢复、跨版本迁移 ││
│ └─────────────────────────────────────┘│
│ │
│ ┌─────────────────────────────────────┐│
│ │ L3: 集群级备份(Velero) ││
│ │ - 频率:每周 ││
│ │ - 保留:1 年 ││
│ │ - 用途:灾难恢复、集群迁移 ││
│ └─────────────────────────────────────┘│
└─────────────────────────────────────────┘
# 定时快照 CronJob
apiVersion: batch/v1
kind: CronJob
metadata:
name: volume-snapshot-cron
spec:
schedule: "0 */6 * * *" # 每 6 小时
jobTemplate:
spec:
template:
spec:
serviceAccountName: snapshot-creator
containers:
- name: snapshot
image: bitnami/kubectl
command:
- /bin/sh
- -c
- |
cat <<EOF | kubectl apply -f -
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
name: mysql-snapshot-$(date +%Y%m%d-%H%M%S)
namespace: database
spec:
volumeSnapshotClassName: csi-snapclass
source:
persistentVolumeClaimName: mysql-data-mysql-0
EOF
restartPolicy: OnFailure
7. 故障排查
# 常见问题排查流程
# 1. PVC 一直处于 Pending
kubectl describe pvc <pvc-name>
# 检查:
# - StorageClass 是否存在
# - 是否有匹配的 PV
# - 容量是否满足
# 2. Pod 无法挂载 Volume
kubectl describe pod <pod-name>
kubectl get events --field-selector involvedObject.name=<pod-name>
# 检查:
# - PVC 是否 Bound
# - CSI Driver 是否正常
# - 节点是否有存储访问权限
# 3. 存储性能问题
# 检查 IOPS 和吞吐量
kubectl exec <pod> -- fio --name=test --ioengine=libaio --rw=randread --bs=4k --numjobs=1 --size=1G --runtime=60
# 4. 磁盘空间不足
kubectl exec <pod> -- df -h
# 扩容 PVC 或清理数据
8. 成本优化
成本优化策略:
1. 选择合适的存储类型
- 不是所有数据都需要 SSD
- 日志和归档用 HDD
2. 设置合理的回收策略
- 开发/测试环境:Delete(自动清理)
- 生产环境:Retain(手动管理)
3. 使用 WaitForFirstConsumer
- 避免创建未使用的 PV
4. 定期清理未使用的 PV/PVC
kubectl get pvc --all-namespaces | grep Bound
kubectl get pv | grep Available
5. 监控存储使用率
- 删除不再使用的 PVC
- 缩容过度分配的存储
6. 使用存储分层
- 热数据:SSD
- 温数据:标准磁盘
- 冷数据:归档存储
实践练习
练习 1:创建生产级 StorageClass
# 为不同应用场景创建存储类
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-ssd
provisioner: ebs.csi.aws.com
parameters:
type: gp3
iopsPerGB: "50"
fsType: ext4
encrypted: "true"
reclaimPolicy: Retain
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: standard-hdd
provisioner: ebs.csi.aws.com
parameters:
type: st1
fsType: ext4
encrypted: "true"
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
练习 2:配置存储监控
# 查看 PVC 使用情况
kubectl get pvc -A -o custom-columns=\
NAMESPACE:.metadata.namespace,\
NAME:.metadata.name,\
STATUS:.status.phase,\
VOLUME:.spec.volumeName,\
CAPACITY:.spec.resources.requests.storage
# 查看 PV 使用率(需要 metrics-server)
kubectl top pv
练习 3:模拟故障恢复
# 1. 创建测试数据
kubectl exec mysql-0 -- mysql -uroot -ppassword123 -e "CREATE DATABASE disaster_test; USE disaster_test; CREATE TABLE t1(data VARCHAR(100)); INSERT INTO t1 VALUES('backup_test');"
# 2. 创建快照
kubectl apply -f - <<EOF
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
name: disaster-backup
spec:
volumeSnapshotClassName: csi-snapclass
source:
persistentVolumeClaimName: mysql-data-mysql-0
EOF
# 3. 模拟数据丢失
kubectl exec mysql-0 -- mysql -uroot -ppassword123 -e "DROP DATABASE disaster_test;"
# 4. 从快照恢复
# ... 创建新 PVC 并验证恢复
常见误解
1. 默认 StorageClass 不一定是最佳选择
默认 StorageClass 可能使用 Delete 回收策略
生产环境应明确指定 StorageClass
不要依赖集群默认配置
2. 大容量不等于高性能
IOPS 和吞吐量与容量相关但不是线性关系
高 IOPS 场景需要选择支持预配置 IOPS 的存储类型
容量规划和性能规划要分开考虑
小结
| 要点 | 说明 |
|---|---|
| 存储分层 | 按场景选择 SSD/HDD/冷存储 |
| 安全配置 | 加密、RBAC、网络策略 |
| 备份策略 | 快照 + 应用备份 + 集群备份 |
| 监控告警 | PVC 使用率、PV 状态 |
| 故障排查 | 描述资源、查看事件、检查 CSI |
| 成本优化 | 合理选择、定期清理、使用分层 |
练习编辑器
bash
Loading...