当前位置:首页 » 服务存储 » k8s挂载网络存储
扩展阅读
webinf下怎么引入js 2023-08-31 21:54:13
堡垒机怎么打开web 2023-08-31 21:54:11

k8s挂载网络存储

发布时间: 2023-05-03 06:31:05

⑴ 深入剖析k8s中的存储

本文是《深入剖析k8s》学习笔记的第四篇,主要对k8s中的存储数据卷进行分析和学唤腊习。

容器中的存储是不稳定的,一旦容器重启或者销毁,这些存储就都会丢失。所以真实使用场景下,都会以数据卷挂载的方式将外部存储应用到容器中,带来的好处就是:

在k8s中,如果要在容器中使用数据卷,需要像如下一个pod的yaml示例一样进行声明定义:

其中pod的定义中,声明使用了自定义名称为 my-volume 的数据卷,并且类型为emptyDir;k8s的volume支持多种数据类型,可以通过命令 kubectl explain pod.spec.volumes 来查看所有支持的volume类型,其中常用的类型及意义比较如下:

从工程分工角度上来说,存储的定义和声明应该由运维人员完成,开发人员只要使用即可。因此,为了避免将存储细节过度地暴露给开发人员,k8s才引进了Persistent Volume Claim(PVC)和Persistent Volume(PV)这两个API对象,同时也降低了开发人员使用存储卷的门槛。如此,开发人员只需要如下两步就能解决存储卷的使用问题:

那么开发人员声明的PVC到底使用的是什么存储卷呢,这个和厅就由运维人员负责维护就行了,如下是一个PV的定义,开发人员了解即可:

为什么这个PV可以和上面的PVC绑定呢?只要符合如下的条件,k8s就会自动将它们绑定,绑定后,在PVC的配置文件中就能看到使用的数据卷就是该PV了。

总的来说,PVC和PV的关系就像是接口和实现的关系,PVC是接口定义,声明要使用什么,至于怎么实现,就是PV去完成的事情。如此解耦,使得开发和运维都能高效地搞定存储。

假设开发人员在创建好带有PVC的pod之后,且pod已经运行了,才发现运维还没有来得及创建对应的PVC或者PVC创建有问题,致使pod存储卷使用有问题该怎么办?只要运维及时创建对应的PV,k8s中的volume controller会循环遍历没有成功绑定PV的PVC,帮它们寻找唤链隐合适的PV进行绑定。

一个k8s集群往往有很多开发团队在使用,开发会部署很多pod,如果这些pod都需要存储卷,运维人员就需要天天创建pv来满足开发人员pvc绑定的需求了,太浪费人力,所以这种重复工作就被k8s中的storageClass取代了。原先手动创建PV的方式被称为static provisioning,使用storageClass自动创建PV的方式被称为dynamic provisioning,storageClass其实就是PV的一个模板,其定义大致分为两个部分:

在开发人员创建PVC的时候,只要指定使用的storageClassName是如上定义和创建的my-storageclass,那么k8s就会根据该storageClass自动创建一个PV与该PVC绑定。

⑵ [K8S系列七]存储-PV、PVC与Storage Class

本质上说,一个volume(卷)就是一个目录,从容器内部可以访问这个目录中的内容,而这个目录是怎么来的,它背后的媒介是什么以及它里面的内容,都是由volume的类型来决定的;而使用volume,只需要在pod上指定使用哪种类型的volume,以及mount到容器中的什么位置即可。K8S支持的存储类型如下所示,这里主要介绍HostPath和Persistent Volume。

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

根据附录1的volume-pod.yaml创建一个pod,使用hostPath类型的volume

部署后查看pods详情, 发现volume-pod位于w2节点,登录到w2 尝试在pods的容器中创建文件

因为hostPath类型的volume只映射pod所在的节点的文件或目录到pod中,如果pod因为重启被调度到其他节点时,将会看不到原来节点保存的数据,因此有了网络存储+pv+pvc的方式。
通过PersistentVolume(PV)与PersistentVolumeClaim(PVC)将提供存储与消费存储分离:

