Q's blog

一些个人文档笔记

ceph

存储基础

image-20201024224735002

image-20201024224655443

存储架构

image-20201024224854558

组件 功能
Monitor 它是一个在主机上面运行的守护进程,这个守护进程,扮演着监控集群整个组件的职责,包括多少个存储池,存储池中有多少个PG,PG与osd映射的关系,每个节点有多少个osd等等,都要监视,它是整个集群运行图(Cluster Map)的持有者,一共5个运行图。 它还维护集群的认证信息,客户端有用户名密码等;内部的OSD也需要与mon通信,也需要认证,它是通过cephX协议进行认证的,各个组件之间通信,都必须认证,认证都需要经过mon,因此mon还是认证中心,有些同学就会想到,如果集群很大了的话,认证中心会不会成为瓶颈,所以这也是需要多台mon的原因,mon在认证上是无状态的,可以做任意横向扩展,可以使用负载均衡负载的;
Managers 它的专门守护进程是ceph-mgr,负责收集集群的状态指标,运行时的metrics,存储的利用率,当前性能指标和系统负载,它有很多基于Python的插件,以实现ceph-mgr功能的提升,用户辅助mon的。
OSD Osd是指的单独的资源存储设备,一般情况下一台服务器上面放多块磁盘,ceph为了使用每个节点上面的osd单独进行管理,每一个osd都会有一个单独的、专用的守护进程,比如说,一台服务器上面有6个osd,就需要6个ceph-osd进程,每一个磁盘上面,都有一个守护进程。它提供存储 PG 的数据、数据复制、恢复、再均衡,并提供一些监控信息供mon和mgr来check,并且还可以通过心跳检测其它副本;至少需要有三个osd,不是三台节点哦,这里要注意下,一般情况下我们是1主2从,1主PG、2个副本PG、以确保其高可用性;
CURSH CRUSH 是 Ceph 使用的数据分布算法,类似一致性哈希,让数据分配到预期的位置。
PG PG 全称 Placement Groups,是一个逻辑的概念,一个 PG 包含多个 OSD 。引入 PG 这一层其实是为了更好的分配数据和定位数据。
Object 文件需要切分成大小为4M(默认)的块即对象,Ceph 最底层的存储单元就是 Object对象,每个 Object 包含元数据和原始数据;
RADOS 实现数据分配、Failover 等集群操作。
Libradio librados提供了访问RADOS存储集群支持异步通信的API接口,支持对集群中对象数据的直接并行访问,用户可通过支持的编程语言开发自定义客户端程序通过RADOS协议与存储系统进行交互;
MDS MDS全称Ceph Metadata Server,是CephFS服务依赖的元数据服务;
RBD RBD全称 RADOS Block Device,是 Ceph 对外提供的块设备服务;
RGW RGW依赖于在RADOS集群基础上独立运行的守护进程(ceph-radosgw)基于http 或https协议提供相关的API服务,不过,通常仅在需要以REST对象形式存取数据时才部署RGW;
CephFS CephFS全称Ceph File System,是 Ceph 对外提供的文件系统服务,它是最早出现的,但也是最后可用于生产的,目前的版本,可以用在生产中。
Admin Ceph常用管理接口通常都是命令行工具,如rados、ceph、rbd等命令,另外Ceph还有可以有一个专用的管理节点,在此节点上面部署专用的管理工具来实现近乎集群的一些管理工作,如集群部署,集群组件管理等。

集群部署

image-20201024225000923

主机名和hosts

1
2
3
10.211.56.201 node-1
10.211.56.202 node-2
10.211.56.203 node-3

ssh免密

1
2
ssh-keygen
ssh-copy-id

安全设置

1
2
3
4
5
6
7
8
systemctl stop firewalld
systemctl disable firewalld
iptables -F && iptables -X && iptables -F -t nat && iptables -X -t nat
iptables -P FORWARD ACCEPT
setenforce 0
sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config
systemctl stop NetworkManager
systemctl disable NetworkManager

ntp时间同步

yum源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-6.repo
sed -i -e '/mirrors.cloud.aliyuncs.com/d' -e '/mirrors.aliyuncs.com/d' /etc/yum.repos.d/CentOS-Base.repo
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
yum makecache

cat > /etc/yum.repos.d/ceph.repo << EOF
[norch]
name=norch
baseurl=https://mirrors.aliyun.com/ceph/rpm-nautilus/el7/noarch/
enable=1
gpgcheck=0

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

安装ceph-deploy

1
2
yum install -y python-setuptools
yum install -y ceph-deploy #ceph-deploy v2.0.1

安装monitor节点

1
2
3
4
5
6
mkdir my-cluster
cd my-cluster
ceph-deploy new --public-network 10.211.55.0/24 --cluster-network 10.211.56.0/24 node-1
#创建集群
#cluster-network用于内部数据同步
#public-network:ceph对外入口

image-20201025204658001

1
2
3
4
5
yum install -y ceph ceph-mon ceph-mgr ceph-radosgw ceph-mds #所有节点
ceph-deploy mon create-initial #初始化
ceph-deploy admin node-1 node-2 node-3 #推送秘钥
ceph-deploy mgr create node-1 #创建监控节点
ceph quorum_status --format json-pretty # 查看节点信息

安装osd

先在宿主机挂盘

1
2
3
4
5
6
7
8
echo "- - -" > /sys/class/scsi_host/host0/scan
echo "- - -" > /sys/class/scsi_host/host1/scan
echo "- - -" > /sys/class/scsi_host/host2/scan

$ ceph-deploy osd create --data /dev/sdb node-1
$ ceph-deploy osd create --data /dev/sdb node-2
$ ceph-deploy osd create --data /dev/sdb node-3
$ ceph osd pool create ceph-demo 32 32

扩展mon与mgr

1
2
3
4
5
ceph-deploy mon add node-2 --address 10.211.55.202 #添加监控节点
ceph-deploy mon add node-3 --address 10.211.55.203 #添加监控节点
ceph mon dump #mon状态
ceph mon stat
ceph-deploy mgr create node-2 node-3 #添加mgr节点

image-20201025210520508

image-20201025210603427

RBD块存储

介绍

image-20201025210841602

创建资源池Pool

关于存储池

Ceph 存储系统支持“池”概念,它是存储对象的逻辑分区。

Ceph 客户端从监视器获取一张集群运行图,并把对象写入存储池。存储池的 size 或副本数、 CRUSH 规则集和归置组数量决定着 Ceph 如何放置数据。

image-20201025211114850

存储池至少可设置以下参数:

  • 对象的所有权/访问权限;
  • 归置组数量;以及,
  • 使用的 CRUSH 规则集。

PG 映射到 OSD

每个存储池都有很多归置组, CRUSH 动态的把它们映射到 OSD 。 Ceph 客户端要存对象时, CRUSH 将把各对象映射到某个归置组。

把对象映射到归置组在 OSD 和客户端间创建了一个间接层。由于 Ceph 集群必须能增大或缩小、并动态地重均衡。如果让客户端“知道”哪个 OSD 有哪个对象,就会导致客户端和 OSD 紧耦合;相反, CRUSH 算法把对象映射到归置组、然后再把各归置组映射到一或多个 OSD ,这一间接层可以让 Ceph 在 OSD 守护进程和底层设备上线时动态地重均衡。下列图表描述了 CRUSH 如何将对象映射到归置组、再把归置组映射到 OSD 。

image-20201025211412781

有了集群运行图副本和 CRUSH 算法,客户端就能精确地计算出到哪个 OSD 读、写某特定对象。

1
2
3
4
5
6
7
8
9
10
11
12
ceph osd pool create ceph-demo  32      32 
# 名称 pg数量 pgp数量
ceph osd ls
ceph osd lspools
ceph osd pool get ceph-demo pg_num
ceph osd pool get ceph-demo pgp_num
ceph osd pool get ceph-demo size
ceph osd pool get ceph-demo crush_rule
ceph osd pool set ceph-demo size 2 #设置pool副本数,默认3
ceph osd pool set ceph-demo pg_num 128 #调整pg
ceph osd pool set ceph-demo pgp_num 128 #调整pg,对应的pgp也要调整
rbd poll init <pool-name> ##先不做

RBD创建和映射

1
2
3
4
5
rbd create -p ceph-demo --image rbd-demo.img --size 10G
rbd create -p ceph-demo/rbd-demo.img --size 10G
rbd -p ceph-demo ls
rbd info ceph-demo/rbd-demo.img
rbd rm -p ceph-demo/rbd-demo.img #删除

image-20201025214601818

有些参数内核不支持:

  • 升级内核

    5+版都支持

  • 去掉参数

    image-20201025214854737

    1
    2
    3
    4
    rbd feature disable ceph-demo/rbd-demo.img deep-flatten #从后往前依次关闭特性
    rbd feature disable ceph-demo/rbd-demo.img fast-diff
    rbd feature disable ceph-demo/rbd-demo.img object-map
    rbd feature disable ceph-demo/rbd-demo.img exclusive-lock

映射块设备

1
rbd map ceph-demo/rbd-demo.img 

image-20201025215415736

image-20201025215506969-1604217444470.png

挂载

1
2
3
mkfs.ext4 /dev/rbd0
mkdir /mnt/rbd-demo
mount /dev/rbd0 /mnt/rbd-demo

扩容

1
2
3
rbd resize ceph-demo/rbd-demo.img --size 15G #扩容
rbd info ceph-demo/rbd-demo.img #查询
resize2fs /dev/rbd0

数据流写入过程

image-20201025222956312

查看对象信息

1
2
3
4
5
6
7
8
rbd info  ceph-demo/rbd-demo.img #查看pool信息
rados -p ceph-demo ls | grep rbd_data.1e505c9f4eed1 #查询object id = oid
rados -p ceph-demo stat rbd_data.1e505c9f4eed1.0000000000000020 #obj情况
ceph osd map ceph-demo rbd_data.1e505c9f4eed1.0000000000000620 #落盘情况
ceph osd tree #osd信息
for i in `rados -p ceph-demo ls | grep rbd_data.1e505c9f4eed1`;do rados -p ceph-demo stat ${i};done
for i in `rados -p ceph-demo ls | grep rbd_data.1e505c9f4eed1`;do ceph osd map ceph-demo ${i};done
watch -n 1 'rados -p ceph-demo ls | grep rbd_data.1e505c9f4eed1 | wc -l' #查看有多少个object

image-20201025225832909

image-20201025225849996

image-20201025225849996

image-20201025230755329

报警排查

