10 K8S 持久化存储 Ceph


Ceph 介绍

为什么要用 Ceph

  1. Ceph是当前非常流行的开源分布式存储系统,具有高扩展性、高性能、高可靠性等优点,同时提供块存储服务(rbd)、对象存储服务(rgw)以及文件系统存储服务(cephfs)。
  2. Ceph在存储的时候充分利用存储节点的计算能力,在存储每一个数据时都会通过计算得出该数据的位置,尽量的分布均衡。
  3. 目前也是OpenStack的主流后端存储,随着OpenStack在云计算领域的广泛使用,ceph也变得更加炙手可热。
  4. 国内目前使用ceph搭建分布式存储系统较为成功的企业有x-sky,深圳元核云,上海UCloud等三家企业。
  5. Ceph设计思想:集群可靠性、集群可扩展性、数据安全性、接口统一性、充分发挥存储设备自身的计算能力、去除中心化。

Ceph 架构介绍

  1. Ceph使用RADOS提供对象存储,通过librados封装库提供多种存储方式的文件和对象转换。
  2. 外层通过RGW(Object,有原生的API,而且也兼容Swift和S3的API,适合单客户端使用)、RBD(Block,支持精简配置、快照、克隆,适合多客户端有目录结构)、CephFS(File,Posix接口,支持快照,适合更新变动少的数据,没有目录结构不能直接打开)将数据写入存储。
1
2
3
4
5
6
7
8
9
10
11
- 高性能  
1. 摒弃了传统的集中式存储元数据寻址的方案,采用CRUSH算法,数据分布均衡,并行度高
2. 考虑了容灾域的隔离,能够实现各类负载的副本放置规则,例如跨机房、机架感知等
3. 能够支持上千个存储节点的规模,支持TB到PB级的数据
- 高可扩展性
1. 去中心化
2. 扩展灵活
3. 随着节点增加而线性增长
- 特性丰富
1. 支持三种存储接口:块存储、文件存储、对象存储
2. 支持自定义接口,支持多种语言驱动

Ceph 核心概念

RADOS

  1. 全称Reliable Autonomic Distributed Object Store,即可靠的、自动化的、分布式对象存储系统。
  2. RADOS是Ceph集群的精华,用户实现数据分配、Failover等集群操作。

Librados

  1. Rados提供库,因为RADOS是协议很难直接访问,因此上层的RBD、RGW和CephFS都是通过librados访问的。
  2. 目前提供PHP、Ruby、Java、Python、C和C++支持。

Crush

  1. Crush算法是Ceph的两大创新之一,通过Crush算法的寻址操作,Ceph得以摒弃了传统的集中式存储元数据寻址方案。
  2. 而Crush算法在一致性哈希基础上很好的考虑了容灾域的隔离,使得Ceph能够实现各类负载的副本放置规则,例如跨机房、机架感知等。
  3. 同时,Crush算法有相当强大的扩展性,理论上可以支持数千个存储节点,这为Ceph在大规模云环境中的应用提供了先天的便利。
1
2
1. Crush 算法 数据平均分配到各个节点上,访问的时候把数据拼起来获取 
2. Crush 类似索引 有地址记录数据存放在哪里

Pool

  1. Pool是存储对象的逻辑分区,它规定了数据冗余的类型和对应的副本分布策略(默认3副本 )。
  2. 支持两种类型:副本(replicated)和 纠删码( Erasure Code)

PG

  1. PG( placement group)是一个放置策略组,它是对象的集合,该集合里的所有对象都具有相同的放置策略。
  2. 简单点说就是相同PG内的对象都会放到相同的硬盘上,PG是ceph的逻辑概念,服务端数据均衡和恢复的最小粒度就是PG。
  3. 一个PG包含多个OSD,引入PG这一层其实是为了更好的分配数据和定位数据;

Object

  1. 简单来说块存储读写快,不利于共享,文件存储读写慢,利于共享。
  2. 能否弄一个读写快,利于共享的出来呢。于是就有了对象存储。最底层的存储单元,包含元数据和原始数据。

Ceph 核心组件

OSD

  1. OSD是负责物理存储的进程,一般配置成和磁盘一一对应,一块磁盘启动一个OSD进程。
  2. 主要功能是存储数据、复制数据、平衡数据、恢复数据,以及与其它OSD间进行心跳检查,负责响应客户端请求返回具体数据的进程等;
1
2
3
4
# Pool、PG和OSD的关系:
1. 1个Pool里有很多PG;
2. 1个PG里包含一堆对象,1个对象只能属于一个PG;
3. PG有主从之分,一个PG分布在不同的OSD上(针对三副本类型);

Monitor

  1. 1个Ceph集群需要多个Monitor组成的小集群,它们通过Paxos同步数据,用来保存OSD的元数据。
  2. 负责坚实整个Ceph集群运行的Map视图(如OSD Map、Monitor Map、PG Map和CRUSH Map),维护集群的健康状态,维护展示集群状态的各种图表,管理集群客户端认证与授权;
  3. Monitor生产上至少3个组成高可用。
  4. 定期探测组件的健康状态。
1
1. osd想要什么数据 去 Monitor 里的 OSD Map 里面获取

MDS

  1. MDS全称Ceph Metadata Server,是CephFS服务依赖的元数据服务。
  2. 负责保存文件系统的元数据,管理目录结构。
  3. 对象存储块设备存储不需要元数据服务;

Mgr

  1. ceph 官方开发了 ceph-mgr,主要目标实现 ceph 集群的管理,为外界提供统一的入口。
  2. 例如 cephmetrics、zabbix、calamari、promethus。
  3. Mgr可以作为主从模式,挂了不影响集群使用。

RGW

  1. RGW 全称RADOS gateway,是Ceph对外提供的对象存储服务,接口与S3和Swift兼容。

Admin

  1. Ceph常用管理接口通常都是命令行工具,如rados、ceph、rbd等命令 。
  2. 另外Ceph还有可以有一个专用的管理节点,在此节点上面部署专用的管理工具来实现近乎集群的一些管理工作,如集群部署,集群组件管理等。

Ceph 三种存储类型

块存储(RBD)

1
2
3
4
5
6
7
8
9
10
11
12
13
- 优点:
* 通过Raid与LVM等手段,对数据提供了保护;
* 多块廉价的硬盘组合起来,提高容量;
* 多块磁盘组合出来的逻辑盘,提升读写效率;

- 缺点:
* 采用SAN架构组网时,光纤交换机,造价成本高;
* 主机之间无法共享数据;

- 使用场景
* docker容器、虚拟机磁盘存储分配;
* 日志存储;
* 文件存储;

文件存储(CephFS)

1
2
3
4
5
6
7
8
9
10
11
12
- 优点:
* 造价低,随便一台机器就可以了;
* 方便文件共享;

- 缺点:
* 读写速率低;
* 传输速率慢;

- 使用场景
* 日志存储;
* FTP、NFS;
* 其它有目录结构的文件存储

对象存储(Object)(适合更新变动较少的数据)

1
2
3
4
5
6
7
- 优点:
* 具备块存储的读写高速;
* 具备文件存储的共享等特性;

- 使用场景
* 图片存储;
* 视频存储;

io ceph 流程

  1. client 访问 Monitor map 拿数据
  2. 然后去OSD去找文件,OSD里面有主从概念,主提供服务,副本不做改动,通过盘符标识(SSD/HDD),分配主从节点。

  1. 读数据 流程到返回
  2. 写数据 强一致性,主副本先写,写完后同步从副本,三个副本之间通信数据一致后,数据才可以继续读取

小总结

  1. 为什么用ceph: 可扩展,节省成本,支持接口多
  2. 架构:分布式架构,多接口,RADOS -> Librados -> RGW,RBD,CephFS ,每个组件分布式,数据也是分布式
  3. 三种存储类型: RBD(块存储),CephFS(文件存储),对象存储(object)

Ceph 集群部署

Ceph 版本选择

  1. 官网安装 最新版本
  2. 手动安装 内网yum源 安装指定版本

Ceph版本来源介绍

  1. Ceph 社区最新版本是 14,而 Ceph 12 是市面用的最广的稳定版本。
  2. 第一个 Ceph 版本是 0.1 ,要回溯到 2008 年 1 月。
  3. 多年来,版本号方案一直没变,直到 2015 年 4 月 0.94.1 ( Hammer 的第一个修正版)发布后,为了避免 0.99 (以及 0.100 或 1.00 ?),制定了新策略。
1
2
3
4
5
6
7
8
9
x.0.z - 开发版(给早期测试者和勇士们)

x.1.z - 候选版(用于测试集群、高手们)

x.2.z - 稳定、修正版(给用户们)

x 将从 9 算起,它代表 Infernalis ( I 是第九个字母),这样第九个发布周期的第一个开发版就是 9.0.0 ;后续的开发版依次是 9.0.1 、 9.0.2 等等。

ceph不好招人,对数据存在敬畏之心,小心操作,数据的安全性和一致性太重要了
版本名称 版本号 发布时间
Argonaut 0.48版本(LTS) 2012年6月3日
Bobtail 0.56版本(LTS) 2013年5月7日
Cuttlefish 0.61版本 2013年1月1日
Dumpling 0.67版本(LTS) 2013年8月14日
Emperor 0.72版本 2013年11月9
Firefly 0.80版本(LTS) 2014年5月
Giant Giant October 2014 - April 2015
Hammer Hammer April 2015 - November 2016
Infernalis Infernalis November 2015 - June 2016
Jewel 10.2.9 2016年4月
Kraken 11.2.1 2017年10月
Luminous 12.2.12 2017年10月
mimic 13.2.7 2018年5月
nautilus 14.2.5 2019年2月
1
2
# 本次实验 nautilus
# 成熟版本 Luminous

Luminous 新版本特性

1. Bluestore

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1. ceph-osd的新后端存储BlueStore已经稳定,是新创建的OSD的默认设置。
# Ceph BlueStore 与 FileStore
# FileStore 先格式化系统盘 把数据写入磁盘形成文件 再写入到 RADOS
# BlueStore 直接转化,无需格式化,直接管理裸盘

# BlueStore通过直接管理物理HDD或SSD而不使用诸如XFS的中间文件系统,来管理每个OSD存储的数据,这提供了更大的性能和功能。
# BlueStore支持Ceph存储的所有的完整的数据和元数据校验。
# BlueStore内嵌支持使用zlib,snappy或LZ4进行压缩。(Ceph还支持zstd进行RGW压缩,但由于性能原因,不为BlueStore推荐使用zstd)

2. 集群的总体可扩展性有所提高。已经成功测试了多达10,000个OSD的集群。按实际走100个osd应该稳定。

3. ceph-mgr
# ceph-mgr是一个新的后台进程,这是任何Ceph部署的必须部分。虽然当ceph-mgr停止时,IO可以继续,但是度量不会刷新,并且某些与度量相关的请求(例如,ceph df)可能会被阻止。
# 我们建议您多部署ceph-mgr的几个实例来实现可靠性。
# ceph-mgr守护进程daemon包括基于REST的API管理。注:API仍然是实验性质的,目前有一些限制,但未来会成为API管理的基础。
# ceph-mgr还包括一个Prometheus插件。
# ceph-mgr现在有一个Zabbix插件。使用zabbix_sender,它可以将集群故障事件发送到Zabbix Server主机。这样可以方便地监视Ceph群集的状态,并在发生故障时发送通知。

安装前准备

1
2
3
4
# 我自己重新创建了3台 阿里云主机
# cephnode01 172.31.228.59
# cephnode02 172.31.228.60
# cephnode03 172.31.228.61
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
(1)关闭防火墙:
systemctl stop firewalld
systemctl disable firewalld

(2)关闭selinux:
sed -i 's/enforcing/disabled/' /etc/selinux/config
setenforce 0

(3)关闭NetworkManager
systemctl disable NetworkManager
systemctl stop NetworkManager

(4)添加主机名与IP对应关系:
vim /etc/hosts

172.31.228.59 cephnode01
172.31.228.60 cephnode02
172.31.228.61 cephnode03

(5)设置主机名:
[root@ceph ~]# hostnamectl set-hostname cephnode01
[root@ceph ~]# hostnamectl set-hostname cephnode02
[root@ceph ~]# hostnamectl set-hostname cephnode03

(6)同步网络时间和修改时区
systemctl restart chronyd.service && systemctl enable chronyd.service
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

(7)设置文件描述符
echo "ulimit -SHn 102400" >> /etc/rc.local
cat >> /etc/security/limits.conf << EOF
* soft nofile 65535
* hard nofile 65535

(8)内核参数优化
cat >> /etc/sysctl.conf << EOF
kernel.pid_max = 4194303
echo "vm.swappiness = 0" /etc/sysctl.conf
EOF
sysctl -p

(9)在cephnode01上配置免密登录到cephnode02、cephnode03
ssh-keygen
ls -l .ssh/
ssh-copy-id root@cephnode02
ssh-copy-id root@cephnode03
ssh root@cephnode03
ssh root@cephnode02

(10)read_ahead,通过数据预读并且记载到随机访问内存方式提高磁盘读操作
echo "8192" > /sys/block/sda/queue/read_ahead_kb

(11) I/O Scheduler,SSD要用noop,SATA/SAS使用deadline
echo "deadline" >/sys/block/sd[x]/queue/scheduler
echo "noop" >/sys/block/sd[x]/queue/scheduler

安装内网yum源

这一步有问题 直接用下面的 阿里云源

1. 安装httpd、createrepo 和 epel源

1
yum install httpd createrepo epel-release -y

2. 编辑yum源文件

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
[root@cephnode01 ~]# vim /etc/yum.repos.d/ceph.repo 

[Ceph]
name=Ceph packages for $basearch
baseurl=http://mirrors.163.com/ceph/rpm-nautilus/el7/$basearch
enabled=1
gpgcheck=1
type=rpm-md
gpgkey=https://download.ceph.com/keys/release.asc
priority=1

