找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

2295

积分

0

好友

321

主题
发表于 2025-12-25 05:21:58 | 查看: 34| 回复: 0

在Kubernetes中,为Pod提供稳定、可靠的存储是构建健壮应用的关键。Kubernetes的存储模型多样,从简单的临时存储到复杂的动态持久化存储,以满足不同场景下的需求。

1. Kubernetes存储分类

K8S存储分类

存储主要分为以下几类:

  • 临时存储:例如 emptyDir
  • 半持久化存储:例如 hostPath
  • 持久化存储
    • 私有云存储:如 NFS、Ceph、GlusterFS
    • 公有云存储:如 AWS EBS、Google Persistent Disk、Azure Disk

2. emptyDir — 临时存储

① 什么是 emptyDir?

当Pod的存储方案设置为emptyDir时,Pod启动后会在其所在节点上创建一个空卷。Pod内容器产生的数据可以读写此卷。该卷的生命周期与Pod绑定,一旦Pod被删除,这个临时卷及其数据也会被一并销毁

② emptyDir 的用途

主要用于充当不需要数据持久化的临时存储空间,例如某些缓存或中间计算结果。

③ emptyDir 配置示例

# emptydir.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: dev
---
apiVersion: v1
kind: Pod
metadata:
  name: test-emptydir
  namespace: dev
spec:
  containers:
  - image: nginx:1.20.0
    name: test-emptydir
    volumeMounts:
    - mountPath: /usr/share/nginx/html # 挂载到容器内的路径
      name: cache-volume
  volumes:
  - name: cache-volume
    emptyDir: {} # 指定存储方式为 emptyDir

3. hostPath — 半持久化存储

① 什么是 hostPath?

hostPath类型卷将节点宿主机上的文件或目录映射到Pod内部。其功能类似于Docker的-v目录映射。
关键限制:由于Pod可能在集群节点间漂移,而hostPath卷只能访问特定节点上的路径,当Pod漂移到其他节点时,将无法访问原有数据,因此它只是一种半持久化的存储方式。

② hostPath 用途

  • 当容器需要访问Docker守护进程内部结构时,例如映射/var/lib/docker
  • 在容器中运行cAdvisor时,映射/dev/cgroups

③ hostPath 配置示例

# hostpath.yaml
apiVersion: v1
kind: Pod
metadata:
  name: test-hostpath
  namespace: dev
spec:
  containers:
  - name: test-hostpath
    image: nginx:1.20.0
    hostname: test-hostpath
    volumeMounts:
    - name: test-hostpath-volume  # 卷名称
      mountPath: /usr/share/nginx/html   # 挂载到容器的路径
  volumes:
  - name: test-hostpath-volume
    hostPath:
      path: /data               # 宿主机节点上的目录路径
      type: DirectoryOrCreate   # 路径类型,如果不存在则创建目录

参数说明

  • spec.volumes: 定义挂载到宿主机的目录。
    volumes配置
  • hostPath.type 枚举值:
    hostPath.type枚举值
  • containers.volumeMounts: 定义挂载到Pod内容器的路径。
    volumeMounts配置

4. PV 和 PVC 概念

emptyDirHostPath都无法解决节点宕机或Pod在其它节点重建时的数据持久化问题。解决方案是使用集群外部的独立存储服务,并通过PersistentVolume (PV)PersistentVolumeClaim (PVC) 机制进行管理。

① PV 是什么?

PV是集群中的一块独立存储资源,由管理员预先创建。它抽象了底层存储细节(如NFS、Ceph、云硬盘),并定义了容量、访问模式等属性。PV的生命周期独立于Pod。

PV支持的后端存储类型非常丰富,包括Ceph、GlusterFS、各种公有云块存储(AWS EBS, GCE PD, Azure Disk)、iSCSI以及本地存储(Local)等。

② PVC 是什么?

PVC是用户(或Pod)对存储资源的声明。它指定了所需的存储大小和访问模式,而不关心底层具体实现。Kubernetes会为PVC自动绑定一个符合条件的PV。PVC实现了存储消费与供给的解耦,是现代云原生架构中的重要概念。

5. PV/PVC 结合 NFS 实战(持久化存储)

① PV 与 PVC 的关系

使用持久化存储时,Pod通过PVC申请存储,PVC会与一个合适的PV进行绑定(一对一绑定)。
创建顺序为:后端存储 -> PV -> PVC -> Pod
PV/PVC关系图

② NFS 服务器搭建

在存储服务器上执行以下运维操作

# 1. 安装nfs服务
yum -y install nfs-utils rpcbind

# 2. 创建共享目录并授权
mkdir -p /nfs/data/k8s
chmod -R 777 /nfs/data

# 3. 编辑exports文件
vim /etc/exports
# 添加以下内容(生产环境应限制IP并谨慎授权):
/nfs/data *(rw,no_root_squash,sync)

