k8sday13数据存储(1.5/2)

目录

二、高级核心存储

1、PV

1.1配置文件

①、访问模式(accessModes)

②、回收策略(persistentVolumeReclaimPolicy)

③、存储类别

④、状态(Status)

1.2创建测试

①、准备NFS环境

②、创建PV

③、验证

2、PVC

1.1配置文件

1.2绑定引用测试

①、创建PVC

②、测试绑定

③、创建Pod准备测试

④、测试链路打通

3、注意事项

PV和PVC未绑定检查步骤

1、容量(Capacity)

2、访问模式(AccessModes)

3、可用状态(Status)

[4、StorageClassName 必须完全一致](#4、StorageClassName 必须完全一致)

4、生命周期

①、资源供应

②、资源绑定

③、资源使用

④、资源释放

⑤、资源回收


二、高级核心存储

​ 之前学过NFS提供存储配置,我们知道要进行存储数据要求用户会自己搭建NFS服务器,会在YAML文件中配置NFS,这显然对于用户来说,要求过高,而且k8s支持的存储系统类型多,要求用户熟知每个存储系统那是不现实的,所以k8s提出高级核心存储的概念(主要包含PV和PVC),二者通过连接绑定,最终实现用户只需要提出Pod的存储要求,而其底层实现由对应的管理员实现 。如图:

1、PV

集群级资源,独立于 Pod 生命周期。可由管理员静态 提前创建,也可通过 StorageClass 让系统自动动态供给。

1.1配置文件

以下给出一个NFS 类型的 PV 示例,供集群管理员提前"静态"创建,

复制代码
  # persistent-volume-nfs.yaml
  # 应用侧只需在 PVC 中声明相同 storageClassName 即可绑定。
  apiVersion: v1
  kind: PersistentVolume        # 声明资源类型是 PV
  metadata:
    name: pv-nfs-share          # PV 对象在集群中的名称,可自定义
    # 由于 PV 是集群级资源,所以没有 namespace 的概念
    labels:
      app: nfs-pv-demo          # 可按需添加 label,方便选择器匹配
  spec:
    capacity:
      storage: 2Gi              # 声明的容量,PVC 申请量需 ≤ 该值
    accessModes:                # 访问模式
      - ReadWriteMany           # 允许多节点同时读写
    persistentVolumeReclaimPolicy: Retain     # 回收策略
    storageClassName: nfs-slow  # 必须与下方对应 PVC 的 storageClassName 一致
    mountOptions:
      - nfsvers=4.1             # 挂载参数,按需调整
      - noatime
    nfs:                        # 存储类型
      server: 192.168.10.5      # NFS 服务器 IP 或域名
      path: /data/nfs/share     # NFS 导出的共享目录
①、访问模式(accessModes)

用于描述用户应用对存储资源的访问权限,访问权限包括下面几种方式:

  • ReadWriteOnce(RWO):读写权限,但是只能被单个节点挂载

  • ReadOnlyMany(ROX):只读权限,可以被多个节点挂载

  • ReadWriteMany(RWX):读写权限,可以被多个节点挂载

++需要注意的是,底层不同的存储类型可能支持的访问模式不同++

②、回收策略(persistentVolumeReclaimPolicy)

当 PV 不再被使用了之后,对其的处理方式。目前支持三种策略:

  • Retain(保留):PVC 删除后仅解除绑定,数据仍在,需要管理员手工清理数据

  • Recycle(回收):清除 PV 中的数据,已废弃,不推荐使用

  • Delete(删除):与 PV 相连的后端存储完成 volume 的删除操作,当然这常见于云服务商的存储服务

++需要注意的是,底层不同的存储类型可能支持的访问模式不同++

③、存储类别

PV可通过storageClassName参数指定一个存储类别

  • 具有了特定类别的PV只能与请求了改特定类别的PVC绑定

  • 没有指定类别的PV只能与不请求任何类别的PVC绑定

④、状态(Status)

一个PV的生命周期内,可能会有4个状态阶段:

  • Available(可用):未被任何PVC绑定

  • Bound(已绑定):PV已经和PVC绑定

  • Released(已释放):PV和PVC已解绑,PVC被删除,但是资源未被集群重新声明

  • Failed(失败):PV自动回收失败

1.2创建测试
①、准备NFS环境
bash 复制代码
  # 获取已有节点,找到control-plane容器记下输出容器内 IP( INTERNAL-IP )例如 172.18.0.4 
  kubectl get node -o wide
  ​
  # 进入控制面(control-plane)容器
  docker exec -it my-multi-node-cluster1-control-plane bash
  ​
  # ---- 容器内执行 ------
  # 更新并安装NFS服务(如果你已经安装过了就不用这一步了)
  apt update && apt install -y nfs-kernel-server
  ​
  # 创建共享目录
  mkdir /tmp/logs/{pv1,pv2,pv3} -pv
  # 把共享目录权限改成 "任何人可读可写可执行"
  chmod 777 /tmp/logs
  # 向 /etc/exports 追加一行 导出规则
  # 当然也可以手动进入 /etc/exports 然后编辑添加规则
  # 建议使用精准的网络白名单
  # 如172.18.0.0/24 只允许这一网段访问;写成 * 就是全网放通,风险高
  echo "/tmp/logs 172.18.0.0/24(rw,sync,no_subtree_check,no_root_squash)" > /etc/exports
  # 重新加载 /etc/exports 并立即生效
  exportfs -rav 
  # 重启 NFS 服务进程
  systemctl restart nfs-kernel-server
  # 如果不可用systemctl,可改为:
  service nfs-kernel-server restart
  ​
  # 退出控制面容器
  exit
②、创建PV
bash 复制代码
  # pv-nfs.yaml
  apiVersion: v1
  kind: PersistentVolume        # 声明资源类型是 PV
  metadata:
    name: pv1-nfs               # PV 对象在集群中的名称,可自定义
    # 由于 PV 是集群级资源,所以没有 namespace 的概念
    labels:
      app: pv1          # 可按需添加 label,方便选择器匹配
  spec:
    capacity:
      storage: 1Gi              # 声明的容量,PVC 申请量需 ≤ 该值
    accessModes:                # 访问模式
      - ReadWriteMany           # 允许多节点同时读写
    persistentVolumeReclaimPolicy: Retain     # 回收策略
    nfs:                        # 存储类型
      server: 172.18.0.4        # NFS 服务器 IP 或域名
      path: /tmp/logs/pv1       # NFS 导出的共享目录
    storageClassName: nfs-static         # 存储类别
  ---
  ​
  apiVersion: v1
  kind: PersistentVolume        # 声明资源类型是 PV
  metadata:
    name: pv2-nfs               # PV 对象在集群中的名称,可自定义
    # 由于 PV 是集群级资源,所以没有 namespace 的概念
    labels:
      app: pv2          # 可按需添加 label,方便选择器匹配
  spec:
    capacity:
      storage: 2Gi              # 声明的容量,PVC 申请量需 ≤ 该值
    accessModes:                # 访问模式
      - ReadWriteMany           # 允许多节点同时读写
    persistentVolumeReclaimPolicy: Retain     # 回收策略
    nfs:                        # 存储类型
      server: 172.18.0.4        # NFS 服务器 IP 或域名
      path: /tmp/logs/pv2       # NFS 导出的共享目录
    storageClassName: nfs-static         # 存储类别
  ---
  ​
  apiVersion: v1
  kind: PersistentVolume        # 声明资源类型是 PV
  metadata:
    name: pv3-nfs               # PV 对象在集群中的名称,可自定义
    # 由于 PV 是集群级资源,所以没有 namespace 的概念
    labels:
      app: pv3         # 可按需添加 label,方便选择器匹配
  spec:
    capacity:
      storage: 3Gi              # 声明的容量,PVC 申请量需 ≤ 该值
    accessModes:                # 访问模式
      - ReadWriteMany           # 允许多节点同时读写
    persistentVolumeReclaimPolicy: Retain     # 回收策略
    nfs:                        # 存储类型
      server: 172.18.0.4        # NFS 服务器 IP 或域名
      path: /tmp/logs/pv3       # NFS 导出的共享目录
    storageClassName: nfs-static         # 存储类别
③、验证
bash 复制代码
  # 创建PV
  kubectl create -f pv-nfs.yaml
  ​
  # 查看PV
  kubectl get pv -o wide

2、PVC

命名空间级资源,由用户/应用开发者创建。Kubernetes 的调度器负责把合适的 PV 绑定到这个 PVC 上。Pod 通过挂载 PVC,从而间接使用 PV

1.1配置文件
bash 复制代码
  # PVC 示例
  # 功能:向集群申请一块 3 GiB 的 NFS 存储,用于 Pod 挂载
  apiVersion: v1
  kind: PersistentVolumeClaim # 声明资源类型是 PVC
  metadata:
    name: pvc-logs            # PVC 在集群里的名字,Pod 通过这个名字引用
    namespace: default        # PVC 是命名空间级资源,按需改成自己的 ns
  spec:
    accessModes:
      - ReadWriteMany         # 必须与目标 PV 的 accessModes 完全一致
    resources:                # 请求空间
      requests:
        storage: 3Gi          # 申请的容量。只要 ≤ PV 的 capacity.storage 即可
    storageClassName: nfs-rwo # 存储类别
      # 1. 如果集群里给 NFS 手动创建的 PV 写了 storageClassName: nfs-rwo,
      #    这里就要写同样的值,才能匹配到该 PV(静态绑定)。
      # 2. 如果想走动态供给(StorageClass + NFS provisioner),
      #    则 storageClassName 指向对应的 StorageClass 名称即可;
      #    留空或写 "" 会落到集群的「默认 StorageClass」。
    # volumeName: pv-nfs-001  # 可选字段,强制绑定到某一台特定 PV
                              # 写死后即使其他 PV 更匹配也不会变,一般不建议用
    # selector:               # 可选,用 label 做更灵活的选择
    #   matchLabels:
    #     app: nfs-pv-demo

PVC的存储类别、访问模式、回收策略都与PV相同

1.2绑定引用测试
①、创建PVC
bash 复制代码
 # pvc-nfs.yaml
  apiVersion: v1
  kind: PersistentVolumeClaim # 声明资源类型是 PVC
  metadata:
    name: pvc1-nfs            # PVC 在集群里的名字,Pod 通过这个名字引用
    namespace: default        # PVC 是命名空间级资源,按需改成自己的 ns
  spec:
    accessModes:
      - ReadWriteMany         # 必须与目标 PV 的 accessModes 完全一致
    resources:                # 请求空间
      requests:
        storage: 1Gi          # 申请的容量。只要 ≤ PV 的 capacity.storage 即可
    storageClassName: nfs-static         # 存储类别
  ---
  ​
  apiVersion: v1
  kind: PersistentVolumeClaim # 声明资源类型是 PVC
  metadata:
    name: pvc2-nfs            # PVC 在集群里的名字,Pod 通过这个名字引用
    namespace: default        # PVC 是命名空间级资源,按需改成自己的 ns
  spec:
    accessModes:
      - ReadWriteMany         # 必须与目标 PV 的 accessModes 完全一致
    resources:                # 请求空间
      requests:
        storage: 1Gi          # 申请的容量。只要 ≤ PV 的 capacity.storage 即可
    storageClassName: nfs-static         # 存储类别
  ---
  ​
  apiVersion: v1
  kind: PersistentVolumeClaim # 声明资源类型是 PVC
  metadata:
    name: pvc3-nfs            # PVC 在集群里的名字,Pod 通过这个名字引用
    namespace: default        # PVC 是命名空间级资源,按需改成自己的 ns
  spec:
    accessModes:
      - ReadWriteMany         # 必须与目标 PV 的 accessModes 完全一致
    resources:                # 请求空间
      requests:
        storage: 4Gi          # 申请的容量。只要 ≤ PV 的 capacity.storage 即可
        # 当前第三个pvc的申请容量,超过所有pv的容量,所以无法绑定
    storageClassName: nfs-static         # 存储类别
②、测试绑定
bash 复制代码
  # 创建PVC
  kubectl create -f pvc-nfs.yaml
  ​
  # 查看PVC
  kubectl get pvc -o wide
  # 查看PV绑定情况
  kubectl get pv -o wide

如图:

③、创建Pod准备测试
bash 复制代码
  # 提供一个 Pod 准备进行 PVC → PV → NFS 链路打通测试
  apiVersion: v1
  kind: Pod
  metadata:
    name: test-pvc-mount        # Pod 名称,可随意改
  spec:
    containers:
    - name: nginx
      image: nginx:1.24.0
      ports:
      - containerPort: 80
      volumeMounts:
      - name: html              # 与 volumes.name 对应
        mountPath: /usr/share/nginx/html   # 容器内挂载点
    volumes:
    - name: html
      persistentVolumeClaim:
        claimName: pvc1-nfs     # 必须和已存在的 PVC 名字一致
    restartPolicy: Never        # 测试用,跑完即停;生产可用 Always
④、测试链路打通
bash 复制代码
  # 1. 应用文件,部署 Pod
  kubectl apply -f pod-test-pvc.yaml
  ​
  # 2. 验证部署成功
  kubectl get pod test-pvc-mount -w
  ​
  # 3. 进入 Pod 写文件
  kubectl exec -it test-pvc-mount -- sh -c 'echo "hello from pod" > /usr/share/nginx/html/index.html'
  ​
  # 4. 在 NFS 服务器或任何节点验证
  # 注意 my-multi-node-cluster1-control-plane 是我的 NFS 服务器名称,记得改为你自己的
  docker exec -it my-multi-node-cluster1-control-plane bash
  cat /tmp/logs/pv1/index.html
  # 应输出:hello from pod
  ​
  # 5. 清理
  kubectl delete -f pod-test-pvc.yaml

测试结果如下:

说明PVC → PV → NFS 链路打通,用户对于 Pod 的数据操作,实际存储在了与 Pod 连接的 PV,与 PV 绑定的 PVC 的存储系统之中,即 :用户→Pod→ PVC → PV → NFS(底层存储系统)

3、注意事项

PV和PVC未绑定检查步骤
1、容量(Capacity)

PVC 申请的 storage 必须 ≤ PV 声明的 capacity.storage,否则不会绑定。

bash 复制代码
  kubectl get pv,pvc -o wide
2、访问模式(AccessModes)

PVC 的 accessModes 必须是 PV 声明的访问模式的子集 。例:PV 只有 RWO,PVC 却要求 RWX,就会一直 Pending

bash 复制代码
  kubectl describe pvc <pvc-name>
3、可用状态(Status)

PV 必须是 Available;如果已被别的 PVC 绑走,就会是 Bound。• 若 PV 是 Released(前一个 PVC 被删但 reclaimPolicy=Retain),需要手动把它重新设为 Available

4、StorageClassName 必须完全一致

• 如果 PV 写了 storageClassName: nfs-rwo,PVC 必须也写 storageClassName: nfs-rwo。• 如果 PV 的 storageClassName: ""(空串),PVC 也必须写 storageClassName: "",不能省略。

bash 复制代码
  kubectl get pv <pv-name> -o jsonpath='{.spec.storageClassName}'
  kubectl get pvc <pvc-name> -o jsonpath='{.spec.storageClassName}'
资源 YAML 里 不写 storageClassName 字段时,实际值 说明
PV ""(空字符串) 明确等于空串,不会被当成任何 StorageClass,只能与同样为 "" 的 PVC 匹配。
PVC 集群中 标记为 default 的 StorageClass(通常是 standard 如果集群设置了 default StorageClass,PVC 会自动填上它的名字;如果没有 default,则也为 ""
  • PVC 没写 ⇒ 自动落到 standard

  • PV 也没写 ⇒ 等于 ""(空串)

    可能会导致二者无法匹配绑定

4、生命周期

PV和PVC遵循类似的生命周期:

①、资源供应
  • PV已创建,未绑定待使用
②、资源绑定
  • PV和对应的PVC绑定,如果找不到应绑定的PV,PVC会一直处于Pending状态,一旦绑定,PVC独占PV
③、资源使用
  • Pod使用PVC
④、资源释放
  • PVC使用完PV后,释放PV,PV处于Released状态
⑤、资源回收
  • 通过提前设定的回收策略回收PV,只有PV存储空间回收完成,才能提供给新的PVC绑定
相关推荐
chenglin01613 分钟前
ES_数据存储知识
java·服务器·elasticsearch
奔跑草-1 小时前
【服务器】Apache Superset功能、部署与体验
运维·服务器·apache·powerbi·superset
提笔惊蚂蚁1 小时前
终端VS命令解释器(Linux & Windows)
linux·运维·windows
Nimsolax1 小时前
Linux文件fd
linux
羊锦磊2 小时前
[ Servlet 服务器]
运维·服务器·servlet
星眠海雾2 小时前
k8s集合
云原生·容器·kubernetes
搬码临时工3 小时前
通过自定义域名访问内网的web服务和tcp应用:内网ip到局域网外域名访问过程
服务器·tcp/ip·php
小红帽2.04 小时前
从ioutil到os:Golang在线客服聊天系统文件读取的迁移实践
服务器·开发语言·golang
逢生博客4 小时前
Ubuntu 安装 gvm 管理 Go 语言开发环境
linux·ubuntu·golang·gvm