k8s-存储(pv/pvc)

简介: pv 介绍pvc 介绍存储基本组件PV 类型PV 卷阶段状态插件实现方法NFS 实现存储NFS 静态存储NFS-CSI 动态存储

Volumn和PV的关系



image.png


Volumn卷


属于 Pod 内部共享资源存储,生命周期和 Pod 相同,与 Container 无关,即使 Pod 上的容 器停止或者重启,Volume 不会受到影响,但是如果 Pod 终止,那么这个 Volume 的生命周 期也将结束。



存储的基本组件



在 k8s 中 对 于 存 储 的 资 源 抽 象 了 两 个 概 念 , 分 别 是 PersistentVolume(PV)和PersistentVolumeClaim(PVC)。


PV 是集群中的资源


PVC 是对这些资源的请求



PV 和 PVC 都只是抽象的概念,在 k8s 中是通过插件的方式提供具体的存储实现。

目前包含 有 NFS、ceph、iSCSI 和云提供商指定的存储系统



image.png


管理存储是管理计算的一个明显问题。


该 PersistentVolume 子系统为用户和管理员提供 了一个 API,用于抽象如何根据消费方式提供存储的详细信息。


为此,我们引入了两个新的 API 资源:PersistentVolume 和 PersistentVolumeClaim



PV/PVC/StorageClass


PersistentVolume(持久化卷):


是对底层的共享存储的一种抽象,PV 由管理员 进行创建和配置,它和具体的底层的共享存储技术的实现方式有关,比如 Ceph、GlusterFS、 NFS 等,都是通过插件机制完成与共享存储的对接



PersistentVolumeClaim(PVC):


是由用户进行存储的请求。 它类似于 pod。 Pod 消耗 节点资源,PVC 消耗 PV 资源。Pod 可以请求特定级别的资源(CPU 和内存)。声明可以请 求特定的大小和访问模式(例如,可以一次读/写或多次只读)。





StorageClass :


为管理员提供了一种描述他们提供的存储的“类”的方法。

不同的类可能映 射到服务质量级别,或备份策略,或者由群集管理员确定的任意策略。

Kubernetes 本身对于什么类别代表是不言而喻的。 这个概念有时在其他存储系统中称为“配置文件”。



PV 是运维人员来创建的,开发操作 PVC,可是大规模集群中可能会有很多 PV,如果这 些 PV 都需要运维手动来处理这也是一件很繁琐的事情,所以就有了动态供给概念.


也就是 Dynamic Provisioning,动态供给的关键就是 StorageClass,它的作用就是创建 PV 模板。


创 建 StorageClass 里面需要定义 PV 属性比如存储类型、大小等;另外创建这种 PV 需要用到 存储插件。最终效果是,用户提交PVC,里面指定存储类型,如果符合我们定义的StorageClass, 则会为其自动创建 PV 并进行绑定


PVC 和 PV 是一一对应



PV 和 PVC 中的 spec 关键字段要匹配,比如存储(storage)大小。


PV 和 PVC 中的 storageClassName 字段必须一致。




四个概念的关系


image.png




Kubernetes 中 存 储 中 有 四 个 重 要 的 概 念 : Volume 、 PersistentVolume ( PV )、 PersistentVolumeClaim(PVC)、StorageClass。




声明周期


PV 是群集中的资源。PVC 是对这些资源的请求,并且还充当对资源的检查。

PV 和 PVC 之间的相互作用遵循以下生命周期:


Provisioning ——-> Binding ——–>Using——>Releasing——>Recycling



供应准备 Provisioning


通过集群外的存储系统或者云平台来提供存储持久化支持



- 静态提供 Static:集群管理员创建多个 PV。 它们携带可供集群用户使用的真实存储的详 细信息。 它们存在于 Kubernetes API 中,可用于消费


