认识K8s容器存储接口CSI

容器存储接口(Container Storage Interface),简称 CSI,CSI试图建立一个行业标准接口的规范,借助CSI容器编排系统(CO)可以将任意存储系统暴露给自己的容器工作负载。

存储可分为临时存储、半持久存储、持久化存储。常见的临时存储主要是emptyDir卷,enptyDir最初是空的,当pod从节点上删除后,emptyDir卷中的数据也会被永久删除,如果pod因为某些原因重启,enptyDir卷内的数据不会丢失。emptyDir卷存储在支持该节点所使用的存储介质上,可以是本地磁盘或者网络存储。emptyDir的空间位于系统根盘,被所有容器共享,所以在磁盘的使用率较高时会触发Pod的eviction操作,故需要根据实际需要来使用emptyDir,一般情况下emptyDir存储中间数据,用于快速恢复。

半持久化存储主要是hostPath卷,hostPath卷将主机节点上文件系统上的文件或者目录挂载到指定pod中,对于需要获取节点系统信息的pod,需要挂载hostPath,例如Calico插件,需要将配置文件等存放到节点的目录上。在使用hostPath卷时需要注意的三个点
1.使用同一个目录的pod由于调度到不同的节点,导致目录中内容不同
2.Kubernetes在调度时无法顾及由hostPath使用的资源
3.pod被删除后,hostPath上的数据会遗留在节点上,会占用磁盘空间

支持持久化存储是所有分布式系统必备的特性,针对持久化存储,Kubernetest引入了StorageClass,Volume,PVC,PV的概念。Kubernetes支持的持久化存储包括主流的块存储和文件存储,在大类上又可以分成网络存储和本地存储两类。
StorageClass:用于指示存储的类型,不同的存储类型可以通过不同的StorageClass来为用户提供服务,StorageClass中主要包含存储插件、provisioner、卷创建和mount参数字段。以下就是定义一个StorageClass的yaml文件例子,每个 StorageClass 都有一个制备器(Provisioner),用来决定使用哪个卷插件制备 PV。

下图是一些常用的Provisioner,更多Provisioner的信息可以查看这里

通过上面的信息描述,可以知道StorageClass对象本质上是创建PV的模板,StorageClass的定义涉及两部分:
第一:PV的属性。比如,存储类型、Volume的大小等。
第二:创建这种PV需要用到的存储插件,如Ceph等。
有了这两个信息之后,Kubernetes就能够根据用户提交的PVC,找到一个对应的StorageClass了。然后Kubernetes就会调用该StorageClass声明的存储插件创建出需要的PV,且把StorageClass相同的PVC和PV进行绑定。这种更具StorageClass自动创建PV且完成绑定的机制叫Dynamic Provisioning机制,有了这种机制运维人员只需要创建出需要的StorageClass即可,PVC本身是由开发人员创建。
PVC:由用户创建,代表用户对存储需求的声明,主要包括需要的存储大小,存储卷的访问模式、StorageClass等类型,其中存储卷的访问模式必须与存储类型一致。下图是一个PVC的yaml文件例子。


PV:由集群管理员提前创建,或者根据PVC的申请动态创建,它代表系统后端的真实存储空间,可以称之为卷空间。备注:如果是通过前面Dynamic Provisioning机制,可以不用定义PV。

下面将通过例子演示如何配置emptyDir实现临时存储,下面是一个部署nginx的yaml文件例子,在yaml文件中指定了emptyDir。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          volumeMounts:
          - mountPath: /cache
            name: cache-volume
      volumes:
      - name: cache-volume
        emptyDir: {}

启动pod后,进入pod,查看文件目录,可以看到有个cache目录,且该目录是空目录。

拷贝一个文件到cache目录下,此时删除pod,等新的pod重启后,再次进入新的pod,可以看到存储的文件消失,故emptyDir适用于临时存储一些内容。

 接下来再看看hostPath的例子,以下是创建PV,PVC,Pod的yaml文件。下面的文件中定义了一个PV,PV关联的hostPath是/mnt/data,pod中mount的地址是usr/share/nginx/html,在主机上创建/mnt/data的目录,然后在该目录下创建一个html文件,然后依次创建下面的对象,pod对象创建成功后,理论上进入pod,在pod的/usr/share/nginx/html目录下存在在主机上创建的html文件。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: task-pv-volume
  labels:
    type: local
spec:
  storageClassName: manual
  capacity:
    storage: 100Mi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/mnt/data"
--
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: task-pv-claim
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 100Mi
--
apiVersion: v1
kind: Pod
metadata:
  name: task-pv-pod-anti-affinity.yaml
spec:
  volumes:
    - name: task-pv-storage
      persistentVolumeClaim:
        claimName: task-pv-claim
  containers:
    - name: task-pv-container
      image: nginx
      ports:
        - containerPort: 80
          name: "http-server"
      volumeMounts:
        - mountPath: "/usr/share/nginx/html"
          name: task-pv-storage