2.PVC由用户创建来消费存储,如同通过创建pod来消费cpu、mem资源。

PVC与PV是通过PersistentVolume Controller 进行绑定的。PV Controller 会不断地循环去查看每一个 PVC,是不是已经处于 Bound(已绑定)状态。如果不是,那它就会遍历所有的、可用的 PV,并尝试将其与未绑定的 PVC 进行绑定,这样,Kubernetes 就可以保证用户提交的每一个 PVC,只要有合适的 PV 出现,它就能够很快进入绑定状态。而所谓将PV 与 PVC 进行“绑定”,其实就是将这个 PV 对象的名字,填在了 PVC 对象的 spec.volumeName 字段上 。

这里以NFS+PV+PVC为例进行说明, NFS搭建过程请参考附录2,根据考附录3 nginx-pv-pvc.yaml ,创建nginx(deployment)、nginx-pv(pv)、nginx-pvc(pvc)。nginx-pv挂载在/nfs/data/nginx 下。在/nfs/data/nginx下创建文件1.html,pod中也可以访问,并且pod的重新创建不影响1.html。

上节说的PV和PVC方法虽然能实现屏蔽底层存储,但是PV创建比较复杂,通常都是由集群管理员管理,这非常不方便。
利用StorageClass实现,可以根据PVC需求,自动构建相对应的PV持久化存储卷,进一步简化运维管理成本。
StorageClass对象会定义下面两部分内容:

示例部分参考 nfs-subdir-external-provisioner 。 相关文件来源于 deploy ,需要略作修改。

1. Volumes
2.《kubernetes权威指南》
3. Kubernetes 存储设计

NFS(Network File System)网络文件系统,是FreeBSD支持的文件系统中的一种,允许网络中的计算机之间通过TCP/IP网络共享资源。

⑶ k8s之存储

k8s的存储常用的就是上面几种模式,分为临时存储,半持久化存储,与持久化存储这三类,本章我们着重讲解emptydir与hostpath与pvc跟pv等

当pod的存储方案设定为emptydir的时候,pod启动时,就会在pod所在节点的磁盘空间开辟出一块空卷,最开始里面是什么都没有的,pod启动后容器产生的数据会存放到那个空卷中。空卷变成了一个临时卷

供pod内的容器读取和写入数据,一旦pod容器消失,节点上开辟出的这个临时卷就会随着pod的销毁而销毁

一般来说emptydir的用途都是用来充当临时存储空间,例如一些不需要数据持久化的微服务,我们都可以用emptydir来当做微服务pod的存储方案

k8s存储emptdir实战例子:以之前的myapp应用为例

创建应用

观察是否生产data目录,并在/data目录创建文件test.txt

手动删除容器模拟容器销毁,用于是pod是被控制器管理的,删除后会被重建新的pod

这时候在看我们之前创建的data.txt已经不见了

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

其实这个功能就相当于docker中的-v 目录映射,只不过在k8s中的时候,pod会漂移,当pod漂移到其他node节点的时候,pod不会跨节点的去读取目录。所以说hostpath只能算一种半持久化的存储方式

实战例子

创建应用

在node节点可以看到生成了/data/volume目录,在里面创建测试文件

检验pod里面的/data是否存在这个映射目录的文件

可以看到刚才创建的文件已经映射到我们的目录里边了

为了验证是否映射到容器里面的目录也会随着pod生命周期的消失而消失,我们手动删除pod模拟容器终止

可以看到容器被删除后,新建的pod也可以看到我们映射的目录,而且里面数据test.txt还在。

这有个缺点就是不能够跨容器去读取数据,如果删除后的pod被调度到其他节点的话,原来的数据也就没有了,如果能不受节点的影响,并且挂载的数据不会随生命周期的结束而结束,我们应该怎么解决呢?就是我们后面讲到的持久化存储了

