K8S中部署Ceph


一、概述

Ceph 在 k8s 中用做共享存储还是非常方便的,Ceph 是比较老牌的分布式存储系统,非常成熟,功能也强大,支持三种模式(块存储、文件系统存储、对象存储),所以接下来就详细讲解如何在 k8s 使用 ceph。

二、Ceph Rook 介绍

Rook是一个开源的云原生存储编排工具,提供平台、框架和对各种存储解决方案的支持,以和云原生环境进行本地集成。

  • Rook 将存储软件转变成自我管理、自我扩展和自我修复的存储服务,通过自动化部署、启动、配置、供应、扩展、升级、迁移、灾难恢复、监控和资源管理来实现。Rook 底层使用云原生容器管理、调度和编排平台提供的能力来提供这些功能。
  • Rook 利用扩展功能将其深度地集成到云原生环境中,并为调度、生命周期管理、资源管理、安全性、监控等提供了无缝的体验。有关 Rook 当前支持的存储解决方案的状态相关的更多详细信息,可以参考 Rook 仓库 的项目介绍。Rook 目前支持 Ceph、NFS、Minio Object Store 和 CockroachDB。

图片

官网: https://rook.io/ 项目地址: https://github.com/rook

三、通过 Rook 在 k8s 中部署 Ceph

官方文档: https://rook.io/docs/rook/v1.10/Getting-Started/quickstart/

【温馨提示】k8s 节点各挂载一块(或者多块)20GB 的未使用的磁盘。

1)下载部署包

# 在k8s-master主机生创建ceph目录
mkdir -p /data/ceph
cd /data/ceph

# 从github克隆部署包
git clone --single-branch --branch v1.10.8 https://github.com/rook/rook.git

# 网络不稳定时,也可以使用教室局域网下载部署包
wget http://192.168.3.200/Software/rook-v1.10.8.zip
unzip rook-v1.10.8.zip
mv rook-v1.10.8 rook

部署ceph需要至少三个节点,这里删除master节点的污点,将master节点作为工作节点使用

kubectl taint node master node-role.kubernetes.io/master:NoSchedule-

部署所用到的镜像如下: 图片

由于镜像源在国外,国内无法下载,这里需要修改一些镜像或者提前下载 tag,操作如下:

在所有节点下载镜像

# 这个几个镜像文件过大,下载十分缓慢
# docker pull rook/ceph:v1.10.8
# docker pull quay.io/ceph/ceph:v17.2.5
# docker pull quay.io/cephcsi/cephcsi:v3.7.2

# 可以使用局域网下载镜像并在所有节点导入下列镜像
wget http://192.168.3.200/Software/ceph-v1.10.8.tar
docker load -i ceph-v1.10.8.tar

wget http://192.168.3.200/Software/quay-ceph-v17.2.5.tar
docker load -i quay-ceph-v17.2.5.tar

wget http://192.168.3.200/Software/cephcsi-v3.7.2.tar
docker load -i cephcsi-v3.7.2.tar

# 下载其他镜像
docker pull registry.aliyuncs.com/google_containers/csi-node-driver-registrar:v2.5.1
docker tag registry.aliyuncs.com/google_containers/csi-node-driver-registrar:v2.5.1 registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.5.1

docker pull registry.aliyuncs.com/google_containers/csi-snapshotter:v6.1.0
docker tag registry.aliyuncs.com/google_containers/csi-snapshotter:v6.1.0 registry.k8s.io/sig-storage/csi-snapshotter:v6.1.0

docker pull registry.aliyuncs.com/google_containers/csi-attacher:v4.0.0
docker tag registry.aliyuncs.com/google_containers/csi-attacher:v4.0.0 registry.k8s.io/sig-storage/csi-attacher:v4.0.0

docker pull registry.aliyuncs.com/google_containers/csi-resizer:v1.6.0
docker tag registry.aliyuncs.com/google_containers/csi-resizer:v1.6.0 registry.k8s.io/sig-storage/csi-resizer:v1.6.0

