k8s基础入门之存储卷管理(PV & PVC)

1.存储卷管理概念

Kubernetes Volume 是一个目录,这一点与 Docker Volume 类似。当 Volume 被 mount 到 Pod,Pod 中的所有容器都可以访问这个 Volume。Kubernetes Volume 也支持多种 backend 类型,包括 emptyDir、hostPath、GCE Persistent Disk、AWS Elastic Block Store、NFS、Ceph 等,完整列表可参考 https://kubernetes.io/docs/concepts/storage/volumes/#types-of-volumes Volume 的生命周期独立于容器,Pod 中的容器可能被销毁和重建,但 Volume 会被保留。 本质上,Kubernetes Volume 是一个目录,这一点与 Docker Volume 类似。当 Volume 被 mount 到 Pod,Pod 中的所有容器都可以访问这个 Volume。Kubernetes Volume 也支持多种 backend 类型,包括 emptyDir、hostPath、GCE Persistent Disk、AWS Elastic Block Store、NFS、Ceph 等,完整列表可参考 https://kubernetes.io/docs/concepts/storage/volumes/#types-of-volumes

2 经常使用的卷类型

本地卷: hostPath,emptyDir 网络卷: nfs,ceph(cephfs,rbd),glusterfs 公有云: aws,azure k8s资源: downwardAPI,configmap,secret

2.1 临时存储emptyDir

emptyDir Volume 对于容器来说是持久的,对于 Pod 则不是。当 Pod 从节点删除时,Volume 的内容也会被删除。但如果只是容器被销毁而 Pod 还在,则 Volume 不受影响。也就是说:emptyDir Volume 的生命周期与 Pod 一致。 Pod中的所有容器都可以共享Volume,它们可以指定各自的mount路径。
我们通过例子来实践 emptyDir,配置文件如下
apiVersion: v1 
kind: Pod
metadata:
 name: emtydirpod
spec:
 containers:
 - name: write
   image: centos
   command: ["bash","-c","for i in {1..100}; do echo $i >> /data/hello; sleep 10; done"]
   volumeMounts:
   - name: data
     mountPath: /data
 - name: read
   image: centos
   command: ["bash","-c","tail -f /data/hello"]
   volumeMounts:
   - name: data
     mountPath: /data
 volumes:
 - name: data
   emptyDir: {}

验证
root@k8s-master01 ~]# kubectl get pods
NAME                         READY   STATUS    RESTARTS   AGE
emtydirpod                   2/2     Running   0          68s

[root@k8s-master01 ~]# kubectl logs emtydirpod read
1
2
3
4
5
6
7

在对应的node上查看挂载的目录
/var/lib/kubelet/pods/6767307c-b6b6-48a7-81ad-10610a666cc6/volumes/kubernetes.io~empty-dir/data

2.2 节点存储hostPath

hostPath Volume 的作用是将 Docker Host 文件系统中已经存在的目录 mount 给 Pod 的容器。大部分应用都不会使用 hostPath Volume,因为这实际上增加了 Pod 与节点的耦合,限制了 Pod 的使用。不过那些需要访问 Kubernetes 或 Docker 内部数据(配置文件和二进制库)的应用则需要使用 hostPath。 应用场景: 日志采集agent,监控agent

hostPath参数说明:

参数 解释
空字符串(默认)用于向后兼容,这意味着在安装 hostPath 卷之前不会执行任何检查。
DirectoryOrCreate 如果在给定路径上什么都不存在,那么将根据需要创建空目录,权限设置为 0755,具有与 kubelet 相同的组和属主信息
Directory 在给定路径上必须存在的目录
FileOrCreate 如果在给定路径上什么都不存在,那么将在那里根据需要创建空文件,权限设置为 0644,具有与 kubelet 相同的组和所有权
File 在给定路径上必须存在的文件
Socket 在给定路径上必须存在的 UNIX 套接字
CharDevice 在给定路径上必须存在的字符设备
BlockDevice 在给定路径上必须存在的块设备
实例展示用法
首先要在所有的node节点建立对应的目录,或者通过DirectoryOrCreate 自动创建.
[root@k8s-master01 ~]# cat hostPathmount.yaml 
apiVersion: v1 
kind: Pod
metadata:
 name: hostpathtest

