十五、K8S-持久卷PV和PVC

目录

一、感念:

1、Persistent Volume(PV)

2、Persistent Volume Claim(PVC)

二、PV和PVC工作原理

1、资源供应(Provisioning)

2、资源绑定(Binding)

3、资源使用(Using)

4、资源回收(Reclaiming)

1、保留数据:

2、Deleted(删除数据):

3、Recycled(回收策略):

5、PVC资源扩容

 三、PV详解

1、存储容量(Capacity):

2、存储卷的模式(Volume Modes):

3、访问模式(Access Modes):

4、存储类别(Class):

5、回收策略(Reclaim Policy):

6、挂载选项:

7、节点亲和性(Node Affinity):

8、storageClassName:

四、PVC详解 

1、资源请求(resources):

2、访问模式(accessModes):

3、存储卷设置(volumeMode):和PV相同

4、PV条件选择(selector):

5、存储类别(Class):

五、StorageClass详解

六、配置pod以使用persistentVolume作为存储

1、创建一个hostPath类型的PersistentVolume

2、创建一个PersistentVolumeClaim,pod使用pvc来请求物理存储

3、创建一个使用PVC作为存储卷的pod

七:注意事项:

创建PVC之后,一直绑定不上

创建挂载了pvc的pod 之后 一直处于Pending状态

八、PVC的自动化部署,使用StatefulSet实现自动创建PV和PVC

1、搭建NFS共享存储再此不做演示,

2、创建rbac授权

3、创建nfs-deployment资源

4、创建storageclass

5、创建StatefulSet,自动生成pvc并绑定pv。yaml文件详解请参照K8S-statefulset

6、在pod资源内创建数据并访问测试

7、删除其中一个pod,查看该pod的数据是否会重新创建并存在

配置pod使用PV官网

一、感念:

        为了能够屏蔽底层存储实现的细节,让用户方便使用及管理员方便管理,引入了Persistent Volume(PV)和Persistent Volume Claim(PVC)两个资源对象。

1、Persistent Volume(PV)

        是集群中由管理员创建和、配置的一段网络存储,他是通过插件式的机制进行管理,供应用访问和使用,PV的声明周期独立于使用它的Pod

2、Persistent Volume Claim(PVC)

是由用户进行存储的请求,就像pod消耗node资源一样,PVC消耗PV资源

二、PV和PVC工作原理

        我们可以将PV看做可用的存储资源,PVC则是对存储资源的请求,并且还充当对资源的检查,

        PV和PVC的生命周期包括:资源供应(Provisioning)、资源绑定(Binding)、资源使用(Using)、资源回收(Reclaiming)几个阶段.

1、资源供应(Provisioning)

        支持两种资源供应模式:静态模式、动态模式,资源供应的结果就是将适合的PV与PVC成功绑定。

        静态模式:集群管理员预先创建许多PV,在PV的定义中能够体现存储资源的特性。

        动态模式:集群管理员无需预先创建PV,而是通过StorageClass的设置对后端存储资源进行描述,标记存储的类型和特性。用户通过创建PVC对存储类型进行申请,系统将自动完成pv的创建和于PVC的绑定。如果PVC声明的Class为“”,则说明PVC不适用动态模式。另外,k8s支持设置集群范围内弄人的StorageClass设置,通过kube-apiserver开启准入控制器DefaultStorageClass,可以为用户创建PVC设置一个默认的存储类StorageClass.

2、资源绑定(Binding)

        在用户定义好PVC之后,系统将根据PVC对存储资源的请求,在已存在的pv中选择一个满足PVC要求的pv,一旦找到,就将该pv于用户定义的PVC绑定,用户的应用就可以使用这个PVC了。如果在系统中没有满足pvc要求的pv,pvc则会无限期处于Pending状态,直到管理员创建了符合其要求的pv。他俩的关系是一对一的,不存在一对多的情况。

        如果资源供应使用的是动态模式,则系统在为pvc找到合适的StroageClass后,将自动创建一个pv并完成与pvc的绑定

3、资源使用(Using)

        Pod需要使用存储资源时,需要在Volume的定义中引用PVC类型的存储卷,将pvc挂载到容器内的某个路径下进行使用,Volume的类型字段为:"persistentVolumeClaim"。Pod在挂载pvc之后,就能使用存储资源了。同一个pvc可以被多个pod同时挂载使用,

