[K8S系列七]存储-PV、PVC与Storage Class

本质上说,一个volume(卷)就是一个目录,从容器内部可以访问这个目录中的内容,而这个目录是怎么来的,它背后的媒介是什么以及它里面的内容,都是由volume的类型来决定的;而使用volume,只需要在pod上指定使用哪种类型的volume,以及mount到容器中的什么位置即可。K8S支持的存储类型如下所示,这里主要介绍HostPath和Persistent Volume。

K8S 目前支持的存储

1. hostPath

hostPath 类型的volume是映射Pod所在的节点的文件或者目录到 pod 里。在使用 hostPath 类型的存储卷时,也可以设置 type 字段,支持的类型有文件、目录、File、Socket、CharDevice 和 BlockDevice。

1.1 示例

根据附录1的volume-pod.yaml创建一个pod,使用hostPath类型的volume

# kubectl apply -f volume-pod.yaml
# kubectl get pods -o wide
volume-pod                          2/2     Running   0              11m    10.244.80.226   w2                

部署后查看pods详情, 发现volume-pod位于w2节点,登录到w2 尝试在pods的容器中创建文件

# docker ps  |grep volume
d8524ebeb2d0        busybox                                                         "sh -c 'echo The app…"   38 seconds ago      Up 37 seconds                           k8s_busybox-container_volume-pod_default_eb751f47-59eb-4541-986f-fb009d137bb7_46
02791634ee65        nginx                                                           "/docker-entrypoint.…"   46 hours ago        Up 46 hours                             k8s_nginx-container_volume-pod_default_eb751f47-59eb-4541-986f-fb009d137bb7_0
637ddb8efe45        registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.6   "/pause"                 46 hours ago        Up 46 hours                             k8s_POD_volume-pod_default_eb751f47-59eb-4541-986f-fb009d137bb7_0

# 在busybox容器的/busybox-volume目录下创建busybox文件
# docker exec d8524ebeb2d0 touch /busybox-volume/busybox
# docker exec d8524ebeb2d0 ls /busybox-volume/
busybox

# 在nginx容器的/nginx-volume目录下创建nginx文件,可以同时看到busybox文件和nginx文件
# docker exec  02791634ee65  touch /nginx-volume/nginx
# docker exec  02791634ee65  ls /nginx-volume/
busybox  nginx

# 在宿主机的 /tmp/volume-pod 目录下也同时可以看到busybox和nginx文件
# ls /tmp/volume-pod/
busybox  nginx

# 删除volume-pod之后,w2节点/tmp/volume-pod/下的busybox和nginx依然存在
# master节点执行
# kubectl delete pod volume-pod
pod "volume-pod" deleted

# w2 节点执行
# ls /tmp/volume-pod/
busybox  nginx

2. PV、PVC与静态分配

2.1 PV与PVC

因为hostPath类型的volume只映射pod所在的节点的文件或目录到pod中,如果pod因为重启被调度到其他节点时,将会看不到原来节点保存的数据,因此有了网络存储+pv+pvc的方式。
通过PersistentVolume(PV)与PersistentVolumeClaim(PVC)将提供存储与消费存储分离:

  1. PV由管理员负责创建,它如同cpu、mem一样属于集群资源,为满足不同用户需求,一般管理员会在集群创建很多种类的PV,而用户不关心这些pv的实现细节;

2.PVC由用户创建来消费存储,如同通过创建pod来消费cpu、mem资源。

2.2 PV与PVC绑定

PVC与PV是通过PersistentVolume Controller 进行绑定的。PV Controller 会不断地循环去查看每一个 PVC,是不是已经处于 Bound(已绑定)状态。如果不是,那它就会遍历所有的、可用的 PV,并尝试将其与未绑定的 PVC 进行绑定,这样,Kubernetes 就可以保证用户提交的每一个 PVC,只要有合适的 PV 出现,它就能够很快进入绑定状态。而所谓将PV 与 PVC 进行“绑定”,其实就是将这个 PV 对象的名字,填在了 PVC 对象的 spec.volumeName 字段上 。


PVC与PV运作过程(图片来自《Kubernetes in Action》)
2.3 PV、PVC示例

这里以NFS+PV+PVC为例进行说明, NFS搭建过程请参考附录2,根据考附录3 nginx-pv-pvc.yaml,创建nginx(deployment)、nginx-pv(pv)、nginx-pvc(pvc)。nginx-pv挂载在/nfs/data/nginx 下。在/nfs/data/nginx下创建文件1.html,pod中也可以访问,并且pod的重新创建不影响1.html。

# 01 创建deployment、pv、pvc
# kubectl apply -f nginx-pv-pvc.yaml

# 02 查看pv、pvc,pv和pvc的状态都是Bound,nginx-pvc的volume指向nginx-pv
# kubectl get pv,pvc
NAME                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM               STORAGECLASS   REASON   AGE
persistentvolume/nginx-pv   2Gi        RWX            Retain           Bound    default/nginx-pvc                           39m

NAME                              STATUS   VOLUME     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/nginx-pvc   Bound    nginx-pv   2Gi        RWX                           39m

# kubectl get pods -o wide
NAME                                READY   STATUS    RESTARTS         AGE    IP              NODE   NOMINATED NODE   READINESS GATES
nginx-7d7959d89b-tr7jj              1/1     Running   0                38m    10.244.80.227   w2                

# 03 创建文件,演示pv和pvc的效果
# echo  "Hello kubernetes." > /nfs/data/nginx/1.html

# kubectl get pods -o wide
NAME                                READY   STATUS    RESTARTS       AGE    IP              NODE   NOMINATED NODE   READINESS GATES
nginx-7d7959d89b-tr7jj              1/1     Running   0              85m    10.244.80.227   w2                