[Ceph-noarch]
name=Ceph noarch packages
baseurl=http://mirrors.163.com/ceph/rpm-nautilus/el7/noarch
enabled=1
gpgcheck=1
type=rpm-md
gpgkey=https://download.ceph.com/keys/release.asc
priority=1

[ceph-source]
name=Ceph source packages
baseurl=http://mirrors.163.com/ceph/rpm-nautilus/el7/SRPMS
enabled=1
gpgcheck=1
type=rpm-md
gpgkey=https://download.ceph.com/keys/release.asc

3. 下载Ceph 相关rpm包

1
[root@cephnode01 ~]# yum --downloadonly --downloaddir=/var/www/html/ceph/rpm-nautilus/el7/x86_64/ install ceph ceph-radosgw

4. 下载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
# 自作源的时候 要下载这些依赖
wget -P /var/www/html/ceph/rpm-nautilus/el7/srpms/ mirrors.163.com/ceph/rpm-nautilus/el7/SRPMS/ceph-14.2.4-0.el7.src.rpm
wget -P /var/www/html/ceph/rpm-nautilus/el7/srpms/ mirrors.163.com/ceph/rpm-nautilus/el7/SRPMS/ceph-deploy-2.0.1-0.src.rpm
wget -P /var/www/html/ceph/rpm-nautilus/el7/noarch/ mirrors.163.com/ceph/rpm-nautilus/el7/noarch/ceph-deploy-2.0.1-0.noarch.rpm
wget -P /var/www/html/ceph/rpm-nautilus/el7/noarch/ mirrors.163.com/ceph/rpm-nautilus/el7/noarch/ceph-grafana-dashboards-14.2.4-0.el7.noarch.rpm
wget -P /var/www/html/ceph/rpm-nautilus/el7/noarch/ mirrors.163.com/ceph/rpm-nautilus/el7/noarch/ceph-mgr-dashboard-14.2.4-0.el7.noarch.rpm
wget -P /var/www/html/ceph/rpm-nautilus/el7/noarch/ mirrors.163.com/ceph/rpm-nautilus/el7/noarch/ceph-mgr-diskprediction-cloud-14.2.4-0.el7.noarch.rpm
wget -P /var/www/html/ceph/rpm-nautilus/el7/noarch/ mirrors.163.com/ceph/rpm-nautilus/el7/noarch/ceph-mgr-diskprediction-local-14.2.4-0.el7.noarch.rpm
wget -P /var/www/html/ceph/rpm-nautilus/el7/noarch/ mirrors.163.com/ceph/rpm-nautilus/el7/noarch/ceph-mgr-rook-14.2.4-0.el7.noarch.rpm
wget -P /var/www/html/ceph/rpm-nautilus/el7/noarch/ mirrors.163.com/ceph/rpm-nautilus/el7/noarch/ceph-mgr-ssh-14.2.4-0.el7.noarch.rpm
wget -P /var/www/html/ceph/rpm-nautilus/el7/noarch/ mirrors.163.com/ceph/rpm-nautilus/el7/noarch/ceph-release-1-1.el7.noarch.rpm
wget -P /var/www/html/ceph/rpm-nautilus/el7/srpms/ mirrors.163.com/ceph/rpm-nautilus/el7/SRPMS/ceph-release-1-1.el7.src.rpm
wget -P /var/www/html/ceph/rpm-nautilus/el7/srpms/ mirrors.163.com/ceph/rpm-nautilus/el7/SRPMS/ceph-medic-1.0.4-16.g60cf7e9.el7.src.rpm
wget -P /var/www/html/ceph/rpm-nautilus/el7/noarch/ mirrors.163.com/ceph/rpm-nautilus/el7/noarch/repodata/repomd.xml
wget -P /var/www/html/ceph/rpm-nautilus/el7/srpms/ mirrors.163.com/ceph/rpm-nautilus/el7/SRPMS/repodata/repomd.xml
wget -P /var/www/html/ceph/rpm-nautilus/el7/noarch/repodata/ mirrors.163.com/ceph/rpm-nautilus/el7/noarch/repodata/a4bf0ee38cd4e64fae2d2c493e5b5eeeab6cf758beb7af4eec0bc4046b595faf-filelists.sqlite.bz2
wget -P /var/www/html/ceph/rpm-nautilus/el7/noarch/repodata/ mirrors.163.com/ceph/rpm-nautilus/el7/noarch/repodata/183278bb826f5b8853656a306258643384a1547c497dd8b601ed6af73907bb22-other.sqlite.bz2
wget -P /var/www/html/ceph/rpm-nautilus/el7/srpms/repodata/ mirrors.163.com/ceph/rpm-nautilus/el7/SRPMS/repodata/52bf459e39c76b2ea2cff2c5340ac1d7b5e17a105270f5f01b454d5a058adbd2-filelists.sqlite.bz2
wget -P /var/www/html/ceph/rpm-nautilus/el7/srpms/repodata mirrors.163.com/ceph/rpm-nautilus/el7/SRPMS/repodata/4f3141aec1132a9187ff5d1b4a017685e2f83a761880884d451a288fcedb154e-primary.sqlite.bz2
wget -P /var/www/html/ceph/rpm-nautilus/el7/srpms/repodata/ mirrors.163.com/ceph/rpm-nautilus/el7/SRPMS/repodata/0c554884aa5600b1311cd8f616aa40d036c1dfc0922e36bcce7fd84e297c5357-other.sqlite.bz2
wget -P /var/www/html/ceph/rpm-nautilus/el7/noarch/repodata/ mirrors.163.com/ceph/rpm-nautilus/el7/noarch/repodata/597468b64cddfc386937869f88c2930c8e5fda3dd54977c052bab068d7438fcb-primary.sqlite.bz2

wget -P /var/www/html/ceph/rpm-nautilus/el7/noarch/repodata/ http://mirrors.163.com/ceph/rpm-nautilus/el7/noarch/repodata/9a25e39d0c5038776cd0385513e275c6a4fd22c4a420a2097f03bac8d20fc2ab-primary.xml.gz
wget -P /var/www/html/ceph/rpm-nautilus/el7/srpms/repodata/ http://mirrors.163.com/ceph/rpm-nautilus/el7/SRPMS/repodata/d65e1c530f969af5458c89e0933adbee9a5192ccab209cbeb8f0887c887aee75-primary.xml.gz
wget -P /var/www/html/ceph/rpm-nautilus/el7/noarch/repodata/ http://mirrors.163.com/ceph/rpm-nautilus/el7/noarch/repodata/b98aa90d4606e473035f3cc0fa28dcb68cac506fea2ac1b62ffe5b4f9dcf6c73-filelists.xml.gz
wget -P /var/www/html/ceph/rpm-nautilus/el7/srpms/repodata/ http://mirrors.163.com/ceph/rpm-nautilus/el7/SRPMS/repodata/eb9fad1d84b372046f07f437219700b5ae5872e65eae396f88b7eaf05da89646-other.xml.gz
wget -P /var/www/html/ceph/rpm-nautilus/el7/srpms/repodata/ http://mirrors.163.com/ceph/rpm-nautilus/el7/SRPMS/repodata/9334c7e361a2e2ec768c1df34e386f15223abee6227b0fd4c5ff953bab4c3ba2-filelists.xml.gz
wget -P /var/www/html/ceph/rpm-nautilus/el7/noarch/repodata/ http://mirrors.163.com/ceph/rpm-nautilus/el7/noarch/repodata/af3ec697842e36c456331b347577225f288124b407d87a173a9e08bf9a482164-other.xml.gz

更新yum源

1
2
createrepo --update  /var/www/html/ceph/rpm-nautilus
[root@cephnode01 rpm-nautilus]# cp -a repodata el7/x86_64/
1
2
3
[root@cephnode01 rpm-nautilus]# systemctl start httpd
[root@cephnode01 rpm-nautilus]# netstat -tnlp|grep 80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 11639/httpd

使用阿里云yum源 安装Ceph集群

1. 编辑yum源

  1. 将yum源同步到其它节点并提前做好 yum makecache
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 三台都操作
[root@cephnode01 html]# vim /etc/yum.repos.d/ceph.repo

[ceph]
name=ceph
baseurl=http://mirrors.aliyun.com/ceph/rpm-nautilus/el7/x86_64/
gpgcheck=0
priority=1

[ceph-noarch]
name=cephnoarch
baseurl=http://mirrors.aliyun.com/ceph/rpm-nautilus/el7/noarch/
gpgcheck=0
priority=1

[ceph-source]
name=Ceph source packages
baseurl=http://mirrors.aliyun.com/ceph/rpm-nautilus/el7/SRPMS
gpgcheck=0
priority=1
1
2
yum clean all
yum makecache

2. 安装ceph-deploy(确认ceph-deploy版本是否为2.0.1)

1
2
3
4
5
[root@cephnode01 rpm-nautilus]# yum list|grep ceph
[root@cephnode01 rpm-nautilus]# yum install ceph-deploy -Y

[root@cephnode01 rpm-nautilus]# ceph-deploy --version
2.0.1

3. 创建一个my-cluster目录

  1. 所有命令在此目录下进行(文件位置和名字可以随意)
  2. 生产上按照项目启目录名字也可以,这个是测试用的
1
2
mkdir /my-cluster
cd /my-cluster

4. 创建一个Ceph集群

1
2
3
4
5
6
7
8
9
[root@cephnode01 my-cluster]# ceph-deploy new cephnode01 cephnode02 cephnode03 

...
[ceph_deploy.new][DEBUG ] Monitor cephnode03 at 172.31.228.61
[ceph_deploy.new][DEBUG ] Monitor initial members are ['cephnode01', 'cephnode02', 'cephnode03']
[ceph_deploy.new][DEBUG ] Monitor addrs are ['172.31.228.59', '172.31.228.60', '172.31.228.61'] # Monitor地址
[ceph_deploy.new][DEBUG ] Creating a random mon key...
[ceph_deploy.new][DEBUG ] Writing monitor keyring to ceph.mon.keyring...
[ceph_deploy.new][DEBUG ] Writing initial config to ceph.conf...

5. 安装Ceph软件(每个节点执行)

1
2
3
4
[root@cephnode01 my-cluster]# yum -y install epel-release
[root@cephnode01 my-cluster]# yum install -y ceph
[root@cephnode01 my-cluster]# ceph -v
ceph version 14.2.6 (f0aa067ac7a02ee46ea48aa26c6e298b5ea272e9) nautilus (stable)

6. 生成monitor检测集群所使用的的秘钥

1
[root@cephnode01 my-cluster]# ceph-deploy mon create-initial

7. 查看基本配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@cephnode01 my-cluster]# ls -l
total 16
-rw-r--r-- 1 root root 253 Jan 15 09:38 ceph.conf # 基础配置
-rw-r--r-- 1 root root 5096 Jan 15 09:38 ceph-deploy-ceph.log # 记录安装过程
-rw------- 1 root root 73 Jan 15 09:38 ceph.mon.keyring
-rw------- 1 root root 113 Jan 15 10:25 ceph.bootstrap-mds.keyring # 秘钥 用于交互
-rw------- 1 root root 113 Jan 15 10:25 ceph.bootstrap-mgr.keyring
-rw------- 1 root root 113 Jan 15 10:25 ceph.bootstrap-osd.keyring
-rw------- 1 root root 113 Jan 15 10:25 ceph.bootstrap-rgw.keyring
-rw------- 1 root root 151 Jan 15 10:25 ceph.client.admin.keyring



[root@cephnode01 my-cluster]# cat ceph.conf
[global]
fsid = 4ed819cf-39be-4a7c-9216-effcae715c58 # 集群编号
mon_initial_members = cephnode01, cephnode02, cephnode03
mon_host = 172.31.228.59,172.31.228.60,172.31.228.61 # 集群成员
auth_cluster_required = cephx
auth_service_required = cephx
auth_client_required = cephx

8. 安装Ceph CLI,方便执行一些管理命令

1
[root@cephnode01 my-cluster]# ceph-deploy admin cephnode01 cephnode02 cephnode03
1
2
3
4
5
6
7
8
# 其他节点下会生成
[root@cephnode02 ceph]# cd /etc/ceph/
[root@cephnode02 ceph]# ls -l
total 12
-rw------- 1 root root 151 Jan 15 10:28 ceph.client.admin.keyring # 管理员的秘钥
-rw-r--r-- 1 root root 253 Jan 15 10:28 ceph.conf
-rw-r--r-- 1 root root 92 Jan 9 03:44 rbdmap
-rw------- 1 root root 0 Jan 15 10:25 tmpk0SexV

9. 配置mgr,用于管理集群

1
2
3
4
5
[root@cephnode01 my-cluster]# ceph-deploy mgr create cephnode01 cephnode02 cephnode03

...
[cephnode03][INFO ] Running command: systemctl start ceph-mgr@cephnode03 # 启动并设置成开机启动
[cephnode03][INFO ] Running command: systemctl enable ceph.target

10. 部署rgw

1
2
3
4
# 生产上多机器安装 rgw 对象存储 用nginx做负载均衡代理
[root@cephnode01 my-cluster]# yum install -y ceph-radosgw
# 加到集群里
[root@cephnode01 my-cluster]# ceph-deploy rgw create cephnode01

11. 部署MDS(CephFS)

1
2
3
4
[root@cephnode01 my-cluster]# ceph-deploy mds create cephnode01 cephnode02 cephnode03 
...
[cephnode03][INFO ] Running command: systemctl start ceph-mds@cephnode03 # 开机自启动
[cephnode03][INFO ] Running command: systemctl enable ceph.target

12. 阿里云购买云盘

  1. 为每台实例购买云盘,按照分区购买后,挂载到实例上
  2. 高效云盘,20G,可用区C
