Kubernetes持久化存储Cephfs

2019 年 11 月 24 日

Kubernetes持久化存储Cephfs

Kubernetes volume


熟悉 kubernetes volume 的同学应该了解,kubernetes 对 volume 的提供支持“静态 PV”和“动态 PV”两种方式。


  • 静态PV


集群管理员创建一些 PV,之后便可用于 PVC 消费。


  • 动态PV


相比静态 PV 而言,动态 PV 无需管理员手动创建 PV,PV 的操作是由一个叫 StorageClass 的控制器创建。对于 Cephfs volume 来说,截止到 kubernetes 1.10 版本并没有直接提供 Cephfs 的 StorageClass。



虽然官方并没有直接提供对 Cephfs StorageClass 的支持,但是社区给出了类似的解决方案 external-storage/ cephfs,后面我们会使用到。


1 静态 PV


编辑 Cephfs PV 对象文件 cephfs-pv.yaml:


apiVersion: v1kind: PersistentVolumemetadata:  name: cephfs-pvspec:  capacity:    storage: 1Gi  accessModes:    - ReadWriteMany  cephfs:    monitors:      - 192.168.0.3:6789    user: kube    secretRef:      name: secret-for-cephfs    readOnly: false  persistentVolumeReclaimPolicy: Recycle
复制代码


创建 PV:


$ kubectl create -f cephfs-pv.yaml -n cephfspersistentvolume "cephfs-pv" created 
$ kubectl get pv -n cephfs
复制代码


创建 PVC


$ vim cephfs-pv-claim.yaml
apiVersion: v1kind: PersistentVolumeClaimmetadata: name: cephfs-pv-claim namespace: cephfs spec: accessModes: - ReadWriteMany resources: requests: storage: 1Gi
复制代码


在 deployment 中使用 PV:


metadata:  name: cephfs-pvc  namespace: cephfsspec:  replicas: 2  template:    metadata:      labels:        app: cephfs-pvc    spec:      containers:      - name: nginx        image: busybox:latest        volumeMounts:        - name: cephfs-pv           mountPath: /data/cephfs          readOnly: false       volumes:      - name: cephfs         persistentVolumeClaim:          claimName: cephfs-pv-claim
复制代码


这样,在同一个 deployment 中的 2 个 pod 容器内都可以读写同一个 cephfs volume 了。


2 动态 PV


对于规模不大的容器平台而言,静态 PV 方式就可以满足需求;但是当容器规模很大时,你不知道用户什么时候创建 PV,因此动态 PV 方式就非常有用了。下面我们看下如何基于 external-storage/cephfs 来实现动态 PV。


部署 cephfs-provisioner


cephfs-provisioner 是 kubernetes 官方社区提供的Cephfs的StorageClass支持。用于动态的调用后端存储Cephfs创建PV。


cephfs-provisoner 的实现机制如图所示:



它主要是包含两部分:


  • cephfs-provisoner.go


是 cephfs-provisoner(cephfs 的 StorageClass)的核心,主要是 watch kubernetes 中 PVC 资源的 CURD 事件,然后以命令行方式调用 cephfs_provisor.py 脚本创建 PV。


  • cephfs_provisoner.py


python 脚本实现的与 cephfs 交互的命令行工具。cephfs-provisoner 对 cephfs 端 volume 的创建都是通过该脚本实现。里面封装了 volume 的增删改查等功能。


创建 StorageClass


#kubectl create -f class.yaml
# kubectl get sc -n cephfsNAME PROVISIONER AGEcephfs ceph.com/cephfs 33d
复制代码


基于 RBAC 授权方式启动 cephfs-provisioner


# kubectl create -f  *
# kubectl get deploy -n cephfs
复制代码


这样动态创建 PV 的环境就准备好了。


动态 PV 方式,无需再手动创建 PV,只需创建 PVC,cephfs-provisoner 会自动的为该 PVC 在后端 cephfs 存储上创建对应的 PV。


kind: PersistentVolumeClaimapiVersion: v1metadata:  name: pvc-1  annotations:    volume.beta.kubernetes.io/storage-class: "cephfs"spec:  accessModes:    - ReadWriteMany  resources:    requests:      storage: 1Gi
复制代码


此时,我们创建 PVC 后,会看到同时会自动创建并绑定上一个 PV。


至此,基于 cephfs 的动态 PV 方式就介绍完了。


cephfs-provisoner 的坑


在使用 cephfs-provisoner 与公司 cephfs 对接的时候遇到了一些坑,在这里一并说一下。


  • 路径问题


在 cephfs_provisioner/ cephfs_provisioner.py 的实现中,默认在 cephfs 中创建的根目录名是”kubernetes“,所有后续创建的卷都在 cephfs 端的 /kubernetes/ 一级目录下 ,代码实现中以 VOlUME_GROUP="kubernetes"定义。 因此,如果你不想在 cephfs 中以该名字命名,需要修改 VOLUME_GROUP 值。