4、资源回收(Reclaiming)

        用户在使用存储资源完毕后,可以删除pvc,与该pvc绑定 的pv将被标记为“已释放”,但还不能立刻与其他的pvc绑定,可以设置3中回收策略:Retained(保留)、Deleted(删除)、和Recycled(回收,已被弃用)

1、保留数据:

        Retained策略表示在删除pvc之后,与之绑定的pv不会被删除,仅被标记为已释放。pv的数据仍然存在,在清空之前不能被新的pvc使用,需要管理员手工清理之后才能继续使用。

清理步骤:

  1. 删除pv资源对象,
  2. 手工清理pv后端存储资产中的数据

  3. 手工删除后端存储资产。

2、Deleted(删除数据):

        Deleted表示自动删除pv资源对象和相关的后端存储资产,并不是多有类型的存储提供商都支持Deleted策略。

3、Recycled(回收策略):

        已被弃用,不用解释,建议使用以动态供应机制管理容器所需要的存储资源

5、PVC资源扩容

        如果要扩容pvc,则首先需要在pvc对应的StorageClass定义中设置 allowVolumeExpansion=true。如下代码:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: example-vol-default
provisioner: vendor-name.example/magicstorage
parameters:
  resturl: "http://192.168.10.100:8080"
  restuser: ""
  secretNamespace: ""
  secretName: ""
allowVolumeExpansion: true

        对pvc进行扩容时,只需要修改pvc的定义,将resources.requests.storage设置为一个更大的值即可。

        此外,存储资源扩容还存在以下几种情况

1、CSI类型存储卷的扩容

2、包含文件系统存储卷的扩容

3、使用中的pvc在线扩容

        :使用该功能需要设置kube-apiserver、kube-controller-manager、kubelet服务的启动参数

--feature-gates=ExpandInUsePersistentVolumes=true来开启该特性的开关,pvc在线扩容机制要求使用了pvc的pod成功运行,对于没被任何pod使用的pvc,不会有实际的扩容效果。

4、扩容失败的恢复机制:

        如果扩容资源存储机制失败,则集群管理员可以手工恢复pvc的状态并且取消之前的扩容请求。否则系统将不断尝试扩容请求。

执行恢复操作步骤:

1、设置与pvc绑定的pv资源的回收策略为“Retained",

2、删除PVC,此时pv的数据仍然存在;

3、删除PV中的clainmRef定义,这样新的PVC可以与之绑定,结果将使得PV的状态为“Available"

4、新建一个pvc,设置比pv空间小的存储空间申请,同时设置volumeName字段为pv的名称,结果将使得pv和PVC完成绑定,恢复PVC的原回收策略。

 三、PV详解

        PV作为存储资源的定义,主要涉及存储能力、访问模式、存储类型、回收策略、后端存储类型等关键信息的设置。详情如下:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0003
spec:
  capacity:#存储容量
    storage: 5Gi #5Gi存储空间
  volumeMode: Filesystem #存储卷模式为 Filesystem、
  accessModes: #访问模式
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle #回收策略
  storageClassName: slow  #名字需要与storageClass中名字一样
  mountOptions: #设置挂载选项
    - hard
    - nfsvers=4.1
  nfs: #设置后端的存储类型为nfs
    path: /tmp
    server: 172.17.0.2

1、存储容量(Capacity):

        目前仅支持storage=xx

2、存储卷的模式(Volume Modes):

        包括,Filesystem(文件系统,默认值)和Block(块设备)。文件系统模式的pv将以目录形式挂载到pod内。

3、访问模式(Access Modes):

        PV存储卷在挂载到宿主机上时,可以设置不同的访问模式,有以下几种

        1、ReadWriteOnce(RWO):读写权限,并且只能被单个node挂载

        2、ReadOnlyMany(ROX):只读权限,允许被多个node挂载

        3、ReadWriteany(RWX):读写权限,允许被多个node挂载

        4、ReadWriteOncePod:允许单个pod以读写方式挂载

PV支持多种访问模式,但是挂载时只能使用一个访问模式,多种访问模式不能同时生效。

