什么是 Ceph
Ceph是一个统一的分布式存储系统,设计初衷是提供较好的性能、可靠性和可扩展性。Ceph项目最早起源于Sage就读博士期间的工作(最早的成果于2004年发表),并随后贡献给开源社区。在经过了数年的发展之后,目前已得到众多云计算厂商的支持并被广泛应用。RedHat及OpenStack都可与Ceph整合以支持虚拟机镜像的后端存储。
核心组件及概念介绍
- Monitor
一个Ceph集群需要多个Monitor组成的小集群,它们通过Paxos同步数据,用来保存OSD的元数据。 - OSD
OSD全称Object Storage Device,也就是负责响应客户端请求返回具体数据的进程。一个Ceph集群一般都有很多个OSD。 - MDS
MDS全称Ceph Metadata Server,是CephFS服务依赖的元数据服务。 - Object
Ceph最底层的存储单元是Object对象,每个Object包含元数据和原始数据。 - PG
PG全称Placement Grouops,是一个逻辑的概念,一个PG包含多个OSD。引入PG这一层其实是为了更好的分配数据和定位数据。 - RADOS
RADOS全称Reliable Autonomic Distributed Object Store,是Ceph集群的精华,用户实现数据分配、Failover等集群操作。 - Libradio
Librados是Rados提供库,因为RADOS是协议很难直接访问,因此上层的RBD、RGW和CephFS都是通过librados访问的,目前提供PHP、Ruby、Java、Python、C和C++支持。 - CRUSH
CRUSH是Ceph使用的数据分布算法,类似一致性哈希,让数据分配到预期的地方。 - RBD
RBD全称RADOS block device,是Ceph对外提供的块设备服务。 - RGW
RGW全称RADOS gateway,是Ceph对外提供的对象存储服务,接口与S3和Swift兼容。 - CephFS
CephFS全称Ceph File System,是Ceph对外提供的文件系统服务。
ceph-ansible
ceph 官方提供了 ansible 的安装脚本 ceph-ansible。将项目克隆到本地,可以看到最新的稳定版本是 stable-4.0,克隆代码后注意切换到改分支或者4.x的tag。根据集群要求准备了3台服务器。部署 OSDs 的节点需要一块额外的磁盘用作存储。ansible 的 hosts 文件如下所示:
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[all]
192.168.56.121 ansible_user=vagrant ansible_ssh_pass=vagrant ansible_become=true
192.168.56.122 ansible_user=vagrant ansible_ssh_pass=vagrant ansible_become=true
192.168.56.123 ansible_user=vagrant ansible_ssh_pass=vagrant ansible_become=true
[mons]
192.168.56.121
192.168.56.122
192.168.56.123
[osds]
192.168.56.121
192.168.56.122
192.168.56.123
[mgrs]
192.168.56.121
192.168.56.122
192.168.56.123
[mdss]
192.168.56.121
192.168.56.122
192.168.56.123
[grafana-server]
192.168.56.121这里将 192.168.56.121 作为用于执行 ansible-playbook 的节点。在这个节点上需要配置到另外2台服务器的 ssh 免密码登录并安装一些依赖:
1
2
3
4
5
6
7
8
9for host in \
192.168.56.121 \
192.168.56.122 \
192.168.56.123; \
do \
ssh-copy-id -i ~/.ssh/id_rsa.pub vagrant@$host; \
done
yum install -y ansible epel-release python2-pip
pip install -r requirements.txt配置 site.yml 配置文件,将没用到的 hosts 注释:
1
2
3
4
5
6- hosts:
- mons
- osds
- mgrs
- mdss
- grafana-server配置全局变量 group_vars/all.yml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16cluster: ceph
centos_package_dependencies:
- epel-release
- libselinux-python
ceph_origin: repository
ceph_repository: community
ceph_mirror: http://mirrors.aliyun.com/ceph
ceph_stable_key: http://mirrors.aliyun.com/ceph/keys/release.asc
ceph_stable_repo: "{{ ceph_mirror }}/rpm-{{ ceph_stable_release }}"
ceph_stable_release: nautilus
ceph_stable: true
fetch_directory: ~/ceph-ansible-keys
monitor_interface: eth0
public_network: 192.168.56.1/24
cluster_network: "{{ public_network }}"配置 OSDs 变量,主要配置用哪个盘存储数据:
1
2devices:
- /dev/vdb配置好可以运行 ansible-playbook -i hosts site.yml;等待 ceph 安装完毕。安装完成后执行 ceph -s 可以看到如下输出:
1
2
3
4
5
6
7
8
9
10
11
12
13
14cluster:
id: b358e8f9-3ffa-438b-8b38-38f9f5468d12
health: HEALTH_OK
services:
mon: 3 daemons, quorum VM_48_51_centos,VM_48_62_centos,VM_48_83_centos (age 2d)
mgr: VM_48_51_centos(active, since 2d), standbys: VM_48_83_centos
osd: 3 osds: 3 up (since 87m), 3 in (since 87m)
data:
pools: 0 pools, 0 pgs
objects: 0 objects, 0 B
usage: 3.0 GiB used, 294 GiB / 297 GiB avail
pgs:
kubernetes 配置 ceph
客户端节点配置
k8s 节点安装 ceph 客户端,添加 ceph 的源,将以下内容写入到 /etc/yum.repo.d/ceph.repo:
1
2
3
4
5
6
7[ceph]
name=Ceph noarch packages
baseurl=http://mirrors.aliyun.com/ceph/rpm-nautilus/el7/x86_64/
enabled=1
gpgcheck=1
type=rpm-md
gpgkey=http://mirrors.aliyun.com/ceph/keys/release.asc安装,注意版本要和服务端的一致。
1
2yum clean all && yum makecache
yum install -y ceph-common创建 RBD pool:
1
ceph osd pool create kube 128
授权 kube 用户:
1
2ceph auth get-or-create client.kube mon 'allow r' osd 'allow class-read, allow rwx pool=kube' -o ceph.client.kube.keyring
ceph auth get client.kube将生成的 keyring 文件放到 k8s 节点的 /etc/ceph/ 目录下
创建 storageclass
创建 ceph secret:
1
2
3ceph auth get-key client.admin | base64
ceph auth get-key client.kube | base64
kubectl apply -f ceph-kube-secret.yamlceph-kube-secret.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22apiVersion: v1
kind: Namespace
metadata:
name: ceph
apiVersion: v1
kind: Secret
metadata:
name: ceph-admin-secret
namespace: ceph
type: kubernetes.io/rbd
data:
key: QVFEVGdBOWQ4bDA1TUJBQWhnamFJNHd6QzROVXJyR1J3RnlPWnc9PQ==
apiVersion: v1
kind: Secret
metadata:
name: ceph-kube-secret
namespace: ceph
type: kubernetes.io/rbd
data:
key: QVFBVWJ4VmRYbHNwS3hBQUxJSDdQWmxlalk5WW10Rm5DRnQwU2c9PQ==创建动态 RBD StorageClass:
1
kubectl apply -f ceph-storageclass.yaml
ceph-storageclass.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ceph-rbd
annotations:
storageclass.kubernetes.io/is-default-class: "true"
provisioner: kubernetes.io/rbd
parameters:
monitors: 192.168.0.10:6789,192.168.0.11:6789,192.168.0.12:6789
adminId: admin
adminSecretName: ceph-admin-secret
adminSecretNamespace: ceph
pool: kube
userId: kube
userSecretName: ceph-kube-secret
fsType: xfs
imageFormat: "2"
imageFeatures: "layering"创建 pvc 测试
1
kubectl apply -f ceph-pvc.yaml -n ceph
ceph-pvc.yaml
1
2
3
4
5
6
7
8
9
10
11kind: PersistentVolumeClaim
metadata:
name: ceph-pvc
namespace: ceph
spec:
storageClassName: ceph-rbd
accessModes:
- ReadOnlyMany
resources:
requests:
storage: 1Gi查看 pvc 的状态发现一直是 pending,describe 查看 pvc 事件,发现报错:
1
rbd: create volume failed, err: executable file not found in $PATH
结合日志查阅资料发现是在 kube-controller-manager 的 pod 容器中没有 rbd 命令。具体可以查看 github issue 可以通过安装 external-storage 插件来解决。克隆下来后路径如下:
1
2
3
4
5
6
7
8
9
10
11
12
13ceph
└── rbd
└── deploy
├── non-rbac
│ └── deployment.yaml
├── rbac
│ ├── clusterrolebinding.yaml
│ ├── clusterrole.yaml
│ ├── deployment.yaml
│ ├── rolebinding.yaml
│ ├── role.yaml
│ └── serviceaccount.yaml
└── README.md由于部署 k8s 集群的时候启用了 rbac,所以我们用 rbac 目录下的部署文件。将 clusterrolebinding.yaml 和 rolebingding.yaml 的 namespace 修改为 ceph,然后部署:
1
kubectl apply -f rbac -n ceph
等到部署完成后,修改 storageClass 的配置,把 provisioner: kubernetes.io/rbd 更改为 provisioner: ceph.com/rbd,重新部署。等待创建完成,重新部署 pvc,发现已经可以绑定了。查看 pvc 发现也已经创建了。
到 ceph 的 monitor 节点上,执行如下命令:
1
2rbd ls -p kube
rbd info kubernetes-dynamic-pvc-10321857-9952-11e9-aac5-0a580ae9419b -p kube可以获取到 image 的详细信息,说明 ceph 确实被使用了。
创建一个 pod 进行测试,发现 pod 一直处于 container creating 的状态。
pod.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19apiVersion: v1
kind: Pod
metadata:
labels:
test: rbd-dyn-pvc-pod
name: ceph-rbd-dyn-pv-pod2
spec:
containers:
- name: ceph-rbd-dyn-pv-busybox2
image: busybox
command: ["sleep", "60000"]
volumeMounts:
- name: ceph-dyn-rbd-vol1
mountPath: /mnt/ceph-dyn-rbd-pvc/busybox
readOnly: false
volumes:
- name: ceph-dyn-rbd-vol1
persistentVolumeClaim:
claimName: ceph-pvc查看 pod 事件,发现如下报错:
1
2
3MountVolume.WaitForAttach failed for volume "pvc-ec2aa2a2-b290-11e9-998e-5254003f0e66" : rbd: map failed exit status 110, rbd output: rbd: sysfs write failed
In some cases useful info is found in syslog - try "dmesg | tail".
rbd: map failed: (110) Connection timed out在 pod 所在节点执行命令 dmesg | tail,发现如下报错:
1
2
3
4
5
6[260542.633436] libceph: mon1 10.107.36.4:6789 feature set mismatch, my 106b84a842a42 < server's 40106b84a842a42, missing 400000000000000
[260542.638039] libceph: mon1 10.107.36.4:6789 missing required protocol features
[260552.602373] libceph: mon2 10.107.36.12:6789 feature set mismatch, my 106b84a842a42 < server's 40106b84a842a42, missing 400000000000000
[260552.606904] libceph: mon2 10.107.36.12:6789 missing required protocol features
[260562.618453] libceph: mon0 10.107.36.21:6789 feature set mismatch, my 106b84a842a42 < server's 40106b84a842a42, missing 400000000000000
[260562.623014] libceph: mon0 10.107.36.21:6789 missing required protocol features查阅资料发现这个错误和内核的特性有关,可以升级内核至4.5以上。也可以通过设置 ceph 来解决,具体可以查看 https://k2r2bai.com/2018/02/11/ceph/luminous-crush-issue/
这里通过调整 ceph 配置来解决:
1
ceph osd crush tunables hammer
ceph 配置 dashboard
启用模块:
1
ceph mgr enable dashboard
创建证书:
1
ceph dashboard create-self-signed-cert
重启:
1
2ceph mgr module disable dashboard
ceph mgr module enable dashboard配置 ip,端口:
1
2ceph config set mgr mgr/dashboard/server_addr $IP
ceph config set mgr mgr/dashboard/server_port $PORT注意 ip 是 active monitor 节点的 ip
创建用户:
1
ceph dashboard ac-user-create <username> <password> administrator