另外,它的二级目录也是固定的为/kubernetes/volumes,二级目录是 python-cephfs 模块中由 DEFAULT_VOL_PREFIX 变量定义:


POOL_PREFIX = "fsvolume_"DEFAULT_VOL_PREFIX = "/volumes"DEFAULT_NS_PREFIX = "fsvolumens_"
复制代码


因此,要定制化在 cephfs 端的一级和二级目录,需要修改这两个地方。


  • 权限问题


这里遇到两个权限问题:


1.挂载权限问题


默认 python-cephfs 模块在连接 cephfs 挂载时是 mount 的根目录”/“。


而根目录只有 admin 用户才有权限进行挂载,所以这个地方除了 admin 用户外,没办法使用其它用户。但是,我们在使用 cephfs 时,为了安全,管理员是不会给我们 admin 用户使用的,所以这个地方肯定是接受不了的。为此,我们定制修改了 libcephfs2 和 python-cephfs 的源码,增加了 connect_with_path 方法,允许指定挂载的目录,这样我们只要在挂载时不使用根目录即可。


  1. 读写权限问题


在 cephfs_provisoner.py 的实现中,默认添加了对 cephfs namespace 的支持,因此在对 volume 授权时会添加对 namespace 相关的权限设置。因为,我们使用的 ceph 版本 luminous 没有对 namespace 进行支持,所以,在使用时产生了创建的 volume 挂载到 pod 内后没有读写权限"input/output error"的问题。 此时,你在 cephfs 端查看卷的读写权限时,你可以看到目录读写权限都是问号。于是我们修改了这部分逻辑,去掉了 namespace 相关的部分。


本文转载自公众号贝壳产品技术(ID:gh_9afeb423f390)。


原文链接:


https://mp.weixin.qq.com/s/fpWNBEC5RxrZACcu9zrq9Q


2019 年 11 月 24 日 23:49389

评论

发布
暂无评论
发现更多内容

目标检测综述

Dreamer

接口测试人员需要掌握的知识技能

测试人生路

接口测试

在2020年更受关注和追捧的JS框架

Geek_Willie

react.js Vue js Svelte

华为云的销售凭什么说“赢”了罗振宇?

ToB行业头条

tob

C++ primer -- 第18章 探讨C++新标准

Dreamer

c++

独立显卡市场又一巨头跻入,英特尔锐炬® Xe MAX 独立显卡来了!

intel001

架构师训练营第 1 期 第 3 周作业

李循律(祥龙)

极客大学架构师训练营

永续合约系统开发源码,合约跟单软件搭建app

WX13823153201

SpringBoot-技术专题-war包部署读取外部配置Yml

李浩宇/Alex

Caffe 安装踩坑记录

Dreamer

caffe

试用阿里网盘内测版-不限速、无广告、隐私安全我全都要

郭旭东

阿里云网盘

C++ primer -- 第16章 string类和标准模版库

Dreamer

c++

当下工作流管理系统的发展趋势

Marilyn

敏捷开发 快速开发 软件架构 企业开发

Docker底层技术

混沌畅想

Docker 容器 DevOps 底层技术

TypeScript魔法堂:函数类型声明其实很复杂

肥仔John

Java typescript

SpringBoot-技术专题-war包部署读取外部配置Properties

李浩宇/Alex

直播预告 | CloudQuery初体验——安装及多数据源连接

CloudQuery社区

数据库 sql 安全 工具软件 dba

基于React+Koa实现一个h5编辑器

徐小夕

Java nodejs H5 React koa

EDA最强攻略,如何为EDA选择存储?

焱融科技

分布式 高性能 存储 半导体 EDA

架构师训练营 1 期第 6 周作业

木头发芽

面试时说Redis是单线程的,被喷惨了!

云流

redis 编程 程序员 计算机

一个研发团队是如何坚持7年技术分享的?

PingCode

团队管理 敏捷开发 研发管理 技术分享 程序员节

TensorFlow 篇 | TensorFlow 数据输入的最佳实践

Alex

tensorflow keras input pipeline dataset

MySQL中事务的持久性实现原理

X先生

MySQL 数据库 sql 数据库事务 事务

数据结构与算法系列之链表操作全集(二)(GO)

书旅

go 数据结构 算法

快速掌握并发编程---深入学习ThreadLocal

田维常

C++ primer -- 第17章 输入,输出和文件

Dreamer

c++

专利申请其实并不难?四步教你玩转专利申请!

华为云开发者社区

专利 保护

架构师训练营第 1 期 第 5 周作业

李循律(祥龙)

极客大学架构师训练营

Forsage矩阵系统开发,智能合约搭建

薇電13242772558

写文档太麻烦,试试这款 IDEA 插件吧!

程序员小航

Java markdown IDEA idea插件 文档

Kubernetes持久化存储Cephfs-InfoQ