1
2
3
4
5
[root@cephnode01 my-cluster]# lsblk 
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
vda 253:0 0 40G 0 disk
└─vda1 253:1 0 40G 0 part /
vdb 253:16 0 20G 0 disk 裸盘

13. 添加osd

1
2
3
4
5
6
7
8
9
10
# 该命令可以将 裸盘 vdb 自动格式化成ceph BlueStore 认识的格式 
[root@cephnode01 my-cluster]# ceph-deploy osd create --data /dev/vdb cephnode01

...
[cephnode01][WARNIN] --> ceph-volume lvm activate successful for osd ID: 0 # osd编号0,之前的版本都要手动执行
[cephnode01][WARNIN] --> ceph-volume lvm create successful for: /dev/vdb
[cephnode01][INFO ] checking OSD status...
[cephnode01][DEBUG ] find the location of an executable
[cephnode01][INFO ] Running command: /bin/ceph --cluster=ceph osd stat --format=json
[ceph_deploy.osd][DEBUG ] Host cephnode01 is now ready for osd use.
1
2
3
4
5
[root@cephnode01 my-cluster]# ceph osd tree
ID CLASS WEIGHT TYPE NAME STATUS REWEIGHT PRI-AFF
-1 0.01859 root default
-3 0.01859 host cephnode01
0 hdd 0.01859 osd.0 up 1.00000 1.00000 # 加入,标识hdd sata盘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 查看集群状态
[root@cephnode01 my-cluster]# ceph -s
cluster:
id: 4ed819cf-39be-4a7c-9216-effcae715c58
health: HEALTH_WARN # 当前是 WARN状态 pg太少了
Reduced data availability: 8 pgs inactive
Degraded data redundancy: 8 pgs undersized
OSD count 1 < osd_pool_default_size 3
too few PGs per OSD (8 < min 30)

services:
mon: 3 daemons, quorum cephnode01,cephnode02,cephnode03 (age 34m)
mgr: cephnode01(active, since 29m), standbys: cephnode03, cephnode02
osd: 1 osds: 1 up (since 2m), 1 in (since 2m)

data:
pools: 1 pools, 8 pgs
objects: 0 objects, 0 B
usage: 1.0 GiB used, 18 GiB / 19 GiB avail
pgs: 100.000% pgs not active
8 undersized+peered

把其他实例上的盘也加入到集群里

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 别忘记购买啊...
[root@cephnode02 ceph]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
vda 253:0 0 40G 0 disk
└─vda1 253:1 0 40G 0 part /
vdb 253:16 0 20G 0 disk

[root@cephnode03 ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
vda 253:0 0 40G 0 disk
└─vda1 253:1 0 40G 0 part /
vdb 253:16 0 20G 0 disk

# 添加osd 加入集群
[root@cephnode01 my-cluster]# ceph-deploy osd create --data /dev/vdb cephnode02
[root@cephnode01 my-cluster]# ceph-deploy osd create --data /dev/vdb cephnode03

[cephnode02][WARNIN] --> ceph-volume lvm activate successful for osd ID: 1
[cephnode02][WARNIN] --> ceph-volume lvm create successful for: /dev/vdb
[cephnode02][INFO ] checking OSD status...
[cephnode02][DEBUG ] find the location of an executable
[cephnode02][INFO ] Running command: /bin/ceph --cluster=ceph osd stat --format=json
[ceph_deploy.osd][DEBUG ] Host cephnode02 is now ready for osd use.
1
2
3
4
5
6
7
8
9
10
# 三块盘 每台实例加入一块
[root@cephnode01 my-cluster]# ceph osd tree
ID CLASS WEIGHT TYPE NAME STATUS REWEIGHT PRI-AFF
-1 0.05576 root default
-3 0.01859 host cephnode01
0 hdd 0.01859 osd.0 up 1.00000 1.00000
-5 0.01859 host cephnode02
1 hdd 0.01859 osd.1 up 1.00000 1.00000
-7 0.01859 host cephnode03
2 hdd 0.01859 osd.2 up 1.00000 1.00000
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 在磁盘不平衡或者新加盘的时候 会出现 WARN状态
# 等数据填满平衡时 会变成OK
[root@cephnode01 my-cluster]# ceph -s
cluster:
id: 4ed819cf-39be-4a7c-9216-effcae715c58
health: HEALTH_OK

services:
mon: 3 daemons, quorum cephnode01,cephnode02,cephnode03 (age 42m)
mgr: cephnode01(active, since 37m), standbys: cephnode03, cephnode02
osd: 3 osds: 3 up (since 33s), 3 in (since 33s)
rgw: 1 daemon active (cephnode01)

data:
pools: 4 pools, 32 pgs
objects: 187 objects, 1.2 KiB
usage: 3.0 GiB used, 54 GiB / 57 GiB avail
pgs: 32 active+clean

io:
recovery: 67 B/s, 4 objects/s
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 有报错的话 会看到详细报错
[root@cephnode01 my-cluster]# ceph health detail
HEALTH_OK

# 查看实时日志
[root@cephnode01 my-cluster]# ceph -w

# 查看每块盘使用的空间
[root@cephnode01 my-cluster]# ceph osd df
ID CLASS WEIGHT REWEIGHT SIZE RAW USE DATA OMAP META AVAIL %USE VAR PGS STATUS
0 hdd 0.01859 1.00000 19 GiB 1.0 GiB 3.6 MiB 0 B 1 GiB 18 GiB 5.28 1.00 32 up
1 hdd 0.01859 1.00000 19 GiB 1.0 GiB 3.6 MiB 0 B 1 GiB 18 GiB 5.28 1.00 32 up
2 hdd 0.01859 1.00000 19 GiB 1.0 GiB 3.6 MiB 0 B 1 GiB 18 GiB 5.28 1.00 32 up
TOTAL 57 GiB 3.0 GiB 11 MiB 0 B 3 GiB 54 GiB 5.28

# AVAIL 可用 里面有元数据信息
1
2
3
4
5
6
# 查看pool
[root@cephnode01 my-cluster]# ceph osd lspools
1 .rgw.root
2 default.rgw.control
3 default.rgw.meta
4 default.rgw.log
1
2
# 查看pg,pg是逻辑概念,磁盘规置
[root@cephnode01 my-cluster]# ceph pg dump

添加硬盘业务无感知

  1. 如果新加盘需要清空再键入
  2. 最好直接加入裸盘

ceph.conf

1
2
3
4
5
6
7
8
9
10
11
# 原始配置文件 
# 修改配置也在这个文件中
# 完成修改后 通过 ceph-deploy 推送
[root@cephnode01 my-cluster]# cat /my-cluster/ceph.conf
[global]
fsid = 4ed819cf-39be-4a7c-9216-effcae715c58
mon_initial_members = cephnode01, cephnode02, cephnode03
mon_host = 172.31.228.59,172.31.228.60,172.31.228.61
auth_cluster_required = cephx
auth_service_required = cephx
auth_client_required = cephx

书写格式

  1. 该配置文件采用init文件语法,#和;为注释,ceph集群在启动的时候会按照顺序加载所有的conf配置文件。 配置文件分为以下几大块配置。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
global: 全局配置。
osd: osd专用配置,可以使用osd.N,来表示某一个OSD专用配置,N为osd的编号,如0、2、1等。
mon: mon专用配置,也可以使用mon.A来为某一个monitor节点做专用配置,其中A为该节点的名称,ceph-monitor-2、ceph-monitor-1等。使用命令 ceph mon dump 可以获取节点的名称。
client: 客户端专用配置。

[root@cephnode01 my-cluster]# ceph mon dump
dumped monmap epoch 1
epoch 1
fsid 4ed819cf-39be-4a7c-9216-effcae715c58
last_changed 2020-01-15 10:25:08.611321
created 2020-01-15 10:25:08.611321
min_mon_release 14 (nautilus)
0: [v2:172.31.228.59:3300/0,v1:172.31.228.59:6789/0] mon.cephnode01
1: [v2:172.31.228.60:3300/0,v1:172.31.228.60:6789/0] mon.cephnode02
2: [v2:172.31.228.61:3300/0,v1:172.31.228.61:6789/0] mon.cephnode03

[root@cephnode01 my-cluster]# ceph mgr dump
[root@cephnode01 my-cluster]# ceph osd dump
  1. 配置文件可以从多个地方进行顺序加载,如果冲突将使用最新加载的配置,其加载顺序为。
1
2
3
4
5
6
# 不需要改动
$CEPH_CONF环境变量
-c 指定的位置
/etc/ceph/ceph.conf
~/.ceph/ceph.conf
./ceph.conf
  1. 配置文件还可以使用一些元变量应用到配置文件,如
1
2
3
4
5
$cluster:   当前集群名。
$type: 当前服务类型。
$id: 进程的标识符。
$host: 守护进程所在的主机名。
$name: 值为$type.$id。
  1. ceph.conf 详细参数
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
# 全局设置 默认接口 不用调整太多
[global]
fsid = xxxxxxxxxxxxxxx # 集群标识ID
mon host = 10.0.1.1,10.0.1.2,10.0.1.3 # monitor IP 地址
auth cluster required = cephx # 集群认证
auth service required = cephx # 服务认证
auth client required = cephx # 客户端认证
osd pool default size = 3 # 最小副本数 默认是3
osd pool default min size = 1 # 当副本只剩下1个的时候,数据就无法使用 PG 处于 degraded 状态不影响其 IO 能力,min_size是一个PG能接受IO的最小副本数
public network = 10.0.1.0/24 # 公共网络(monitorIP段) 用户使用的网络 万M网络
cluster network = 10.0.2.0/24 # 集群网络 集群数据同步走的网络 万M网络 两个网段隔离用户网络,走的更快
max open files = 131072 # 默认0#如果设置了该选项,Ceph会设置系统的max open fds
mon initial members = node1, node2, node3 # 初始monitor (由创建monitor命令而定)

##############################################################

[mon]
mon data = /var/lib/ceph/mon/ceph-$id
mon clock drift allowed = 1 # 默认值0.05 #monitor间的clock drift
mon osd min down reporters = 13 # 默认值1 向monitor报告down的最小OSD数 超过该数 数据无法使用
mon osd down out interval = 600 # 默认值300 标记一个OSD状态为down和out之前ceph等待的秒数 自动踢出集群
##############################################################

[osd]
osd data = /var/lib/ceph/osd/ceph-$id
osd mkfs type = xfs # 格式化系统类型 默认即可
osd max write size = 512 # 默认值90 #OSD一次可写入的最大值(MB)
osd client message size cap = 2147483648 # 默认值100 #客户端允许在内存中的最大数据(bytes)
osd deep scrub stride = 131072 # 默认值524288 健康检查 扫描数据一致 在Deep Scrub时候允许读取的字节数(bytes)
osd op threads = 16 # 默认值2 并发文件系统操作数
osd disk threads = 4 # 默认值1 #OSD密集型操作例如恢复和Scrubbing时的线程
osd map cache size = 1024 # 默认值500 # 保留OSD Map的缓存(MB)
osd map cache bl size = 128 # 默认值50 # OSD进程在内存中的OSD Map缓存(MB)
osd mount options xfs = "rw,noexec,nodev,noatime,nodiratime,nobarrier" # 默认值rw,noatime,inode64 #Ceph OSD xfs Mount选项
osd recovery op priority = 2 # 默认值10 恢复操作优先级,取值1-63,值越高占用资源越高
osd recovery max active = 10 # 默认值15 同一时间内活跃的恢复请求数
osd max backfills = 4 # 默认值10 一个OSD允许的最大backfills数
osd min pg log entries = 30000 # 默认值3000 修建PGLog是保留的最小PGLog数
osd max pg log entries = 100000 # 默认值10000 修建PGLog是保留的最大PGLog数
osd mon heartbeat interval = 40 # 默认值30 OSD ping一个monitor的时间间隔(默认30s)
ms dispatch throttle bytes = 1048576000 # 默认值 104857600 #等待派遣的最大消息数
objecter inflight ops = 819200 # 默认值1024 客户端流控,允许的最大未发送io请求数,超过阀值会堵塞应用io,为0表示不受限
osd op log threshold = 50 # 默认值5 一次显示多少操作的log
osd crush chooseleaf type = 0 # 默认值为1 CRUSH规则用到chooseleaf时的bucket的类型
##############################################################
[client]
rbd cache = true # 默认值 true RBD缓存
rbd cache size = 335544320 # 默认值33554432 RBD缓存大小(bytes)
rbd cache max dirty = 134217728 # 默认值25165824 缓存为write-back时允许的最大dirty字节数(bytes),如果为0,使用write-through
rbd cache max dirty age = 30 # 默认值1 在被刷新到存储盘前dirty数据存在缓存的时间(seconds)
rbd cache writethrough until flush = false # 默认值true 该选项是为了兼容linux-2.6.32之前的virtio驱动,避免因为不发送flush请求,数据不回写
# 设置该参数后,librbd会以writethrough的方式执行io,直到收到第一个flush请求,才切换为writeback方式。
rbd cache max dirty object = 2 # 默认值0 最大的Object对象数,默认为0,表示通过rbd cache size计算得到,librbd默认以4MB为单位对磁盘Image进行逻辑切分
# 每个chunk对象抽象为一个Object;librbd中以Object为单位来管理缓存,增大该值可以提升性能
rbd cache target dirty = 235544320 # 默认值16777216 开始执行回写过程的脏数据大小,不能超过 rbd_cache_max_dirty

Ceph RBD

RBD 介绍

  1. RBD即RADOS Block Device的简称,RBD块存储是最稳定且最常用的存储类型。
  2. RBD块设备类似磁盘可以被挂载。
  3. RBD块设备具有快照、多副本、克隆和一致性等特性,数据以条带化的方式存储在Ceph集群的多个OSD中。
  4. 如下是对Ceph RBD的理解。
1
2
3
4
5
6
7
8
9
10
1. RBD:                 就是 Ceph 里的块设备,一个 4T 的块设备的功能和一个 4T 的 SATA 类似,挂载的 RBD 就可以当磁盘用;
2. resizable: 这个块可大可小;
3. data striped: 这个块在Ceph里面是被切割成若干小块来保存,不然 1PB 的块怎么存的下;
4. thin-provisioned: 精简置备,1TB 的集群是能创建无数 1PB 的块的。其实就是块的大小和在 Ceph 中实际占用大小是没有关系的,刚创建出来的块是不占空间,今后用多大空间,才会在 Ceph 中占用多大空间。
举例:你有一个 32G 的 U盘,存了一个2G的电影,那么 RBD 大小就类似于 32G,而 2G 就相当于在 Ceph 中占用的空间 ;

# 总结
1. 快设备就好似一块盘,拥有快照备份的功能。
2. 这个块可以调整
3. 创建出来的块是不占用空间的,用多少使用占用多少
  1. 块存储本质就是将裸磁盘或类似裸磁盘(lvm)设备映射给主机使用,主机可以对其进行格式化并存储和读取数据,块设备读取速度快但是不支持共享。
1
2
3
1. ceph可以通过内核模块和librbd库提供块设备支持。
2. 客户端可以通过内核模块挂在rbd使用,客户端使用rbd块设备就像使用普通硬盘一样,可以对其就行格式化然后使用;
3. 客户应用也可以通过librbd使用ceph块,典型的是云平台的块存储服务(如下图),云平台可以使用rbd作为云的存储后端提供镜像存储、volume块或者客户的系统引导盘等。
  1. 使用场景:
1
2
3
4
1. 云平台(OpenStack做为云的存储后端提供镜像存储)
2. K8s容器
3. map成块设备直接使用
4. ISCIS,安装Ceph客户

RBD 常用命令

命令 功能
rbd create 创建块设备映像
rbd ls 列出 rbd 存储池中的块设备
rbd info 查看块设备信息
rbd diff 可以统计 rbd 使用量
rbd map 映射块设备
rbd showmapped 查看已映射块设备
rbd remove 删除块设备
rbd resize 更改块设备的大小

RBD 配置操作

RBD 挂载到操作系统

创建rbd使用的pool

1
2
3
4
5
# 32 pg_num 32 pgp_num 随着容量在增加扩容 生产要做规划
# pgp_num 描述pg位置
# osd 与 pg 算法 ?
ceph osd pool create rbd 32 32
# 创建标记 rbd
1
2
3
4
5
6
7
8
9
[root@cephnode01 my-cluster]# ceph osd pool create rbd  32 32
pool 'rbd' created

[root@cephnode01 my-cluster]# ceph osd pool ls detail
...
pool 5 'rbd' replicated size 3 min_size 2 crush_rule 0 object_hash rjenkins pg_num 32 pgp_num 32 autoscale_mode warn last_change 29 flags hashpspool stripe_width 0

[root@cephnode01 my-cluster]# ceph osd pool application enable rbd rbd
enabled application 'rbd' on pool 'rbd'

创建一个块设备

1
[root@cephnode01 my-cluster]# rbd create --size 10240 image01

查看快设备

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[root@cephnode01 my-cluster]# rbd ls
image01

[root@cephnode01 my-cluster]# rbd info image01
rbd image 'image01':
size 10 GiB in 2560 objects # 大小 放多少个对象
order 22 (4 MiB objects)
snapshot_count: 0
id: 11797bd74618
block_name_prefix: rbd_data.11797bd74618
format: 2
features: layering, exclusive-lock, object-map, fast-diff, deep-flatten
op_features:
flags:
create_timestamp: Wed Jan 15 15:20:46 2020
access_timestamp: Wed Jan 15 15:20:46 2020
modify_timestamp: Wed Jan 15 15:20:46 2020

[root@cephnode01 my-cluster]# rados -p rbd ls --all
rbd_id.image01
rbd_directory
rbd_info
rbd_object_map.11797bd74618
rbd_header.11797bd74618

禁用当前系统内核不支持的feature

1
[root@cephnode01 my-cluster]# rbd feature disable image01  exclusive-lock, object-map, fast-diff, deep-flatten

将块设备映射到系统内核

1
2
3
4
5
[root@cephnode01 my-cluster]# rbd map image01 
/dev/rbd0

[root@cephnode01 my-cluster]# ls -l /dev/rbd0
brw-rw---- 1 root disk 251, 0 Jan 15 15:26 /dev/rbd0

格式化块设备镜像

1
[root@cephnode01 my-cluster]# mkfs.xfs /dev/rbd0

mount到本地

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@cephnode01 my-cluster]# mount /dev/rbd0 /mnt