spec:
 volumes:
 - name: html
   hostPath:
      path: /html
      type: DirectoryOrCreate

 containers:
 - name: nginx
   image: nginx:1.15
   volumeMounts:
   - name: html
     mountPath: /usr/share/nginx/html

[root@k8s-master01 ~]# kubectl apply -f hostPathmount.yaml 
pod/hostpathtest created
[root@k8s-master01 ~]# 

测试
root@hostpathtest:/usr/share/nginx/html# cat index.html 
hhh

dddd

[root@k8s-master01 /]# kubectl get pods -o wide
NAME                         READY   STATUS    RESTARTS   AGE     IP             NODE         NOMINATED NODE   READINESS GATES
hostpathtest                 1/1     Running   0          3m30s   10.244.2.88    k8s-node02   <none>           <none>

查看pod所在的节点对应/html
[root@k8s-node02 html]# cat index.html 
hhh

dddd

[root@k8s-node02 html]# pwd
/html

通过hostpath创建的目录 不会因为pod的消失而消失.

3 网络卷挂载使用

3.1 NFS存储卷

1.搭建nfs服务
 yum install nfs-utils -y rpcbind
mkdir /data/k8s-volume -p 
chmod 755 /data/k8s-volume
vim /etc/exports
/data/k8s-volume  *(rw,no_root_squash,sync)
#存储目录,*允许所有人连接,rw读写权限,sync文件同时写入硬盘及内存,no_root_squash 使用者root用户自动修改为普通用户

systemctl start rpcbind
systemctl restart nfs
systemctl status nfs
[root@k8s-node01 ~]# cat /var/lib/nfs/etab 
/data/k8s-volume    *(rw,sync,wdelay,hide,nocrossmnt,secure,no_root_squash,no_all_squash,no_subtree_check,secure_locks,acl,no_pnfs,anonuid=65534,anongid=65534,sec=sys,rw,secure,no_root_squash,no_all_squash)

#检查nfs挂载目录是否正常
[root@k8s-node01 ~]# showmount -e localhost
Export list for localhost:
/data/k8s-volume *

要在所有的node上都安装客户端软件
yum install -y nfs-utils rpcbind
[root@所有节点 ~]# mkdir -p /data1/k8s/
[root@所有节点 ~]#  mount -t nfs 192.168.10.72:/data/k8s-volume /data1/k8s

查看挂载情况
[root@k8s-node02 k8s]# df -h |grep data1
192.168.10.72:/data/k8s-volume   27G   11G   17G   39% /data1/k8s

[root@k8s-master01 ~]# cat nfs_volume.yaml

apiVersion: v1 
kind: Pod
metadata:
   name: nfs-volume-pod
   labels:
     app: redis
spec: 
  containers:
  - name: redis
    image: redis
    ports:
    - containerPort: 6379
      name: redisport
    volumeMounts:
    - name: redisdata
      mountPath: /data
  volumes:
  - name: redisdata
    nfs:
      server: 192.168.10.72
      path: /data/k8s-volume
      readOnly: false 

创建pod挂载nfs
[root@k8s-master01 ~]# kubectl  apply -f nfs_volume.yaml 
pod/nfs-volume-pod created

[root@k8s-master01 ~]# kubectl logs nfs-volume-pod
1:C 11 Apr 2021 12:14:37.364 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
1:C 11 Apr 2021 12:14:37.364 # Redis version=6.2.1, bits=64, commit=00000000, modified=0, pid=1, just started
1:C 11 Apr 2021 12:14:37.364 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
1:M 11 Apr 2021 12:14:37.365 * monotonic clock: POSIX clock_gettime
1:M 11 Apr 2021 12:14:37.365 * Running mode=standalone, port=6379.
1:M 11 Apr 2021 12:14:37.365 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
1:M 11 Apr 2021 12:14:37.365 # Server initialized
1:M 11 Apr 2021 12:14:37.366 * Ready to accept connections

