K8s数据持久化

红米1年前技术文章385

一、为什么需要持久化

为了解决pod里面的容器被删除后数据不丢失,则引入了存储类型,类似于docker中的数据卷。

在kubernetes集群中,其是支持多种存储类型,包括但不限于emptyDir,HostPath,NFS等。

二、数据卷概述

1、为什么需要数据卷

容器部署过程中一般有以下三种数据:

(1)启动时需要的初始数据,例如配置文件;

(2)启动过程中产生的临时数据,该临时数据需要多个容器间共享,例如类似于Redis的数据库;

(3)启动容器过程中产生的持久化数据,例如MySQL的数据目录(datadir);

如下图所示,我们可以基于数据卷的方式实现数据的共享。

持久卷01_d3XH-oLsFS.png

2、数据卷的分类

数据卷:

    (1)kubernetes中的Volume提供了在容器中挂载外部存储的能力;

    (2)Pod需要设置卷来源(po.spec.volumes)和挂载点(po.spec.containers.volumeMounts)两个信息后才可以使用相应的volume;

按类型分类:

    本地数据卷: hostPath,emptyDir等

    网络数据卷: NFS,Ceph,GlusterFS等

    公有云: AWS,EBS等

    K8S资源: configmap,secret等

三、emptyDir存储类型

1、emptyDir概述

emptyDir数据卷是一个临时存储卷,与Pod生命周期绑定在一起,如果Pod删除了,这意味着数据卷也会被删除。

作用:

(1)可以实现持久化的功能;

(2)多个Pod之间不能通信数据,但是同一个Pod的多个容器是可以实现数据共享的;

(3)随着Pod的生命周期而存在,当我们删除Pod时,其数据也会被随之删除。

应用场景(同一个Pod中各个容器之间数据的共享):

(1)缓存空间,例如基于磁盘的归并排序;

(2)为耗时较长的计算任务提供检查点,以便任务能方便地从崩溃前状态恢复执行;

(3)存储Web服务器的访问日志及错误日志等信息;

📌温馨提示:使用emptyDir持久化数据时,删除容器并不会删除数据,因为容器删除并不能说明Pod被删除哟。

2、创建Pod并使用emptyDir案例

#创建一个命名空间和pod
[root@172-16-121-211 ~]# cat 01-volumes-emptydir-demo.yml
apiVersion: v1
kind: Namespace
metadata:
 name: emptydir-volume

---

apiVersion: v1
kind: Pod
metadata:
 name: hongmi-pod-emptydir
 namespace: emptydir-volume
spec:
 # 定义数据卷的来源
 volumes:
 - name: data
   emptyDir: {}
 # 我们无需为emptyDir指定任何参数,通常写个"{}"即可,表示创建的是一个空目录。
 - name: log
   emptyDir: {}

 containers:
 # 创建一个负责写入数据的容器
 - name: linux-producer
   image: alpine:latest
   # 启动容器后执行的命令,模拟生产数据即可
   command: ["sh","-c","for i in `seq 1000`;do echo $i >> /mydata/topic;sleep 1;done"]
   # 挂载数据卷
   volumeMounts:
     - name: data  # 注意哈,该名称必须在上面的"volumes"的name字段中存在哟~
       mountPath: /mydata  # 指定挂载到容器的位置

 # 创建一个负责读取数据的容器
 - name: linux-consumer
   image: alpine:latest
   # 启动容器后执行的命令,模拟消费数据即可
   command: ["sh","-c","tail -f /mydata2021/topic"]
   # 挂载数据卷
   volumeMounts:
     - name: data  # 注意哈,该名称必须在上面的"volumes"的name字段中存在哟~
       mountPath: /mydata2021

 - name: hongmi-linux
   image: alpine:latest
   command: ["sh","-c","tail -f /etc/hosts"]
   volumeMounts:
     - name: log
       mountPath: /hongmi

