HiHuo
首页
博客
手册
工具
关于
首页
博客
手册
工具
关于
  • 运维手册

    • Kubernetes 全栈实战与性能原理教程
    • 第一部分:Linux 基础与系统原理
    • 第二部分:Kubernetes 网络深度解析
    • 第三部分:Kubernetes 存储管理实战
    • 第四部分:Kubernetes 调度器深度解析
    • 第五部分:Kubernetes 性能调优实战
    • 第六部分:CNI 与 eBPF 网络深度实践
    • 第七部分:Kubernetes 生产级调优案例
    • 第八部分:命令速查与YAML模板库
    • 第九部分:实验环境快速搭建指南
    • 第十部分:面试题库与进阶路径
    • 第11章:Kubernetes 网络·存储·大文件排查专项手册

第三部分:Kubernetes 存储管理实战

从临时存储到持久化卷的完整存储体系

目录

  • 第5章:Kubernetes 存储抽象与 PV/PVC 机制
  • 第9章:存储类型与 CSI 驱动实战
  • 存储性能优化与测试
  • 存储排障完整案例
  • 实验环境搭建
  • 命令速查表

第5章:Kubernetes 存储抽象与 PV/PVC 机制

5.1 为什么需要持久化存储

容器默认的文件系统是临时的(ephemeral),一旦 Pod 被删除、重启或迁移,数据就会消失。

K8s 提供了三种方式来管理数据:

存储类型生命周期用途示例
EmptyDirPod 生命周期内临时缓存、共享空间编译缓存、临时文件
HostPath与宿主机目录绑定调试、本地卷日志收集、配置文件
PersistentVolume (PV)独立于 Pod数据库、日志、业务数据MySQL 数据、应用日志

5.2 容器文件系统的分层原理

在理解 K8s 存储之前,要先明白容器层文件系统的结构:

容器文件系统:
OverlayFS = 可写层 (Writable) + 镜像层 (Image Layers)

当你执行:

docker run -v /data:/data nginx

实际上挂载的是一个新的卷层叠加到容器可写层。

查看容器挂载:

docker inspect <container_id> | grep Mounts -A 10

5.3 Kubernetes Volume 类型总览

类型说明典型场景示例
emptyDirPod 临时存储缓存/中间文件编译缓存
hostPath宿主机目录调试/日志/配置日志收集
nfs网络文件系统共享数据共享存储
configMap挂载配置文件环境配置应用配置
secret加密凭据密钥、Token数据库密码
persistentVolumeClaim持久卷声明数据库、持久存储MySQL 数据
local节点本地盘高性能存储数据库存储

5.4 PV / PVC 的核心机制

Kubernetes 的持久化存储是通过 三层抽象 实现的:

Pod → PVC → PV → 存储后端(NFS、Ceph、Local、EBS...)

5.4.1 PersistentVolume(PV)

系统中定义好的实际存储资源。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  nfs:
    path: /data
    server: 192.168.1.100

5.4.2 PersistentVolumeClaim(PVC)

Pod 用于"申请"存储的声明。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mypvc
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 5Gi

Kubernetes 会自动匹配符合条件的 PV。

5.4.3 Pod 使用 PVC

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: app
    image: nginx
    volumeMounts:
      - mountPath: /usr/share/nginx/html
        name: mydata
  volumes:
    - name: mydata
      persistentVolumeClaim:
        claimName: mypvc

5.5 PV 生命周期与回收策略

阶段说明状态
Available可用 PV等待绑定
Bound已绑定某个 PVC正在使用
ReleasedPVC 已删除,但数据未清除等待回收
Failed无法使用或错误状态需要人工处理

回收策略:

策略说明适用场景
Retain手动删除数据数据库卷、重要数据
Recycle清空数据(已废弃)已废弃
Delete自动删除后端卷云盘、临时数据

5.6 StorageClass 与动态卷分配

5.6.1 StorageClass 定义

StorageClass 定义了"存储供应方式":

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp3
  fsType: ext4
reclaimPolicy: Delete
volumeBindingMode: Immediate

5.6.2 PVC 自动绑定 StorageClass

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mypvc
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: fast
  resources:
    requests:
      storage: 10Gi

当 PVC 创建时,系统会:

  1. 根据 storageClassName 调用 provisioner
  2. 自动创建 PV
  3. 自动绑定

5.7 存储访问模式(Access Modes)