[root@k8s-master01 ~]# kubectl exec -it nfs-volume-pod redis-cli
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead.
127.0.0.1:6379> set key hello
OK
127.0.0.1:6379> get key
"hello"
127.0.0.1:6379> BGSAVE
Background saving started
127.0.0.1:6379> exit

查看nfs挂载目录 redis数据已保存
[root@k8s-node01 ~]# ll /data/k8s-volume/dump.rdb 
-rw-r--r-- 1 polkitd ssh_keys 108 4月  11 20:17 /data/k8s-volume/dump.rdb

删除pod,重新创建,查看redis数据
[root@k8s-master01 ~]# kubectl delete  -f nfs_volume.yaml 
pod "nfs-volume-pod" deleted
[root@k8s-master01 ~]# kubectl apply  -f nfs_volume.yaml 
pod/nfs-volume-pod created

[root@k8s-master01 ~]# kubectl exec -it nfs-volume-pod redis-cli
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead.
127.0.0.1:6379> get key
"hello"
127.0.0.1:6379> 
通过以上操作,数据没有同pod一起被删除.

3.2 RBD存储卷

4 持久存储卷(pv,pvc)

4.1 持久存储卷概念

PV 的全称是:PersistentVolume(持久化卷),是对底层的共享存储的一种抽象,PV 由管理员进行创建和配置,它和具体的底层的共享存储技术的实现方式有关,比如 Ceph、GlusterFS、NFS 等,都是通过插件机制完成与共享存储的对接。
PVC 的全称是:PersistentVolumeClaim(持久化卷声明),PVC 是用户存储的一种声明,PVC 和 Pod 比较类似,Pod 消耗的是节点,PVC 消耗的是 PV 资源,Pod 可以请求 CPU 和内存,而 PVC 可以请求特定的存储空间和访问模式。对于真正使用存储的用户不需要关心底层的存储实现细节,只需要直接使用 PVC 即可。
但是通过PVC请求一定的存储空间也很有可能不足以满足对于存储设备的各种需求,而且不同的应用程序对于存储性能的要求也能也不尽相同,比如读写速度、并发性能等,为了解决这一问题,Kubernetes又为我们引入了一个新的资源对象: StorageClass,通过StorageClass的定义,管理员可以将存储资源定义为某种类型的资源,比如快速存储、慢速存储等,用户根据StorageClass的描述就可以非常直观的知道各种存储资源特性了,这样就可以根据应用的特性去申请合适的存储资源了
静态 pv
集群管理员创建一些 PV。它们带有可供群集用户使用的实际存储的细节。它们存在于Kubernetes API 中,可用于消费
动态pv
当管理员创建的静态 PV都不匹配用户的PersistentVolumeClaim时,集群可能会尝试动态地为 PVC创建卷。此配置基于StorageClasses:PVC 必须请求
[存储类],并且管理员必须创建并配置该类才能进行动态创建。声明该类为””可以有效地禁用其动态配置要启用基于存储级别的动态存储配置,集群管理员需要启用 API server上的DefaultStorageClass[准入控制器]。例如,通过确保DefaultStorageClass位于API server组件的—admission-control标志,使用逗号分隔的有序值列表中,可以完成此操作

4.2 PV和PVC的生命周期

k8s基础入门之存储卷管理(PV & PVC)
1.资源供应 (Provisioning)

