2万字长文:Kubernetes云原生开源分布式存储
文章插图
本文转载自公众号: 民生运维人
作者:付广平
出处:;mid=2247483769 --tt-darkmode-bgcolor: #131313;">1 Kubernetes存储介绍1.1 为何引入PV、PVC以及StorageClass?熟悉Kubernetes的都对PV、PVC以及StorageClass不陌生 , 我们经常用到 , 因此这里不再详细介绍PV、PVC以及StorageClass的用法 , 仅简单聊聊为什么需要引入这三个概念 。
我们看下最早期Pod使用Volume的写法:
apiVersion: v1kind: Podmetadata:name: test-podspec:containers:- image: ...name: test-podvolumeMounts:- mountPath: /dataname: datavolumes:- name: datacapacity:storage: 10Gicephfs:monitors:- 172.16.0.1:6789- 172.16.0.2:6789- 172.16.0.3:6789path: /opt/eshop_dir/eshopuser: adminsecretRef:name: ceph-secret
这种方式至少存在两个问题:
- Pod声明与底层存储耦合在一起 , 每次声明volume都需要配置存储类型以及该存储插件的一堆配置 , 如果是第三方存储 , 配置会非常复杂 。
- 开发人员的需求可能只是需要一个20GB的卷 , 这种方式却不得不强制要求开发人员了解底层存储类型和配置 。
于是引入了PV(Persistent Volume) , PV其实就是把Volume的配置声明部分从Pod中分离出来:
apiVersion: v1kind: PersistentVolumemetadata:name: cephfsspec:capacity:storage: 10GiaccessModes:- ReadWriteManycephfs:monitors:- 172.16.0.1:6789- 172.16.0.2:6789- 172.16.0.3:6789path: /opt/eshop_dir/eshopuser: adminsecretRef:name: ceph-secret
我们发现PV的spec部分几乎和前面Pod的volume定义部分是一样的 。有了PV , 在Pod中就可以不用再定义volume的配置了 , 直接引用即可 , volume定义和Pod松耦合了 。
但是这没有解决volume定义的第二个问题 , 存储系统通常由运维人员管理 , 开发人员并不知道底层存储配置 , 也就很难去定义好PV 。
为了解决这个问题 , 引入了PVC(Persistent Volume Claim) , 声明与消费分离 , 开发与运维责任分离 。
运维人员负责存储管理 , 可以事先根据存储配置定义好PV , 而开发人员无需了解底层存储配置 , 只需要通过PVC声明需要的存储类型、大小、访问模式等需求即可 , 然后就可以在Pod中引用PVC , 完全不用关心底层存储细节 。
kind: PersistentVolumeClaimapiVersion: v1metadata:name: cephfsspec:accessModes:- ReadWriteManyresources:requests:storage: 8Gi
PVC会根据声明的大小、存储类型(如storageClassName)、accessModes等关键字查找PV , 如果找到了匹配的PV , 则会与之关联 。通过PV以及PVC , 开发人员的问题是解决了 , 但没有解决运维人员的问题 。 运维人员需要维护一堆PV列表和配置 , 如果PV不够用需要手动创建新的PV , PV空闲了还需要手动去回收 , 管理效率太低了 。
于是又引入了StorageClass , StorageClass类似声明了一个非常大的存储池 , 其中一个最重要的参数是provisioner , 这个provisioner声明了谁来提供存储源 , 我们熟悉的OpenStack Cinder、Ceph、AWS EBS等都是provisioner 。
kind: StorageClassapiVersion: storage.k8s.io/v1metadata:name: aws-gp2provisioner: kubernetes.io/aws-ebsparameters:type: gp2fsType: ext4
有了StorageClass后 , Kubernetes会根据开发人员定义的PVC中声明的StorageClassName以及大小等需求自动创建PV , 即Dynamic Provisioning 。而运维人员只需要声明好StorageClass以及Quota配额 , 无需维护PV 。
通过PV、PVC以及StorageClass , 开发和运维的工作彻底解放了 。
1.2 Kubernetes存储方案发展过程概述我们知道Kubernetes存储最开始是通过Volume Plugin实现集成外部存储系统 , 即不同的存储系统对应不同的volume plugin 。
Volume Plugin实现代码全都放在了Kubernetes主干代码中(in-tree) , 也就是说这些插件与核心Kubernetes二进制文件一起链接、编译、构建和发布 。
这种方案至少存在如下几个问题:
- 在Kubernetes中添加新存储系统支持需要在核心Kubernetes增加插件代码 , 随着存储插件越来越多 , Kubernetes代码也会变得越来越庞大 。
- Kubernetes与具体的存储plugin耦合在一起 , 一旦存储接口发生任何变化都需要重新修改plugin代码 , 也就是说不得不修改Kubernetes代码 , 这会导致Kubernetes代码维护越来越困难 。
- 如果plugin有bug或者存储系统故障导致crash , 可能导致整个Kubernetes集群整体crash 。
- 这些插件运行时无法做权限管控 , 具有Kubernetes所有组件的所有权限 , 存在一定的安全风险 。
- 插件的实现必须通过Golang语言编写并与Kubernetes一起开源 , 可能对一些厂商不利 。
- Kubernetes 运维小记:node 为系统保留最低资源
- 在kubernetes中部署企业级ELK并使用其APM
- Kubernetes上对应用程序进行故障排除的技巧
- 代表|以Kubernetes为代表的容器技术,已成为云计算的新界面
- 微信|万字长文:谈谈我对视频号的思考
- Kubernetes核心原理和搭建
- 管理20+Kubernetes集群、400台机器,秘诀在于?
- 中文|万字长文:谷歌进入到退出中国市场的前因后果
- 万字长文,ConcurrentSkipListMap源码详解
- 用Ansible的Kubernetes模块实现容器编排自动化