# 4. 使配置生效并启动服务
exportfs -r
systemctl start rpcbind && systemctl enable rpcbind
systemctl start nfs && systemctl enable nfs

# 5. 在本机测试NFS共享
showmount -e localhost

所有Kubernetes Node节点上安装NFS客户端:

yum -y install nfs-utils rpcbind

③ 定义 PersistentVolume (PV)

# nginx-pv-demo.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nginx-pv  # PV的名称
spec:
  capacity:
    storage: 2Gi   # PV的容量
  accessModes:
    - ReadWriteMany # 访问模式:可被多个节点读写
  nfs:
    path: /nfs/data/     # NFS服务器共享路径
    server: 10.0.0.16    # NFS服务器IP地址

④ 定义 PersistentVolumeClaim (PVC)

PVC会根据定义的访问模式和存储大小,自动寻找并绑定符合要求的PV。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nginx-pvc
  namespace: dev
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 2Gi  # 申请2G存储空间

⑤ 定义 Pod,使用 PVC

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-pvc
  namespace: dev  # 必须与PVC所在命名空间一致
spec:
  selector:
    matchLabels:
      app: nginx-pvc
  template:
    metadata:
      labels:
        app: nginx-pvc
    spec:
      containers:
      - name: nginx-test-pvc
        image: nginx:1.20.0
        ports:
        - containerPort: 80
        volumeMounts:
        - name: nginx-persistent-storage
          mountPath: /usr/share/nginx/html
      volumes:
      - name: nginx-persistent-storage
        persistentVolumeClaim:
          claimName: nginx-pvc  # 引用上面定义的PVC

⑥ 应用并查看

kubectl apply -f nginx-pv-demo.yaml
kubectl get pv,pvc -n dev -o wide
kubectl get pods -n dev -o wide

⑦ PV的回收

  1. 删除Pod和PVC(必须先删Pod):
    kubectl delete deploy/nginx-pvc -n dev
    kubectl delete pvc/nginx-pvc -n dev
  2. 查看PV状态:PVC删除后,Kubernetes会自动启动清理Job清除PV数据,随后PV状态恢复为Available,可供新的PVC申请。
    kubectl get pv

    ⑧ PV回收策略

    通过persistentVolumeReclaimPolicy字段设置:

    • Recycle:清除数据,自动回收(基础存储如NFS)。
    • Retain:保留数据,需要手动清理。
    • Delete:删除存储卷(云存储专用)。

6. 使用 PVC 模板自动创建 (VolumeClaimTemplates)

对于有状态应用(如StatefulSet),可以使用volumeClaimTemplates为每个Pod实例自动创建独立的PVC。

① 预先创建多个 PV

首先在NFS服务器上创建多个目录(如v1-v5),然后定义对应的PV资源。

② 在StatefulSet中使用 VolumeClaimTemplates

# pvctemplate.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "nginx-headless"
  replicas: 3
  selector:
    matchLabels:
      app: nginx-pvc
  template:
    metadata:
      labels:
        app: nginx-pvc
    spec:
      containers:
      - name: nginx
        image: nginx:1.20.0
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:  # PVC模板
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteMany" ]
      resources:
        requests:
          storage: 1Gi

应用后,会生成类似www-web-0www-web-1的PVC,并自动绑定到符合条件的PV。

7. StorageClass:动态卷供应

① 什么是 StorageClass?

StorageClass是PV的自动化创建工具。管理员可以定义不同的存储类别(如高速SSD、标准HDD)。当用户创建PVC并指定storageClassName时,StorageClass会根据PVC需求,自动创建对应的PV及底层存储,极大简化了运维。

② 为什么要使用 StorageClass?

  • 简化管理:无需手动预创建大量PV。
  • 动态供应:按需自动创建存储资源。
  • 抽象存储:用户只需关注存储类别,无需了解后端细节。

③ StorageClass 工作原理

StorageClass结构图
在动态供应模式下,StorageClass 配合 PVC 实现资源的自动绑定与供给。

④ StorageClass 字段说明

  • Provisioner (存储制备器):决定使用哪个插件来制备PV。
    • 内置:如 kubernetes.io/aws-ebs
    • 外部:如 nfs-client-provisionercsi-provisioner
  • reclaimPolicy (回收策略):同上文PV的RetainDelete
  • allowVolumeExpansion:是否允许卷扩容。
  • volumeBindingMode (卷绑定模式)
    • Immediate:创建PVC后立即绑定PV。
    • WaitForFirstConsumer:延迟到Pod调度时再绑定,适用于拓扑受限的存储。

8. NFS StorageClass 实战

① 搭建 NFS 服务器 (同上文步骤②)

② 创建 ServiceAccount 和 RBAC 授权

StorageClass 等资源需要特定权限来管理,因此需创建专用账户并授权。

# sa.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-client-provisioner
  namespace: default