[root@172-16-121-211 ~]# kubectl  apply  -f 01-volumes-emptydir-demo.yml
[root@172-16-121-211 ~]# kubectl get pods -n emptydir-volume   -o wide
NAME                  READY   STATUS    RESTARTS   AGE     IP           NODE            NOMINATED NODE   READINESS GATES
hongmi-pod-emptydir   3/3     Running   0          3m17s   10.244.1.5   172-16-121-88   <none>           <none>

查看数据存储情况:

image_eIh2Jp6zev.png

📌 注意:删除Pod则持久化到本地的数据同时将被删除

四、HostPath存储类型

1、概述:

可以解决同一个Node节点的多个Pod数据共享哟,但多个Pod不在同一个Node节点时则无法通过HostPath来查找数据

2、hostPath数据卷:

挂载Node文件系统(Pod所在节点)上文件或者目录到Pod中的容器。

如果Pod删除了,宿主机的数据并不会被删除,这一点是否感觉和咱们的数据卷有异曲同工之妙呢?

3、应用场景:

Pod中容器需要访问宿主机文件。

[root@172-16-121-211 hostpath]# ls
00-wordpress-namespace.yaml  01-wordpress-mysql.yaml  02-wordpress-mysql-svc.yml  03-wordpress-web.yaml  04-wordpress-svc.yml
[root@172-16-121-211 hostpath]# pwd
/root/hostpath
[root@172-16-121-211 hostpath]#
[root@172-16-121-211 hostpath]# ls
00-wordpress-namespace.yaml  01-wordpress-mysql.yaml  02-wordpress-mysql-svc.yml  03-wordpress-web.yaml  04-wordpress-svc.yml
[root@172-16-121-211 hostpath]# free -h
             total        used        free      shared  buff/cache   available
Mem:           3.7G        1.1G        148M        162M        2.4G        2.2G
Swap:            0B          0B          0B
[root@172-16-121-211 hostpath]#
[root@172-16-121-211 hostpath]#
[root@172-16-121-211 hostpath]# LS
-bash: LS: command not found
[root@172-16-121-211 hostpath]#
[root@172-16-121-211 hostpath]# ls
00-wordpress-namespace.yaml  01-wordpress-mysql.yaml  02-wordpress-mysql-svc.yml  03-wordpress-web.yaml  04-wordpress-svc.yml
[root@172-16-121-211 hostpath]# cat *
00-wordpress-namespace.yaml

apiVersion: v1
kind: Namespace
metadata:
 name: hongmi-wordpress
 
01-wordpress-mysql.yaml  
apiVersion: apps/v1
kind: Deployment
metadata:
 name: hongmi-wordpress-mysql
 namespace: hongmi-wordpress
spec:
 replicas: 1
 selector:
   matchLabels:
     app: hongmi-wordpress-mysql
 template:
   metadata:
     labels:
       app: hongmi-wordpress-mysql
   spec:
     containers:
     - name: mysql
       image: mysql:5.7
       ports:
       - containerPort: 3306
       env:
       - name: MYSQL_ROOT_PASSWORD
         value: somewordpress
       - name: MYSQL_DATABASE
         value: wordpress
       - name: MYSQL_USER
         value: wordpress
       - name: MYSQL_PASSWORD
         value: wordpress
         
#02-wordpress-mysql-svc.yml
apiVersion: v1
kind: Service
metadata:
 name: hongmi-mysql
 namespace: hongmi-wordpress
spec:
 ports:
   - port: 3306
     targetPort: 3306
 selector:
   app: hongmi-wordpress-mysql
   
#03-wordpress-web.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
 name: wordpress
 namespace: hongmi-wordpress
spec:
 replicas: 1
 selector:
   matchLabels:
     app: wordpress
 template:
   metadata:
     labels:
       app: wordpress
   spec:
     volumes:
       - name: wordpress-code
         hostPath:
           path: /data/wordpress-code
     #nodeName: k8s102.oldboyedu.com
     containers:
     - name: wordpress
       image: wordpress:latest
       ports:
       - containerPort: 80
       volumeMounts:
         - mountPath: /var/www/html
           name: wordpress-code
       env:
       - name: WORDPRESS_DB_HOST
         value: hongmi-mysql  # 注意哈,这里我写的是暴露MySQL服务的service名称哟~
       - name: WORDPRESS_DB_USER
         value: wordpress
       - name: WORDPRESS_DB_PASSWORD
         value: wordpress

