k8s卷管理-2

k8s卷管理-2

之前已经介绍了本地存储和网络存储这两种类型,但是在生产环境中,这两种存储方式用的很少,而现在要介绍的存储方式才是使用率最高的

pv和pvc

他们的区别
pv(PersistentVolume)是集群中的存储资源,所有的namespace都是可以查看到的,pv并不属于某一namespace,而是属于整个集群,它是由底层的存储服务器提供给k8s集群的
pvc(PersistentVolumeClaim)是表达用户对于pv的申请,它可以定义用户想要多少个G的存储空间,相当于购物车,你想要什么都放在这个请求里面,k8s会对你的请求给你分配对应的pv让你来使用,pvc是属于namespace的资源,不同的namespace是查不到其他namespace的资源的

他们之间的关系
pv与pvc是一一对应的,一个pv只能绑定到一个pvc上,尽管资源没有分配完,那么剩下的也不会再次绑定给其他的pvc了

pv

pv的底层可以对接很多的存储系统,比如NFS,Ceph,Iscsi,cinde(已弃用),关于想要知道目前支持哪些后端存储的话可以到k8s的官方文档去查看

地址 https://kubernetes.io

pv的定义

我就在这里使用nfs作为后端存储,因为nfs比较方便

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv01
spec:
# 这里是定义的pv的大小
  capacity:
    storage: 5Gi
# 卷的类型,由Filesystem 和 Block两种,如果你使用的是Iscsi这种那你就定义成Block,默认就是Filesystem
  volumeMode: Filesystem
# pv的访问模式,ReadWriteOnce的意思是只允许一个节点以读写的方式挂载,但是一个节点上有多个pod的话,这些pod都能挂载。不能跨节点
  accessModes:
    - ReadWriteOnce
# 这里定义的就是后端存储的类型,地址啥的
  nfs:
    path: /nfs
    server: 192.168.200.200

使用这个yaml文件去创建pv,验证一下是否所有的namespace都可以查得到

# 现在是在default命名空间下
[root@master k8s]# kubectl apply -f pv.yaml 
persistentvolume/pv01 created
[root@master k8s]# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv01   5Gi        RWO            Retain           Available                                   4s
# 切换命名空间到kube-system再次查看
[root@master k8s]# kubectl config set-context --current --namespace kube-system
Context "kubernetes-admin@kubernetes" modified.
[root@master k8s]# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv01   5Gi        RWO            Retain           Available                                   20s

我们可以看到,pv确实是所有的命名空间都可以查得到的,这个就是pv的定义,定义好了之后状态是可用,那么现在只需要等到一个有缘人发起一个pvc的请求,只要请求的访问模式一致,并且大小不超过pv的大小,那么这个pv就会被绑定咯,来看看pvc

pvc

pvc就是一个对pv请求的清单,比如我想要一个访问模式是ReadOnlyMany,并且大小是100G的pv,我只需要把这些条件表达出来,然后交给k8s,那么k8s集群就会去找有没有合适的pv分配给我,有的话那么pv就和我的pvc绑定上了,那么这个pv就不会再分配给别人了,尽管我请求的是100G,他这个PV有1T,那么剩下的空间也不会再分配出去了,也验证了前面所说的一一对应

pvc的定义

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: myclaim
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
# 这里是请求的资源大小,5G
  resources:
    requests:
      storage: 5Gi

我们来创建一下这个pvc,看看他是否能够成功绑定

[root@master k8s]# kubectl apply -f pvc.yaml
persistentvolumeclaim/myclaim created
[root@master k8s]# kubectl get pvc
NAME      STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
myclaim   Bound    pv01     5Gi        RWO                           3s
[root@master k8s]# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM             STORAGECLASS   REASON   AGE
pv01   5Gi        RWO            Retain           Bound    default/myclaim                           5m

我们可以看到,pv和pvc的状态现在都变成了Bound,那么现在pv和pvc的定义就完成了

pv和pvc的绑定关系

如果你感兴趣的话,不妨尝试一下多创建几个pv,然后再去创建pvc,你会发现,只要资源能够匹配的上的话,他是随机给你分配pv的,或者说,现在只剩下一个pv是可用的,有2个用户都请求了这个pv,那么这个pv会分配给谁呢?答案是谁手速快那就分配给谁,你的请求先到达k8s集群,那么这个pv就是你的,如果我们想自己手动指定pv呢,可以做到吗?当然是可以的,我们只需要在pv的yaml文件里面加上storageClassName: 就可以了

手动指定pv与pvc绑定

