k8s中使用MySQL共享存储_k8s存储方式的介绍及应用 (持久化,mysql对数据持久化的应用)...

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" > /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

cb23e54e388c6f63e3e521f956152f5a.png

查看日志

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

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

334d1ea81ba0cdd75a6bd0e3d8c51780.png

查看挂载的目录

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

[root@node01 shared-volume]# docker ps

a5ccf1adb37fd288bbdd8c63ed07ae4d.png

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

a32ee5032232d4825541e65aa1c95583.png

进入挂载目录查看一下

088f1ba787cea8981e84ef7723b2b3df.png

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的概念,这样开发人员和使用者就不需要关注后端存储是什么,使用什么参数等问题。如下图:

b10f32721ab0dc9b6e590f7ff6e28625.png

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

0fbc115ceec186f601ce4f68b216555c.png

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

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

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

Provisioning(配置)---> Binding(绑定)--->Using(使用)---> Releasing(释放) ---> 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

de3d592057fa488d76e3f9e91b71b585.png

<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

060f1246490e4af9cf603687fda5e743.png

<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

7a51f2617b264066a2412554ebe109b3.png

[root@master yaml]# kubectl get pv

9f6ea5d8497ae38761a97980ca88e414.png

(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

a2017622a1aa793fa11fd8321c7126ea.png

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

查看一下test-pod的信息看看是哪里的问题

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

ecd5496cd2ae443184d966c03569bf1f.png

那是因为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

606194cb8af365499c7757e6adbead0a.png

(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

14b05f01841e078779edcaf0efa6d7da.png

和刚刚的一样

(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

d9090fea7bb3b3a3b7dda8c24e005a30.png

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

7a17928c5c18237accdf126f5103f6d1.png

文件已被回收

(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

查看一下

aa3a50fe8e20865b9eea200739ab3bda.png

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

38c2a17447e65748f7bb14b68f9c078b.png

创建pvc

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

查看一下pod

[root@master yaml]# kubectl get pod

315480abd0b096859167ede922822049.png

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

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

查看一下挂载目录

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

9bf17835e2e07a3a7ff85a5128cc4490.png

删除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/

a7808308e1f3ebf802929b32219f97a2.png

内容还在

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

842599c67612d0e71122bc424e04b966.png

[root@master yaml]# kubectl get pvc

bd81faae9b3bafff0f8ea932e18b7d19.png

(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

74bb76470d4aa2492103ddc9e13536f1.png

(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;

03093f6e3ce31410936aad3ee31019aa.png

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

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

afd88e01ce16520d5160893056c685c9.png

查看一下pod

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

b9d7df87998a5d17b1b853d24d976e66.png

挂起node01

1b604ca15c7bd2a4c7a30a71a2feda9b.png

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

进入数据库

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

查看数据库

mysql> show databases;

dfab0d0c667f92e7acae9d409f7dcdbf.png

查看表

mysql> show tables;

f11c6a3fc47ce5eb739296e2797be0b3.png

mysql> select * from my_id;

e62160f5e3fc6600559a5d16d4c10def.png

可以看到数据还在

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模块关联的

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值