模式含义适用场景示例
ReadWriteOnce (RWO)单节点读写大多数应用数据库、应用数据
ReadOnlyMany (ROX)多节点只读配置共享配置文件、只读数据
ReadWriteMany (RWX)多节点读写NFS / CephFS共享存储、日志
ReadWriteOncePod (RWOP)单Pod独占高一致性数据库单实例数据库

第9章:存储类型与 CSI 驱动实战

9.1 常见存储类型与实现

类型机制优点缺点适用场景
HostPath挂载宿主机路径简单不可迁移调试、单节点
NFS网络文件系统共享读写性能一般共享存储
CephFS / RBD分布式存储高可用维护复杂生产环境
Local Path本地盘绑定高性能不可调度高性能应用
GlusterFS块分布式存储弹性扩展运维成本高大规模存储
EBS / OSS / CSI云盘存储自动化受限于云厂商云环境

9.2 CSI(Container Storage Interface)机制

CSI 是容器存储的标准接口(类似 CNI 之于网络)。

9.2.1 CSI 架构

Kubelet
  ↕
  CSI Driver (Node + Controller)
  ↕
  存储后端(NFS、Ceph、EBS、NAS...)

9.2.2 工作流程

  1. Pod 申请 PVC
  2. kubelet 调用 CSI Node 插件
  3. 创建卷并挂载到容器
  4. 卷生命周期与 PVC 绑定

9.2.3 典型 CSI 插件

插件存储后端特点适用场景
csi-hostpath本地路径简单开发测试
csi-nfsNFS共享存储小规模生产
csi-cephfsCephFS分布式大规模生产
csi-aws-ebsAWS EBS云存储AWS 环境
alibaba-cloud-csi阿里云盘云存储阿里云环境

存储性能优化与测试

性能测试工具:fio

fio 是专业的 I/O 性能测试工具,支持多种 I/O 模式。

基础 fio 测试

# 随机读测试
fio --name=randread --filename=/data/test.file --bs=4k --iodepth=32 --rw=randread --numjobs=4 --time_based --runtime=60 --group_reporting

# 随机写测试
fio --name=randwrite --filename=/data/test.file --bs=4k --iodepth=32 --rw=randwrite --numjobs=4 --time_based --runtime=60 --group_reporting

# 混合读写测试
fio --name=mixed --filename=/data/test.file --bs=4k --iodepth=32 --rw=randrw --rwmixread=70 --numjobs=4 --time_based --runtime=60 --group_reporting

在 Kubernetes 中运行 fio 测试

apiVersion: v1
kind: Pod
metadata:
  name: fio-test
spec:
  containers:
  - name: fio
    image: nixery.dev/shell/fio
    command: ["sh", "-c"]
    args:
    - |
      fio --name=randread \
          --filename=/data/test.file \
          --bs=4k \
          --iodepth=32 \
          --rw=randread \
          --numjobs=4 \
          --time_based \
          --runtime=60 \
          --group_reporting
    volumeMounts:
    - name: test-volume
      mountPath: /data
  volumes:
  - name: test-volume
    persistentVolumeClaim:
      claimName: test-pvc

存储性能优化方向

优化点建议命令示例
IO 性能使用本地 SSD 或 Cephfio --rw=randread
网络延迟挂载同可用区节点kubectl get nodes -o wide
并发写入避免 RWX 并发数据库使用 RWO 模式
缓存使用 emptyDir + 内存模式emptyDir: { medium: Memory }
文件系统使用 ext4/XFS,禁用 journalingmkfs.xfs /dev/sdb
Cloud Storage合理设置 IOPS / 吞吐配额云控制台配置

存储排障完整案例

案例1:PVC 一直 Pending

问题描述

PVC 创建后一直处于 Pending 状态,无法绑定到 PV。

排查步骤

#!/bin/bash
# PVC Pending 排查脚本

PVC_NAME="my-pvc"
echo "=== PVC Pending 排查 ==="

# 1. 查看 PVC 状态
echo "1. 查看 PVC 状态:"
kubectl get pvc $PVC_NAME -o yaml

# 2. 查看 PVC 事件
echo "2. 查看 PVC 事件:"
kubectl describe pvc $PVC_NAME

# 3. 查看 StorageClass
echo "3. 查看 StorageClass:"
kubectl get storageclass
kubectl describe storageclass

# 4. 查看可用 PV
echo "4. 查看可用 PV:"
kubectl get pv

# 5. 检查 CSI 驱动状态
echo "5. 检查 CSI 驱动状态:"
kubectl get pods -n kube-system | grep -E "(csi|storage)"

