k8s存储方式的介绍及应用

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文件

[[email protected] 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: {}

执行一下

[[email protected] yaml]# kubectl apply -f emptyDir.yaml 

查看一下

[[email protected] yaml]# kubectl get pod  

查看日志

[[email protected] yaml]# kubectl logs  producer-consumer producer
[[email protected] yaml]# kubectl logs  producer-consumer consumer

查看挂载的目录

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

[[email protected] shared-volume]# docker ps 

[[email protected] 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所需安装包

[[email protected] ~]# yum -y install nfs-utils  rpcbind

创建共享目录

[[email protected] ~]# mkdir /nfsdata

创建共享目录的权限

[[email protected] ~]# vim /etc/exports
/nfsdata *(rw,sync,no_root_squash)

开启nfs和rpcbind

[[email protected] ~]# systemctl start nfs-server.service
[[email protected] ~]# systemctl start rpcbind

测试一下

[[email protected] ~]# showmount -e

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

[[email protected] yaml]# cd yaml/
[[email protected] 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>执行一下

[[email protected] yaml]# kubectl apply -f nfs-pv.yaml 

<3>查看一下

[[email protected] yaml]# kubectl get pv

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

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

[[email protected] yaml]# vim nfs-pvc.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: test-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: nfs

<2>执行一下

[[email protected] yaml]# kubectl apply -f nfs-pvc.yaml 

<3>查看一下

[[email protected] yaml]# kubectl get pvc

[[email protected] yaml]# kubectl get pv

(2)创建一个pod资源

[[email protected] 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> 执行一下

[[email protected] yaml]# kubectl apply -f pod.yaml 

<2>查看一下

[[email protected] yaml]# kubectl get pod -o wide

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

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

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

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

[[email protected] yaml]# kubectl exec test-pod touch /mydata/hello

进入容器

[[email protected] yaml]# kubectl exec -it test-pod  /bin/sh
/ # echo 123 > /mydata/hello
/ # exit

挂载目录查看一下

[[email protected] yaml]# cat  /nfsdata/pv1/hello 

和刚刚的一样

(4)测试回收策略

删除pod和pvc,pv

[[email protected] yaml]# kubectl delete pod test-pod
[[email protected] yaml]# kubectl delete pvc test-pvc
[[email protected] yaml]# kubectl delete pv test-pv 

查看一下

[[email protected] yaml]# kubectl get pv

[[email protected] yaml]# cat  /nfsdata/pv1/hello

文件已被回收

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

修改

[[email protected] 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

执行一下

[[email protected] yaml]# kubectl apply -f nfs-pv.yaml 

创建pod

[[email protected] yaml]# kubectl apply -f pod.yaml 

查看一下

[[email protected] yaml]# kubectl describe pod test-pod 

创建pvc

[[email protected] yaml]# kubectl apply -f nfs-pvc.yaml 

查看一下pod

[[email protected] yaml]# kubectl get pod

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

[[email protected] yaml]# kubectl exec test-pod touch /mydata/k8s

查看一下挂载目录

[[email protected] yaml]# ls /nfsdata/pv1/

删除pod和pvc,pv,再次查看挂载目录

[[email protected] yaml]# kubectl delete pod test-pod
[[email protected] yaml]# kubectl delete pvc test-pvc
[[email protected] yaml]# kubectl delete pv test-pv 

查看挂载目录

[[email protected] yaml]# ls /nfsdata/pv1/

内容还在

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

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

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

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

[[email protected] yaml]# kubectl apply -f  nfs-pv.yaml
[[email protected] yaml]# kubectl apply -f  nfs-pvc.yaml 

查看一下

[[email protected] yaml]# kubectl get pv

[[email protected] yaml]# kubectl get pvc

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

[[email protected] 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

执行一下

[[email protected] yaml]# kubectl apply -f mysql.yaml 

查看一下

[[email protected] yaml]# kubectl get pod

(3)进入mysql容器

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

[[email protected] 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)查看本地的挂载目录

[[email protected] yaml]# ls /nfsdata/pv1/

查看一下pod

[[email protected] yaml]# kubectl get pod -o wide -w

挂起node01

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

进入数据库

[[email protected] 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模块关联的

原文地址:https://blog.51cto.com/14320361/2469627

时间: 2024-10-08 22:30:10

k8s存储方式的介绍及应用的相关文章

安卓中的数据存储方式以及ContentProvider的简单介绍

1.介绍android的数据存储方式 File存储 sharedPrefrence存储方式 conmtentprovider sqlitedatabase 网络存储 2.请介绍下ContentProvider是如何实现数据共享的 安卓中如果想将自己应用程序的数据暴露给其他的应用程序的时候就需要创建内容提供者.第三方可以通过contentResolver来访问该provider 3.为什么要使用ContentProvider?它和sql的实现上有什么差别? ContentProvider屏蔽了数据

小记--------hbase数据库介绍及存储方式

一.Hbase基本原理 1.hbase基本介绍 HBASE是一个分布式的,面向列的开源数据库.Hbase的存储是基于hadoop的.因为Hadoop实现了一个分布式文件系统(HDFS),基于hadoop意味着hbase与生俱来的超强的扩展性和吞吐量,hbase采用的是key.value的存储方式.意味着即使随着数据量增大,也几乎不会导致查询的性能下降. 2.hbase存储方式 hbase将数据按列簇分别存储,而并非简单的列式存储:首先了解几个概念:行式存储.列式存储.列簇式存储. A.行式存储:

iOS常用的存储方式介绍

在iOS App开发过程中经常需要操作一些需要持续性保留的数据,比如用户对于App的相关设置.需要在本地缓存的数据等等.本文针对OC中经常使用的一下存储方式做了个整理. 常用的存储工具/方式: NSUserDefaults类 Plist文件 解归档 手动存放沙盒 // sqlite CoreData 第三方数据存储框架 1. NSUserDefaults 一般对于一些基本的用户设置,因为数据量很小,我们可以使用OC语言中的 NSUserDefaults类来进行处理.使用方法很简单,只需要调用类中

介绍HTML5几种存储方式

总体情况 h5之前,存储主要是用cookies.cookies缺点有在请求头上带着数据,大小是4k之内.主Domain污染. 主要应用:购物车.客户登录 对于IE浏览器有UserData,大小是64k,只有IE浏览器支持. 下面就跟兄弟连(www.lampbrother.net )HTML5课程一起来学习HTML5几种存储方式: 目标 解决4k的大小问题 解决请求头常带存储信息的问题 解决关系型存储的问题 跨浏览器 1.本地存储localstorage 存储方式: 以键值对(Key-Value)

QList介绍(QList比QVector更快,这是由它们在内存中的存储方式决定的。QStringList是在QList的基础上针对字符串提供额外的函数。at()操作比操作符[]更快,因为它不需要深度复制)非常实用

FROM:http://apps.hi.baidu.com/share/detail/33517814 今天做项目时,需要用到QList来存储一组点.为此,我对QList类的说明进行了如下翻译. QList是一种表示链表的模板类.QList<T>是Qt的一种泛型容器类.它以链表方式存储一组值,并能对这组数据进行快速索引,还提供了快速插入和删除等操作.QList.QLinkedList和QVector提供的操作极其相似:* 对大多数操作来说,我们用QList就可以了.其API是基于索引(inde

浮点型数据存储方式

C语言和C#语言中,对于浮点类型的数据采用单精度类型(float)和双精度类型(double)来存储,float数据占用32bit,double数据占用64bit,我们在声明一个变量float f= 2.25f的时候,是如何分配内存的呢?如果胡乱分配,那世界岂不是乱套了么,其实不论是float还是double在存储方式上都是遵从IEEE的规范的,float遵从的是IEEE R32.24 ,而double 遵从的是R64.53. 无论是单精度还是双精度在存储中都分为三个部分: 符号位(Sign)

android五种数据存储方式

在Android中提供了如下五种数据存储方式: SharedPreferences 文件存储 SQLite数据库方式 内容提供器(ContentProvider) 网络存储 下面具体介绍一下这五种数据存储方式的用法. 1. SharedPreferences SharedPreferences是android平台上的一个轻量级存储类,主要保存一些常用的配置信息.可以保存long.int.String类型数据. SharedPreferences以键值对方式读取和存入,最终会以XML方式保存数据,

IOS的四种数据存储方式及优劣

IOS有四种经常使用数据存储方式: 第一种方法:用NSUserDefaults存储配置信息 NSUserDefaults被设计用来存储设备和应用的配置信息.它通过一个工厂方法返回默认的.也是最经常使用到的实例对象. 这个对象中储存了系统中用户的配置信息,开发人员能够通过这个实例对象对这些已有的信息进行改动.也能够依照自己的需求创建新的配置项. 他实际上是存储于文件沙盒中的一个.plist文件,而且没有被系统加密,仅仅是ios6以后不是存于经常使用的文档文件夹下,所以不破解系统是看不到该文件的.所

float浮点数的二进制存储方式及转换

int和float都是4字节32位表示形式.为什么float的范围大于int? float精度为6-7位.1.66*10^10的数字结果并不是166 0000 0000 指数越大,误差越大. 这些问题,都是浮点数的存储方式造成的. float和double在存储方式上都是遵从IEEE的规范的,float遵从的是IEEE R32.24 ,而double 遵从的是R64.53. 无论是单精度还是双精度在存储中都分为三个部分: 符号位(Sign) : 0代表正,1代表为负 指数位(Exponent):