Kubernetes之数据存储

        pod中容器的销毁重建我们会发现一个问题,容器销毁时,保存在容器中的数据也会随之被清除,因此我们需要借助Volume来实现数据的持久化。
        在创建pod时,可以定义Volume,它是挂载到具体的文件目录下的,这个Volume可以被多个容器所共享。kubernetes通过Volume实现了同一个Pod中不同容器之间的数据共享以及数据的持久化存储。

Kubernetes的Volume有如下几种类型:

  • 简单存储:EmptyDir、HostPath、NFS
  • 高级存储:PV、PVC
  • 配置存储:ConfigMap、Secret

一、简单存储类型

1、EmptyDir

        该类型的Volume在Pod分配到Node上时被创建,并自动分配一个目录,因此无需指定宿主机Node上对应的目录文件。当Pod销毁时,EmptyDir中的数据也会被永久删除。
其用途如下说明:

  • 临时空间:例如用于某些应用程序运行时所需的临时目录,且无须永久保留
  • 一个容器需要从另一个容器中获取数据的目录(多容器共享目录)

如下我们通过busybox读取一个springboot项目中的log信息,来演示多容器共享目录:

emptydir-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: volume-emptydir
  namespace: dev
spec:
  containers:
  - name: boot
    image: registry.cn-hangzhou.aliyuncs.com/button_dev/test:v1.4
    ports:
    - containerPort: 8082
    volumeMounts:  # 将name为:logs-volume的volume挂载到容器中,对应的目录为/var/tmp/logs
    - name: logs-volume
      mountPath: /var/tmp/logs
  - name: busybox
    image: busybox:1.30
    command: ["/bin/sh","-c","tail -f /logs/boot.info.log"] # 初始命令,动态读取指定文件中内容
    volumeMounts:  # 将logs-volume挂载到busybox容器中,对应的目录为 /logs
    - name: logs-volume
      mountPath: /logs
  volumes: # 声明volume,name为logs-volume,类型为emptyDir
  - name: logs-volume
    emptyDir: {}

然后我们查看busybox容器中的log信息,可以发现读取到了我们springboot项目的启动日志:

 kubectl logs -f volume-emptydir -n dev -c busybox

在这里插入图片描述

2、HostPath

        思考一个问题,EmptyDir在销毁时数据就丢失了,如果想长期保存这些数据,EmptyDir显然不能满足了。如果想简单的将数据持久化到主机中,可以选择HostPath。HostPath是将Node主机中一个实际目录挂载到Pod中,以供容器使用,就算pod销毁了,数据依然保存在node主机上。

vim hostpath-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: volume-hostpath
  namespace: dev
spec:
  containers:
 - name: boot
    image: registry.cn-hangzhou.aliyuncs.com/button_dev/test:v1.4
    ports:
    - containerPort: 8082
    volumeMounts:  # 将name为logs-hostpath-volume的volume挂载到容器中,对应的目录为/var/tmp/logs
    - name: logs-hostpath-volume
      mountPath: /var/tmp/logs
 - name: busybox
    image: busybox:1.30
    command: ["/bin/sh","-c","tail -f /logs/boot.info.log"]
    volumeMounts:  # 将logs-hostpath-volume挂载到busybox容器中,对应的目录为/logs
    - name: logs-hostpath-volume
      mountPath: /logs
  volumes: # 声明volume,name为logs-hostpath-volume,类型为hostPath
 - name: logs-hostpath-volume
    hostPath:
      path: /mnt/logs
      type: DirectoryOrCreate  # 目录存在就使用,不存在就先创建后使用

type值的说明:

  • DirectoryOrCreate 目录存在就使用,不存在就先创建后使用
  • Directory 目录必须存在
  • FileOrCreate 文件存在就使用,不存在就先创建后使用
  • File 文件必须存在
  • Socket unix套接字必须存在
  • CharDevice 字符设备必须存在
  • BlockDevice 块设备必须存在
    在这里插入图片描述
    在node2中查看对应的文件目录:
    Kubernetes之数据存储_第1张图片

3、NFS

        HostPath将pod的数据保存到了调度的node节点上,一旦node节点故障,pod被调度到了别的节点,此时相应的数据也就丢失了。所以需要单独的存储系统,我们只需要将相关数据保存至存储系统,就可以解决该问题。比较常见的存储系统有NFS、CIF等。

以nfs为例,找一台机器安装nfs(我这里直接安装到了master节点上):

