16.5.6 本地存储与网络存储实践
本节聚焦生产环境中常见的本地存储与网络存储落地方式,覆盖选型、部署、使用与运维要点,强调性能、可用性与数据安全的权衡,并提供安装、命令、排错与练习示例。
一、本地存储(Local)实践
原理草图(本地PV与调度绑定)
- 适用场景:高性能、低延迟、数据可重建或可容忍节点级故障(如缓存、日志、临时计算数据、部分数据库热数据)。
- 实现方式:
local卷 +nodeAffinity(生产建议)。hostPath(仅开发测试,易误删/误挂载)。- 关键注意点:
- 调度约束:PVC 绑定后 Pod 必须调度到同一节点。
- 故障处理:节点故障导致数据不可用,需应用层副本或重建。
- 生命周期:结合 LVM/RAID,统一挂载点和命名规范。
安装与配置示例:Local PV 静态供给
1) 准备节点本地磁盘与目录
# 在 Node A 上执行
sudo mkdir -p /data/local1
sudo chmod 777 /data/local1
# 可选:通过 fstab 挂载独立磁盘到 /data/local1
2) 创建 StorageClass(禁止动态供给)
# /etc/k8s/manifests/sc-local.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: local-static
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
3) 创建 Local PV(绑定 Node A)
# /etc/k8s/manifests/pv-local.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-local-1
spec:
capacity:
storage: 20Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: local-static
local:
path: /data/local1
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- node-a
4) 创建 PVC 与 Pod(自动绑定)
# /etc/k8s/manifests/pvc-local.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-local-1
spec:
accessModes:
- ReadWriteOnce
storageClassName: local-static
resources:
requests:
storage: 10Gi
---
# /etc/k8s/manifests/pod-local.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-local
spec:
containers:
- name: app
image: busybox
command: ["sh", "-c", "echo local > /data/flag && sleep 3600"]
volumeMounts:
- mountPath: /data
name: data
volumes:
- name: data
persistentVolumeClaim:
claimName: pvc-local-1
5) 应用并验证
kubectl apply -f /etc/k8s/manifests/sc-local.yaml
kubectl apply -f /etc/k8s/manifests/pv-local.yaml
kubectl apply -f /etc/k8s/manifests/pvc-local.yaml
kubectl apply -f /etc/k8s/manifests/pod-local.yaml
kubectl get pv,pvc,pod -o wide
# 预期:PVC Bound,Pod 调度到 node-a
命令解释
- volumeBindingMode: WaitForFirstConsumer:延迟绑定,避免跨区调度。
- nodeAffinity:指定 PV 所在节点,确保 Pod 与 PV 同节点。
常见排错(本地存储)
- PVC Pending:检查 StorageClass 是否为 no-provisioner,PV 是否满足容量/SC。
- Pod Pending:检查节点标签与 nodeAffinity 是否匹配。
- 挂载失败:kubectl describe pod pod-local 查看事件,检查节点目录权限。
二、网络存储实践(NFS/iSCSI/分布式存储)
原理草图(NFS 共享存储)
- 适用场景:多节点共享、跨节点调度、有状态应用。
- 常见方案:
- NFS:部署简单,适合中小规模。
- iSCSI:块存储性能较好,但运维复杂。
- 分布式存储:Ceph/Rook/Longhorn,高可用与弹性扩展。
安装与配置示例:NFS 服务器 + 静态 PV
1) NFS 服务器安装与导出
# 在 NFS Server 上
sudo yum install -y nfs-utils
sudo mkdir -p /export/k8s
sudo chmod 777 /export/k8s
# /etc/exports
/export/k8s *(rw,sync,no_root_squash)
sudo systemctl enable --now nfs-server
sudo exportfs -rv
2) 在 K8s 中创建 NFS PV 与 PVC
# /etc/k8s/manifests/pv-nfs.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-nfs-1
spec:
capacity:
storage: 50Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
nfs:
server: 10.0.0.10
path: /export/k8s
---
# /etc/k8s/manifests/pvc-nfs.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-nfs-1
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Gi
3) 挂载验证
# /etc/k8s/manifests/pod-nfs.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-nfs
spec:
containers:
- name: app
image: busybox
command: ["sh", "-c", "echo nfs > /data/flag && sleep 3600"]
volumeMounts:
- mountPath: /data
name: data
volumes:
- name: data
persistentVolumeClaim:
claimName: pvc-nfs-1
kubectl apply -f /etc/k8s/manifests/pv-nfs.yaml
kubectl apply -f /etc/k8s/manifests/pvc-nfs.yaml
kubectl apply -f /etc/k8s/manifests/pod-nfs.yaml
kubectl exec -it pod-nfs -- cat /data/flag
# 预期输出:nfs
命令解释
- ReadWriteMany:允许多 Pod 跨节点读写。
- no_root_squash:避免容器内 root 写入受限(生产需谨慎)。
常见排错(NFS)
- mount.nfs: access denied:检查 /etc/exports 与 exportfs -rv。
- Pod 卡在 ContainerCreating:检查节点是否安装 nfs-utils。
- IO 慢:检查存储网络、NFS 线程/缓存参数。
三、本地与网络存储选型对比
- 性能:本地存储优于网络存储。
- 可用性:网络存储支持跨节点,容灾能力更强。
- 复杂度:本地存储运维简单;分布式网络存储复杂。
- 适配应用:数据库/状态服务优先网络存储;缓存/日志可选本地存储。
四、生产最佳实践(含命令)
1) 存储类型与数据等级匹配
kubectl label pvc pvc-nfs-1 data-tier=gold
kubectl label pvc pvc-local-1 data-tier=silver
2) 性能基线与告警
# 使用 fio 简易压测(在挂载 Pod 中)
kubectl exec -it pod-nfs -- sh -c "fio -name=randrw -rw=randrw -size=1G -bs=4k -runtime=30 -numjobs=1 -direct=1 -ioengine=libaio"
3) 统一命名规范
# 约定:pv-<app>-<env>-<idx>
kubectl get pv -o name | grep pv-
4) 备份与恢复演练
# 示例:打包并导出 NFS 数据
kubectl exec -it pod-nfs -- tar czf /data/backup.tar.gz /data
五、常见问题与处理思路(含排错命令)
- PVC Pending
kubectl describe pvc pvc-local-1
kubectl get storageclass
# 排查:StorageClass 名称不一致、PV 容量不足、provisioner 不可用
- 挂载失败
kubectl describe pod pod-nfs
kubectl logs -n kube-system <csi-plugin-pod>
# 排查:NFS 服务、CSI 驱动、节点依赖包
- IO 性能不足
kubectl top node
kubectl exec -it pod-nfs -- iostat -xm 2 3
# 排查:存储后端瓶颈、网络拥塞、Pod 资源限制
- 数据丢失风险
kubectl get pv pv-local-1 -o jsonpath='{.spec.persistentVolumeReclaimPolicy}{"\n"}'
# 建议:本地存储使用 Retain,并明确业务重建/备份策略
六、练习题
1) 使用本地 PV 创建一个 5Gi PVC,并确保 Pod 被调度到指定节点。
2) 搭建 NFS 服务并让两个 Pod 同时写入同一目录,验证 RWX。
3) 故意将 NFS 服务停掉,观察 Pod 事件并记录排错步骤。
4) 为 PVC 添加 data-tier 标签,并输出带标签的 PVC 列表。