19 使用 Rook 构建生产可用存储环境实践

Rook 是基于 Kubernetes 之上构建的存储服务框架。它支持 Ceph、NFS 等多种底层存储的创建和管理。帮助系统管理员自动化维护存储的整个生命周期。存储的整个生命周期包括部署、启动、配置、申请、扩展、升级、迁移、灾难恢复、监控和资源管理等,看着就让笔者觉得事情不少,Rook 的目标就是降低运维的难度,让 Kubernetes 和 Rook 来帮你托管解决这些任务。

Rook 管理 Ceph 集群

Ceph 分布式存储是 Rook 支持的第一个标记为 Stable 的编排存储引擎,在笔者验证 Rook 操作 Ceph 的过程中发现,其社区文档、脚本都放在一起,初次新手很难知道如何一步一步体验 Rook 搭建 Ceph 的过程。这从一个侧面反应了分布式存储的技术难度和兼容性是一个长期的迭代过程,Rook 的本意是为了降低部署管理 Ceph 集群的难度,但是事与愿违,初期使用的过程并不友好,有很多不知名的问题存在官方文档中。

16-1-rook-arch.png

在安装 Ceph 前要注意,目前最新的 Ceph 支持的存储后端 BlueStore 仅支持裸设备,不支持在本地文件系统之上建立存储块。因为 Rook 文档的混乱,一开始我们需要自己找到安装脚本目录,它在

https://github.com/rook/rook/tree/master/cluster/examples/kubernetes/ceph

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
$ git clone https://github.com/rook/rook.git

$ cd rook

$ git checkout release-1.4

$ cd cluster/examples/kubernetes/ceph



$ kubectl create -f common.yaml

# 检查 namesapce 是否有 rook-ceph 了

$ kubectl get namespace

$ kubectl create -f operator.yaml

# 上述的步骤必须确定 pods 已经处于 running or complete 才能做下一个阶段,否则很有可能会 fail,上述的步骤需要等一会。

$ kubectl create -f cluster.yaml

# 等待 Ceph 集群创建成功。



$ kubectl -n rook-ceph get pods

# mgr 1, mon 3,

# rook-ceph-crashcollector (有几个 node 就有几个)

# rook-ceph-osd (有几个 disk,就会有几个 pod,排序从 0 开始)


Ceph 的问题很多,经常需要使用工具箱查看一些情况,按照如下步骤部署:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
$ kubectl create -f toolbox.yaml

$ kubectl -n rook-ceph get pods | grep ceph-tools

rook-ceph-tools-649c4dd574-gw8tx 1/1 Running 0 3m20s

$ kubectl -n rook-ceph exec -it rook-ceph-tools-649c4dd574-gw8tx bash

$ ceph -s

cluster:

id: 9ca03dd5-05bc-467f-89a8-d3dfce3b9430

health: HEALTH_OK



services:

mon: 3 daemons, quorum a,d,e (age 12m)

mgr: a(active, since 8m)

osd: 44 osds: 44 up (since 13m), 44 in (since 13m)



data:

pools: 1 pools, 1 pgs

objects: 0 objects, 0 B

usage: 45 GiB used, 19 TiB / 19 TiB avail

pgs: 1 active+clean

# ceph 集群可以使用的容量

$ ceph df

# ceph osd 与 node 的关系分布

$ ceph osd tree

# 删除 ceph toolbox 工具

$ kubectl delete -f toolbox.yaml


使用 Dashboard 查看 Ceph 运行情况:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
$ vim dashboard-external-https.yaml

apiVersion: v1

kind: Service

metadata:

name: rook-ceph-mgr-dashboard-external-https

namespace: rook-ceph

labels:

app: rook-ceph-mgr

rook_cluster: rook-ceph

spec:

ports:

- name: dashboard

port: 8443

protocol: TCP

targetPort: 8443

selector:

app: rook-ceph-mgr

rook_cluster: rook-ceph

sessionAffinity: None

type: NodePort

$ kubectl create -f dashboard-external-https.yaml

$ kubectl -n rook-ceph get service

rook-ceph-mgr-dashboard-external-https NodePort 10.107.117.151 <none> 8443:31955/TCP 8m23s


访问地址是 31955,https://master\_ip:31955 就可以访问。账号是 admin,密码可以在线查到:

1
2
3
$ kubectl -n rook-ceph get secret rook-ceph-dashboard-password -o jsonpath="{['data']['password']}" | base64 --decode && echo


清空 Ceph:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ cd /rook/cluster/examples/kubernetes/ceph

$ kubectl -n rook-ceph delete cephcluster rook-ceph

$ kubectl -n rook-ceph get cephcluster

# 确认 rook-ceph 被删除

$ kubectl delete -f operator.yaml

# 删除集群

$ kubectl delete -f common.yaml

$ kubectl delete -f cluster.yaml


用 Rook 管理 NFS 文件系统

NFS 文件系统目前在国内企业还是很常见的一种存储方案。用 Rook 来管理 NFS 文件系统可以极大的方便开发者的存储环境。安装 rook 之前需要先安装 NFS Client 安装包。在 CentOS 节点上安装 nf-utils,在 Ubuntu 节点上安装 nf-common。然后就可以安装 Rook 了。步骤如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
git clone --single-branch --branch v1.4.6 https://github.com/rook/rook.git