上面介绍了俩种临时存储于半持久化存储的方案。在k8s实际生产环境中,一般会选用私有云持久化存储方案还有公有云持久化存储方案,私有云存储方案包括nfs,ceph,glusterfs等方案。公有云存储会用到AWS等方案

存储方案各有各的优缺点,可参考 https://www.cnblogs.com/yswenli/p/7234579.html 这篇文章。今天我们主要讲解pvc,pv,nfs之间的关系。

简单来说,要使用持久化存储,就需要使用pvc去跟pv去申请,然后pv查看自己有没有合适的存储空间卷,有合适的就与pvc进行绑定。pv与pvc是一一对应绑定的。现在我们用一幅图来说明pvc,pv,nfs的关系

实战例子

准备存储服务安装nfs

接下来创建pv与nfs绑定

创建pvc与pv关联

创建并查看结果

注意:STATUS为Bound说明该pvc已经与pv绑定了

接下来创建pod来引用pvc

创建pod

接下来验证一下在nfs创建一个测试文件,看是否被映射到容器中

可以看到容器里面也可以看到创建的文件

手动删除容器,或者调度到其他节点原来的文件还是不会被删除的,这里就省略验证了,这就是nfs的好处,不过企业一般不会选用nfs,磁盘IO,性能读取方面不太理想,毕竟是本地存储,还是有一定的风险。推荐用用云存储。

文件存储提供无限扩展的文件系统来给云服务器存取数据实际上相当于nfs

1、已注册阿里云账号,并完成实名认证。

如果没有,请先注册阿里云账号,详情请参见阿里云账号注册流程。

2、已开通NAS服务。

首次登录NAS控制台时,根据页面提示开通NAS服务。

3、在需要创建文件系统的地域,已有可用的云服务器ECS。

k8s应用NAS实战例子

1、打开阿里云NAS控制台确认已创建好文件系统

2、把复制挂载参数把它挂载到服务器中创建测试目录,前提是服务器需要安装nfs客户端。

安装完成挂载到本地目录并创建test目录作为测试目录

并在里面创建一个测试文件1.txt

接下来可以创建pvc和pv了

创建并查看

接下来创建pod去引用pvc

创建pod

检验刚才的1.txt是否挂到容器的/data/nas下

云存储适合于生产环境k8s的存储解决方案

⑷ 9. K8s存储

Kubernetes的Volume是Pod的一部分,Volume不是单独的对象,不能独立创建,只能在Pod中定义。
Pod中的所有容器都可以访问Volume,但必须要挂载,且可以挂载到容器中任何目录。
实际中使用容器存储如下图所示,将容器的内容挂载到Volume中,通过Volume两个容器间实现了存储共享。

Volume的生命周期与挂载它的Pod相同,但是Volume里面的文件可能在Volume消失后仍然存在,这取决于Volume的类型。

Kubernetes的Volume有非常多的类型:

这个Volume挂载后就是一个空目录,应用程序可以在里面读写文件,emptyDir Volume的生命周期与Pod相同,Pod删除后Volume的数据也同时删除掉。
emptyDir的一些用途:

配置示例

emptyDir也可以设置存储介质为内存

HostPath存储的内容与节点相关,如果Pod被调度到其他Node,HostPath无法提供跨Node的数据。
配置示例

ConfigMap存储的是键值对,在Volume中应用时键值对表示的是 文件名 和 文件内容 ,代表将ConfigMap的每条数据填入Volume。ConfigMap的配置数据在 data 字段下定义。

ConfigMap文件示例

Volume中引用ConfigMap

与ConfigMap类似,在data字段中存储key-value键值对形式,不过存储的value不是明文,是Base64编码的加密值。
在Volume中引用后,文件中的值是Base64解码后的值,而非加密值。

