k8s 卷存储

应用场景

pod 中的容器的数据随着pod 的重启,删除就会消失,有的应用场景需要持久化数据,这时就需要卷挂载。

Tips:

volumes  是 pod 的一个组成部分, 因此像容器一样在 pod 的规范中就定义了。 它们不是独立的 Kubernetes 资源对象, 也不能单独创建或删除。 pod 中的所有容器都可以使用卷, 但必须先将它挂载在每个需要访问它的容器中。 在每个容器中, 都可以在其文件系统的任意位置挂载卷。

常见的类型

empty   一  用于存储临时数据的简单空目录。
 
hostPath — 用于将目录从工作节点的文件系统挂载到pod中
 
gitRepo  一 通过检出Git仓库的内容来初始化的卷。
 
nfs  —  挂载到pod中的NFS共享卷。
 
configMap secret downwardAPI 一 用于将 Kubemetes 部分资源和集群信息公开给 pod 的特殊类型的卷

empty 配置

emptyDir类型的Volume在Pod分配到Node上时被创建,Kubernetes会在Node上自动分配一个目录,因此无需指定宿主机Node上对应的目录文件。 这个目录的初始内容为空,当Pod从Node上移除时,emptyDir中的数据会被永久删除。emptyDir Volume主要用于某些应用程序无需永久保存的临时目录,多个容器的共享目录等。

在Pod中的定义

apiVersion: vl 
kind: Pod 
metadata: 
    name: fortune 
spec: 
  containers: 
- image: luksa/fortune                       #第一个容器名为 html-asdf
  name: html-asdf 
  volumeMounts: 
  - name: html                               #容器挂载的本地卷为 html
    mountPath: /var/htdocs                   #挂载到容器的此目录
    
- image: nginx:alpine 
  name: web-server                           #第二个容器称为 web-server
  volumeMounts : 
  - name: html                               #容器挂载的本地卷为 html
    mountPath: /usr/share/nginx/html         #设为只读 
    readOnly: true 
  ports: 
  - containerPort: 80 
    protocol: TCP 

volumes 
- name: html                                 #命名为html
  emptyDir: {}                               #卷的类型为emptyDir
View Code
指定用于 EMPTYDIR 的介质
作为卷来使用的 emptyDir ,是在承载 pod 工作节点的实际磁盘上创建的,此其性能取决于节点的磁盘类型。 但我们可以通知 Kubemete tmfs 文件系统存在内存而非硬盘创建 emptyDir 。因 此,将emptyDir medium 设置为 Memory
volumes: 
- name: html
  emptyDir
    medium: Memory
View Code

使用 Git 仓库作为存储卷

gitRepo 卷基本上也是 emptyDir 卷,它通过克隆 Git 仓库并在 pod启动时(但在创建容器之前 检出特定版本来填充数据)。gitRepo 容器就像 emptyDir 卷一样, 基本上是一个专用目录, 专门用于包含卷的容器并单独使用。
 
当 pod 被删除时, 卷及其内容被删除。 然而, 其他类型的卷并不创建新目录, 而是将现有的外部目录挂载到 pod 的容器文件系统中。 该卷的内容可以保存多个 pod 实例化

 

Notice:

在创 gitRepo 卷后,它并不能和对应 repo 保持同步,当向Git 仓库推送新增的提交时,卷中的文件将不会被更新。然而,如果所用 pod 是由 ReplicationController 管理的,删除这个 pod 将触发新建一个新的 pod ,而这个新 pod的卷中将包含最新的提交
apiVersion: vl 
kind: Pod 
metadata: 
  name: gitrepo-vol-pod
spec: 
  containers: 
  - image: nginx:alpine 
    name: web-server 
    volumeMounts : 
    - name : html
      mountPath: /usr/share/nginx/html 
      readOnly: true 
    ports: 
    - containerPort: 80
      protocol: TCP
  volumes:
  - name: html                                 #容器挂载的本地卷为 html
    gitRepo:
    repository: https://github.com/kzf/asdf-website-example.git
    revision: master 
    directory: . 
View Code

Tips: 

为了实现pod  gitrepo 目录与git 仓库实时同步可以通过 sidecar 容器

hostPath卷

hostPath 卷是一种持久性类型的存储。因为gitRepo 和 emptyDir 卷的内容都会在 pod 被删除时被删除, 而 hostPath 卷的内容则不会被删除。 如果删除了一个 pod, 并且下一个 pod 使用了指向主机上相同路径的 hostPath 卷, 则新 pod 将会发现上一个 pod 留下的数据, 但前提是必须将其调度到与第一个 pod 相同的节点上。

应用场景

大多数情况下都使用这种类型的卷来访问节点的日志文件、 kubeconfig (Kubemetes 配置文件)或CA 证书,有时会配合DaemonSet 使用。
正常情况没有一个pod 使用 hostPath 卷来存储自己的数据, 都是使用这种卷来访问节点的数据。 

使用持久化存储

当运行在一个 pod 中的应用程序需要将数据保存到磁盘上, 并且即使该 pod 重新调度到另 一个节点时也要求具有相同的数据可用。由于这些数据需要可以从任何集群节点访问, 因此必须将其存
储在某种类型的网络存储 (NAS) 中。