1
2
3
4
5
6
7
8
9
10
ceph -s
ceph health detail
ceph osd pool application enable ceph-demo rbd
$ ceph osd pool application get ceph-demo
{
"rbd": {}
}
ceph crash ls
ceph crash info <crash-name>
ceph crash archive <crash-name>#打包

RGW对象存储

简介

Ceph 对象网关是一个构建在 librados 之上的对象存储接口,它为应用程序访问Ceph 存储集群提供了一个 RESTful 风格的网关 。 Ceph 对象存储支持 2 种接口:

  1. 兼容S3: 提供了对象存储接口,兼容 亚马逊S3 RESTful 接口的一个大子集。
  2. 兼容Swift: 提供了对象存储接口,兼容 Openstack Swift 接口的一个大子集。

Ceph 对象存储使用 Ceph 对象网关守护进程( radosgw ),它是个与 Ceph 存储集群交互的 FastCGI 模块。因为它提供了与 OpenStack Swift 和 Amazon S3 兼容的接口, RADOS 要有它自己的用户管理。 Ceph 对象网关可与 Ceph FS 客户端或 Ceph 块设备客户端共用一个存储集群。 S3 和 Swift 接口共用一个通用命名空间,所以你可以用一个接口写如数据、然后用另一个接口取出数据。

image-20201026223002059

1
2
3
4
5
6
7
8
9
[21:49:43 root@node-1 ~] $ rados df
POOL_NAME USED OBJECTS CLONES COPIES MISSING_ON_PRIMARY UNFOUND DEGRADED RD_OPS RD WR_OPS WR USED COMPR UNDER COMPR
ceph-demo 2.4 GiB 226 0 678 0 0 0 1 0 B 0 0 B 0 B 0 B
testpool 0 B 0 0 0 0 0 0 0 0 B 0 0 B 0 B 0 B

total_objects 226
total_used 5.4 GiB #使用情况
total_avail 145 GiB
total_space 150 GiB

部署RGW存储网关

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
#yum list | grep ceph-radosgw
ceph-radosgw.x86_64 2:14.2.12-0.el7 @x86_64
$ cd ceph-deploy/
$ ceph-deploy rgw create node-1 #部署RGW存储网关
...
...
$ ceph -s
cluster:
id: a96a9084-601e-46ca-a8b1-cf6b1ab5edf1
health: HEALTH_OK

services:
mon: 3 daemons, quorum node-1,node-2,node-3 (age 25m)
mgr: node-1(active, since 2h), standbys: node-2, node-3
osd: 3 osds: 3 up (since 72m), 3 in (since 25h)
rgw: 1 daemon active (node-1) #新节点

task status:

data:
pools: 6 pools, 224 pgs
objects: 413 objects, 825 MiB
usage: 5.4 GiB used, 145 GiB / 150 GiB avail
pgs: 224 active+clean
$ ss -antupl | grep 7480
tcp LISTEN 0 128 *:7480 *:* users:(("radosgw",pid=8526,fd=48))
tcp LISTEN 0 128 [::]:7480 [::]:* users:(("radosgw",pid=8526,fd=49))
$ yum whatprovides netstat查询命令包
已加载插件:fastestmirror
Loading mirror speeds from cached hostfile
* elrepo: mirror-hk.koddos.net
net-tools-2.0-0.25.20131004git.el7.x86_64 : Basic networking tools
源 :@base
匹配来源:
文件名 :/usr/bin/netstat

$ curl http://node-1:7480
<?xml version="1.0" encoding="UTF-8"?><ListAllMyBucketsResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/"><Owner><ID>anonymous</ID><DisplayName></DisplayName></Owner><Buckets></Buckets></ListAllMyBucketsResult>

修改RGW默认端口

1
2
3
4
5
6
7
8
#修改ceph配置文件
[19:14:03 root@node-1 ~/ceph-deploy] # cat ceph.conf
......
[client.rgw.node-1]
rgw_frontends = "civetweb port=80"

$ ceph-deploy --overwrite-conf config push node-1 node-2 node-3 #强制推送配置文件
$ systemctl restart ceph-radosgw.target #重启服务

S3接口使用

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
$ radosgw-admin user create --uid="ceph-s3-user" --display-name="Ceph S3 User Demo"  #创建用户
{
"user_id": "ceph-s3-user",
"display_name": "Ceph S3 User Demo",
"email": "",
"suspended": 0,
"max_buckets": 1000,
"subusers": [],
"keys": [
{
"user": "ceph-s3-user",
"access_key": "LGHYIQC44CM0T7BHKW2U",
"secret_key": "olbc2icqlZwT3JA9d3dx86JAOIGtLZbopdneH8gu"
}
],
"swift_keys": [],
"caps": [],
"op_mask": "read, write, delete",
"default_placement": "",
"default_storage_class": "",
"placement_tags": [],
"bucket_quota": {
"enabled": false,
"check_on_raw": false,
"max_size": -1,
"max_size_kb": 0,
"max_objects": -1
},
"user_quota": {
"enabled": false,
"check_on_raw": false,
"max_size": -1,
"max_size_kb": 0,
"max_objects": -1
},
"temp_url_keys": [],
"type": "rgw",
"mfa_ids": []
}
$ radosgw-admin user info --uid ceph-s3-user #查询

测试 S3 访问

为了验证 S3 访问,你需要编写并运行一个 Python 测试脚本。S3 访问测试脚本将连接 radosgw, 新建一个新的 bucket 并列出所有的 buckets。 aws_access_key_idaws_secret_access_key 的值来自于命令radosgw_admin 的返回值 access_keysecret_key

执行下面的步骤:

  1. 你需要安装 python-boto 包:

    1
    sudo yum install python-boto
  2. 新建 Python 脚本文件:

    1
    vi s3test.py
  3. 将下面的内容添加到文件中:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    import boto
    import boto.s3.connection

    access_key = 'LGHYIQC44CM0T7BHKW2U'
    secret_key = 'olbc2icqlZwT3JA9d3dx86JAOIGtLZbopdneH8gu'
    conn = boto.connect_s3(
    aws_access_key_id=access_key,
    aws_secret_access_key=secret_key,
    host='10.211.55.201', port=7480,
    is_secure=False, # uncomment if you are not using ssl
    calling_format=boto.s3.connection.OrdinaryCallingFormat(),
    )
    bucket = conn.create_bucket('my-new-bucket')
    for bucket in conn.get_all_buckets():
    print
    "{name} {created}".format(
    name=bucket.name,
    created=bucket.creation_date,
    )


    {hostname} 替换为你配置了网关服务的节点的主机名。比如 gateway host. 将 {port} 替换为 Civetweb 所使用的端口。

  4. 运行脚本:

    1
    python s3test.py	

    输出类似下面的内容:

    1
    my-new-bucket 2015-02-16T17:09:10.000Z #个人做实验不会输出,但bucket已创建

S3cmd使用

配置文件

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
# yum install s3cmd
$ s3cmd --configure

Enter new values or accept defaults in brackets with Enter.
Refer to user manual for detailed description of all options.

Access key and Secret key are your identifiers for Amazon S3. Leave them empty for using the env variables.
Access Key: LGHYIQC44CM0T7BHKW2U #Access Key
Secret Key: olbc2icqlZwT3JA9d3dx86JAOIGtLZbopdneH8gu #Secret Key
Default Region [US]: #默认

Use "s3.amazonaws.com" for S3 Endpoint and not modify it to the target Amazon S3.
S3 Endpoint [s3.amazonaws.com]: 10.211.55.201:80 #地址

Use "%(bucket)s.s3.amazonaws.com" to the target Amazon S3. "%(bucket)s" and "%(location)s" vars can be used
if the target S3 system supports dns based buckets.
DNS-style bucket+hostname:port template for accessing a bucket [%(bucket)s.s3.amazonaws.com]: 10.211.55.201:80/%(bucket)s #

Encryption password is used to protect your files from reading
by unauthorized persons while in transfer to S3
Encryption password:
Path to GPG program [/usr/bin/gpg]:

When using secure HTTPS protocol all communication with Amazon S3
servers is protected from 3rd party eavesdropping. This method is
slower than plain HTTP, and can only be proxied with Python 2.7 or newer
Use HTTPS protocol [Yes]: no

On some networks all internet access must go through a HTTP proxy.
Try setting it here if you can't connect to S3 directly
HTTP Proxy server name:

New settings:
Access Key: LGHYIQC44CM0T7BHKW2U
Secret Key: olbc2icqlZwT3JA9d3dx86JAOIGtLZbopdneH8gu
Default Region: US
S3 Endpoint: 10.211.55.201:80
DNS-style bucket+hostname:port template for accessing a bucket: 10.211.55.201:80/%(bucket)s
Encryption password:
Path to GPG program: /usr/bin/gpg
Use HTTPS protocol: False
HTTP Proxy server name:
HTTP Proxy server port: 0

Test access with supplied credentials? [Y/n] y
Please wait, attempting to list all buckets...
Success. Your access key and secret key worked fine :-)

Now verifying that encryption works...
Not configured. Never mind.

Save settings? [y/N] y
Configuration saved to '/root/.s3cfg'

创建Bucket

1
2
3
4
5
6
7
8
9
10
$ s3cmd mb s3://test-demo
ERROR: S3 error: 403 (SignatureDoesNotMatch)
$ vim /root.s3
...
signature_v2 = False #替换为True
...
$ s3cmd mb s3://test-demo
Bucket 's3://test-demo/' created
$ s3cmd ls
2020-10-29 13:47 s3://test-demo

坑:

1
2
3
4
5
[22:06:38 root@node-1 ~/my-cluster] #s3cmd put /etc/fstab s3://my-new-bucket/fstab-demo
upload: '/etc/fstab' -> 's3://my-new-bucket/fstab-demo' [1 of 1]
389 of 389 100% in 0s 515.09 B/s done
ERROR: S3 error: 416 (InvalidRange) ####
将默认pg_num和pgp_num设置为较低的值(例如8)(未测试),或在ceph.conf中将mon_max_pg_per_osd=300设置为较高的值(已测试)

文件操作

1
2
3
4
5
$ s3cmd put /etc/fstab s3://test-demo/fstab-demo
$ s3cmd ls s3://test-demo/
$ s3cmd put /etc s3://test-demo/fstab-demo/etc --recursive #递归上传文件夹
$ s3cmd get s3://ceph-s3-test/test test2 #下载
$ s3cmd rm s3://ceph-s3-test/test #删除

image-20201029221514361

