Kubernetes 容器持久化存储
2020-03-24 14:26:00 0 举报
Kubernetes 容器持久化存储相关知识点整理
作者其他创作
大纲/内容
External Attacher
用户创建了一个声明使用上述 PVC 的 Pod,并且这个 Pod 被调度器调度到了宿主机 A 上
CSI 插件体系
Attach
kind: DaemonSetapiVersion: apps/v1beta2metadata: name: csi-do-node namespace: kube-systemspec: selector: matchLabels: app: csi-do-node template: metadata: labels: app: csi-do-node role: csi-do spec: serviceAccount: csi-do-node-sa hostNetwork: true containers: - name: driver-registrar image: quay.io/k8scsi/driver-registrar:v0.3.0 ... - name: csi-do-plugin image: digitalocean/do-csi-plugin:v0.2.0 args : - \"--endpoint=$(CSI_ENDPOINT)\" - \"--token=$(DIGITALOCEAN_ACCESS_TOKEN)\" - \"--url=$(DIGITALOCEAN_API_URL)\" env: - name: CSI_ENDPOINT value: unix:///csi/csi.sock - name: DIGITALOCEAN_API_URL value: https://api.digitalocean.com/ - name: DIGITALOCEAN_ACCESS_TOKEN valueFrom: secretKeyRef: name: digitalocean key: access-token imagePullPolicy: \"Always\" securityContext: privileged: true capabilities: add: [\"SYS_ADMIN\"] allowPrivilegeEscalation: true volumeMounts: - name: plugin-dir mountPath: /csi - name: pods-mount-dir mountPath: /var/lib/kubelet mountPropagation: \"Bidirectional\" - name: device-dir mountPath: /dev volumes: - name: plugin-dir hostPath: path: /var/lib/kubelet/plugins/com.digitalocean.csi.dobs type: DirectoryOrCreate - name: pods-mount-dir hostPath: path: /var/lib/kubelet type: Directory - name: device-dir hostPath: path: /dev---kind: StatefulSetapiVersion: apps/v1beta1metadata: name: csi-do-controller namespace: kube-systemspec: serviceName: \"csi-do\" replicas: 1 template: metadata: labels: app: csi-do-controller role: csi-do spec: serviceAccount: csi-do-controller-sa containers: - name: csi-provisioner image: quay.io/k8scsi/csi-provisioner:v0.3.0 ... - name: csi-attacher image: quay.io/k8scsi/csi-attacher:v0.3.0 ... - name: csi-do-plugin image: digitalocean/do-csi-plugin:v0.2.0 args : - \"--endpoint=$(CSI_ENDPOINT)\" - \"--token=$(DIGITALOCEAN_ACCESS_TOKEN)\" - \"--url=$(DIGITALOCEAN_API_URL)\" env: - name: CSI_ENDPOINT value: unix:///var/lib/csi/sockets/pluginproxy/csi.sock - name: DIGITALOCEAN_API_URL value: https://api.digitalocean.com/ - name: DIGITALOCEAN_ACCESS_TOKEN valueFrom: secretKeyRef: name: digitalocean key: access-token imagePullPolicy: \"Always\" volumeMounts: - name: socket-dir mountPath: /var/lib/csi/sockets/pluginproxy/ volumes: - name: socket-dir emptyDir: {}
CSI Controller
+ 表示是持久化存储数据卷对象 + 这个 API 对象定义了一个持久化存储在宿主机上的目录(如 NFS 的挂载目录)+ 通常情况下,PV 对象由运维人员事先创建在 Kubernetes 集群里```apiVersion: v1kind: PersistentVolumemetadata:name: nfsspec:storageClassName: manualcapacity: storage: 1GiaccessModes: - ReadWriteManynfs: server: 10.244.1.4 path: \"/\"```
运行在宿主机 A 上的 kubelet,就会通过 VolumeManagerReconciler,发现当前宿主机上有一个 Volume 对应的存储设备(比如磁盘)已经被 Attach 到了某个设备目录下
Driver Register
后续
DaemonSet
PVC 类似于接口,PV 类似于具体实现,storageClassName 需要保持一致,才能被绑定,Pod 声明 PVC,kubelet 将对应的 PV,即某个 Volumes 挂载到Pod 容器内的某个目录
+ 在宿主机上执行的操作:```service Node { // temporarily mount the volume to a staging path rpc NodeStageVolume (NodeStageVolumeRequest) returns (NodeStageVolumeResponse) {} // unmount the volume from staging path rpc NodeUnstageVolume (NodeUnstageVolumeRequest) returns (NodeUnstageVolumeResponse) {} // mount the volume from staging to target path rpc NodePublishVolume (NodePublishVolumeRequest) returns (NodePublishVolumeResponse) {} // unmount the volume from staging path rpc NodeUnpublishVolume (NodeUnpublishVolumeRequest) returns (NodeUnpublishVolumeResponse) {} // stats for the volume rpc NodeGetVolumeStats (NodeGetVolumeStatsRequest) returns (NodeGetVolumeStatsResponse) {} ... // Similar to NodeGetId rpc NodeGetInfo (NodeGetInfoRequest) returns (NodeGetInfoResponse) {}}```
External Persistent Storage(Ceph 等)
External Attacher 容器使用这个VolumeAttachment 里的宿主机和 Volume 名字,调用同一个 Pod 里的 CSI 插件的 CSI Controller 服务的 ControllerPublishVolume 方法,完成 Attach 阶段
Volume Controller 的 AttachDetachController 就会发现,上述 PVC 对应的 Volume,需要被 Attach 到宿主机 A 上
请求CreateVolume创建 PV
+ CSI Controller 服务,定义的则是对 CSI Volume 的管理接口,比如: + 创建和删除 CSI Volume + 对 CSI Volume 进行 Attach/Dettach(在 CSI 里,这个操作被叫作 Publish/Unpublish) + 以及对 CSI Volume 进行 Snapshot 等```service Controller { // provisions a volume rpc CreateVolume (CreateVolumeRequest) returns (CreateVolumeResponse) {} // deletes a previously provisioned volume rpc DeleteVolume (DeleteVolumeRequest) returns (DeleteVolumeResponse) {} // make a volume available on some required node rpc ControllerPublishVolume (ControllerPublishVolumeRequest) returns (ControllerPublishVolumeResponse) {} // make a volume un-available on some required node rpc ControllerUnpublishVolume (ControllerUnpublishVolumeRequest) returns (ControllerUnpublishVolumeResponse) {} ... // make a snapshot rpc CreateSnapshot (CreateSnapshotRequest) returns (CreateSnapshotResponse) {} // Delete a given snapshot rpc DeleteSnapshot (DeleteSnapshotRequest) returns (DeleteSnapshotResponse) {} ...}```
External Components
请求 Identity获取插件信息
StatefulSet 里的 External Provisioner 容器,就会监听到这个 PVC 的诞生
Mount
AttachDetachController 会创建一个 VolumeAttachment 对象,这个对象携带了宿主机 A 和待处理的 Volume 的名字
Custom Components
External Privisioner
CSI Node
Kubelet 与两阶段处理
两阶段持久化宿主机目录
CSI 插件部署
+ 负责 Attach 阶段+ 监听 APIServer 里 VolumeAttachment 对象的变化+ 一旦出现了 VolumeAttachment 对象,External Attacher 就会调用 CSI Controller 服务的 ControllerPublish 方法,完成它所对应的 Volume 的 Attach 阶段+ 而 Volume 的 Mount 阶段 ,并不属于 External Components 的职责+ 当 kubelet 的 VolumeManagerReconciler 控制循环检查到它需要执行 Mount 操作的时候,会通过 pkg/volume/csi 包,直接调用 CSI Node 服务完成 Volume 的 Mount 阶段
PV
Kube-apiserver
+ 负责 Provision 阶段+ 监听(Watch)APIServer 里的 PVC 对象。当一个 PVC 被创建时,它就会调用 CSI Controller 的 CreateVolume 方法,为你创建对应 PV+ 此外,如果你使用的存储是公有云提供的磁盘(或者块设备)的话,这一步就需要调用公有云(或者块设备服务)的 API 来创建这个 PV 所描述的磁盘(或者块设备)了
请求ControllerPublish实现 Attach
部署在任意一个提供 CSI Node 服务
+ 持久化 Volume 的实现,往往依赖于一个远程存储服务+ 而 Kubernetes 需要做的工作,就是使用这些存储服务,来为容器准备一个持久化的宿主机目录,以供将来进行绑定挂载时使用
CSI Identity
部署在每个节点提供 CSI Node 服务
Volumes
+ 接下来,kubelet 只要把这个 Volume 目录通过 CRI 里的 Mounts 参数,传递给 Docker,然后就可以为 Pod 里的容器挂载这个“持久化”的 Volume 了+ 相当于执行如下所示的命令:docker run -v ...
+ Pod 所希望使用的持久化存储的属性 + 如:Volume 存储的大小、可读写权限等等 + PVC 对象通常由开发人员创建,或者以 PVC 模板的方式成为 StatefulSet 的一部分,然后由 StatefulSet 控制器负责创建带编号的 PVC```apiVersion: v1kind: PersistentVolumeClaimmetadata: name: nfsspec: accessModes: - ReadWriteMany storageClassName: manual resources: requests: storage: 1Gi```
Master 节点上的 Volume Controller,就会通过 PersistentVolumeController,发现这对新创建出来的 PV 和 PVC,并且看到它们声明的是同一个 StorageClass
持久化 Volumes
CSI 插件实现持久化 Volumes 创建
+ 上述关于 PV 的“两阶段处理”流程,是靠独立于 kubelet 主控制循环之外的两个控制循环来实现的: + Attach(以及 Dettach)操作,是由 Volume Controller 负责维护的:AttachDetachController(不断地检查每一个 Pod 对应的 PV,和这个 Pod 所在宿主机之间挂载情况。从而决定,是否需要对这个 PV 进行操作) + 作为一个 Kubernetes 内置的控制器,Volume Controller 是 kube-controller-manager 的一部分 + Mount(以及 Unmount)操作,必须发生在 Pod 对应的宿主机上,是 kubelet 组件的一部分,叫作 VolumeManagerReconciler,是一个独立于 kubelet 主循环的 Goroutine
+ 如果 Volume 类型是远程块存储,那么kubelet 就需要先调用相应的 API,将它所提供的 Persistent Disk 注册到 Pod 所在的宿主机上+ 这一步为虚拟机注册远程磁盘的操作,对应的正是“两阶段处理”的第一阶段+ 在 Kubernetes 中,我们把这个阶段称为 Attach+ Kubernetes 提供的可用参数是 nodeName,即宿主机的名字
+ 对外暴露这个插件本身的信息:```service Identity { // return the version and name of the plugin rpc GetPluginInfo(GetPluginInfoRequest) returns (GetPluginInfoResponse) {} // reports whether the plugin has the ability of serving the Controller interface rpc GetPluginCapabilities(GetPluginCapabilitiesRequest) returns (GetPluginCapabilitiesResponse) {} // called by the CO just to check whether the plugin is running or not rpc Probe (ProbeRequest) returns (ProbeResponse) {}}```
调用同一个 Pod 里的 CSI 插件的 CSI Controller 服务的 CreateVolume 方法,创建出对应的磁盘块(即 PV)
Provision 阶段
PVC
StatefulSet
+ 将一个宿主机上的目录,跟一个容器里的目录绑定挂载在了一起
示例
+ 将插件注册到 kubelet 里面,这可以类比为,将可执行文件放在插件目录下
用户创建 PVC
Kubelet
+ 就是这个宿主机上的目录,具备“持久性” + 即:这个目录里面的内容,既不会因为容器的删除而被清理掉,也不会跟当前的宿主机绑定 + 当容器被重建出来之后,它仍然能够通过挂载这个 Volume,访问到这些内容 + 持久化 Volume 的实现,往往依赖于一个远程存储服务,比如:远程文件存储(比如,NFS、GlusterFS)、远程块存储(比如,公有云提供的远程磁盘)等等 + 所谓“持久化”,指的是容器在这个目录里写入的文件,都会保存在远程存储中,从而使得这个目录具备了“持久性”
StorageClass
+ 接下来,kubelet 还要进行第二个操作,即:格式化这个磁盘设备,然后将它挂载到宿主机指定的挂载点上+ 这个挂载点,正是在前面反复提到的 Volume 的宿主机目录+ 这一步对应的正是“两阶段处理”的第二个阶段:Mount+ Mount 阶段完成后,容器在它里面写入的内容,会保存在远程磁盘中+ Kubernetes 提供的可用参数是 dir,即 Volume 的宿主机目录
Kubernetes容器持久化存储
PersistentVolumeController 会把这一对 PV 和 PVC 绑定起来,使 PVC 进入 Bound 状态
+ StorageClass 对象的作用,其实就是创建 PV 的模板+ 第二个作用就是 StorageClass 的另一个重要作用,是指定 PV 的 Provisioner(存储插件)。这时候,如果你的存储插件支持 Dynamic Provisioning 的话,Kubernetes 就可以自动为你创建 PV 了+ 会定义如下两个部分内容: + 第一,PV 的属性(比如,存储类型、Volume 的大小等) + 第二,创建这种 PV 需要用到的存储插件(比如,Ceph 等)```apiVersion: storage.k8s.io/v1kind: StorageClassmetadata: name: block-serviceprovisioner: kubernetes.io/gce-pdparameters: type: pd-ssd```
kubelet 就会调用同一台宿主机上的 CSI 插件的 CSI Node 服务的 NodeStageVolume 和 NodePublishVolume 方法,完成这个 Volume 的 Mount 阶段
StatefulSet 里的 External Attacher 容器,就会监听到这个 VolumeAttachment 对象的诞生
收藏
0 条评论
下一页