#04-wordpress-svc.yml        
apiVersion: v1
kind: Service
metadata:
 name: wordpress
 namespace: hongmi-wordpress
spec:
 type: NodePort
 ports:
   - port: 80
     nodePort: 32020
     targetPort: 80
 selector:
   app: wordpress

五、NFS存储类型

1、概述

适合不同的node节点的Pod共享存储,但存在单点故障

NFS数据卷:提供对NFS挂载支持,可以自动将NFS共享路径挂载到Pod中。

NFS:英文全称为"Network File System"(网络文件系统),是由SUN公司研制的UNIX表示层协议(presentation layer protocol),能使使用者访问网络上别处的文件就像在使用自己的计算机一样。

NFS是一个主流的文件共享服务器,但存在单点故障,我们需要对数据进行备份,如果有必要可以使用分布式文件系统哈。

2、安装NFS环境并测试

(1)在所有节点上都安装"nfs-utils"软件包,安装该软件包不仅仅会包含NFS服务端软件,还会包含其客户端软件
yum -y install nfs-utils

(2)将"master"设置为NFS服务端,配置共享"/data/kubernetes"目录
# vim /etc/exports
#cat /etc/exports
/backup/kubernetes  *(rw,no_root_squash)

# mkdir -pv /backup/kubernetes
# ll /backup/kubernetes
总用量 0

# systemctl start nfs  && systemctl enable nfs  #启动nfs
Created symlink from /etc/systemd/system/multi-user.target.wants/nfs-server.service to /usr/lib/systemd/system/nfs-server.service.

# exportfs   # 查看NFS的挂载信息
/backup/kubernetes
   <world>

# touch /backup/kubernetes/nfs.log  # 创建测试文件,便于客户端挂载测试验证
(3)客户端验证NFS的可用性
mount -t nfs master:/backup/kubernetes  /mnt/  # 手动挂载NFS的服务端进行测试

(4)手动卸载NFS
# umount /mnt  # 手动卸载NFS

(5)所有节点
systemctl start nfs && systemctl enable nfs
showmount -e 172.16.104.15

📌温馨提示: 建议在Kubernetes的每个工作节点都安装nfs-utils软件包,如果只在NFS服务端安装,客户端未安装的话,可能客户端在使用mount命令手动挂在时会挂在不上哟~  

3、测试案例


[root@k8s101.oldboyedu.com ~]# cat 03-volumes-nfs-demo.yaml
apiVersion: v1
kind: Namespace
metadata:
 name: hongmi-volume

---

apiVersion: apps/v1  
kind: Deployment
metadata:
 name: mynginx-deploy
 namespace: hongmi-volume
spec:
 selector:
   matchLabels:
     app: nginx-nfs
 replicas: 3
 template:
   metadata:
     labels:
       app: nginx-nfs
   spec:
     # 配置NFS的数据源
     volumes:
     - name: hongmi-nfs
       nfs:
         server: master    #指定NFS的服务器的地址,如果指定主机名请确保可以正常进行解析哟~
         path: /data/kubernetes  #指定NFS的挂载路径
     containers:
     - name: my-nginx
       image: nginx:1.18
       # 在容器中挂载数据卷
       volumeMounts:
       - name: hongmi-nfs
         mountPath: /usr/share/nginx/html
       ports:
       - containerPort: 80
[root@172-16-104-15 ~]# kubectl apply -f 03-volumes-nfs-demo.yaml
namespace "hongmi-volume" created
deployment "mynginx-deploy" created
[root@172-16-104-15 ~]# kubectl get pods -n hongmi-volume
NAME                              READY     STATUS    RESTARTS   AGE
mynginx-deploy-1210620599-0tqll   1/1       Running   0          6s
mynginx-deploy-1210620599-kp0p8   1/1       Running   0          6s
mynginx-deploy-1210620599-rb8z5   1/1       Running   0          6s

