1. Rook介绍
1.1 Rook简介
Rook是一个运行在Kubernetes集群中的开源云原生存储服务编排工具,为各种存储方案提供平台、框架和支持,将存储软件转变为自我管理、自我扩展和自我修复的存储服务,以便与云原生环境集成。Rook基于底层容器管理平台实现自动部署、启动、配置、分配(provisioning)、扩缩容、升级、迁移、灾难恢复、监控,以及资源管理等功能。
Rook初期专注于Kubernetes+Ceph。在0.8版本中,Rook已经变成Beta版。Rook目前支持Ceph、NFS、Minio Object Store和CockroachDB。
Rook出现前,在kubernetes中搭建并维护Ceph集群的非常复杂,Rook就是为此而生,使用Kubernetes分布式平台简化大量针对Ceph存储的操作和维护工作。
Rook是通过Operator实现这些。Kubernetes中的Operator其实就是对一个自定义的CRD资源及其控制器的封装。
1.2 Rook架构
1.2.1 整体架构
目前,Rook是基于FlexVolume存储插件机制实现的。Rook整体架构如下图所示:


由图可知,Rook主要由3部分组成:
Operator。主要是CRD资源的控制器
Agent。主要通过FlexVolume驱动执行一些存储操作,比如attaching/detaching, mount/unmount
Discover。用来定期去发现节点上新的存储设备

1.2.2 启动流程
Rook的三个组件都集成在一个rook/ceph镜像中。rook的启动流程如下所示:

首先,会使用Deployment启动Operator组件;
然后,使用Daemonset在每个容器云的主机上启动一个Agent组件,同时将FlexVolume插件安装在每台主机的volume-plugin-dir目录下;
接着,同样使用Daemonset形式在每个主机上启动一个Discover组件;
最后,创建了两个自定义资源的控制器ProvisionController和ClusterController。
Rook的Operator启动后可以看到在rook-ceph-system
这个namespace下创建了与上面相对应的一些pod:
2. Rook对Ceph的管理
Ceph是一个分布式存储系统,支持文件、块、对象存储,在生产环境中被广泛应用。
使用rook部署ceph集群后,在rook-ceph
这个namespace下会启动如下一些pod:
分为以下几种类型:
mon
mgr
osd
mds
rgw
mon
即Ceph集群中的mon(monitor)组件,负责监控整个Ceph集群的运行状况。会启动quorum中指定个数的mon,一般集群中会有三个mon以保证集群的高可用。在创建集群时,Rook会:
启动特定节点上的mon,确保与quorum中指定的相同
之后,定期检查mon的数量,确保与quorum中指定的相同;如果某个mon挂了,并且没有自动重启,Operator会再起一个新的mon,加到quorum中,并从quorum中移除失效的mon
有mon挂了后,更新Ceph客户端和Daemons中的mon的IP地址
mgr
即Ceph集群中的mgr(manager)组件,主要负责监控一些非paxos相关的服务(比如pg相关统计信息),这里的mgr是一个无状态服务,提供集群一些非paxos相关的监控指标。Rook除了启动mgr外,还负责配置其它两个mgr插件:
收集可供Prometheus抓取的指标
启动Ceph dashoard
osd
即Ceph集群的osd组件,集群的核心存储组件。
mds
即Ceph集群的mds组件,是Ceph分布式文件系统的元数据服务器。一或多个mds 协作管理文件系统的命名空间、协调到共享osd集群的访问。当在集群中声明要一个共享文件系统时,Rook会:
为CephFS创建metadata和数据池
创建文件系统
启动指定数量active-standby的mds实例
创建的共享文件系统可以被集群中Pod使用。
rgw
即Ceph集群的rgw组件,为应用提供RESTful类型的对象存储接口。当在集群中声明要一个对象存储时,Rook会:
为对象存储创建metadata和数据池
启动rgw daemon,如果需要还可以运行多个实例做高可用
创建一个service来为rgw daemon提供一个负载均衡访问地址
3. rook安装
3.1 rook集群部署
1.找一块大点的磁盘(至少大于5GB),创建rook数据存储目录:
$ sudo mkdir app/dcos/rook
2.到release页面下载rook,我下载的v0.8.3版:
$ wget https://github.com/rook/rook/archive/v0.8.3.zip && unzip v0.8.3.zip
3.配置kubelet,设置启动参数--volume-plugin-dir
:
这个参数告诉kubelet到哪里去找第三方存储插件,确保这个参数指定的目录有读写权限。不指定的话,默认值是
/usr/libexec/kubernetes/kubelet-plugins/volume/exec/
。
4.配置operator.yaml,需要和kubelet的--volume-plugin-dir
参数中的保持一致:
$ cd v0.8.3/cluster/examples/kubernetes/ceph $ vim operator.yaml - name: FLEXVOLUME_DIR_PATH value: "/usr/libexec/kubernetes/kubelet-plugins/volume/exec"
5.配置cluster.yaml,修改rook数据存储目录:
$ cd v0.8.3/cluster/examples/kubernetes/ceph $ vim cluster.yaml dataDirHostPath: app/rook/data
6.部署
$ kubectl apply -f operator.yaml $ kubectl apply -f cluster.yaml
cluster.yaml部署好后,一个ceph集群就创建好了。
备注
1.operator.yaml中主要是一些自定义资源对象的定义(CRD),有:Cluster、Filesystem、ObjectStore、Pool、Volume;还创建了rook的三种组件Operator、Agent、Discover。
2.cluster.yaml中主要创建了一个Cluster(ceph集群)自定义资源对象(CR)
3.2 ceph集群的访问
3.2.1 通过图形界面
部署一个external的dashboard service,以nodePort的形式对外提供图形界面访问:
$ kubectl apply -f dashboard-external.yaml