image-20201029221457258

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ ceph osd lspools
2 testpool
3 ceph-demo
4 .rgw.root
5 default.rgw.control
6 default.rgw.meta
7 default.rgw.log
8 default.rgw.buckets.index #索引
9 default.rgw.buckets.data #bucket存储池

$ s3cmd put /etc/fstab s3://test-demo/test

$ rados -p default.rgw.buckets.data ls #查看池文件
b7384d89-0aff-4a0b-acc9-c461bf7e5471.204143.2_test

swift风格api接口

  • 需要新建一个 Swift 子用户
  • 创建 Swift 用户包括两个步骤。第一步是创建用户。第二步是创建 secret key。

新建 Swift 用户:

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
radosgw-admin subuser create --uid=ceph-s3-user <--主用户id> --subuser=ceph-s3-user:swift --access=full
{
"user_id": "ceph-s3-user",
"display_name": "Ceph S3 User Demo",
"email": "",
"suspended": 0,
"max_buckets": 1000,
"subusers": [
{
"id": "ceph-s3-user:swift",
"permissions": "full-control"
}
],
"keys": [
{
"user": "ceph-s3-user",
"access_key": "LGHYIQC44CM0T7BHKW2U",
"secret_key": "olbc2icqlZwT3JA9d3dx86JAOIGtLZbopdneH8gu"
}
],
"swift_keys": [
{
"user": "ceph-s3-user:swift",
"secret_key": "bVLptVg3gFoyXzEFY2Trg4uMAXHP5954hkdl0vTr"
}
],
"caps": [],
"op_mask": "read, write, delete",
"default_placement": "",
"default_storage_class": "",
"placement_tags": [],
"bucket_quota": {
"enabled": false,
"check_on_raw": false,
"max_size": -1,
"max_size_kb": 0,
"max_objects": -1
},
"user_quota": {
"enabled": false,
"check_on_raw": false,
"max_size": -1,
"max_size_kb": 0,
"max_objects": -1
},
"temp_url_keys": [],
"type": "rgw",
"mfa_ids": []
}

新建 secret key:

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
radosgw-admin key create --subuser=ceph-s3-user:swift --key-type=swift --gen-secret
{
"user_id": "ceph-s3-user",
"display_name": "Ceph S3 User Demo",
"email": "",
"suspended": 0,
"max_buckets": 1000,
"subusers": [
{
"id": "ceph-s3-user:swift",
"permissions": "full-control"
}
],
"keys": [
{
"user": "ceph-s3-user",
"access_key": "LGHYIQC44CM0T7BHKW2U",
"secret_key": "olbc2icqlZwT3JA9d3dx86JAOIGtLZbopdneH8gu"
}
],
"swift_keys": [
{
"user": "ceph-s3-user:swift",
"secret_key": "lB93qfuWfaIyIZpPM5cbubajOWvS2ADtyN1pp8aS"
}
],
"caps": [],
"op_mask": "read, write, delete",
"default_placement": "",
"default_storage_class": "",
"placement_tags": [],
"bucket_quota": {
"enabled": false,
"check_on_raw": false,
"max_size": -1,
"max_size_kb": 0,
"max_objects": -1
},
"user_quota": {
"enabled": false,
"check_on_raw": false,
"max_size": -1,
"max_size_kb": 0,
"max_objects": -1
},
"temp_url_keys": [],
"type": "rgw",
"mfa_ids": []
}
1
"secret_key": "bVLptVg3gFoyXzEFY2Trg4uMAXHP5954hkdl0vTr"

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#安装环境
easy_install pip
pip install --upgrade setuptools
pip install --upgrade python-swiftclient
#测试
$ swift -A http://10.211.55.201:7480/auth/1.0 -U ceph-s3-user:swift -K 'lB93qfuWfaIyIZpPM5cbubajOWvS2ADtyN1pp8aS' list
ceph-s3-test
my-new-bucket
##可将变量保存开机启动脚本/etc/profile
export ST_AUTH=http://10.211.55.201:7480/auth
export ST_USER=ceph-s3-user:swift
export ST_KEY=lB93qfuWfaIyIZpPM5cbubajOWvS2ADtyN1pp8aS
$ swift list
ceph-s3-test
my-new-bucket

文件操作

1
2
3
4
5
6
7
8
9
10
11
$ swift post swift-demo
$ swift list
ceph-s3-test
my-new-bucket
swift-demo
$ swift upload swift-demo /etc/fstab #上传
etc/fstab
$ swift list swift-demo
etc/fstab
$ swift download swift-demo etc/fstab #下载
etc/fstab [auth 0.003s, headers 0.006s, total 0.006s, 0.105 MB/s]

查找文件

所有资源都是以对象的形式存储在资源池pool中,对象最终会映射到pg上,再由pg落盘到osd上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#rados -p default.rgw.buckets.data ls
b7384d89-0aff-4a0b-acc9-c461bf7e5471.204143.3_etc/fstab
b7384d89-0aff-4a0b-acc9-c461bf7e5471.204143.2_test$ ceph osd lspools
2 testpool
3 ceph-demo
4 .rgw.root
5 default.rgw.control
6 default.rgw.meta
7 default.rgw.log
8 default.rgw.buckets.index
9 default.rgw.buckets.data
$ rados -p default.rgw.buckets.data ls
b7384d89-0aff-4a0b-acc9-c461bf7e5471.204143.3_etc/fstab
b7384d89-0aff-4a0b-acc9-c461bf7e5471.204143.2_test
$ ceph osd map default.rgw.buckets.data b7384d89-0aff-4a0b-acc9-c461bf7e5471.204143.2_test
osdmap e255 pool 'default.rgw.buckets.data' (9) object 'b7384d89-0aff-4a0b-acc9-c461bf7e5471.204143.2_test' -> pg 9.fc424a45 (9.5) -> up ([2,1,0], p2) acting ([2,1,0], p2)
obj_id 'b7384d89-0aff-4a0b-acc9-c461bf7e5471.204143.2_test'--> pg 9.fc424a45 pg_id 9.5 --> osd [2,1,0]

CephFs文件系统

1
2
#挂载安装依赖
yum install nfs-utils

组件架构

Ceph文件系统或CephFS是在Ceph的分布式对象存储RADOS之上构建的POSIX兼容文件系统。CephFS致力于为各种应用程序提供最新,多用途,高可用性和高性能的文件存储,包括传统用例(如共享主目录,HPC暂存空间和分布式工作流共享存储)。

CephFS通过使用一些新颖的架构选择来实现这些目标。值得注意的是,文件元数据与文件数据存储在单独的RADOS池中,并通过可调整大小的元数据服务器MDS集群提供服务,该集群可扩展以支持更高吞吐量的元数据工作负载。文件系统的客户端可以直接访问RADOS来读写文件数据块。因此,工作负载可能会随着基础RADOS对象存储的大小线性扩展。也就是说,没有网关或代理为客户端中介数据I / O。

通过MDS集群协调对数据的访问,该集群充当客户端和MDS共同维护的分布式元数据缓存状态的授权机构。每个MDS都会将对元数据的突变汇总为对RADOS上日记的一系列有效写入。MDS不会在本地存储任何元数据状态。此模型允许在POSIX文件系统的上下文中客户端之间进行连贯且快速的协作。

image-20201031153325508

安装部署MDS集群

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ cd ceph-deploy/
$ ceph-deploy mds create node-1
$ ceph -s
cluster:
id: a96a9084-601e-46ca-a8b1-cf6b1ab5edf1
health: HEALTH_OK

services:
mon: 3 daemons, quorum node-1,node-2,node-3 (age 114m)
mgr: node-2(active, since 115m), standbys: node-1, node-3
mds: 1 up:standby #还没有文件系统,是standby状态
osd: 3 osds: 3 up (since 114m), 3 in (since 5d)
rgw: 1 daemon active (node-1)

task status:

data:
pools: 8 pools, 288 pgs
objects: 460 objects, 825 MiB
usage: 5.5 GiB used, 145 GiB / 150 GiB avail
pgs: 288 active+clean
$ ceph-deploy mds create node-2 node-3
$ ceph mds stat
3 up:standby

创建文件系统

1
2
3
4
5
6
7
8
9
$ ceph osd pool create cephfs_data 16 16
$ ceph osd pool create cephfs_meta 16 16
$ ceph fs new cephfs-demo cephfs_meta cephfs_data
$ ceph fs ls
name: cephfs-demo, metadata pool: cephfs_meta, data pools: [cephfs_data ]
$ ceph -s
...
mds: cephfs-demo:1 {0=node-2=up:active} 2 up:standby
...

内核挂载

{path-to-be-mounted}是CephFS中将要挂载的路径, {mount-point}是文件系统中将要挂载CephFS的点,并且{user-name}是有权在机器上挂载CephFS的CephX用户的名称。以下命令是扩展形式,但是这些额外的细节由mount.ceph帮助程序自动找出:

1
2
$ mount -t ceph {ip-address-of-MON}:{port-number-of-MON}:{path-to-be-mounted} -o name={user-name},secret={secret-key} {mount-point}
$ mount -t ceph 10.211.55.201:6789:/ /mnt/cephfs/ -o name=admin

如果群集上有多个文件系统,则需要将fs={fs-name}option传递 给-ooption mount

1
sudo mount -t ceph :/ /mnt/kcephfs2 -o name=admin,fs=mycephfs2
1
2
3
4
5
$ lsmod | grep ceph
ceph 438272 1
libceph 339968 1 ceph
fscache 376832 1 ceph
libcrc32c 16384 2 xfs,libceph

用户态挂载

要使用FUSE(用户空间中的文件系统)挂载CephFS,请运行:

1
2
3
yum install ceph-fuse -y
mkdir /mnt/ceph-fuse
ceph-fuse -n client.admin -m 10.211.55.201:6789,10.211.55.202:6789,10.211.55.203:6789 /mnt/ceph-fuse

要在CephFS中挂载特定目录,您可以使用-r

1
ceph-fuse -r {path-to-be-mounted} /mnt/mycephfs

如果群集上有多个文件系统,则需要传递 给命令:--client_fs {fs-name}``ceph-fuse

1
ceph-fuse /mnt/mycephfs2 --client_fs mycephfs2

osd扩容与换盘

osd纵向扩容

1
2
3
4
5
$ ceph-deploy disk list node-1 #查看节点磁盘
$ ceph-deploy disk zap node-1 /dev/sdc # 清理磁盘分区 ceph-deploy disk zap {osd-server-name} {disk-name}
$ ceph-deploy osd create node-1 --data /dev/sdc
$ ceph-deploy osd create node-2 --data /dev/sdc
$ ceph-deploy osd create node-3 --data /dev/sdc