六、PV和PVC的基本使用

1、概述

什么是pv:

全称为:"persistent volume",属于k8s集群的全局资源,因此并不支持名称空间(namespace)。

该资源对象本身并不负责数据的真实存储,而是负责和后端存储进行关联,每个pv都有提前定义好的存储能力。

持久卷是对存储资源数据卷(volume)创建和使用的抽象,使得存储作为集群中的资源管理。

这样我们就可以对数据卷的使用空间,读写权限做一个基本的权限管控,而不是放任Pod使用所有的数据卷资源。

pv的作用:  

PV解决了企业对于存储的依赖问题,比如A公司使用的是nfs作为存储,而B公司使用的是cephfs作为存储,对于运维人员而言可能需要手动维护不同的组件,而一旦使用pv对存储资源进行抽象后,在迁移服务时就无需关心集群底层存储使用的资源,而是直接使用pv即可。

简而言之,就是实现了以下三大特性:

1、后端存储的权限管控(rw,ro);

2、存储能力(比如使用多大的存储空间);

3、后端存储卷(volumes)存储类型的应用解耦。

什么是PVC: 全称为:"persistent volume  claim",   属于k8s集群某一个namespace的局部资源。该资源对象本身并不负责数据的真实存储,而是显式声明需要使用的存储资源需求。

PVC的作用:

让用户不需要关心具体的Volume实现细节。pvc的一个最重要的作用就是去关联符合条件的pv,从而实现对存储资源的使用。

推荐阅读: https://kubernetes.io/docs/concepts/storage/persistent-volumes/

温馨提示:

(1)全局资源指的是所有的namespace都能看到该资源,很明显是全局唯一的。

(2)局部资源指的是该资源只属于某个namespace哟。

(3)PVPVC均属于k8s资源,而k8s的所有资源通常都支持打标签的哟。

2、创建PV资源

(1)创建pv的存储目录,注意该目录是NFS的挂载目录哟~
mkdir -pv /data/kubernetes/pv0{1,2,3}

(2)编写pv的资源清单
# cd /oldboyedu/persistentVolume
# cat 01-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
 name: pv01
 labels:
   type: ssd
spec:
 capacity:  # 定义PV存储容量的大小
   storage: 10Gi
 accessModes:  # 指定访问模式
   - ReadWriteMany
 persistentVolumeReclaimPolicy: Recycle  # 指定PV的回收策略
 nfs:  # 指定PV后端的支持存储设备类型
   path: "/data/kubernetes/pv01"
   server: 172.200.1.101 #改为nfs的服务器ip
   readOnly: false

# cat 02-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
 name: pv02
 labels:
   type: ssd
spec:
 capacity:  # 定义PV存储容量的大小
   storage: 30Gi
 accessModes:  # 指定访问模式
   - ReadWriteMany
 persistentVolumeReclaimPolicy: Recycle  # 指定PV的回收策略
 nfs:  # 指定PV后端的支持存储设备类型
   path: "/data/kubernetes/pv02"
   server: 172.200.1.101。#改为nfs的服务器ip
   readOnly: false

# cat 03-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
 name: pv03
 labels:
   type: ssd
spec:
 capacity:  # 定义PV存储容量的大小
   storage: 50Gi
 accessModes:  # 指定访问模式
   - ReadWriteMany
 persistentVolumeReclaimPolicy: Recycle  # 指定PV的回收策略
 nfs:  # 指定PV后端的支持存储设备类型
   path: "/data/kubernetes/pv03"
   server: 172.200.1.101 #改为nfs的服务端ip
   readOnly: false

(3)创建pv资源
# kubectl apply -f .
persistentvolume "pv01" created
persistentvolume "pv02" created
persistentvolume "pv03" created

常用的字段如下:

NAME: 有关PV资源的名称。

CAPACITY:   该PV资源的容量大小。

