kubernetes数据持久化


Pod是由容器组成的,而容器宕机或停止之后,数据就随之丢了,那么这也就意味着我们在做Kubernetes集群的时候就不得不考虑存储的问题,而存储卷就是为了Pod保存数据而生的。存储卷的类型有很多,我们常用到一般有四种:emptyDir,hostPath,NFS以及云存储(ceph, glasterfs…)等。

一、emptyDir

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

apiVersion: apps/v1
kind: Deployment
metadata:
  name: emptydir
spec:
  replicas: 1
  selector:
    matchLabels:
      app: emptydir
  template:
    metadata:
      labels:
        app: emptydir
    spec:
      containers:
        - name: busybox
          image: busybox
          imagePullPolicy: IfNotPresent
          command: ["/bin/sh","-c","while true;do echo $HOSTNAME-`date` >> /tmp/log ;sleep 1;done"]
          volumeMounts:
            - mountPath: /tmp
              name: emptydir
        - name: busybox1
          image: busybox
          imagePullPolicy: IfNotPresent
          command: ["/bin/sh","-c","while true;do echo $HOSTNAME-`date` >> /tmp/log ;sleep 1;done"]
          volumeMounts:
            - mountPath: /tmp
              name: emptydir
      volumes:
        - name: emptydir
          emptyDir: {}


# 应用资源
[root@k8s-master ~]# kubectl apply -f emptydir.yaml

#查看pod运行状态
[root@k8s-master ~]# kubectl get pods

# 进入到容器内部查看
[root@k8s-master ~]# kubectl exec -it emptydir-7ddfb976cc-b9j4x -- sh
/ # tail -f /tmp/log

# 再次进入到另一个容器进行查看(???)
[root@k8s-master ~]# kubectl exec -it emptydir-7ddfb976cc-gh9lk  -- sh
/ # tail -f /tmp/log

总结:

  • 临时数据存储卷,跟Pod一起创建一起删除,里面的数据全部销毁。
  • 非常的轻量级,主要用来存放临时数据或者Pod中容器之间的文件共享。
  • 主要用来创建一个空目录

二、hostPath

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

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hostpath
spec:
  selector:
    matchLabels:
      app: hostpath
  template:
    metadata:
      labels:
        app: hostpath
    spec:
      containers:
        - name: mysql
          image: mysql:5.7
          imagePullPolicy: IfNotPresent
          env:
            - name: MYSQL_ROOT_PASSWORD
              value: "123456"
          volumeMounts:
            - mountPath: /var/lib/mysql # 容器目录
              name: hostpath
      volumes:
        - name: hostpath
          hostPath:
            path: /data # 节点目录,不存在会自动创建,如果存在,则需要保证事先为空

# 应用资源
[root@k8s-master ~]# kubectl apply -f hostpath.yaml 
deployment.apps/hostpath created

# 查看pod被创建到哪个节点
[root@k8s-master ~]# kubeclt get pods -o wide
-bash: kubeclt: command not found
[root@k8s-master ~]# kubectl get pods -o wide
NAME                      READY   STATUS    RESTARTS   AGE   IP             NODE        NOMINATED NODE   READINESS GATES
hostpath-f46c6679-45rqp   1/1     Running   0          23s   10.244.1.145   k8s-node2   <none>           <none


# 可以看到,节点二/data目录上的数据已经存在
[root@k8s-node2 ~]# ls /data/
auto.cnf    ca.pem           client-key.pem  ibdata1      ib_logfile1  mysql               private_key.pem  server-cert.pem  sys
ca-key.pem  client-cert.pem  ib_buffer_pool  ib_logfile0  ibtmp1       performance_schema  public_key.pem   server-key.pem

容器内时间与本地时间同步

让容器内时间与本地时间同步,就可以用到hostpath,例如启动一个pod,运行tomcat,保证时间同步

apiVersion: apps/v1
kind: Deployment
metadata:
  name: tomcat
spec:
  selector:
    matchLabels:
      app: tomcat

  template:
    metadata:
      labels:
        app: tomcat
    spec:
      imagePullSecrets:
        - name: myregistrykey
      containers:
        - name: tomcat
          image: harbor.bertwu.online/beijing/tomcat:latest
          imagePullPolicy: IfNotPresent
          volumeMounts:
            - mountPath: /etc/localtime # 挂在到容器中的时间文件
              name: localtime
      volumes:
        - name: localtime
          hostPath:
            path: /etc/localtime # 本地时间文件