# 将之前的pv的yaml文件复制过来,改动一行内容
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv02
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
# 加上这一行内容,给他一个test名字,那么pvc在请求的时候必须带上这个参数,否则不会绑定
  storageClassName: test
  nfs:
    path: /nfs
    server: 192.168.200.200

尝试一下pvc里面不带这个参数是否能绑定

[root@master k8s]# kubectl apply -f pv2.yaml 
persistentvolume/pv02 created
[root@master k8s]# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv02   5Gi        RWO            Retain           Available           test                    11
# pvc的yaml文件还是之前那个,不做修改
[root@master k8s]# kubectl apply -f pvc.yaml 
persistentvolumeclaim/myclaim created
[root@master k8s]# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv02   5Gi        RWO            Retain           Available           test                    41s
[root@master k8s]# kubectl get pvc
NAME      STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
myclaim   Pending                                                     11s

我们可以看到,pv的状态依旧是可用,pvc的状态是pending,说明他们确实没有绑定上,现在我们将pvc里面也加上这一行参数

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: myclaim2
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 5Gi
  storageClassName: test

使用这个yaml文件创建一个pvc看看效果

[root@master k8s]# kubectl apply -f pvc2.yaml 
persistentvolumeclaim/myclaim2 created
[root@master k8s]# kubectl get pvc
NAME       STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
myclaim2   Bound    pv02     5Gi        RWO            test           6s
[root@master k8s]# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM              STORAGECLASS   REASON   AGE
pv02   5Gi        RWO            Retain           Bound    default/myclaim2   test                    20s

我们发现他绑定上了,说明这个参数生效了,也就是说加上这个参数之后,光匹配模式和大小是不行的,还必须把这个存储类的名字也匹配上才行

pod使用pvc

pod挂载pvc

目前,pv和pvc的定义都已经说过了,但是好像没有涉及到pod,那么pod是如何去使用这个pv存储的呢?我们直接来看yaml文件,很容易理解

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: volume1
  name: volume1
spec:
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: volume1
    resources: {}
    volumeMounts:
    - name: myvolume
      mountPath: /usr/share/nginx/html
  volumes:
# 这里的名字是你给这个卷起的名字,可以随意,但是得和pod挂载的卷名一致
  - name: myvolume
# 在这里使用pvc,指定pvc的名字
    persistentVolumeClaim:
# 这里的名字必须要写你的pvc的名字
      claimName: myclaim2
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

看看效果

[root@master k8s]# kubectl apply -f pod_pvc.yaml 
pod/volume1 created
[root@master k8s]# kubectl get pods
NAME      READY   STATUS    RESTARTS   AGE
volume1   1/1     Running   0          3s
# 进入容器查看挂载点
[root@master k8s]# kubectl exec -it pods/volume1 -- /bin/bash
root@volume1:/# df -hT
Filesystem           Type     Size  Used Avail Use% Mounted on
overlay              overlay   46G   14G   32G  31% /
tmpfs                tmpfs     64M     0   64M   0% /dev
tmpfs                tmpfs    1.9G     0  1.9G   0% /sys/fs/cgroup
/dev/mapper/cs-root  xfs       46G   14G   32G  31% /etc/hosts
shm                  tmpfs     64M     0   64M   0% /dev/shm
192.168.200.200:/nfs nfs4      46G   15G   31G  32% /usr/share/nginx/html
tmpfs                tmpfs    3.8G   12K  3.8G   1% /run/secrets/kubernetes.io/serviceaccount
tmpfs                tmpfs    1.9G     0  1.9G   0% /proc/acpi
tmpfs                tmpfs    1.9G     0  1.9G   0% /proc/scsi
tmpfs                tmpfs    1.9G     0  1.9G   0% /sys/firmware

我们现在发现pod已经挂载了nfs了,我们再来创建一个pod

访问模式的区别

访问模式一共有4种,分别是

  1. ReadWriteOnce

卷可以被一个节点以读写方式挂载。 ReadWriteOnce 访问模式也允许运行在同一节点上的多个 Pod 访问卷。

  1. ReadOnlyMany

卷可以被多个节点以只读方式挂载。

  1. ReadWriteMany

卷可以被多个节点以读写方式挂载。

  1. ReadWriteOncePod

卷可以被单个 Pod 以读写方式挂载。 如果你想确保整个集群中只有一个 Pod 可以读取或写入该 PVC, 请使用 ReadWriteOncePod 访问模式。这只支持 CSI 卷以及需要 Kubernetes 1.22 以上版本。

posted @ 2024-01-11 17:46  FuShudi  阅读(173)  评论(0编辑  收藏  举报