4、存储类别(Class):

        PV可以设定其存储类别,通过storageClassName参数指定一个StorageClass资源对象的名称。

5、回收策略(Reclaim Policy):

        通过PV定义中 persistentVolumeReclaimPolicy字段进行设置,可选项如下:

        1、Retailed:保留数据,需要手工处理

        2、Recycle:简单清除文件的操作

        3、Delete :于PV相连的后端存储完成Volume的删除操作

6、挂载选项:

7、节点亲和性(Node Affinity):

        pv可以设置节点亲和性来限制只能通过某些Node访问Volume,可以在PV定义的nodeAffinity字段中进行设置。使用这些volume的Pod将被调度到满足条件的Node上。对于大多数卷而言,不需要手工设置,都自动完成了设置,对于Local类型的PV,需要手工设置。详细信息见官网

8、storageClassName:

        pv的类,可以说是一个类名,PVC和PV的这个名字一样,才能被绑定。

PV的生命周期:

1、Available:可用状态

2、Bound:已于某个PVC绑定

3、Released:与之绑定的PVC已被删除,但未完成资源回收,不能被其他PVC使用

4、Failed:自动资源回收失败

定义完pv资源之后,就需要通过定义PVC来使用PV资源了

四、PVC详解 

        PVC作为用户对存储资源的需求申请,主要涉及存储空间请求,访问模式、PV选择条件、存储类别等信息的设置,如下:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: myclaim
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 2Gi
  storageClassName: slow
  selector:
    matchLabels:
      release: "stable"
    matchExpressions:
      - {key: environment, operator: In, values: [dev]}

说明:

1、资源请求(resources):

        描述对存储资源的请求,通过resources.requests.storage字段设置需要的存储空间大小

2、访问模式(accessModes):

        PVC也可以设置访问模式,模式必须与pv相同

3、存储卷设置(volumeMode):和PV相同

4、PV条件选择(selector):

        通过Label Selector的设置,可使PVC对于系统中已存在的各种PV进行筛选。选择条件可以使用matchLabels和matchExpressions进行设置,如果两个字段都设置了,则两个条件必须同时满足才能完成匹配。

5、存储类别(Class):

        PVC在定义时可以设定需要的后端存储的类别(通过storageClassName 字段指定),以减少对后端存储特性的详细信息的依赖。只有设置了该Class的PV才能被系统选出,并与该PVC进行绑定。

注意:当selector和Class都进行了设置时,系统将选择两个条件同时满足的pv与之匹配。

另外,如果PVC设置了Selector,则系统无法使用动态供给模式为其分配PV。

五、StorageClass详解

        StorageClass是一个存储类,通过创建StorageClass可以动态生成一个存储卷,创建存储类对象时,除了名称之外,还需要为其定义三个关键字段:provisioner,parameters和reclaimPolicy。当管理员设置 StorageClass 对象的命名和其他参数,一旦创建了对象就不能再对其更新。

        资源清单

apiVersion: storage.k8s.io/v1 #api版本
kind: StorageClass   #类型
metadata:            #元数据
  name: nfs-storage
  #annotations:
    #storageclass.kubernetes.io/is-default-class: "true"  #是否设置为默认的storageclass
provisioner: nfs-client #---动态卷分配者名称,必须和上面创建的"PROVISIONER_NAME"变量中设置的Name一致
parameters:
  archiveOnDelete: "true" #---设置为"false"时删除PVC不会保留数据,"true"则保留数据
#允许卷扩展,PersistentVolume 可以配置成可扩展的卷。将此功能设置为true时,允许用户通过编辑相应的 PVC 对象来调整卷大小。
#此功能仅用于扩容卷,不能用于缩小卷    
allowVolumeExpansion: true 

六、配置pod以使用persistentVolume作为存储

创建过程:

  1. 作为集群管理员创建由物理存储支持的PersistentVolume,这不会与任何pod关联
  2. 创建一个PersistentVolumeClaim,它将自动绑定到合适的PersistentVolume上
  3. 创建一个使用PersistentVolumeClaim作为存储的Pod.

1、创建一个hostPath类型的PersistentVolume

apiVersion: v1
kind: PersistentVolume
metadata:
  name: task-pv-volume
  labels:
    type: local