数据rebalancing重分布

当您将Ceph OSD守护程序添加到Ceph存储群集时,群集映射将使用新的OSD更新。再次参考计算PG ID,这将更改群集映射。因此,它更改了对象放置,因为它更改了计算的输入。下图描述了重新平衡过程(尽管相当粗略,因为它对大型集群的影响较小),其中一些(但不是全部)PG从现有OSD(OSD 1和OSD 2)迁移到新OSD(OSD 3) )。即使重新平衡,破碎也很稳定。许多放置组仍保持其原始配置,并且每个OSD都增加了一些容量,因此重新平衡完成后,新OSD上不会出现负载峰值。

1
$ ceph df

image-20201101154218826

1
2
dd if=/dev/zero of=rebalancing-file.img bs=1M count=5120
cp rebalancing-file.img /mnt/cephfs/

image-20201101154727560

1
2
3
4
cp rebalancing-file.img /mnt/rbd-demo/
# node-3加盘
cd ceph-deploy
ceph-deploy osd create node-3 --data /dev/sdd

recovery流量进行数据重分布

image-20201101161322118

临时关闭rebalancing

1
2
3
4
5
6
7
8
ceph --admin-daemon /var/run/ceph/ceph-mon.node-1.asok config show| grep max_backfills
"osd_max_backfills": "1",
#最多有一个线程做数据填充,每个osd会拿1个线程同步数据
cat ceph.conf
...
public_network = 10.211.55.0/24 #客户端连接网络
cluster_network = 10.211.56.0/24 # 扩容重分布走cluster_network
...
1
2
3
4
5
6
7
8
9
10
$ ceph osd set norebalance #关闭数据分布标志位
$ ceph osd set nobackfill #关闭数据填充
$ ceph -s
cluster:
id: a96a9084-601e-46ca-a8b1-cf6b1ab5edf1
health: HEALTH_WARN
nobackfill,norebalance flag(s) set
...
$ ceph osd unset norebalance #取消数据分布标志位
$ ceph osd unset nobackfill #取消数据填充

osd坏盘更换

1
2
dmesg #查看日志信息
ceph osd perf #查看osd延迟

删除OSD,通常为upin。您需要将其从群集中删除,以便Ceph可以开始重新平衡并将其数据复制到其他OSD。

1
ceph osd out {osd-num}

模拟坏盘

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ ceph osd tree
ID CLASS WEIGHT TYPE NAME STATUS REWEIGHT PRI-AFF
....
-7 0.17569 host node-3
2 hdd 0.04880 osd.2 up 1.00000 1.00000
5 hdd 0.04880 osd.5 up 1.00000 1.00000
6 hdd 0.07809 osd.6 up 1.00000 1.00000 ##第六快盘
[root@node-3 ~] $ systemctl stop ceph-osd@6.service
$ ceph osd tree
....
-7 0.17569 host node-3
2 hdd 0.04880 osd.2 up 1.00000 1.00000
5 hdd 0.04880 osd.5 up 1.00000 1.00000
6 hdd 0.07809 osd.6 down 1.00000 1.00000 #down状态
  • 坏盘后大约10分钟后数据重分布

image-20201101171351988

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ ceph osd out osd.6
$ ceph osd tree
ID CLASS WEIGHT TYPE NAME STATUS REWEIGHT PRI-AFF
....
-7 0.17569 host node-3
....
6 hdd 0.07809 osd.6 down 0 1.00000 #权重为0
$ ceph osd crush dump | less #osd6依然在crush算法里
$ ceph osd crush rm osd.6 #删除osd.6 crush算法
$ ceph osd rm osd.6 #删除osd
$ ceph auth list && ceph auth rm osd.6 #删除认证
$ dmsetup status #查看lvm信息
$ ceph-volume lvm zap /dev/sdd --destroy #在所在osd删除lvm卷
$ echo "w" | fdisk /dev/sdd #更新磁盘信息

c71970eb16b0dacbe6c8a79391a0003

步骤:

  1. ceph osd out 驱逐
  2. ceph osd crush rm osd.6删除osd.6 crush算法
  3. ceph osd rm osd.6 #删除osd
  4. ceph auth rm osd.6 #删除认证

数据一致性检查DATA CONSISTENCY

作为保持数据一致性和整洁度的一部分,Ceph OSD还可以清理放置组中的对象。也就是说,Ceph OSD可以将一个放置组中的对象元数据与其存储在其他OSD中的放置组中的副本进行比较。

清理(通常每天执行一次)会捕获OSD错误或文件系统错误。OSD还可以通过逐位比较对象中的数据来执行更深入的清理。

深度清理(通常每周执行一次)会发现磁盘上的坏扇区在轻度清理中并不明显。

Ceph清理类似于fsck对象存储层上的清理。对于每个pg,Ceph都会生成所有对象的目录,并比较每个主要对象及其副本,以确保没有对象丢失或不匹配。轻擦洗(每天)检查对象的大小和属性。深度清理(每周一次)读取数据并使用校验和以确保数据完整性。

配置清理参数

清理有两种,针对pg,针对osd

1
2
3
4
5
$ ceph pg dump #获取pg_id
$ ceph pg scrub 6.1b #轻度检查
$ ceph pg deep-scrub 6.1b
$ ceph pg dump | grep "active" |awk '{print $1}' | xargs -I{} -- ceph pg deep-scrub {} #深度检查所有pg
$ for i in `ceph pg dump | grep "active" |awk '{print $1}'`;do ceph pg deep-scrub ${i};done #停不下来

出现deep scrub

ceph集群运维

守护服务管理

1
systemctl start ceph.target       # 对应所有服务

要列出节点上的Ceph systemd单元

1
systemctl status ceph\*.service ceph\*.target | grep Load

按类型

1
2
3
systemctl start ceph-osd.target #对应所有osd的守护进程
systemctl start ceph-mon.target
systemctl start ceph-mds.target

特定的守护程序实例

1
systemctl start ceph-osd@1

服务日志分析

/var/log/ceph(默认位置)下查看Ceph日志文件

集群状态监控

集群

ceph以交互方式运行该工具,请ceph在命令行中键入,不带参数。例如:

1
2
3
4
5
ceph
ceph> health
ceph> status
ceph> quorum_status
ceph> mon stat

ceph -s = ceph status

1
2
ceph -s = ceph status
ceph -w

存储

要检查集群在池中的数据使用情况和数据分布,可以使用该df选项。它类似于Linux df。执行以下命令:

1
ceph df

输出的RAW STORAGE部分提供了群集管理的存储量的概述。

  • 类别: OSD设备的类别(或群集的总数)

  • 大小:集群管理的存储容量。

  • 可用:自由空间的集群中使用的量。

  • 已用:用户数据消耗的原始存储量。

  • 原始使用用户数据,内部开销或保留的容量消耗的原始存储量。

  • 已用%RAW:已用原始存储空间的百分比。将此数字与和结合使用,以确保未达到群集的容量。有关更多详细信息,请参见存储容量full ratio near full ratio

输出的POOLS部分提供了池的列表以及每个池的概念用法。本节的输出反映副本,克隆或快照。例如,如果存储的对象具有1MB的数据,则名义使用量将为1MB,但实际使用量可能为2MB或更多,具体取决于副本,克隆和快照的数量。

  • NAME:池的名称。
  • ID:池ID。
  • 已使用:名义上存储的数据量(以千字节为单位),除非数字在M(兆字节)后附加G(千兆字节)。
  • %USED:每个池使用的名义存储百分比。
  • MAX AVAIL:可以写入此池的名义数据量的估计值。
  • 对象:每个池中存储的对象的名义数量。

注意:

POOLS部分中的数字是名义上的。它们不包括副本,快照或克隆的数量。其结果是,在总和USED%USED金额不会加起来 USED%USED的数量RAW输出的部分。

MAX AVAIL值是用于复制或纠删码的复杂函数,映射到存储设备上的CRUSH规则,这些设备的利用率,以及配置的mon_osd_full_ratio。

osd

1
2
3
4
ceph osd status
ceph osd dump
ceph osd tree
ceph osd df

mon

1
2
ceph mon stat
ceph mon dump

要检查监视器群集的仲裁状态,请执行以下操作:

1
ceph quorum_status | jq

mds

1
2
ceph mds stat
ceph fs dump

使用socket

1
2
3
ceph --admin-daemon /var/run/ceph/ceph-mon.node-1.asok help | jq
ceph --admin-daemon /var/run/ceph/ceph-mon.node-1.asok config show | jq
ceph --admin-daemon /var/run/ceph/ceph-mon.node-1.asok config set <参数> <值>

POOL管理

首次部署群集而不创建池时,Ceph使用默认池来存储数据。

  • 弹性Resilience:可以设置允许多少OSD发生故障而不丢失数据。对于复制池,它是对象的所需副本数/副本数。典型的配置存储一个对象和一个附加副本,但是您可以确定副本/副本的数量。对于擦除编码池,它是编码块的数量(即在擦除代码配置文件中**)size = 2``m=2
  • Placement Groups:您可以设置池的放置组数。一个典型的配置每个OSD使用大约100个放置组,以提供最佳的平衡,而不会消耗太多的计算资源。设置多个池时,请确保为池和整个群集设置合理数量的放置组。
  • CRUSH规则:将数据存储在池中时,对象及其副本(或用于擦除编码池的块)在群集中的位置由CRUSH规则控制。如果默认规则不适用于您的用例,则可以为您的池创建自定义的CRUSH规则。
  • 快照:使用创建快照时,可以有效地为特定池拍摄快照。ceph osd pool mksnap
1
2
3
4
5
ceph osd lspools
ceph osd pool create {pool-name} [{pg-num} [{pgp-num}]] [replicated] \
[crush-rule-name] [expected-num-objects最大允许对象obj数量]
ceph osd pool get testpool size
ceph osd pool set testpool size 1

将pool关联到应用程序

对于其他情况,您可以手动将自由格式的应用程序名称关联到池。

1
ceph osd pool application enable {pool-name} {application-name}
  • CephFS使用应用程序名称cephfs,RBD使用应用程序名称rbd,而RGW使用应用程序名称rgw
1
2
3
4
5
6
7
8
$ ceph osd pool application get testpool
{}
$ ceph osd pool application enable testpool rbd
enabled application 'rbd' on pool 'testpool'
$ ceph osd pool application get testpool
{
"rbd": {}
}