docker pull registry.aliyuncs.com/google_containers/csi-provisioner:v3.3.0
docker tag registry.aliyuncs.com/google_containers/csi-provisioner:v3.3.0 registry.k8s.io/sig-storage/csi-provisioner:v3.3.0

2)部署 Rook Operator

cd /data/ceph/rook/deploy/examples/
# 使用yaml文件部署Rook Operator
kubectl create -f crds.yaml -f common.yaml -f operator.yaml
# 检查
kubectl get pod -n rook-ceph
#--------------------------------------------------------------------------------
NAME                                 READY   STATUS            RESTARTS   AGE
rook-ceph-operator-c955c5c9d-dh2lm   1/1     Running           0          7m53s

也可以通过 helm 部署(之后学习)

helm repo add rook-release https://charts.rook.io/release
helm install --create-namespace --namespace rook-ceph rook-ceph rook-release/rook-ceph -f values.yaml

3)创建 Rook Ceph 集群

现在 Rook Operator 处于 Running 状态,接下来我们就可以创建 Ceph 集群了。为了使集群在重启后不受影响,请确保设置的 dataDirHostPath 属性值为有效得主机路径。

cd /data/ceph/rook/deploy/examples/
kubectl apply -f cluster.yaml
# 检查启动状态,安装大约需要3~10分钟
kubectl get pod -n rook-ceph
#---------------------------------------------------------------------------------------------------------
NAME                                              READY   STATUS      RESTARTS   AGE
csi-cephfsplugin-ln5xv                            2/2     Running     0          2m40s
csi-cephfsplugin-provisioner-866bb9b49b-gww7g     5/5     Running     0          2m40s
csi-cephfsplugin-provisioner-866bb9b49b-n469h     5/5     Running     0          2m40s
csi-cephfsplugin-xw7w5                            2/2     Running     0          2m40s
csi-cephfsplugin-ztvk2                            2/2     Running     0          2m40s
csi-rbdplugin-4pxk7                               2/2     Running     0          2m40s
csi-rbdplugin-provisioner-f6b7f64f7-brchm         5/5     Running     0          2m40s
csi-rbdplugin-provisioner-f6b7f64f7-m8nb9         5/5     Running     0          2m40s
csi-rbdplugin-rb2jl                               2/2     Running     0          2m40s
csi-rbdplugin-tn4ks                               2/2     Running     0          2m40s
rook-ceph-crashcollector-master-c7fb554c-czl9z    1/1     Running     0          89s
rook-ceph-crashcollector-node1-6cdc5b749d-6ddcn   1/1     Running     0          104s
rook-ceph-crashcollector-node2-548c78fdc7-d8xsq   1/1     Running     0          64s
rook-ceph-mgr-a-57d966cfb4-6jpmp                  3/3     Running     0          104s
rook-ceph-mgr-b-5bd6f77c55-thhrf                  3/3     Running     0          104s
rook-ceph-mon-a-579fdb5799-nlgsh                  2/2     Running     0          2m33s
rook-ceph-mon-b-7f5d79ff96-n4sp6                  2/2     Running     0          2m6s
rook-ceph-mon-c-5b9f9bfd5b-5v5zq                  2/2     Running     0          116s
rook-ceph-operator-7d4596d8bd-dh2lm               1/1     Running     0          8m39s
rook-ceph-osd-0-74cbfb4c44-sc5vc                  2/2     Running     0          64s
rook-ceph-osd-1-76b546cb86-l7x56                  2/2     Running     0          65s
rook-ceph-osd-prepare-master-dhq9t                0/1     Completed   0          36s
rook-ceph-osd-prepare-node1-rggsp                 0/1     Completed   0          33s
rook-ceph-osd-prepare-node2-n246t                 0/1     Completed   0          30s

4)部署 Rook Ceph 工具