Kubernetes抽象了PV(PersistentVolume)和PVC(PersistentVolumeClaim)来解耦网络存储种类多样的问题,从而让使用者不用关心具体的基础设施,当需要存储资源的时候,只要像CPU和内存一样,声明要多少即可。
PV是集群级别的资源,并不属于某个命名空间(在 default 命名空间下),而PVC是命名空间级别的资源,PV可以与任何命名空间的PVC资源绑定。

Kubernetes管理员设置好网络存储的类型,提供对应的PV描述符配置到Kubernetes,使用者需要存储的时候只需要创建PVC,然后在Pod中使用Volume关联PVC,即可让Pod使用到存储资源,它们之间的关系如下图所示。

PV 持久卷是用 插件 的形式来实现的,目前支持以下插件:

CSI
Container Storage Interface,容器存储接口,基于CSI这套接口,可以开发定制出CSI插件,从而支持特定的存储,达到解耦的目的。

PVC创建示例:

使用StorageClass可以自动创建PV,StorageClass包含 provisioner 、 parameters 和 reclaimPolicy 字段, 这些字段会在 StorageClass 需要动态分配 PersistentVolume 时会使用到。在声明PVC时加上StorageClassName,就可以自动创建PV,并自动创建底层的存储资源。

provisioner: PV配置器,用来决定使用哪个卷插件制备 PV。 该字段必须指定。
reclaimPolicy: 回收策略,可以是 Delete 或者 Retain ,默认是 Delete

使用StorageClassName创建PVC示例:

⑸ kubernetes(十一) 数据存储(挂载卷管理)

在前面已经提到,容器的生命周期可能很短,会被频繁地创建和销毁。那么容器在销毁时,保存在容器中的数据也会被清除。这种结果对用户来说,在某些情况下是不乐意看到的。为了持久化保存容器的数据,kubernetes引入了Volume的概念。

Volume是Pod中能够被多个容器访问的共享目录,它被定义在Pod上,然后被一个Pod里的多个容器挂载到具体的文件目录下,kubernetes通过Volume实现同一个Pod中不同容器之间的数据共享以及数据的持久化存储。Volume的生命容器不与Pod中单个容器的生命周期相关,当容器终止或者重启时,Volume中的数据也不会丢失。销帆宴

kubernetes的Volume支持多种类型,比较常见的有下面几个:

EmptyDir是最基础的Volume类型,一个EmptyDir就是Host上的一个空目录。

EmptyDir是在Pod被分配到Node时创建的,它的初始内容为空,并且无须指定宿主机上对应的目录文件,因为kubernetes会自动分配一个目录,当Pod销毁时, EmptyDir中的数据也会被永久删除。 EmptyDir用途如下:

接下来,通过一个容器之间文件共享的案例来使用一下EmptyDir。

在一个Pod中准备两个容器nginx和busybox,然后声明一个Volume分别挂在到两个容器的亏银目录中,然后nginx容器负责向Volume中写日志,busybox中通过命令将日志内容读到控制台。

创建一个volume-emptydir.yaml

EmptyDir中数据不会被持久化,它会随着Pod的结束而销毁,如果想简单的将数据持久化到主机中,可以选择HostPath。

HostPath就是将Node主机中一个实际目录挂在到Pod中,以供容器使用,这样的设计就可以保证Pod销毁了,但是数据依据可以存在于Node主机上。

创建一个volume-hostpath.yaml:

HostPath可以解决数据持久化的问题,但是一旦Node节点故障了,Pod如果转移到了别的节点,又会出现问题了,此时需要准备单独的网络存储系统,比较常用的用NFS、CIFS。

NFS是一个网络文件存储系统,可以搭建一台NFS服务器,然后将Pod中的存储直接连接到NFS系统上,这样的话,无论Pod在节点上怎么转移,只要Node跟NFS的对接没问题,数据就可以成功访问。

1)首先要准备nfs的服务器,这里为了简单,直接是master节点做nfs服务器

2)接下来,要在的每个node节点上都安装下nfs,这样的目的是为了node节点可以驱动nfs设备