设置pool配额

您可以将池配额设置为每个池的最大字节数和/或最大对象数。

1
ceph osd pool set-quota {pool-name} [max_objects {obj-count}] [max_bytes {bytes}]

例如:

1
2
3
4
5
6
$ ceph osd pool set-quota testpool max_objects 100
set-quota max_objects = 100 for pool testpool
$ ceph osd pool get-quota testpool
quotas for pool 'testpool':
max objects: 100 objects
max bytes : N/A

删除配额,将其值设置为0

重命名

要重命名池,请执行:

1
ceph osd pool rename {current-pool-name} {new-pool-name}

如果重命名池,并且您具有针对经过身份验证的用户的每个池功能,则必须使用新的池名称更新用户的功能(即上限)。

pool利用率

1
rados df

要获取特定池或全部池的I / O信息,请执行以下操作:

1
ceph osd pool stats [{pool-name}]

命名一个pool

1
ceph osd pool rename {current-pool-name} {new-pool-name}

如果重命名了一个存储池,且认证用户有每存储池能力,那你必须用新存储池名字更新用户的能力(即 caps )。

pool参数

https://docs.ceph.com/en/octopus/rados/operations/pools/#set-pool-values

pg数据分布

存储池内的归置组( PG )把对象汇聚在一起,因为跟踪每一个对象的位置及其元数据需要大量计算——即一个拥有数百万对象的系统,不可能在对象这一级追踪位置。

Ceph 客户端会计算某一对象应该位于哪个归置组里,它是这样实现的,先给对象 ID 做哈希操作,然后再根据指定存储池里的 PG 数量、存储池 ID 做一个运算。

计算pg

image-20201107161954468

总pg数 = (OSD数量 * 100) / pool 副本数(默认为3)

然后取其最近的 2的n次方

1
(200*100)/3=6667 #去最近2的n次方: 4096或8192

创建pool是指定大小

1
2
3
$ ceph osd pool set mypool target_size_bytes 100T
#会告诉系统mypool预计会占用100 TiB的空间。
$ ceph osd pool set mypool target_size_ratio 1.0 #设置百分比

如果mypool是群集中唯一的池,则意味着预期使用了总容量的100%。

如果第二个池的target_size_ratio= 1.0,则两个池都将使用50%的群集容量。

如果指定了不可能的目标大小值(例如,容量大于整个群集的容量),则会发出健康警告(POOL_TARGET_SIZE_BYTES_OVERCOMMITTED)。

如果为池指定了target_size_ratiotarget_size_bytes,则仅考虑比率,并发出运行状况警告(POOL_HAS_TARGET_SIZE_BYTES_AND_RATIO)。

指定池的PG的边界

也可以为一个池指定最小数量的PG。这对于确定执行IO时客户端将看到的并行度的数量的下限很有用,即使池中大多数都是空的。设置下限可以防止Ceph将PG编号减少(或建议减少)到配置的编号以下。

您可以使用以下方法设置池的最小PG数量:

1
ceph osd pool set <pool-name> pg_num_min <num>

您也可以使用命令的可选参数来指定创建池时的最小PG数量。

1
ceph osd pool create --pg-num-min <num> 

CEPH参数调整配置

删除pool

要删除一存储池,执行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
ceph osd pool delete {pool-name} [{pool-name} --yes-i-really-really-mean-it]
# 提示需加参数
ceph --admin-daemon /var/run/ceph/ceph-mon.node-1.asok config show | grep mon_allow
#设置参数
ceph --admin-daemon /var/run/ceph/ceph-mon.node-1.asok config set mon_allow_pool_delete true #需在所有mon节点执行 这个只是临时调整

#或在配置文件添加参数
[global]
mon_allow_pool_delete = true

#强制推送配置文件
ceph-deploy --overwrite-conf config push node-1 node-2 node-3

#重启服务

如果你给自建的存储池创建了定制的规则集,你不需要存储池时最好删除它。如果你曾严格地创建了用户及其权限给一个存储池,但存储池已不存在,最好也删除那些用户。

调整CRUSH MAP

简介

CRUSH 算法通过计算数据存储位置来确定如何存储和检索。 CRUSH 授权 Ceph 客户端直接连接 OSD ,而非通过一个中央服务器或代理。数据存储、检索算法的使用,使 Ceph 避免了单点故障、性能瓶颈、和伸缩的物理限制。

CRUSH 需要一张集群的 Map,且使用 CRUSH Map 把数据伪随机地、尽量平均地分布到整个集群的 OSD 里。CRUSH Map 包含 OSD 列表、把设备汇聚为物理位置的“桶”列表、和指示 CRUSH 如何复制存储池里的数据的规则列表。

bucket是层次结构中内部节点(主机,机架,行等)的CRUSH术语。CRUSH映射定义了一系列用于描述这些节点的类型。默认情况下,这些类型包括:

  • osd(或设备)
  • 主机host
  • 机壳
  • 机架
  • pdu
  • pod
  • 机房
  • 数据中心
  • 地区

大多数群集仅使用其中少数几个类型,可以根据需要定义其他类型。

该层次结构是通过osd在叶子的设备(通常为type ),内部节点(具有非设备类型)和type的根节点 构建的root。例如,

规则剖析

查看规则树:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ ceph osd crush tree
ID CLASS WEIGHT TYPE NAME
-1 0.29279 root default
-3 0.09760 host node-1
0 hdd 0.04880 osd.0
3 hdd 0.04880 osd.3
-5 0.09760 host node-2
1 hdd 0.04880 osd.1
4 hdd 0.04880 osd.4
-7 0.09760 host node-3
2 hdd 0.04880 osd.2
5 hdd 0.04880 osd.5
$ ceph osd osd tree
$ ceph osd crush dump
$ ceph osd crush rule ls
replicated_rule #默认规则
$ ceph osd pool get testpool crush_rule
crush_rule: replicated_rule
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
{
"devices": [ #osd设备
{
"id": 0,
"name": "osd.0",
"class": "hdd"
},
{
"id": 1,
"name": "osd.1",
"class": "hdd"
},
{
"id": 2,
"name": "osd.2",
"class": "hdd"
},
{
"id": 3,
"name": "osd.3",
"class": "hdd"
},
{
"id": 4,
"name": "osd.4",
"class": "hdd"
},
{
"id": 5,
"name": "osd.5",
"class": "hdd"
}
],
"types": [ #层级类型
{
"type_id": 0,
"name": "osd"
},
{
"type_id": 1,
"name": "host"
},
{
"type_id": 2,
"name": "chassis"
},
{
"type_id": 3,
"name": "rack"
},
{
"type_id": 4,
"name": "row"
},
{
"type_id": 5,
"name": "pdu"
},
{
"type_id": 6,
"name": "pod"
},
{
"type_id": 7,
"name": "room"
},
{
"type_id": 8,
"name": "datacenter"
},
{
"type_id": 9,
"name": "zone"
},
{
"type_id": 10,
"name": "region"
},
{
"type_id": 11,
"name": "root"
}
],
"buckets": [ #顶层root
{
"id": -1,
"name": "default",
"type_id": 11,
"type_name": "root",
"weight": 19188,
"alg": "straw2",
"hash": "rjenkins1",
"items": [ #下属host
{
"id": -3,
"weight": 6396,
"pos": 0
},
{
"id": -5,
"weight": 6396,
"pos": 1
},
{
"id": -7,
"weight": 6396,
"pos": 2
}
]
},
{
"id": -2,
"name": "default~hdd",
"type_id": 11,
"type_name": "root",
"weight": 19188,
"alg": "straw2",
"hash": "rjenkins1",
"items": [
{
"id": -4,
"weight": 6396,
"pos": 0
},
{
"id": -6,
"weight": 6396,
"pos": 1
},
{
"id": -8,
"weight": 6396,
"pos": 2
}
]
},
{
"id": -3, #node-1节点信息
"name": "node-1",
"type_id": 1,
"type_name": "host",
"weight": 6396,
"alg": "straw2",
"hash": "rjenkins1",
"items": [
{
"id": 0,
"weight": 3198,
"pos": 0
},
{
"id": 3,
"weight": 3198,
"pos": 1
}
]
},
{
"id": -4,
"name": "node-1~hdd",
"type_id": 1,
"type_name": "host",
"weight": 6396,
"alg": "straw2",
"hash": "rjenkins1",
"items": [
{
"id": 0,
"weight": 3198,
"pos": 0
},
{
"id": 3,
"weight": 3198,
"pos": 1
}
]
},
{
"id": -5,
"name": "node-2",
"type_id": 1,
"type_name": "host",
"weight": 6396,
"alg": "straw2",
"hash": "rjenkins1",
"items": [
{
"id": 1,
"weight": 3198,
"pos": 0
},
{
"id": 4,
"weight": 3198,
"pos": 1
}
]
},
{
"id": -6,
"name": "node-2~hdd",
"type_id": 1,
"type_name": "host",
"weight": 6396,
"alg": "straw2",
"hash": "rjenkins1",
"items": [
{
"id": 1,
"weight": 3198,
"pos": 0
},
{
"id": 4,
"weight": 3198,
"pos": 1
}
]
},
{
"id": -7,
"name": "node-3",
"type_id": 1,
"type_name": "host",
"weight": 6396,
"alg": "straw2",
"hash": "rjenkins1",
"items": [
{
"id": 2,
"weight": 3198,
"pos": 0
},
{
"id": 5,
"weight": 3198,
"pos": 1
}
]
},
{
"id": -8,
"name": "node-3~hdd",
"type_id": 1,
"type_name": "host",
"weight": 6396,
"alg": "straw2",
"hash": "rjenkins1",
"items": [
{
"id": 2,
"weight": 3198,
"pos": 0
},
{
"id": 5,
"weight": 3198,
"pos": 1
}
]
}
],
"rules": [
{
"rule_id": 0,
"rule_name": "replicated_rule",
"ruleset": 0,
"type": 1,
"min_size": 1,
"max_size": 10,
"steps": [
{
"op": "take",
"item": -1,
"item_name": "default"
},
{
"op": "chooseleaf_firstn",
"num": 0,
"type": "host"
},
{
"op": "emit"
}
]
}
],
"tunables": { #一些参数
"choose_local_tries": 0,
"choose_local_fallback_tries": 0,
"choose_total_tries": 50,
"chooseleaf_descend_once": 1,
"chooseleaf_vary_r": 1,
"chooseleaf_stable": 1,
"straw_calc_version": 1,
"allowed_bucket_algs": 54,
"profile": "jewel",
"optimal_tunables": 1,
"legacy_tunables": 0,
"minimum_required_version": "jewel",
"require_feature_tunables": 1,
"require_feature_tunables2": 1,
"has_v2_rules": 0,
"require_feature_tunables3": 1,
"has_v3_rules": 0,
"has_v4_buckets": 1,
"require_feature_tunables5": 1,
"has_v5_rules": 0
},
"choose_args": {}
}