[root@k8s-master ~]# kubectl apply -f tomcat.yaml 

[root@k8s-master ~]# kubectl get pods
NAME                      READY   STATUS    RESTARTS   AGE
tomcat-57bbf9778c-262mz   1/1     Running   0          6s

[root@k8s-master ~]# kubectl exec -it tomcat-57bbf9778c-262mz -- bash
# 查看容器内的时间是否与本地时间一致
root@tomcat-57bbf9778c-262mz:/usr/local/tomcat# date
Sun Jan  2 13:11:58 CST 2022

三、NFS

nfs使得我们可以挂载已经存在的共享到我们的Pod中,和emptyDir不同的是,当Pod被删除时,emptyDir也会被删除。但是nfs不会被删除,仅仅是解除挂在状态而已,这就意味着NFS能够允许我们提前对数据进行处理,而且这些数据可以在Pod之间相互传递,并且nfs可以同时被多个pod挂在并进行读写。
1.搭建nfs服务
在10.0.0.32主机上

yum -y install nfs-utils rpcbind

systemctl enable nfs
systemctl restart nfs

group add www -g 666
useradd www -g www -u 666 -s /sbin/nologin

创建挂在数据目录

mkdir /k8sdata
chown -R www.www /k8sdata

添加授权

[root@nfs ~]# cat /etc/exports
/k8sdata 10.0.0.0/16(rw,sync,no_root_squash,anonuid=666,anongid=666)

systemctl restart nfs
  1. 在所有k8s节点安装nfs-utils
yum install nfs-utils rpcbind -y

创建pod使用nfs

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nfs
spec:
  selector:
    matchLabels:
      app: nfs
  template:
    metadata:
      labels:
        app: nfs
    spec:
      containers:
        - name: mysql
          image: mysql:5.7
          imagePullPolicy: IfNotPresent
          env:
            - name: MYSQL_ROOT_PASSWORD
              value: "123456"
          volumeMounts:
            - mountPath: /var/lib/mysql # 容器内需要持久化的目录
              name: nfs
      volumes:
        - name: nfs
          nfs:
            path: /k8sdata # nfs服务段共享目录
            server: 10.0.0.32 # nfs服务端地址
# 应用资源
[root@k8s-master ~]# kubectl apply -f nfs.yaml 
deployment.apps/nfs created

# 查看资源
[root@k8s-master ~]# kubectl get pods
NAME                      READY   STATUS    RESTARTS   AGE
nfs-9cf648dcf-k4kdd       1/1     Running   0          4s
#在nfs服务端查看是否同步数据成功

[root@nfs ~]# ls /k8sdata/
auto.cnf    ca.pem           client-key.pem  ibdata1      ib_logfile1  performance_schema  public_key.pem   server-key.pem
ca-key.pem  client-cert.pem  ib_buffer_pool  ib_logfile0  mysql        private_key.pem     server-cert.pem  sys

四、PV与PVC

PersistentVolume(PV)是集群中已由管理员配置的一段网络存储。 集群中的资源就像一个节点是一个集群资源。 PV是诸如卷之类的卷插件,但是具有独立于使用PV的任何单个pod的生命周期。 该API对象捕获存储的实现细节,即NFS,iSCSI或云提供商特定的存储系统。

PersistentVolumeClaim(PVC)是用户存储的请求。PVC的使用逻辑:在pod中定义一个存储卷(该存储卷类型为PVC),定义的时候直接指定大小,pvc必须与对应的pv建立关系,pvc会根据定义去pv申请,而pv是由存储空间创建出来的。pv和pvc是kubernetes抽象出来的一种存储资源。

4.1 pv的访问模式(accessModes)

模式解释
ReadWriteOnce(RWO)可读可写,但只支持被单个节点挂载 (如果底层存储如果允许它还是可以挂载多个节点的)。
ReadOnlyMany(ROX)只读,可以被多个节点挂载 (如果底层存储如果允许它写还是可以写的)。
ReadWriteMany(RWX)多路可读可写。这种存储可以以读写的方式被多个节点共享。不是每一种存储都支持这三种方式,像共享方式,目前支持的还比较少,比较常用的是 NFS。在 PVC 绑定 PV 时通常根据两个条件来绑定,一个是存储的大小,另一个就是访问模式。