spec:
  storageClassName: manual
  capacity:
    storage: 2Gi
  accessModes:
  - ReadWriteOnce  
  hostPath:
    path: "/k8s/kubernetes/cfg/test/pv-pvc-test"
[root@k8s-master-1 pv-pvc-test]# kubectl apply -f pv-volume.yaml 
persistentvolume/task-pv-volume created
[root@k8s-master-1 pv-pvc-test]# kubectl get pv
NAME             CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
task-pv-volume   2Gi        RWO            Retain           Available           manual                  5s
输出结果显示该 PersistentVolume 的状态(STATUS)为 Available(可达)。 这意味着它还没有被绑定给 PersistentVolumeClaim。


- - - - - -创建一个nfs类型的PersistentVolume - - - - - -
apiVersion: v1
kind: PersistentVolume
metadata:
  name: task-pv-volume
  labels:
    type: local
spec:
  storageClassName: manual
  capacity:
    storage: 2Gi
  accessModes:
  - ReadWriteOnce  
 nfs:   
   path: "/k8s/kubernetes/cfg/test/pv-pvc-test"
   server: 192.168.134.137

注释:此配置文件制定卷位于节点上的/k8s/kubernetes/cfg/test/pv-pvc-test路径,其配置制定 了卷的容量大小为2GB,访问模式为ReadWriteOnce,说明该卷可以被单个节点以读写方式安装,还定义了StorageClassName为manual,它将用于将PVC的请求绑定到这个PV上。

2、创建一个PersistentVolumeClaim,pod使用pvc来请求物理存储

[root@k8s-master-1 pv-pvc-test]# vim pvc-volume.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: task-pvc-claim
spec:
  storageClassName: manual
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
[root@k8s-master-1 pv-pvc-test]# kubectl apply -f pvc-volume.yaml 
创建完成之后查看PV状态为Bound
[root@k8s-master-1 pv-pvc-test]# kubectl get pv
NAME             CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                    STORAGECLASS   REASON   AGE
task-pv-volume   2Gi        RWO            Retain           Bound    default/task-pvc-claim   manual                  22m
[root@k8s-master-1 pv-pvc-test]# kubectl get pvc
NAME             STATUS   VOLUME           CAPACITY   ACCESS MODES   STORAGECLASS   AGE
task-pvc-claim   Bound    task-pv-volume   2Gi        RWO            manual         10m
输出结果表示:该task-pvc-claim绑定到了task-pv-volume

        创建完PVC之后,kubernetes控制平面将查找满足申请要求的PV,如果找到具有相同StorageClass的适当pv.则将PVC绑定到该PV上。

        如果删除了PVC,因为PV的策略,状态会变成Released。与之绑定的pv不会被删除,仅被标记为已释放。pv的数据仍然存在,在清空之前不能被新的pvc使用,需要管理员手工清理之后才能继续使用。清理步骤如上2.d.i 如果策略是默认的则只需要修改pv文件即可,如下

        删除pvc以后--——>k8s会创建一个回收的pod——>根据pv 的回收策略进行pv的回收——>回收完之后——>pv的状态就会变成可被绑定的状态,其他的Pending状态的pvc匹配到了这个PV,就能和这个pv进行绑定

[root@k8s-master-1 pv-pvc-test]# kubectl get pv
NAME             CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS     CLAIM                   STORAGECLASS   REASON   AGE
task-pv-volume   2Gi        RWO            Retain           Released   default/task-pv-claim   manual                  16m
[root@k8s-master-1 pv-pvc-test]# kubectl edit pv task-pv-volume
  claimRef:
    apiVersion: v1
    kind: PersistentVolumeClaim
    name: task-pvc-claim
    namespace: default
    resourceVersion: "1425513"
    uid: 42aca166-8f09-491c-b387-f2ca7fd58c8e
把这些信息掉掉,PV的状态就会变为Available

3、创建一个使用PVC作为存储卷的pod

apiVersion: v1
kind: Pod
metadata:
  name: task-pv-pod
spec:
  containers:
  - name: task-pv-container
    image: nginx:1.15.3
    ports:
    - containerPort: 80
      name: "http-server"
    volumeMounts:
    - mountPath: "/usr/share/nginx/thml"
      name: task-pv-storage
  volumes:
  - name: task-pv-storage
    persistentVolumeClaim:
      claimName: task-pvc-claim