Kubernetes支持两种资源的供应模式:静态模式(Staic)和动态模式(Dynamic)。资源供应的结果就是创建好的PV。

    静态模式:集群管理员手工创建许多PV,在定义PV时需要将后端存储的特性进行设置
    动态模式:集群管理员无须手工创建PV,而是通过StorageClass的设置对后端存储进行描述,标记为某种 “类型(Class)”。此时要求PVC对存储的类型进行声明,系统将自动完成PV的创建及PVC的绑定。PVC可以声明Class为””,说明该PVC禁止使用动态模式

2.资源绑定 (Binding)

在用户定义好PVC后,系统将根据PVC对存储资源的请求 (存储空间和访问模式)在已存在的PV中选择一个满足PVC要求的PV,一旦找到,就将该PV与用户定义的PVC进行绑定,然后用户的应用就可以使用这个PVC了。如果系统中没有满足PVC要求的PV,PVC则会无限期处于Pending状态,直到等到系统管理员创建了一个符合要求的PV。PV一旦绑定在某个PVC上,就被这个PVC独占,不能再与其他PVC进行绑定了。在这种情况下,当PVC申请的存储空间比PV的少时,整个PV的空间都能够为PVC所用,可能会造成资源的浪费。如果资源供应使用的是动态模式,则系统在PVC找到合适的StorageClass后,将会自动创建PV并完成PVC的绑定

3.资源使用 (Using)

Pod 使用volume的定义,将PVC挂载到容器内的某个路径进行使用。volume的类型为persistentVoulumeClaim,在容器应用挂载了一个PVC后,就能被持续独占使用。不过,多个Pod可以挂载同一个PVC,应用程序需要考虑多个实例共同访问一块存储空间的问题

4.资源释放 (Releasing)

当用户对存储资源使用哪个完毕后,用户可以删除PVC,与该PVC绑定的PV将会被标记为已释放,但还不能立刻与其他PVC进行绑定。通过之前PVC写入的数据可能还留在存储设备上,只有在清除之后该PV才能继续使用

5.资源回收 (Reclaiming)

对于PV,管理员可以设定回收策略(Reclaim Policy)用于设置与之绑定的PVC释放资源之后,对于遗留数据如何处理。只有PV的存储空间完成回收,才能供新的PVC绑定和使用。

4.3 pv的创建

PV容量(capacity):设定当前PV的容量,单位为Gi、Mi 访问模式:PersistentVolume可以以资源提供者支持的任何方式挂载到主机上。每个PV的访问模式都将被设置为该卷支持的特定模式。
ReadWriteOnce——该卷可以被单个节点以读/写模式挂载
ReadOnlyMany——该卷可以被多个节点以只读模式挂载
ReadWriteMany——该卷可以被多个节点以读/写模式挂载
在命令行中,访问模式缩写为:
RWO - ReadWriteOnce
ROX - ReadOnlyMany
RWX - ReadWriteMany

persistentVolumeReclaimPolicy(回收策略)

