k8s存储方式的介绍及应用 (持久化,mysql对数据持久化
更新:HHH   时间:2023-1-7


k8s存储: (持久化)

docker容器是有生命周期的。
volume

1,存储类(Storage class)是k8s资源类型的一种,它是有管理员为管理PV更加方便创建的一个逻辑组,可以按照存储系统的性能高低,或者综合服务质量,备份策略等分类。不过k8s本身不知道类别到底是什么,它这是作为一个描述。

2,存储类的好处之一就是支持PV的动态创建,当用户用到持久性存储时,不必再去提前创建PV,而是直接创建PVC就可以了,非常的方便。

3,存储类对象的名称很重要,并且出了名称之外,还有3个关键字段
Provisioner(供给方):
及提供了存储资源的存储系统。k8s内建有多重供给方,这些供给方的名字都以“kubernetes.io”为前缀。并且还可以自定义。
Parameters(参数):存储类使用参数描述要关联到的存储卷,注意不同的供给方参数也不同。
reclaimPolicy:PV的回收策略,可用值有Delete(默认)和Retain

简介

1, 由于容器本身是非持久化的,因此需要解决在容器中运行应用程序遇到的一些问题。首先,当容器崩溃时,kubelet将重新启动容器,但是写入容器的文件将会丢失,容器将会以镜像的初始状态重新开始;第二,在通过一个Pod中一起运行的容器,通常需要共享容器之间一些文件。Kubernetes通过存储卷解决上述的两个问题。

2, 在Docker有存储卷的概念卷,但Docker中存储卷只是磁盘的或另一个容器中的目录,并没有对其生命周期进行管理。Kubernetes的存储卷有自己的生命周期,它的生命周期与使用的它Pod生命周期一致。因此,相比于在Pod中运行的容器来说,存储卷的存在时间会比的其中的任何容器都长,并且在容器重新启动时会保留数据。当然,当Pod停止存在时,存储卷也将不再存在。在Kubernetes支持多种类型的卷,而Pod可以同时使用各种类型和任意数量的存储卷。在Pod中通过指定下面的字段来使用存储卷:
spec.volumes:通过此字段提供指定的存储卷
spec.containers.volumeMounts:通过此字段将存储卷挂接到容器中

环境介绍

主机 IP地址 服务
master 192.168.1.21 k8s
node01 192.168.1.22 k8s
node02 192.168.1.23 k8s

1.emptyDir(空目录):类似docker 数据持久化的:docer manager volume

使用场景:在同一 个Pod里,不同的容器,共享数据卷。

如果容器被删除,数据仍然存在,如果Pod被 删除,数据也会被删除。

<1> 介绍

一个emptyDir 第一次创建是在一个pod被指定到具体node的时候,并且会一直存在在pod的生命周期当中,正如它的名字一样,它初始化是一个空的目录,pod中的容器都可以读写这个目录,这个目录可以被挂在到各个容器相同或者不相同的的路径下。当一个pod因为任何原因被移除的时候,这些数据会被永久删除。注意:一个容器崩溃了不会导致数据的丢失,因为容器的崩溃并不移除pod.

emptyDir的使用场景如下:

  • 空白的初始空间,例如合并/排序算法中,临时将数据保存在磁盘上。
  • 长时间计算中存储检查点(中间结果),以便容器崩溃时,可以从上一次存储的检查点(中间结果)继续进行,而不是从头开始。
  • 作为两个容器的共享存储,使得第一个内容管理的容器可以将生成的数据存入其中,同时由一个webserver容器对外提供这些页面。
  • 默认情况下,emptyDir数据卷存储在node节点的存储介质(机械硬盘、SSD或网络存储)上。

<2>emptyDir 磁盘的作用:

(1)普通空间,基于磁盘的数据存储
(2)作为从崩溃中恢复的备份点
(3)存储那些那些需要长久保存的数据,例web服务中的数据
默认的,emptyDir 磁盘会存储在主机所使用的媒介上,可能是SSD,或者网络硬盘,这主要取决于你的环境。当然,我们也可以将emptyDir.medium的值设置为Memory来告诉Kubernetes 来挂在一个基于内存的目录tmpfs,因为
tmpfs速度会比硬盘块度了,但是,当主机重启的时候所有的数据都会丢失。

测试编写一个yaml文件

[root@master yaml]# vim emptyDir.yaml
apiVersion: v1
kind: Pod
metadata:
  name: producer-consumer
spec:
  containers:
  - image: busybox
    name: producer
    volumeMounts:
    - mountPath: /producer_dir
      name: shared-volume
    args:
    - /bin/sh
    - -c
    - echo "hello k8s" &gt; /producer_dir/hello; sleep 30000
  - image: busybox
    name: consumer
    volumeMounts:
    - mountPath: /consumer_dir
      name: shared-volume
    args:
    - /bin/sh
    - -c
    - cat /consumer_dir/hello; sleep 30000
  volumes:
  - name: shared-volume
    emptyDir: {}

执行一下

[root@master yaml]# kubectl apply -f emptyDir.yaml 

查看一下

[root@master yaml]# kubectl get pod  

查看日志

[root@master yaml]# kubectl logs  producer-consumer producer
[root@master yaml]# kubectl logs  producer-consumer consumer

查看挂载的目录

node节点查看容器名,并通过容器名查看挂载的目录

[root@node01 shared-volume]# docker ps 

[root@node01 shared-volume]# docker inspect k8s_consumer_producer-consumer_default_9ec83f9e-e58b-4bf8-8e16-85b0f83febf9_0

进入挂载目录查看一下

2.hostPath Volume:类似docker 数据持久化的:bind mount

<1> 介绍

hostPath宿主机路径,就是把pod所在的宿主机之上的脱离pod中的容器名称空间的之外的宿主机的文件系统的某一目录和pod建立关联关系,在pod删除时,存储数据不会丢失。

<2> 作用

如果Pod被删除,数据会保留,相比较emptyDir要好一点。不过一旦host崩溃,hostPath也无法访问 了。

docker或者k8s集群本身的存储会采用hostPath这种方式。

适用场景如下:

某容器需要访问 Docker,可使用 hostPath 挂载宿主节点的 /var/lib/docker
在容器中运行 cAdvisor,使用 hostPath 挂载宿主节点的 /sys

3.Persistent Volume| PV(持久卷) 提前做好的,数据持久化的数据存放目录。

Psesistent Volume Claim| PVC( 持久卷使用声明|申请)

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

PVC和PV的概念

我们前面提到kubernetes提供那么多存储接口,但是首先kubernetes的各个Node节点能管理这些存储,但是各种存储参数也需要专业的存储工程师才能了解,由此我们的kubernetes管理变的更加复杂的。由此kubernetes提出了PV和PVC的概念,这样开发人员和使用者就不需要关注后端存储是什么,使用什么参数等问题。如下图:

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

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

虽然PersistentVolumeClaims允许用户使用抽象存储资源,但是常见的需求是,用户需要根据不同的需求去创建PV,用于不同的场景。而此时需要集群管理员提供不同需求的PV,而不仅仅是PV的大小和访问模式,但又不需要用户了解这些卷的实现细节。 对于这样的需求,此时可以采用StorageClass资源。这个在前面就已经提到过此方案。

PV是集群中的资源。 PVC是对这些资源的请求,也是对资源的索赔检查。 PV和PVC之间的相互作用遵循这个生命周期:

Provisioning(配置)---&gt; Binding(绑定)---&gt;Using(使用)---&gt; Releasing(释放) ---&gt; Recycling(回收)

(1)基于nfs服务来做的PV

nfs使的我们可以挂在已经存在的共享到的我们的Pod中,和emptyDir不同的是,emptyDir会被删除当我们的Pod被删除的时候,但是nfs不会被删除,仅仅是解除挂在状态而已,这就意味着NFS能够允许我们提前对数据进行处理,而且这些数据可以在Pod之间相互传递.并且,nfs可以同时被多个pod挂在并进行读写
注意:必须先保证NFS服务器正常运行在我们进行挂在nfs的时候
下载nfs所需安装包

[root@node02 ~]# yum -y install nfs-utils  rpcbind

创建共享目录

[root@master ~]# mkdir /nfsdata

创建共享目录的权限

[root@master ~]# vim /etc/exports
/nfsdata *(rw,sync,no_root_squash)

开启nfs和rpcbind

[root@master ~]# systemctl start nfs-server.service 
[root@master ~]# systemctl start rpcbind

测试一下

[root@master ~]# showmount -e

<1>创建nfs-pv的yaml文件
[root@master yaml]# cd yaml/
[root@master yaml]# vim nfs-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: test-pv
spec:
  capacity:   #pv容量的大小
    storage: 1Gi
  accessModes:  #访问pv的模式
    - ReadWriteOnce #能以读-写mount到单个的节点
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: nfs
  nfs:
    path: /nfsdata/pv1
    server: 192.168.1.21
  accessModes:(PV支持的访问模式)
    - ReadWriteOnce: 能以读-写mount到单个的节点
    - ReadWriteMany: 能以读-写mount到多个的节点。
  - ReadOnlyOnce:  能以只读的方式mount到单个节点。
persistentVolumeReclaimPolicy : (PV存储空间的回收策略是什么)
  Recycle: 自动清除数据。
  Retain: 需要管理员手动回收。
  Delete: 云存储专用。
<2>执行一下
[root@master yaml]# kubectl apply -f nfs-pv.yaml 
<3>查看一下
[root@master yaml]# kubectl get pv

<1>创建nfs-pvc的yaml文件

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

[root@master yaml]# vim nfs-pvc.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: test-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: nfs
<2>执行一下
[root@master yaml]# kubectl apply -f nfs-pvc.yaml 
<3>查看一下
[root@master yaml]# kubectl get pvc

[root@master yaml]# kubectl get pv

(2)创建一个pod资源

[root@master yaml]# vim pod.yaml
kind: Pod
apiVersion: v1
metadata:
  name: test-pod
spec:
  containers:
    - name: pod1
      image: busybox
      args:
      - /bin/sh
      - -c
      - sleep 30000
      volumeMounts:
      - mountPath: "/mydata"
        name: mydata
  volumes:
    - name: mydata
      persistentVolumeClaim:
        claimName: test-pvc
<1> 执行一下
[root@master yaml]# kubectl apply -f pod.yaml 
<2>查看一下
[root@master yaml]# kubectl get pod -o wide

可以看到现在没有开启成功

查看一下test-pod的信息看看是哪里的问题
[root@master yaml]# kubectl describe pod test-pod 

那是因为pv的本地挂载目录没有创建好
[root@master yaml]# mkdir /nfsdata/pv1/
//要和nfs-pv.yaml的名字一样
重新创建一下pod
[root@master yaml]# kubectl delete -f pod.yaml 
[root@master yaml]# kubectl apply -f pod.yaml 
[root@master yaml]# kubectl get pod -o wide

(3)test-pod创建hello创建文件并添加内容

[root@master yaml]# kubectl exec test-pod touch /mydata/hello

进入容器

[root@master yaml]# kubectl exec -it test-pod  /bin/sh
/ # echo 123 > /mydata/hello
/ # exit

挂载目录查看一下

[root@master yaml]# cat  /nfsdata/pv1/hello 

和刚刚的一样

(4)测试回收策略

删除pod和pvc,pv
[root@master yaml]# kubectl delete pod test-pod 
[root@master yaml]# kubectl delete pvc test-pvc 
[root@master yaml]# kubectl delete pv test-pv 
查看一下
[root@master yaml]# kubectl get pv

[root@master yaml]# cat  /nfsdata/pv1/hello

文件已被回收

(5)修改pv的回收策略为手动

修改
[root@master yaml]# vim nfs-pv.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: test-pv
spec :
  capacity :
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain   #修改
  storageClassName: nfs
  nfs:
    path: /nfsdata/pv1
    server: 192.168.1.21
执行一下
[root@master yaml]# kubectl apply -f nfs-pv.yaml 
创建pod
[root@master yaml]# kubectl apply -f pod.yaml 
查看一下

[root@master yaml]# kubectl describe pod test-pod 

创建pvc
[root@master yaml]# kubectl apply -f nfs-pvc.yaml 
查看一下pod
[root@master yaml]# kubectl get pod

(6)test-pod创建hello创建文件并添加内容

[root@master yaml]# kubectl exec test-pod touch /mydata/k8s
查看一下挂载目录
[root@master yaml]# ls /nfsdata/pv1/

删除pod和pvc,pv,再次查看挂载目录
[root@master yaml]# kubectl delete pod test-pod 
[root@master yaml]# kubectl delete pvc test-pvc
[root@master yaml]# kubectl delete pv test-pv 
查看挂载目录
[root@master yaml]# ls /nfsdata/pv1/

内容还在

4.mysql对数据持久化的应用

下面演示如何为 MySQL 数据库提供持久化存储,步骤为:

  • 创建 PV 和 PVC。
  • 部署 MySQL。
  • 向 MySQL 添加数据。
  • 模拟节点宕机故障,Kubernetes 将 MySQL 自动迁移到其他节点。
  • 验证数据一致性。

(1)通过之前的yaml文件,创建pv和pvc

[root@master yaml]# kubectl apply -f  nfs-pv.yaml 
[root@master yaml]# kubectl apply -f  nfs-pvc.yaml 

查看一下

[root@master yaml]# kubectl get pv

[root@master yaml]# kubectl get pvc

(2)编写一个mysql的yaml文件

[root@master yaml]# vim mysql.yaml

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: test-mysql
spec:
  selector:
    matchLabels:    #支持等值的标签
      app: mysql
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: test-mysql
spec:
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - image: mysql:5.6
        name: mysql
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: 123.com
        volumeMounts:
        - name: mysql-storage
          mountPath: /var/lib/mysql
      volumes:
      - name: mysql-storage
        persistentVolumeClaim:
          claimName: test-pvc

执行一下

[root@master yaml]# kubectl apply -f mysql.yaml 

查看一下

[root@master yaml]# kubectl get pod

(3)进入mysql容器

① 切换到数据库 mysql。
② 创建数据库表 my_id。
③ 插入一条数据。
④ 确认数据已经写入。
关闭 k8s-node2,模拟节点宕机故障。

[root@master yaml]# kubectl exec -it test-mysql-569f8df4db-rkpwm  -- mysql -u root -p123.com 

创建数据库

mysql> create database yun33;

切换数据库

mysql> use yun33;

创建表

mysql> create table my_id( id int(4));

在表中插入数据

mysql> insert my_id values(9527);

查看表

mysql> select * from my_id;

(4)查看本地的挂载目录

[root@master yaml]# ls /nfsdata/pv1/

查看一下pod

[root@master yaml]# kubectl get pod -o wide -w

挂起node01

(5)查看node02上面数据是否和刚才一样(验证数据的一致性)

进入数据库

[root@master yaml]#  kubectl exec -it test-mysql-569f8df4db-nsdnz  -- mysql -u root -p123.com 

查看数据库

mysql> show databases;

查看表

mysql> show tables;

mysql> select * from my_id;

可以看到数据还在

5. 排错方法

kubectl describe
//查看详细信息,找出问题
kubectl logs
//查看日志,找出问题
/var/ log/messages
//查看该节点的kubelet的日志。

6. 小结

本章我们讨论了 Kubernetes 如何管理存储资源。
emptyDir 和 hostPath 类型的 Volume 很方便,但可持久性不强,Kubernetes 支持多种外部存储系统的 Volume。
PV 和 PVC 分离了管理员和普通用户的职责,更适合生产环境。我们还学习了如何通过 StorageClass 实现更高效的动态供给。
最后,我们演示了如何在 MySQL 中使用 PersistentVolume 实现数据持久性。

1. PV的访问控制类型

accessModes:(PV支持的访问模式)

  • ReadWriteOnce: 能以读-写mount到单个的节点
  • ReadWriteMany: 能以读-写mount到多个的节点。
  • ReadOnlyOnce: 能以只读的方式mount到单个节点。
2. PV的空间回收策略

persistentVolumeReclaimPolicy : (PV存储空间的回收策略是什么)

Recycle: 自动清除数据。
Retain: 需要管理员手动回收。
Delete: 云存储专用。

3. PV和PVC相互关联

是通过accessModes和storageClassName模块关联的

返回云计算教程...