Skip to content

Kubernetes(五)–Storage是如何工作的?

这篇文章来谈一谈在Kubernetes中如何使用Storage。主要包含以下部分:
– 整体介绍
– Kubernetes Container Storage Interface(CSI)
– Kubernetes 永久数据卷子系统
– Storage Class 和动态创建
– 一个实际的例子

整体介绍

Kubernetes 支持多种存储类型比如Azure Storage, AWS EBS, NFS等。这些外部的存储被用在Kubernetes时,kubernetes把这些存储当作一个数据卷。
各个存储提供商基于Kubernetes开发插件从而让Kubernetes 消费存储, Kubernetes为了方便不同的厂商,定义了一套开源的标准,这个标准就叫做Container Storage Interface。

当Kubernetes使用这些storage时,会先基于这些支持Container Storage Interface的存储创建一个Persistent Volumes(PV), Kubernetes直接管理消费的是这个数据卷PV,
创建完PV后,还需要创建Persistent Volume Claims(PVC), 这个 PVC是用来做Pod使用PV的授权认证的。

Container Storage Interface(CSI)

CSI 是Kubernetes定义的统一的标准接口,当一个存储服务商根据CSI 开发插件时,那么Kubernetes就能对其进行编排。

Kubernetes Persistent volume subsystem

Kubernetes persistent volume subsystem 包含3个资源:Persistent Volume(PV),Persistent Volume Claims(PVC)和Storage class(SC)。

PV

我们先来看下创建一个PV的yaml manifest:

apiVersion: v1
kind: PersistentVolume
metadata: 
  name: pv1
spec:
  accessModes:
  - ReadWriteOnce
  storageClassName: test
  capacity:
    storage: 10Gi
  persistentVolumeReclaimPolicy: Retain
  gcePersistentDisk:
    pdName: uber-disk

其中.spec.accessModes定义了PV被挂载的方式,共有3个选项,ReadWriteOnce(RWO)表示一个PV只能以R/W的方式被一个PVC挂载绑定。
ReadWriteMany(RWM)表示一个PV可以被多个PVC绑定。RWM模式只适用文件和对象存储,比如NFS。而不适用块存储。
ReadOnlyMany(ROM)表示一个PV能以R/O的方式被多个PVC绑定。

spec.persistentVolumeReclaimPolicy 定义了当PVC被释放后Kubernetes对PV的处理方式。有两种Policy: Delete和Retain。
Delete Policy表示Kubernetes 将会把Pv和与之关联的外部的存储一起删掉,这也是通过StorageClass 动态创建PV的默认Policy。
Retain 表示将会保留PV和与之对象的外部存储。但是这种模式会导致另外的PVC继续使用这个PV,如果要想重新利用一个Retained PV,需要先手动删除这个PV,然后基于外部存储创建一个新的PV。

spec.capacity 告诉Kubernetes PV的容量,这个数值可以小于外部的实际物理存储,但是不能超过。举个例子根据一个容量为10GB的外部存储,不能创建一个20GB的PV。

PVC

再来看一个PVC的yaml manifest

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc1
spec:
  accessModes:
  - ReadWriteOnce
  storageClassName: test
  resources:
    requests:
      storage: 10Gi

当创建一个PVC时,accessModestorageClassName 必须和PV中定义的相同。而容量上PVC要求的容量不能大于PV定义的容量。

那么如何在Pod中使用PV呢?

一个使用PV的Pod的manifest

apiVersion: v1
kind: Pod
metadata:
  name: volpod
spec:
  volumes:
  - name: data
    persistentVolumeClaim:
      claimName: pvc1
  containers:
  - name: ubuntu-ctr
    image: ubuntu:latest
    command:
    - /bin/bash
    - "-c"
    - "sleep 60m"
    volumeMounts:
    - mountPath: /data
      name: data

部署Pod时会先定义一个volumes,然后在container中定义volumeMounts。

Storage Class和动态创建

截止到现在我们知道了原始的如何手动创建PV和PVC。但是这种基础的原始的方式在实际中却不用。因为在一个大型的Kubernetes环境中会需要很多PV和PVC,手动的创建和管理大量的PV和PVC显然是不可能的。

Kubernetes 通过Storage Class来动态地创建PV。
一个StorageClass的yaml

apiVersion: storage.k8s.io/v1
kind: StorageClassName
metadata:
  name: fast
provisioner: kubernetes.io/aws-ebs
parameters:
  type: io1
  zones: eu-west-la
  iopsPerGB: "10"

kind 定义了object的类型,apiVersion指定了创建这个resource的schema 版本。

StorageClass 是不可变的object,一旦部署讲无法更改。
provisionerplugin可以互换使用,这里使用了provisioner,parameters和具体的provisioner相关。
一个StorageClass 只能绑定一个provisioner。当StorageClass 被部署后,这个StorageClass object会监测API Server,当发现被PVC引用时,
StorageClass 会自动创建PV。

一个实际的例子

我们之前提到过Kubernetes支持多种多样的类型,这里我用Azure File作为存储,与之对应的cluster也是AKS cluster。

首先使用Azure CLI 执行

az aks get-credentials --resource-group myResourceGroup --name myAKSCluster

执行完后会在我本地的kube.config文件中增加一个aks cluster的连接信息,并且把aks cluster作为当前的活动上下文,即每次执行kubectl 相关的命令都是操纵的AKS cluster而不是我本地的local cluster了。
然后在AKS cluster上安装azure-file-driver
在linux 环境中执行以下命令

curl -skSL https://raw.githubusercontent.com/kubernetes-sigs/azurefile-csi-driver/master/deploy/install-driver.sh | bash -s master --

然后创建一个azure storage 和file share, 并找到AKS cluster的service principal 并赋予它storage的权限。
这样准备工作就做好了。

首先创建一个StorageClass, 其manifest如下

sc.yml

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: myazurefiledynamic
provisioner: file.csi.azure.com
allowVolumeExpansion: true
parameters:
  storageAccount: azurestorage
  shareName: testforkubernetes
  resourceGroup: rg
mountOptions:
  - dir_mode=0777
  - file_mode=0777
  - uid=0
  - gid=0
  - mfsymlinks
  - cache=strict
  - nosharesock
  - actimeo=30

然后部署

kubectl apply -f sc.yml

创建一个PVC

pvc.yml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: azurepvcdynamic
spec:
  accessModes:
  - ReadWriteMany
  storageClassName: "myazurefiledynamic"
  resources:
    requests:
      storage: 1Gi

然后部署它

kubectl apply -f pvc.yml

然后执行

kubectl get pvc

就能够看到这个PVC 处于Bound 状态

然后执行

kubectl get pv

能够找到一个名字为myazurefiledynamic的PV。

Published inKubernetes

Comments are closed.

Author Copyriht by BackendSite