kubectl exec -it task-pv-pod -- bash
在挂载目录下,echo "123" > 1.txt
然后退出,看下pod被调度到了哪个节点,去节点的/k8s/kubernetes/cfg/test/pv-pvc-test 看看是否有1.txt文件

七:注意事项:

POD 文件制定了PVC,并没有制定PV。对于pod而言,pvc就是一个存储卷

  1. 创建PVC之后,一直绑定不上

    1. PVC的空间申请大小大于PV的大小
    2. PVC的storageClassName没有和PV的一致
    3. PVC的访问模式和PV不一致
  2. 创建挂载了pvc的pod 之后 一直处于Pending状态

    1. pvc没有被创建成功或者,没有被创建
    2. pvc和pod不在同一namespaces
    3. pod中pvc的名字指定pvc不对

八、PVC的自动化部署,使用StatefulSet实现自动创建PV和PVC

        使用volumeClaimTemplates参数完成pvc的自动化部署,不需要手动创建PVC,此时每个pod都有一个pvc。

1、搭建NFS共享存储再此不做演示,

        详情请查看K8S存储Volume中介绍:十四、K8S存储Volumes-CSDN博客​​​​​​​

2、创建rbac授权

 #创建一个用于认证的服务账号                          
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: default

---

kind: ClusterRole   #创建群集规则
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: nfs-client-provisioner-runner
rules:
  - apiGroups: [""]
    resources: ["nodes"]
    verbs: ["get", "list", "watch"]
  - 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: ["create", "update", "patch"]

---
kind: ClusterRoleBinding    #将服务认证用户与群集规则进行绑定
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: run-nfs-client-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    # replace with namespace where provisioner is deployed
    namespace: default     #必写字段,否则会提示错误
roleRef:
  kind: ClusterRole
  name: nfs-client-provisioner-runner
  apiGroup: rbac.authorization.k8s.io

---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: default
rules:
  - apiGroups: [""]
    resources: ["endpoints"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]

---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: default
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    # replace with namespace where provisioner is deployed
    namespace: default
roleRef:
  kind: Role
  name: leader-locking-nfs-client-provisioner
  apiGroup: rbac.authorization.k8s.io

#创建成功
[root@k8s-master-1 pv-pvc-test]# kubectl apply -f rbac-rolebind.yaml 
serviceaccount/nfs-provisioner created
clusterrole.rbac.authorization.k8s.io/nfs-provisioner-runner created
clusterrolebinding.rbac.authorization.k8s.io/run-nfs-provisioner created

3、创建nfs-deployment资源

  • 自动创建的 PV 以 namespace−namespace−{pvcName}-${pvName} 的命名格式创建在 NFS 上
  • 当这个 PV 被回收后会以 archieved-namespace−namespace−{pvcName}-${pvName} 的命名格式存在 NFS 服务器上
[root@k8s-master-1 pvc-zd]# vim nfs-deployment.yaml           
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nfs-client-provisioner
  labels:
    app: nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: default
spec:
  replicas: 1
  strategy:
    type: Recreate    # --- 设置升级策略为删除再创建(默认为滚动更新)
  selector:
    matchLabels:
      app: nfs-client-provisioner
  template:
    metadata:
      labels:
        app: nfs-client-provisioner
    spec:
      serviceAccountName: nfs-client-provisioner   #指定rbac yaml文件中创建认证的用户账号 
      containers:
        - name: nfs-client-provisioner
         # image: registry.k8s.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2
         # image: registry.cn-beijing.aliyuncs.com/mydlq/nfs-subdir-external-provisioner:v4.0.0
          image: docker.io/eipwork/nfs-subdir-external-provisioner:v4.0.2
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes   #指定容器内挂载的目录
          env:
            - name: PROVISIONER_NAME
              value: nfs-subdir-external-provisioner   #---nfs-provisioner的名称,以后设置的storageclass要和这个保持一致
            - name: NFS_SERVER
              value: 192.168.134.135   #---NFS服务器地址,和 valumes 保持一致
            - name: NFS_PATH
              value: /nfsdata    #---NFS服务器目录,和 valumes 保持一致
      volumes:
        - name: nfs-client-root
          nfs:
            server: 192.168.134.135     #---NFS服务器地址
            path: /nfsdata   #---NFS服务器目录
