k8s入门篇-持久化存储管理

作者:@skyflask
转载本文请注明出处:https://www.cnblogs.com/skyflask/p/16823590.html


目录

一、Volumes
二、Volumes的类型
2.1  ConfigMap
2.2 emptyDir
2.3  hostPath
2.4 NFS
3  PV&PVC
3.1 PV&PVC概述
3.2 创建PV
3.3 PVC使用案例
3.4 PVC创建和挂载失败原因

一、Volumes

 

 

二、Volumes的类型

2.1  ConfigMap

ConfigMap卷也可以作为volume使用,存储在ConfigMap中的数据可以通过ConfigMap类型的卷挂载到Pod中,然后使用该ConfigMap中的数据。引用ConfigMap对象时,只需要在volume中引用ConfigMap的名称即可,同时也可以自定义ConfigMap的挂载路径。

例如,将名称为log-config的ConfigMap挂载到Pod的/etc/config目录下,挂载的文件名称为path指定的值,当前为log_level:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: v1
kind: Pod
metadata:
  name: configmap-pod
spec:
  containers:
    - name: test
      image: busybox
      volumeMounts:
        - name: config-vol
          mountPath: /etc/config
  volumes:
    - name: config-vol
      configMap:
        name: log-config
        items:
          - key: log_level
            path: log_level

  

2.2 emptyDir

 

和上述volume不同的是,如果删除Pod,emptyDir卷中的数据也将被删除,一般emptyDir卷用于Pod中的不同Container共享数据。它可以被挂载到相同或不同的路径上。

默认情况下,emptyDir卷支持节点上的任何介质,可能是SSD、磁盘或网络存储,具体取决于自身的环境。可以将emptyDir.medium字段设置为Memory,让Kubernetes使用tmpfs(内存支持的文件系统),虽然tmpfs非常快,但是tmpfs在节点重启时,数据同样会被清除,并且设置的大小会被计入到Container的内存限制当中

使用emptyDir卷的示例,直接指定emptyDir为{}即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: k8s.gcr.io/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  volumes:
  - name: cache-volume
    emptyDir: {}

  

案例:容器中使用emptyDir进行数据共享

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "1"
  labels:
    app: nginx
  name: nginx-emptdir-deploy
  namespace: default
spec:
  progressDeadlineSeconds: 600
  replicas: 2 #副本数
  revisionHistoryLimit: 10 # 历史记录保留的个数
  selector:
    matchLabels:
      app: nginx-emptydir
      type: front
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx-emptydir
        type: front
    spec:
      containers:
      - image: nginx:1.15.2  #第一个容器,挂载点/opt,类型是emptydir
        imagePullPolicy: IfNotPresent
        name: nginx
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:
        - mountPath: /opt
          name: share-volume
      - image: nginx:1.15.2  #第二个容器,挂载点/mnt,类型是emptydir
        imagePullPolicy: IfNotPresent
        name: nginx2
        command:
        - sh
        - -c
        - sleep 3600
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:
        - mountPath: /mnt
          name: share-volume
      dnsPolicy: ClusterFirst
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
      volumes:
      - name: share-volume
        emptyDir: {}

 

挂载后,写入test字符串:

1
2
3
4
[root@k8s-master01 ~/k8s/volums]# kubectl exec -it nginx-emptdir-deploy-7784c5bcf4-25v89 -c nginx -- cat /opt/test
test
[root@k8s-master01 ~/k8s/volums]# kubectl exec -it nginx-emptdir-deploy-7784c5bcf4-25v89 -c nginx2 -- cat /mnt/test
test

  

再次修改,可以看到两个容器内的内容都变了,说明emptydir是容器间共享。

1
2
3
4
5
6
7
8
9
10
[root@k8s-master01 ~/k8s/volums]# kubectl exec -it nginx-emptdir-deploy-7784c5bcf4-25v89 -c nginx -- bash
root@nginx-emptdir-deploy-7784c5bcf4-25v89:/# echo "my name is nginx" /opt/test
my name is nginx /opt/test
root@nginx-emptdir-deploy-7784c5bcf4-25v89:/# echo "my name is nginx" > /opt/test
root@nginx-emptdir-deploy-7784c5bcf4-25v89:/# exit
exit
[root@k8s-master01 ~/k8s/volums]# kubectl exec -it nginx-emptdir-deploy-7784c5bcf4-25v89 -c nginx2 -- cat /mnt/test
my name is nginx
[root@k8s-master01 ~/k8s/volums]# kubectl exec -it nginx-emptdir-deploy-7784c5bcf4-25v89 -c nginx -- cat /opt/test
my name is nginx

  

2.3  hostPath

通过挂载宿主机的目录或文件到容器里面,例如,我们将宿主机的时区文件挂载到pod,初始化pod时区:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "1"
  labels:
    app: nginx
  name: nginx-hostpath-deploy
  namespace: default