[root@cephnode01 my-cluster]# umount /mnt

[root@cephnode01 my-cluster]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 40G 2.3G 36G 6% /
/dev/rbd0 10G 33M 10G 1% /mnt
...


# 在/mnt下写数据相当于存放到 这个rbd里了
[root@cephnode01 my-cluster]# cd /mnt/
[root@cephnode01 mnt]# touch a
[root@cephnode01 mnt]# ls -l
-rw-r--r-- 1 root root 0 Jan 15 15:30 a

取消挂载

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
[root@cephnode01 mnt]# rbd showmapped
id pool namespace image snap device
0 rbd image01 - /dev/rbd0

[root@cephnode01 /]# umount /mnt

# 取消块设备和内核映射
[root@cephnode01 /]# rbd unmap image01
[root@cephnode01 /]# rbd showmapped
[root@cephnode01 /]# rbd ls
image01

[root@cephnode01 /]# rbd info image01
rbd image 'image01':
size 10 GiB in 2560 objects
order 22 (4 MiB objects)
snapshot_count: 0
id: 11797bd74618
block_name_prefix: rbd_data.11797bd74618
format: 2
features: layering
op_features:
flags:
create_timestamp: Wed Jan 15 15:20:46 2020
access_timestamp: Wed Jan 15 15:20:46 2020
modify_timestamp: Wed Jan 15 15:20:46 2020

# 虽然取消了挂载,但是里面的数据还在

删除RBD块设备

1
2
3
4
[root@cephnode01 /]# rbd rm image01
Removing image: 100% complete...done.

[root@cephnode01 /]# rbd ls

其他机器需要创建

1
2
ceph common k8s会讲到
创建快需要调用rbd命令 , 需要再机器上安装ceph common 才可以创建块

RBD 快照配置

1
2
3
[root@cephnode01 my-cluster]# rbd create --size 10240 image02
[root@cephnode01 my-cluster]# rbd ls
image02

创建快照

1
[root@cephnode01 my-cluster]# rbd snap create image02@image02_snap01

列出创建的快照

1
2
3
4
5
6
7
8
[root@cephnode01 my-cluster]# rbd snap list image02
SNAPID NAME SIZE PROTECTED TIMESTAMP
4 image02_snap01 10 GiB Wed Jan 15 15:58:41 2020

[root@cephnode01 my-cluster]# rbd ls -l
NAME SIZE PARENT FMT PROT LOCK
image02 10 GiB 2
image02@image02_snap01 10 GiB 2 # 快照 用于很重要的数据 可以用于回滚

查看快照详细信息

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
[root@cephnode01 my-cluster]# rbd info image02@image02_snap01
rbd image 'image02':
size 10 GiB in 2560 objects
order 22 (4 MiB objects)
snapshot_count: 1
id: 11b2d62f36b7
block_name_prefix: rbd_data.11b2d62f36b7
format: 2
features: layering, exclusive-lock, object-map, fast-diff, deep-flatten
op_features:
flags:
create_timestamp: Wed Jan 15 15:57:55 2020
access_timestamp: Wed Jan 15 15:57:55 2020
modify_timestamp: Wed Jan 15 15:57:55 2020
protected: False

[root@cephnode01 my-cluster]# rbd info image02
rbd image 'image02':
size 10 GiB in 2560 objects
order 22 (4 MiB objects)
snapshot_count: 1
id: 11b2d62f36b7
block_name_prefix: rbd_data.11b2d62f36b7
format: 2
features: layering, exclusive-lock, object-map, fast-diff, deep-flatten
op_features:
flags:
create_timestamp: Wed Jan 15 15:57:55 2020
access_timestamp: Wed Jan 15 15:57:55 2020
modify_timestamp: Wed Jan 15 15:57:55 2020

克隆快照(快照必须处于被保护状态才能被克隆)

1
2
3
4
5
6
7
8
9
10
11
# 保护状态就无法操作了
[root@cephnode01 my-cluster]# rbd snap protect image02@image02_snap01

# 创建一个新pool kube
[root@cephnode01 my-cluster]# ceph osd pool create kube 16 16
pool 'kube' created

[root@cephnode01 my-cluster]# rbd clone rbd/image02@image02_snap01 kube/image02_clone01

[root@cephnode01 my-cluster]# rbd ls -p kube
image02_clone01

查看快照的children

1
2
3
# 查看快照的子快照
[root@cephnode01 my-cluster]# rbd children image02
kube/image02_clone01

去掉快照的parent

1
2
3
4
5
# 取消克隆关系
[root@cephnode01 my-cluster]# rbd flatten kube/image02_clone01
Image flatten: 100% complete...done.
[root@cephnode01 my-cluster]# rbd children image02
# 这就成为了 独立的快照

恢复快照

1
2
3
# 回滚 一开始有5个文件 一直写 想回滚
[root@cephnode01 my-cluster]# rbd snap rollback image02@image02_snap01
Rolling back to snapshot: 100% complete...done.

删除快照

1
2
3
4
5
6
# 取消保护
[root@cephnode01 my-cluster]# rbd snap unprotect image02@image02_snap01
[root@cephnode01 my-cluster]# rbd snap remove image02@image02_snap01
Removing snap: 100% complete...done.

[root@cephnode01 my-cluster]# rbd snap list image02

RBD 镜像导出导入

导出RBD镜像

1
2
3
4
5
6
7
8
9
10
[root@cephnode01 my-cluster]# rbd export image02 /tmp/image02
Exporting image: 100% complete...done.

[root@cephnode01 tmp]# ls -lh /tmp/image02
-rw-r--r-- 1 root root 10G Jan 15 16:11 /tmp/image02

[root@cephnode01 tmp]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 40G 2.3G 36G 6% /
...

导入RBD镜像

1
2
3
4
5
6
7
8
9
10
[root@cephnode01 tmp]# rbd ls
image02
[root@cephnode01 tmp]# rbd remove image02
Removing image: 100% complete...done.
[root@cephnode01 tmp]# rbd ls

[root@cephnode01 tmp]# rbd import /tmp/image02 rbd/image02 --image-format 2
Importing image: 100% complete...done.
[root@cephnode01 tmp]# rbd ls
image02

RBD 扩容

1
2
3
4
5
6
7
8
[root@cephnode01 tmp]# rbd info image02|grep size
size 10 GiB in 2560 objects

[root@cephnode01 tmp]# rbd --image image02 resize --size 15240
Resizing image: 100% complete...done.

[root@cephnode01 tmp]# rbd info image02|grep size
size 15 GiB in 3810 objects

总结

1
2
3
4
5
1. 把rbd映射到文件系统挂载
2. 再通过nfs /etc/exports 暴露,映射共享到其他机器上
3. 快照 备份回滚,快照占用空间,可以定期拍摄快照,对重要的块进行快照,如果太大了 就导出备份
4. 克隆 到另外的集群
5. 数据分成3份 分到3个pg上 再分到3个osd上

Ceph 文件系统 CephFS

  1. Ceph File System (CephFS) 是与 POSIX 标准兼容的文件系统, 能够提供对 Ceph 存储集群上的文件访问.
  2. Jewel 版本 (10.2.0) 是第一个包含稳定 CephFS 的 Ceph 版本.
  3. CephFS 需要至少一个元数据服务器 (Metadata Server - MDS) daemon (ceph-mds) 运行, MDS daemon 管理着与存储在 CephFS 上的文件相关的元数据, 并且协调着对 Ceph 存储系统的访问。
  4. 对象存储的成本比起普通的文件存储还是较高,需要购买专门的对象存储软件以及大容量硬盘。如果对数据量要求不是海量,只是为了做文件共享的时候,直接用文件存储的形式好了,性价比高。

CephFS 架构

  1. 底层是核心集群所依赖的, 包括:
1
2
3
4
1. OSDs (ceph-osd):     CephFS 的数据和元数据就存储在 OSDs 上
2. MDS (ceph-mds): Metadata Servers, 管理着 CephFS 的元数据
3. Mons (ceph-mon): Monitors 管理着集群 Map 的主副本
Ceph 存储集群的协议层是 Ceph 原生的 librados 库, 与核心集群交互.

  1. 数据访问流程
1
2
3
1. client 访问MDS 获取数据的元数据(文件名,大小等信息) 
2. client 去 RADOS(OSD) 获取数据
3. RADOS(OSD) 和 MDS 通过 Journal Metadata 记录文件写入的操作,数据最终都存入RADOS中。

配置 CephFS MDS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 当前集群状态
[root@cephnode01 my-cluster]# ceph -s
cluster:
id: 4ed819cf-39be-4a7c-9216-effcae715c58
health: HEALTH_OK

services:
mon: 3 daemons, quorum cephnode01,cephnode02,cephnode03 (age 15m)
mgr: cephnode02(active, since 15m), standbys: cephnode03, cephnode01
osd: 3 osds: 3 up (since 15m), 3 in (since 21h)
rgw: 1 daemon active (cephnode01)

data:
pools: 6 pools, 80 pgs
objects: 196 objects, 1.9 KiB
usage: 3.0 GiB used, 54 GiB / 57 GiB avail
pgs: 80 active+clean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1. 要使用 CephFS, 至少就需要一个 metadata server 进程。
2. 可以手动创建一个 MDS, 也可以使用 ceph-deploy 或者 ceph-ansible 来部署 MDS。
3. 登录到ceph-deploy工作目录执行
[root@cephnode01 my-cluster]# cd /my-cluster/
[root@cephnode01 my-cluster]# ceph-deploy mds create cephnode01 cephnode02 cephnode03