- 动态提供 Dynamic:当管理员创建的静态 PV 都不匹配用户的 PersistentVolumeClaim 时, 集群可能会尝试为 PVC 动态配置卷。 此配置基于 StorageClasses:PVC 必须请求一个类, 并且管理员必须已创建并配置该类才能进行动态配置。 要求该类的声明有效地为自己禁用 动态配置。



绑定 Binding


用户创建 pvc 并指定需要的资源和访问模式。在找到可用 pv 之前,pvc 会 保持未绑定状态。



使用 Using


用户可在 pod 中像 volume 一样使用 pvc。




释放 Releasing


用户删除 pvc 来回收存储资源,pv 将变成“released”状态。由于还保留着 之前的数据,这些数据需要根据不同的策略来处理,否则这些存储资源无法被其他 pvc 使 用。



回收Recycling



pv可以设置三种回收策略:保留(Retain),回收(Recycle)和删除(Delete)。


  • 保留策略:允许人工处理保留的数据。
  • 删除策略:将删除 pv 和外部关联的存储资源,需要插件支持。
  • 回收策略:将执行清除操作,之后可以被新的 pvc 使用,需要插件支持。 注:目前只有 NFS 和 HostPath 类型卷支持回收策略,AWS EBS,GCE PD,Azure Disk 和 Cinder 支持删除(Delete)策略



PV 类型


  • GCEPersistentDisk
  • AWSElasticBlockStore
  • AzureFile AzureDisk
  • FC (Fibre Channel)
  • Flexvolume
  • NFS
  • iSCSI
  • RBD (Ceph Block Device)
  • CephFS
  • Cinder (OpenStack block storage)
  • Glusterfs
  • VsphereVolume
  • Quobyte Volumes
  • StorageOS


PV 卷阶段状态


  • Available – 资源尚未被 claim 使用
  • Bound – 卷已经被绑定到 claim 了
  • Released – claim 被删除,卷处于释放状态,但未被集群回收。
  • Failed – 卷自动回收失败




k8s存储架构图



image.png


Kubernetes 卷插件实现方法



In Tree


Kubernetes 卷插件目前是“in-tree”,意味着它们与核心 kubernetes 二进制文件链接,编译, 构建和一起发布。


有不利于核心代码的发布,增加了工作量,并且卷插件的权限太高等缺点 需要将后端存储的代码逻辑放到 K8S 的代码中运行。逻辑代码可能会引起与 K8S 其他部件 之间的相互影响




image.png




Out-of-tree Provisioner-FlexVolume


现有的 Flex Volume 插件需要访问节点和主机的根文件系统才能部署第三方驱动程序文件, 并且对主机的依赖性强.


调用一个主机的可执行程序包的方式执行存储卷的挂载使用。


解决了 In-Tree 方式的强耦合, 不过命令行调用的方式,在主机安全性、部署依赖的容器化、与 K8S 服务之间的相互扩展性 等方面存在不足Flexvolume 运行在 host 空间,不能使用 rbac授权机制访问Kubernetes API, 导致其功能极大的受限 Storage providers support this type and develop Driver




image.png







Out-of-tree Provisioner -CSI


容器存储接口(CSI)是由来自各个 CO 的社区成员(包括 Kubernetes,Mesos,Cloud Foundry 和 Docker)之间的合作产生的规范。


此接口的目标是为 CO 建立标准化机制,以将任意存 储系统暴露给其容器化工作负载。


CSI 标准使 K8S 和存储提供者之间将彻底解耦,将存储的所有的部件作为容器形式运行在 K8S 上。 CO Container Orchestrer Storage providers support this type and develop Driver





image.png


NFS实现存储


创建一个 NFS 服务器作为 K8s 的存储系统, nfs 默认不支持动态存储。


使用了第三方的 NFS 插件 实现 flexvolume and CSI 方式使用存 储。



image.png




NFS服务建立



  1. 安装nfs-server
yum install nfs-utils rpcbind -y
systemctl enable rpcbind nfs-server
systemctl start rpcbind nfs-server
systemctl status rpcbind nfs-server



  1. 创建共享目录