在定义PV和PVC过程中都涉及到accessMode配置,accessMode支持三种类型

  • ReadWriteMany 多路读写,卷能被集群多个节点挂载并读写
  • ReadWriteOnce 单路读写,卷只能被单一集群节点挂载读写
  • ReadOnlyMany 多路只读,卷能被多个集群节点挂载且只能读

接着再看看PVC和StorageClass,如下图所示一个myslq的pod部署时,在pod的部署文件中配置了volume信息,volume配置中设置了需要的PVC名称。

下面是PVC的定义,可以看到PVC中又指定了StorageClass,故如果要让Mysql部署成功,那么首选需要创建StorageClass,创建完成后可以通过kubectl get storageclass查看。关于如何在aws上创建StorageClass可以查看aws官网的详细文档

下图是在aws上申请eks集群后,按照官网文档安装存储插件后,创建出来的storageClass。

创建出StorageClass后再部署上面的mysql服务,能成功部署。 

mysql服务部署的方式属于动态挂载volume的方式,按volume的挂载方式可以分为动态挂载和本地独占两种模式,接下来看看这两个模式的过程。

动态挂载volume过程

  • 创建PVC:用户创建PVC,PVC处于pending状态。
  • 创建Pod:用户创建Pod
  • Pod选择节点:kube-sheduler开始调度pod,通过PVC的resource.reqeust.storage等选择满足条件的节点。
  • 更新PVC:选择节点后,kube-scheduler会给PVC添加包含节点信息的annotation:volume.kubernetes.io/selected-node:节点名称
  • 创建卷:运行的节点上的容器external-provisioner监听到PVC有该节点相关的annotation,向相应的CSI驱动申请分配卷
  • 创建PV:PVC申请到所需的存储空间后,external-provisioner创建PV,该PV的pv.Spec.claimRef设置为对应的PVC
  • PVC和PV绑定:kube-controller-manager将PVC和PV进行绑定,状态修改为Bound
  • 监听PVC状态:kube-scheduler等待PVC变成Bound状态
  • Pod调度到节点:当PVC的状态为Bound时,Pod才算真正调度成功,如果PVC一直处于pending状态,超时后会再次进行调度。
  • Mound卷:kubelet监听到有Pod已经调度到节点上,对本地存储进行mount操作。
  • 启动容器:启动容器。

如果是通过kubeadm初始化的集群,也可以通过如下方式创建storageclass和PVC来感受下动态存储的挂载过程。

1.apt-get install nfs-kernel-server 安装nfs-server
2.mkdir -p /data/cloudnative 创建存储数据的目录,可以自己任意命名
3.cat /etc/exports,修改exports中的配置信息
/data/cloudnative  192.168.31.0/24(rw,sync,no_subtree_check,no_root_squash),这里设置了nfs-server的地址段,实验时设置的k8s master的内部IP地址段(10.0.1.0/24)
4.执行命令:exportfs -rv(重新加载上面的配置文件信息)
5.showmount -e 10.0.1.22(用master的内网IP作为nf-server的IP地址,对于企业会搭建自己的nfs-sever)
6.安装客户端driver
curl -skSL https://raw.githubusercontent.com/kubernetes-csi/csi-driver-nfs/master/deploy/install-driver.sh | bash -s master --
7.创建storageClass的yaml文件,里面server地址要设置正确
 

8.创建PVC,里面需要配置正确的storageClassName的名字,创建pvc后进行查看,是binding状态即表示存储绑定成功。

独占的Local Volume 

  • 创建PV:通过local-volume-provisioner Daemonset创建本地存储的PV
  • 创建PVC:用户创建PVC,由于它处于pending状态,所以kube-controller-manager并不会对PVC做任何操作
  • 创建Pod:用户创建Pod
  • Pod挑选节点:kube-sheduler开始调度pod,通过PVC的resource.reqeust.storage和volumeMode选择满足条件的PV,并且为Pod选择一个合适的节点
  • 更新PV:kube-scheduler将PV的pv.Spec.claimRef设置为对应PVC,并且设置annotaion pv.kubernetes.io/bound-by-controller的值为yes
  • PVC和PV绑定:pv_controller同步PVC和PV的状态,并将PVC和PV进行绑定
  • 监听PVC对象:kube-scheduler等待PVC的状态变成Bound状态
  • Pod调度到节点:如果PVC的状态变为Bound则说明调度成功,如果PVC一直处于pending状态,超时后会再次调度。
  • Mount卷启动容器:kubelet监听到有Pod已经调度到节点上,对本地存储进行mount操作,并启动容器。

定义PV的yaml文件如下图所示:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0003
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: slow
  mountOptions:
    - hard
    - nfsvers=4.1
  nfs:
    path: /tmp
    server: 172.17.0.2
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

taoli-qiao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值