第九课:kubernetes存储

概述
介绍kubernetes中为什么需要使用存储
volume的基本管理方式
怎样创建PVC与PV
结合实际场景怎样使用NFS存储

1. volume介绍与管理

pod里面定义的一种属性值
在dokcer的设计实现中,容器中的数据是临时的,当容器被销毁时,其中的数据将会丢失。如果需要(有状态的服务)持久化数据(集群或者日志),那么就需要使用docker数据卷挂载宿主机上的文件或者目录到容器中。在kubernetes中,当pod重建的时候,数据会丢失,另外,一个pod中同时运行多个容器时,容器之间需要共享文件,所以kubernetes通过数据卷挂载的方式来提供pod数据的持久化。

1.1 区别于docker的volume

docker也有volume概念,但对它只有少量且松散的管理。在docker中,volume是磁盘上或者另外一个容器内的目录。虽然docker现在也能提供volume驱动程序,但是目前功能还非常有限(截止docker1.7,每个容器只允许有一个volume驱动程序,并且无法将参数传递给卷,并且支持的存储驱动有限)。

1.2 声明方式

使用卷时,Pod声明中需要提供卷的类型(.spec.volumes字段)和卷挂载的位置(.spec.containers.volumeMounts字段)

1.3 kubernetes中常用支持的卷类型

目前kubernetes支持的数据全,类型如下:

类型 说明
EmptyDir 单节点存储
HostPath 单节点存储
GCE Persistent Disk 谷歌云存储
AWS Elastic Block Store AWS云存储
NFS 网络文件系统
iSCSI
GlusterFS
RBD ceph块存储
Persistent Volume Claim(PVC)

图解volume在kubernetes中的位置
第九课:kubernetes存储

1.4 kubernetes哪些资源对象使用volume?

Pod

1.3.1 案例一:挂载hostpath到pod

hostPath 卷能将主机节点文件系统上的文件或目录挂载到您的 Pod 中。
把主机中的/data/nginx/log目录挂载到pod中的/var/log/nginx目录
需要在所有节点创建目录/data/nginx/log

node01&node02
mkdir -p /data/nginx/log
master01
mkdir -p /root/volume && cd /root/volume
cat >demo-mount-hostpath.yaml<<EOF
apiVersiono: v1
kind: Pod
metadata:
  name: pod-hostpath
spec:
  containers:
  - name: nginx
    image: nginx
    volumeMounts:
    - name: nginx-log
      mountPath: /var/log/nginx
  volumes:
  - name: nginx-log
    hostPath:
      path: /data/nginx/log
EOF

启动nginx服务

[root@master01 volume]# kubectl apply -f demo-mount-hostpath.yaml 
pod/pod-hostpath created
[root@master01 volume]# kubectl get pod -o wide
NAME                                     READY   STATUS      RESTARTS   AGE     IP             NODE             NOMINATED NODE   READINESS GATES
pod-hostpath                             1/1     Running     0          20s     172.17.15.13   192.168.68.149   <none>           <none>

启用dnstools容器,测试nginx访问,并在node01上查看日志文件内容

[root@master01 volume]# kubectl run -it --rm --restart=Never --image=infoblox/dnstools:latest dnstools
If you don‘t see a command prompt, try pressing enter.
dnstools# curl 172.17.15.13