ACCESSMODES(访问模式):   是用来对PV进行访问模式的设置,用于描述用户应用对存储资源的访问权限,访问权限包括以下几种方式:

ReadWriteOnce(RWO): 读写权限,但是只能被单个节点挂载。

ReadOnlyMany(ROX): 只读权限,可以被多个节点挂载。

ReadWriteMany(RWX): 读写权限,可以被多个节点挂载。

ReadWriteOncePod: 卷可以由单个Pod以读写方式挂载。这仅支持CSI卷和Kubernetes 1.22+版

RECLAIMPOLICY(回收策略):  

目前新版本中PV支持的策略有三种:

Retain(保留): 保留数据,需要管理员手工清理数据,这是默认策略哟。

Recycle(回收): 清除PV中的数据,效果相当于执行"rm -rf /data/kubernetes/ *"。

Delete(删除): 与PV相连的后端存储同时删除。

STATUS(状态):     一个PV的生命周期中,可能会处于四种不同的阶段:

Available(可用): 表示可用状态,还未被任何PVC绑定。

Bound(已绑定): 表示PV已经被PVC绑定。

Released(已释放): PVC被删除,但是资源还未被集群重新声明。

Failed(失败): 表示该PV的自动回收失败。

CLAIM: 被那个pvc声明使用

3、创建PVC

(1)创建namespace,以便于将PVC放入该名称空间
# cat ns-hongmi-tomcat.yaml
apiVersion: v1
kind: Namespace
metadata:
 name: hongmi-tomcat

# kubectl apply -f ns-hongmi-tomcat.yaml

(2)创建PVC
# cat 01-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
 name: tomcat-mysql-pvc
 namespace: hongmi-tomcat
spec:
 accessModes:
   - ReadWriteMany
 resources:
   requests:
     storage: 35Gi

温馨提示:

(1)当我们创建的PVC申请的存储大小要小于PV现有存储大小时,K8S会自动评估PVC和与哪一个后端PV进行绑定(Bound),如果PVC找不到合适的PV则pvc始终会停留在"Pending"状态

(2)如下图所示,本案例PVC仅申请了35G内存,但实际上PVC会自动去关联全局资源,匹配最合适的PV,这个过程是由K8s集群自动实现的,无需运维人员手动绑定,绑定成功请注意观察PV和PVC的状态均为"Bound"。

(3)如下图所示,如果将PVC申请的数量过大(本案例是32GB),就会导致PVC无法自动关联全局PV资源,因此PVC的状态始终为"Pending",因为此时并没有一个PV的存储能力能够满足该PVC

4、PV和PVC生命周期

PV是群集中的资源。PVC是对这些资源的请求,并且还充当对资源的检查。

PV和PVC之间的相互作用遵循以下生命周期:

Provisioning ——-> Binding ——–>Using——>Releasing——>Recycling

  • 供应准备—Provisioning---通过集群外的存储系统或者云平台来提供存储持久化支持。

    • - 静态提供Static:集群管理员创建多个PV。 它们携带可供集群用户使用的真实存储的详细信息。 它们存在于Kubernetes API中,可用于消费

    • - 动态提供Dynamic:当管理员创建的静态PV都不匹配用户的PersistentVolumeClaim时,集群可能会尝试为PVC动态配置卷。 此配置基于StorageClasses:PVC必须请求一个类,并且管理员必须已创建并配置该类才能进行动态配置。 要求该类的声明有效地为自己禁用动态配置。

  • 绑定—Binding---用户创建pvc并指定需要的资源和访问模式。在找到可用pv之前,pvc会保持未绑定状态。

  • 使用—Using---用户可在pod中像volume一样使用pvc。

  • 释放—Releasing---用户删除pvc来回收存储资源,pv将变成“released”状态。由于还保留着之前的数据,这些数据需要根据不同的策略来处理,否则这些存储资源无法被其他pvc使用。

  • 回收—Recycling---pv可以设置三种回收策略:保留(Retain),回收(Recycle)和删除(Delete)。

    • - 保留策略:允许人工处理保留的数据。

    • - 删除策略:将删除pv和外部关联的存储资源,需要插件支持。

    • - 回收策略:将执行清除操作,之后可以被新的pvc使用,需要插件支持