3.2.2 通过ceph命令行工具访问
官方给出了一个toolbox容器,里面包含各种ceph的客户端程序,可以在这个容器中对ceph进行操作。
$ kubectl apply -f toolbox.yaml
进入pod中可以执行各种ceph命令:
$ kubectl -n rook-ceph exec -it rook-ceph-tools bash ceph status ceph osd status ceph df rados df ...
4. 使用
4.1 块存储
块存储一次只能挂给一个Pod使用。
4.1.1 创建块存储storageclass
修改配置文件cluster/examples/kubernetes/ceph/storageclass.yaml,根据ceph数据盘的文件系统类型修改fstype参数:
fstype: xfs
创建块存储的storageclass:
$ kubectl apply -f storageclass.yaml
4.1.2 块存储使用示例
创建两个应用mysql和wordpress,spec.volumes.persistentVolumeClaim.claimName
指定块存储的storageclass:
$ cd cluster/examples/kubernetes $ kubectl apply -f mysql.yaml $ kubectl apply -f wordpress.yaml
效果:
$ kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE mysql-pv-claim Bound pvc-3fe82814-f37f-11e8-a569-286ed488cbd8 20Gi RWO rook-ceph-block 5h51m wp-pv-claim Bound pvc-ddb04927-f382-11e8-a569-286ed488cbd8 20Gi RWO rook-ceph-block 5h25m $ kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pvc-3fe82814-f37f-11e8-a569-286ed488cbd8 20Gi RWO Delete Bound default/mysql-pv-claim rook-ceph-block 5h51m pvc-ddb04927-f382-11e8-a569-286ed488cbd8 20Gi RWO Delete Bound default/wp-pv-claim rook-ceph-block 5h26m
4.2 共享文件系统
共享文件系统可以以r/w的权限同时挂给多个Pod使用。目前rook默认只支持创建一个共享文件系统,在ceph中创建多个共享文件系统目前是实验性质的,可以通过修改rook-operator.yaml
中的ROOK_ALLOW_MULTIPLE_FILESYSTEMS
环境变量开启。
4.2.1 创建一个Filesystem资源
创建Filesystem资源:
kubectl apply -f filesystem.yaml
可以看到创建了一个名为myfs的Filesystem:
[docker@k8s ]$ kubectl get Filesystem -n rook-ceph NAME AGE myfs 6h
进入toolbox查看mds数据,还可以看到生成了一个standby-replay模式的mds实例:
$ kubectl -n rook-ceph exec -it rook-ceph-tools bash ... services: mds: myfs-1/1/1 up {0=myfs-7bd69578d7-q7nch=up:active}, 1 up:standby-replay
4.2.2 共享文件系统使用示例
使用kube-registry.yaml文件创建一个应用指定使用刚才创建的名为myfs的filesystem:
volumes: - name: image-store flexVolume: driver: ceph.rook.io/rook fsType: ceph options: fsName: myfs # name of the filesystem specified in the filesystem CRD. clusterName: rook-ceph # namespace where the Rook cluster is deployed
4.3 对象存储
4.3.1 创建对象存储
创建一块对象存储,向存储集群中暴露S3的API给应用使用。
$ kubectl apply -f object.yaml
对象存储创建后,rook operator会创建所有需要的pool和其他所需资源来启动服务。
等一段时间后,可以看到启动了一个rgw pod(rgw daemon):
$ kubectl -n rook-ceph get pod -l app=rook-ceph-rgw NAME READY STATUS RESTARTS AGE rook-ceph-rgw-my-store-84487c4898-z25zq 1/1 Running 0 6h44m
部署一个external的service,使得rgw也可以通过nodePort提供给集群外部使用:
$ kubectl apply -f rgw-external.yaml
4.3.2 创建用户
创建对象存储用户需要在toolbox容器中运行radosgw-admin
命令:
$ kubectl -n rook-ceph exec -it rook-ceph-tools bash [root@rook-ceph-tools /]# radosgw-admin user create --uid rook-user --display-name "A rook rgw User" --rgw-realm=my-store --rgw-zonegroup=my-store { "user_id": "rook-user", "display_name": "A rook rgw User", "email": "", "suspended": 0, "max_buckets": 1000, "auid": 0, "subusers": [], "keys": [ { "user": "rook-user", "access_key": "EXS3PTFWTUQ7C8JO1LBE", "secret_key": "7DoGlb2YkV8lIsLhvkl4iKdvQfKICwzby7uPmJpu" } ], "swift_keys": [], "caps": [], "op_mask": "read, write, delete", "default_placement": "", "placement_tags": [], "bucket_quota": { "enabled": false, "check_on_raw": false, "max_size": -1, "max_size_kb": 0, "max_objects": -1 }, "user_quota": { "enabled": false, "check_on_raw": false, "max_size": -1, "max_size_kb": 0, "max_objects": -1 }, "temp_url_keys": [], "type": "rgw" }
现在使用认证过的rook-user
用户就可以访问对象存储了,记下上面打印出来的access_key
和secret_key
,后面会用到:
{ "user": "rook-user", "access_key": "EXS3PTFWTUQ7C8JO1LBE", "secret_key": "7DoGlb2YkV8lIsLhvkl4iKdvQfKICwzby7uPmJpu" }
4.3.3 使用对象存储
这一步连接对象存储并从上面上传、下载。方便起见,可以使用toolbox中的s3cmd
命令。进入到toolbox容器中执行以下命令:
1.使用S3对应的client在对象存储中创建bucket
设置连接的环境变量:
[root@rook-ceph-tools /]# export AWS_HOST=rook-ceph-rgw-my-store.rook-ceph [root@rook-ceph-tools /]# export AWS_ENDPOINT=10.233.40.208:80 [root@rook-ceph-tools /]# export AWS_ACCESS_KEY_ID=EXS3PTFWTUQ7C8JO1LBE [root@rook-ceph-tools /]# export AWS_SECRET_ACCESS_KEY=7DoGlb2YkV8lIsLhvkl4iKdvQfKICwzby7uPmJpu
其中:
Host: rgw服务在k8s集群中的dns主机名,假如用的是默认的rook-ceph集群,是rook-ceph-rgw-my-store.rook-ceph
Endpoint: rgw服务在k8s集群中监听的地址,即通过kubectl -n rook-ceph get svc rook-ceph-rgw-my-store命令获取的clusterIP+port
Access key: 上面打印出的用户access_key
Secret key: 上面打印出的用户secret_key
2.创建bucket
在对象存储中创建一个bucket:
[root@rook-ceph-tools /]# s3cmd mb --no-ssl --host=${AWS_HOST} --host-bucket= s3://rookbucket Bucket 's3://rookbucket/' created
查看创建的bucket:
[root@rook-ceph-tools /]# s3cmd ls --no-ssl --host=${AWS_HOST} 2018-11-29 06:23 s3://rookbucket
3.PUT 或 GET 一个对象
Upload a file to the newly created bucket
上传一个文件到刚才创建的bucket中:
[root@rook-ceph-tools /]# echo "Hello Rook" > /tmp/rookObj [root@rook-ceph-tools /]# s3cmd put /tmp/rookObj --no-ssl --host=${AWS_HOST} --host-bucket= s3://rookbucket upload: '/tmp/rookObj' -> 's3://rookbucket/rookObj' [1 of 1] 11 of 11 100% in 0s 228.95 B/s done
从bucket中下载并验证这个文件:
[root@rook-ceph-tools /]# s3cmd get s3://rookbucket/rookObj /tmp/rookObj-download --no-ssl --host=${AWS_HOST} --host-bucket= download: 's3://rookbucket/rookObj' -> '/tmp/rookObj-download' [1 of 1] 11 of 11 100% in 0s 250.92 B/s done [root@rook-ceph-tools /]# cat /tmp/rookObj-download Hello Rook