# 6. 查看 CSI 驱动日志
echo "6. 查看 CSI 驱动日志:"
kubectl logs -n kube-system -l app=csi-driver --tail=50

# 7. 检查节点存储
echo "7. 检查节点存储:"
kubectl get nodes -o jsonpath='{.items[0].status.addresses[0].address}' | xargs -I {} ssh {} "df -h"

# 8. 检查存储配额
echo "8. 检查存储配额:"
kubectl describe quota --all-namespaces

案例2:Pod 挂载失败

问题描述

Pod 启动时无法挂载存储卷,显示挂载失败错误。

排查步骤

#!/bin/bash
# Pod 挂载失败排查脚本

POD_NAME="my-pod"
echo "=== Pod 挂载失败排查 ==="

# 1. 查看 Pod 状态
echo "1. 查看 Pod 状态:"
kubectl get pod $POD_NAME -o wide

# 2. 查看 Pod 事件
echo "2. 查看 Pod 事件:"
kubectl describe pod $POD_NAME

# 3. 查看 Pod 日志
echo "3. 查看 Pod 日志:"
kubectl logs $POD_NAME

# 4. 检查 PVC 状态
echo "4. 检查 PVC 状态:"
kubectl get pvc
kubectl describe pvc

# 5. 检查 PV 状态
echo "5. 检查 PV 状态:"
kubectl get pv
kubectl describe pv

# 6. 检查节点存储
echo "6. 检查节点存储:"
NODE_NAME=$(kubectl get pod $POD_NAME -o jsonpath='{.spec.nodeName}')
kubectl get nodes -o jsonpath='{.items[0].status.addresses[0].address}' | xargs -I {} ssh {} "df -h"

# 7. 检查挂载点
echo "7. 检查挂载点:"
kubectl get nodes -o jsonpath='{.items[0].status.addresses[0].address}' | xargs -I {} ssh {} "mount | grep -E '(nfs|ceph|local)'"

# 8. 检查 CSI 驱动日志
echo "8. 检查 CSI 驱动日志:"
kubectl logs -n kube-system -l app=csi-driver --tail=100

案例3:存储性能问题

问题描述

应用访问存储时延迟过高,I/O 性能不满足要求。

排查步骤

#!/bin/bash
# 存储性能问题排查脚本

echo "=== 存储性能问题排查 ==="

# 1. 创建性能测试 Pod
kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: storage-test
spec:
  containers:
  - name: test
    image: nixery.dev/shell/fio
    command: ["sh", "-c"]
    args:
    - |
      echo "开始存储性能测试..."
      fio --name=randread \
          --filename=/data/test.file \
          --bs=4k \
          --iodepth=32 \
          --rw=randread \
          --numjobs=4 \
          --time_based \
          --runtime=30 \
          --group_reporting
    volumeMounts:
    - name: test-volume
      mountPath: /data
  volumes:
  - name: test-volume
    persistentVolumeClaim:
      claimName: test-pvc
EOF

# 2. 等待 Pod 就绪
kubectl wait --for=condition=Ready pod storage-test --timeout=60s

# 3. 运行性能测试
echo "3. 运行性能测试:"
kubectl exec storage-test -- fio --name=randread --filename=/data/test.file --bs=4k --iodepth=32 --rw=randread --numjobs=4 --time_based --runtime=30 --group_reporting

# 4. 检查节点 I/O 状态
echo "4. 检查节点 I/O 状态:"
kubectl get nodes -o jsonpath='{.items[0].status.addresses[0].address}' | xargs -I {} ssh {} "iostat -x 1 5"

# 5. 检查网络延迟(NFS)
echo "5. 检查网络延迟:"
kubectl exec storage-test -- ping -c 10 nfs-server

# 6. 检查文件系统类型
echo "6. 检查文件系统类型:"
kubectl exec storage-test -- df -T /data

# 7. 检查 I/O 调度器
echo "7. 检查 I/O 调度器:"
kubectl get nodes -o jsonpath='{.items[0].status.addresses[0].address}' | xargs -I {} ssh {} "cat /sys/block/sda/queue/scheduler"

# 8. 清理测试 Pod
kubectl delete pod storage-test

实验环境搭建

快速搭建脚本

#!/bin/bash
# Kubernetes 存储实验环境搭建脚本

set -e

echo "开始搭建 Kubernetes 存储实验环境..."