mkdir /nfs-server


  1. 配置共享目录
vi /etc/exports  # 编辑或创建/etc/exports文件
/nfs-server *(rw,sync,no_root_squash   # 配置nfs-server

image.png


  1. 对/etc/exports 增加或修改的部分进行挂载和卸载
exportfs -a

注意: exportfs 命令,参考 https://wker.com/linux-command/exportfs.html



Client 安装NFS服务


Note: 在每一个节点都需要安装NFS服务



yum install nfs-utils rpcbind -y
systemctl enable rpcbind nfs-server
systemctl start rpcbind nfs-server
systemctl status rpcbind nfs-server



测试共享卷是否可用


showmount -e 192.168.56.5   # nfs server 的ip
mount -t nfs 192.168.56.5:/nfs-server /home   # bind 共享卷
umount /home   # unbind 共享卷



NFS共享存储实践



静态供应



  1. 创建PV


pv1.yaml


apiVersion: v1
kind: PersistentVolume
metadata:
 name: pv0001
spec:
 capacity:
  storage: 5Gi
 accessModes:
  - ReadWriteMany
 persistentVolumeReclaimPolicy: Recycle
 nfs:
   path: "/nfs-server"
   server: 192.168.10.201


  1. 创建PVC


pvc1.yaml


apiVersion: v1
kind: PersistentVolumeClaim
metadata:
 name: nfs-pvc
spec:
 accessModes:
 - ReadWriteMany
 resources:
  requests:
   storage: 1Gi


  1. 创建Pod


pod1.yaml


kind: Pod
apiVersion: v1
metadata:
 name: nfs-test
spec:
 containers:
  - name: my-busybox
    image: busybox
    volumeMounts:
    - mountPath: "/data"
      name: sample-volume
    command: ["sleep", "1000000"]
    imagePullPolicy: IfNotPresent
 volumes:
  - name: sample-volume
    persistentVolumeClaim:
      claimName: nfs-pvc


  1. 测试


进入 pod容器中,在/data目录创建一个test.txt文件


image.png


查看nfs-server 是否包含共享了test.txt文件


image.png




NFS CSI类型动态供应




NFS CSI Driver 是 K8s 官方提供的 CSI 示例程序,只实现了 CSI 的最简功能 Controller 由 CSI Plugin+csi-provisioner+livenessprobe 组成 node-server 由 CSI Plugin+liveness-probe+node-driver-registrar 组成



安装CSI组件


rbac-csi.yaml 文件配置

---apiVersion: v1
kind: ServiceAccount
metadata:  name: csi-nfs-controller-sa
  namespace: kube-system
---kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:  name: nfs-external-provisioner-role
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: ["get","list","watch","create","update","patch"]  - apiGroups: ["storage.k8s.io"]    resources: ["csinodes"]    verbs: ["get","list","watch"]  - apiGroups: [""]    resources: ["nodes"]    verbs: ["get","list","watch"]  - apiGroups: ["coordination.k8s.io"]    resources: ["leases"]    verbs: ["get","list","watch","create","update","patch"]  - apiGroups: [""]    resources: ["secrets"]    verbs: ["get"]---kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:  name: nfs-csi-provisioner-binding
subjects:  - kind: ServiceAccount
    name: csi-nfs-controller-sa
    namespace: kube-system
roleRef:  kind: ClusterRole
  name: nfs-external-provisioner-role
  apiGroup: rbac.authorization.k8s.io


csi-nfs-driverinfo.yaml 文件配置

---apiVersion: storage.k8s.io/v1
kind: CSIDriver
metadata:  name: nfs.csi.k8s.io
spec:  attachRequired: false  volumeLifecycleModes:    - Persistent
    - Ephemeral




csi-nfs-node.yaml 文件配置



---# This YAML file contains driver-registrar & csi driver nodeplugin API objects# that are necessary to run CSI nodeplugin for nfskind: DaemonSet
apiVersion: apps/v1
metadata:  name: csi-nfs-node
  namespace: kube-system
spec:  updateStrategy:    rollingUpdate:      maxUnavailable: 1    type: RollingUpdate
  selector:    matchLabels:      app: csi-nfs-node
  template:    metadata:      labels:        app: csi-nfs-node
    spec:      hostNetwork: true  # original nfs connection would be broken without hostNetwork setting      dnsPolicy: ClusterFirstWithHostNet
      nodeSelector:        kubernetes.io/os: linux
      tolerations:        - operator: "Exists"      containers:        - name: liveness-probe
          image: registry.cn-hangzhou.aliyuncs.com/liuyik8s/livenessprobe:v2.5.0
          args:            - --csi-address=/csi/csi.sock
            - --probe-timeout=3s
            - --health-port=29653
            - --v=2
          volumeMounts:            - name: socket-dir
              mountPath: /csi
          resources:            limits:              memory: 100Mi
            requests:              cpu: 10m
              memory: 20Mi
        - name: node-driver-registrar
          image: registry.cn-hangzhou.aliyuncs.com/liuyik8s/csi-node-driver-registrar:v2.4.0
          args:            - --v=2
            - --csi-address=/csi/csi.sock
            - --kubelet-registration-path=$(DRIVER_REG_SOCK_PATH)
          livenessProbe:            exec:              command:                - /csi-node-driver-registrar
                - --kubelet-registration-path=$(DRIVER_REG_SOCK_PATH)
                - --mode=kubelet-registration-probe
            initialDelaySeconds: 30            timeoutSeconds: 15          env:            - name: DRIVER_REG_SOCK_PATH
              value: /var/lib/kubelet/plugins/csi-nfsplugin/csi.sock
            - name: KUBE_NODE_NAME
              valueFrom:                fieldRef:                  fieldPath: spec.nodeName
          volumeMounts:            - name: socket-dir
              mountPath: /csi
            - name: registration-dir
              mountPath: /registration
          resources:            limits:              memory: 100Mi
            requests:              cpu: 10m
              memory: 20Mi
        - name: nfs
          securityContext:            privileged: true            capabilities:              add: ["SYS_ADMIN"]            allowPrivilegeEscalation: true          image: mcr.microsoft.com/k8s/csi/nfs-csi:v3.1.0
          args:            - "-v=5"            - "--nodeid=$(NODE_ID)"            - "--endpoint=$(CSI_ENDPOINT)"          env:            - name: NODE_ID
              valueFrom:                fieldRef:                  fieldPath: spec.nodeName
            - name: CSI_ENDPOINT
              value: unix:///csi/csi.sock
          ports:            - containerPort: 29653              name: healthz
              protocol: TCP
          livenessProbe:            failureThreshold: 5            httpGet:              path: /healthz
              port: healthz
            initialDelaySeconds: 30            timeoutSeconds: 10            periodSeconds: 30          imagePullPolicy: "IfNotPresent"          volumeMounts:            - name: socket-dir
              mountPath: /csi
            - name: pods-mount-dir
              mountPath: /var/lib/kubelet/pods
              mountPropagation: "Bidirectional"          resources:            limits:              memory: 300Mi
            requests:              cpu: 10m
              memory: 20Mi
      volumes:        - name: socket-dir
          hostPath:            path: /var/lib/kubelet/plugins/csi-nfsplugin
            type: DirectoryOrCreate
        - name: pods-mount-dir
          hostPath:            path: /var/lib/kubelet/pods
            type: Directory
        - hostPath:            path: /var/lib/kubelet/plugins_registry
            type: Directory
          name: registration-dir


csi-nfs-controller.yaml 文件配置


---kind: Deployment
apiVersion: apps/v1
metadata:  name: csi-nfs-controller
  namespace: kube-system
spec:  replicas: 2  selector:    matchLabels:      app: csi-nfs-controller
  template:    metadata:      labels:        app: csi-nfs-controller
    spec:      hostNetwork: true  # controller also needs to mount nfs to create dir      dnsPolicy: ClusterFirstWithHostNet
      serviceAccountName: csi-nfs-controller-sa
      nodeSelector:        kubernetes.io/os: linux  # add "kubernetes.io/role: master" to run controller on master node      priorityClassName: system-cluster-critical
      tolerations:        - key: "node-role.kubernetes.io/master"          operator: "Exists"          effect: "NoSchedule"        - key: "node-role.kubernetes.io/controlplane"          operator: "Exists"          effect: "NoSchedule"      containers:        - name: csi-provisioner
          image: registry.cn-hangzhou.aliyuncs.com/liuyik8s/csi-provisioner:v2.2.2
          args:            - "-v=2"            - "--csi-address=$(ADDRESS)"            - "--leader-election"          env:            - name: ADDRESS
              value: /csi/csi.sock
          volumeMounts:            - mountPath: /csi
              name: socket-dir
          resources:            limits:              memory: 400Mi
            requests:              cpu: 10m
              memory: 20Mi
        - name: liveness-probe
          image: registry.cn-hangzhou.aliyuncs.com/liuyik8s/livenessprobe:v2.5.0
          args:            - --csi-address=/csi/csi.sock
            - --probe-timeout=3s
            - --health-port=29652
            - --v=2
          volumeMounts:            - name: socket-dir
              mountPath: /csi
          resources:            limits:              memory: 100Mi
            requests:              cpu: 10m
              memory: 20Mi
        - name: nfs
          image: mcr.microsoft.com/k8s/csi/nfs-csi:v3.1.0
          securityContext:            privileged: true            capabilities:              add: ["SYS_ADMIN"]            allowPrivilegeEscalation: true          imagePullPolicy: IfNotPresent
          args:            - "-v=5"            - "--nodeid=$(NODE_ID)"            - "--endpoint=$(CSI_ENDPOINT)"          env:            - name: NODE_ID
              valueFrom:                fieldRef:                  fieldPath: spec.nodeName
            - name: CSI_ENDPOINT
              value: unix:///csi/csi.sock
          ports:            - containerPort: 29652              name: healthz
              protocol: TCP
          livenessProbe:            failureThreshold: 5            httpGet:              path: /healthz
              port: healthz
            initialDelaySeconds: 30            timeoutSeconds: 10            periodSeconds: 30          volumeMounts:            - name: pods-mount-dir
              mountPath: /var/lib/kubelet/pods
              mountPropagation: "Bidirectional"            - mountPath: /csi
              name: socket-dir
          resources:            limits:              memory: 200Mi
            requests:              cpu: 10m
              memory: 20Mi
      volumes:        - name: pods-mount-dir
          hostPath:            path: /var/lib/kubelet/pods
            type: Directory
        - name: socket-dir
          emptyDir: {}


storageclass-nfs.yaml 文件配置


---apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:  name: nfs-csi
provisioner: nfs.csi.k8s.io
parameters:  server: 192.168.56.5  #修改为自己的nfs的服务器地址  share: /nfs-server  #修改为nfs的目录reclaimPolicy: Retain  # only retain is supported,目前这个回收策略只支持RetainvolumeBindingMode: Immediate
mountOptions:  - hard
  - nfsvers=4.1



安装CSI


kubectl apply -f rbac-csi.yaml
kubectl apply -f csi-nfs-driverinfo.yaml
kubectl apply -f csi-nfs-node.yaml
kubectl apply -f csi-nfs-controller.yaml
kubectl apply -f storageclass-nfs.yaml



官网连接更新参考:

https://artifacthub.io/packages/helm/keyporttech/csi-driver-nfs/0.1.4https://github.com/kubernetes-csi/csi-driver-nfs/blob/master/deploy/example/README.md



CSI动态供应存储创建 PVC/POD


Deployment 无状态使用



pod-pvc-csi.yaml 文件配置

apiVersion: v1
kind: PersistentVolumeClaim
metadata:   name: nfs2
#   annotations:#    hitachi.io/note: "pvc-sample"spec:   accessModes:   - ReadWriteOnce
   resources:      requests:         storage: 5Gi
   storageClassName: nfs-csi      # 指定className,动态创建pv---kind: Pod
apiVersion: v1
metadata:  name: nfs-test-csi
spec:  containers:    - name: my-busybox
      image: busybox
      volumeMounts:      - mountPath: "/data"        name: sample-volume
      command: ["sleep","1000000"]      imagePullPolicy: IfNotPresent
  volumes:    - name: sample-volume
      persistentVolumeClaim:        claimName: nfs2


安装 pod-pvc-csi.yaml


kubectl apply -f pod-pvc-csi.yaml



image.png



查看pvc


image.png



查看storageClassName



image.png




测试


进入 nfs-test-csi 容器中,创建 test-csi.txt

image.png


查看nfs-server的共享卷


image.png



Statefulset 有状态使用


apiVersion: v1
kind: Service
metadata:  name: nginx
  labels:    app: nginx
spec:  ports:  - port: 80    name: web
  clusterIP: None
  selector:    app: nginx
---apiVersion: apps/v1
kind: StatefulSet
metadata:  name: web
spec:  serviceName: "nginx"  replicas: 3  selector:    matchLabels:      app: nginx
  volumeClaimTemplates:  - metadata:      name: test
      annotations:        volume.beta.kubernetes.io/storage-class: "nfs-csi"    spec:      accessModes: ["ReadWriteOnce"]      resources:        requests:          storage: 2Gi
#----  template:    metadata:      labels:        app: nginx
    spec:      containers:      - name: nginx
        image: nginx:1.9        ports:        - containerPort: 80          name: web
        volumeMounts:        - name: test
          readOnly: false          mountPath: "/usr/share/nginx/html"






相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
4月前
|
存储 Kubernetes Linux
解决Linux中/var/lib/docker/磁盘空间过大及k8s存储卷磁盘空间使用率过高的问题
解决Linux中/var/lib/docker/磁盘空间过大及k8s存储卷磁盘空间使用率过高的问题
146 0
|
1月前
|
存储 运维 Kubernetes
K8S基于NFS来动态创建PV【亲测可用】
K8S基于NFS来动态创建PV【亲测可用】
73 2
|
4月前
|
存储 Kubernetes Docker
k8s持久化储存:pv,pvc和nfs等相关技术
k8s持久化储存:pv,pvc和nfs等相关技术
|
4月前
|
存储 Kubernetes Cloud Native
云原生|kubernetes|持久化存储pv,pvc和StorageClass的学习
云原生|kubernetes|持久化存储pv,pvc和StorageClass的学习
123 0
|
4月前
|
存储 Kubernetes 关系型数据库
kubernetes学习之持久化存储StorageClass(4---nfs存储服务)
kubernetes学习之持久化存储StorageClass(4---nfs存储服务)
47 0
|
4月前
|
存储 Kubernetes 安全
k8s学习-持久化存储(Volumes、hostPath、emptyDir、PV、PVC)详解与实战
k8s学习-持久化存储(Volumes、hostPath、emptyDir、PV、PVC)详解与实战
67 0
|
4月前
|
存储 Kubernetes API
k8s实战系列:3-存储的花样玩法(下)
k8s实战系列:3-存储的花样玩法(下)
28 0
|
4月前
|
存储 Kubernetes Cloud Native
k8s实战系列:3-存储的花样玩法(上)
k8s实战系列:3-存储的花样玩法(上)
43 0
|
4月前
|
存储 Kubernetes 对象存储
Kubernetes存储:Ceph架构,部署和使用
Kubernetes存储:Ceph架构,部署和使用
78 0
|
4月前
|
存储 Kubernetes Unix
k8s教程(Volume篇)-CSI存储机制详解
k8s教程(Volume篇)-CSI存储机制详解
276 0
k8s教程(Volume篇)-CSI存储机制详解

推荐镜像

更多