5、新建一个mysql实例进行测试

[root@172-16-121-211 ~]# cat mysql-deploy.yml 
apiVersion: apps/v1
kind: Deployment
metadata:
 name: mysql
 namespace: hongmi-tomcat
spec:
 replicas: 1
 selector:
   matchLabels:
     app: hongmi-mysql
 template:
   metadata:
     labels:
       app: hongmi-mysql
   spec:
     volumes:
       - name: datadir
         persistentVolumeClaim:
           claimName: tomcat-mysql-pvc  # 指定PVC的名称,注意要创建的Pod的名称空间中必须存在该PVC哟~
           readOnly: false  # PVC是否只读,默认值就为false,如果想要只读请设置为"true"
       - name: logbin  # 我们可以定义多个存储卷,但下面若不挂载,则始终不会应用它哟!
         emptyDir: {}

     containers:
       - name: mysql
         image: mysql:5.7
         ports:
           - containerPort: 3306
         env:
           - name: MYSQL_ROOT_PASSWORD
             value: '123456'
         volumeMounts:
           - name: datadir
             mountPath: /var/lib/mysql

结果展示

6、标签选择器

(1)创建一个pv04,标签为hdd
[root@172-16-121-211 ~]# cat 04-pv.yml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv04
  labels:
    type: hdd
spec:
  capacity:  # 定义PV存储容量的大小
    storage: 50Gi 
  accessModes:  # 指定访问模式
    - ReadWriteMany 
  persistentVolumeReclaimPolicy: Recycle  # 指定PV的回收策略
  nfs:  # 指定PV后端的支持存储设备类型
    path: "/backup/kubernetes/pv04"
    server: 172.16.104.15
    readOnly: false

(2)创建一个pvc,标签选择器为hdd
[root@172-16-121-211 ~]# cat 04-pvc.yml  
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: tomcat-mysql-pvc2
  namespace: hongmi-tomcat
spec:
  selector:
    matchLabels:
      type: hdd
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 25Gi

结果展示:

image_H_s1YJNlb5.png

返回列表

上一篇:pg_restore

下一篇:pg_probackup

相关文章

RDS通过DMS管理登录处理

RDS通过DMS管理登录处理

问题描述无法通过DMS管理登录进入数据库,报错如下:问题处理方式一在RDS控制台新建账号 账号管理--创建账号将此数据库添加进DMS在DMS控制台--数据库实例--新增实例将新建的数据库账号信息进行录...

MySQL运维实战(4.6) SQL_MODE之NO_BACKSLASH_ESCAPES

设置NO_BACKSLASH_ESCAPES后,反斜杠(\)不作为转义符。不设置NO_BACKSLASH_ESCAPES时,反斜杠(\)用来转义后一个字符mysql> create&n...

压测实操--TestDFSIO压测hdfs读写方案

压测实操--TestDFSIO压测hdfs读写方案

TestDFSIO主要是对hdfs的I/O性能进行测试,通过使用MapReduce作业来完成测试,作为并行读写文件进行I/O性能测试。每个map任务用于读或写每个文件,map的输出用于收集与处理文件相...

Linux操作系统之Linux命令的返回值

Linux命令执行后无论成功与否都有一个返回值,如果为 0,则表示命令执行成功,其它值则表示执行错误。具体的错误码含义如下:  "OS error code  1: Operation not per...

MySQL运维实战之ProxySQL(9.3)使用ProxySQL实现读写分离

proxysql读写分离主要通过mysql_query_rules表中的规则来实现。下面是具体的配置步骤:hostgroup配置insert into mysql_servers&...

RAC和DG的选择

RAC和DG的选择

RAC和DG的选择一、RAC1、什么是RAC实时应用集群,是负载均衡模式,两台机器同时工作参与到业务系统中,如果其中一个节点出现问题,所有的会话连接会转到另一个节点,保证业务系统正常运行,但是数据只有...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。