#安装
yum install nfs-utils -y
#创建一个共享目录
mkdir /home/data/nfs -pv
#将共享目录的读写权限暴露给指定网段中的所有主机(根据自己网段配置)
vim /etc/exports
#配置内容如下
/home/data/nfs     192.168.242.0/24(rw,no_root_squash)
#启动nfs
systemctl restart nfs

接下来在每个kubernetes集群节点上都安装nfs,不需要配置和启动(只是为了node节点可以驱动nfs设备):

yum install nfs-utils -y

将上面的案例做些改动:

vim nfs-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: volume-nfs
  namespace: dev
spec:
  containers:
  - name: boot
    image: registry.cn-hangzhou.aliyuncs.com/button_dev/test:v1.4
    ports:
    - containerPort: 8082
    volumeMounts:
    - name: logs-nfs-volume
      mountPath: /var/tmp/logs
  - name: busybox
    image: busybox:1.30
    command: ["/bin/sh","-c","tail -f /logs/boot.info.log"]
    volumeMounts:
    - name: logs-nfs-volume
      mountPath: /logs
  volumes:
  - name: logs-nfs-volume
    nfs:
      server: 192.168.242.134 #nfs服务器地址
      path: /home/data/nfs #共享文件路径

创建完成后,我们可以查看nfs的文件目录:
在这里插入图片描述

一、高级存储

在kubernetes集群使用数据存储,由于所支持的存储服务众多,为了能够屏蔽底层存储的实现细节,方便我们的使用,k8s引入了PV和PVC两种资源对象。
PV(Persistent Volume)是持久化卷的意思,是对底层存储设备的一种抽象。一般该部分由管理员创建和配置。
PVC(Persistent Volume Claim)是持久化卷声明的意思,简单来说就是我们对应存储的需求声明。简而言之PVC就是用户向kubernetes系统发出的一种资源需求申请。
看到这里,简单概括一下分工:存储服务一般由存储负责的工程师维护,PV由kubernetes管理员维护,PVC由用户维护。

1、PV

资源清单如下:

apiVersion: v1  
kind: PersistentVolume
metadata:
  name: pv2
spec:
  nfs:       # 存储类型,与底层真正存储对应
  capacity:  # 存储能力
    storage: 2Gi
  accessModes:  # 访问模式
  storageClassName: # 存储类别
  persistentVolumeReclaimPolicy: # 回收策略

参数详细说明:
(1)存储类型:根据自己的需求,不同存储类型的配置都有所差异
(2)存储能力(capacity):目前支持存储空间的设置( storage=1Gi )
(3)访问模式(accessModes):底层存储类型不同,所支持的访问模式也不同

  • ReadWriteOnce(RWO):读写权限,只能被单个节点挂载
  • ReadOnlyMany(ROX): 只读权限,可以被多个节点挂载
  • ReadWriteMany(RWX):读写权限,可以被多个节点挂载