3)接下来,就可以编写pod的配置文件了,创建volume-nfs.yaml

4)最后,运行下pod,观察结果

前面已经学习了使用NFS提供存储,此时就要求用户会搭建NFS系统,并且会在yaml配置nfs。由于kubernetes支持的存储系统有很多,要求客户全都掌握,显然不现实。为了能够屏蔽底层存储实现的细节,方便用户使用, kubernetes引入PV和PVC两种资源对象。

PV(Persistent Volume)是持轿培久化卷的意思,是对底层的共享存储的一种抽象。一般情况下PV由kubernetes管理员进行创建和配置,它与底层具体的共享存储技术有关,并通过插件完成与共享存储的对接。

PVC(Persistent Volume Claim)是持久卷声明的意思,是用户对于存储需求的一种声明。换句话说,PVC其实就是用户向kubernetes系统发出的一种资源需求申请。

使用了PV和PVC之后,工作可以得到进一步的细分:

PV是存储资源的抽象,下面是资源清单文件:

PV 的关键配置参数说明:

实验
使用NFS作为存储,来演示PV的使用,创建3个PV,对应NFS中的3个暴露的路径。
1.准备NFS环境

2.创建pv.yaml

PVC是资源的申请,用来声明对存储空间、访问模式、存储类别需求信息。下面是资源清单文件:

PVC 的关键配置参数说明:

实验
1.创建pvc.yaml,申请pv

2.创建pods.yaml, 使用pv

PVC和PV是一一对应的,PV和PVC之间的相互作用遵循以下生命周期:

ConfigMap是一种比较特殊的存储卷,它的主要作用是用来存储配置信息的。

创建configmap.yaml,内容如下:

接下来,使用此配置文件创建configmap

接下来创建一个pod-configmap.yaml,将上面创建的configmap挂载进去

在kubernetes中,还存在一种和ConfigMap非常类似的对象,称为Secret对象。它主要用于存储敏感信息,例如密码、秘钥、证书等等。

1.首先使用base64对数据进行编码

2.接下来编写secret.yaml,并创建Secret

3.创建pod-secret.yaml,将上面创建的secret挂载进去:

至此,已经实现了利用secret实现了信息的编码。

⑹ k8s nfs挂载设置

nfs服务端配置

/data/xxxx  *(rw,async,no_root_squash)

k8s 客户端配置

apiVersion: v1

kind: PersistentVolume

metadata:

  name: $Sonar_Name-nfs-pv

  namespace: rdc

  labels:

    sonar: $Sonar_Name

spec:

  capacity:

    storage: 30Gi

 档缺 accessModes:

 行绝辩   - ReadWriteMany

  nfs:

    server: 192.168.36.32

    path: /data/sonar11

---

apiVersion: v1

kind: PersistentVolumeClaim

metadata:

  namespace: rdc

  name: $Sonar_Name-pvc

spec:

  accessModes:

    - ReadWriteMany

  storageClassName: ""

  resources:

    requests:

      storage: 30Gi

  selector: 

    matchLabels:

      sonar: $Sonar_Name

PV 和PVC 是一一对应的关宏碧系

⑺ K8s 数据存储之Volume

一切container和它之中的数据都是临时的。如果container重启,这些数据会丢失。Volume用于container保存需要持久化的数据。这些数据也可以用于container共享。

Docker中有volume的概念。在Docker中,volume是container中的一个目录。Volume没有生命周期的概念,volume中的数据只有储存在本地磁盘这一种形式。

Kubernetes的volume具有明确的生命空间。Volume生命周期比pod中运行的container长。Container重启之后,volume的数据仍会保留。但是,当Pod销毁之时,该pod关联的volume也会同时销毁。

使用volume的方法:在spec.volumes处声明volume,在spec.containers[*].volumeMount中挂载volume到container。

可以将ConfigMap的值注入到volume中。这样可以在pod中使用config map。同时,Volume中的值会随着ConfigMap的修改而自动更新。