[root@node01 log]# tail access.log -f
172.17.15.14 - - [18/Aug/2020:04:15:32 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.60.0" "-"

1.3.2 案例二:挂载空目录到POD

emptyDir类型的volume在pod分配到node上时被创建,kubernetes会在node上自动分配一个目录,因此无需指定宿主机node上对应的目录文件。这个目录的初始内容为空,当pod从node上移除时,emptyDir中的数据会被永久删除。

说明:容器崩溃并不会导致Pod从节点上移除,因此容器崩溃时emptyDir卷中的数据是安全的。

emptyDir Volume主要用于某些应用程序无需永久保存的临时目录,多个容器的共享目录等。
Pod示例:

cat > demo-mount-emptydir.yaml<<EOF
apiVersiono: v1
kind: Pod
metadata:
  name: pod-emptydir
spec:
  containers:
  - name: test-container
    image: patsys/test-webserver
    volumeMounts:
    - name: cache-volume
      mountPath: /cache
  volumes:
  - name: cache-volume
    emptyDir: {}
EOF

测试:
从master上打开新建的pod-emptydir的终端,在/cache目录下创建一个测试文件test.txt,在node01上可以查看到在pod里创建的文件,删除pod以后,文件也被移除。

[root@master01 volume]# kubectl exec -it nginx-7bb7cd8db5-5h2d5 /bin/sh
/ # cd /cache/
/cache # ls
/cache # touch test.txt
test.txt
#node01
find / -name "test.txt"
/var/lib/kubelet/pods/d80a3125-8b2d-485d-9096-e7053797ee93/volumes/kubernetes.io~empty-dir/cache-volume/test.txt

[root@master01 volume]# kubectl delete -f demo-mount-emptydir.yaml  
pod "pod-emptydir" deleted
[root@node01 cache-volume]# find / -name "test.txt"
[root@node01 cache-volume]# 

2. PersistentVolume 与 Persistent Volume Claim

2.1 持久卷Persistent Volume(PV)

PV是由管理员设置的存储卷,它是集群的一部分,就像节点是集群中的资源一样,PV也是集群中的资源。PV是与Vloume类似的卷插件,具有独立的生命周期。

2.1.1 配置方式

动态和静态方式
推荐的方式是使用动态配置

2.1.2 PV回收策略

PV可以由多种回收策略,包括“Retain”,“Recycle”,“Delete”。对于动态配置的PV来说,默认回收策略为“Delete”。
"delete",表示当用户删除对应的PVC的时候,动态配置的volume将自动删除。
"Retain",如果用户删除PVC,对应的PV不会被删除。相反,它将变成Released状态,表示所有的数据可以被手动恢复。
"Recycle" 该策略已被弃用。

2.1.3 列出PV

[root@master01 volume]# kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                        STORAGECLASS          REASON   AGE
pvc-957bd492-cf4c-4a01-92b7-c76fded6c538   5Gi        RWX            Delete           Bound    monitoring/prometheus-data   managed-nfs-storage            5d20h
pvc-a0ff4b83-c9f3-430e-92fb-d95878db0f51   5Gi        RWO            Delete           Bound    monitoring/grafana           managed-nfs-storage            5d20h

2.1.4 修改PV回收策略

选择PV中的一个并更改它的回收策略

kubectl patch pv <your-pv-name> -p ‘{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}‘

2.1.5 PV的访问模式

  1. ReadWriteOnce:最基本的方式,可读可写单个pod挂载
  2. ReadOnlyMany:可以以只读的方式被多个pod挂载
  3. ReadWriteMany:可以以读写的方式被多个pod挂载
    注意:不是每一种存储都支持这三种方式,如共享方式,目前支持的还不多(数据一致性问题),通常简单的实现为NFS。所以在PVC绑定PV时通常根据两个条件来绑定,一个是存储的大小,另一个就是访问模式。

2.1.6 PV支持的存储驱动

NFS,ISCSI,RBD,HostPath

2.2 Persistent Volume Claim(PVC)

PVC是用户对存储PV的请求,它与POD相似,pod消耗节点资源,PVC消耗PV资源。pod可以请求特定级别的资源(CPU和内存)。声明可以请求特定大小和访问模式(例如:可以以读写一次或者只读多次模式挂载)。集群管理员还可以使用StorageClasses来设置动态提供存储。

2.2.1 PVC存储挂载过程

  1. 集群管理员创建由物理存储支持的PV。管理员不将卷与任何pod关联。
  2. 集群用户创建一个PVC,它将自动绑定到合适的PV。
  3. 用户创建一个使用PVC作为存储的pod。

2.2.2 PV与volume的区别

  1. PV只能是网络存储,不属于任何的节点,必须可以在每个节点上可以访问。
  2. PV不是定义在pod上,而是独立于pod,是属于kubernetes存储的一部分。
  3. PV目前支持的类型:NFS,ISCSI,RBD,HostPath
  4. volume与使用它的pod之间是一种静态绑定关系,是定义pod里面的一种属性,同时定义了它使用的volume的类型。
  5. volume无法单独创建,因为它不是独立的kubernetes资源对象。

2.2.3 案例一:PVC挂载NFS(以部署grafana服务为例)

2.2.3.1 安装NFS服务

我们在安装监控的时候已经安装了NFS,并且创建了PV,分别挂载到prometheus和grafana两个服务的POD上。
创建NFS的过程参考“第六课:部署集群监控系统”

2.2.3.2 关联NFS到PV

参考我们之前配置监控服务的时候创建的NFS存储,同时创建的2个PV

[root@master01 grafana]# kubectl get pv pvc-957bd492-cf4c-4a01-92b7-c76fded6c538 -o yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  annotations:
    pv.kubernetes.io/provisioned-by: fuseim.pri/ifs
  creationTimestamp: "2020-08-13T04:54:09Z"
  finalizers:
  - kubernetes.io/pv-protection
  name: pvc-957bd492-cf4c-4a01-92b7-c76fded6c538
  resourceVersion: "414964"
  selfLink: /api/v1/persistentvolumes/pvc-957bd492-cf4c-4a01-92b7-c76fded6c538
  uid: 9d3e3cb5-76ee-42af-9fe5-93a953c7cbc1
spec:
  accessModes:
  - ReadWriteMany                            #访问模式[ReadWriteOnce|ReadOnlyMany|ReadWriteMany]
  capacity:                                  #容量
    storage: 5Gi                             #PV可用的大小
  claimRef:
    apiVersion: v1
    kind: PersistentVolumeClaim
    name: prometheus-data
    namespace: monitoring
    resourceVersion: "414957"
    uid: 957bd492-cf4c-4a01-92b7-c76fded6c538
  nfs:                                       #NFS配置
    path: /ifs/kubernetes/monitoring-prometheus-data-pvc-957bd492-cf4c-4a01-92b7-c76fded6c538  #NFS路径
    server: 192.168.68.146                   #NFSserver地址
  persistentVolumeReclaimPolicy: Delete      #回收策略[Delete|Retain|Recycle]
  storageClassName: managed-nfs-storage      #存储类名称
  volumeMode: Filesystem
status:
  phase: Bound

2.2.3.3 创建PVC

创建PVC并关联到PV,主要关注点:存储类的名称,访问模式,存储空间请求。

[root@master01 grafana]# more grafana-pvc.yaml 
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: grafana
  namespace: monitoring
spec:
  storageClassName: managed-nfs-storage      #存储类名称,与PV文件中spec:storageClassName相对应
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi

2.2.3.4 pod关联pvc

创建使用该PVC的Pod

[root@master01 grafana]# more grafana-deployment.yaml 
...
  seec:
    containers:
      volumes:
      - name: grafana-storage
        persistentVolumeClaim:
          claimName: grafana                 #关联PVC的名称,与PVC.yaml内的metadata:name对应

2.3 StorageClass

为PVC动态分配PV
每个StorageClass都有一个分配器,用来决定使用哪个卷插件分配PV。

2.3.1 StorageClass

在kubernetes中,用户使用pod需要持久化数据(集群),通常情况下,需要集群管理员手工创建PV,然后用户绑定在POD中,提供给pod中的集群使用。假设在大规模的情况下,如果每次都是需要管理员人工创建PV,那么严重影响效率,所以引入了StorageClass,让PVC通过StorageClass自动创建PV。

2.3.2 StorageClass支持的卷插件

  1. AWS Elastic Block Store
  2. RBD
  3. Local
  4. GlusterFS
  5. CephFS

2.3.3 StorageClass创建PV流程

  1. 集群管理员预先创建存储类(storageclass)
  2. 用户创建pod,pod中使用指定存储类的持久化存储声明(PVC)
  3. 存储持久化声明(PVC)通知系统,需要一个持久化存储(PV)
  4. 系统读取存储类信息
  5. 系统基于存储类的信息,在后台自动创建PVC需要的PV
  6. 在后台创建完成PV之后,PVC绑定到PV,进行数据的持久化处理
  7. POD通过PVC持久化存储数据

2.3.4 案例分析:监控服务存储部署

1.管理员预先创建存储类storageclass名称为:managed-nfs-class
每个sotrageclass都包含provisionerparameters,reclaimPolicy字段,这些字段在storageclass需要动态分配PV时会用到。

[root@master01 nfs]# more nfs-class.yaml 
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‘ 匹配nfs-deployment.yaml中env:name:PROVISIONER_NAME
parameters:
  archiveOnDelete: "true"

2.创建nfs服务

[root@master01 nfs]# more nfs-deployment.yaml 
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-client-provisioner
---
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: nfs-client-provisioner
spec:
  replicas: 1
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: nfs-client-provisioner
    spec:
      serviceAccountName: nfs-client-provisioner
      containers:
        - name: nfs-client-provisioner
          imagePullPolicy: IfNotPresent
          image: quay.io/external_storage/nfs-client-provisioner:latest
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME   #这里的提供者字段需要与storageclass里的想对应
              value: fuseim.pri/ifs
            - name: NFS_SERVER
              value: 192.168.68.146
            - name: NFS_PATH
              value: /ifs/kubernetes
      volumes:
        - name: nfs-client-root
          nfs:
            server: 192.168.68.146
            path: /ifs/kubernetes

3.声明PVC
创建pvc名称为grafana,关联存储类stroageclass的名称为前面我们创建的managed-nfs-storage

[root@master01 grafana]# more grafana-pvc.yaml 
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: grafana
  namespace: monitoring
spec:
  storageClassName: managed-nfs-storage
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi

4.PVC会自动生成一个PV,并绑定到PVC

[root@master01 grafana]# kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                        STORAGECLASS          REASON   AGE
pvc-a0ff4b83-c9f3-430e-92fb-d95878db0f51   5Gi        RWO            Delete           Bound    monitoring/grafana           managed-nfs-storage            6d2h

这里的PV名称为pvc-a0ff4b83-c9f3-430e-92fb-d95878db0f51并不是我们手动创建的,而是系统通过PVC在后台自动生成的,并且绑定到名称为grafana的pvc上。
5.在创建服务的deployment文件中引用PVC

[root@master01 grafana]# more grafana-deployment.yaml
...
    volumes:
      - name: grafana-storage
        persistentVolumeClaim:
          claimName: grafana
...

6.启动POD后,数据会持久化到nfs上

[root@master01 monitoring-grafana-pvc-a0ff4b83-c9f3-430e-92fb-d95878db0f51]# ll
total 1752
-rw-r--r-- 1 nfsnobody nfsnobody 1794048 Aug 19 15:01 grafana.db
drwxr-xr-x 3 nfsnobody nfsnobody      36 Aug 14 14:28 plugins
drwx------ 2 nfsnobody nfsnobody       6 Aug 13 12:53 png

第九课:kubernetes存储

上一篇:图片上传接口


下一篇:ajax