# rbac.yaml
# 内容较长,主要为 nfs-client-provisioner 账户绑定操作 PV、PVC、StorageClass 等资源的权限

③ 部署 NFS Client Provisioner

Provisioner 是一个Pod,负责对接NFS服务器并动态创建子目录作为PV。

# nfs-client-provisioner.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nfs-client-provisioner
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nfs-client-provisioner
  template:
    metadata:
      labels:
        app: nfs-client-provisioner
    spec:
      serviceAccountName: nfs-client-provisioner # 使用刚创建的SA
      containers:
      - name: nfs-client-provisioner
        image: registry.cn-hangzhou.aliyuncs.com/open-ali/nfs-client-provisioner
        volumeMounts:
        - name: nfs-client-root
          mountPath: /persistentvolumes
        env:
        - name: PROVISIONER_NAME
          value: nfs-storage # Provisioner名称,需与StorageClass对应
        - name: NFS_SERVER
          value: 192.168.1.34 # NFS服务器IP
        - name: NFS_PATH
          value: /nfs/data/k8s # NFS共享路径
      volumes:
      - name: nfs-client-root
        nfs:
          server: 192.168.1.34
          path: /nfs/data/k8s

④ 创建 StorageClass

# nfs-storageclass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: managed-nfs-storage
provisioner: nfs-storage # 必须与Provisioner中定义的名称一致
parameters:
  server: "192.168.1.34"
  path: "/nfs/data/k8s"
  readOnly: "false"

⑤ 测试使用

  1. 创建PVC,它将触发StorageClass动态创建PV。
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: my-nfs-pvc
    spec:
      storageClassName: managed-nfs-storage # 指定使用的StorageClass
      accessModes:
        - ReadWriteMany
      resources:
        requests:
          storage: 1Gi
  2. 创建Pod并使用该PVC。
    apiVersion: v1
    kind: Pod
    metadata:
      name: my-pod
    spec:
      volumes:
      - name: my-volume
        persistentVolumeClaim:
          claimName: my-nfs-pvc
      containers:
      - name: my-container
        image: nginx
        volumeMounts:
        - mountPath: "/usr/share/nginx/html"
          name: my-volume

⑧ 实战部署流程总结

  1. 搭建NFS服务器,提供底层存储。
  2. 部署NFS Client Provisioner,作为动态存储供应商。
  3. 创建StorageClass,定义动态供给规则。
  4. 用户创建PVC(指定StorageClass),触发PV的自动创建与绑定。
  5. Pod挂载PVC,使用持久化存储。

Pod使用PVC的完整流程
Pod -> PVC -> StorageClass -> Provisioner -> 在NFS服务器创建目录 -> PV -> 绑定回PVC -> 供Pod使用。
动态供给流程

9. 有状态服务 + StorageClass 综合示例

StatefulSet 配合 volumeClaimTemplates 和 StorageClass 是实现有状态应用(如MySQL、Redis)数据持久化的最佳实践。

① 创建 Headless Service

apiVersion: v1
kind: Service
metadata:
  name: mystatefulset-sctemplate
  namespace: devlop
spec:
  clusterIP: None # 无头服务
  selector:
    app: mysts-sctemp
  ports:
  - port: 3306
    name: mysql-port

② 创建 StatefulSet

关键点在于使用 volumeClaimTemplates 自动为每个Pod实例创建PVC,并指定 storageClassName

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysts-sctemp
  namespace: devlop
spec:
  serviceName: mystatefulset-sctemplate
  replicas: 3
  selector:
    matchLabels:
      app: mysts-sctemp
  template:
    metadata:
      labels:
        app: mysts-sctemp
    spec:
      containers:
      - name: mysql-3306
        image: mysql:8.0.27
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: "123456789"
        volumeMounts:
        - name: mysql-data
          mountPath: /var/lib/mysql
        - name: mysql-log
          mountPath: /var/log/mysql
  volumeClaimTemplates: # 自动创建PVC的模板
  - metadata:
      name: mysql-data
    spec:
      accessModes: [ "ReadWriteMany" ]
      storageClassName: managed-nfs-storage # 指定StorageClass
      resources:
        requests:
          storage: 5Gi
  - metadata:
      name: mysql-log
    spec:
      accessModes: [ "ReadWriteMany" ]
      storageClassName: managed-nfs-storage # 指定StorageClass
      resources:
        requests:
          storage: 10Gi

通过以上配置,每个MySQL Pod都会拥有自己独立的、由StorageClass动态提供的持久化存储卷,非常适合作为数据库等有状态服务的存储方案。




上一篇:AI安全专家如何看待AGI风险:末日论者的逻辑与近期争议分析
下一篇:深度解析Google OCS光路解耦:从TPUv4到百万卡全光计算织物的架构演进
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-1-11 19:56 , Processed in 0.199044 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表