(4)存储类别

  • 具有特定类别的PV只能与请求了该类别的PVC进行绑定
  • 未设定类别的PV则只能与不请求任何类别的PVC进行绑定
    (5)回收策略(persistentVolumeReclaimPolicy):底层不同的存储类型可能支持的回收策略不同
    当PV不再被使用了之后,对其的处理方式:
  • Retain (保留):保留数据,需要管理员手工清理在这里插入代码片数据
  • Recycle(回收):清除 PV 中的数据,效果相当于执行 rm -rf /data/*
  • Delete (删除):当对应PVC删除后,动态配置的volume将自动删除

PVC的生命周期有如下几个阶段:

  • Available(可用): 表示可用状态,还未被任何 PVC 绑定
  • Bound(已绑定): 表示 PV 已经被 PVC 绑定
  • Released(已释放): 表示 PVC 被删除,但是资源还未被集群重新声明
  • Failed(失败): 表示该 PV 的自动回收失败

创建PVC:
前提准备:nfs我们暴露三个目录出来:

vim /etc/exports
```.

```bash
/home/data/pv1     192.168.242.0/24(rw,async,no_root_squash)
/home/data/pv2     192.168.242.0/24(rw,async,no_root_squash)
/home/data/pv3     192.168.242.0/24(rw,async,no_root_squash)
systemctl restart nfs

创建3个PV:

vim pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv1-dev
spec:
  capacity:
    storage: 1Gi
  accessModes:
  - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  nfs:
    path: /home/data/pv1
    server: 192.168.242.134

---

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv2-dev
spec:
  capacity:
    storage: 2Gi
  accessModes:
  - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  nfs:
    path: /home/data/pv2
    server: 192.168.242.134

---

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv3-dev
spec:
  capacity:
    storage: 3Gi
  accessModes:
  - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  nfs:
    path: /home/data/pv3
    server: 192.168.242.134

Kubernetes之数据存储_第2张图片

2、PVC

资源清单如下:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc
  namespace: dev
spec:
  accessModes:      # 访问模式
  selector:         # 采用标签对PV选择
  storageClassName: # 存储类别
  resources:        # 请求空间
    requests:
      storage: 2Gi

参数说明如下:
(1)访问模式(accessModes)
描述用户应用对存储资源的访问权限
(2)选择条件(selector)
通过对Label Selector的设置,PVC可以对系统中己存在的PV进行筛选
(3)存储类别(storageClassName)
PVC在定义时可以设定需要的后端存储的类别,只有设置了该class的pv才能被系统选出
(4)资源请求(Resources)
描述对存储资源的需求

创建PVC:

vim pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc1-dev
  namespace: dev
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 1Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc2-dev
  namespace: dev
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 1.6Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc3-dev
  namespace: dev
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 2Gi

Kubernetes之数据存储_第3张图片
创建完成PV与PVC后接着创建Pod:

vim pvc-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod1-dev
  namespace: dev
spec:
  containers:
  - name: boot
    image: registry.cn-hangzhou.aliyuncs.com/button_dev/test:v1.4
    ports:
    - containerPort: 8082
    volumeMounts:
    - name: logs-volume
      mountPath: /var/tmp/logs
  volumes:
    - name: logs-volume
      persistentVolumeClaim:
        claimName: pvc1-dev
---
apiVersion: v1
kind: Pod
metadata:
  name: pod2-dev
  namespace: dev
spec:
  containers:
  - name: boot
    image: registry.cn-hangzhou.aliyuncs.com/button_dev/test:v1.4
    ports:
    - containerPort: 8082
    volumeMounts:
    - name: logs-volume
      mountPath: /var/tmp/logs
  volumes:
    - name: logs-volume
      persistentVolumeClaim:
        claimName: pvc2-dev

---
apiVersion: v1
kind: Pod
metadata:
  name: pod3-dev
  namespace: dev
spec:
  containers:
  - name: boot
    image: registry.cn-hangzhou.aliyuncs.com/button_dev/test:v1.4
    ports:
    - containerPort: 8083
    volumeMounts:
    - name: logs-volume
      mountPath: /var/tmp/logs
  volumes:
    - name: logs-volume
      persistentVolumeClaim:
        claimName: pvc3-dev

Kubernetes之数据存储_第4张图片
这时我们去查看nfs中不同存储文件中的内容:
Kubernetes之数据存储_第5张图片

一、配置存储

1、ConfigMap

如果需要存储配置信息,可以使用ConfigMap,它是一种比较特殊的存储卷。

首先定义configmap

vim configmap.yaml

只保存了“loginname”和“password”两项配置

apiVersion: v1
kind: ConfigMap
metadata:
  name: configmap-dev
  namespace: dev
data:
  info: |
    loginname: admin
    password: 123456

创建configmap

kubectl create -f configmap.yaml

在这里插入图片描述
查看其详情:
Kubernetes之数据存储_第6张图片
创建pod

vim configmap-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-configmap
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.17.1
    volumeMounts: # 将configmap挂载到目录
    - name: config
      mountPath: /data/configmap/config
  volumes: # 引用configmap
  - name: config
    configMap:
      name: configmap-dev

创建:

kubectl create -f configmap-pod.yaml

在这里插入图片描述
我们进入到容器中,查看挂载目录中的信息:

kubectl exec -it pod-configmap -n dev /bin/bash

可以发现configmap中配置的key映射成文件,value是文件中内容。
Kubernetes之数据存储_第7张图片

这时我们修改configmap中的内容,并重新创建configmap:
Kubernetes之数据存储_第8张图片
这时再进入pod中查看,内容也修改过来了:
在这里插入图片描述

2、Secret

对于敏感信息,可以使用Secret对象进行存储。
(1)对敏感信息进行base64编码

echo -n 'admin' | base64 
echo -n '987654' | base64 

在这里插入图片描述
(2)创建secret

vim secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: secret-dev
  namespace: dev
type: Opaque  
data:
  username: YWRtaW4=
  password: OTg3NjU0

在这里插入图片描述
(3)创建pod

vim secret-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-secret
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.17.1
    volumeMounts: # 将secret挂载到目录
    - name: config
      mountPath: /data/secret/config
  volumes:
  - name: config
    secret:
      secretName: secret-dev

创建好后进入容器中,查看对应的加密信息,已经被自动解密了:
Kubernetes之数据存储_第9张图片

你可能感兴趣的