使用云厂商的存储

如果你的 Kubemetes 集群运行在 Google Kubemetes 引擎上所以需要创建 GCE persistent disk。当在其他地方运行 Kubemetes 集群时,应该根据不同的基础设施使用其他类型的卷。
例如,如果你的 Kubemetes 集群运行在 Amazon 的 AWS EC2 上,就可以使用 awsElasticBlockStore卷给你的 pod 提供持久化存储。如果集群在 Microsoft Azure 上运行,则可以使用 azureFile 或者 azureDisk卷。我们无法在这里详细介绍如何去实现,实际上是一样的。首先,需要创建实际的底层存储,然后在卷定义中设置适当的属性。
 
Amazon 的 AWS EC2 使用示例
apiVersion: vl 
kind: Pod 
metadata:
  name: mongodb 
spec: 
  volumes:
  - name: mongodb-data
    awsElasticBlockStore:
    volumeid: my-volume
    fsType: ext4
  containers:
  ...
View Code

使用NFS卷

如果集群是运行在自有的一组服务器上,那么就有大量其他可移植的选项用于在卷内挂载外部存储。例如,要挂载一个简单的NFS 共享,只需指定NFS服务器和共享路径。
volumes:
  - name: vol-name
    nfs:
      server: 1.2.3.4
      path: /somewhere/path
View Code

使用其他存储技术

其他的支持选项包括用于挂载ISCSI磁盘资源的iscsi, 用于挂载GlusterFS的glusterfs, 适用于RADOS块设备的rbd 还有flexVolume、cinder、cephfs、flocker、fc(光纤通道)等。rbd 如果你不会使用到它们,就不需要知道所有的信息。这里提到是为了展示Kubernetes支持广泛的存储技术,并且可以使用喜欢和习惯的任何存储技术。

从底层存储技术解耦pod(持久卷和持久卷声明)

到目前为止, 我们探索过的所有持久卷类型都要求 pod 的开发人员了解集群中可用的真实网络存储的基础结构。 例如, 要创建支持 NFS 协议的卷, 开发人员必须知道 NFS 节点所在的实际服务器。 这违背了 Kubernetes 的基本理念, 这个理念旨在向应用程序及其开发人员隐藏真实的基础设施, 使他们不必担心基础设施的具体状态, 并使应用程序可在大量云服务商和数据企业之间进行功能迁移。
 
在 Kubemetes 集群中为了使应用能够正常请求存储资源, 同时避免处理基础设施细节, 引入了两个新的资源, 分别是待久卷和持久卷声明

创建持久卷

持久卷不属于任何命名空间, 它跟节点一样是集群层面的资源。

apiVersion: vl 
kind: PersistentVolume 
metadata: 
    name: fortune 
spec:
  capacity:
    storage: lGi  
  accessModes:
  - ReadWriteOnce                                        #可以被单个客户端挂载为读写模
  - ReadOnlyMany                                         #式或者被多个客户端挂载为只读(这里指的是持久卷声明)
  persistentVolumeReclaimPolicy: Retain        #当声明被释放后,PersistentVolume 将会被保留(不清理和删除)
  gcePersistentDisk:                   #PersistentVolume指定支持之前创建的GCE持久磁盘
  pdName: asdf
  fsType: ext4
View Code

查看

$ kubectl get pv 
  NAME       CAPACITY  RECLAIMPOLICY ACCESSMODES   STATUS 
  mongodb-pv   lGi     Retain     RWO,ROX      Available 
View Code
 

通过创建持久卷声明来获取持久卷

持久卷声明是属于命名空间的资源对象,持久卷声明只能被同一命名空间内的 pod 创建使用

apiVersion: vl 
kind: PersistentVolumeClaim 
metadata: 
    name: fortune-pvc
spec:
  resources:
    requests:
      storage: lGi                       #申请1G 的存储空间
  accessModes:
  - ReadWriteOnce                        #可以被单个客户端挂载为读写模
  storageClassName: ""                   #将空字符串指定为存储类名可确保PVC 绑定到预先配置的 PV,而不是动态配置新的PV。关于动态配置pv 下文有介绍。
View Code

当创建好声明, kubernetes 就会找到适当的持久卷并将其绑定到声明 ,持久卷的容量必须足够大以满足声明的需求,并且卷模式必须包含声明中指定的访问模式 。在该示例中,声明请求 1GiB 的存储空间和 ReadWriteOnce 访问模式,之前创建的持久卷符合刚刚声明中 的这两个条件,所以它被绑定到对应的声明中。 

 

列举持久卷声明

$ kubectl get pvc 
  NAME     STATUS   VOLUME     CAPACITY   ACCESSMODES   AGE 
  mongodb-pvc Bound    mongodb-pv   lGi     RWO,ROX      3s
View Code
PVC 状态显示己与持久卷的 mongodb pv 绑定。请留意访问模式的简写:
  RWO ReadWriteOnce -- 仅允许单个节点挂载读写。
  ROM ReadOnlyMany  -- 仅允许多个节点挂载只读。
  RWX ReadWriteMany -- 允许多个节点挂载读写这个卷。