cd /data/ceph/rook/deploy/examples/
kubectl create -f toolbox.yaml

5)部署 Ceph Dashboard

cd /data/ceph/rook/deploy/examples/
kubectl apply -f dashboard-external-https.yaml

# 获取 dashboard admin密码
kubectl -n rook-ceph get secret rook-ceph-dashboard-password -o jsonpath="{['data']['password']}" | base64 -d

通过 Ceph Dashboard 查看 Ceph 集群状态

# 查看对外端口(端口随机生成)
kubectl get svc -n rook-ceph

图片

# 使用任意node节点的ip地址,端口为随机生成,例如:32453
https://<nodeip>:nodePort/

# 用户名:admin 密码:为上一步生成的,例如:RWR0`_!.I@|OO@}3+W}1

注意使用的是https不是http

打开dashboard显示HEALTH_WARN警告

图片

进入 ceph-tools 执行以下命令:

# 进入ceph容器
kubectl exec -it `kubectl get pods -n rook-ceph|grep rook-ceph-tools|awk '{print $1}'` -n rook-ceph -- bash

# 执行命令
ceph config set mon auth_allow_insecure_global_id_reclaim false

exit

图片

6)检查

kubectl get pods,svc -n rook-ceph

图片

7)通过 ceph-tool 工具 pod 查看 ceph 集群状态

kubectl exec -it `kubectl get pods -n rook-ceph|grep rook-ceph-tools|awk '{print $1}'` -n rook-ceph -- bash

ceph -s

图片

四、 测试验证

1) 块存储(RBD)测试

1、创建 StorageClass

cd /data/ceph/rook/deploy/examples/
# 创建一个名为replicapool的rbd pool
kubectl apply -f csi/rbd/storageclass.yaml

图片

2、部署 WordPress

kubectl apply -f mysql.yaml
kubectl apply -f wordpress.yaml

2)文件系统 (CephFS) 测试

1、创建 StorageClass

kubectl apply -f csi/cephfs/storageclass.yaml

2、部署应用

kubectl apply -f filesystem.yaml

3)对象存储 (RGW) 测试

1、创建对象存储

kubectl create -f object.yaml

# 验证rgw pod正常运行
kubectl -n rook-ceph get pod -l app=rook-ceph-rgw

2、创建对象存储 user

kubectl create -f object-user.yaml

3、获取 accesskey secretkey

# 获取AccessKey
kubectl -n rook-ceph get secret rook-ceph-object-user-my-store-my-user -o yaml | grep AccessKey | awk '{print $2}' | base64 --decode

# 获取 SecretKey
kubectl -n rook-ceph get secret rook-ceph-object-user-my-store-my-user -o yaml | grep SecretKey | awk '{print $2}' | base64 --decode

4、部署 rgw nodeport

kubectl apply -f rgw-external.yaml

kubectl -n rook-ceph get service rook-ceph-rgw-my-store rook-ceph-rgw-my-store-external

5、通过 api 接口使用 Ceph 对象存储

#首先,我们需要安装 python-boto 包,用于测试连接 S3。:
# yum install python-boto -y
apt install python-boto -y
# 然后,编写 python 测试脚本。
# cat s3.py
#!/usr/bin/python

import boto
import boto.s3.connection
# 修改为自己机器生成的access_key和secret_key
access_key = 'C7492VVSL8O11NZBK3GT' 
secret_key = 'lo8IIwMfmow4fjkSOMbjebmgjzTRBQSO7w83SvBd'
conn = boto.connect_s3(
    aws_access_key_id = access_key,
    aws_secret_access_key = secret_key,
    host = '192.168.8.128', port=30369,
    is_secure=False,
    calling_format = boto.s3.connection.OrdinaryCallingFormat(),
)
bucket = conn.create_bucket('my-first-s3-bucket')
for bucket in conn.get_all_buckets():
        print "{name}\t{created}".format(
                name = bucket.name,
                created = bucket.creation_date,
)