本文是介绍Kubernetes的基本概念的系列文章之一, 在第一篇文章中,咱们简略介绍了长久卷(Persistent Volumes)。在本文中,咱们将学习如何设置数据持久性,并将编写Kubernetes脚本以将咱们的Pod连贯到长久卷。在此示例中,将应用Azure文件存储(Azure File Storage)来存储来自咱们MongoDB数据库的数据,但您能够应用任何类型的卷来实现雷同的后果(例如Azure Disk,GCE长久磁盘,AWS弹性块存储等)。

如果你想全面理解K8S其余概念的话,能够先查看此前公布的文章。

请留神:本文提供的脚本不限定于某个平台,因而您能够应用其余类型的云提供商或应用具备K3S的本地集群实际本教程。本文倡议应用K3S,因为它十分轻,所有的依赖项被打包在单个二进制中包装大小小于100MB。它也是一种高可用的认证的Kubernetes发行版,用于在资源受限环境中的生产工作负载。想理解更多信息,请查看官网文档:

https://docs.rancher.cn/k3s/

后期筹备

在开始本教程之前,请确保已装置Docker。同时装置Kubectl(如果没有,请拜访以下链接装置:

https://kubernetes.io/docs/tasks/tools/#install-kubectl-on-windows

在kubectl Cheat Sheet.中能够找到整个本教程中应用的kubectl命令:

https://kubernetes.io/docs/reference/kubectl/cheatsheet/

本教程中,咱们将应用Visual Studio Code,您也能够应用其余的编辑器。

Kubernetes长久卷能够解决什么问题?

请记住,咱们有一个节点(硬件设施或虚拟机)和在节点外部,咱们有一个Pod(或多个Pod),在Pod中,咱们有容器。Pod的状态是临时的,所以他们诡秘莫测(时常会被删除或从新调度等)。在这种状况下,如果你想在Pod被删除之后曾经保留其中的数据,你须要数据挪动到Pod内部。这样它就能够独立于任何Pod存在。此外部地位称为卷,它是存储系统的形象。应用卷,您能够在多个Pod放弃长久化状态。

什么时候应用长久卷

当容器开始被广泛应用时,它们旨在反对无状态工作负载,其持久性数据存储在其余中央。从那时起,人们做了很多致力以反对容器生态系统中的有状态利用。

每个我的项目都须要某种数据持久性,因而,您通常须要一个数据库来存储数据。但在简洁的设计中,你不想依赖具体的实现;您想写一个尽可能能够重复使用和独立于平台的应用程序。

始终以来,始终须要向应用程序暗藏存储实现的详细信息。但当初,在云原生利用的时代,云提供商创立了的环境中,想要拜访数据的应用程序或用户须要与特定存储系统集成。例如,许多应用程序间接应用特定存储系统,诸如Amazon S3、AzureFile或块存储等,这造成了不衰弱的依赖。Kubernetes正在尝试通过创立一个名为长久卷的形象来扭转这一状况,它容许云原生应用程序连贯到各种云存储系统,而无需与这些零碎建设明确的依赖关系。这能够使云存储的耗费更加无缝和打消集成老本。它还能够更容易地迁徙云并采纳多云策略。

即便有时候,因为金钱,工夫或人力等客观条件的限度,你须要做出一些斗争,将你的应用程序与特定的平台或提供商间接耦合,您应该尽量避免尽可能多的间接依赖项。从理论数据库实现中解耦应用程序的一种办法(还有其余解决方案,但这些解决方案更加简单)是应用容器(和长久卷来避免数据失落)。这样,您的应用程序将依赖于形象而不是特定实现。

当初真正的问题是,咱们是否应该总是应用带有持久性卷的容器化数据库,或者哪些存储系统类型不应该在容器中应用?

何时应用长久卷并没有通用的黄金法令,但作为终点,您应该思考可扩展性和集群中节点失落的解决。

依据可扩展性,咱们能够有两种类型的存储系统:

  • 垂直伸缩——包含传统的RDMS解决方案,例如MySQL、PostgreSQL以及SQL Server
  • 程度伸缩——包含“NoSQL”解决方案,例如ElasticSearch或基于Hadoop的解决方案

像MySQL、Postgres、Microsoft SQL等垂直伸缩的解决方案不应进入容器。这些数据库平台须要高I / O、共享磁盘、块存储等,并且不能优雅地解决集群中的节点失落,这通常产生在基于容器的生态系统中。

对于程度伸缩的应用程序(Elastic、Cassandra、Kafka等),您应该应用容器,因为它们能够接受数据库集群中的节点失落,并且数据库应用程序能够独立地再均衡。

通常,您能够并且应该分布式数据库容器化,这些数据库应用冗余存储技术,能够接受数据库集群中的节点失落(Elasticsearch是一个十分好的例子)。

Kubernetes长久卷的类型

咱们能够依据其生命周期和配置形式对Kubernetes卷进行分类。

思考到卷的生命周期,咱们能够分为:

  • 长期卷,即与节点的生命周期严密耦合(例如ExpertDir或HostPath),如果节点开张,则删除它们的截阵数量。
  • 长久卷,即长期存储,并且与Ppd或节点生命周期无关。这些能够是云卷(如gcePersistentDisk、awselasticBlockStore、AzureFile或AzureDisk),NFS(网络文件系统)或Persistent
    Volume Claim(一系列形象来连贯到底层云提供存储卷)。

依据卷的配置形式,咱们能够分为:

  1. 间接拜访
  2. 动态配置
  1. 动静配置

间接拜访长久卷

在这种状况下,Pod将间接与Volume耦合,因而它将晓得存储系统(例如,Pod将与Azure存储帐户耦合)。该解决方案与云无关,它取决于具体实施而不是形象。因而,如果可能的话尽量避免这样的解决方案。它惟一的长处是速度快,在Pod中创立Secret,并指定应应用的Secret和确切的存储类型。

创立Secret脚本如下:

apiVersion: v1  kind: Secret  metadata:    name: static-persistence-secret  type: Opaque  data:    azurestorageaccountname: "base64StorageAccountName"    azurestorageaccountkey: "base64StorageAccountKey"

在任何Kubernetes脚本中,在第2行咱们指定了资源的类型。在这种状况下,咱们称之为Secret。在第4行,咱们给它一个名字(咱们称之为动态,因为它是由管理员手动创立的,而不是主动生成的)。从Kubernetes的角度来看,Opaque类型意味着该Secret的内容(数据)是非结构化的(它能够蕴含任意键值对)。要理解无关Kubernetes Secrets的更多信息,能够参阅Secrets Design Document和ConfigureKubernetes Secrets。

https://github.com/kubernetes/community/blob/master/contributors/design-proposals/auth/secrets.md

https://kubernetes.io/docs/concepts/configuration/secret/

在数据局部中,咱们必须指定帐户名称(在Azure中,它是存储帐户的名称)和Access键(在Azure中,抉择存储帐户下的“Settings ”,Access key)。别忘了两者应该应用Base64进行编码。

下一步是批改咱们的Deployment脚本以应用卷(在这种状况下,卷是Azure File Storage)。

apiVersion: apps/v1  kind: Deployment  metadata:    name: user-db-deployment  spec:    selector:      matchLabels:        app: user-db-app    replicas: 1    template:      metadata:        labels:          app: user-db-app      spec:        containers:          - name: mongo            image: mongo:3.6.4            command:              - mongod              - "--bind_ip_all"              - "--directoryperdb"            ports:              - containerPort: 27017            volumeMounts:              - name: data                mountPath: /data/db            resources:              limits:                memory: "256Mi"                cpu: "500m"        volumes:          - name: data            azureFile:              secretName: static-persistence-secret              shareName: user-mongo-db              readOnly: false

咱们能够发现,惟一的区别是,从第32行咱们指定了应用的卷,给它一个名称并指定底层存储系统的确切详细信息。secretName必须是先前创立的Secret的名称。

Kubernetes存储类

要理解动态或动静配置,首先咱们必须理解Kubernetes存储类。

通过StorageClass,管理员能够提供对于可用存储的配置文件或“类”。不同的类可能映射到不同服务质量级别,或备份策略或由集群管理员确定的任意策略。

例如,你能够有一个在HDD上存储数据的配置文件,命名为慢速存储,或一个在SSD上存储数据的配置文件,命名为疾速存储。这些存储的类型由供应者确定。对于Azure,有两种提供者:AzureFile和AzureDisk(区别在于AzureFile能够与Read Wriite Many拜访模式一起应用,而AzureDisk只反对Read Write Once拜访,当您心愿同时应用多个Pod时,这可能是不利因素)。您能够在此处理解无关不同类型的Storage Classes:

https://kubernetes.io/docs/concepts/storage/storage-classes/

以下是Storage Class的脚本:

kind: StorageClass  apiVersion: storage.k8s.io/v1  metadata:    name: azurefilestorage  provisioner: kubernetes.io/azure-file  parameters:    storageAccount: storageaccountname  reclaimPolicy: Retain  allowVolumeExpansion: true

Kubernetes预约义提供者属性的值(请参阅Kubernetes存储类)。保留回收策略意味着在咱们删除PVC和PV之后,未革除理论存储介质。咱们能够将其设置为删除和应用此设置,一旦删除PVC,它也会触发相应的PV以及理论存储介质(此处理论存储是Azure文件存储)的删除。

长久卷及Persistent Volume Claim

Kubernetes对每一个传统的存储操作流动(供给/配置/附加)都有一个匹配的原语。长久卷是供给,存储类正在配置,并且长久卷Claim是附加的。

来自初始文档:

*Persistent Volume(PV)是集群中的存储,它已由管理员配置或应用存储类动静配置。
Persistent Volume Claim(PVC)是用户存储的申请。它相似于Pod。Pod耗费节点资源与PVC耗费PV资源是相似的。Pod能够申请特定的资源级别(CPU和内存)。Claim能够申请特定的大小和拜访模式(例如,它们能够装置一次读/写或屡次只读)。
这意味着管理员将创立长久卷以指定Pod能够应用的存储大小、拜访模式和存储类型。开发人员将创立Persistent Volume Claim,要求提供一个卷、拜访权限和存储类型。这样一来,在“开发侧”和“运维侧”之间就有了显著的辨别。开发人员负责要求必要的卷(PVC),运维人员负责筹备和配置要求的卷(PV)。
动态和动静配置之间的差别是,如果没有长久卷和管理员手动创立的Secret,Kubernetes将尝试主动创立这些资源。*

动静配置

在这种状况下,没有手动创立的长久卷和Secret,因而Kubernetes将尝试生成它们。Storage Class是必要的,咱们将应用在前文中创立的Storage Class。

PersistentVolumeClaim的脚本如下所示:

apiVersion: v1  kind:Persistent Volume Claim  metadata:    name: persistent-volume-claim-mongo  spec:    accessModes:      - ReadWriteMany    resources:      requests:        storage: 1Gi    storageClassName: azurefilestorage

以及咱们更新的Deployment脚本:

apiVersion: apps/v1  kind: Deployment  metadata:    name: user-db-deployment  spec:    selector:      matchLabels:        app: user-db-app    replicas: 1    template:      metadata:        labels:          app: user-db-app      spec:        containers:          - name: mongo            image: mongo:3.6.4            command:              - mongod              - "--bind_ip_all"              - "--directoryperdb"            ports:              - containerPort: 27017            volumeMounts:              - name: data                mountPath: /data/db            resources:              limits:                memory: "256Mi"                cpu: "500m"        volumes:          - name: data            Persistent Volume Claim:              claimName: persistent-volume-claim-mongo

如你所见,在第34行中,咱们通过名称援用了先前创立的PVC。在这种状况下,咱们没有手动为它创立长久卷或Secret,因而它将主动创立。

这种办法的最重要的劣势是您不用手动创立PV和Secret,而且Deployment是与云无关的。存储的底层细节不存在于Pod的spec中。然而也有一些毛病:您无奈配置存储帐户或文件共享,因为它们是主动生成的,并且您无奈重复使用PV或Secret ——它们将为每个新Claim从新生成。

动态配置

动态和动静配置之间的惟一区别是咱们手动创立动态配置中的长久卷和Secret。这样,咱们就能够齐全管制在集群中创立的资源。

长久卷脚本如下:

apiVersion: v1  kind: PersistentVolume  metadata:    name: static-persistent-volume-mongo    labels:      storage: azurefile  spec:    capacity:      storage: 1Gi    accessModes:      - ReadWriteMany    storageClassName: azurefilestorage    azureFile:      secretName: static-persistence-secret      shareName: user-mongo-db      readOnly: false

重要的是,在第12行咱们按名称援用Storage Class。此外,在第14行咱们援用了Secret,用于拜访底层存储系统。

本文更举荐这个解决方案,即便它须要更多的工作,但它是与云无关的(cloud-agnostic)。它还容许您利用无关角色(集群管理员与开发人员)的关注点拆散,并让您管制命名和创立资源。

总结

在本文中,咱们理解了如何应用Volume长久化数据和状态,并提出了三种不同的办法来设置零碎,即为间接拜访、动静配置和动态配置,并探讨了每个零碎的优缺点。

作者简介

Czako Zoltan,一位经验丰富的全栈开发人员,在包含前端,后端,DevOps,物联网和人工智能等多个畛域都领有丰盛的教训。