View Code
注意:RWO ROX RWX 涉及可以同时使用卷的工作节点的数量而并非 pod 数量

 

pod 中使用持久卷声明

持久卷现在已经可用了 ,除非先释放掉卷,否则没有人可以申明相同的卷。要pod 中使用持久卷,需要在pod 的卷中引用持久卷声明名称,如下面的代码清单所示
apiVersion: vl 
kind: Pod 
metadata: 
  name: mongodb
spec: 
  containers: 
  - image: mongo 
    name: mongodb 
    volumeMounts: 
    - name : mogodb-data
      mountPath: /data/db 
    ports: 
    - containerPort: 27017 
      protocol: TCP 
  volumes: 
  - name: mongodb-data 
    persistentVolumeClaim: 
    claimName: mongodb-pvc
View Code

 针对持久卷的回收有两种方式:自动回收,手动回收。

持久卷的动态卷配置

使用持久卷和持久卷声明可以轻松获得持久化存储资源,无须研发人员处理下面实际使用的存储技术,但这仍然需要一个集群管理员来支持实际的存储。幸运的是, kubernetes 还可以通过动态配置持久卷来自动执行此任务。
与管理员预先提供一组持久卷不同的是,它们需要定义一个或两个(或多个)StorageClass 并允许系统在每次通过持久卷声明请求时自动创建1个新的持久卷。最重要的是,不可能耗尽持久卷(很明显 ,你可以用完存储空间)
 

StorageClass 资源定义

apiVersion: vl 
kind: StorageClass 
metadata: 
    name: fast
provisioner: kubernetes.io/gce-pd      #用于配置持久卷的插件
parameters:
  type:pd-ssd                  #传递给parameters的参数
  zone:europe-westl-b
View Code
Tips: kubernetes  包括最流行的云服务提供商的置备程序 provisioner ,所以管理员并不总是需要创建一个置备程序。 但是如果 kubernetes 部署在本地,则需要配置定制的置备程序。
 
运行机制
StorageClass 资源指定当持久卷声明请求此 StorageClass 时应使用哪个置备程序来提供持久卷 StorageClass 定义中定义的参数将传递给置备程序并具体到每个供应器插件。 StorageClass 使用 GCE 持久磁盘的预配置器,这意味着当 Kubernetes  在GCE 中运行时可供使用。对于其他云提供商,需要使用其的置备程序
 

创建一个请求特定存储类的 PVC 定义 

vi storageclass.yaml
  apiVersion: vl 
  kind: PersistentVolumeClaim 
  metadata: 
      name: mongodb-pvc
  spec:
    storageClassName:fast                #该pvc请求自定义存储类
    resources:
      requests
        storage: lGi                        #申请1G 的存储空间
    accessModes:
    - ReadWriteOnce                        #可以被单个客户端挂载为读写模

随后查看会发现自动生成了一个持久卷
$ kubectl get pv
  NAME      CAPACITY   ACCESSMODES  RECLAIMPOLICY   STATUS  STORAGECLASS
  pvc-le6bc048  lGi      RWO        Delete       Bound   fast
 
 
可以看到动态配置的持久卷其容量和访问模式是在PVC中所要求的 。它的回收策略是 Delete,这意味着当PVC被删除时,持久卷也将被删除。
除了 PV置备程序还提供了真实的存储空间,fast StorageClass 被配置为使用 kubernetes.io/gce-pd 从而提供了GCE 持久磁盘。
 
可以使用以下命令查看磁盘
  $ gcloud compute disks list  
    NAME                ZONE        SIZE_GB     TYPE        STATUS
    kekub-dy-pvc-le6bc04      europe-westl-d   1        pd-standard     READY
 
 
如上所示例 盘的名称表明它是动态配置的, 同时 类型显示为一个 SSD,正如在前面创建的存储类中所指定的那样。
 
View Code

注意 如果在 PVC 中引用一个不存在的存储类, PV 的配直将失败(在 PVC 上使用 kubectl describe 时,将会看到 ProvisioningFailed 事件)

 了解存储类的使用

集群管理员可以创建具有不同性能或其他特性的多个存储类,然后研发人员再决定对应每一个声明最适合的存储类。
StorageClasses 的好处在于,声明是通过名称引用它们的,因此只要 StorageClass名称在所有这些名称中相同, PVC 定义便可跨不同集群移植
 
列出存储类
$ kubectl get sc 
  NAME           TYPE 
  fast            kubernetes.io/gce-pd 
  standard (default)   kubernetes.io/gce-pd
View Code

 Notice:

1、如果持久卷 明没有明确指出要使用哪个存储类, 默认存储类会用于动态提供持久卷的内容。

2、如果尚未将 storageClassName 属性设置为空字符串, 则尽管已存在适当的预配置持久卷,但动态卷置备程序仍将配置新的持久卷。

 

动态持久卷的配置图

 

 

posted @ 2020-01-15 09:33  fanggege  阅读(849)  评论(1编辑  收藏  举报