定制CRUSH拓扑架构

CRUSH Map 主要有 4 个段落。

  • 设备:由任意对象存储设备组成,即对应一个 ceph-osd进程的存储器。 Ceph 配置文件里的每个 OSD 都应该有一个设备。
  • 桶类型: 定义了 CRUSH 分级结构里要用的桶类型( types ),桶由逐级汇聚的存储位置(如行、机柜、机箱、主机等等)及其权重组成。
  • 桶实例: 定义了桶类型后,还必须声明主机的桶类型、以及规划的其它故障域。
  • 规则: 由选择桶的方法组成。

要编辑现有的CRUSH映射,请执行以下操作:

  1. 获取CRUSH地图
  2. 反编译CRUSH映射。
  3. 编辑设备,存储规则中的至少一项。
  4. 重新编译CRUSH映射。
  5. 设置CRUSH图

image-20201110150639939

两种修改方式

手动编辑

1
2
3
4
5
6
7
$ ceph osd getcrushmap -o crushmap.bin #保存crushmap二进制文件
22
$ file crushmap.bin
crushmap.bin: MS Windows icon resource - 16 icons, 1-colors
$ crushtool -d crushmap.bin -o crushmap.txt #反编译
$ file crushmap.txt
crushmap.txt: ASCII text
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
# begin crush map
tunable choose_local_tries 0
tunable choose_local_fallback_tries 0
tunable choose_total_tries 50
tunable chooseleaf_descend_once 1
tunable chooseleaf_vary_r 1
tunable chooseleaf_stable 1
tunable straw_calc_version 1
tunable allowed_bucket_algs 54

# devices
device 0 osd.0 class hdd
device 1 osd.1 class hdd
device 2 osd.2 class hdd
device 3 osd.3 class ssd
device 4 osd.4 class ssd
device 5 osd.5 class ssd

# types
type 0 osd
type 1 host
type 2 chassis
type 3 rack
type 4 row
type 5 pdu
type 6 pod
type 7 room
type 8 datacenter
type 9 zone
type 10 region
type 11 root

# buckets
host node-1 {
id -3 # do not change unnecessarily
id -4 class hdd # do not change unnecessarily
# weight 0.098
alg straw2
hash 0 # rjenkins1
item osd.0 weight 0.049
}
host node-2 {
id -5 # do not change unnecessarily
id -6 class hdd # do not change unnecessarily
# weight 0.098
alg straw2
hash 0 # rjenkins1
item osd.1 weight 0.049
}
host node-3 {
id -7 # do not change unnecessarily
id -8 class hdd # do not change unnecessarily
# weight 0.098
alg straw2
hash 0 # rjenkins1
item osd.2 weight 0.049
}
host node-1-ssd {
# weight 0.098
alg straw2
hash 0 # rjenkins1
item osd.3 weight 0.049
}
host node-2-ssd {
# weight 0.098
alg straw2
hash 0 # rjenkins1
item osd.4 weight 0.049
}
host node-3-ssd {
# weight 0.098
alg straw2
hash 0 # rjenkins1
item osd.5 weight 0.049
}
root default {
id -1 # do not change unnecessarily
id -2 class hdd # do not change unnecessarily
# weight 0.293
alg straw2
hash 0 # rjenkins1
item node-1 weight 0.049
item node-2 weight 0.049
item node-3 weight 0.049
}
root ssd {
# weight 0.293
alg straw2
hash 0 # rjenkins1
item node-1-ssd weight 0.049
item node-2-ssd weight 0.049
item node-3-ssd weight 0.049
}

# rules
rule replicated_rule {
id 0
type replicated
min_size 1
max_size 10
step take default
step chooseleaf firstn 0 type host
step emit
}
rule demo_rule {
id 10
type replicated
min_size 1
max_size 10
step take ssd
step chooseleaf firstn 0 type host
step emit
}

# end crush map

1
$ crushtool -c crushmap.txt -o crushmap-new.bin #编译新规则文件

image-20201110232102291

应用规则

1
2
$ ceph osd setcrushmap -i crushmap-new.bin 
23

image-20201110232310060

修改rule

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ ceph osd lspools
2 testpool
3 ceph-demo
4 .rgw.root
...
$ ceph osd pool get ceph-demo crush_rule
crush_rule: replicated_rule #修改前
$ ceph osd pool set ceph-demo crush_rule demo_rule
set pool 3 crush_rule to demo_rule #修改后
$ ceph osd pool get ceph-demo crush_rule
crush_rule: demo_rule

$ rbd create ceph-demo/test-rbd.img --size 1G
$ ceph osd map ceph-demo test-rbd.img
osdmap e771 pool 'ceph-demo' (3) object 'test-rbd.img' -> pg 3.48f5ff89 (3.9) -> up ([4,3,5], p4) acting ([4,3,5], p4)

命令行调整

已将crush恢复初始

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$ ceph osd crush add-bucket ssd root #从上往下,先添加顶层bucket
added bucket ssd type root to crush map
$ ceph osd crush add-bucket node-1-ssd host
added bucket node-1-ssd type host to crush map
$ ceph osd crush add-bucket node-2-ssd host
$ ceph osd crush add-bucket node-3-ssd host
$ ceph osd tree
ID CLASS WEIGHT TYPE NAME STATUS REWEIGHT PRI-AFF
-12 0 host node-3-ssd
-11 0 host node-2-ssd
-10 0 host node-1-ssd
-9 0 root ssd
-1 0.29279 root default
...
# 将bucket加入顶层root ssd
$ ceph osd crush move node-1-ssd root=ssd
$ ceph osd crush move node-2-ssd root=ssd
$ ceph osd crush move node-3-ssd root=ssd
# 将osd移动到host
$ ceph osd crush move osd.3 host=node-1-ssd root=ssd
$ ceph osd crush move osd.4 host=node-2-ssd root=ssd
$ ceph osd crush move osd.5 host=node-3-ssd root=ssd

1
2
3
4
5
6
# 修改osd class
$ ceph osd crush rm-device-class 3 #先删除
$ ceph osd crush set-device-class ssd 3 #在设置
# 创建rule
# osd crush rule create-replicated <name> <root> <type> {<class>}
$ ceph osd crush rule create-replicated ssd-demo ssd host ssd

注意事项

  • 操作前先备份

  • 保留每次修改的bin文件

  • 初始就规划好

  • 重启osd crushmap会变动

    1
    2
    3
    4
    5
    6
    #增加osd配置文件
    [osd]
    osd crush update on start = flase
    ceph-deploy --overwrite-conf config push node-1 node-2 node-3
    # 重启osd
    systemctl reset-failed ceph-osd@0.service
  • 增加配置后新加osd需手动添加crushmap

RBD高级功能

RBD回收站机制

正常的 rbd image 一旦删除了就没了,但是 ceph rbd 提供了回收站方式给你反悔的机会。

实验

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
$ rbd create ceph-demo/ceph-trash.img --size 1G
$ rbd info ceph-demo/ceph-trash.img
rbd image 'ceph-trash.img':
size 1 GiB in 256 objects
order 22 (4 MiB objects)
snapshot_count: 0
id: 60403c5044e18
block_name_prefix: rbd_data.60403c5044e18
format: 2
features: layering, exclusive-lock, object-map, fast-diff, deep-flatten
op_features:
flags:
create_timestamp: Wed Nov 11 19:57:02 2020
access_timestamp: Wed Nov 11 19:57:02 2020
modify_timestamp: Wed Nov 11 19:57:02 2020
$ rbd rm ceph-demo/ceph-trash.img #直接删除后毛都不留
Removing image: 100% complete...done.
$ rbd -p ceph-demo trash ls # 查看回收站

### 使用回收站删除
rbd trash move [--pool <pool>] [--namespace <namespace>]
[--image <image>] [--expires-at <expires-at>]
<image-spec>
$ rbd trash move ceph-demo/test-rbd.img --expires-at 20201130
$ rbd -p ceph-demo trash ls #过期自动清理
567c52ba8a29b test-rbd.img

###回收镜像
rbd trash restore -p ceph-demo 567c52ba8a29b

镜像制作快照

1
2
3
4
5
6
7
8
9
10
$ rbd create ceph-demo/rbd-tst.img --image-feature layering --size 1G
$ rbd device map ceph-demo/rbd-tst.img
$ mkfs.ext4 /dev/rbd0
$ mount /dev/rbd0 /media
$ echo 20201111 > /media/file20201111
$ sync #同步数据
$ rbd snap create ceph-demo/rbd-tst.img@snap20201111 #创建快照
$ rbd snap ls ceph-demo/rbd-tst.img
SNAPID NAME SIZE PROTECTED TIMESTAMP
4 snap20201111 1 GiB Wed Nov 11 22:15:25 2020

快照数据恢复

1
2
3
4
5
6
$ rm /media/file1 -f
# rbd snap rollback [<pool-name>/[<namespace>/]]<image-name>@<snapshot-name>)
$ umount /media #先卸载
$ rbd snap rollback ceph-demo/rbd-tst.img@snap20201111
Rolling back to snapshot: 100% complete...done.
$ mount /dev/rbd0 /media/

删除RBD

1
2
3
4
5
6
7
8
9
#全部卸载
$ rbd unmap ceph-demo/rbd-tst.img #卸载镜像
#rbd snap purge {pool-name}/{namespace}
$ rbd snap purge ceph-demo/rbd-tst.img #清除所有快照
$ rbd snap remove ceph-demo/rbd-tst.img@snap20201111 #单个删除
$ rbd remove ceph-demo/rbd-tst.img #删除镜像
$ rbd device ls
id pool namespace image snap device
0 ceph-demo rbd-tst.img - /dev/rbd0

镜像克隆机制

Ceph支持创建块设备快照的许多写时复制(COW)克隆的功能。快照分层使Ceph块设备客户端可以非常快速地创建图像。例如,您可能会在写入了Linux VM的情况下创建块设备映像。然后,对映像进行快照,保护快照,并根据需要创建尽可能多的写时复制克隆。快照是只读的,因此克隆快照可以简化语义,从而可以快速创建克隆。