[root@k8s-master-1 pvc-zd]# kubectl apply -f nfs-deployment.yaml 
deployment.apps/nfs-provisioner created
[root@k8s-master-1 pvc-zd]# kubectl get pod
NAME                               READY   STATUS    RESTARTS   AGE

nfs-provisioner-58f454c46c-szrdz   1/1     Running   0          34s

4、创建storageclass

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-storage
  #annotations:
    #storageclass.kubernetes.io/is-default-class: "true"  #是否设置为默认的storageclass
provisioner: nfs-client #---动态卷分配者名称,必须和上面创建的"PROVISIONER_NAME"变量中设置的Name一致
parameters:
  archiveOnDelete: "true" #---设置为"false"时删除PVC不会保留数据,"true"则保留数据
allowVolumeExpansion: true #
[root@k8s-master-1 pvc-zd]# kubectl apply -f storageclass.yaml 
storageclass.storage.k8s.io/nfs-storage created
[root@k8s-master-1 pvc-zd]# kubectl get sc
NAME                    PROVISIONER   RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
nfs-storage (default)   nfs-client    Delete          Immediate           true                   7s

5、创建StatefulSet,自动生成pvc并绑定pv。yaml文件详解请参照K8S-statefulset

[root@k8s-master-1 deploy]# vim statefulset.yaml
apiVersion: v1
kind: Service
metadata:
  name: headless-svc
  labels:
    app: headless-svc
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: headless-pod

---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: statefulset-test
spec:
  selector:
    matchLabels:
      app: headless-pod
  serviceName: headless-svc
  replicas: 3
  template:
    metadata:
      labels:
        app: headless-pod
    spec:
      containers:
      - name: nginx
        image: nginx:1.15.3
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: test
          mountPath: /mnt
  volumeClaimTemplates:
  - metadata:
      name: test
      annotations:
        volume.beta.kubernetes.io/storage-class: nfs-client
    spec:
      accessModes: [ "ReadWriteOnce"]
      resources:
        requests:
          storage: 1Gi

[root@k8s-master-1 deploy]# kubectl apply -f statefulset.yaml 
service/headless-svc created
statefulset.apps/statefulset-test created

[root@k8s-master-1 deploy]# kubectl get pod
NAME                                      READY   STATUS    RESTARTS   AGE
nfs-client-provisioner-664f9c577b-qd6z2   1/1     Running   0          7m17s
statefulset-test-0                        1/1     Running   0          16s
statefulset-test-1                        1/1     Running   0          12s
statefulset-test-2                        1/1     Running   0          7s

[root@k8s-master-1 deploy]# kubectl get pvc
NAME                      STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
test-statefulset-test-0   Bound    pvc-ad4ae127-151a-4abf-9cad-65139a85df70   1Gi        RWO            nfs-client     20s
test-statefulset-test-1   Bound    pvc-59bb2b13-7452-4eff-b91b-a9f46c0311cf   1Gi        RWO            nfs-client     16s
test-statefulset-test-2   Bound    pvc-ba9d93cf-91d6-491e-9f29-d5e59e1ca170   1Gi        RWO            nfs-client     11s
[root@k8s-master-1 deploy]# 

[root@k8s-master-1 deploy]# 
[root@k8s-master-1 deploy]# kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                             STORAGECLASS   REASON   AGE
pvc-59bb2b13-7452-4eff-b91b-a9f46c0311cf   1Gi        RWO            Delete           Bound    default/test-statefulset-test-1   nfs-client              18s
pvc-ad4ae127-151a-4abf-9cad-65139a85df70   1Gi        RWO            Delete           Bound    default/test-statefulset-test-0   nfs-client              22s
pvc-ba9d93cf-91d6-491e-9f29-d5e59e1ca170   1Gi        RWO            Delete           Bound    default/test-statefulset-test-2   nfs-client              13s

