Notice: Constant WP_DEBUG already defined in /var/www/html/wordpress/wp-content/plugins/changyan/sohuchangyan.php on line 12

Notice: Constant WP_DEBUG_LOG already defined in /var/www/html/wordpress/wp-content/plugins/changyan/sohuchangyan.php on line 13

Notice: Constant WP_DEBUG_DISPLAY already defined in /var/www/html/wordpress/wp-content/plugins/changyan/sohuchangyan.php on line 14
【转载】干货│Kubernetes Storage Management @eBay – zoues

LOADING

Follow me

【转载】干货│Kubernetes Storage Management @eBay
四月 28, 2017|DockerPaaS

【转载】干货│Kubernetes Storage Management @eBay

【转载】干货│Kubernetes Storage Management @eBay

干货│Kubernetes Storage Management @eBay


Kubernetes Storage Management @eBay

   

Author: Li, CY

干货│Kubernetes Storage Management @eBay

eBay

文章目录

一、前言

二、Kubernetes存储概念

(一)卷插件

(二)持久卷/持久卷请求

(三)动态卷供应

(四)卷的相关组件

三、Kubernetes存储在eBay的实践

(一)StorageClass的定义

(二)网络卷

(三)本地卷

(四)健康监督

四、展望

我从2015年底开始接触kubernetes,当时kubernetes比较适合无状态的(stateless)应用,这些应用几乎没有什么存储的需求,但是随着大数据应用在互联网的普及,业界有越来越多的呼声,想把大数据的应用,类似kafka、nosql database容器化,然后用kubernetes来管理,eBay内部这里需求也很强,所以我们做了一些kubernetes存储方面的研究和开发工作,在这里和大家分享一下。

本文第一部分首先介绍kubernetes存储方面的基本概念,包含卷插件(Volume Plugins),持久卷和持久卷请求(Persistent Volume/Persistent Volume Claims,PV/PVC),以及动态卷供应(Dynamic Volumes Provisioning)。

第二部分介绍eBay是如何运用kubernetes的这些特性来管理存储,包含如何定义存储类别(Storage Class),如何使用网络卷(Network Volume), 为什么要开发自己的本地卷(Local Volume),并且如何使用本地卷以及开发过程中的难点。

一、Kubernetes存储概念

01

卷插件

Volume Plugins

kubernetes中,卷(Volume),即一个能够被容器访问的目录,提供给Pod进行数据存储。Kubernetes定义了一组标准的Volume操作接口,不同的存储后端以一个插件(Plugin)的方式实现。

我们可以将Volume分为三大类:

01
网络卷

几乎可以支持目前绝大数的分布式文件系统和网络存储协议,包括cinder, nfs, rbd, iSCSI, cephfs, gcePersistentDisk, awsElasticBlockStore等等。 

02
本地卷

目前主要支持的有两类: emptyDir和hostPath。 

03
Expose Kubernetes API

这类volume主要是提供类似API接口的功能,如Secret Volume。 

一个Pod直接使用Cinder Volume的例子:

apiVersion: v1

kind: Pod

metadata:

  name: test-pd

spec:

  containers:

  – image: gcr.io/google_containers/test-webserver

    name: test-container

    volumeMounts:

    – mountPath: /cache

      name: cache-volume

volumes:

    – name: cache-volume

      cinder:

        volumeID: bd82f7e2-wece-4c01-a505-4acf60b07f4a

        fsType: ext4

这里CinderVolume需要预先申请好,得到它的UUID (如bd82f7e2-wece-4c01-a505-4acf60b07f4a), 并且写入到Pod的Spec中。这种Volume的使用方式,当Pod被删除后,volume也随之删除。如果用户希望Volume的生命周期独立于Pod的生命周期,那么需要使用到Kubernetes的持久卷(Persistent Volume)。

02

持久卷/持久卷请求 

Persistent Volume/Persistent Volume Claim

持久卷(Persistent VolumePV)的特性在Kubernetes官方文档的定义中最主要包含下面两点:

①PV是由管理员(Admin)创建的一块网络存储块 

②PV的生命周期独立于使用这个PV的Pod 

用户(user)在使用时只需要定义持久卷请求(Persistent Volume Claim,PVC),包含两个最基本的信息(size和access mode)即可。Kubernetes的Master节点循环监控新产生的PVC,找到与之匹配的PV,并把他们绑定在一起。

一个简单的PVC的例子:

kind: PersistentVolumeClaim

apiVersion: v1

metadata:

  name: myclaim

spec:

  accessModes:

    – ReadWriteOnce

  resources:

    requests:

      storage: 1Gi

整个过程如下:

干货│Kubernetes Storage Management @eBay

Figure 1 PV和PVC的使用过程

1

管理员创建PV。 

2

Kubernetes通过Volume plugin去Network Volume后端申请一块Volume。 

3

用户创建PVC, 指定所需Volume的size和 access mode 

4

C和系统中某个availKubernetes将PVable的PV绑定。 

5

用户创建一个包含PVC的Pod 

6

Kubernetes将Network Volume attach到Pod所在的节点(Node), 并且在Pod创建后将Volume挂载到Pod中。 

03

动态卷供应

Dynamic Volumes Provisioning

在上面这个PV/PVC的使用过程中,我们看到有两个问题:

①管理员必须预先创建好PV, 用户才可以使用。

②在一个Cluster中,无法使用两种Network Volume 后端。

要解决前面PV/PVC碰到的问题, Kubernetes提出了 Dynamic Volumes Provisioning的概念。它最大的好处是用户在创建PVC的时候,系统可以自动的创建PV。同时Kubernetes引入了一个StorageClass的Object,来描述存储的分类。不同的分类可以对应不同的后端、不同的质量服务Qos等级、备份策略和其他自定义的策略。

kind: StorageClass

apiVersion: storage.k8s.io/v1beta1

metadata: 

  name: cinder-standard

provisioner: kubernetes.io/cinder

parameters: 

  type: standard

创建指定相应的StorageClass的PVC:

kind: PersistentVolumeClaim

volume.alpha.kubernetes.io/storage-class: “cinder-standard”

有了Dynamic Volumes Provisioning 之后,用户在使用Persistent Volume就变的比较方便了。

干货│Kubernetes Storage Management @eBay

Figure 2 Dynamic volumes provisioning

1

管理员创建StorageClass,指定StorageClassProvisioner, 比如是cinder

2

用户创建PVC, 指定所需Volume的size和 access mode, 以及StorageClass。 

3

Kubernetes根据PVC中指定的StorageClass, 找到系统中的定义,并且创建与Provisioner相对应的PV。 

4

创建PV后,Kubernetes调用对应的Volume Plugin去申请Network Volume。 

5

然后Kubernetes将PVC和新建的PV相绑定。 

6

用户创建一个包含PVC的Pod。 

7

Kubernetes将Network Volume attach到Pod所在的Node, 并且在Pod创建后将Volume挂载到Pod中。 

04

卷的相关组件

Kubernetes Components for Volumes

在这章的最后,我们看一下Kubernetes中与Volume相关的模块:

Volume 相关的模块主要在Kube-controller-manager和Kubelet里。

Volume Plugins在Kube-controller-manager和Kubelet中都注册了,每个Plugin为自己的存储后端实现了attach/detach, mount/unmount, provision, recycle, delete等一组标准操作。

在Kube-controller-manager中有两个Volume相关的controllers, Persistent Volume controller主要是通过apiserver 接口监控PV/PVC object在etcd中的变化,然后进行PV和PVC相互绑定和解绑定的操作;AttachDetach controller监控etcd中Pod, PV的相应变化对Network Volume进行attach或者detach到Node的操作。

在Kubelet中有一个Volume Manager controller, 它的功能主要是监控etcd中Pod, PV的变化,然后调用Volume Plugin的接口进行mount和umount操作。

干货│Kubernetes Storage Management @eBay

Figure 3 volume的相关组件

          二、Kubernetes存储在eBay的实践

01

StorageClass的定义

StorageClass Definition

eBay根据Volume不同的性能, 主要指标是IOPSThroughput,定义了三类Storage Classes, 用户可以根据自己应用的IO特性来选择Storage Class, 而不用关心后端的实现方式。

Storage Class

IOPS/Throughput

Use Cases

Storage Solutions

Hot Tier

>50K IOPS

500 MB/s

NoSQL,
eBay In-house App

Local SSD

Warm

Tier

10000 IOPS

300 MB/s

Hadoop, Kafka

SolidFire,
Local HDD

Standard Tier

300 IOPS

150 MB/s

Archive

Ceph HDD based

在实际中,我们提供了Network Volume和Local Volume的两种方式,分别是SolidFire和Ceph HDD的存储后端和Local SSD的存储后端,满足客户的不同的需求。

02

网络卷

Network Volume

在Kubernetes里,若Pod使用Network Persistent Volume, Pod无论怎么重启,被调度到任意一个Node上,它使用的Network Volume都可以被挂载到Pod上。因此使用Network Volume是最方便的,也是我们首先推荐给用户的。

在eBay, 我们选择Cinder Volume来作为Kubernetes的 Network Volume, 因为我们已经有一个很成熟的Openstack Cloud平台, 目前我们Kubernetes Nodes都是从Openstack Cloud里申请出来的VMs。

Cinder Volume Plugin是eBay在2015向Kubernetes社区贡献的, 目前Cinder Volume在Kubernetes 里已经比较成熟, 我们使用的方式和前一章Figure 2 中描述的流程一样。同时我们定义了两个Storage Classes, 为用户提供不同性能的Volume。

01
cinder-performance

后端是SolidFire的存储,提供Warm Tier较高性能的存储。

02
cinder-standard

后端是Ceph HDD的存储, 提供Standard Tier的存储

03

本地卷

Local Volume

动机

虽然在Kubernetes里已经有很完善的Network Volume的支持,但是很多大数据的用户还是希望能够使用Local SSD, 最主要的原因还是Local SSD和Network Volume 相比较还是有很大的性能优势,如Fingure 4显示,在IO延时方面,Local SSD比SolidFire的延时要小8倍左右。

同时从availability的角度考虑,很多大数据的应用例如Kafka, MogoDB, 都可以在应用层做Replica来做数据的备份,因此一个SSD磁盘的损坏并不会影响到应用程序。

干货│Kubernetes Storage Management @eBay

Figure 4  I/O延时比较

Kubernetes目前支持两种Local Volume,即emptyDir和hostPath,但是它们都不支持PV/PVC这种使用方式, 同时这两种Volume在磁盘数据写入大小以及读写性能方面都是没有保证的。

基于用户的需求以及目前Kubernetes对Local Volume的支持现状,我们开发了自己的Local Volume。

实现

在Local Volume实现方面,我们做了这几部分:

第一步:Volume Plugin

首先实现了一个LocalVolume Plugin,支持将整个磁盘(disk) 或者是一个磁盘分区(disk partition)来作为一个volume进行分配与绑定。同时也支持LVM模式, 能在一个VG下申请lv用做volume, plugin里主要包含的mounter, unmounter, provisioner, recycler, delete等接口的实现。

第二步:Persistent Volume

支持PV/PVC, 在PersistentVolume的PersistentVolumeSource里增加了LocalVolume。

然后为dynamic volume provisioning 提供了两个Storage Classes, 分别支持disklvm

第三步:Sheduling

在scheduling方面亦有所改动,LocalVolume和其它Network Volume 不一样,应为它是和Node绑定的,一旦选择了Volume也就是选择了Node。所以我们需要在Pod Scheduler里增加了一个predicate function, 也就是在Pod调度的时候需要看Node上有没有LocalVolume资源,此外还要在Persistent Volume controller里,PVC绑定PV的时候要考虑一些LocalVolume特殊的情况。

干货│Kubernetes Storage Management @eBay

Figure 5 Local Volume的组件

示例

示例1, 用户Pod直接使用LocalVolume

apiVersion: v1

kind: Pod

metadata:

  name: ld-test

spec:

  containers:

  – image: busybox

    command:

    – sleep

    – “3600”

    imagePullPolicy: IfNotPresent

    name: ld-test

    volumeMounts:

    – mountPath: /mnt/disk1

      name: test-vol1

    – mountPath: /mnt/disk2

      name: test-vol2

  volumes:

    – localVolume:

         type: disk

    name: test-vol1

    – localVolume:

         type: disk

    name: test-vol2

  restartPolicy: Always

示例2, 管理员建好StorageClass, 用户Pod使用LocalVolume PVC

kind: StorageClass

apiVersion: storage.k8s.io/v1beta1metadata: 

  name: local-ssd

provisioner: kubernetes.io/local-volume

parameters: 

  type: disk

apiVersion: v1

kind: PersistentVolumeClaim

metadata:

  name: myclaim

  annotations:

    volume.beta.kubernetes.io/storage-class:”local-ssd”

spec:

accessModes:

ReadWriteOnce

resources:

  requests:

    storage: 100Gi

apiVersion: v1

kind: PersistentVolumeClaim

metadata:

  name: myclaim

  annotations:

    volume.beta.kubernetes.io/storage-class:”local-ssd”

spec:

accessModes:

ReadWriteOnce

resources:

  requests:

    storage: 100Gi

难点

在实现Local Volume的时候,有几个问题需要特别的解决。

Volume回收

在用户将PVC删除的时候,需要将对应Volume上的数据删除。对于Network Volume, 只要在删除PVC的时候把对应的PV也删除就行了,但是对于Local Volume 需要到指定的Node, 把指定磁盘上的数据删除, 问题在于接受处理PVC删除的是在Master的kube-controller-manager上,而数据在某个Node上。

目前采用的方法是:创建一个特殊Pod,指定Pod调度到需要的Node上删除指定磁盘上的数据。

一个Pod使用多个LocalVolume PVC

当一个Pod需要同时用几个LocalVolume时,会创建几个PVC。我们需要保证这几个PVC所绑定的LocalVolume PV都在同一个Node上。


目前采用的方法是:在PVC中加入一个groupannotation, 里面包含group namecount, 在进行PVCPV绑定的时候,只有同一个group namePVC数目达到count指定的数目时,才做绑定操作并且保证被绑定的Local Volume都在同一个Node上。

annotations:

    volume.beta.kubernetes.io/storage-class:”local-ssd”

    volume.beta.kubernetes.io/group: ‘{“name”:”group1″, “count”:”2″}

反关联(Anti-affinity)

用户在部署应用的时候,考虑到可用性(availability )往往会有anti-affinity的需求,同一类的Pod需要在不同的Node或者不同的Rack上,这个功能在Kubernetes Pod上已经实现了,但是一旦使用LocalVolume PVC, 就会把anti-affinity的选择提前到PVC与PV绑定的阶段。

目前采用的方法是:在PVC上加上了anti-affinity的annotation :

annotations:

    volume.beta.kubernetes.io/storage-class:”local-ssd”

    volume.alpha.kubernetes.io/antiaffinity: ‘{“labelSelector”:{ “matchLabels”:{ “key”:”ssdtest” } }, “topologyKey”:”kubernetes.io/hostname”}’

04

健康监控

Health Monitoring

健康监控对于生产环境来说总是不可或缺的,对于Kubernetes存储的监控,Network Volume 和 Local Volume有不同的侧重。

Network Volume, 由于使用Cinder Volume,  我们关心的指标是Volume可以attach到Node或者从Node 上detach的成功率,以及attach/detach所花费的时间。

Local Volume, 我们关心的是本地磁盘是否有故障,使用了raid和磁盘检测工具来查看。

不论是哪种检测,最后的指标都是以Prometheus的格式向外输出,如Figure 6所示。

干货│Kubernetes Storage Management @eBay

Figure 6 Health Monitoring

干货│Kubernetes Storage Management @eBay

展望

Future Work

我们在Kubernetes 存储上还有很多工作要做。例如,对于Network Volume, 我们需要在裸机(Bare Mental, BM)上支持Cinder的接口,还需要支持共享文件系统(shared filesystem)。

对于Local Volume, 我们需要再慎重考量PVPVC的绑定是应该在kube-scheduler中还是在Persistent Volume controller里。进一步,我们还需要支持把raw disk device直接暴露给用户的Pod。

干货│Kubernetes Storage Management @eBay

干货│Kubernetes Storage Management @eBay

no comments
Share