1
2
3
4
5
6
7
8
9
# rbd clone {pool-name}/{parent-image}@{snap-name} {pool-name}/{child-image-name}
$ rbd snap create ceph-demo/rbd-tst.img@template # 创建镜像快照
$ rbd snap protect ceph-demo/rbd-tst.img@template #镜像保护
$ rbd snap rm ceph-demo/rbd-tst.img@template #无法删除
Removing snap: 0% complete...failed.
rbd: snapshot 'template' is protected from removal.
2020-11-12 20:04:38.434 7f49ae2a3c80 -1 librbd::Operations: snapshot is protected
# 从快照克隆镜像
$ rbd clone ceph-demo/rbd-tst.img@template ceph-demo/vm1-clone.img

快照子项

1
2
3
4
##rbd children {pool-name}/{image-name}@{snapshot-name}
$ rbd children ceph-demo/rbd-tst.img
ceph-demo/vm1-clone.img
ceph-demo/vm2-clone.img

解除依赖关系

1
2
3
4
5
6
7
8
9
10
#rbd flatten {pool-name}/{image-name}
$ rbd flatten ceph-demo/vm1-clone.img
Image flatten: 100% complete...done.
$ rbd children ceph-demo/rbd-tst.img
ceph-demo/vm2-clone.img
$ rbd info ceph-demo/vm2-clone.img
rbd image 'vm2-clone.img':
...
parent: ceph-demo/rbd-tst.img@template #存在依赖关系
overlap: 1 GiB

RBD备份与恢复

1
2
3
4
5
6
$ rbd export ceph-demo/vm2-clone.img /root/test.img #备份
Exporting image: 100% complete...done.
$ du -sh /root/test.img
32M /root/test.img
$ rbd import /root/test.img ceph-demo/vm2-clone-new.img #导入
## 导入存在镜像会报错,按提示忽略