#查看是否创建爱你持久化目录
[root@k8s-master-1 deploy]# cd /nfsdata/
[root@k8s-master-1 nfsdata]# 
[root@k8s-master-1 nfsdata]# ll
总用量 0
drwxrwxrwx 2 root root 6 6月   9 14:01 default-test-statefulset-test-0-pvc-ad4ae127-151a-4abf-9cad-65139a85df70
drwxrwxrwx 2 root root 6 6月   9 14:01 default-test-statefulset-test-1-pvc-59bb2b13-7452-4eff-b91b-a9f46c0311cf
drwxrwxrwx 2 root root 6 6月   9 14:01 default-test-statefulset-test-2-pvc-ba9d93cf-91d6-491e-9f29-d5e59e1ca170

6、在pod资源内创建数据并访问测试

[root@k8s-master-1 nfsdata]# echo 111 > default-test-statefulset-test-0-pvc-ad4ae127-151a-4abf-9cad-65139a85df70/index.html
[root@k8s-master-1 nfsdata]# 

[root@k8s-master-1 nfsdata]# echo 222 > default-test-statefulset-test-1-pvc-59bb2b13-7452-4eff-b91b-a9f46c0311cf/index.html
[root@k8s-master-1 nfsdata]# 
[root@k8s-master-1 nfsdata]# echo 333 > default-test-statefulset-test-2-pvc-ba9d93cf-91d6-491e-9f29-d5e59e1ca170/index.html

[root@k8s-master-1 nfsdata]# kubectl exec -it statefulset-test-0 -- bash
root@statefulset-test-0:/# cd /mnt/
root@statefulset-test-0:/mnt# cat index.html 
111

7、删除其中一个pod,查看该pod的数据是否会重新创建并存在

[root@k8s-master-1 nfsdata]# kubectl delete pod statefulset-test-0
pod "statefulset-test-0" deleted
[root@k8s-master-1 nfsdata]# 
[root@k8s-master-1 nfsdata]# kubectl get pod
NAME                                      READY   STATUS    RESTARTS   AGE
nfs-client-provisioner-664f9c577b-qd6z2   1/1     Running   0          36m
statefulset-test-0                        1/1     Running   0          2s
statefulset-test-1                        1/1     Running   0          29m
statefulset-test-2                        1/1     Running   0          29m
[root@k8s-master-1 nfsdata]# 
[root@k8s-master-1 nfsdata]# kubectl exec -it statefulset-test-0 -- bash
root@statefulset-test-0:/# cd /mnt/
root@statefulset-test-0:/mnt# ls
index.html
root@statefulset-test-0:/mnt# 
root@statefulset-test-0:/mnt# cat index.html 
111
可以看到 删除pod之后会重新创建一个pod,并且数据依在。

  • 21
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
PV(PersistentVolume)和PVC(PersistentVolumeClaim)是Kubernetes中用于实现持久存储的重要概念。 PV是集群中的一块存储,可以是NFS、iSCSI、本地存储等,由管理员进行配置或使用存储类进行动态配置。PV定义了存储的容量、访问模式、持久存储的类型等属性。PV的生命周期是独立于Pod的,即使Pod被删除,PV仍然存在,可以被其他Pod继续使用。 PVC是一个持久存储,用于访问各种类型的持久存储,如本地存储、网络存储、云存储等。PVC的使用使应用程序更加灵活和可移植,同时也提高了存储资源的利用率。PVCPV是一一对应的关系,即一个PVC只能绑定一个PV,而一个PV也只能被一个PVC绑定。 下面是一个演示k8s持久存储PVPVC的案例: 1. 创建PV: ```yaml apiVersion: v1 kind: PersistentVolume metadata: name: my-pv spec: capacity: storage: 1Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain storageClassName: my-storage-class nfs: path: /data server: nfs-server-ip ``` 2. 创建PVC: ```yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: my-pvc spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: my-storage-class ``` 3. 创建Pod,并挂载PVC: ```yaml apiVersion: v1 kind: Pod metadata: name: my-pod spec: containers: - name: my-container image: nginx volumeMounts: - name: my-volume mountPath: /data volumes: - name: my-volume persistentVolumeClaim: claimName: my-pvc ``` 4. 删除PVC的正确步骤: ```shell kubectl delete pod my-pod kubectl delete pvc my-pvc kubectl delete pv my-pv ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

繁华依在

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值