...
[cephnode03][INFO ] Running command: systemctl enable ceph-mds@cephnode03
[cephnode03][INFO ] Running command: systemctl start ceph-mds@cephnode03
[cephnode03][INFO ] Running command: systemctl enable ceph.target

[root@cephnode01 my-cluster]# ps -ef|grep mds
ceph 957 1 0 08:34 ? 00:00:00 /usr/bin/ceph-mds -f --cluster ceph --id cephnode01 --setuser ceph --setgroup ceph
root 2640 2102 0 08:56 pts/0 00:00:00 grep --color=auto mds

[root@cephnode01 my-cluster]# tail -200 /var/log/ceph/ceph-mds.cephnode01.log

部署 Ceph 文件系统

  1. 部署一个 CephFS, 步骤如下:
1
2
3
4
5
1. 在一个 Mon 节点上创建 Ceph 文件系统.
2. 若使用 CephX 认证,需要创建一个访问 CephFS 的客户端
3. 挂载 CephFS 到一个专用的节点.
- 以 kernel client 形式挂载 CephFS
- 以 FUSE client 形式挂载 CephFS

创建一个 Ceph 文件系统

1. CephFS 需要两个 Pools

1
2
3
# cephfs-data 和 cephfs-metadata, 分别存储文件数据和文件元数据 
# ceph osd pool create cephfs-data 256 256
# ceph osd pool create cephfs-metadata 64 64
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@cephnode01 my-cluster]# ceph osd pool create cephfs-data 16 16
pool 'cephfs-data' created

[root@cephnode01 my-cluster]# ceph osd pool create cephfs-metadata 16 16
pool 'cephfs-metadata' created

[root@cephnode01 my-cluster]# ceph osd lspools
1 .rgw.root
2 default.rgw.control
3 default.rgw.meta
4 default.rgw.log
5 rbd
6 kube
7 cephfs-data
8 cephfs-metadata
1
2
3
# 注意
1. 一般 metadata pool 可以从相对较少的 PGs 启动,
2. 之后可以根据需要增加 PGs. 因为 metadata pool 存储着 CephFS 文件的元数据, 为了保证安全, 最好有较多的副本数. 为了能有较低的延迟, 可以考虑将 metadata 存储在 SSDs 上.

2. 创建一个 CephFS, 名字为 cephfs

1
2
[root@cephnode01 my-cluster]# ceph fs new cephfs cephfs-metadata cephfs-data
new fs with metadata pool 8 and data pool 7

3. 验证至少有一个 MDS 已经进入 Active 状态

1
2
3
[root@cephnode01 my-cluster]# ceph fs status cephfs

# 现在源数据的进程跑在 cephnode03上

4. 在 Monitor 上, 创建一个用户,用于访问CephFs

1
2
3
[root@cephnode01 my-cluster]# ceph auth get-or-create client.cephfs mon 'allow r' mds 'allow rw' osd 'allow rw pool=cephfs-data, allow rw pool=cephfs-metadata'
[client.cephfs]
key = AQCluh9eDsknLBAAjxABEQpF8vJeUt8Buk22Dg==

5. 验证key是否生效

1
2
3
4
5
6
7
[root@cephnode01 my-cluster]# ceph auth get client.cephfs
exported keyring for client.cephfs
[client.cephfs]
key = AQCluh9eDsknLBAAjxABEQpF8vJeUt8Buk22Dg==
caps mds = "allow rw" # 读写
caps mon = "allow r" # 读
caps osd = "allow rw pool=cephfs-data, allow rw pool=cephfs-metadata" # 读写

6. 检查CephFs和mds状态

1
2
3
4
5
6
7
8
9
10
11
[root@cephnode01 my-cluster]# ceph -s

[root@cephnode01 my-cluster]# ceph mds stat
cephfs:1 {0=cephnode03=up:active} 2 up:standby

[root@cephnode01 my-cluster]# ceph fs ls
name: cephfs, metadata pool: cephfs-metadata, data pools: [cephfs-data ]
# 文件系统名称 cephfs

[root@cephnode01 my-cluster]# ceph fs status
# 以上正常说明 cephfs 文件系统创建成功

挂载 CephFS 文件系统

以 kernel client 形式挂载 CephFS

1
2
3
4
5
# 找一台不在集群中的服务器测试挂载 
# 联系系统内核挂载文件系统,和挂载文件一样
# 缺点: 读写速度有限
1. 创建挂载目录 cephfs
[root@cephnode04 ~]# mkdir /cephfs
1
2
3
# secret 就是刚生成的秘钥 key = AQCluh9eDsknLBAAjxABEQpF8vJeUt8Buk22Dg==
2. 挂载目录
mount -t ceph 172.31.228.59:6789,172.31.228.60:6789,172.31.228.61:6789:/ /cephfs/ -o name=cephfs,secret=AQCluh9eDsknLBAAjxABEQpF8vJeUt8Buk22Dg==

1
2
3
# 开机自动挂载
3. 自动挂载
echo "mon1:6789,mon2:6789,mon3:6789:/ /cephfs ceph name=cephfs,secretfile=/etc/ceph/cephfs.key,_netdev,noatime 0 0" | sudo tee -a /etc/fstab
1
2
4. 验证是否挂载成功
stat -f /cephfs

以 FUSE client 形式挂载 CephFS

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
1. 安装ceph-common

[root@cephnode04 cephfs]# vim /etc/yum.repos.d/ceph.repo

[ceph]
name=ceph
baseurl=http://mirrors.aliyun.com/ceph/rpm-nautilus/el7/x86_64/
gpgcheck=0
priority=1

[ceph-noarch]
name=cephnoarch
baseurl=http://mirrors.aliyun.com/ceph/rpm-nautilus/el7/noarch/
gpgcheck=0
priority=1

[ceph-source]
name=Ceph source packages
baseurl=http://mirrors.aliyun.com/ceph/rpm-nautilus/el7/SRPMS
gpgcheck=0
priority=1

[root@cephnode04 cephfs]# yum install -y ceph-common
# 安装完成后 客户端就会有ceph和rbd命令
[root@cephnode04 cephfs]# ceph
[root@cephnode04 cephfs]# rbd
1
2
3
2. 安装ceph-fuse 
# 客户端工具,用ceph的方式挂载
yum install -y ceph-fuse
1
2
3
4
5
6
7
3. 将集群的ceph.conf拷贝到客户端
[root@cephnode04 ceph]# scp root@172.31.228.59:/etc/ceph/ceph.conf /etc/ceph/
[root@cephnode04 ceph]# scp root@172.31.228.59:/etc/ceph/ceph.client.admin.keyring /etc/ceph/
[root@cephnode04 ceph]# chmod 644 /etc/ceph/ceph.conf

[root@cephnode04 ceph]# ls
ceph.conf rbdmap
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
4. 使用 ceph-fuse 挂载 CephFS 
# 挂载之前把刚才的挂载umount
[root@cephnode04 ~]# umount /cephfs/

# 先去获取一下认证信息
[root@cephnode01 my-cluster]# ceph auth get client.cephfs
exported keyring for client.cephfs
[client.cephfs]
key = AQCluh9eDsknLBAAjxABEQpF8vJeUt8Buk22Dg==
caps mds = "allow rw"
caps mon = "allow r"
caps osd = "allow rw pool=cephfs-data, allow rw pool=cephfs-metadata"

# 写入到keyring 文件中
[root@cephnode04 ~]# vim /etc/ceph/ceph.client.cephfs.keyring

[client.cephfs]
key = AQCluh9eDsknLBAAjxABEQpF8vJeUt8Buk22Dg==
caps mds = "allow rw"
caps mon = "allow r"
caps osd = "allow rw pool=cephfs-data, allow rw pool=cephfs-metadata"


# 挂载
# ceph-fuse 自己的文件系统格式
[root@cephnode04 ~]# ceph-fuse --keyring /etc/ceph/ceph.client.cephfs.keyring --name client.cephfs -m 172.31.228.59:6789,172.31.228.60:6789,172.31.228.61:6789 /cephfs/

1
2
3
4
5
6
7
8
# 验证 CephFS 已经成功挂载

[root@cephnode04 ~]# stat -f /cephfs
File: "/cephfs"
ID: 0 Namelen: 255 Type: fuseblk
Block size: 4194304 Fundamental block size: 4194304
Blocks: Total: 4362 Free: 4362 Available: 4362
Inodes: Total: 1 Free: 0
1
2
3
4
# 自动挂载 
echo "none /cephfs fuse.ceph ceph.id=cephfs[,ceph.conf=/etc/ceph/ceph.conf],_netdev,defaults 0 0"| sudo tee -a /etc/fstab

echo "id=cephfs,conf=/etc/ceph/ceph.conf /mnt/ceph2 fuse.ceph _netdev,defaults 0 0"| sudo tee -a /etc/fstab
1
2
# 卸载 
fusermount -u /cephfs

存储文件测试并查看

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
# 在目录下写点东西
[root@cephnode04 ~]# touch test

# 看看存在pool里是什么样子
[root@cephnode01 my-cluster]# rados lspools

# 创建的是空文件 没有数据
[root@cephnode01 my-cluster]# rados -p cephfs-data ls --all

# 源文件数据
[root@cephnode01 my-cluster]# rados -p cephfs-metadata ls --all
601.00000000
602.00000000
600.00000000
603.00000000
1.00000000.inode
200.00000000
200.00000001
606.00000000
607.00000000
mds0_openfiles.0
608.00000000
604.00000000
500.00000000
mds_snaptable
605.00000000
mds0_inotable
100.00000000
mds0_sessionmap
609.00000000
400.00000000
100.00000000.inode
1.00000000

挂载小总结

1
2
3
# 推荐ceph-fuse 效率更高
# 实际应用中 其实也没什么区别 只不过ceph-fuse 是源生的可能更好
# 生产上如果追求少安装软件的话 用内核模式也可以

MDS主备与主主切换

配置主主模式

  1. 当cephfs的性能出现问题时,就应该配置多个活动的MDS。
  2. 通常是多个客户机应用程序并行的执行大量元数据操作,并且它们分别有自己单独的工作目录。这种情况下很适合使用多主MDS模式。
  3. 配置MDS多主模式
  4. 每个cephfs文件系统都有一个max_mds设置,可以理解为它将控制创建多少个主MDS。注意只有当实际的MDS个数大于或等于max_mds设置的值时,mdx_mds设置才会生效。
  5. 例如,如果只有一个MDS守护进程在运行,并且max_mds被设置为两个,则不会创建第二个主MDS。
1
2
3
4
5
# 设置完成后 存在两个主
[root@cephnode01 my-cluster]# ceph fs set cephfs max_mds 2

# 还原单主MDS
[root@cephnode01 my-cluster]# ceph fs set cephfs max_mds 1

配置备用 MDS

  1. 即使有多个活动的MDS,如果其中一个MDS出现故障,仍然需要备用守护进程来接管。因此,对于高可用性系统,实际配置max_mds时,最好比系统中MDS的总数少一个。
  2. 但如果你确信你的MDS不会出现故障,可以通过以下设置来通知ceph不需要备用MDS,否则会出现insufficient standby daemons available告警信息:
1
2
# 设置不需要备用MDS
ceph fs set <fsname> standby_count_wanted 0

Ceph Dashboard

  1. Ceph 的监控可视化界面方案很多—-grafana、Kraken。但是从Luminous开始,Ceph 提供了原生的Dashboard功能
  2. 通过Dashboard可以获取Ceph集群的各种基本状态信息。
  3. mimic版 (nautilus版) dashboard 安装。如果是 (nautilus版) 需要安装 ceph-mgr-dashboard

配置 Ceph Dashboard

1
2
3
4
5
6
7
8
9
10
1. 在每个mgr节点安装
# yum install ceph-mgr-dashboard
2. 开启mgr功能
# ceph mgr module enable dashboard
3. 生成并安装自签名的证书
# ceph dashboard create-self-signed-cert
4. 创建一个dashboard登录用户名密码
# ceph dashboard ac-user-create guest 1q2w3e4r administrator
5. 查看服务访问方式
# ceph mgr services
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
# 出现问题 ImportError: cannot import name UnrewindableBodyError
[root@cephnode01 my-cluster]# tail -200 /var/log/ceph/ceph-mgr.cephnode01.log

# 需要重新安装 urllib3
pip uninstall urllib3
yum install python-urllib3 -y
yum remove ceph-mgr-dashboard
yum install -y ceph-mgr-dashboard

# 在所有的mgr上都要装这个包 ,有1个的话只装1个
[root@cephnode01 my-cluster]# ceph mgr module enable dashboard

