k8s Persistent Volume

  • Volume 生命周期

  • Volume 的生命周期包括 5 个阶段

  1. Provisioning,即 PV 的创建,可以直接创建 PV(静态方式),也可以使用 StorageClass 动态创建
  2. Binding,将 PV 分配给 PVC
  3. Using,Pod 通过 PVC 使用该 Volume,并可以通过准入控制 StorageObjectInUseProtection(1.9 及以前版本为 PVCProtection)阻止删除正在 使用的 PVC
  4. Releasing,Pod 释放 Volume 并删除 PVC
  5. Reclaiming,回收 PV,可以保留 PV 以便下次使用,也可以直接从云存储中删除
  6. Deleting,删除 PV 并从云存储中删除后段存储
  • Volume 的状态有以下 4 种

  1. Available:可用
  2. Bound:已经分配给 PVC
  3. Released:PVC 解绑但还未执行回收策略
  4. Failed:发生错误 
  • PV 

PersistentVolume(PV)是集群之中的一块网络存储。跟 Node 一样,也是集群的资源。PV 跟 Volume (卷) 类似,不过会有独立于 Pod 的生命周期。比如一个 NFS 的 PV 可以定义为:

apiVersion: v1
kind: PersistentVolume
metadata:
    name: pv0003
spec:
    capacity:
        storage: 5Gi
    accessModes:
        - ReadWriteOnce
    persistentVolumeReclaimPolicy: Recycle
    nfs:
        path: /tmp
        server: 172.17.0.2
  •  PV 的访问模式(accessModes)有三种

  1. ReadWriteOnce (RWO):是最基本的方式,可读可写,但只支持被单个节点挂载。
  2. ReadOnlyMany (ROX):可以以只读的方式被多个节点挂载。
  3. ReadWriteMany (RWX):这种存储可以以读写的方式被多个节点共享。不是每一 种存储都支持这三种方式,像共享方式,目前支持的还比较少,比较常用的是 NFS。在 PVC 绑定 PV 时通常根据两个条件来绑定,一个是存储的大小,另一个就是访问模式。 
  • PV 的回收策略(persistentVolumeReclaimPolicy,即 PVC 释放卷的时候 PV 该如何操作)也有三种: 

  1. Retain:不清理, 保留 Volume(需要手动清理)
  2. Recycle:删除数据,即 rm -rf /thevolume/* (只有 NFS 和 HostPath 支持)
  3. Delete:删除存储资源,比如删除 AWS EBS 卷(只有 AWS EBS, GCE PD, Azure Disk 和 Cinder 支持)

 StorageClass

上面通过手动的方式创建了一个 NFS Volume,这在管理很多 Volume 的时候不太方便。Kubernetes 还提供了 StorageClass 来动态创建 PV,不仅节省了管理员的时间,可以封装不同类型的存储供 PVC 选用。 

  • StorageClass 包括四个部分 

  1. provisioner:指定 Volume 插件的类型,包括内置插件(如 kubernetes.io/glusterfs)和外部插件(如 external-storage 提供的 ceph.com/cephfs)。
  2. mountOptions:指定挂载选项,当 PV 不支持指定的选项时会直接失败。比如 NFS 支持 hard 和 nfsvers=4.1 等选项。
  3. parameters:指定 provisioner 的选项,比如 kubernetes.io/aws-ebs 支持 type 、 zone 、 iopsPerGB 等参数。
  4. reclaimPolicy:指定回收策略,同 PV 的回收策略。 

在使用 PVC 时,可以通过 DefaultStorageClass 准入控制设置默认 StorageClass, 即给未设置 storageClassName 的 PVC 自动添加默认的 StorageClass。而默认的 StorageClass 带有 annotation storageclass.kubernetes.io/is-default-class=true 

Volume PluginInternal ProvisionerConfig Example
AWSElasticBlockStoreYhttps://kubernetes.io/docs/concepts/storage/storage-classes/#aws
AzureFileYhttps://kubernetes.io/docs/concepts/storage/storage-classes/#azure-file
AzureDiskYhttps://kubernetes.io/docs/concepts/storage/storage-classes/#azure-disk
CephFS--
CinderYhttps://kubernetes.io/docs/concepts/storage/storage-classes/#openstack-cinder
FC--
FlexVolume--
FlockerY-
GCEPersistentDiskYhttps://kubernetes.io/docs/concepts/storage/storage-classes/#gce
GlusterfsYhttps://kubernetes.io/docs/concepts/storage/storage-classes/#glusterfs
iSCSI--
PhotonPersistentDiskY-
QuobyteYhttps://kubernetes.io/docs/concepts/storage/storage-classes/#quobyte
NFS--
RBDYhttps://kubernetes.io/docs/concepts/storage/storage-classes/#ceph-rbd
VsphereVolumeYhttps://kubernetes.io/docs/concepts/storage/storage-classes/#vsphere
PortworxVolumeYhttps://kubernetes.io/docs/concepts/storage/storage-classes/#portworx-volume
ScaleIOYhttps://kubernetes.io/docs/concepts/storage/storage-classes/#scaleio
StorageOSYhttps://kubernetes.io/docs/concepts/storage/storage-classes/#storageos
Local-https://kubernetes.io/docs/concepts/storage/storage-classes/#local

创建一个NFS类型的storagecalss,并将它挂载到nginx的pod中

  • 首先在系统中安装nfs服务 
$ sudo apt-get install nfs-common
$ sudo apt install nfs-kernel-server

设置共享目录(在/etc/exports 最下面加这一行)
/k8s-data *(rw,no_root_squash,no_all_squash,sync)
  • 启动nfs服务
$ sudo systemctl strart rpcbind
$ sudo service nfs-kernel-server start


查看共享目录设置情况
$ showmount -e
Export list for xxxxxxx:
/k8s-data *

这时候nfs的共享目录就设置好了,路径是server的/k8s-data 目录

  • 创建pv
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv1
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: nfs
  nfs:
    path: /k8s-data
    server: xxxxxxx


$ kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM          STORAGECLASS   REASON   AGE
pv1    1Gi        RWO            Retain           Bound    default/pvc1   nfs                     23m

设置pv的大小为1G,storageClass为nfs,指向nfs server的/k8s-data 路径

  • 创建pvc
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc1
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: nfs


$ kubectl get pvc
NAME   STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
pvc1   Bound    pv1      1Gi        RWO            nfs            23m

  •  创建一个nginx的deployment,并且将创建的pv挂载到pods上面
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:latest
          imagePullPolicy: IfNotPresent
          ports:
          - containerPort: 80
          volumeMounts:
            - mountPath: /data
              name: data
      volumes:
        - name: data
          persistentVolumeClaim:
            claimName: pvc1

这里面引用刚刚创建的pvc1,并且将它挂载到pods的/data 目录下,然后通过kubectl create -f nginx-dep.yaml创建deployment

$ kubectl get pods
NAME                                 READY   STATUS    RESTARTS       AGE
nginx-deployment-68ffbd49cc-hf79w    1/1     Running   0              25m
nginx-deployment-68ffbd49cc-jffw7    1/1     Running   0              25m

$ kubectl get deployment
NAME                READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment    2/2     2            2           25m

$ kubectl describe deployment nginx-deployment
Name:                   nginx-deployment
Namespace:              default
CreationTimestamp:      Mon, 05 Aug 2024 16:45:46 +0800
Labels:                 <none>
Annotations:            deployment.kubernetes.io/revision: 1
Selector:               app=nginx
Replicas:               2 desired | 2 updated | 2 total | 2 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  app=nginx
  Containers:
   nginx:
    Image:        nginx:latest
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:
      /data from data (rw)
  Volumes:
   data:
    Type:       PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
    ClaimName:  pvc1
    ReadOnly:   false
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  <none>
NewReplicaSet:   nginx-deployment-68ffbd49cc (2/2 replicas created)
Events:
  Type    Reason             Age   From                   Message
  ----    ------             ----  ----                   -------
  Normal  ScalingReplicaSet  26m   deployment-controller  Scaled up replica set nginx-deployment-68ffbd49cc to 2


通过上面的查看,已经能看到pvc1被挂载到nginx-deployment上面了

  • 测试

在主机的/k8s-data目录下创建几个文件

/k8s-data$ ls
1.txt  2.txt  3.txt

然后登录到pod里面查看/data 目录,发现也可以看到这几个文件

$ kubectl exec -it nginx-deployment-68ffbd49cc-hf79w -- /bin/sh
# ls /data
1.txt  2.txt  3.txt

再通过pod的/data 目录创建文件

# cd /data
# ls
1.txt  2.txt  3.txt
# touch 4.txt
# ls
1.txt  2.txt  3.txt  4.txt

在主机的/k8s-data目录下也可以看到新建的文件

/k8s-data$ ls
1.txt  2.txt  3.txt  4.txt

至此pv创建并挂载完成

  • 22
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值