在Volume中使用ConfigMap的用法如下:

这里例子将名字为log-config的config map中key为log_level的值,作为文件log_level的内容,放入config-vol的根目录。然后把config-vol挂载到 /etc/config ,目录。也就是container中 /etc/config/log_level 文件的内容为log-config中log_level的值。

可以使用DownWard API的方式,将k8s资源的spec信息作为文件内容放入到volume中。

例子如下:

此处volume使用了downwardAPI。volume中labels文件的内容为pod metadata的labels配置项内容,即:

annotation文件的内容为为pod metadata的annotations配置项内容,即:

生命周期和pod一样。emptyDir的初始状态为一个没有任何内容的volume。如果Pod从集群节点上移除,那么emptyDir类型的volume中的内容会被清除。

Container遇到崩溃或重启,这时候Pod本身不会受任何影响,这种情况下emptyDir volume中的数据会保留。Container重启之后数据仍然可见。

emptyDir volume具有的这种特性适合如下场景使用:

默认来说emptyDir类型volume的物理存储在硬盘,SSD或网络设备上。可以设置 emptyDir.medium 为 Memory ,这时候k8s会使用tempfs(基于内存的文件系统)。此时volume的容量限制收到container的内存配额的制约。

配置样例为:

使用tempfs(内存)的羡历肆emptyDir volume的配置样例如下;

gitRepo比较简单:兄轿先准备一个emptyDir类型的volume,再clone一个git repo到volume,烂袭然后把volume mount到container。

此模式挂载pod宿主机文件系统中的文件或目录到pod。

hostPath必须指定一个path参与,用于指定使用宿主机哪个目录。

除此之外还有一个可选的type参数,有如下值可供配置:

需要注意的是由于hostPath类型volume的数据和宿主机强绑定,如果pod停止后被schele到其他节点,pod读取到的数据会有变化。

使用hostPath的例子:

local模式支持使用磁盘,分区或者是目录。local还支持使用静态创建的PersistentVolume,不支持Dynamic provisioning(使用PVC的方式)。

与hostPath不同的是,local模式无需手动配置将pod调度到固定的node上。local模式系统通过volume的node affinity配置来感知volume的node限制(volume只能生成在特定的node上)。

使用例子:

nodeAffinity必须配置。这个例子创建出的PersistentVolume必须创建在hostname包含 example-node 的节点上。

VolumeMode默认值为Filesystem。可以配置为 Block ,将volume作为块设备使用。

使用local模式的时候建议配套的StorageClass的 volumeBindingMode 设置为 WaitForFirstConsumer 。如下所示:

延迟volume绑定可以允许在volume绑定的时候考虑到pod中配置的一些限制,例如node资源限制,node选择器和pod affinity以及pod anti-affinity。

使用PVC声明式的创建所需的PersistentVolume。这个稍后在PersistentVolume中介绍。

映射多个类型的配置(数据源)到volume中。相当于多种volume合并使用。

可以映射的volume类型为:

所有的volume数据源要求必须和使用它的pod在同一个namespace之下。

一个使用例子如下:

通常我们绑定volume时,映射的是volume的根目录。我们可以通过指定subPath参数,将volume中的其他目录挂载到container中。对于一个pod多个container,且多处使用同一个volume的场景最为适用。

例子如下:

这个例子中mysql和php两个container使用同一个volume site-data。Volume的 mysql 目录映射到了mysql container的 /var/lib/mysql 。Volume的 html 目录映射到了php container的 /var/www/html 。

emptyDir使用磁盘时的限制取决于kubelet所在的文件系统(/var/lib/kubelet)。emptyDir或者hostPath占用多大磁盘空间是没有限制的。

⑻ K8s 数据存储之PersistentVolume

这两个概念用于pod和volume之间解耦。Pod根据自己的需要提吵悉出数据卷的申请,k8s系统将符合条件的数据卷返回给pod。这样一来pod就无需直接和数据卷本身强绑定了。Pod无需知道数据卷的细节信息,比如具体用的是什么存储。