[root@cephnode01 my-cluster]# ceph mgr module ls
{
"enabled_modules": [
"dashboard",
"iostat",
"restful"
],
...

[root@cephnode01 my-cluster]# ceph dashboard create-self-signed-cert
Self-signed certificate created

[root@cephnode01 my-cluster]# ceph dashboard ac-user-create guest 1q2w3e4r administrator
{"username": "guest", "lastUpdate": 1579144411, "name": null, "roles": ["administrator"], "password": "$2b$12$ZwdxYdVcpKI7FCz2IZyKs.qR.fJrkGnxlNttZN8eoRbNHcqGdRZry", "email": null}

[root@cephnode01 my-cluster]# ceph mgr services
{
"dashboard": "https://cephnode02:8443/"
}

# web访问
https://47.240.15.208:8443

修改默认配置命令

1
2
3
4
5
指定集群dashboard的访问端口
# ceph config-key set mgr/dashboard/server_port 7000

指定集群 dashboard的访问IP
# ceph config-key set mgr/dashboard/server_addr $IP

开启Object Gateway管理功能

1
2
3
4
5
6
7
8
9
10
11
# 这块可能有问题 需要用到对象存储的时候 再网上查查
# 可以参考官方给出的开启方式开启

1、创建rgw用户
# radosgw-admin user create --uid=user01 --display-name=user01
2、提供Dashboard证书
# ceph dashboard set-rgw-api-access-key $access_key
# ceph dashboard set-rgw-api-secret-key $secret_key
3、配置rgw主机名和端口
# ceph dashboard set-rgw-api-host 10.151.30.125
4、刷新web页面

Promethus+Grafana 监控 Ceph

安装 grafana

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
1、配置yum源文件
# vim /etc/yum.repos.d/grafana.repo
[grafana]
name=grafana
baseurl=https://packages.grafana.com/oss/rpm
repo_gpgcheck=1
enabled=1
gpgcheck=1
gpgkey=https://packages.grafana.com/gpg.key
sslverify=1
sslcacert=/etc/pki/tls/certs/ca-bundle.crt

2.通过yum命令安装grafana
# yum -y install grafana

3.启动grafana并设为开机自启
[root@cephnode04 ~]# yum list | grep grafana
ceph-grafana-dashboards.noarch 2:14.2.6-0.el7 @ceph-noarch
grafana.x86_64 6.5.3-1 @grafana
pcp-webapp-grafana.noarch 4.3.2-3.el7_7 updates

# systemctl start grafana-server.service
# systemctl enable grafana-server.service

[root@cephnode04 ~]# netstat -antlp|grep grafana

# web访问:
http://47.240.10.142:3000/login admin/admin

安装 promethus

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
1、下载安装包,下载地址
https://prometheus.io/download/
wget https://github.com/prometheus/prometheus/releases/download/v2.14.0/prometheus-2.14.0.linux-amd64.tar.gz

2、解压压缩包
# tar fvxz prometheus-2.14.0.linux-amd64.tar.gz

3、将解压后的目录改名
# mv prometheus-2.14.0.linux-amd64 /opt/prometheus

4、查看promethus版本
# ./prometheus --version

5、配置系统服务启动
# vim /etc/systemd/system/prometheus.service
[Unit]
Description=Prometheus Monitoring System
Documentation=Prometheus Monitoring System

[Service]
ExecStart=/opt/prometheus/prometheus \
--config.file /opt/prometheus/prometheus.yml \
--web.listen-address=:9090

[Install]
WantedBy=multi-user.target

6、加载系统服务
# systemctl daemon-reload

7、启动服务和添加开机自启动
# systemctl start prometheus
# systemctl enable prometheus

# web访问
http://47.240.10.142:9090/graph

ceph mgr prometheus插件配置

1
2
3
4
5
6
7
8
9
10
11
12
# ceph mgr module enable prometheus
# netstat -nltp | grep mgr 检查端口
# curl 127.0.0.1:9283/metrics 测试返回值

[root@cephnode01 my-cluster]# ceph mgr services
{
"dashboard": "https://cephnode02:8443/",
"prometheus": "http://cephnode02:9283/"
}

# web访问 采集数据
http://47.240.15.208:9283/metrics

配置 promethus

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@cephnode04 prometheus]# vim /opt/prometheus/prometheus.yml 
...
scrape_configs:
# The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
- job_name: 'prometheus'

# metrics_path defaults to '/metrics'
# scheme defaults to 'http'.

static_configs:
- targets: ['localhost:9090']

- job_name: 'ceph_cluster'
honor_labels: true
scrape_interval: 5s
static_configs:
- targets: ['172.31.228.60:9283']
labels:
instance: ceph
...
1
2
3
# 重启promethus服务
[root@cephnode04 prometheus]# systemctl restart prometheus
[root@cephnode04 prometheus]# ps -ef|grep prometheus
1
2
# 检查prometheus服务器中是否添加成功
http://47.240.10.142:9090/targets

配置 grafana

1
2
3
4
5
6
1. 浏览器登录 grafana 管理界面  
2. 添加 data sources,点击 configuration --> data sources
3. 添加 dashboard,点击HOME--》find dashboard on grafana.com
4. 搜索ceph的dashboard
5. 点击HOME-->Import dashboard, 选择合适的dashboard,模板编号: 2842
6. avg(ceph_osd_apply_latency_ms) 关注延迟,如果到秒级,集群就变慢了,正常都是毫秒

K8S 接入 Ceph 存储

PV、PVC 概述

  1. 管理存储是管理计算的一个明显问题。PersistentVolume子系统为用户和管理员提供了一个API,用于抽象如何根据消费方式提供存储的详细信息。
  2. 于是引入了两个新的API资源:PersistentVolume和PersistentVolumeClaim
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1. PersistentVolume(PV)是集群中已由管理员配置的一段网络存储。 
集群中的资源就像一个节点是一个集群资源。
PV是诸如卷之类的卷插件,但是具有独立于使用PV的任何单个pod的生命周期。
该API对象包含存储的实现细节,即NFS,iSCSI或云提供商特定的存储系统。

2. PersistentVolumeClaim(PVC)是用户存储的请求。
它类似于pod。Pod消耗节点资源,PVC消耗存储资源。
pod可以请求特定级别的资源(CPU和内存)。
权限要求可以请求特定的大小和访问模式。

3. 虽然PersistentVolumeClaims允许用户使用抽象存储资源,但是常见的是,用户需要具有不同属性(如性能)的PersistentVolumes,用于不同的问题。
管理员需要能够提供多种不同于PersistentVolumes,而不仅仅是大小和访问模式,而不会使用户了解这些卷的实现细节。 对于这些需求,存在StorageClass资源。

4. StorageClass为集群提供了一种描述他们提供的存储的“类”的方法。
不同的类可能映射到服务质量级别,或备份策略,或者由群集管理员确定的任意策略。
Kubernetes本身对于什么类别代表是不言而喻的,这个概念有时在其他存储系统中称为“配置文件”

POD 动态供给

  1. 动态供给主要是能够自动帮你创建pv,需要多大的空间就创建多大的pv。
  2. k8s帮助创建pv,创建pvc就直接api调用存储类来寻找pv。
  3. 如果是存储静态供给的话,会需要我们手动去创建pv,如果没有足够的资源,找不到合适的pv,那么pod就会处于pending等待的状态。
  4. 而动态供给主要的一个实现就是StorageClass存储对象,其实它就是声明你使用哪个存储,然后帮你去连接,再帮你去自动创建pv。

小总结

  1. pv去存储里申请的一块空间,映射到pv上,作为物理卷存活在容器里
  2. POD使用pvc联系pv拿到存储
  3. 动态供给,省却手动创建pv,而是调用StorageClass帮我们去创建

POD 使用 RBD 做为持久数据卷

安装与配置

  1. RBD支持ReadWriteOnce,ReadOnlyMany两种模式
1
2
3
4
# 访问模式包括:
ReadWriteOnce 该volume只能被单个节点以读写的方式映射
ReadOnlyMany 该volume可以被多个节点以只读方式映射
ReadWriteMany 该volume只能被多个节点以读写的方式映射

配置 rbd-provisioner

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
# 配置rbd-provisioner 
cat >external-storage-rbd-provisioner.yaml<<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: rbd-provisioner
namespace: kube-system
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: rbd-provisioner
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: ["endpoints"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
- apiGroups: [""]
resources: ["services"]
resourceNames: ["kube-dns"]
verbs: ["list", "get"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: rbd-provisioner
subjects:
- kind: ServiceAccount
name: rbd-provisioner
namespace: kube-system
roleRef:
kind: ClusterRole
name: rbd-provisioner
apiGroup: rbac.authorization.k8s.io

---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: rbd-provisioner
namespace: kube-system
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: rbd-provisioner
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: rbd-provisioner
subjects:
- kind: ServiceAccount
name: rbd-provisioner
namespace: kube-system

---
apiVersion: apps/v1
kind: Deployment
metadata:
name: rbd-provisioner
namespace: kube-system
spec:
selector:
matchLabels:
app: rbd-provisioner
replicas: 1
strategy:
type: Recreate
template:
metadata:
labels:
app: rbd-provisioner
spec:
containers:
- name: rbd-provisioner
image: "quay.io/external_storage/rbd-provisioner:v2.0.0-k8s1.11"
env:
- name: PROVISIONER_NAME
value: ceph.com/rbd
serviceAccount: rbd-provisioner
EOF
1
2
3
4
[root@k8s-master1 ceph]# kubectl apply -f external-storage-rbd-provisioner.yaml
[root@k8s-master1 ceph]# kubectl get pod --all-namespaces
kube-system rbd-provisioner-578dc7dd99-5w7lr 1/1 Running 0 70s
...

配置 storageclass

  1. 创建pod时,kubelet需要使用rbd命令去检测和挂载pv对应的ceph image,所以要在所有的worker节点安装ceph客户端ceph-common。
  2. 将ceph的ceph.client.admin.keyring和ceph.conf文件拷贝到所有工作节点的/etc/ceph目录下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@k8s-master1 ceph]# vim /etc/yum.repos.d/ceph.repo 

[ceph]
name=ceph
baseurl=http://mirrors.aliyun.com/ceph/rpm-nautilus/el7/x86_64/
gpgcheck=0
priority=1

[ceph-noarch]
name=cephnoarch
baseurl=http://mirrors.aliyun.com/ceph/rpm-nautilus/el7/noarch/
gpgcheck=0
priority=1

[ceph-source]
name=Ceph source packages
baseurl=http://mirrors.aliyun.com/ceph/rpm-nautilus/el7/SRPMS
gpgcheck=0
priority=1
1
2
3
4
5
6
yum -y install ceph-common
mkdir -p /etc/ceph
cd /etc/ceph
scp root@172.31.228.59:/etc/ceph/ceph.client.admin.keyring .
scp root@172.31.228.59:/etc/ceph/ceph.conf .
ceph -s

创建 osd pool

1
2
3
4
5
6
7
8
9
10
11
[root@cephnode01 my-cluster]# ceph osd pool create kube 16 16
pool 'kube' already exists
[root@cephnode01 my-cluster]# ceph osd lspools
1 .rgw.root
2 default.rgw.control
3 default.rgw.meta
4 default.rgw.log
5 rbd
6 kube
7 cephfs-data
8 cephfs-metadata

创建k8s访问ceph的用户

1
ceph auth get-or-create client.kube mon 'allow r' osd 'allow class-read object_prefix rbd_children, allow rwx pool=kube' -o ceph.client.kube.keyring

查看 key

1
2
3
4
5
[root@cephnode01 my-cluster]# ceph auth get-key client.admin
AQAReB5ebROqLBAAdMpq/uEqUBSxZeUVxxTAvw==

[root@cephnode01 my-cluster]# ceph auth get-key client.kube
AQCQGyBeHjByOhAAj8oEic0LQOOX3MT6O5FVSg==

创建 admin secret

1
2
3
kubectl create secret generic ceph-secret --type="kubernetes.io/rbd" \
--from-literal=key=AQAReB5ebROqLBAAdMpq/uEqUBSxZeUVxxTAvw== \
--namespace=kube-system

在 default 命名空间创建 pvc 用于访问ceph的 secret

1
2
3
kubectl create secret generic ceph-user-secret --type="kubernetes.io/rbd" \
--from-literal=key=AQCQGyBeHjByOhAAj8oEic0LQOOX3MT6O5FVSg== \
--namespace=default
1
[root@k8s-master1 ceph]# kubectl get secret --all-namespaces

配置 StorageClass

  1. 源码中,monitors需要k8s dns解析,我这里使用外部ceph,肯定没有相关解析。
  2. 所以手动添加解析。
  3. 而且storageclass配置默认不支持直接修改(只能删除再添加),维护解析比维护storageclass配置要好些。
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
[root@k8s-master1 ceph]# kubectl create ns ceph

[root@k8s-master1 ceph]# vim rbd-monitor-dns.yaml

kind: Service
apiVersion: v1
metadata:
name: ceph-mon-1
namespace: ceph
spec:
type: ExternalName
externalName: 172.31.228.59.xip.io
---
kind: Service
apiVersion: v1
metadata:
name: ceph-mon-2
namespace: ceph
spec:
type: ExternalName
externalName: 172.31.228.60.xip.io
---
kind: Service
apiVersion: v1
metadata:
name: ceph-mon-3
namespace: ceph
spec:
type: ExternalName
externalName: 172.31.228.61.xip.io

[root@k8s-master1 ceph]# kubectl create -f rbd-monitor-dns.yaml

[root@k8s-master1 ceph]# kubectl get svc -n ceph
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ceph-mon-1 ExternalName <none> 172.31.228.59.xip.io <none> 9s
ceph-mon-2 ExternalName <none> 172.31.228.60.xip.io <none> 9s
ceph-mon-3 ExternalName <none> 172.31.228.61.xip.io <none> 9s
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@k8s-master1 ceph]# vim storageclass-ceph-rdb.yaml 

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: dynamic-ceph-rdb
provisioner: ceph.com/rbd
parameters:
monitors: ceph-mon-1.ceph.svc.cluster.local.:6789,ceph-mon-2.ceph.svc.cluster.local.:6789,ceph-mon-3.ceph.svc.cluster.local.:6789
adminId: admin
adminSecretName: ceph-secret
adminSecretNamespace: kube-system
pool: kube
userId: kube
userSecretName: ceph-user-secret
fsType: ext4
imageFormat: "2"
imageFeatures: "layering"
1
2
3
4
5
6
[root@k8s-master1 ceph]# kubectl apply -f storageclass-ceph-rdb.yaml
storageclass.storage.k8s.io/dynamic-ceph-rdb created

[root@k8s-master1 ceph]# kubectl get sc
NAME PROVISIONER AGE
dynamic-ceph-rdb ceph.com/rbd 13s

测试使用

创建 pvc 测试