增量备份与恢复

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ echo 111 > /media/file20201111-new
$ sync
$ rbd snap create ceph-demo/rbd-tst.img@v1
$ rbd export-diff ceph-demo/rbd-tst.img@v1 rbd-tst.img@v1
$ du -sh ./*
7.4M ./rbd-tst.img@v1 ##增量导出大小
32M ./test.img
##挂载之前导入的镜像
$ rbd map ceph-demo/vm2-clone-new.img
$ mkdir /vm2-clone-new
$ mount /dev/rbd1 /vm2-clone-new
$ ll /vm2-clone-new
总用量 24
-rw-r--r-- 1 root root 13 11月 13 15:27 file20201111
###导入增量备份
$ rbd import-diff /root/rbd-tst.img@v1 ceph-demo/vm2-clone-new.img
#重新挂载rbd
$ ll /vm2-clone-new
总用量 24
-rw-r--r-- 1 root root 13 11月 13 15:27 file20201111
-rw-r--r-- 1 root root 4 11月 13 15:49 file20201111-new

导入导出总结

RGW高可用集群

拓展RGW集群

之前部署只有一个RGW网关

1
2
$ cd ceph-deploy
$ ceph-deploy rgw create node-2

可以修改端口

搭建高可用环境

主机名 IP地址 端口 软件 VIP+端口
node-1 10.211.55.201 81 rgw+ha+kp 10.211.55.200:80
node-2 10.211.55.202 81 rgw+ha+kp 10.211.55.200:8

配置keepalived

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
$ yum install keepalived libnl3-devel ipset-devel -y
#### node-1
! Configuration File for keepalived

global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id RGW #
vrrp_skip_check_adv_addr
#vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_script chk_haproxy { #健康检查脚本,检测到异常时,权重降低2
script "killall -0 haproxy"
interval 2 #检测间隔
weight -2
}
vrrp_instance RGW {
state MASTER #master角色
interface eth0
virtual_router_id 51
priority 100 #权重100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
10.211.55.200/24 #VIP地址
}
track_script {
chk_haproxy
}
}


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
#### node-2
! Configuration File for keepalived

global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id RGW #
vrrp_skip_check_adv_addr
#vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_script chk_haproxy { #健康检查脚本
script "killall -0 haproxy"
interval 2
weight -2
}
vrrp_instance RGW {
state BACKUP #BACKUP角色
interface eth0
virtual_router_id 51
priority 99 #权重99
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
10.211.55.200/24 #VIP地址
}
track_script {
chk_haproxy
}
}


配置haproxy

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
global

log 127.0.0.1 local2

chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
user haproxy
group haproxy
daemon

# turn on stats unix socket
stats socket /var/lib/haproxy/stats

defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000

frontend http_web *:80
mode http
default_backend rgw

backend rgw
balance roundrobin
mode http
server node-1 10.211.55.201:7480 check
server ndoe-2 10.211.55.202:7480 check

修改客户端指向

s3

1
2
3
4
5
6
7
8
9
10
11
12
$ vim ~/.s3cfg
host_base = 10.211.55.200:80
host_bucket = 10.211.55.200:80/%(bucket)s
$ s3cmd ls
2020-10-30 12:49 s3://ceph-s3-test
2020-10-30 12:48 s3://my-new-bucket
2020-10-30 13:50 s3://swift-demo
$ s3cmd mb s3://test-1
Bucket 's3://test-1/' created
$ s3cmd put test s3://test-1/
upload: 'test' -> 's3://test-1/test' [1 of 1]
61 of 61 100% in 0s 2.00 KB/s done

swift

1
2
3
4
5
6
#修改环境变量/etc/profile
$ swift list
ceph-s3-test
my-new-bucket
swift-demo
test-1

CEPH集群测试

mon

模式为选举 最多挂n/2-1

1
2
##配置文件
mon_host = 10.211.55.201,10.211.55.202,10.211.55.203

mds

模式为一主多备,确保集群中至少有1个

RGW

ha+kp高可用

OSD坏盘

对象为3副本,最多挂2个节点

fio性能压测评估

4K随机写-IOPS

1
2
3
4
5
6
7
8
$ fio -filename=/media/fio.img<文件名> -direct=1 \
-iodepth 32<深度对应numjobs并发,每个并发队列深度为32> \
-thread -rw=randwrite<类型为随机写> -ioengine=libaio<引擎> \
-bs=4k<块大小> -size=200m -numjobs=8<并发,对应cpu核数> \
-runtime=60 -group_reporting -name=mytest
$ yum install sysstat -y
$ watch -n 0.5 iostat -x #磁盘io信息
$ ceph osd perf #osd延迟

虚拟机稀烂的数据

image-20201114215425196

4K随机读-IOPS

1
$ fio -filename=/media/fio.img -direct=1 -iodepth 32 -thread -rw=randread -ioengine=libaio -bs=4k -size=200m -numjobs=8 -runtime=60 -group_reporting -name=mytest

image-20201114221925729

4K随机读写-IOPS r70% w30%

1
$ fio -filename=/media/fio.img -direct=1 -iodepth 32 -thread -rw=randrw -rwmixread=70 -ioengine=libaio -bs=4k -size=200m -numjobs=8 -runtime=60 -group_reporting -name=mytest

1M顺序写-吞吐

1
$ fio -filename=/media/fio.img -direct=1 -iodepth 32 -thread -rw=write  -ioengine=libaio -bs=1m -size=200m -numjobs=8 -runtime=60 -group_reporting -name=mytest

RBD Bench压力测试

1
2
3
4
$ rbd help bench 
$ rbd bench ceph-demo/rbd-tst.img --io-size 4K --io-threads 16 --io-total
...
elapsed: 49 ops: 51200 ops/sec: 1040.25 bytes/sec: 4260872.35

CEPH与K8s集成

官方文档https://v1-18.docs.kubernetes.io/docs/concepts/storage/volumes/

Ceph与volumes集成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 下载并安装sealos, sealos是个golang的二进制工具,直接下载拷贝到bin目录即可, release页面也可下载
$ wget -c https://sealyun.oss-cn-beijing.aliyuncs.com/latest/sealos && \
chmod +x sealos && mv sealos /usr/bin

# 下载离线资源包
$ wget -c https://sealyun.oss-cn-beijing.aliyuncs.com/7b6af025d4884fdd5cd51a674994359c-1.18.0/kube1.18.0.tar.gz

# 安装一个kubernetes单节点
sealos init --passwd '123456' \
--master 10.211.55.10 --node 10.211.55.10 \
--pkg-url /root/kube1.18.0.tar.gz \
--version v1.18.0

yum -y install ceph-common #在k8s节点安装包

准备工作

1、创建pool和用户

1
[root@node-1 ~]# ceph osd pool create kubernetes 8 8 

2、创建认证用户

1
2
3
[root@node-1 ~]# ceph auth get-or-create client.kubernetes mon 'profile rbd' osd 'profile rbd pool=kubernetes'
[client.kubernetes]
key = AQD/6LBfg19MIhAA4UGpvND9amAsVjJtsDfvtQ==

3、创建secrets对象存储将Ceph的认证key存储在Secrets中

获取步骤2生成的key,并将其加密为base64格式

1
2
[root@node-1 ~]# echo AQD/6LBfg19MIhAA4UGpvND9amAsVjJtsDfvtQ== | base64 
QVFELzZMQmZnMTlNSWhBQTRVR3B2TkQ5YW1Bc1ZqSnRzRGZ2dFE9PQo=

创建定义secrets对象

1
2
3
4
5
6
7
apiVersion: v1
kind: Secret
metadata:
name: ceph-secret
type: "kubernetes.io/rbd"
data:
key: QVFELzZMQmZnMTlNSWhBQTRVR3B2TkQ5YW1Bc1ZqSnRzRGZ2dFE9PQo=

生成secrets

1
2
3
4
5
6
7
[root@node-1 volumes]# kubectl apply -f secret.yaml 
secret/ceph-secret created

[root@node-1 volumes]# kubectl get secret
NAME TYPE DATA AGE
ceph-secret kubernetes.io/rbd 1 10s
default-token-hn65d kubernetes.io/service-account-token 3 41d

容器中调用RBD volumes

1、创建rbd块

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@node-1 ~]# rbd create -p kubernetes --image-feature layering rbd.img --size 10G

[root@node-1 ~]# rbd info kubernetes/rbd.img
rbd image 'rbd.img':
size 10 GiB in 2560 objects
order 22 (4 MiB objects)
id: 519576b8b4567
block_name_prefix: rbd_data.519576b8b4567
format: 2
features: layering
op_features:
flags:
create_timestamp: Mon Apr 20 23:27:02 2020

2、pod中引用RBD volumes

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@node-1 volumes]# cat pods.yaml 
apiVersion: v1
kind: Pod
metadata:
name: volume-rbd-demo
spec:
containers:
- name: pod-with-rbd
image: nginx:1.7.9
imagePullPolicy: IfNotPresent
ports:
- name: www
containerPort: 80
protocol: TCP
volumeMounts:
- name: rbd-demo
mountPath: /data
volumes:
- name: rbd-demo
rbd:
monitors:
- 10.211.55.201:6789
- 10.211.55.202:6789
- 10.211.55.203:6789
pool: kubernetes
image: rbd.img
fsType: ext4
user: kubernetes
secretRef:
name: ceph-secret

测试验证

1、生成pod

1
2
3
4
5
6
[root@node-1 volumes]# kubectl apply -f pods.yaml 
pod/volume-rbd-demo configured
[root@node-1 volumes]# kubectl get pods
NAME READY STATUS RESTARTS AGE
demo-8ffbcf7c5-r2wzf 1/1 Running 1 21h
volume-rbd-demo 1/1 Running 0 43m

2、查看挂载的情况,可以看到RBD块存储挂载至data目录

1
2
3
4
5
6
7
[root@node-1 volumes]# kubectl exec -it volume-rbd-demo -- df -h
Filesystem Size Used Avail Use% Mounted on
rootfs 50G 6.7G 41G 15% /
overlay 50G 6.7G 41G 15% /
tmpfs 64M 0 64M 0% /dev
tmpfs 920M 0 920M 0% /sys/fs/cgroup
/dev/rbd0 9.8G 37M 9.7G 1% /data

Ceph与PV/PVC集成

准备工作

参考步骤一,创建好pool,镜像,用户认证,secrets

定义PV和PVC

1、PV定义,定义一块存储,抽象化为PV

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ rbd create -p kubernetes --image-feature layering demo-1.img --size 10G
[root@node-1 pv_and_pvc]# cat pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: rbd-demo
spec:
accessModes:
- ReadWriteOnce
capacity:
storage: 10G
rbd:
monitors:
- 10.211.55.201:6789
- 10.211.55.202:6789
- 10.211.55.203:6789
pool: kubernetes
image: demo-1.img
fsType: ext4
user: kubernetes
secretRef:
name: ceph-secret
persistentVolumeReclaimPolicy: Retain
storageClassName: rbd

2、PVC定义,引用PV

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@node-1 pv_and_pvc]# cat pvc.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-demo
spec:
accessModes:
- ReadWriteOnce
volumeName: rbd-demo
resources:
requests:
storage: 10G
storageClassName: rbd

3、生成PV和PVC

1
2
3
4
5
6
7
8
9
10
11
12
[root@node-1 pv_and_pvc]# kubectl apply -f pv.yaml 
persistentvolume/rbd-demo created

[root@node-1 pv_and_pvc]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
rbd-demo 10G RWO Retain Available rbd 9s

[root@node-1 pv_and_pvc]# kubectl apply -f pvc.yaml
persistentvolumeclaim/pvc-demo created
[root@node-1 pv_and_pvc]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pvc-demo Pending rbd-demo 0 rbd 2s

Pod中引用PVC

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@node-1 pv_and_pvc]# cat pod-demo.yaml 
apiVersion: v1
kind: Pod
metadata:
name: pod-demo
spec:
containers:
- name: demo
image: nginx:1.7.9
imagePullPolicy: IfNotPresent
ports:
- name: www
protocol: TCP
containerPort: 80
volumeMounts:
- name: rbd
mountPath: /data
volumes:
- name: rbd
persistentVolumeClaim:
claimName: pvc-demo

文档:

Ceph与StorageClass集成

初始化

创建所需的ServiceAccount和RBAC ClusterRole / ClusterRoleBinding Kubernetes对象。这些对象不一定需要针对您的Kubernetes环境进行自定义,因此可以从 ceph -csi部署YAML中按原样使用:

1
2
3
4
5
6
7
8
9
10
wget https://raw.githubusercontent.com/ceph/ceph-csi/master/deploy/rbd/kubernetes/csi-provisioner-rbac.yaml
wget https://raw.githubusercontent.com/ceph/ceph-csi/master/deploy/rbd/kubernetes/csi-nodeplugin-rbac.yaml
wget https://raw.githubusercontent.com/ceph/ceph-csi/master/deploy/rbd/kubernetes/csi-rbdplugin-provisioner.yaml
wget https://raw.githubusercontent.com/ceph/ceph-csi/master/deploy/rbd/kubernetes/csi-rbdplugin.yaml


kubectl apply -f csi-provisioner-rbac.yaml
kubectl apply -f csi-nodeplugin-rbac.yaml
kubectl apply -f csi-rbdplugin-provisioner.yaml
kubectl apply -f csi-rbdplugin.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
---
apiVersion: v1
kind: ConfigMap
data:
config.json: |-
[
{
"clusterID": "a96a9084-601e-46ca-a8b1-cf6b1ab5edf1",
"monitors": [
"10.211.55.201:6789",
"10.211.55.202:6789",
"10.211.55.203:6789"
]
}
]
metadata:
name: ceph-csi-config
1
2
3
4
5
6
7
8
9
---
apiVersion: v1
kind: Secret
metadata:
name: csi-rbd-secret
namespace: default
stringData:
userID: kubernetes
userKey: QVFELzZMQmZnMTlNSWhBQTRVR3B2TkQ5YW1Bc1ZqSnRzRGZ2dFE9PQo=

创建sc

1
2
官网少个configmap报错
https://github.com/ceph/ceph-csi/blob/master/examples/kms/vault/kms-config.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
cat <<EOF > csi-rbd-sc.yaml
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: csi-rbd-sc
provisioner: rbd.csi.ceph.com
parameters:
clusterID: a96a9084-601e-46ca-a8b1-cf6b1ab5edf1
pool: kubernetes
csi.storage.k8s.io/provisioner-secret-name: csi-rbd-secret
csi.storage.k8s.io/provisioner-secret-namespace: default
csi.storage.k8s.io/node-stage-secret-name: csi-rbd-secret
csi.storage.k8s.io/node-stage-secret-namespace: default
imageFeatures: layering #定义特性
reclaimPolicy: Delete
mountOptions:
- discard
EOF
$ kubectl apply -f csi-rbd-sc.yaml

创建pvc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
cat <<EOF > raw-block-pvc.yaml
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: raw-block-pvc
spec:
accessModes:
- ReadWriteOnce
volumeMode: Block
resources:
requests:
storage: 1Gi
storageClassName: csi-rbd-sc
EOF
$ kubectl apply -f raw-block-pvc.yaml

创建pvc后申请pv出错,权限不足

修改为admin权限后重新创建

1
ceph auth list

image-20201115210128101

容器调用StorageClass

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
---
apiVersion: v1
kind: Pod
metadata:
name: csi-rbd-demo-pod
spec:
containers:
- name: web-server
image: nginx
volumeMounts:
- name: mypvc
mountPath: /var/lib/www/html
volumes:
- name: mypvc
persistentVolumeClaim:
claimName: rbd-pvc
readOnly: false
EOF
$ kubectl apply -f pod.yaml
  • 如果没有升级内核会报错

  • 可根据提示关闭rbd特性

  • 或者修改ceph配置

    1
    2
    3
    4
    5
    $ ceph --admin-daemon /var/run/ceph/ceph-mon.node-1.asok config show | grep features
    "enable_experimental_unrecoverable_data_corrupting_features": "",
    "mon_debug_no_initial_persistent_features": "false",
    "rbd_default_features": "61",
    将rbd_default_features改为1 ##好像没用,要在sc里修改,生效需删除重建

Ceph与KVM集成

CEPH与OpenStack集成

环境准备

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
我们安装的是all-in-one环境的openstack,测试机IP:192.168.1.10
[root@openstack ~]# cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core)
内存:4G 硬盘:80G CPU:4核

1)、[root@openstack ~]# vim /etc/environment
LANG=en_US.utf-8
LC_ALL=en_US.utf-8

2)、禁用firewalld、NetworkManager
[root@openstack ~]# systemctl stop firewalld && systemctl disable firewalld
[root@openstack ~]# systemctl stop NetworkManager && systemctl disable NetworkManager
3)、关闭selinux
[root@openstack ~]# vim /etc/selinux/config SELINUX=disabled
[root@openstack ~]# setenforce 0
[root@openstack ~]# getenforce Permissive
4)、 添加软件源和repo源,这里我添加的是阿里云的源,你也可以用其他的
[root@openstack ~]# yum install -y net-tools wget
[root@openstack ~]#curl -o /etc/yum.repos.d/Centos-7.repo http://mirrors.aliyun.com/repo/Centos-7.repo
[root@openstack ~]#curl -o /etc/yum.repos.d/epel-7.repo http://mirrors.aliyun.com/repo/epel-7.repo
[root@openstack ~]#cat > /etc/yum.repos.d/openstack-train.repo << EOF
[train]
name=openstack train
baseurl=https://mirrors.aliyun.com/centos/7/cloud/x86_64/openstack-train/
enabled=1
gpgcheck=0
EOF
yum clean all && yum makecache

centos7.8回退leatherman版本

1
yum downgrade leatherman

2、安装pakcstack

1
2
3
4
5
6
[root@openstack ~]# yum install -y openstack-packstack python-pip centos-release-openstack-train
在家目录下生成answer文件
[root@openstack ~]# packstack --gen-answer-file=answer-file-fbo.conf
[root@openstack ~]# packstack --answer-file=./answer-file-fbo.conf

或者 packstack --allinone

Ceph管理与监控

Dashboard安装

1
2
3
4
5
$ yum install ceph-mgr-dashboard
#在正在运行的Ceph集群中,可以通过以下方式启用Ceph仪表板:
$ ceph mgr module enable dashboard #无法开启
$ ceph mgr module ls
$ ceph mgr module enable dashboard --force #强制开启

SSL / TLS支持

1
ceph dashboard create-self-signed-cert

仪表板绑定到TCP / IP地址和TCP端口。

1
2
3
4
5
6
ceph config set mgr mgr/dashboard/server_addr 10.211.55.201
ceph config set mgr mgr/dashboard/server_port 8080
ceph config set mgr mgr/dashboard/ssl_server_port 8443
ceph mgr servicesdashboard
#创建用户
ceph dashboard ac-user-create admin admin123 administrator

启用Prometheus模块

0%