【k8s应用管理】kubernetes 存储管理

文章目录

  • [Kubernetes 存储](#Kubernetes 存储)
    • [Volume 与存储卷详解](#Volume 与存储卷详解)
      • 背景
      • [emptyDir 存储卷](#emptyDir 存储卷)
        • [emptyDir 存储卷示例](#emptyDir 存储卷示例)
      • [hostPath 存储卷](#hostPath 存储卷)
        • [hostPath 存储卷示例](#hostPath 存储卷示例)
      • [NFS 共享存储卷](#NFS 共享存储卷)
        • [NFS 存储卷示例](#NFS 存储卷示例)
      • 总结
    • [PV 与 PVC](#PV 与 PVC)
      • 核心概念
      • [PV 与 PVC 生命周期](#PV 与 PVC 生命周期)
      • [PV 的 4 种状态](#PV 的 4 种状态)
      • [PV 的创建方式](#PV 的创建方式)
      • 关键配置字段
        • [PV 配置(`spec` 字段)](#PV 配置(spec 字段))
        • [PVC 配置(`spec` 字段)](#PVC 配置(spec 字段))
      • 示例
        • [静态 PV 与 PVC 示例](#静态 PV 与 PVC 示例)
        • [动态 PV 示例(StorageClass)](#动态 PV 示例(StorageClass))
      • 总结
      • 存储卷类型对比
      • [静态创建 PV 与动态创建 PV 对比](#静态创建 PV 与动态创建 PV 对比)
    • [实例:用 NFS 作为存储后端的 PV 与 PVC 配置指南](#实例:用 NFS 作为存储后端的 PV 与 PVC 配置指南)
      • [1. 配置 NFS 服务器](#1. 配置 NFS 服务器)
      • [2. 静态创建 PV 资源](#2. 静态创建 PV 资源)
      • [3. 创建 PVC 并绑定 PV](#3. 创建 PVC 并绑定 PV)
      • [4. 测试数据持久化](#4. 测试数据持久化)
      • 注意
    • [搭建 StorageClass + NFS-Client-Provisioner 实现 NFS 动态 PV 创建](#搭建 StorageClass + NFS-Client-Provisioner 实现 NFS 动态 PV 创建)
      • 背景
      • 步骤概览
      • 详细步骤
        • [1. 配置 NFS 服务器](#1. 配置 NFS 服务器)
        • [2. 创建 RBAC 权限](#2. 创建 RBAC 权限)
        • [3. 部署 NFS-Client-Provisioner](#3. 部署 NFS-Client-Provisioner)
        • [4. 创建 StorageClass](#4. 创建 StorageClass)
        • [5. 测试 PVC 和 Pod](#5. 测试 PVC 和 Pod)

Kubernetes 存储

Volume 与存储卷详解

背景

容器磁盘上的文件生命周期是短暂的,这会导致以下问题:

  1. 容器崩溃时数据丢失:当容器崩溃后,kubelet 会重启容器,但容器中的文件会丢失,恢复到镜像的初始状态。
  2. 多容器间文件共享需求 :在同一个 Pod 中运行的多个容器通常需要共享文件。
    Kubernetes 通过 Volume 抽象 解决了这些问题。Pod 中的容器通过 Pause 容器 共享 Volume,从而实现数据的持久化和共享。

emptyDir 存储卷

  • 特点
    • 当 Pod 被分配到节点时,emptyDir 卷会被创建。
    • 只要 Pod 在该节点上运行,emptyDir 卷就会存在。
    • 卷最初是空的,Pod 中的容器可以读取和写入 emptyDir 卷中的相同文件。
    • 当 Pod 从节点中删除时,emptyDir 中的数据会被永久删除。
  • 适用场景
    • 临时数据存储。
    • 多容器间文件共享。
emptyDir 存储卷示例
  1. 创建 YAML 文件
    /opt/volumes 目录下创建 pod-emptydir.yaml 文件:

    yaml 复制代码
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-emptydir
      namespace: default
      labels:
        app: myapp
        tier: frontend
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
        imagePullPolicy: IfNotPresent
        ports:
        - name: http
          containerPort: 80
        volumeMounts:
        - name: html
          mountPath: /usr/share/nginx/html/
      - name: busybox
        image: busybox:latest
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - name: html
          mountPath: /data/
        command: ['/bin/sh','-c','while true;do echo $(date) >> /data/index.html;sleep 2;done']
      volumes:
      - name: html
        emptyDir: {}
  2. 应用 YAML 文件
    使用以下命令创建 Pod:

    bash 复制代码
    kubectl apply -f pod-emptydir.yaml
  3. 查看 Pod 状态
    确认 Pod 已成功运行:

    bash 复制代码
    kubectl get pods -o wide

    输出示例:

    NAME           READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
    pod-emptydir   2/2     Running   0          36s   10.244.2.19   node02   <none>           <none>
    
  4. 验证数据共享

    • busybox 容器会每隔 2 秒将当前日期写入 /data/index.html 文件。

    • myapp 容器通过挂载的 emptyDir 卷读取 /usr/share/nginx/html/index.html 文件。

    • 使用 curl 命令访问 Nginx 服务,验证是否能够获取日期信息:

      bash 复制代码
      curl 10.244.2.19

      输出示例:

      Thu May 27 18:17:11 UTC 2021
      Thu May 27 18:17:13 UTC 2021
      Thu May 27 18:17:15 UTC 2021
      Thu May 27 18:17:17 UTC 2021
      Thu May 27 18:17:19 UTC 2021
      Thu May 27 18:17:21 UTC 2021
      Thu May 27 18:17:23 UTC 2021
      

hostPath 存储卷

  • 功能:将 Node 节点上的文件或目录挂载到 Pod 中。
  • 特点
    • 实现持久化存储,但数据与 Node 节点绑定。
    • 如果 Node 节点故障,数据会丢失。
    • 适用于单节点数据持久化或调试场景。
hostPath 存储卷示例
  1. 在 Node 节点上创建挂载目录

    • node01 上:

      bash 复制代码
      mkdir -p /data/pod/volume1
      echo 'node01.xy101.com' > /data/pod/volume1/index.html
    • node02 上:

      bash 复制代码
      mkdir -p /data/pod/volume1
      echo 'node02.xy101.com' > /data/pod/volume1/index.html
  2. 创建 Pod 资源 YAML 文件

    yaml 复制代码
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-hostpath
      namespace: default
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
        volumeMounts:
        - name: html
          mountPath: /usr/share/nginx/html
          readOnly: false
      volumes:
      - name: html
        hostPath:
          path: /data/pod/volume1
          type: DirectoryOrCreate
  3. 应用 YAML 文件

    bash 复制代码
    kubectl apply -f pod-hostpath.yaml
  4. 验证 Pod 状态

    bash 复制代码
    kubectl get pods -o wide

    输出示例:

    NAME           READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
    pod-hostpath   1/1     Running   0          37s   10.244.2.35   node02   <none>           <none>
    
  5. 访问测试

    bash 复制代码
    curl 10.244.2.35

    输出示例:

    node02.xy101.com
    
  6. 验证数据持久化

    • 删除 Pod 并重新创建:

      bash 复制代码
      kubectl delete -f pod-hostpath.yaml
      kubectl apply -f pod-hostpath.yaml
    • 再次访问 Pod:

      bash 复制代码
      curl 10.244.2.37

      输出示例:

      node02.xy101.com
      

NFS 共享存储卷

  • 功能:将 NFS 服务器的共享目录挂载到 Pod 中。
  • 特点
    • 实现跨节点的数据持久化和共享。
    • 数据存储在 NFS 服务器上,即使 Pod 或 Node 故障,数据也不会丢失。
NFS 存储卷示例
  1. 在 NFS 服务器上配置 NFS 服务

    • 创建共享目录并设置权限:

      bash 复制代码
      mkdir /data/volumes -p
      chmod 777 /data/volumes
    • 编辑 /etc/exports 文件:

      bash 复制代码
      /data/volumes 192.168.80.0/24(rw,no_root_squash)
    • 启动 NFS 服务:

      bash 复制代码
      systemctl start rpcbind
      systemctl start nfs
    • 验证 NFS 共享:

      bash 复制代码
      showmount -e

      输出示例:

      Export list for stor01:
      /data/volumes 192.168.80.0/24
      
  2. 创建 Pod 资源 YAML 文件

    yaml 复制代码
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-vol-nfs
      namespace: default
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
        volumeMounts:
        - name: html
          mountPath: /usr/share/nginx/html
      volumes:
      - name: html
        nfs:
          path: /data/volumes
          server: stor01
  3. 应用 YAML 文件

    bash 复制代码
    kubectl apply -f pod-nfs-vol.yaml
  4. 验证 Pod 状态

    bash 复制代码
    kubectl get pods -o wide

    输出示例:

    NAME           READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
    pod-vol-nfs    1/1     Running   0          21s   10.244.2.38   node02   <none>           <none>
    
  5. 在 NFS 服务器上创建测试文件

    bash 复制代码
    cd /data/volumes
    echo '<h1> nfs stor01</h1>' > index.html
  6. 访问测试

    bash 复制代码
    curl 10.244.2.38

    输出示例:

    <h1> nfs stor01</h1>
    
  7. 验证数据持久化

    • 删除 Pod 并重新创建:

      bash 复制代码
      kubectl delete -f pod-nfs-vol.yaml
      kubectl apply -f pod-nfs-vol.yaml
    • 再次访问 Pod:

      bash 复制代码
      curl 10.244.2.38

      输出示例:

      <h1> nfs stor01</h1>
      

总结

特性 emptyDir hostPath nfs
功能 实现 Pod 内容器之间的目录数据共享。 将 Node 节点上的目录或文件挂载到 Pod 容器中使用。 将 NFS 服务的共享目录挂载到 Pod 容器中使用。
持久化能力 无持久化能力,数据随 Pod 删除而丢失。 具备持久化能力,但数据仅绑定到单个 Node 节点。 具备持久化能力,数据存储在 NFS 服务器上。
数据共享范围 仅限于 Pod 内容器之间共享。 仅限于 Pod 所在 Node 节点上的容器使用。 支持跨 Node 节点的容器共享数据。
适用场景 临时数据存储或容器间数据共享。 单节点数据持久化或调试场景。 多节点数据共享或持久化存储。
数据可靠性 低,数据随 Pod 删除而丢失。 中,数据与 Node 节点绑定,节点故障时数据丢失。 高,数据存储在 NFS 服务器上,可靠性高。
配置复杂度 简单,无需额外配置。 中等,需在 Node 节点上创建目录。 较高,需配置 NFS 服务器和共享目录。
跨节点支持 不支持跨节点共享。 不支持跨节点共享。 支持跨节点共享。

PV 与 PVC

核心概念

  • PV(PersistentVolume)

    • 定义:集群中的持久化存储资源,由运维人员创建和管理。
    • 特点:独立于 Pod 生命周期,支持多种存储类型(如 NFS、Ceph、iSCSI 等)。
  • PVC(PersistentVolumeClaim)

    • 定义:用户对存储资源的请求,描述所需的存储特性(如容量、访问模式)。
    • 特点:通过绑定 PV 实现存储资源的动态分配。
  • StorageClass(SC)

    • 作用:动态创建 PV 的模板,自动化管理存储资源。
    • 核心字段
      • provisioner:存储插件(如 nfs-clientceph-rbd)。
      • reclaimPolicy:PV 回收策略(默认 Delete)。

PV 与 PVC 生命周期

阶段 描述
Provisioning 创建 PV(静态手动创建 或 动态通过 StorageClass 自动创建)。
Binding PVC 与 PV 绑定,PV 进入 Bound 状态。
Using Pod 通过 PVC 使用 PV 存储资源。
Releasing Pod 释放存储资源,删除 PVC,PV 进入 Released 状态。
Recycling 根据回收策略处理 PV(保留、删除或复用)。

PV 的 4 种状态

状态 描述
Available PV 已创建但未被 PVC 绑定。
Bound PV 已与 PVC 绑定,可被 Pod 使用。
Released PVC 已删除,但 PV 尚未回收(数据可能保留)。
Failed PV 或 PVC 配置错误或存储后端故障,无法正常使用。

PV 的创建方式

方式 特点
静态创建 手动创建 PV,适合固定存储需求。
动态创建 通过 StorageClass 自动创建 PV,适合大规模动态存储需求。

关键配置字段

PV 配置(spec 字段)
  • 存储类型

    yaml 复制代码
    nfs:
      path: /data/volumes
      server: stor01
  • 访问模式(accessModes

    • ReadWriteOnce(RWO):单节点读写。
    • ReadOnlyMany(ROX):多节点只读。
    • ReadWriteMany(RWX):多节点读写。
    • ReadWriteOncePod(RWOP):单 Pod 读写。
  • 容量(capacity

    yaml 复制代码
    capacity:
      storage: 10Gi
  • 回收策略(persistentVolumeReclaimPolicy

    • Retain:保留数据,需手动清理。
    • Delete:自动删除 PV 及后端存储(仅支持云存储)。
    • Recycle:清除数据并复用 PV(已废弃,建议使用动态配置)。
PVC 配置(spec 字段)
  • 资源请求(resources

    yaml 复制代码
    resources:
      requests:
        storage: 5Gi
  • 存储类(storageClassName

    yaml 复制代码
    storageClassName: "nfs-storage"

示例

静态 PV 与 PVC 示例
  1. 创建 PV

    yaml 复制代码
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv-nfs
    spec:
      capacity:
        storage: 10Gi
      accessModes:
        - ReadWriteMany
      persistentVolumeReclaimPolicy: Retain
      nfs:
        path: /data/volumes
        server: stor01
  2. 创建 PVC

    yaml 复制代码
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: pvc-nfs
    spec:
      accessModes:
        - ReadWriteMany
      resources:
        requests:
          storage: 5Gi
      storageClassName: ""
  3. Pod 挂载 PVC

    yaml 复制代码
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-pvc
    spec:
      containers:
      - name: nginx
        image: nginx
        volumeMounts:
        - name: data
          mountPath: /usr/share/nginx/html
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: pvc-nfs
动态 PV 示例(StorageClass)
  1. 创建 StorageClass

    yaml 复制代码
    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: nfs-storage
    provisioner: example.com/nfs
    reclaimPolicy: Delete
  2. 创建 PVC

    yaml 复制代码
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: pvc-dynamic
    spec:
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 5Gi
      storageClassName: nfs-storage

总结

存储卷类型对比

特性 emptyDir hostPath nfs PV/PVC
持久化能力 单节点持久化 跨节点持久化 持久化(依赖后端存储)
数据共享范围 Pod 内容器 Pod 所在节点 跨节点 集群范围
适用场景 临时数据共享 单节点调试/数据持久化 多节点共享数据 生产环境持久化存储
配置复杂度 简单 中等 高(需管理 PV 和 PVC)

  • PV/PVC
    • 实现存储资源与 Pod 解耦,提供灵活的存储管理。
    • 静态配置适合固定需求,动态配置适合大规模场景。
  • StorageClass
    • 自动化 PV 创建,降低运维成本。
  • 访问模式与回收策略
    • 根据业务需求选择,例如 ReadWriteMany 适合多节点读写,Retain 策略保障数据安全。

静态创建 PV 与动态创建 PV 对比

步骤 静态创建 PV 动态创建 PV
1. 准备存储设备 确保存储设备可用并配置好(如 NFS、Ceph、iSCSI 等)。 确保存储设备可用并配置好(如 NFS、Ceph、iSCSI 等)。
2. 创建 PV 资源 手动创建 PV,定义访问模式、存储空间、回收策略、存储设备类型等。 无需手动创建 PV,由 StorageClass 自动创建。
3. 创建 PVC 资源 手动创建 PVC,绑定已创建的 PV,定义访问模式和请求的存储空间。 创建 PVC,指定 StorageClass,动态生成并绑定 PV。
4. 创建 Pod 资源 挂载 PVC 存储卷,定义挂载点目录。 挂载 PVC 存储卷,定义挂载点目录。
5. 存储卷插件 无需额外配置存储卷插件。 需配置存储卷插件(Provisioner),如 NFS、Ceph 等。
6. RBAC 授权 无需 RBAC 授权。 如果是外置卷插件,需创建 ServiceAccount 和 RBAC 授权。
7. StorageClass 无需 StorageClass。 需创建 StorageClass,定义 Provisioner、参数和回收策略。
适用场景 适合固定存储需求,PV 数量较少。 适合动态存储需求,PV 数量较多,自动化程度高。
运维复杂度 较高,需手动管理 PV 和 PVC。 较低,自动化管理 PV 和 PVC。
灵活性 灵活性较低,需提前规划存储资源。 灵活性高,按需动态创建存储资源。

  • 静态创建 PV

    • 适合固定存储需求,PV 数量较少。
    • 需手动管理 PV 和 PVC,运维复杂度较高。
    • 灵活性较低,需提前规划存储资源。
  • 动态创建 PV

    • 适合动态存储需求,PV 数量较多。
    • 自动化管理 PV 和 PVC,运维复杂度较低。
    • 灵活性高,按需动态创建存储资源。

实例:用 NFS 作为存储后端的 PV 与 PVC 配置指南

1. 配置 NFS 服务器

目标:创建共享目录并配置 NFS 服务,使 Kubernetes 集群可以访问这些存储资源。

  1. 创建共享目录

    在 NFS 服务器上创建多个共享目录:

    bash 复制代码
    mkdir -p /data/volumes/v{1,2,3,4,5}
  2. 配置 NFS 共享

    编辑 /etc/exports 文件,定义共享目录及访问权限:

    bash 复制代码
    vim /etc/exports

    添加以下内容:

    /data/volumes/v1 192.168.80.0/24(rw,no_root_squash)
    /data/volumes/v2 192.168.80.0/24(rw,no_root_squash)
    /data/volumes/v3 192.168.80.0/24(rw,no_root_squash)
    /data/volumes/v4 192.168.80.0/24(rw,no_root_squash)
    /data/volumes/v5 192.168.80.0/24(rw,no_root_squash)
    
  3. 生效配置并验证

    bash 复制代码
    exportfs -arv        # 重新加载 NFS 共享配置
    showmount -e         # 验证共享目录是否生效

2. 静态创建 PV 资源

目标:定义多个 PV,关联 NFS 共享目录,并设置容量、访问模式和回收策略。

  1. 定义 PV 资源文件

    创建 pv-demo.yaml,配置 5 个 PV:

    yaml 复制代码
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv001
      labels:
        name: pv001
    spec:
      nfs:
        path: /data/volumes/v1
        server: stor01
      accessModes: ["ReadWriteMany", "ReadWriteOnce"]
      capacity:
        storage: 1Gi
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv002
      labels:
        name: pv002
    spec:
      nfs:
        path: /data/volumes/v2
        server: stor01
      accessModes: ["ReadWriteOnce"]
      capacity:
        storage: 2Gi
    ---
    # 其他 PV 配置(pv003、pv004、pv005)类似,需修改路径和容量
  2. 应用 PV 配置

    bash 复制代码
    kubectl apply -f pv-demo.yaml
  3. 验证 PV 状态

    bash 复制代码
    kubectl get pv

    输出示例:

    NAME    CAPACITY  ACCESS MODES  RECLAIM POLICY  STATUS      AGE
    pv001   1Gi       RWO,RWX       Retain          Available   10s
    pv002   2Gi       RWO           Retain          Available   10s
    pv003   2Gi       RWO,RWX       Retain          Available   10s
    pv004   4Gi       RWO,RWX       Retain          Available   10s
    pv005   5Gi       RWO,RWX       Retain          Available   10s
    

3. 创建 PVC 并绑定 PV

目标:定义 PVC 请求存储资源,并自动绑定符合条件的 PV。

  1. 定义 PVC 和 Pod 资源文件

    创建 pod-vol-pvc.yaml

    yaml 复制代码
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: mypvc
      namespace: default
    spec:
      accessModes: ["ReadWriteMany"]
      resources:
        requests:
          storage: 2Gi
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-vol-pvc
      namespace: default
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
        volumeMounts:
        - name: html
          mountPath: /usr/share/nginx/html
      volumes:
      - name: html
        persistentVolumeClaim:
          claimName: mypvc
  2. 应用 PVC 和 Pod 配置

    bash 复制代码
    kubectl apply -f pod-vol-pvc.yaml
  3. 验证 PVC 和 PV 绑定状态

    bash 复制代码
    kubectl get pv
    kubectl get pvc

    输出示例:

    # PV 状态
    NAME    STATUS   CLAIM           CAPACITY  ACCESS MODES
    pv003   Bound    default/mypvc   2Gi       RWO,RWX
    
    # PVC 状态
    NAME    STATUS   VOLUME  CAPACITY  ACCESS MODES
    mypvc   Bound    pv003   2Gi       RWO,RWX
    

4. 测试数据持久化

目标:验证 Pod 通过 PVC 挂载的存储是否正常工作。

  1. 在 NFS 服务器上创建测试文件

    bash 复制代码
    echo "welcome to use pv3" > /data/volumes/v3/index.html
  2. 访问 Pod 服务

    获取 Pod 的 IP 地址并访问:

    bash 复制代码
    kubectl get pods -o wide
    curl <Pod_IP>

    输出示例:

    welcome to use pv3
    

注意

  1. PV 配置字段

    • accessModes:定义 PV 的访问模式(如 ReadWriteMany)。
    • capacity:设置存储容量(如 2Gi)。
    • persistentVolumeReclaimPolicy:回收策略(默认 Retain)。
  2. PVC 配置字段

    • accessModes:必须与 PV 支持的访问模式匹配。
    • resources.requests.storage:请求的存储空间大小。
常见问题与其他注意事项
  1. 访问模式匹配

    • PVC 的 accessModes 必须是 PV 支持的模式子集。
    • 例如,若 PVC 请求 ReadWriteMany,则 PV 必须支持该模式。
  2. 存储容量匹配

    • PVC 请求的存储空间需小于等于 PV 的容量。
    • Kubernetes 会自动选择容量最小的符合条件的 PV。
  3. 回收策略影响

    • Retain 策略下,删除 PVC 后 PV 不会自动清理,需手动处理。
    • Delete 策略仅适用于部分存储后端(如云存储)。
  4. 多 Pod 共享存储

    • 若多个 Pod 使用同一 PVC,需确保存储后端支持并发读写(如 NFS 的 ReadWriteMany)。

搭建 StorageClass + NFS-Client-Provisioner 实现 NFS 动态 PV 创建

背景

Kubernetes 默认不支持 NFS 的动态 PV 创建,因此需要使用外部存储卷插件(Provisioner)来实现。NFS-Client-Provisioner 是一个常用的 Provisioner,它能够自动在 NFS 服务器上创建目录,并将其与 PV 关联。

步骤概览

  1. 配置 NFS 服务器:准备 NFS 共享目录。
  2. 创建 RBAC 权限:为 NFS-Client-Provisioner 配置 ServiceAccount 和权限。
  3. 部署 NFS-Client-Provisioner:使用 Deployment 部署 Provisioner。
  4. 创建 StorageClass:定义动态 PV 的创建规则。
  5. 测试 PVC 和 Pod:验证动态 PV 创建和挂载功能。

详细步骤

1. 配置 NFS 服务器

在 NFS 服务器上创建共享目录并配置 NFS 服务。

  1. 创建共享目录

    bash 复制代码
    mkdir -p /opt/k8s
    chmod 777 /opt/k8s
  2. 配置 NFS 共享
    编辑 /etc/exports 文件:

    bash 复制代码
    vim /etc/exports

    添加以下内容:

    /opt/k8s 192.168.80.0/24(rw,no_root_squash,sync)
    
  3. 重启 NFS 服务

    bash 复制代码
    systemctl restart nfs
2. 创建 RBAC 权限

为 NFS-Client-Provisioner 配置 ServiceAccount 和权限。

  1. 创建 RBAC 配置文件
    创建 nfs-client-rbac.yaml

    yaml 复制代码
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: nfs-client-provisioner
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: nfs-client-provisioner-clusterrole
    rules:
      - apiGroups: [""]
        resources: ["persistentvolumes"]
        verbs: ["get", "list", "watch", "create", "delete"]
      - apiGroups: [""]
        resources: ["persistentvolumeclaims"]
        verbs: ["get", "list", "watch", "update"]
      - apiGroups: ["storage.k8s.io"]
        resources: ["storageclasses"]
        verbs: ["get", "list", "watch"]
      - apiGroups: [""]
        resources: ["events"]
        verbs: ["list", "watch", "create", "update", "patch"]
      - apiGroups: [""]
        resources: ["endpoints"]
        verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: nfs-client-provisioner-clusterrolebinding
    subjects:
      - kind: ServiceAccount
        name: nfs-client-provisioner
        namespace: default
    roleRef:
      kind: ClusterRole
      name: nfs-client-provisioner-clusterrole
      apiGroup: rbac.authorization.k8s.io
  2. 应用 RBAC 配置

    bash 复制代码
    kubectl apply -f nfs-client-rbac.yaml
3. 部署 NFS-Client-Provisioner

使用 Deployment 部署 NFS-Client-Provisioner。

  1. 解决 Kubernetes 1.20+ 的 SelfLink 问题

    编辑 kube-apiserver.yaml

    bash 复制代码
    vim /etc/kubernetes/manifests/kube-apiserver.yaml

    添加以下内容:

    yaml 复制代码
    spec:
      containers:
      - command:
        - kube-apiserver
        - --feature-gates=RemoveSelfLink=false

    重启 kube-apiserver:

    bash 复制代码
    kubectl delete pods kube-apiserver -n kube-system
  2. 创建 Provisioner 配置文件

    创建 nfs-client-provisioner.yaml

    yaml 复制代码
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nfs-client-provisioner
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: nfs-client-provisioner
      strategy:
        type: Recreate
      template:
        metadata:
          labels:
            app: nfs-client-provisioner
        spec:
          serviceAccountName: nfs-client-provisioner
          containers:
          - name: nfs-client-provisioner
            image: quay.io/external_storage/nfs-client-provisioner:latest
            imagePullPolicy: IfNotPresent
            volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
            env:
            - name: PROVISIONER_NAME
              value: nfs-storage
            - name: NFS_SERVER
              value: stor01
            - name: NFS_PATH
              value: /opt/k8s
          volumes:
          - name: nfs-client-root
            nfs:
              server: stor01
              path: /opt/k8s
  3. 应用 Provisioner 配置

    bash 复制代码
    kubectl apply -f nfs-client-provisioner.yaml
  4. 验证 Provisioner 状态

    bash 复制代码
    kubectl get pods

    输出示例:

    NAME                                      READY   STATUS    RESTARTS   AGE
    nfs-client-provisioner-7f5d8c5c5c-6q9q2   1/1     Running   0          10s
    
4. 创建 StorageClass

定义动态 PV 的创建规则。

  1. 创建 StorageClass 配置文件

    创建 nfs-client-storageclass.yaml

    yaml 复制代码
    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: nfs-client-storageclass
    provisioner: nfs-storage
    parameters:
      archiveOnDelete: "false"
  2. 应用 StorageClass 配置

    bash 复制代码
    kubectl apply -f nfs-client-storageclass.yaml
  3. 验证 StorageClass 状态

    bash 复制代码
    kubectl get storageclass

    输出示例:

    NAME                      PROVISIONER    RECLAIMPOLICY   VOLUMEBINDINGMODE   AGE
    nfs-client-storageclass   nfs-storage    Delete          Immediate           10s
    
5. 测试 PVC 和 Pod

验证动态 PV 创建和挂载功能。

  1. 创建 PVC 和 Pod 配置文件
    创建 test-pvc-pod.yaml

    yaml 复制代码
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: test-nfs-pvc
    spec:
      accessModes:
        - ReadWriteMany
      storageClassName: nfs-client-storageclass
      resources:
        requests:
          storage: 1Gi
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: test-storageclass-pod
    spec:
      containers:
      - name: busybox
        image: busybox:latest
        command: ["/bin/sh", "-c", "sleep 3600"]
        volumeMounts:
        - name: nfs-pvc
          mountPath: /mnt
      volumes:
      - name: nfs-pvc
        persistentVolumeClaim:
          claimName: test-nfs-pvc
  2. 应用 PVC 和 Pod 配置

    bash 复制代码
    kubectl apply -f test-pvc-pod.yaml
  3. 验证 PVC 和 PV 状态

    bash 复制代码
    kubectl get pvc
    kubectl get pv

    输出示例:

    NAME            STATUS   VOLUME                                     CAPACITY   ACCESS MODES   AGE
    test-nfs-pvc    Bound    pvc-11670f39-782d-41b8-a842-eabe1859a456   1Gi        RWX            10s
    
  4. 验证数据持久化

    • 进入 Pod 并创建测试文件:

      bash 复制代码
      kubectl exec -it test-storageclass-pod -- /bin/sh
      echo "this is test file" > /mnt/test.txt
    • 在 NFS 服务器上验证文件:

      bash 复制代码
      cat /opt/k8s/default-test-nfs-pvc-pvc-11670f39-782d-41b8-a842-eabe1859a456/test.txt

      输出示例:

      this is test file
      
相关推荐
drebander4 分钟前
Docker 镜像详解:构建、管理与优化
运维·docker·容器
深圳特力康何哈哈1 小时前
输电杆塔沉降智能监测系统:如何用数据守护电网安全
运维·安全
nandao1581 小时前
nginx通过location配置代理的原理和方式
运维·nginx
kk努力学编程1 小时前
Linux基础18-C语言篇之运算符Ⅰ【入门级】
linux·运维·c语言
Ruimin05193 小时前
Mysql8.0使用PXC
运维
陈老师还在写代码5 小时前
在服务器部署JVM后,如何评估JVM的工作能力,比如吞吐量
运维·服务器·jvm
handsomestWei5 小时前
k8s优雅操作pod容器组
运维·云原生·k8s·pod
淡黄的Cherry5 小时前
Spring Cloud + Nacos + K8S 零影响发布方案
spring cloud·容器·kubernetes
钟离墨笺5 小时前
【Linux】【网络】IO多路复用 select、poll、epoll
linux·运维·网络