1
2
3
4
5
6
7
8
9
10
11
12
13
cat >ceph-rdb-pvc-test.yaml<<EOF
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: ceph-rdb-claim
spec:
accessModes:
- ReadWriteOnce
storageClassName: dynamic-ceph-rdb
resources:
requests:
storage: 5Gi
EOF
1
[root@k8s-master1 ceph]# kubectl apply -f ceph-rdb-pvc-test.yaml
1
2
3
4
5
6
7
8
9
[root@k8s-master1 ceph]# kubectl describe pvc ceph-rdb-claim

[root@k8s-master1 ceph]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
ceph-rdb-claim Bound pvc-436de81b-1b3f-4fd4-ad1b-7663409d34a1 5Gi RWO dynamic-ceph-rdb 10s

[root@k8s-master1 ceph]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-436de81b-1b3f-4fd4-ad1b-7663409d34a1 5Gi RWO Delete Bound default/ceph-rdb-claim dynamic-ceph-rdb 25s

创建 nginx pod 挂载测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
cat >nginx-pod.yaml<<EOF
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod1
labels:
name: nginx-pod1
spec:
containers:
- name: nginx-pod1
image: nginx:alpine
ports:
- name: web
containerPort: 80
volumeMounts:
- name: ceph-rdb
mountPath: /usr/share/nginx/html
volumes:
- name: ceph-rdb
persistentVolumeClaim:
claimName: ceph-rdb-claim
EOF
1
2
3
4
5
6
[root@k8s-master1 ceph]# kubectl apply -f nginx-pod.yaml
pod/nginx-pod1 created

[root@k8s-master1 ceph]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-pod1 1/1 Running 0 37s 10.244.2.3 k8s-master1 <none> <none>
1
2
3
4
5
6
# 修改文件内容
[root@k8s-master1 ceph]# kubectl exec -ti nginx-pod1 -- /bin/sh -c 'echo this is from Ceph RBD!!! > /usr/share/nginx/html/index.html'

# 访问测试
[root@k8s-master1 ceph]# curl http://10.244.2.3
this is from Ceph RBD!!!
1
2
3
# 清理
kubectl delete -f nginx-pod.yaml
kubectl delete -f ceph-rdb-pvc-test.yaml

POD 使用 CephFS 做为持久数据卷

  1. CephFS方式支持k8s的pv的3种访问模式ReadWriteOnce,ReadOnlyMany ,ReadWriteMany
1
2
3
4
5
6
7
访问模式包括:
1. ReadWriteOnce 该volume只能被单个节点以读写的方式映射
2. ReadOnlyMany 该volume可以被多个节点以只读方式映射
3. ReadWriteMany 该volume只能被多个节点以读写的方式映射

# 注意:即使volume支持很多种访问模式,但它同时只能使用一种方式来映射。
# 比如,GCEPersistentDisk可以被单个节点映射为ReadWriteOnce,或者多个节点映射为ReadOnlyMany,但不能同时使用这两种方式来映射。
  1. Pod挂载cephfs有时候会用fuse挂载 如果宿主机没有这个工具会导致挂载失败 pod无法启动
1
yum install -y ceph-fuse

Ceph 端创建 CephFS pool

  1. 在ceph节点,CephFS需要使用两个Pool来分别存储数据和元数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@cephnode01 my-cluster]# ceph osd pool create fs_data 16
pool 'fs_data' created

[root@cephnode01 my-cluster]# ceph osd pool create fs_metadata 16
pool 'fs_metadata' created

[root@cephnode01 my-cluster]# ceph osd lspools
1 .rgw.root
2 default.rgw.control
3 default.rgw.meta
4 default.rgw.log
5 rbd
6 kube
7 cephfs-data
8 cephfs-metadata
9 fs_data
10 fs_metadata
1
2
3
4
5
6
7
8
9
# 创建一个CephFS 
# 删除之前的
[root@cephnode01 my-cluster]# ceph fs volume rm cephfs --yes-i-really-mean-it

[root@cephnode01 my-cluster]# ceph fs new cephfs fs_metadata fs_data
new fs with metadata pool 10 and data pool 9

[root@cephnode01 my-cluster]# ceph fs ls
name: cephfs, metadata pool: fs_metadata, data pools: [fs_data ]

部署 cephfs-provisioner

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
120
121
# 使用社区提供的cephfs-provisioner

cat >external-storage-cephfs-provisioner.yaml<<EOF
apiVersion: v1
kind: Namespace
metadata:
name: cephfs
labels:
name: cephfs

---
apiVersion: v1
kind: ServiceAccount
metadata:
name: cephfs-provisioner
namespace: cephfs

---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: cephfs-provisioner
namespace: cephfs
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["create", "get", "delete"]
- apiGroups: [""]
resources: ["endpoints"]
verbs: ["get", "list", "watch", "create", "update", "patch"]

---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: cephfs-provisioner
namespace: cephfs
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"]
resourceNames: ["kube-dns","coredns"]
verbs: ["list", "get"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "create", "delete"]
- apiGroups: ["policy"]
resourceNames: ["cephfs-provisioner"]
resources: ["podsecuritypolicies"]
verbs: ["use"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: cephfs-provisioner
namespace: cephfs
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: cephfs-provisioner
subjects:
- kind: ServiceAccount
name: cephfs-provisioner

---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: cephfs-provisioner
subjects:
- kind: ServiceAccount
name: cephfs-provisioner
namespace: cephfs
roleRef:
kind: ClusterRole
name: cephfs-provisioner
apiGroup: rbac.authorization.k8s.io

---
apiVersion: apps/v1
kind: Deployment
metadata:
name: cephfs-provisioner
namespace: cephfs
spec:
selector:
matchLabels:
app: cephfs-provisioner
replicas: 1
strategy:
type: Recreate
template:
metadata:
labels:
app: cephfs-provisioner
spec:
containers:
- name: cephfs-provisioner
image: "quay.io/external_storage/cephfs-provisioner:latest"
env:
- name: PROVISIONER_NAME
value: ceph.com/cephfs
command:
- "/usr/local/bin/cephfs-provisioner"
args:
- "-id=cephfs-provisioner-1"
- "-disable-ceph-namespace-isolation=true"
serviceAccount: cephfs-provisioner
EOF
1
2
3
4
5
[root@k8s-master1 ceph]# kubectl apply -f external-storage-cephfs-provisioner.yaml 

[root@k8s-master1 ceph]# kubectl get pods --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
cephfs cephfs-provisioner-847468fc-95rkg 1/1 Running 0 62s

配置 StorageClass

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 查看key 在ceph的mon或者admin节点
# 重新配置一下

[root@cephnode01 my-cluster]# ceph auth get-key client.admin
AQAReB5ebROqLBAAdMpq/uEqUBSxZeUVxxTAvw==

[root@k8s-master1 ceph]# kubectl delete secret ceph-secret -n kube-system

kubectl create secret generic ceph-secret --type="kubernetes.io/rbd" \
--from-literal=key=AQAReB5ebROqLBAAdMpq/uEqUBSxZeUVxxTAvw== \
--namespace=kube-system

[root@k8s-master1 ceph]# kubectl get secret -n kube-system
NAME TYPE DATA AGE
ceph-secret kubernetes.io/rbd 1 3s
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 配置 StorageClass

cat >storageclass-cephfs.yaml<<EOF
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: dynamic-cephfs
provisioner: ceph.com/cephfs
parameters:
monitors: 172.31.228.59:6789,172.31.228.60:6789,172.31.228.61:6789
adminId: admin
adminSecretName: ceph-secret
adminSecretNamespace: "kube-system"
claimRoot: /volumes/kubernetes
EOF
1
2
3
4
5
6
7
[root@k8s-master1 ceph]# kubectl apply -f storageclass-cephfs.yaml
storageclass.storage.k8s.io/dynamic-cephfs created

[root@k8s-master1 ceph]# kubectl get sc
NAME PROVISIONER AGE
dynamic-ceph-rdb ceph.com/rbd 52m
dynamic-cephfs ceph.com/cephfs 2s

测试使用

创建pvc测试

1
2
3
4
5
6
7
8
9
10
11
12
13
cat >cephfs-pvc-test.yaml<<EOF
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: cephfs-claim
spec:
accessModes:
- ReadWriteOnce
storageClassName: dynamic-cephfs
resources:
requests:
storage: 2Gi
EOF
1
2
3
4
5
6
7
8
9
10
[root@k8s-master1 ceph]# kubectl apply -f cephfs-pvc-test.yaml
persistentvolumeclaim/cephfs-claim created

[root@k8s-master1 ceph]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
cephfs-claim Bound pvc-ac8186ab-ff09-4134-9357-044ca377af25 2Gi RWO dynamic-cephfs 10s

[root@k8s-master1 ceph]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-ac8186ab-ff09-4134-9357-044ca377af25 2Gi RWO Delete Bound default/cephfs-claim dynamic-cephfs 12s
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 创建 nginx pod 挂载测试

cat >nginx-pod2.yaml<<EOF
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod2
labels:
name: nginx-pod2
spec:
containers:
- name: nginx-pod2
image: nginx
ports:
- name: web
containerPort: 80
volumeMounts:
- name: cephfs
mountPath: /usr/share/nginx/html
volumes:
- name: cephfs
persistentVolumeClaim:
claimName: cephfs-claim
EOF
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@k8s-master1 ceph]# kubectl apply -f nginx-pod2.yaml

[root@k8s-master1 ceph]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-pod2 1/1 Running 0 3m28s 10.244.1.3 k8s-node1 <none> <none>

[root@k8s-master1 ceph]# kubectl exec -ti nginx-pod2 sh
# df -h
Filesystem Size Used Avail Use% Mounted on
overlay 40G 4.9G 33G 13% /
tmpfs 64M 0 64M 0% /dev
tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup
/dev/vda1 40G 4.9G 33G 13% /etc/hosts
shm 64M 0 64M 0% /dev/shm
ceph-fuse 18G 0 18G 0% /usr/share/nginx/html
tmpfs 1.9G 12K 1.9G 1% /run/secrets/kubernetes.io/serviceaccount
tmpfs 1.9G 0 1.9G 0% /proc/acpi
tmpfs 1.9G 0 1.9G 0% /proc/scsi
tmpfs 1.9G 0 1.9G 0% /sys/firmware
1
2
3
4
5
6
# 修改文件内容
[root@k8s-master1 ceph]# kubectl exec -ti nginx-pod2 -- /bin/sh -c 'echo This is from CephFS!!! > /usr/share/nginx/html/index.html'

# 访问pod测试
[root@k8s-master1 ceph]# curl http://10.244.1.3
This is from CephFS!!!
1
2
3
4
5
# 清理
# pod 被删除 再拉起 数据是还在的
kubectl delete -f nginx-pod2.yaml
# pvc 删除 pv 数据就都不在了,storageclass自动回收
kubectl delete -f cephfs-pvc-test.yaml

Ceph 日常运维管理

集群监控管理

  1. 集群整体运行状态
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
[root@cephnode01 my-cluster]# ceph -s 
cluster:
id: 4ed819cf-39be-4a7c-9216-effcae715c58
health: HEALTH_OK

services:
mon: 3 daemons, quorum cephnode01,cephnode02,cephnode03 (age 9h)
mgr: cephnode02(active, since 6h), standbys: cephnode03, cephnode01
mds: cephfs:1 {0=cephnode02=up:active} 2 up:standby
osd: 3 osds: 3 up (since 9h), 3 in (since 31h)
rgw: 1 daemon active (cephnode01)

data:
pools: 10 pools, 144 pgs
objects: 260 objects, 43 KiB
usage: 3.0 GiB used, 54 GiB / 57 GiB avail
pgs: 144 active+clean

id: 集群ID
health: 集群运行状态,这里有一个警告,说明是有问题,意思是pg数大于pgp数,通常此数值相等。
mon: Monitors运行状态。
osd: OSDs运行状态。
mgr: Managers运行状态。
mds: Metadatas运行状态。
pools: 存储池与PGs的数量。
objects: 存储对象的数量。
usage: 存储的理论用量。
pgs: PGs的运行状态

# 持续输出
ceph -w
# 健康检查
ceph health detail

PG 状态

  1. 查看pg状态查看通常使用下面两个命令即可,dump可以查看更详细信息,如
1
2
3
4
5
6
7
8
9
10
11
12
13
ceph pg dump
ceph pg stat

[root@cephnode01 my-cluster]# ceph pg stat
144 pgs: 144 active+clean; 43 KiB data, 32 MiB used, 54 GiB / 57 GiB avail

# 144个pg
# 43k数据
# 32M使用
# 54G空间

ceph pg dump
# pg的位置 如果主pg坏了 剩下的2个会选举出一个来在让用户访问

Pool状态

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
ceph osd pool stats

[root@cephnode01 my-cluster]# ceph osd pool stats
pool .rgw.root id 1
nothing is going on

pool default.rgw.control id 2
nothing is going on

pool default.rgw.meta id 3
nothing is going on

pool default.rgw.log id 4
nothing is going on

pool rbd id 5
nothing is going on

pool kube id 6
nothing is going on

pool cephfs-data id 7
nothing is going on

pool cephfs-metadata id 8
nothing is going on

pool fs_data id 9
nothing is going on

pool fs_metadata id 10
nothing is going on

OSD 状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
ceph osd stat
ceph osd dump
ceph osd tree
ceph osd df

[root@cephnode01 my-cluster]# ceph osd tree
ID CLASS WEIGHT TYPE NAME STATUS REWEIGHT PRI-AFF
-1 0.05576 root default
-3 0.01859 host cephnode01
0 hdd 0.01859 osd.0 up 1.00000 1.00000
-5 0.01859 host cephnode02
1 hdd 0.01859 osd.1 up 1.00000 1.00000
-7 0.01859 host cephnode03
2 hdd 0.01859 osd.2 up 1.00000 1.00000