cd rook/cluster/examples/kubernetes/nfs

kubectl create -f common.yaml

kubectl create -f provisioner.yaml

kubectl create -f operator.yaml



#查看运行情况

[[email protected] ~]# kubectl -n rook-nfs-system get pod

NAME READY STATUS RESTARTS AGE

rook-nfs-operator-59fb455d77-2cxn4 1/1 Running 0 75m

rook-nfs-provisioner-b4bbf4cc4-qrzqd 1/1 Running 1 75m


创建权限,rbac.yaml 内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
---

apiVersion: v1

kind: Namespace

metadata:

name: rook-nfs

---

apiVersion: v1

kind: ServiceAccount

metadata:

name: rook-nfs-server

namespace: rook-nfs

---

kind: ClusterRole

apiVersion: rbac.authorization.k8s.io/v1

metadata:

name: rook-nfs-provisioner-runner

rules:

- apiGroups: [""]

resources: ["persistentvolumes"]

verbs: ["get", "list", "watch", "create", "delete"]

- apiGroups: [""]

resources: ["persistentvolumeclaims"]

verbs: ["get", "list", "watch", "update"]

- apiGroups: ["storage.k8s.io"]

resources: ["storageclasses"]

verbs: ["get", "list", "watch"]

- apiGroups: [""]

resources: ["events"]

verbs: ["create", "update", "patch"]

- apiGroups: [""]

resources: ["services", "endpoints"]

verbs: ["get"]

- apiGroups: ["policy"]

resources: ["podsecuritypolicies"]

resourceNames: ["rook-nfs-policy"]

verbs: ["use"]

- apiGroups: [""]

resources: ["endpoints"]

verbs: ["get", "list", "watch", "create", "update", "patch"]

- apiGroups:

- nfs.rook.io

resources:

- "*"

verbs:

- "*"

---

kind: ClusterRoleBinding

apiVersion: rbac.authorization.k8s.io/v1

metadata:

name: rook-nfs-provisioner-runner

subjects:

- kind: ServiceAccount

name: rook-nfs-server

# replace with namespace where provisioner is deployed

namespace: rook-nfs

roleRef:

kind: ClusterRole

name: rook-nfs-provisioner-runner

apiGroup: rbac.authorization.k8s.io


执行 yaml 创建权限:

1
2
3
kubectl create -f rbac.yaml


当前主流的做法是采用动态申请资源的方式创建 NFSServer,步骤如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
kubectl create -f nfs.yaml



# sc.yaml

apiVersion: storage.k8s.io/v1

kind: StorageClass

metadata:

labels:

app: rook-nfs

name: rook-nfs-share1

parameters:

exportName: share1

nfsServerName: rook-nfs

nfsServerNamespace: rook-nfs

provisioner: rook.io/nfs-provisioner

reclaimPolicy: Delete

volumeBindingMode: Immediate


kubectl create \-f sc.yaml 将创建 StorageClass,然后就可以申请资源:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
apiVersion: v1

kind: PersistentVolumeClaim

metadata:

name: rook-nfs-pv-claim

spec:

storageClassName: "rook-nfs-share1"

accessModes:

- ReadWriteMany

resources:

requests:

storage: 1Mi


kubectl create \-f pvc.yaml 将创建一份文件卷。校验结果:

1
2
3
4
5
6
7
[[email protected] nfs]# kubectl get pvc

NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE

rook-nfs-pv-claim Bound pvc-504eb26d-1b6f-4ad8-9318-75e637ab50c7 1Mi RWX rook-nfs-share1 7m5s


测试使用的案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
> kubectl create -f busybox-rc.yaml

> kubectl create -f web-rc.yaml



> kubectl get pod -l app=nfs-demo



> kubectl create -f web-service.yaml



> echo; kubectl exec $(kubectl get pod -l app=nfs-demo,role=busybox -o jsonpath='{.items[0].metadata.name}') -- wget -qO- http://$(kubectl get services nfs-web -o jsonpath='{.spec.clusterIP}'); echo



Thu Oct 22 19:28:55 UTC 2015

nfs-busybox-w3s4t


当你发现 NFS Server 没有运行起来,可以用这一行命令查看问题:

1
2
3
kubectl -n rook-nfs-system logs -l app=rook-nfs-operator


总结

Rook 项目从笔者入手来,其目标定位还是很准,并且真实的解决了简化 Ceph 安装配置的痛点,并且依据 Ceph 使用的经验开始注入更多的存储驱动,如 NFS 存储驱动。使用起来并不复杂,但是它的文档实在是太糟糕了。社区中也没有人来专门维护这套文档,导致文章中很多描述都是过期的,你根本不清楚如何配置。一不小心就会配置错误。所以大家在使用过程中,还是要仔细熟悉一遍 yaml 文档的内容,了解到它的功能后在安装,就会事半功倍。这种不完善其实对开源技术爱好者来说,也是一种机会,让你通过修改文档的方式参与到 Rook 这个项目中。以我梳理一遍之后,通过最新版本的安装步骤,你可以几分钟就可以部署自己的分布式存储环境,Rook 确实事半功倍,值得推荐并大量实践使用。

参考资料