# 1. 创建实验集群
kind create cluster --name storage-test --config - <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
- role: worker
networking:
  podSubnet: "10.244.0.0/16"
  serviceSubnet: "10.96.0.0/12"
EOF

# 2. 等待集群就绪
kubectl wait --for=condition=Ready node --all --timeout=60s

# 3. 安装 NFS 服务器(用于测试)
kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nfs-server
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nfs-server
  template:
    metadata:
      labels:
        app: nfs-server
    spec:
      containers:
      - name: nfs-server
        image: k8s.gcr.io/volume-nfs:0.8
        ports:
        - containerPort: 2049
        volumeMounts:
        - name: nfs-data
          mountPath: /exports
      volumes:
      - name: nfs-data
        emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
  name: nfs-server
spec:
  selector:
    app: nfs-server
  ports:
  - port: 2049
    targetPort: 2049
EOF

# 4. 等待 NFS 服务器就绪
kubectl wait --for=condition=Ready pod -l app=nfs-server --timeout=60s

# 5. 创建 NFS PV
kubectl apply -f - <<EOF
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  nfs:
    server: nfs-server
    path: /exports
EOF

# 6. 创建 NFS StorageClass
kubectl apply -f - <<EOF
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
EOF

# 7. 安装测试工具
kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: storage-tools
spec:
  replicas: 1
  selector:
    matchLabels:
      app: storage-tools
  template:
    metadata:
      labels:
        app: storage-tools
    spec:
      containers:
      - name: tools
        image: nixery.dev/shell/fio
        command: ["sleep", "3600"]
EOF

echo "Kubernetes 存储实验环境搭建完成!"
echo "运行 'kubectl get pv' 查看 PV 状态"
echo "运行 'kubectl get pvc' 查看 PVC 状态"

测试用例集合

# 创建测试用例
kubectl apply -f - <<EOF
# 测试用例1:基础 PVC 绑定
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: test-pvc-1
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: nfs-storage
---
# 测试用例2:多访问模式 PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: test-pvc-2
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 2Gi
  storageClassName: nfs-storage
---
# 测试用例3:大容量 PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: test-pvc-3
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  storageClassName: nfs-storage
EOF

命令速查表

存储管理命令

命令功能示例
kubectl get pv查看 PVkubectl get pv
kubectl get pvc查看 PVCkubectl get pvc
kubectl get storageclass查看 StorageClasskubectl get storageclass
kubectl describe pv <pv>查看 PV 详细信息kubectl describe pv nfs-pv
kubectl describe pvc <pvc>查看 PVC 详细信息kubectl describe pvc test-pvc
kubectl describe storageclass <sc>查看 StorageClass 详细信息kubectl describe storageclass nfs-storage

存储测试命令

命令功能示例
fio --name=test --filename=/data/test.file --bs=4k --iodepth=32 --rw=randread --numjobs=4 --time_based --runtime=60 --group_reporting随机读测试在 Pod 中运行
fio --name=test --filename=/data/test.file --bs=4k --iodepth=32 --rw=randwrite --numjobs=4 --time_based --runtime=60 --group_reporting随机写测试在 Pod 中运行
fio --name=test --filename=/data/test.file --bs=4k --iodepth=32 --rw=randrw --rwmixread=70 --numjobs=4 --time_based --runtime=60 --group_reporting混合读写测试在 Pod 中运行
dd if=/dev/zero of=/data/test.file bs=1M count=1000顺序写测试在 Pod 中运行
dd if=/data/test.file of=/dev/null bs=1M顺序读测试在 Pod 中运行

系统存储命令

命令功能示例
df -h查看磁盘使用情况df -h
lsblk查看块设备lsblk
mount查看挂载点mount
iostat -x 1查看 I/O 统计iostat -x 1
iotop查看 I/O 进程iotop
du -sh <path>查看目录大小du -sh /data

存储排障命令

命令功能示例
kubectl get events --sort-by=.lastTimestamp查看事件kubectl get events --sort-by=.lastTimestamp
kubectl logs -n kube-system -l app=csi-driver查看 CSI 驱动日志kubectl logs -n kube-system -l app=csi-driver
kubectl describe pod <pod>查看 Pod 详细信息kubectl describe pod my-pod
kubectl exec -it <pod> -- sh进入 Pod 执行命令kubectl exec -it my-pod -- sh

Prev
第二部分:Kubernetes 网络深度解析
Next
第四部分:Kubernetes 调度器深度解析