spec:
  progressDeadlineSeconds: 600
  replicas: 2 #副本数
  revisionHistoryLimit: 10 # 历史记录保留的个数
  selector:
    matchLabels:
      app: nginx-hostpath
      type: front
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx-hostpath
        type: front
    spec:
      containers:
      - image: nginx:1.15.2
        imagePullPolicy: IfNotPresent
        name: nginx
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:
        - mountPath: /opt
          name: share-volume
        - mountPath: /etc/localtime  #将宿主机的时区挂载到pod
          name: timezone
      - image: nginx:1.15.2
        imagePullPolicy: IfNotPresent
        name: nginx2
        command:
        - sh
        - -c
        - sleep 3600
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:
        - mountPath: /mnt
          name: share-volume
      dnsPolicy: ClusterFirst
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
      volumes:
      - name: share-volume
        emptyDir: {}
      - name: timezone  #设置hostpath
        hostPath:
          path: /etc/localtime
          type: File

  

 

 

hostPath卷常用的type(类型)如下:

  • type为空字符串:默认选项,意味着挂载hostPath卷之前不会执行任何检查。
  • DirectoryOrCreate:如果给定的path不存在任何东西,那么将根据需要创建一个权限为0755的空目录,和Kubelet具有相同的组和权限。
  • Directory:目录必须存在于给定的路径下。
  • FileOrCreate:如果给定的路径不存储任何内容,则会根据需要创建一个空文件,权限设置为0644,和Kubelet具有相同的组和所有权。
  • File:文件,必须存在于给定路径中。
  • Socket:UNIX套接字,必须存在于给定路径中。
  • CharDevice:字符设备,必须存在于给定路径中。
  • BlockDevice:块设备,必须存在于给定路径中。

 

2.4 NFS

NFS卷也是一种网络文件系统,同时也可以作为动态存储,和GFS类似,删除Pod时,NFS中的数据不会被删除。NFS可以被多个写入同时挂载。

在其中一个节点安装nfs服务。

1
2
3
4
5
6
7
8
9
yum install nfs-uitls -y
systemctl nfs-server start
systemctl start rpcbind
systemctl start nfs
systemctl enable rpcbind
systemctl enable nfs
 
cat /etc/exports
/data1/nfs 10.10.2.0/24(rw,sync,no_root_squash)

  

在每个需求挂载nfs的机器上安装nfs客户端:yum install nfs-uitls -y

使用nfs:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "1"
  labels:
    app: nginx
  name: nginx-hostpath-deploy
  namespace: default
spec:
  progressDeadlineSeconds: 600
  replicas: 2 #副本数
  revisionHistoryLimit: 10 # 历史记录保留的个数
  selector:
    matchLabels:
      app: nginx-hostpath
      type: front
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx-hostpath
        type: front
    spec:
      containers:
      - image: nginx:1.15.2
        imagePullPolicy: IfNotPresent
        name: nginx
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:
      - image: nginx:1.15.2
        imagePullPolicy: IfNotPresent
        name: nginx2
        command:
        - sh
        - -c
        - sleep 3600
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:
        - mountPath: /opt
          name: nfs-volume   #挂载nfs卷
      dnsPolicy: ClusterFirst
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
      volumes:
      - name: nfs-volume  #定义nfs挂载卷
        nfs:
          server: 10.10.2.129
          path: /data1/nfs/nginx

  

测试:

nfs上更新文件:

 

 

pod上查看文件:

 

 

 缺点:nfs属于单点,没有保障,不建议生产环境上使用。

 

3  PV&PVC

3.1 PV&PVC概述

PersistentVolume(简称PV)是由管理员设置的存储,它同样是集群中的一类资源,PV是容量插件,如Volumes(卷),但其生命周期独立使用PV的任何Pod,PV的创建可使用NFS、iSCSI、GFS、CEPH等。

PersistentVolumeClaim(简称PVC)是用户对存储的请求,类似于Pod,Pod消耗节点资源,PVC消耗PV资源,Pod可以请求特定级别的资源(CPU和内存),PVC可以请求特定的大小和访问模式。例如,可以以一次读/写或只读多次的模式挂载。

虽然PVC允许用户使用抽象存储资源,但是用户可能需要具有不同性质的PV来解决不同的问题,比如使用SSD硬盘来提高性能。所以集群管理员需要能够提供各种PV,而不仅是大小和访问模式,并且无须让用户了解这些卷的实现方式,对于这些需求可以使用StorageClass资源实现。

目前PV的提供方式有两种:静态或动态。

静态PV由管理员提前创建,动态PV无需提前创建,只需指定PVC的StorageClasse即可。

(1)回收策略

当用户使用完卷时,可以从API中删除PVC对象,从而允许回收资源。回收策略会告诉PV如何处理该卷,目前卷可以保留、回收或删除。

  • Retain:保留,该策略允许手动回收资源,当删除PVC时,PV仍然存在,volume被视为已释放,管理员可以手动回收卷。【静态PV推荐】
  • Recycle:回收,如果volume插件支持,Recycle策略会对卷执行rm -rf清理该PV,并使其可用于下一个新的PVC,但是本策略已弃用,建议使用动态配置。【将会被废弃】
  • Delete:删除,如果volume插件支持,删除PVC时会同时删除PV,动态卷默认为Delete。【动态PV推荐】