Pod中对数据卷的申请为PVC,用来和PVC绑定的数据卷称为PV。

PV可以有多种存储方式,比如NFS,iSCSI等。

PVC是使用PV资源的声明。

PV有两种供应方式

这个阶段指的是PV和PVC绑定的过程。系统有一个机制,循环检查新创建的PVC,然后找到一个符合条件的PV,把他们绑定到一起。如果有多个满足要求的PV可以绑定,会使用消耗资源最小的那个。PV和PVC之间是一对一的关系。如果找不到符合条件的PV,PVC会一致保持未绑定状态。

PVC绑定合适的PV之后,Pod使用这个PV。和PVC绑定并处于使用状态的PV不会被系统删除,防止数据丢失。

如果用户删除了Pod正笑码在使用的PVC,这个PVC不会被立即移除。直到这个PVC不被任何Pod时候的时候,才会被真正的删除。

当PV不再使用的时候,k8s根据不同的策略来回收这些PV。

Retain策略在volume不再使用的时候,不删除旧的数据,等待管理员处理。

Delete策略会删除不再使用的PV,同时删除这些PV对应真实存储的资升升乎源。

删除volume内的内容,使得volume可供下次使用。

PV的容量

可以使用Filesystem或者Block。Filesystem为默认值。

具有如下可选值:

配置storageClassName。

可以使用如下回收策略:

可以指定存储的类型。

Local volume必须要设定这个属性。该属性规定了volume可以通过哪些node访问。

访问模式。和PV相同。

volume的挂载模式,可以为Filesystem或block。

约定声明PV的大小等参数。

用于限制volume,只有label匹配的volume才能绑定到PVC上。可以使用 matchLabels 或者 matchExpressions 来约束。

用于实现动态供给。只有StorageClassName相同的PV和PVC才能够绑定到一起。如果PVC的StorageClassName设置为"",那么它只会和StorageClassName也为""的PV绑定到一起。

创建StorageClass的时候如果将它的 storageclass.kubernetes.io/is-default-class annotation设置为true,那么此StorageClass会成为默认的StorageClass。如果PVC没有指定StorageClassName,那么它会和StorageClassName为默认StorageClass的PV绑定到一起。当然,使用这个特性必须要开启DefaultStorageClass的admission plugin。

如果没有启动这个admission plugin。没有指定StorageClass的PVC只能和没有指定StorageClass的PV绑定在一起。没有指定StorageClass和设置StorageClass的值为"",含义是相同的。

这种类型的PV把数据储存在集群中某个节点上。

注意:nodeAffinity属性是必须要指定的,因为local模式一定要确定数据保存在哪个机器。

对应StorageClass如下:

⑼ microk8s上给Pod挂载NFS

团队新开发的区域医疗平台包含一个课件上传与播放模块,其实际的业务包含如下的步骤:

1.  县级和乡镇卫生院的医生们通过在线视频参加培训、并录制视频。

2. 医生上传视频,并共享课件。

3.  平台上的其他医生可以在课件学习栏目学习录制的培训会议。

通常,课件的上传和保存我们都是通过对象存储做的,对象存储的好处显而易见:不担心文件丢失(三份备份), 不担心容量(云服务商集群),https/http访问, 数据安全(对象访问签名);  但是这个平台需要部署到区域医疗机构的机房里,多数情况下是没有对象存储的,外购对象存储也成本过高, 所以我们采用了折中的方案,存储系统换为NFS, 只需要一个大存储量的机器就可以了,大概服务如下:

我们开发了一个uploader服务,用于上传文件,同时使用Nginx提供http/https服务,两个服务之间共享存储,使用NFS存储挂载给他们。

这里我们来看看怎么给microk8s上的pod挂载NFS存储。

首先,我们需要安装NFS server 用于测试

我们使用ubuntu来进行测试,先执行命令:sudo apt install nfs-kernel-server