# curl 10.244.80.227/1.html
Hello kubernetes.

# kubectl delete pod nginx-7d7959d89b-tr7jj
pod "nginx-7d7959d89b-tr7jj" deleted

# kubectl get pods -o wide
NAME                                READY   STATUS    RESTARTS        AGE    IP              NODE   NOMINATED NODE   READINESS GATES
nginx-7d7959d89b-p99k5              1/1     Running   0               113s   10.244.190.89   w1                

# curl 10.244.190.89/1.html
Hello kubernetes.

# docker exec 9cef89890c56 cat /usr/share/nginx/html/1.html
Hello kubernetes.
deployment、pvc、pv、nfs

3.基于StorageClass的动态分配

上节说的PV和PVC方法虽然能实现屏蔽底层存储,但是PV创建比较复杂,通常都是由集群管理员管理,这非常不方便。
利用StorageClass实现,可以根据PVC需求,自动构建相对应的PV持久化存储卷,进一步简化运维管理成本。
StorageClass对象会定义下面两部分内容:

  1. PV的属性。比如,存储类型,Volume的大小等;
  2. 创建这种PV需要用到的存储插。


    StorageClass 运作过程(图片来自《Kubernetes in Action》)
3.1 示例

示例部分参考nfs-subdir-external-provisioner。 相关文件来源于deploy,需要略作修改。

# 01 搭建NFS服务,参考附录2

# 02 配置account及授权, 如果不修改rbac.yaml会使用默认的命名空间
# kubectl apply -f rbac.yaml

# 03 修改deployment.yaml中nfs服务的配置:NFS_SERVER和NFS_PATH。
# kubectl apply -f deployment.yaml

# kubectl get deployment
NAME                     READY   UP-TO-DATE   AVAILABLE   AGE
nfs-client-provisioner   1/1     1            1           78s

# 04 部署Storage Class
# kubectl apply -f class.yaml
storageclass.storage.k8s.io/nfs-client created
# kubectl get storageClass
NAME         PROVISIONER                                   RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
nfs-client   k8s-sigs.io/nfs-subdir-external-provisioner   Delete          Immediate           false                  4s

# 05 部署PVC,发现PV也被自动创建
# kubectl apply -f test-claim.yaml
persistentvolumeclaim/test-claim created
# kubectl get pv,pvc
NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                STORAGECLASS   REASON   AGE
persistentvolume/pvc-f2ec97fc-5b67-4d33-87a4-7344ceb8f522   1Mi        RWX            Delete           Bound    default/test-claim   nfs-client              25s

NAME                               STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/test-claim   Bound    pvc-f2ec97fc-5b67-4d33-87a4-7344ceb8f522   1Mi        RWX            nfs-client     25s

# 06 创建pod使用存储
# kubectl apply -f test-pod.yaml
pod/test-pod created
[root@master storageclass-nfs]# kubectl get pv,pvc
NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                STORAGECLASS   REASON   AGE
persistentvolume/pvc-f2ec97fc-5b67-4d33-87a4-7344ceb8f522   1Mi        RWX            Delete           Bound    default/test-claim   nfs-client              76s

NAME                               STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/test-claim   Bound    pvc-f2ec97fc-5b67-4d33-87a4-7344ceb8f522   1Mi        RWX            nfs-client     76s

[root@master ~]# ls /nfs/data/default-test-claim-pvc-f2ec97fc-5b67-4d33-87a4-7344ceb8f522/
SUCCESS

参考文献

1.Volumes
2.《kubernetes权威指南》
3.Kubernetes 存储设计

附录

1.volume-pod.yaml
kind: Pod
metadata:
  name: volume-pod
spec:
  containers:
  - name: nginx-container
    image: nginx
    ports:
    - containerPort: 80
    volumeMounts:
    - name: volume-pod
      mountPath: /nginx-volume
  - name: busybox-container
    image: busybox
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
    volumeMounts:
    - name: volume-pod
      mountPath: /busybox-volume
  volumes:
  - name: volume-pod
    hostPath:
      path: /tmp/volume-pod

2. NFS搭建流程

NFS(Network File System)网络文件系统,是FreeBSD支持的文件系统中的一种,允许网络中的计算机之间通过TCP/IP网络共享资源。

# 01 master节点搭建nfs
# 安装nfs
yum install -y nfs-utils

# 创建nfs目录
mkdir -p /nfs/data/

# 授予权限
chmod -R 777 /nfs/data
# 编辑export文件
vi /etc/exports
/nfs/data *(rw,no_root_squash,sync)

# 使配置生效
exportfs -r

# 查看是否生效
exportfs
# 显示 /nfs/data      

# 启动rpcbind、nfs服务
systemctl restart rpcbind && systemctl enable rpcbind
systemctl restart nfs && systemctl enable nfs

# 查看rpc服务的注册情况
rpcinfo -p localhost
# showmount测试, 192.168.0.51 为master ip
# showmount -e 192.168.0.51
Export list for 192.168.0.51:
/nfs/data *


# 02 所有node上安装客户端
yum -y install nfs-utils
systemctl start nfs && systemctl enable nfs
3 nginx-pv-pvc.yaml
# 定义PV
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nginx-pv
spec:
  accessModes:
    - ReadWriteMany
  capacity:
    storage: 2Gi
  nfs:
    path: /nfs/data/nginx
    server: 192.168.0.51

---
# 定义PVC,用于消费PV
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nginx-pvc
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 2Gi

---
# 定义Pod,指定需要使用的PVC
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - name: nginx-persistent-storage
          mountPath: /usr/share/nginx/html
      volumes:
      - name: nginx-persistent-storage
        persistentVolumeClaim:
          claimName: nginx-pvc

你可能感兴趣的:([K8S系列七]存储-PV、PVC与Storage Class)