#注:ceph支持ReadWriteOnce、ReadWriteMany , nfs上面三种都支持

4.2 pv的回收策略(persistentVolumeReclaimPolicy)

策略解释
Retain不清理, 保留 Volume(需要手动清理)。解绑之后,不做任何操作
Recycle删除数据,即 rm -rf /thevolume/*(只有 NFS 和 HostPath 支持)。解绑之后立即释放绑定状态 (已经淘汰)
Delete删除存储资源,比如删除 AWS EBS 卷(只有 AWS EBS, GCE PD, Azure Disk 和 Cinder 支持)。解绑之后,会删除所有的数据 ,同时会删除存储卷

4.3 pv的状态

状态解释
Available可用。
Bound已经分配给 PVC。
ReleasedPVC 解绑但还未执行回收策略。
Failed发生错误。

创建三个pv

[root@k8s-master ~]# cat pv.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-v1
spec:
  nfs:
    path: /nfs/v1 # nfs服务端共享目录
    server: 10.0.0.32 # nfs服务地址
  accessModes:
    - "ReadWriteMany" # 访问模式 多路可读写
  persistentVolumeReclaimPolicy: Retain # 回收策略,保持
  capacity:
    storage: 2Gi

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-v2
spec:
  nfs:
    path: /nfs/v2
    server: 10.0.0.32
  accessModes:
    - "ReadOnlyMany" # 访问模式 只读
  persistentVolumeReclaimPolicy: Retain
  capacity:
    storage: 2Gi


---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-v3
spec:
  nfs:
    path: /nfs/v3
    server: 10.0.0.32
  accessModes:
    - "ReadWriteOnce" # 可读写,但只支持被单个节点挂载
  persistentVolumeReclaimPolicy: Retain
  capacity:
    storage: 2Gi


# 应用资源
[root@k8s-master ~]# kubectl apply -f pv.yaml 
persistentvolume/nfs-v1 unchanged
persistentvolume/nfs-v2 unchanged
persistentvolume/nfs-v3 created

# 查看pv的状态
[root@k8s-master ~]# kubectl get pv
NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
nfs-v1   2Gi        RWX            Retain           Available                                   56s
nfs-v2   2Gi        ROX            Retain           Available                                   56s
nfs-v3   2Gi        RWO            Retain           Available                                   9s

2.创建pvc

[root@k8s-master ~]# cat pvc.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-v1 # pvc名字
spec:
  accessModes:  # 指定pvc访问策略
    - "ReadWriteMany"
  resources:
    requests:
      storage: 2Gi #pvc大小不能超过pv

pvc会自动匹配合适的pv

[root@k8s-master ~]# kubectl get pvc 
NAME     STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
nfs-v1   Bound    nfs-v1   2Gi        RWX                           7s
[root@k8s-master ~]# 
[root@k8s-master ~]# kubectl get pv
NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM            STORAGECLASS   REASON   AGE
nfs-v1   2Gi        RWX            Retain           Bound       default/nfs-v1                           17m
nfs-v2   2Gi        ROX            Retain           Available                                            17m
nfs-v3   2Gi        RWO            Retain           Available                                            16m

配置清单应用pvc

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nfs-v1
spec:
  selector:
    matchLabels:
      app: nfs-v1
  template:
    metadata:
      labels:
        app: nfs-v1
    spec:
      containers:
        - name: nginx
          image: nginx
          imagePullPolicy: IfNotPresent
          volumeMounts:
            - mountPath: /usr/share/nginx/html
              name: nfs-v1

      volumes:
        - name: nfs-v1
          persistentVolumeClaim:
            claimName: nfs-v1 # 指定用哪个pvc

# 应用资源
[root@k8s-master ~]# kubectl apply -f pvc-deployment.yaml 
[root@k8s-master ~]# kubectl get pods
NAME                      READY   STATUS    RESTARTS   AGE
nfs-v1-6479df84bc-9dzdd   1/1     Running   0          4s

# 进入pod
[root@k8s-master ~]# kubectl exec -it nfs-v1-6479df84bc-9dzdd -- bash
root@nfs-v1-6479df84bc-9dzdd:/# cd /usr/share/nginx/html/
root@nfs-v1-6479df84bc-9dzdd:/usr/share/nginx/html# ls

# 创建文件
root@nfs-v1-6479df84bc-9dzdd:/usr/share/nginx/html# touch 1.txt
root@nfs-v1-6479df84bc-9dzdd:/usr/share/nginx/html# ls
1.txt


# 查看nfs服务端对应目录文件是否存在
[root@nfs nfs]# ll /nfs/v1/
total 0
-rw-r--r-- 1 root root 0 Jan  2 16:47 1.txt

还可以创建pvc2,pvc3依次是实验

# pvc2
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-v2
spec:
  accessModes:
    - "ReadOnlyMany"
  resources:
    requests:
      storage: 2Gi
---

# pvc3
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-v3
spec:
  accessModes:
    - "ReadWriteOnce"
  resources:
    requests:
      storage: 2Gi

结论: 访问策略只是一种约定,其实还是可以读写,由底层存储决定

总结:
1.EmptyDir就是Host上的一个空目录,临时存放文件,同一个pod之间容器间共享目录
作为容器之间共享存储。一旦pod销毁结束,它也就结束了,数据不会保存下来

2.HostPath就是将Node主机中一个实际目录挂载到Pod中,以供容器使用。这样的设计就可以保证Pod销毁了,但是数据依据可以存在Node主机上,实现文件的持久化存储。
DirectoryOrCreate # 目录存在就使用,不存在就先创建后使用

3.Pv就是底层存储对外统一的接口,系统管理员提前准备好的一些空间
PVC 就是用户给的申请,比如说用户需要多大的硬盘空间

五、StorageClass

在一个大规模的Kubernetes集群里,可能有成千上万个PVC,这就意味着运维人员必须实现创建出这个多个PV,此外,随着项目的需要,会有新的PVC不断被提交,那么运维人员就需要不断的添加新的,满足要求的PV,否则新的Pod就会因为PVC绑定不到PV而导致创建失败。而且通过 PVC 请求到一定的存储空间也很有可能不足以满足应用对于存储设备的各种需求,而且不同的应用程序对于存储性能的要求可能也不尽相同,比如读写速度、并发性能等,为了解决这一问题,Kubernetes 又为我们引入了一个新的资源对象:StorageClass,通过 StorageClass 的定义,管理员可以将存储资源定义为某种类型的资源,比如快速存储、慢速存储等,kubernetes根据 StorageClass 的描述就可以非常直观的知道各种存储资源的具体特性了,这样就可以根据应用的特性去申请合适的存储资源了。

StorageClass首先提供了自动创建存储资源的功能,它可以根据PVC自动为我们创建PV。所以只需要编写pod和pvc资源清单验证时即可。

每一个存储类都包含provisioner、parameters和reclaimPolicy这三个参数域,当一个属于某个类的PersistentVolume需要被动态提供时,将会使用上述的参数域。

官方网站: https://helm.sh/
# 下载helm
wget https://get.helm.sh/helm-v3.3.4-linux-amd64.tar.gz

# 解压
tar xf helm-v3.3.4-linux-amd64.tar.gz
# 安装
mv linux-amd64/helm /usr/local/bin/

# 验证
helm version

添加仓库

 helm repo add moikot https://moikot.github.io/helm-charts
 helm repo add ckotzbauer https://ckotzbauer.github.io/helm-
 helm repo add kaiyuanshe http://mirror.kaiyuanshe.cn/kubernetes/charts/

# 查看仓库是否添加成功
[root@k8s-master linux-amd64]# helm repo list
NAME      	URL                                           
moikot    	https://moikot.github.io/helm-charts          
ckotzbauer	https://ckotzbauer.github.io/helm-charts      
kaiyuanshe	http://mirror.kaiyuanshe.cn/kubernetes/charts/

# 搜索nfs-client
root@k8s-master linux-amd64]# helm search repo  nfs-client
NAME                             	CHART VERSION	APP VERSION	DESCRIPTION                                       
ckotzbauer/nfs-client-provisioner	2.0.0        	3.1.0      	DEPRECATED - nfs-client is an automatic provisi...
kaiyuanshe/nfs-client-provisioner	1.2.11       	3.1.0      	DEPRECATED - nfs-client is an automatic provisi...
moikot/nfs-client-provisioner    	1.3.0        	3.1.0      	nfs-client is an automatic provisioner that us

# 拉取镜像
root@k8s-master nfs-client]# helm pull kaiyuanshe/nfs-client-provisioner


 # 查看
[root@k8s-master nfs-client]# ls
nfs-client-provisioner  nfs-client-provisioner-1.2.11.tgz

# 解压
[root@k8s-master nfs-client]# tar xf nfs-client-provisioner-1.2.11.tgz 

[root@k8s-master nfs-client]# cd nfs-client-provisioner/
[root@k8s-master nfs-client-provisioner]# ls
Chart.yaml  ci  README.md  templates  values.yaml

# 修改
[root@k8s-master nfs-client-provisioner]# vim values.yaml 
nfs:
  server: 10.0.0.32	# nfs服务端ip
  path: /nfs/v1		# nfs服务端已配好的挂载目录
  
   accessModes: ReadWriteMany	# 改成多路可读可写(访问策略)

# 安装
[root@k8s-master nfs-client-provisioner]# helm install nfs ./
NAME: nfs
LAST DEPLOYED: Sun Jan  2 21:28:01 2022
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None

[root@k8s-master nfs-client-provisioner]# helm list
NAME	NAMESPACE	REVISION	UPDATED                                	STATUS  	CHART                        	APP VERSION
nfs 	default  	1       	2022-01-02 21:28:01.578229377 +0800 CST	deployed	nfs-client-provisioner-1.2.11	3.1.0      
[root@k8s-master nfs-client-provisioner]# 

# 查看pod启动情况
[root@k8s-master nfs-client-provisioner]# kubectl get pods -o wide
NAME                                          READY   STATUS    RESTARTS   AGE   IP             NODE        NOMINATED NODE   READINESS GATES
nfs-nfs-client-provisioner-595777dd9d-xlz4s   1/1     Running   0          14m   10.244.1.152   k8s-node2   <none>           <none>


# 查看storageclass是否启动
[root@k8s-master ~]# kubectl get sc
NAME         PROVISIONER                                RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
nfs-client   cluster.local/nfs-nfs-client-provisioner   Delete          Immediate           true                   15m

测试StorageClass存储类

# 编写pvc资源清单
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: test-sc
spec:
  storageClassName: nfs-client		# storageclass名
  accessModes:	# 访问模式/策略
    - "ReadWriteMany"	# 多路读写
  resources: # 资源
    requests: # 请求
      storage: 2Gi	# 存储大小,只是显示,不会实际限制文件存储大小,只要硬盘装得下
---
# 创建密码secret清单
kind: Secret
apiVersion: v1
metadata:
  name: test
data:
  MYSQL_ROOT_PASSWORD: MTIzNDU2   # 这里指定加密过后的密码
---
# 编写pod资源清单
kind: Deployment
apiVersion: apps/v1
metadata:
  name: mysql
spec:
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - name: mysql
          image: mysql:5.7
          imagePullPolicy: IfNotPresent
          envFrom:                  # 指定环境变量
            - secretRef:           # 将secret当中的某一项定义成内部的环境变量
                name: test          # secret的名称
                optional: true      # 指定是否必须定义

          volumeMounts:
            - mountPath: /var/lib/mysql
              name: nfs
      volumes:
        - name: nfs
          persistentVolumeClaim:	# 挂在方式pvc类型
            claimName: test-sc
#查看自动创建的pv
[root@k8s-master ~]# kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM             STORAGECLASS   REASON   AGE
pvc-c7a49ab0-4337-42d9-8a4b-07894ed03bcc   2Gi        RWX            Delete           Bound    default/test-sc   nfs-client              8s

# 查看手动创建的pvc
[root@k8s-master ~]# kubectl get pvc
NAME      STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
test-sc   Bound    pvc-c7a49ab0-4337-42d9-8a4b-07894ed03bcc   2Gi        RWX            nfs-client     47s

# 查看nfs服务端
[root@nfs k8sdata]# ls
default-test-sc-pvc-c7a49ab0-4337-42d9-8a4b-07894ed03bcc


[root@nfs k8sdata]# cd default-test-sc-pvc-c7a49ab0-4337-42d9-8a4b-07894ed03bcc/

#mysql的数据已经挂载到了服务端
[root@nfs default-test-sc-pvc-c7a49ab0-4337-42d9-8a4b-07894ed03bcc]# ls
auto.cnf    ca.pem           client-key.pem  ibdata1      ib_logfile1  mysql               private_key.pem  server-cert.pem  sys
ca-key.pem  client-cert.pem  ib_buffer_pool  ib_logfile0  ibtmp1       performance_schema  public_key.pem   server-key.pem

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值