这个命令将安装服务器端,以及所有相关的包:

在home目录下创建一个nfsshare的文件夹用作共享目录。然后我们来编辑nfs配置文件,配置该共享目录,默认允许所有IP段挂在:

启动nfs: sudo /etc/init.d/nfs-kernel-server start

可以使用服务命令查看服务状态: service nfs-kernel-server   status

使用ip addr命令查看以下当前主机的IP:

现在我们来使用nfsclient端测试一下:

sudo mount 10.0.2.15:/home/nfsshare   /mnt

查询 /mnt 目录,可以看到在 /home/nsshare下面创建的文件和子目录

测试完后umount 挂载点:  sudo umount -v /mnt

1. 先写一个PV, 用来表示可以挂载的NFS存储:

2. 接着写一个PVC,用于绑定PV:

3. 然后写包装了nginx的存储服务的deployment文件:

4. 最后写存储服务对应的service文件:

完成了所有配置文件,使用microk8s kubectl apply -f 命令,依次创建资源对象。

查询创建的pod:

使用exec 登陆docker,

查询/usr/share/storage目录,如下图,nfs已经挂载好了,可以看见我们在test目录下创建了几个文件:

最后,我们来验证一下http方式访问文件

现在storage的nfs目录下创建两个子目录,attachement、video , 对应docker的挂在路径为: /usr/share/storage/atttachment、/usr/share/storage/video。 

在两个文件夹下面,分别创建两个文件 helloA.txt  helloB.txt, 并随意写写内容。

完成后我们通过30080端口,从microk8s节点的浏览器访问两个文件:

至此,在k8s下,给pod挂在nfs的工作,并通过http访问的任务就完了。另外:

1.   后续需要考虑,通过Lua写一个脚本和nginx集成,实现访问资源签名验证,这个机制可以很容易的参考对象存储的验证。

2. 这里没有讨论,如何写upload和制作storage服务的镜像,upload服务也需要挂载nfs,原理是一样的,所以就不再讨论。 storage服务是基于Nginx镜像实现,下面的附录了带上了可参考的配置文件。

==============================================================

附录A: storageservice服务中,nginx的配置文件storage.conf

附录B:  storageservice服务中dockerfile文件

附录C: Storageservice的build.gradle文件

参考 一个Springboot项目的build.gradle和Dockerfile ,  这里的buiild.gradle文件不需要java build, 仅需要用来生成新docker镜像。

⑽ k8s分布式存储-Ceph

RADOS

Librados

Crush

Pool

PG

Object

Pool、PG和OSD的关系

OSD

块存储( RBD )

文件存储( CephFS )

对象存储( Object )

关闭防火墙

关闭selinux

关闭 swap

根据规划设置主机名

添加 hosts

设置文件描述符

时间同步

配置 SSH 免交互认证

1、创建rbd使用的pool

2、指定存储池使用存储类型

3、创建一个块设备

3、查看块设备

1、禁用当前系统内核不支持的feature

2、映射(任意节点操作)

3、格式化块设备

4、mount到本地

5、取消块设备和内核映射

6、删除RBD块设备

1、拷贝配置文件和秘钥

2、安装 Ceph 客户端

3、剩余操作就与本地挂载操作一样了

1、创建快照

2、列出创建的快照

3、还原快照

4、重新映射并挂载验证

5、删除快照

1、创建一个块设备

2、创建快照

3、设置快照处于被保护状态

4、通过快照克隆一个新块设备

5、将克隆的快照独立于父设备

挂载本地目录

fuse方式挂载

**全部统一命名空间到 ceph-csi **

k8s节点安装 Ceph 客户端

csi-config-map.yaml

storageclass

secret

启动验证

rbd-pod-test.yaml

测试

**全部统一命名空间到 ceph-csi **

k8s节点安装 Ceph 客户端

csi-config-map

storageclass

secret

启动验证

ceph-cephfs-test

测试