[root@cephnode01 my-cluster]# ceph osd df
ID CLASS WEIGHT REWEIGHT SIZE RAW USE DATA OMAP META AVAIL %USE VAR PGS STATUS
0 hdd 0.01859 1.00000 19 GiB 1.0 GiB 11 MiB 0 B 1 GiB 18 GiB 5.32 1.00 144 up
1 hdd 0.01859 1.00000 19 GiB 1.0 GiB 11 MiB 0 B 1 GiB 18 GiB 5.32 1.00 144 up
2 hdd 0.01859 1.00000 19 GiB 1.0 GiB 11 MiB 0 B 1 GiB 18 GiB 5.32 1.00 144 up
TOTAL 57 GiB 3.0 GiB 32 MiB 0 B 3 GiB 54 GiB 5.32
MIN/MAX VAR: 1.00/1.00 STDDEV: 0

Monitor状态和查看仲裁状态

1
2
3
ceph mon stat
ceph mon dump
ceph quorum_status

集群空间用量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
ceph df 常用
ceph df detail

[root@cephnode01 my-cluster]# ceph df
RAW STORAGE:
CLASS SIZE AVAIL USED RAW USED %RAW USED
hdd 57 GiB 54 GiB 32 MiB 3.0 GiB 5.32
TOTAL 57 GiB 54 GiB 32 MiB 3.0 GiB 5.32

POOLS:
POOL ID STORED OBJECTS USED %USED MAX AVAIL
.rgw.root 1 1.2 KiB 4 768 KiB 0 17 GiB
default.rgw.control 2 0 B 8 0 B 0 17 GiB
default.rgw.meta 3 0 B 0 0 B 0 17 GiB
default.rgw.log 4 0 B 175 0 B 0 17 GiB
rbd 5 19 B 3 192 KiB 0 17 GiB
kube 6 709 B 6 576 KiB 0 17 GiB
cephfs-data 7 0 B 0 0 B 0 17 GiB
cephfs-metadata 8 6.4 KiB 41 2.6 MiB 0 17 GiB
fs_data 9 23 B 1 192 KiB 0 17 GiB
fs_metadata 10 34 KiB 22 1.5 MiB 0 17 GiB

集群配置管理 (临时和全局,服务平滑重启)

  1. 有时候需要更改服务的配置,但不想重启服务,或者是临时修改。这时候就可以使用tell和daemon子命令来完成此需求。

查看运行配置

1
2
3
4
5
命令格式:
# ceph daemon {daemon-type}.{id} config show

命令举例:
# ceph daemon osd.0 config show

tell 子命令格式

  1. 使用 tell 的方式适合对整个集群进行设置,使用 * 号进行匹配,就可以对整个集群的角色进行设置。
  2. 而出现节点异常无法设置时候,只会在命令行当中进行报错,不太便于查找。
1
2
3
4
5
6
7
8
命令格式:
# ceph tell {daemon-type}.{daemon id or *} injectargs --{name}={value} [--{name}={value}]
命令举例:
# ceph tell osd.0 injectargs --debug-osd 20 --debug-ms 1

1. daemon-type:为要操作的对象类型如osd、mon、mds等。
2. daemon id:该对象的名称,osd通常为0、1等,mon为ceph -s显示的名称,这里可以输入*表示全部。
3. injectargs:表示参数注入,后面必须跟一个参数,也可以跟多个

daemon子命令

  1. 使用 daemon 进行设置的方式就是一个个的去设置,这样可以比较好的反馈,此方法是需要在设置的角色所在的主机上进行设置。
1
2
3
4
5
命令格式:
# ceph daemon {daemon-type}.{id} config set {name}={value}

命令举例:
# ceph daemon mon.ceph-monitor-1 config set mon_allow_pool_delete false

集群操作

1
2
3
4
5
6
7
8
1. 启动所有守护进程
# systemctl start ceph.target
2. 按类型启动守护进程
# systemctl start ceph-mgr.target
# systemctl start ceph-osd@id
# systemctl start ceph-mon.target
# systemctl start ceph-mds.target
# systemctl start ceph-radosgw.target

添加和删除OSD

添加 OSD

1
2
3
4
5
1、格式化磁盘
ceph-volume lvm zap /dev/sd<id>

2、进入到ceph-deploy执行目录/my-cluster,添加OSD
# ceph-deploy osd create --data /dev/sd<id> $hostname

删除 OSD

1
2
3
4
5
6
7
8
9
10
1. 调整osd的crush weight为 0
ceph osd crush reweight osd.<ID> 0.0
2. 将osd进程stop
systemctl stop ceph-osd@<ID>
3. 将osd设置out
ceph osd out <ID>
4. 立即执行删除OSD中数据
ceph osd purge osd.<ID> --yes-i-really-mean-it
5. 卸载磁盘
umount /var/lib/ceph/osd/ceph-?

扩容 PG

1
2
3
4
5
6
7
ceph osd pool set {pool-name} pg_num 128
ceph osd pool set {pool-name} pgp_num 128

注:
1. 扩容大小取跟它接近的2的N次方
2. 在更改pool的PG数量时,需同时更改PGP的数量。PGP是为了管理placement而存在的专门的PG,它和PG的数量应该保持一致。
如果你增加pool的pg_num,就需要同时增加pgp_num,保持它们大小一致,这样集群才能正常rebalancing。

Pool 操作

1
2
# 列出存储池
ceph osd lspools
1
2
3
4
5
# 创建存储池
命令格式:
# ceph osd pool create {pool-name} {pg-num} [{pgp-num}]
命令举例:
# ceph osd pool create rbd 32 32
1
2
3
4
5
# 设置存储池配额 
命令格式:
# ceph osd pool set-quota {pool-name} [max_objects {obj-count}] [max_bytes {bytes}]
命令举例:
# ceph osd pool set-quota rbd max_objects 10000
1
2
# 删除存储池 
ceph osd pool delete {pool-name} [{pool-name} --yes-i-really-really-mean-it]
1
2
# 重命名存储池 
ceph osd pool rename {current-pool-name} {new-pool-name}
1
2
# 查看存储池统计信息 
rados df
1
2
# 给存储池做快照 
ceph osd pool mksnap {pool-name} {snap-name}
1
2
# 删除存储池的快照 
ceph osd pool rmsnap {pool-name} {snap-name}
1
2
# 获取存储池选项值 
ceph osd pool get {pool-name} {key}
1
2
3
4
5
6
7
8
9
10
11
12
# 调整存储池选项值
ceph osd pool set {pool-name} {key} {value}
size:设置存储池中的对象副本数,详情参见设置对象副本数。仅适用于副本存储池。
min_size:设置 I/O 需要的最小副本数,详情参见设置对象副本数。仅适用于副本存储池。
pg_num:计算数据分布时的有效 PG 数。只能大于当前 PG 数。
pgp_num:计算数据分布时使用的有效 PGP 数量。小于等于存储池的 PG 数。
hashpspool:给指定存储池设置/取消 HASHPSPOOL 标志。
target_max_bytes:达到 max_bytes 阀值时会触发 Ceph 冲洗或驱逐对象。
target_max_objects:达到 max_objects 阀值时会触发 Ceph 冲洗或驱逐对象。
scrub_min_interval:在负载低时,洗刷存储池的最小间隔秒数。如果是 0 ,就按照配置文件里的 osd_scrub_min_interval 。
scrub_max_interval:不管集群负载如何,都要洗刷存储池的最大间隔秒数。如果是 0 ,就按照配置文件里的 osd_scrub_max_interval 。
deep_scrub_interval:“深度”洗刷存储池的间隔秒数。如果是 0 ,就按照配置文件里的 osd_deep_scrub_interval 。

获取对象副本数

1
ceph osd dump | grep 'replicated size'

用户管理

  1. Ceph 把数据以对象的形式存于各存储池中。
  2. Ceph 用户必须具有访问存储池的权限才能够读写数据。
  3. 另外,Ceph 用户必须具有执行权限才能够使用 Ceph 的管理命令。
1
2
3
4
5
6
7
# 查看用户信息
查看所有用户信息
# ceph auth list
获取所有用户的key与权限相关信息
# ceph auth get client.admin
如果只需要某个用户的key信息,可以使用pring-key子命令
# ceph auth print-key client.admin
1
2
3
4
5
# 添加用户
# ceph auth add client.john mon 'allow r' osd 'allow rw pool=liverpool'
# ceph auth get-or-create client.paul mon 'allow r' osd 'allow rw pool=liverpool'
# ceph auth get-or-create client.george mon 'allow r' osd 'allow rw pool=liverpool' -o george.keyring
# ceph auth get-or-create-key client.ringo mon 'allow r' osd 'allow rw pool=liverpool' -o ringo.key
1
2
3
4
5
# 修改用户权限 
# ceph auth caps client.john mon 'allow r' osd 'allow rw pool=liverpool'
# ceph auth caps client.paul mon 'allow rw' osd 'allow rwx pool=liverpool'
# ceph auth caps client.brian-manager mon 'allow *' osd 'allow *'
# ceph auth caps client.ringo mon ' ' osd ' '

增加和删除Monitor

1
2
3
# 新增一个monitor
# ceph-deploy mon create $hostname
注意:执行ceph-deploy之前要进入之前安装时候配置的目录。/my-cluster
1
2
3
# 删除Monitor 
# ceph-deploy mon destroy $hostname
注意: 确保你删除某个 Mon 后,其余 Mon 仍能达成一致。如果不可能,删除它之前可能需要先增加一个。

Pool 配置大小

1
2
3
4
5
# Pool的基本配置
若少于5个OSD 设置pg_num为128。
5~10个OSD 设置pg_num为512。
10~50个OSD 设置pg_num为4096。
超过50个OSD 可以参考pgcalc计算。

常见问题

nearfull osd(s) or pool(s) nearfull

  1. 此时说明部分osd的存储已经超过阈值,mon会监控ceph集群中OSD空间使用情况。
  2. 如果要消除WARN,可以修改这两个参数,提高阈值,但是通过实践发现并不能解决问题,可以通过观察osd的数据分布情况来分析原因。
1
2
3
# 配置文件设置阈值 
"mon_osd_full_ratio": "0.95",
"mon_osd_nearfull_ratio": "0.85"
1
2
3
# 自动处理 
ceph osd reweight-by-utilization
ceph osd reweight-by-pg 105 cephfs_data(pool_name)
1
2
# 手动处理 
ceph osd reweight osd.2 0.8
1
2
3
4
5
6
# 全局处理 
ceph mgr module ls
ceph mgr module enable balancer
ceph balancer on
ceph balancer mode crush-compat
ceph config-key set "mgr/balancer/max_misplaced": "0.01"

PG 故障状态

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
PG状态概述
一个PG在它的生命周期的不同时刻可能会处于以下几种状态中:

Creating(创建中)
在创建POOL时,需要指定PG的数量,此时PG的状态便处于creating,意思是Ceph正在创建PG。

Peering(互联中)
peering的作用主要是在PG及其副本所在的OSD之间建立互联,并使得OSD之间就这些PG中的object及其元数据达成一致。

Active(活跃的)
处于该状态意味着数据已经完好的保存到了主PG及副本PG中,并且Ceph已经完成了peering工作。

Clean(整洁的)
当某个PG处于clean状态时,则说明对应的主OSD及副本OSD已经成功互联,并且没有偏离的PG。也意味着Ceph已经将该PG中的对象按照规定的副本数进行了复制操作。

Degraded(降级的)
当某个PG的副本数未达到规定个数时,该PG便处于degraded状态,例如:

在客户端向主OSD写入object的过程,object的副本是由主OSD负责向副本OSD写入的,直到副本OSD在创建object副本完成,并向主OSD发出完成信息前,该PG的状态都会一直处于degraded状态。又或者是某个OSD的状态变成了down,那么该OSD上的所有PG都会被标记为degraded。
当Ceph因为某些原因无法找到某个PG内的一个或多个object时,该PG也会被标记为degraded状态。此时客户端不能读写找不到的对象,但是仍然能访问位于该PG内的其他object。

Recovering(恢复中)
当某个OSD因为某些原因down了,该OSD内PG的object会落后于它所对应的PG副本。而在该OSD重新up之后,该OSD中的内容必须更新到当前状态,处于此过程中的PG状态便是recovering。

Backfilling(回填)
当有新的OSD加入集群时,CRUSH会把现有集群内的部分PG分配给它。这些被重新分配到新OSD的PG状态便处于backfilling。

Remapped(重映射)
当负责维护某个PG的acting set变更时,PG需要从原来的acting set迁移至新的acting set。这个过程需要一段时间,所以在此期间,相关PG的状态便会标记为remapped。

Stale(陈旧的)
默认情况下,OSD守护进程每半秒钟便会向Monitor报告其PG等相关状态,如果某个PG的主OSD所在acting set没能向Monitor发送报告,或者其他的Monitor已经报告该OSD为down时,该PG便会被标记为stale。

OSD 状态

1
2
3
4
5
6
7
8
9
10
11
12
13
单个OSD有两组状态需要关注,其中一组使用in/out标记该OSD是否在集群内,另一组使用up/down标记该OSD是否处于运行中状态。两组状态之间并不互斥,换句话说,当一个OSD处于“in”状态时,它仍然可以处于up或down的状态。

OSD状态为in且up
这是一个OSD正常的状态,说明该OSD处于集群内,并且运行正常。

OSD状态为in且down
此时该OSD尚处于集群中,但是守护进程状态已经不正常,默认在300秒后会被踢出集群,状态进而变为out且down,之后处于该OSD上的PG会迁移至其它OSD。

OSD状态为out且up
这种状态一般会出现在新增OSD时,意味着该OSD守护进程正常,但是尚未加入集群。

OSD状态为out且down
在该状态下的OSD不在集群内,并且守护进程运行不正常,CRUSH不会再分配PG到该OSD上。