3.2 创建PV

在使用持久化时,需要先创建PV,然后再创建PVC,PVC会和匹配的PV进行绑定,然后Pod即可使用该存储。

3.2.1 创建一个基于NFS的PV

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0003  #PV名称
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: slow
  mountOptions:
    - hard
    - nfsvers=4.1
  nfs:
    path: /tmp
    server: 10.10.2.129

  

说明:

capacity:容量。需要后端存储支持才行,比如NFS就不支持。

accessModes:访问模式。包括以下3种:

  • ReadWriteOnce:可以被单节点以读写模式挂载,命令行中可以被缩写为RWO。
  •  ReadOnlyMany:可以被多个节点以只读模式挂载,命令行中可以被缩写为ROX。
  •  ReadWriteMany:可以被多个节点以读写模式挂载,命令行中可以被缩写为RWX。

storageClassName:PV的类,一个特定类型的PV只能绑定到特定类别的PVC。【PV和PVC绑定关系的名称】

persistentVolumeReclaimPolicy:回收策略。

  • Retain:保留,该策略允许手动回收资源,当删除PVC时,PV仍然存在,volume被视为已释放,管理员可以手动回收卷。【静态PV推荐】
  • Recycle:回收,如果volume插件支持,Recycle策略会对卷执行rm -rf清理该PV,并使其可用于下一个新的PVC,但是本策略已弃用,建议使用动态配置。【将会被废弃】
  • Delete:删除,如果volume插件支持,删除PVC时会同时删除PV,动态卷默认为Delete。【动态PV推荐】

mountOptions:非必须,新版本中已弃用。

nfs:NFS服务配置。包括以下两个选项:

  •  path:NFS上的目录
  • server:NFS的IP地址

创建的PV会有以下几种状态:

  1. Available(可用),没有被PVC绑定的空间资源。
  2. Bound(已绑定),已经被PVC绑定。
  3. Released(已释放),PVC被删除,但是资源还未被重新使用。
  4. Failed(失败),自动回收失败。

 

 3.2.2 创建一个hostpath的PV

1
2
3
4
5
6
7
8
9
10
11
12
13
14
kind: PersistentVolume
apiVersion: v1
metadata:
  name: task-pv-volume
  labels:
    type: local
spec:
  storageClassName: hostpath
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/mnt/data"

  hostpath的PV一般在线上环境很少使用,除非是内网环境,将某台节点的目录共享给pod使用,此时,共享目录和pod必须绑定,也就是pod的调度只能绑定在本主机上,不能随便漂移。

 

3.3 PVC使用案例

我们通过一个案例来体验PV和PVC的使用。

3.3.1 定义一个PV

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
cat pv-nfs.yaml
 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: nfs-slow
  nfs:
    path: /data1/nfs
    server: 10.10.2.129

  定义一个叫pv-nfs的pv,大小5GB,单节点读写权限,storageClassName是 nfs-slow。挂载在nfs的/data1/nfs下面。

 

3.3.2 定义一个PVC

1
2
3
4
5
6
7
8
9
10
11
12
13
cat pvc-nfs.yaml
 
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: task-pvc-claim
spec:
  storageClassName: nfs-slow
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 3Gi

  PVC的名称是task-pvc-claim,同样,storageClassName是 nfs-slow,单点读写权限,大小3GB。注意:storageClassName和读写权限必须一样,大小必须小于等于PV,这样才会满足。

 

 

3.3.3 定义deployment使用pvc

定义deploy:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
cat dp-nfs.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx-pvc
  name: nginx-pvc-test
  namespace: default
spec:
  replicas: 2
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: nginx-pvc
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx-pvc
    spec:
      volumes:   #使用pvc
      - name: task-pv-storage
        persistentVolumeClaim:
          claimName: task-pvc-claim
      containers:
      - env:
        - name: TZ
          value: Asia/Shanghai
        - name: LANG
          value: C.UTF-8
        image: nginx
        imagePullPolicy: IfNotPresent
        name: nginx
        volumeMounts:  #将PV的内容挂载到容器
        - mountPath: "/usr/share/nginx/html"
          name: task-pv-storage

  

定义svc来测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
cat nginx-svc.yaml
  
apiVersion: v1
kind: Service
metadata:
  annotations:
  labels:
    app: nginx-pvc
  name: nginx-pvc-svc
  namespace: default
spec:
  ports:
  - name: web #service端口的名称
    port: 80 #service自己的端口
    protocol: TCP #后端协议
    targetPort: 80 #后端应用的端口
  sessionAffinity: None
  selector:
    app: nginx-pvc
  type: NodePort
status:
  loadBalancer: {}

  

 

 

 

 

 

 

 

3.4 PVC创建和挂载失败原因

 

 

 

posted @   skyflask  阅读(148)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
历史上的今天:
2019-10-25 Zabbix实战-简易教程--中间件kafka监控
2019-10-25 Zabbix实战-简易教程--中间件ZooKeeper监控
2019-10-25 Zabbix实战-简易教程--中间件RabbitMQ监控
点击右上角即可分享
微信分享提示