Retain(保留)——管理员手动回收
Recycle(回收)——基本擦除(rm -rf /thevolume/*),目前仅NFS和hostPath支持此操作。
Delete(删除)——关联的存储资产(例如 AWS EBS、GCE PD、Azure Disk 和OpenStack Cinder 卷)将被删除
StorageClass的名称(storageClassName):当前PV所属的StorageClass的名称;pvc与pv绑定时根据此name值匹配

卷可以处于以下的某种状态:
Available(可用)——一块空闲资源还没有被任何声明绑定
Bound(已绑定)——卷已经被声明绑定
Released(已释放)——声明被删除,但是资源还未被集群重新声明
Failed(失败)——该卷的自动回收失败命令行会显示绑定到 PV 的 PVC 的名称
[root@k8s-master01 ~]# cat pv.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
   name: pv00001  #pv名称
spec:
  capacity:    #存储能力,一个pv对象都要指定一个存储能力,目前仅支持存储空间的设置
    storage: 5Gi  #存储空间
  accessModes:
  - ReadWriteMany  #存储空间
  persistentVolumeReclaimPolicy: Recycle #Recycle(回收)
  nfs:
   path: /data/k8s-volume/pv00001
   server: 192.168.10.72

apiVersion: v1
kind: PersistentVolume
metadata:
   name: pv00002
spec:
  capacity:
    storage: 3Gi
  accessModes:
  - ReadWriteMany
  persistentVolumeReclaimPolicy: Recycle
  nfs:
   path: /data/k8s-volume/pv00002
   server: 192.168.10.72

apiVersion: v1
kind: PersistentVolume
metadata:
   name: pv00003
spec:
  capacity:
    storage: 6Gi
  accessModes:
  - ReadWriteMany
  persistentVolumeReclaimPolicy: Recycle  
  nfs:
   path: /data/k8s-volume/pv00003
   server: 192.168.10.72   

创建 pv 
 kubectl apply -f pv.yaml 

查看创建的pv
[root@k8s-master01 ~]# kubectl get pv
NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv00001   5Gi        RWX            Recycle          Available                                   2m27s
pv00002   3Gi        RWX            Recycle          Available                                   2m49s
pv00003   6Gi        RWX            Recycle          Available                                   4m10s

4.4 pvc的创建

[root@k8s-master01 ~]# cat pvc.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
   name: pvc-nfs
spec:
  accessModes:
  - ReadWriteMany
  resources: 
    requests:
       storage: 5Gi

[root@k8s-master01 ~]# kubectl apply -f pvc.yaml 
persistentvolumeclaim/pvc-nfs created
[root@k8s-master01 ~]# kubectl get pv
NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM             STORAGECLASS   REASON   AGE
pv00001   5Gi        RWX            Recycle          Bound  (已绑定在pvc上)     default/pvc-nfs                           18m
pv00002   3Gi        RWX            Recycle          Available                                             18m
pv00003   6Gi        RWX            Recycle          Available                                             20m
[root@k8s-master01 ~]# kubectl get pvc
NAME      STATUS   VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS   AGE
pvc-nfs   Bound    pv00001   5Gi        RWX                           15s

创建一个pvc小于提供的pv的大小的
[root@k8s-master01 ~]# cat pvc1.yaml 
apiVersion: v1 
kind: PersistentVolumeClaim
metadata: 
  name: pvc002
spec:
  accessModes:
  - ReadWriteMany
  resources:
      requests:
        storage: 2Gi
[root@k8s-master01 ~]# kubectl get pv
NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM             STORAGECLASS   REASON   AGE
pv00001   5Gi        RWX            Recycle          Bound       default/pvc-nfs                           24m
pv00002   3Gi        RWX            Recycle          Bound       default/pvc002                            24m
pv00003   6Gi        RWX            Recycle          Available                                             26m
[root@k8s-master01 ~]# kubectl get pvc
NAME      STATUS   VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS   AGE
pvc-nfs   Bound    pv00001   5Gi        RWX                           6m15s
pvc002    Bound    pv00002   3Gi        RWX                           71s
如上 ,pvc磁盘要求不大于提供的最大的pv磁盘的情况下,会选取接近的pv绑定

pvc也可以使用指定的pv,通过标签选择器
#记得我们需要修改一下名字,名字是不可以重复的
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv2
  labels:           #这里将pv设置一个labels
    app: nfs
spec:
  capacity:
    storage: 10Gi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    path: /data/k8s-volume/pv00002
    server: 192.168.10.72

---

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc2-nfs
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  selector:         ##pvc匹配标签为app=nfs的pv
    matchLabels:
      app: nfs

4.5 创建pod使用pvc

[root@k8s-master01 ~]# cat pod-redis-pvc.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pvc-nfs-pod
spec:
  containers:
  - name: redis
    image: redis:lastest
    ports: 
    - containerPort: 6379
      name: redisport
    volumeMounts:
    - mountPath: /data
      name: redisdata
  volumes:
    - name: redisdata
      persistentVolumeClaim: 
            claimName: pvc-nfs 

[root@k8s-master01 ~]# kubectl apply -f pod-redis-pvc.yaml
pod/pvc-nfs-pod created

创建使用pvc的pod
[root@k8s-master01 ~]# kubectl exec -it pvc-nfs-pod redis-cli
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead.
127.0.0.1:6379> SET devopstack yes
OK
127.0.0.1:6379> get devopstack
"yes"
127.0.0.1:6379> BGSAVE
Background saving started

删除pod重建pod 查看key还有没

[root@k8s-master01 ~]# kubectl delete -f pod-redis-pvc.yaml 
pod "pvc-nfs-pod" deleted

[root@k8s-master01 ~]# kubectl apply -f pod-redis-pvc.yaml 
pod/pvc-nfs-pod created

[root@k8s-master01 ~]# kubectl exec -it pvc-nfs-pod redis-cli
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead.
127.0.0.1:6379> get devopstack
"yes"

pv pvc具有持久性
数据保存在挂载的pv中了
[root@k8s-node01 pv00001]# ll
总用量 4
-rw-r--r-- 1 polkitd ssh_keys 113 4月  14 15:09 dump.rdb
[root@k8s-node01 pv00001]# pwd
/data/k8s-volume/pv00001

4.6 动态pv(storageclass)的创建

StorageClass作为对存储资源的抽象定义,对用户设置的PVC申请屏蔽后端的细节,一方面减轻用户对于存储资源细节的关注,另一方面也减轻了管理员手工管理PV的工作,由系统自动完成PV的创建和绑定,实现了动态的资源供应。使用基于StorageClass的动态资源供应模式将逐步成为云平台的标准存储配置模式
要使用 StorageClass,我们就得安装对应的自动配置程序,比如我们这里存储后端使用的是 nfs,那么我们就需要使用到一个 nfs-client 的自动配置程序,我们也叫它 Provisioner,这个程序使用我们已经配置好的 nfs 服务器,来自动创建持久卷,也就是自动帮我们创建 PV。

参考文档为
https://github.com/kubernetes-retired/external-storage/tree/master/nfs-client

1.配置nfs-client的Deployment文件,将里面的对应的参数替换成我们自己的nfs配置
 wget https://raw.githubusercontent.com/kubernetes-retired/external-storage/master/nfs-client/deploy/deployment.yaml

[root@k8s-master01 storageclass]# cat 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
      containers:
        - name: nfs-client-provisioner
          image: quay.io/external_storage/nfs-client-provisioner:latest
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              value: fuseim.pri/ifs
            - name: NFS_SERVER
              value: 192.168.10.72
            - name: NFS_PATH
              value: /data/k8s-volume
      volumes:
        - name: nfs-client-root
          nfs:
            server: 192.168.10.72
            path: /data/k8s-volume

2.创建一个serveraccount,用于将nfs-client-provisioner中的ServiceAccount绑定到一个nfs-client-provisioner-runner的ClusterRole。而该ClusterRole声明了一些权限,其中就包括了对persistentvolumes的增删改查,所以我们就可以利用ServiceAccount来自动创建PV
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: ["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

fuseim.pri/ifs 需要和deployment保持一致

3.声明了一个名为managed-nfs-storage的Storageclass对象
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: managed-nfs-storage
provisioner: fuseim.pri/ifs # or choose another name, must match deployment's env PROVISIONER_NAME'
parameters:
  archiveOnDelete: "false"

创建

[root@k8s-master01 storageclass]# kubectl apply -f . 
storageclass.storage.k8s.io/managed-nfs-storage created
deployment.apps/nfs-client-provisioner created
serviceaccount/nfs-client-provisioner created
clusterrole.rbac.authorization.k8s.io/nfs-client-provisioner-runner created
clusterrolebinding.rbac.authorization.k8s.io/run-nfs-client-provisioner created
role.rbac.authorization.k8s.io/leader-locking-nfs-client-provisioner created
rolebinding.rbac.authorization.k8s.io/leader-locking-nfs-client-provisioner created

查看 
[root@k8s-master01 storageclass]# kubectl get pods
NAME                                      READY   STATUS    RESTARTS   AGE
nfs-client-provisioner-794b747b95-vdgs4   1/1     Running   0          3m57s

[root@k8s-master01 storageclass]# kubectl get sc
NAME                  PROVISIONER      RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
managed-nfs-storage   fuseim.pri/ifs   Delete          Immediate           false                  8m15s

创建pvc验证我们创建的storageclass

[root@k8s-master01 storageclass]# cat storageclass-nfs.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: test-storage-pvc
spec:
 storageClassName: "managed-nfs-storage"
 accessModes: 
 - ReadWriteMany
 resources:
  requests:
     storage: 1Gi

创建动态的pvc
[root@k8s-master01 storageclass]# kubectl apply  -f storageclass-nfs.yaml 
persistentvolumeclaim/test-storage-pvc created

查看自动创建的pv
[root@k8s-master01 ~]# kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM                      STORAGECLASS          REASON   AGE

pvc-bceac085-3d11-425f-a0b5-a1a9bd8a1fb0   1Gi        RWX            Delete           Bound       default/test-storage-pvc   managed-nfs-storage            9m7s

查看我们创建的pvc
[root@k8s-master01 storageclass]# 

[root@k8s-master01 storageclass]# kubectl get pvc
NAME               STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS          AGE
test-storage-pvc   Bound    pvc-bceac085-3d11-425f-a0b5-a1a9bd8a1fb0   1Gi        RWX            managed-nfs-storage   10s
如上我们已经成功创建了动态的pvc

通过使用pod测试我们创建的动态的pvc,storageclass主要代替pv的工作,当pvc申请资源的时候,自动创建对应的[pv资源.

[root@k8s-master01 storageclass]# cat pod-redis-pvc-storageclass.yaml
apiVersion: v1
kind: Pod
metadata:
  name: storage-nfs-pod
spec:
  containers:
  - name: redis
    image: redis
    ports: 
    - containerPort: 6379
      name: redisport
    volumeMounts:
    - mountPath: /data
      name: redisdata
  volumes:
    - name: redisdata
      persistentVolumeClaim: 
            claimName: test-storage-pvc 

执行
[root@k8s-master01 storageclass]# kubectl apply -f pod-redis-pvc-storageclass.yaml 
pod/storage-nfs-pod created

测试
[root@k8s-master01 storageclass]# # kubectl exec -it storage-nfs-pod redis-cli
[root@k8s-master01 storageclass]# kubectl exec -it storage-nfs-pod redis-cli
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead.
127.0.0.1:6379> SET storage yes
OK
127.0.0.1:6379> BGSAVE
Background saving started
127.0.0.1:6379> 

[root@k8s-master01 storageclass]# kubectl delete -f storageclass-nfs.yaml
persistentvolumeclaim "test-storage-pvc" deleted

[root@k8s-node01 default-test-storage-pvc-pvc-bceac085-3d11-425f-a0b5-a1a9bd8a1fb0]# ll
总用量 4
-rw-r--r-- 1 polkitd ssh_keys 114 4月  15 21:00 dump.rdb
[root@k8s-node01 default-test-storage-pvc-pvc-bceac085-3d11-425f-a0b5-a1a9bd8a1fb0]# pwd
/data/k8s-volume/default-test-storage-pvc-pvc-bceac085-3d11-425f-a0b5-a1a9bd8a1fb0

[root@k8s-master01 storageclass]# kubectl apply -f pod-redis-pvc-storageclass.yaml
pod/storage-nfs-pod created

[root@k8s-master01 storageclass]# kubectl exec -it storage-nfs-pod redis-cli
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead.
127.0.0.1:6379> GET storage
"yes"

  • 我的微信
  • 这是我的微信扫一扫
  • weinxin
  • 我的微信公众号
  • 我的微信公众号扫一扫
  • weinxin
avatar

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: