CephJCloud

Ceph在Kubernetes中的一些应用

2017-03-24  本文已影响2590人  魔哈Moha

很抱歉,前两周我还在说没发现Kubernetes有扩展API来对接Ceph创建RBD卷,这两天翻阅文档才看到原来Kubernetes已经在1.2的Alpha中支持了,在1.4中就release这个特性。

StoragaClass

StoragaClass,从表面上看像是在Kubernetes资源中定义了一个存储的方法。官方wiki介绍如下:

Each StorageClass contains the fields provisioner and parameters, which are used when a PersistentVolume belonging to the class needs to be dynamically provisioned.The name of a StorageClass object is significant, and is how users can request a particular class. Administrators set the name and other parameters of a class when first creating StorageClass objects, and the objects cannot be updated once they are created.Administrators can specify a default StorageClass just for PVCs that don’t request any particular class to bind to: see the PersistentVolumeClaim section for details.

简单来说,每个StorageClass包括provisionerparameters两个资源,当PV需要绑定动态卷的时候便会用到。

那么什么是provisionerparameters?

Provisioner

Storage classes have a provisioner that determines what volume plugin is used for provisioning PVs. This field must be specified. During beta, the available provisioner types are kubernetes.io/aws-ebs and kubernetes.io/gce-pd.

Storage Classes中的provisioner字段决定着部署PV的插件。

Parameters

Storage classes have parameters that describe volumes belonging to the storage class. Different parameters may be accepted depending on the provisioner. For example, the value io1, for the parameter type, and the parameter iopsPerGB are specific to EBS. When a parameter is omitted, some default is used.

Storage Classes 的parameter字段用来描述属于该storage class的volume。不同的provisioner其参数也不同。简单来说就是存储的配置信息。

目前StorageClass也封装好了几类存储的实现方法;

本文着重引用Ceph RBD的方式来做实例,环境还是写前两片文章用到的那个Ceph测试环境

Ceph RBD

  apiVersion: storage.k8s.io/v1beta1
  kind: StorageClass
  metadata:
    name: ceph-chengdu
  provisioner: kubernetes.io/rbd
  parameters:
    monitors: 192.168.68.53:6789,192.168.68.54:6789,192.168.68.57:6789
    adminId: kube
    adminSecretName: ceph-secret
    adminSecretNamespace: kube-system
    pool: kube
    userId: kube
    userSecretName: ceph-secret

关于Ceph的Secret可以参看以前的文章,将Ceph的keyring导入进去就好了。简单介绍下storageclass里字段的含义

创建PVC

在导入StoragaClass后,就可以在创建PVC里面引用这个方法了。

 {
  "kind": "PersistentVolumeClaim",
  "apiVersion": "v1",
  "metadata": {
    "name": "magine1989",
    "annotations": {
        "volume.beta.kubernetes.io/storage-class": "ceph-chengdu"
    }
  },
  "spec": {
    "accessModes": [
      "ReadWriteOnce"
    ],
    "resources": {
      "requests": {
        "storage": "10Gi"
      }
    }
  }
}

我这里定义了一个名叫magine1989的RBD块,其容量为10G。简单看下PVC和Ceph的状态。

$ kubectl get pvc
NAME                 STATUS    VOLUME                                     CAPACITY   ACCESSMODES   AGE
magine1989           Bound     pvc-0023420f-103d-11e7-9489-52540095b1e1   10Gi       RWO           3h

$ kubectl get pv
NAME                                       CAPACITY   ACCESSMODES   RECLAIMPOLICY   STATUS    CLAIM                        REASON    AGE
pvc-0023420f-103d-11e7-9489-52540095b1e1   10Gi       RWO           Delete          Bound     default/magine1989                     4h

$ rbd ls kube --name client.kube
kubernetes-dynamic-pvc-eca2e400-103c-11e7-b8c8-52540095b1e1

$ rbd info kube/kubernetes-dynamic-pvc-eca2e400-103c-11e7-b8c8-52540095b1e1 --name client.kube
rbd image 'kubernetes-dynamic-pvc-eca2e400-103c-11e7-b8c8-52540095b1e1':
    size 10240 MB in 2560 objects
    order 22 (4096 kB objects)
    block_name_prefix: rb.0.c3b7.2ae8944a
    format: 1

可以看到在创建pvc的时候,k8s已经帮我们在Ceph的存储池里面创建一个10G的RBD块,然后创建好PV后绑定上该PVC。这样一来用户在申请PVC的时候就更方便了,不必像以前还需要系统管理员在底层手动创建好PV在通知用户创建PVC。

StatefulSet

StatefulSet在1.5版本以前叫PetSet,除了名字改了,API对象并没有太多变化。对于将现有老的,有状态的,需要容器化的项目,StatefulSet提供非常有效的支持。
我们知道,Deploymentreplicasets类型可以非常快速的创建Pod副本,但是前提是这些都是无状态的应用,这对于一些有状态的应用就非常尴尬了。
目前采用StatefulSet类型的容器结合一些共享存储的方案,可以解决一些这类有状态的应用在业务pod出现漂移,业务pod扩容引发的问题。

那么采用StatefulSe的应用场景如下:

apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "nginx"
  replicas: 3
  volumeClaimTemplates:
  - metadata:
      name: test 
      annotations:
        volume.beta.kubernetes.io/storage-class: ceph-chengdu
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 5Gi 
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: magine1989
        image: nginx:1.11.10
        volumeMounts:
        - mountPath: "/mnt/rbd"
          name: test
      nodeSelector:
        ceph: up

这里介绍下volumeClaimTemplates,这个主要在容器在使用volumes时候,动态创建和映射容器和PVC的关系。我这里结合StorageClass就可以实现每个应用副本对应一个Volumes。

$ kubectl get pod
NAME                    READY     STATUS    RESTARTS   AGE
web-0                   1/1       Running   0          3h
web-1                   1/1       Running   0          3h
web-2                   1/1       Running   0          3h

$ kubectl get pvc
NAME                 STATUS    VOLUME                                     CAPACITY   ACCESSMODES   AGE
test-web-0           Bound     pvc-a202a0dc-1042-11e7-9489-52540095b1e1   5Gi        RWO           3h
test-web-1           Bound     pvc-a2052fad-1042-11e7-9489-52540095b1e1   5Gi        RWO           3h
test-web-2           Bound     pvc-a2070608-1042-11e7-9489-52540095b1e1   5Gi        RWO           3h

$ kubectl get pod web-0  -o yaml
.....
  volumes:
  - name: test
    persistentVolumeClaim:
      claimName: test-web-0
  .....

这里看到POD和PVC的关系是有序的对应上的。

扩展和收缩

前面说道,对于有状态的应用扩容需要结合initcontainer来实现容器运行前的操作。inicontainer我放在后面几期文章里介绍。
这里的扩容只为证明StatefulSet在部署和收缩的时候是有序进行的。

扩展

#将刚刚的3个副本扩容至5个
$ kubectl scale statefulset web --replicas=5

#这个时候观察pod调度状态
$ kubectl get pod
web-0                   1/1       Running             0          3h
web-1                   1/1       Running             0          3h
web-2                   1/1       Running             0          3h
web-3                   0/1       ContainerCreating   0          4s

$ kubectl get pod
web-0                   1/1       Running             0          3h
web-1                   1/1       Running             0          3h
web-2                   1/1       Running             0          3h
web-3                   1/1       Running             0          10s
web-4                   0/1       ContainerCreating   0          0s

$ kubectl get pod
web-0                   1/1       Running   0          3h
web-1                   1/1       Running   0          3h
web-2                   1/1       Running   0          3h
web-3                   1/1       Running   0          35s
web-4                   1/1       Running   0          25s

收缩

#将刚刚的5个副本扩容至2个
$ kubectl scale statefulset web --replicas=2

#只保留了最初的2个POD
$ kubectl get pod
NAME                    READY     STATUS    RESTARTS   AGE
web-0                   1/1       Running   0          3h
web-1                   1/1       Running   0          3h

#PVC保留没有删除
$ kubectl get pvc
NAME                 STATUS    VOLUME                                     CAPACITY   ACCESSMODES   AGE
test-web-0           Bound     pvc-a202a0dc-1042-11e7-9489-52540095b1e1   5Gi        RWO           4h
test-web-1           Bound     pvc-a2052fad-1042-11e7-9489-52540095b1e1   5Gi        RWO           4h
test-web-2           Bound     pvc-a2070608-1042-11e7-9489-52540095b1e1   5Gi        RWO           4h
test-web-3           Bound     pvc-294b1fa7-1064-11e7-9489-52540095b1e1   5Gi        RWO           7m
test-web-4           Bound     pvc-294def6e-1064-11e7-9489-52540095b1e1   5Gi        RWO           7m

这里发现删除StatefulSet时不会删除PVC

上一篇下一篇

猜你喜欢

热点阅读