文章目录
- [第 6 章 Ceph 分布式存储 块存储管理](#第 6 章 Ceph 分布式存储 块存储管理)
-
- [管理 RADOS 块设备](#管理 RADOS 块设备)
-
- [RADOS 块设备](#RADOS 块设备)
- [创建 RBD 镜像](#创建 RBD 镜像)
- [访问 RADOS 块设备存储](#访问 RADOS 块设备存储)
-
- [使用内核RBD(KRBD)访问 Ceph 块存储](#使用内核RBD(KRBD)访问 Ceph 块存储)
-
- [映射 RBD 镜像](#映射 RBD 镜像)
- [持久映射 RBD 镜像](#持久映射 RBD 镜像)
- [使用 librbd 库访问 Ceph 块存储-配合虚拟化,不过多讲解](#使用 librbd 库访问 Ceph 块存储-配合虚拟化,不过多讲解)
-
- [使用 librbd 库访问 Ceph 块存储](#使用 librbd 库访问 Ceph 块存储)
- [RBD 缓存](#RBD 缓存)
- [RBD 缓存模式](#RBD 缓存模式)
- [RBD 缓存参数](#RBD 缓存参数)
- [RBD 镜像格式](#RBD 镜像格式)
-
- [RBD 镜像布局](#RBD 镜像布局)
- [RBD 镜像阶数](#RBD 镜像阶数)
- [RBD 镜像格式](#RBD 镜像格式)
- [使用 rbd 命令管理镜像](#使用 rbd 命令管理镜像)
- [管理 RADOS 块设备快照](#管理 RADOS 块设备快照)
-
- [RBD 镜像功能](#RBD 镜像功能)
- [RBD 快照](#RBD 快照)
- [RBD 克隆](#RBD 克隆)
- 挂载克隆镜像
- [导入和导出 RBD 镜像](#导入和导出 RBD 镜像)
-
- [导入和导出 RBD 镜像](#导入和导出 RBD 镜像)
-
- [导出 RBD 镜像](#导出 RBD 镜像)
- [导入 RBD 镜像](#导入 RBD 镜像)
- 管道导出和导入进程
- [导出和导入 RBD 镜像更改-不做,使用机会不大](#导出和导入 RBD 镜像更改-不做,使用机会不大)
-
- [导出 RBD 镜像更改](#导出 RBD 镜像更改)
- [比较 RBD 镜像更改](#比较 RBD 镜像更改)
- [导入 RBD 镜像更改](#导入 RBD 镜像更改)
- [配置 RBD Mirrors](#配置 RBD Mirrors)
- [第 7 章 Ceph 分布式存储 对象存储管理](#第 7 章 Ceph 分布式存储 对象存储管理)
-
- 对象存储介绍
- [RADOS 网关介绍](#RADOS 网关介绍)
-
- [RADOS 网关简介](#RADOS 网关简介)
- [RADOS 网关架构](#RADOS 网关架构)
- [RADOS 网关用例](#RADOS 网关用例)
- [RADOS 网关部署](#RADOS 网关部署)
-
- 创建对象存储域
- [RADOS 网关部署](#RADOS 网关部署)
-
- [RADOS 网关部署-命令行](#RADOS 网关部署-命令行)
- [# RADOS 网关部署-服务文件#跳过](# RADOS 网关部署-服务文件#跳过)
-
- [#RADOS 网关-部署](#RADOS 网关-部署)
- [#RADOS 网关-实例删除](#RADOS 网关-实例删除)
- [#RADOS 网关-实例添加](#RADOS 网关-实例添加)
- [#RADOS 网关-配置备份](#RADOS 网关-配置备份)
- [#RADOS 网关-配置恢复](#RADOS 网关-配置恢复)
- [#RADOS 网关删除-跳过](#RADOS 网关删除-跳过)
- #删除对象存储域
- 管理对象网关用户
- [使用 Amazon S3 API 访问对象存储](#使用 Amazon S3 API 访问对象存储)
- [使用 Swift API 访问对象存储-跳过](#使用 Swift API 访问对象存储-跳过)
- 管理多站点对象存储网关
- [第 8 章 Ceph 分布式存储 文件系统存储管理](#第 8 章 Ceph 分布式存储 文件系统存储管理)
-
- [介绍 CephFS](#介绍 CephFS)
- [部署 CephFS](#部署 CephFS)
-
- [手动部署 CephFS](#手动部署 CephFS)
-
- [创建 CephFS](#创建 CephFS)
- [删除 CephFS](#删除 CephFS)
- [卷部署 CephFS](#卷部署 CephFS)
-
- [创建 CephFS](#创建 CephFS)
- [删除 CephFS](#删除 CephFS)
- [挂载 CephFS 文件系统](#挂载 CephFS 文件系统)
- [管理 CephFS](#管理 CephFS)
- [管理 CephFS Mirror](#管理 CephFS Mirror)
第 6 章 Ceph 分布式存储 块存储管理
管理 RADOS 块设备
RADOS 块设备
块设备是服务器、笔记本电脑和其他计算系统上最为常见的长期存储设备。**它们以固定大小的块存储数据。**块设备包括基于旋转磁盘的硬盘驱动器,以及基于非易失性存储器的固态驱动器。若要使用存储,用户要使用文件系统格式化块设备,并将它挂载到 Linux 文件系统层次结构中。
Ceph 存储集群的RADOS 块设备 (RBD) 功能 提供虚拟块设备,并以RBD 镜像形式存储在Ceph 存储集群的池中。
创建 RBD 镜像
存储管理员使用 rbd 命令来创建、列出、检索信息、调整大小和删除块设备镜像。
-
创建 rbd 池 。使用 ceph osd pool create 命令来创建用于存储 RBD 镜像池,并使用 rbd pool init 命令进行初始化池。
bash[root@ceph1 ~]# ceph osd pool create images_pool pool 'images_pool' created [root@ceph1 ~]# rbd pool init images_pool #等同于ceph osd pool application enable images_pool rbd [root@ceph1 ~]# ceph osd pool ls detail | grep images_pool #看现象 pool 2 'images_pool' replicated size 3 min_size 2 crush_rule 0 object_hash rjenkins pg_num 32 pgp_num 32 autoscale_mode on last_change 41 flags hashpspool,selfmanaged_snaps stripe_width 0 `application rbd` -
创建专用用户。虽然 Ceph 管理员可以访问这个池,但建议使用受限制的 Cephx 用户访问 rbd 池,仅向该受限用户授予所需 RBD 池的读写权限,而非整个集群的访问权限。
bash[root@ceph1 ~]# ceph auth get-or-create client.rbd mon 'profile rbd' osd 'profile rbd' -o /etc/ceph/ceph.client.rbd.keyring -
创建 RBD 镜像。
bash[root@ceph1 ~]# rbd create images_pool/webapp1 --size 1G # 查看池中镜像清单 [root@ceph1 ~]# rbd ls images_pool webapp1 # 查看池整体情况 [root@ceph1 ~]# rbd pool stats images_pool Total Images: 1 Total Snapshots: 0 Provisioned Size: 1 GiB如果用户不指定池名称,此命令会使用默认的池名称,默认的池名称由 rbd_default_pool 参数指定。使用 ceph config set osd rbd_default_pool value 设置此参数。
访问 RADOS 块设备存储
访问 RADOS 块设备存储方法:
- 使用 KRBD, 客户端 krbd 模块将 RBD 镜像映射为 Linux 块设备。
- 使用 librbd 库,将 RBD 存储提供给 KVM 虚拟机和 OpenStack 云实例。这些客户端使得裸机恢复服务器或虚拟机像普通的块存储一样使用 RBD镜像。在 OpenStack 环境中,OpenStack 将这些 RBD 镜像连接并映射到 Linux 服务器,在那里它们可以充当引导设备。
Ceph 存储将虚拟设块设备使用的实际存储分散在集群中,以利用 IP网络提供高性能访问。
使用内核RBD(KRBD)访问 Ceph 块存储
映射 RBD 镜像
Ceph 客户端可以使用原生 Linux 内核模块 (krbd) 挂载 RBD 镜像。这个模块使用 /dev/rbd0 之类的名称将 RBD 镜像映射到 Linux 块设备。

示例:将 images_pool 池中的 webapp1 镜像映射为client上 /dev/rbd0 设备。
bash
#client上操作:
[root@client ~]# dnf install -y ceph-common
#ceph1上操作:
[root@ceph1 ~]# scp /etc/ceph/ceph.conf /etc/ceph/ceph.client.rbd.keyring root@client:/etc/ceph
# 在客户端 client 上操作
[root@client ~]# rbd --id rbd ls images_pool
webapp1
# 为了简化命令参数,定义CEPH_ARGS环境变量,确保ceph相关命令使用该环境变量提供的默认值。
[root@client ~]# export CEPH_ARGS='--id=rbd'
[root@client ~]# rbd ls images_pool
webapp1
# 使用 krbd 内核模块来映射镜像
[root@client ~]# rbd device map images_pool/webapp1 #或者使用rbd map images_pool/webapp1映射镜像
/dev/rbd0
[root@client ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 200G 0 disk
├─sda1 8:1 0 1G 0 part /boot
└─sda2 8:2 0 199G 0 part
├─cs-root 253:0 0 70G 0 lvm /
├─cs-swap 253:1 0 3.9G 0 lvm [SWAP]
└─cs-home 253:2 0 125.1G 0 lvm /home
sr0 11:0 1 12.8G 0 rom
rbd0 252:0 0 1G 0 disk #多了个rbd0设备
Ceph 客户端系统可以像其他块设备一样使用映射的块设备,例如使用文件系统进行格式化、挂载和卸载。
bash
# 列出计算机中映射的 RBD 镜像
[root@client ~]# rbd showmapped
id pool namespace image snap device
0 images_pool webapp1 - /dev/rbd0
# 或者
[root@client ~]# rbd device list #等于rbd device ls
id pool namespace image snap device
0 images_pool webapp1 - /dev/rbd0
# 格式化和挂载
[root@client ~]# lsblk /dev/rbd0
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
rbd0 252:0 0 1G 0 disk
[root@client ~]# mkfs.xfs /dev/rbd0
[root@client ~]# mkdir -p /webapp/webapp1
[root@client ~]# mount /dev/rbd0 /webapp/webapp1/
[root@client ~]# lsblk /dev/rbd0
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
rbd0 252:0 0 1G 0 disk /webapp/webapp1 #已经挂载
[root@client ~]# echo Hello World > /webapp/webapp1/index.html
[root@client ~]# cat /webapp/webapp1/index.html
Hello World
[root@client ~]# df /webapp/webapp1/
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/rbd0 1038336 40504 997832 4% /webapp/webapp1
[root@client ~]# rbd status images_pool/webapp1 #看看谁在用
Watchers:
watcher=192.168.108.10:0/1267779106 client.44650 cookie=18446462598732840961
取消映射 RBD 镜像,使用以下命令:
bash
# 先卸载改设备
[root@client ~]# umount /webapp/webapp1
# 取消映射
[root@client ~]# rbd unmap /dev/rbd0 # rbd unmap images_pool/webapp1也可以
# 或者
[root@client ~]# rbd device unmap /dev/rbd0
[root@client ~]# rbd device ls #查看现象
注意:rbd map 和 rbd unmap 命令需要 root 特权。
**==注意:==两个客户端可以同时将同一个 RBD 镜像映射为块设备。**但如果块设备含有普通的单挂载文件系统,则建议每次将数据块设备连接到一个客户端。如果将含有普通文件系统的 RADOS 块设备同时挂载到两个或多个客户端上,可能会造成文件系统损坏和数据丢失。
持久映射 RBD 镜像
**rbdmap 服务可在系统启动自动映射 RBD 镜像到系统。**此服务在 /etc/ceph/rbdmap 文件中查找已映射的镜像及其凭据。当 系统识别到 RBD 镜像时,读取 /etc/fstab 文件中记录,并挂载镜像。
下列步骤对 rbdmap 进行配置,以持久映射已包含文件系统的 RBD 镜像:
-
在 /etc/ceph/rbdmap RBD 映射文件内创建一个单行条目。此条目必须指定 RBD 池和镜像的名称。还必须引用 Cephx 用户,该用户具有镜像的读写权限并且具有相应的密钥环文件。确保客户端系统上存在 Cephx 用户的密钥环文件。
bash[root@client ~]# vim /etc/ceph/rbdmap # RbdDevice Parameters #poolname/imagename id=client,keyring=/etc/ceph/ceph.client.keyring images_pool/webapp1 id=rbd,keyring=/etc/ceph/ceph.client.rbd.keyring -
在客户端系统上的 /etc/fstab 文件中为 RBD 创建一个条目。
块设备的名称:/dev/rbd/pool_name/image_name,指定 _netdev 挂载选项,等待 rbdmap 服务映射镜像后,再挂载文件系统。
bash[root@client ~]# vim /etc/fstab ...... /dev/rbd/images_pool/webapp1 /webapp/webapp1 xfs _netdev 0 0 -
确认块设备映射正常工作。使用 rbdmap map 和 rbdmap unmap 命令来挂载和卸载镜像。
-
启用 rbdmap systemd 服务。
bash[root@client ~]# systemctl enable rbdmap.service -
重启系统验证。
bash
[root@client ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 200G 0 disk
├─sda1 8:1 0 1G 0 part /boot
└─sda2 8:2 0 199G 0 part
├─cs-root 253:0 0 70G 0 lvm /
├─cs-swap 253:1 0 3.9G 0 lvm [SWAP]
└─cs-home 253:2 0 125.1G 0 lvm /home
sr0 11:0 1 12.8G 0 rom
rbd0 252:0 0 1G 0 disk /webapp/webapp1 #开机自动挂载
如需更多信息,请参见 rbdmap(8)。
使用 librbd 库访问 Ceph 块存储-配合虚拟化,不过多讲解
使用 librbd 库访问 Ceph 块存储
librbd 库为用户空间应用提供对 RBD 镜像的直接访问。它继承 librados 的功能,将数据块映射到 Ceph 对象存储中的对象,并且实施相关的功能来访问 RBD 镜像和创建快照与克隆。
**OpenStack 和 libvirt 等云和虚拟化解决方案使用 librbd 将 RBD 镜像作为块设备提供给它们管理的云实例和虚拟机。**例如,RBD 镜像可以存储 QEMU 虚拟机镜像。
- 使用 RBD 克隆功能时,虚拟化容器可以在不复制引导镜像的情况下引导虚拟机。
- 使用写时复制 (COW) 机制,在将数据写入到克隆中的未分配对象时,会将数据从父级复制到克隆。
- 使用读时复制 (COR) 机制,在从克隆中的未分配对象读取数据时,会将数据从父级复制到克隆。

RBD 缓存
Ceph 块设备是在用户空间实施(如 librbd),无法利用 Linux 页面缓存。Ceph 块设备会使用Linux系统自己的内存中缓存 ,称为 RBD 缓存。RBD 缓存的行为与 Linux 页面缓存相似。操作系统实施阻碍机制或清空请求时,Ceph 会将所有脏数据写入到 OSD。这意味着,在虚拟机正确发送清空时(例如,Linux 内核 >= 2.6.32),使用回写缓存与使用物理硬盘缓存一样安全。缓存采用"最早使用"(LRU) 算法,而且在回写模式中,它可以联合毗邻的请求来获得更佳的吞吐量。
**RBD 缓存对客户端而言是本地的,因为它使用发起 I/O 请求的计算机上的 RAM。**例如,如果用户的OpenStack 平台安装中有 Nova 计算节点,并且它们将 librbd 用于其虚拟机,则发起 I/O 请求的 OpenStack 客户端会将本地 RAM 用于其 RBD 缓存。
RBD 缓存模式
- 未启用缓存,读取和写入前往 Ceph 对象存储。数据在写入所有相关的 OSD 日志和写入 OSD 设备完成后,Ceph 集群确认写入。
- 回写缓存(write-back) ,需要考量两个值:未清空缓存字节数 U 和最大脏缓存字节数 M。如果 U < M,则此时缓存写入完成即确认写入完成,否则在数据写回到磁盘后确认,直到 U < M 为止。
- 直写缓存(Write-through) ,将最大脏字节数设置为 0,以强制使用直写模式。数据首先写入缓存,然后再写入所有相关的 OSD 日志和写入 OSD 设备完成后,Ceph 集群确认写入。使用直写模式,以最大程度降低服务器故障时数据丢失或文件系统损坏的风险,提供很好的读IO 。
RBD 缓存参数
-
rbd_cache,定义是否启用 RBD 缓存,可用值 true 和 false,默认值true。
-
rbd_cache_policy,定义 RBD 缓存模式,可用值:
- writearound,默认值,写入数据时不经过缓存直接写入后端硬盘。
- writeback,回写。
- writethrough,直写。
-
rbd_cache_size,定义每个 RBD 镜像的缓存大小,以字节为单位。默认值 32 MB。
-
rbd_cache_max_dirty,定义每个 RBD 镜像允许的最大脏字节数。默认值 24 MB。
-
rbd_cache_target_dirty,定义每个 RBD 镜像开始抢先清空的脏字节数。默认值 16 MB。
-
rbd_cache_max_dirty_age,定义清空前的最大页面期限,以秒为单位。默认值 1。
-
rbd_cache_writethrough_until_flush,定义启动直写模式,直至执行第一次清空,可用值 true 和 false,默认值TRUE。
示例:查看并设置以上参数。
bash
[root@ceph1 ~]# ceph config ls | grep rbd_cache
rbd_cache
rbd_cache_policy
rbd_cache_writethrough_until_flush
rbd_cache_size
rbd_cache_max_dirty
rbd_cache_target_dirty
rbd_cache_max_dirty_age
rbd_cache_max_dirty_object
rbd_cache_block_writes_upfront
[root@ceph1 ~]# for arg in $(ceph config ls|grep rbd_cache)
do
echo -n "$arg: "
ceph config get client $arg
done
rbd_cache: true
rbd_cache_policy: writearound
rbd_cache_writethrough_until_flush: true
rbd_cache_size: 33554432
rbd_cache_max_dirty: 25165824
rbd_cache_target_dirty: 16777216
rbd_cache_max_dirty_age: 1.000000
rbd_cache_max_dirty_object: 0
rbd_cache_block_writes_upfront: false
# 设置客户端
[root@ceph1 ~]# ceph config set client rbd_cache_policy writethrough
[root@ceph1 ~]# ceph config get client rbd_cache_policy
writethrough
# 设置全局
[root@ceph1 ~]# ceph config set global rbd_cache_policy writethrough
RBD 镜像格式
RBD 镜像布局
RBD 镜像中的所有对象的名称以各个 RBD 块名称前缀字段中包含的值为开头,可使用rbd info 命令来显示。此前缀后是句点 (.),后跟对象编号。对象编号字段的值是 12 个字符的十六进制数字。
bash
[root@client ~]# rbd info images_pool/webapp1 --id rbd
rbd image 'webapp1':
size 1 GiB in 256 objects
order 22 (4 MiB objects)
snapshot_count: 0
id: acb9415d427f
block_name_prefix: rbd_data.acb9415d427f
format: 2
features: layering, exclusive-lock, object-map, fast-diff, deep-flatten
op_features:
flags:
create_timestamp: Thu Aug 21 21:06:45 2025
access_timestamp: Thu Aug 21 21:06:45 2025
modify_timestamp: Thu Aug 21 21:06:45 2025
Ceph 块设备允许将数据分条存储在Ceph 存储集群中的多个对象存储设备 (OSD) 上。

RBD 镜像阶数
**镜像阶数是用于定义 RBD 镜像的对象大小。**镜像阶数基于 <<(按位左移)C 运算符来定义二进制偏移值。此运算符按照右侧运算对象来偏移左侧运算对象。
例如,1 << 2 = 4。十进制 1 在二进制中是 1,因此 1 << 2 = 4 运算的结果是二进制的 100,也就是十进制的 4。
镜像阶数的值必须在12 到 25 之间,其中 12 = 4 KiB,13 = 8 KiB,以此类推。例如,镜像阶数默认为 22,生成 4 MiB 对象。用户可使用 rbd create 命令的 --order 选项来覆盖默认值。
**用户也可通过 --object-size 选项指定对象的大小。**此参数必须指定介于 4096 字节 (4 KiB) 和33,554,432 字节 (32 MiB) 之间的对象大小,以字节、K 或 M 表示(例如,4096、8 K 或 4 M)。
bash
[root@client ~]# rbd help create
usage: rbd create [--pool <pool>] [--namespace <namespace>] [--image <image>]
[--image-format <image-format>] [--new-format]
[--order <order>] [--object-size <object-size>]
[--image-feature <image-feature>] [--image-shared]
[--stripe-unit <stripe-unit>]
[--stripe-count <stripe-count>] [--data-pool <data-pool>]
[--mirror-image-mode <mirror-image-mode>]
[--journal-splay-width <journal-splay-width>]
[--journal-object-size <journal-object-size>]
[--journal-pool <journal-pool>]
[--thick-provision] --size <size> [--no-progress]
<image-spec>
Create an empty image.
Positional arguments
<image-spec> image specification
(example: [<pool-name>/[<namespace>/]]<image-name>)
......
RBD 镜像格式
与每个 RBD 镜像关联的参数有三个:
- image_format,RBD 镜像格式版本。默认值为 2,即最新的版本。版本 1 已弃用,而且不支持克隆和镜像等功能。
- stripe_unit,一个对象中存储的连续字节数(默认为 object_size)。
- stripe_count,一个条带跨越的 RBD 镜像对象数量(默认为 1)。
对于 RBD 格式 2 镜像,用户可以更改以上各个参数的值。设置必须与下列等式一致:
stripe_unit * stripe_count = object_size
例如: stripe_unit = 1048576, stripe_count = 8 for default 8 MiB objects
bash
[root@client ~]# rbd create --stripe-unit=1M --stripe-count=8 --size 1G images_pool/webapp2 --id rbd
[root@client ~]# rbd info images_pool/webapp2 --id rbd
rbd image 'webapp2':
size 1 GiB in 256 objects
order 22 (4 MiB objects)
snapshot_count: 0
id: ada41793809a
block_name_prefix: rbd_data.ada41793809a
format: 2
features: layering, striping, exclusive-lock, object-map, fast-diff, deep-flatten
op_features:
flags:
create_timestamp: Thu Aug 21 23:07:26 2025
access_timestamp: Thu Aug 21 23:07:26 2025
modify_timestamp: Thu Aug 21 23:07:26 2025
stripe unit: 1 MiB
stripe count: 8
使用 rbd 命令管理镜像
status
用于查看哪些客户端在使用该镜像。
bash
[root@client ~]# rbd status images_pool/webapp1 --id rbd
Watchers:
watcher=192.168.108.10:0/2614504094 client.44320 cookie=18446462598732840961
[root@client ~]# rbd status images_pool/webapp2 --id rbd
Watchers: none
du
用于查看镜像大小使用情况。
bash
[root@client ~]# rbd du images_pool/webapp1 --id rbd
NAME PROVISIONED USED
webapp1 1 GiB 36 MiB
resize
用于扩展和缩减镜像。
bash
# 扩展未在使用的镜像
[root@client ~]# rbd resize images_pool/webapp2 --size 2G --id rbd
Resizing image: 100% complete...done.
[root@client ~]# rbd du images_pool/webapp2
NAME PROVISIONED USED
webapp2 2 GiB 0 B
# 扩展正在使用的镜像
[root@client ~]# rbd resize images_pool/webapp1 --size 2G --id rbd
Resizing image: 100% complete...done.
[root@client ~]# lsblk /dev/rbd0
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
rbd0 252:0 0 2G 0 disk /webapp/webapp1
[root@client ~]# df -h /dev/rbd0
Filesystem Size Used Avail Use% Mounted on
/dev/rbd0 1014M 40M 975M 4% /webapp/webapp1
[root@client ~]# xfs_growfs /webapp/webapp1/
[root@client ~]# df -h /webapp/webapp1/
Filesystem Size Used Avail Use% Mounted on
/dev/rbd0 2.0G 48M 2.0G 3% /webapp/webapp1
# 缩减镜像
[root@client ~]# rbd resize images_pool/webapp2 --size 1G --id rbd
rbd: shrinking an image is only allowed with the --allow-shrink flag
[root@client ~]# rbd resize images_pool/webapp2 --size 1G --allow-shrink --id rbd
Resizing image: 100% complete...done.
[root@client ~]# rbd du images_pool/webapp2 --id rbd
NAME PROVISIONED USED
webapp2 1 GiB 0 B
# 缩减正在使用的镜像(xfs文件系统不支持缩减)
rename 和 mv
用于重命名镜像,该操作不支持跨池。
bash
# 创建新池
[root@ceph1 ~]# ceph osd pool create images_pool_2 32 32
pool 'images_pool_2' created
[root@ceph1 ~]# rbd pool init images_pool_2
# 重命名
[root@ceph1 ~]# rbd rename images_pool/webapp2 images_pool/webapp02
[root@ceph1 ~]# rbd ls images_pool
webapp02
webapp1
[root@ceph1 ~]# rbd mv images_pool/webapp02 images_pool/webapp2
[root@ceph1 ~]# rbd ls images_pool
webapp1
webapp2
# 跨池重命名
[root@ceph1 ~]# rbd rename images_pool/webapp2 images_pool_2/webapp02
rbd: mv/rename across pools not supported #不支持
source pool: images_pool dest pool: images_pool_2
cp
用于复制镜像。
bash
#实验前观察
[root@client ~]# ceph osd lspools
1 device_health_metrics
2 images_pool
3 images_pool_2
[root@client ~]#
[root@client ~]# rbd ls images_pool
webapp1
webapp2
[root@client ~]# rbd ls images_pool_2
[root@ceph1 ~]# rbd cp images_pool/webapp2 images_pool_2/webapp2 #打这条命令之前可以先rbd ls -p images_pool_2查看下
Image copy: 100% complete...done.
[root@ceph1 ~]# rbd ls -p images_pool
webapp1
webapp2
[root@ceph1 ~]# rbd ls -p images_pool_2
webapp2 #原来images_pool_2是没有image的,通过copy产生
trash
使用垃圾箱管理镜像。
bash
# 将镜像放入垃圾箱
[root@ceph1 ~]# rbd ls images_pool #先查看下images_pool
webapp1
webapp2
[root@ceph1 ~]# rbd trash mv images_pool/webapp2
[root@ceph1 ~]# rbd ls images_pool #再验证
webapp1
[root@ceph1 ~]# rbd trash ls images_pool
ada41793809a webapp2
# 恢复垃圾箱中镜像,必须使用id
[root@ceph1 ~]# rbd trash restore -p images_pool ada41793809a
[root@ceph1 ~]# rbd ls images_pool
webapp1
webapp2
[root@client ~]# rbd trash ls images_pool
# 删除垃圾箱中镜像
[root@ceph1 ~]# rbd trash mv images_pool/webapp2
[root@ceph1 ~]# rbd trash ls images_pool
ada41793809a webapp2
[root@ceph1 ~]# rbd trash rm -p images_pool ada41793809a #将回收站中的webapp2删除
Removing image: 100% complete...done.
[root@ceph1 ~]# rbd trash ls images_pool
[root@ceph1 ~]# rbd ls images_pool
webapp1
rm
用于删除镜像。
bash
[root@ceph1 ~]# rbd rm images_pool_2/webapp2
Removing image: 100% complete...done.
[root@ceph1 ~]# rbd ls images_pool_2
管理 RADOS 块设备快照
RBD 镜像功能
使用 格式 2 的RBD 镜像支持若干可选功能:
- layering,镜像分层功能,该功能支持快照和克隆。
- striping,提高性能的分条 v2 功能,由 librbd 提供支持。
- exclusive-lock,独占锁定功能。
- object-map,对象映射功能(依赖 exclusive-lock)。
- fast-diff,快速 diff 命令功能(依赖 object-map 和 exclusive-lock)。
- deep-flatten,扁平化 RBD 镜像的所有快照。
- journaling,日志功能(依赖 exclusive-lock)。
- data-pool,EC 数据池功能。
在RBD的features中,源代码定义如下
bash
#define RBD_FEATURE_LAYERING (1ULL<<0)
#define RBD_FEATURE_STRIPINGV2 (1ULL<<1)
#define RBD_FEATURE_EXCLUSIVE_LOCK (1ULL<<2)
#define RBD_FEATURE_OBJECT_MAP (1ULL<<3)
#define RBD_FEATURE_FAST_DIFF (1ULL<<4)
#define RBD_FEATURE_DEEP_FLATTEN (1ULL<<5)
#define RBD_FEATURE_JOURNALING (1ULL<<6)
#define RBD_FEATURE_DATA_POOL (1ULL<<7)
(1ULL<<0) 2^0=1
(1ULL<<1) 2^1=2
(1ULL<<2) 2^2=4
(1ULL<<3) 2^3=8
(1ULL<<4) 2^4=16
(1ULL<<5) 2^5=32
(1ULL<<6) 2^6=64
(1ULL<<7) 2^7=128
集群中 RBD 镜像默认启用功能:
layering, exclusive-lock, object-map, fast-diff, deep-flatten
bash
[root@ceph1 ~]# ceph config get client rbd_default_features
layering,exclusive-lock,object-map,fast-diff,deep-flatten
-
使用命令 ceph config set client rbd_default_features value 命令设置镜像默认功能。
-
/etc/ceph/ceph.conf 的 [client] 中 rbd_default_features 参数定义镜像支持的功能。
-
命令行创建image时候,可以通过 --image-feature feature-name 指定镜像功能。
禁用 object-map 功能
bash
[root@ceph1 ~]# rbd feature disable images_pool/webapp1 object-map
启用 object-map 功能
bash
[root@ceph1 ~]# rbd feature enable images_pool/webapp1 object-map
有些功能是永久性的,不能直接禁用和启用,例如 layering。
bash
[root@ceph1 ~]# rbd feature disable images_pool/webapp1 layering
rbd: failed to update image features: (22) Invalid argument
2025-08-22T17:31:15.602+0800 7ff4768033c0 -1 librbd::Operations: cannot update immutable features
RBD 快照

RBD 快照使用 COW 技术 ,实现最大程度减少维护快照所需的存储空间。在将写入 I/O 请求应用到 RBD 快照镜像前,集群会将原始数据复制到 I/O 操作所影响对象的 PG 中的另一区域。快照在创建时不会占用存储空间,随着所包含对象的变化而增大。RBD 镜像支持增量快照。

快照 COW 技术在对象级别上运行,不受对 RBD 镜像发出的写入 I/O 请求大小的限制。如果用户在有快照的 RBD 镜像中写入一个字节,则 Ceph 会将整个受影响的对象从 RBD 镜像复制到快照区域。

注意: 在拍摄快照前,一定要完成以下任一操作:
- 卸载文件系统。
- 使用 fsfreeze命令冻结文件系统,只允许读操作。
使用 rbd snap create 命令,创建 Ceph 块设备的快照。
bash
# 重新创建一个镜像
[root@client ~]# export CEPH_ARGS='--id=rbd'
[root@client ~]# rbd create images_pool/webapp --size 2G
[root@client ~]# rbd map images_pool/webapp
/dev/rbd1
[root@client ~]# mkfs.xfs /dev/rbd/images_pool/webapp
[root@client ~]# mkdir /webapp/webapp
[root@client ~]# mount /dev/rbd/images_pool/webapp /webapp/webapp
[root@client ~]# echo Hello World > /webapp/webapp/index.html
[root@client ~]# cat /webapp/webapp/index.html
Hello World
# 卸载文件系统
[root@client ~]# umount /webapp/webapp
# 拍摄快照
[root@client ~]# rbd snap create images_pool/webapp@snap1
Creating snap: 100% complete...done.
[root@client ~]# rbd snap ls images_pool/webapp
SNAPID NAME SIZE PROTECTED TIMESTAMP
4 snap1 2 GiB Fri Aug 22 17:52:20 2025
# 挂载文件系统,并写入新数据
[root@client ~]# mount /dev/rbd/images_pool/webapp /webapp/webapp
[root@client ~]# echo Hello laogao > /webapp/webapp/index.html
[root@client ~]# cat /webapp/webapp/index.html
Hello laogao
使用 rbd snap ls 命令,列出块设备快照。
bash
[root@client ~]# rbd snap ls images_pool/webapp
SNAPID NAME SIZE PROTECTED TIMESTAMP
4 snap1 2 GiB Fri Aug 22 17:52:20 2025
RBD 快照是创建于特定时间的 RBD 镜像的只读副本。
重要提示:镜像快照和镜像具有相同的文件系统,同一客户端不允许挂载具有相同UUID的文件系统。
bash
#将/webapp/webapp里的index.html删除,通过挂载/webapp/webapp@snap1找回来
[root@client ~]# rm /webapp/webapp/index.html
# 在挂载快照前,需要卸载原始镜像
[root@client ~]# umount /dev/rbd/images_pool/webapp
[root@client ~]# mkdir /webapp/webapp-snap1
[root@client ~]# rbd map images_pool/webapp@snap1
/dev/rbd2
[root@client ~]# mount /dev/rbd/images_pool/webapp@snap1 /webapp/webapp-snap1
mount: /webapp/webapp1-snap1: WARNING: device write-protected, mounted read-only.
[root@client ~]# cat /webapp/webapp-snap1/index.html #将快照里的文件复制出来,实现数据找回
Hello World
使用 rbd snap rollback 命令,回滚块设备快照,并用快照中的数据覆盖镜像的当前版本。
实践效果,回滚失败。
bash
# 回滚快照失败
[root@client ~]# rbd snap rollback images_pool/webapp@snap1
Rolling back to snapshot: 0% complete...failed.
rbd: rollback failed: (30) Read-only file system
# 后续我们使用克隆实现恢复
使用 rbd snap rm 命令,删除 Ceph 块设备的快照。
bash
[root@client ~]# umount /dev/rbd/images_pool/webapp@snap1
[root@client ~]# rbd unmap images_pool/webapp@snap1
[root@client ~]# rbd snap rm images_pool/webapp@snap1
Removing snap: 100% complete...done.
[root@client ~]# rbd snap ls images_pool/webapp
使用 rbd snap purge 命令,删除镜像所有快照。
bash
u[root@client ~]# rbd snap create images_pool/webapp@snap1
[root@client ~]# rbd snap create images_pool/webapp@snap2
[root@client ~]# rbd snap ls images_pool/webapp
SNAPID NAME SIZE PROTECTED TIMESTAMP
6 snap1 2 GiB Fri Aug 22 18:07:20 2025
7 snap2 2 GiB Fri Aug 22 18:07:22 2025
[root@client ~]# rbd snap purge images_pool/webapp
Removing all snapshots: 100% complete...done.
[root@client ~]# rbd snap ls images_pool/webapp
提示:镜像存在快照时,将无法删除 RBD 镜像。
RBD 克隆
RBD 克隆是 RBD 镜像的可读写副本,它使用受保护的 RBD 快照克隆。RBD 克隆也可以被扁平化,转换为独立于来源的 RBD 镜像。
克隆过程有三个步骤:
-
创建快照
bash[root@client ~]# rbd snap create images_pool/webapp@snap1 [root@client ~]# rbd snap ls images_pool/webapp SNAPID NAME SIZE PROTECTED TIMESTAMP 10 snap1 2 GiB Fri Aug 22 18:10:18 2025 #看PROTECTED列默认未保护 -
保护快照以免被删除
bash[root@client ~]# rbd snap protect images_pool/webapp@snap1 [root@client ~]# rbd snap ls images_pool/webapp SNAPID NAME SIZE PROTECTED TIMESTAMP 10 snap1 2 GiB yes Fri Aug 22 18:10:18 2025 -
使用受保护的快照创建克隆
bash[root@client ~]# rbd clone images_pool/webapp@snap1 images_pool/webapp-clone-1 [root@client ~]# rbd map images_pool/webapp-clone-1 /dev/rbd3 [root@client ~]# mkdir /webapp/webapp-clone-1 [root@client ~]# umount /webapp/webapp # 挂载clone前确保镜像和快照不要挂载 # 挂载clone前确保镜像和快照不要挂载 [root@client ~]# mount /dev/rbd/images_pool/webapp-clone-1 /webapp/webapp-clone-1 [root@client ~]# df /webapp/webapp-clone-1/ Filesystem 1K-blocks Used Available Use% Mounted on /dev/rbd2 2086912 47864 2039048 3% /webapp/webapp-clone-1新创建的克隆可以像常规 RBD 镜像一样运作,克隆支持 COW 和 COR技术,默认只支持 COW。COW 会将父快照数据复制到克隆中,然后将写入 I/O 请求应用到克隆。
bash[root@ceph1 ~]# ceph config get client rbd_clone_copy_on_read false

RBD 克隆未启用 COR 功能时,父 RBD 快照和克隆相同的数据会直接从父快照读取。相对于客户端而言,父快照的 OSD 具有较高的延迟,这种操作会提高读取的代价。
**如果用户启用了 COR,并且克隆中尚未存在数据,则 Ceph 会在处理读取 I/O 请求前先从父快照复制数据到克隆。**通过为客户端或全局设置运行 ceph config set client rbd_clone_copy_on_read true 命令或 ceph ceph config set global rbd_clone_copy_on_read true 命令来激活 COR 功能。原始数据不会被覆盖。
bash
# ceph config set client rbd_clone_copy_on_read true
# ceph config get client rbd_clone_copy_on_read
true
如果不对 RBD 克隆启用 COR,则克隆无法满足的每个读取操作都会对克隆的父级发出 I/O 请求。

克隆 COW 和 COR 步骤在对象级别上运行,不受 I/O 请求大小的限制。要读取或写入 RBD 克隆的单个字节,Ceph 会将整个对象从父镜像或快照复制到克隆。
查看基于特定快照的克隆列表
bash
[root@client ~]# rbd clone images_pool/webapp@snap1 images_pool/webapp-clone-2
[root@client ~]# rbd children images_pool/webapp@snap1
images_pool/webapp-clone-1
images_pool/webapp-clone-2
扁平化克隆,Ceph 会将所有缺失的数据从父级复制到克隆,然后移除对父级的引用。克隆会变成独立的 RBD 镜像,不再是受保护快照的子级。
bash
[root@client ~]# rbd flatten images_pool/webapp-clone-1
Image flatten: 100% complete...done.
[root@client ~]# rbd children images_pool/webapp@snap1
images_pool/webapp-clone-2
挂载克隆镜像
通过镜像快照克隆出来的镜像,具有原镜像相同的文件系统,而同一客户端不允许挂载具有相同UUID的文件系统。怎么处理?
答案:修改文件系统UUID。
假设客户端将克隆出来的镜像映射为/dev/rbd3设备。操作如下:
bash
[root@client ~]# rbd map images_pool/webapp-clone-2
/dev/rbd4
blkid | grep rbd #看UUID
# 生成新的 UUID
[root@client ~]# uuidgen
e0e005e5-c8a0-4102-a266-3964c7069e18
# 修改 ext4 文件系统 UUID
[root@client ~]# tune2fs -U e0e005e5-c8a0-4102-a266-3964c7069e18 /dev/rbd4
# 修改 xfs 文件系统 UUID
[root@client ~]# xfs_admin -U e0e005e5-c8a0-4102-a266-3964c7069e18 /dev/rbd4
Clearing log and setting UUID
writing all SBs
new UUID = e0e005e5-c8a0-4102-a266-3964c7069e18
# 挂载测试
[root@client ~]# mkdir /webapp/webapp-clone-2
[root@client ~]# mount /dev/rbd4 /webapp/webapp-clone-2/
#查看现象
[root@client ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 200G 0 disk
├─sda1 8:1 0 1G 0 part /boot
└─sda2 8:2 0 199G 0 part
├─cs-root 253:0 0 70G 0 lvm /
├─cs-swap 253:1 0 3.9G 0 lvm [SWAP]
└─cs-home 253:2 0 125.1G 0 lvm /home
sr0 11:0 1 12.8G 0 rom
rbd0 252:0 0 2G 0 disk /webapp/webapp1
rbd1 252:16 0 2G 0 disk
rbd2 252:32 0 2G 1 disk
rbd3 252:48 0 2G 0 disk /webapp/webapp-clone-1
rbd4 252:64 0 2G 0 disk /webapp/webapp-clone-2 #挂载上了
[root@client ~]#
导入和导出 RBD 镜像
导入和导出 RBD 镜像
利用 RBD 导出与导入机制,用户可以在同一集群中,也可以使用另一独立集群维护拥有完整功能和可访问性的 RBD 镜像操作副本。
用户可以将这些副本用于各种不同的用例,包括:
- 利用实际的数据卷测试新版本
- 利用实际的数据卷运行质量保障流程
- 实施业务连续性方案
- 将备份进程从生产块设备分离
导出 RBD 镜像
Ceph 存储提供 rbd export 命令来将 RBD 镜像导出到文件。此命令可以将 RBD 镜像或 RBD镜像快照导出到指定的目标文件。
rbd export 命令的语法如下:
rbd export [--export-format {1|2}] (image-spec | snap-spec) [dest-path]
--export-format 选项可指定导出数据的格式,允许用户将较早的 RBD 格式 1 镜像转换为较新的格式 2 镜像。
示例:
bash
[root@ceph1 ~]# rbd export images_pool/webapp webapp.img
Exporting image: 100% complete...done.
导入 RBD 镜像
Ceph 存储提供 rbd import 命令来从文件导入 RBD 镜像。此命令会新建一个镜像,并从指定的源路径导入数据。
rbd import 命令的语法如下:
rbd import [--export-format {1|2}] [--image-format format-id] [--object-size size-in-B/K/M] [--stripe-unit size-in-B/K/M --stripe-count num] [--image-feature feature-name]... [--image-shared] src-path [image-spec]
-
--export-format 选项指定待导入数据的格式,必须确保 rbd export 和 rbd import 命令使用的--export-format 参数值一致。
-
在导入格式 2 的导出数据时,使用 --stripeunit、--stripe-count、--object-size 和 --image-feature 选项可创建新的 RBD 格式 2镜像。
**示例1:**同一集群导入
bash
[root@ceph1 ~]# rbd import webapp.img images_pool/webapp-backup
Importing image: 100% complete...done.
[root@ceph1 ~]# rbd ls images_pool
webapp
webapp-backup
webapp-clone-1
webapp-clone-2
webapp1
[root@ceph1 ~]# rbd info images_pool/webapp-backup
rbd image 'webapp-backup':
size 2 GiB in 512 objects
order 22 (4 MiB objects)
snapshot_count: 0
id: afec7a78062a
block_name_prefix: rbd_data.afec7a78062a
format: 2
features: layering, exclusive-lock, object-map, fast-diff, deep-flatten
op_features:
flags:
create_timestamp: Fri Aug 22 19:18:19 2025
access_timestamp: Fri Aug 22 19:18:19 2025
modify_timestamp: Fri Aug 22 19:18:19 2025
**示例2:**不同集群导入
bash
[root@ceph1 ~]# scp webapp.img root@ceph4:
[root@ceph4 ~]# ceph osd pool create images_pool 32
[root@ceph4 ~]# rbd pool init images_pool
[root@ceph4 ~]# rbd ls images_pool #查看
[root@ceph4 ~]# rbd import webapp.img images_pool/webapp-backup
Importing image: 100% complete...done.
[root@ceph4 ~]# rbd ls images_pool #导入后再查看
webapp-backup
管道导出和导入进程
将短划线 (-) 字符指定为导出操作的目标文件会导致输出转到标准输出 (stdout)。用户还可使用短划线字符 (-) 将 stdout 或标准输入 (stdin) 指定为导出目标或导入来源。
用户可以将这两个命令传送到一个命令中。
bash
# 同一集群导出和导入
[root@ceph1 ~]# rbd export images_pool/webapp - | rbd import - images_pool/webapp-backup2
Exporting image: 100% complete...done.
Importing image: 100% complete...done.
# 不同集群导出和导入
[root@ceph1 ~]# rbd export images_pool/webapp - | ssh root@ceph4 rbd import - images_pool/webapp-backup2
root@ceph4's password: plete...
Exporting image: 100% complete...done.
Importing image: 100% complete...done.
导出和导入 RBD 镜像更改-不做,使用机会不大
RADOS 块设备功能支持导出和导入整个 RBD 镜像,也可以仅导出和导入两个时间点之间的 RBD 镜像变化。
导出 RBD 镜像更改
Ceph 存储提供 rbd export-diff 命令来导出在两个时间点之间对 RBD 镜像的变更。
bash
[root@ceph1 ~]# rbd help export-diff
usage: rbd export-diff [--pool <pool>] [--namespace <namespace>]
[--image <image>] [--snap <snap>] [--path <path>]
[--from-snap <from-snap>] [--whole-object]
[--no-progress]
<source-image-or-snap-spec> <path-name>
......
起始时间可以是:
- RBD 镜像的创建日期和时间,不使用 --from-snap 选项。
- RBD 镜像的快照,通过 --from-snap snapname 选项获取。
也就是:
- 如果不指定快照,命令将导出自 RBD镜像创建之后的所有更改,这与常规的 RBD 镜像导出操作相同。
- 如果用户指定起始点快照,命令将导出用户创建该快照后的更改。
终止时间可以是:
- RBD 镜像的当前内容,如 poolname/imagename。
- RBD 镜像的快照,如 poolname/imagename@snapname。
实验环境:
在这里插入图片描述
环境准备:
bash
[root@ceph1 ~]# ceph osd pool create rbd 32
[root@ceph1 ~]# rbd pool init rbd
[root@ceph1 ~]# rbd create data -s 1G
[root@ceph1 ~]# rbd map data
[root@ceph1 ~]# mkfs.xfs /dev/rbd0
[root@ceph1 ~]# mkdir -p /mnt/data
# 第一次快照内容
[root@ceph1 ~]# mount /dev/rbd0 /mnt/data
[root@ceph1 ~]# echo snap1 > /mnt/data/snap1
[root@ceph1 ~]# umount /mnt/data
[root@ceph1 ~]# rbd snap create data@snap1
# 第二次快照内容
[root@ceph1 ~]# mount /dev/rbd0 /mnt/data
[root@ceph1 ~]# echo snap2 > /mnt/data/snap2
[root@ceph1 ~]# umount /mnt/data
[root@ceph1 ~]# rbd snap create rbd/data@snap2
# 当前内容
[root@ceph1 ~]# mount /dev/rbd0 /mnt/data
[root@ceph1 ~]# echo laogao > /mnt/data/laogao
[root@ceph1 ~]# umount /dev/rbd0
[root@ceph1 ~]# rbd unmap /dev/rbd0
实践部分:
bash
# 导出镜像完整变化
[root@ceph1 ~]# rbd export-diff rbd/data begin-end.data
# 导出创建之初到snap1之间变化
[root@ceph1 ~]# rbd export-diff rbd/data@snap1 begin-snap1.data
# 导出snap1到snap2之间变化
[root@ceph1 ~]# rbd export-diff --from-snap snap1 rbd/data@snap2 snap1-snap2.data
# 导出snap1到当前镜像之间变化
[root@ceph1 ~]# rbd export-diff --from-snap snap1 rbd/data snap1-end.data
比较 RBD 镜像更改
Ceph 存储提供 rbd diff 命令来比较两个时间点之间对 RBD 镜像的变更。
bash
[root@ceph1 ~]# rbd help diff
usage: rbd diff [--pool <pool>] [--namespace <namespace>] [--image <image>]
[--snap <snap>] [--from-snap <from-snap>] [--whole-object]
[--format <format>] [--pretty-format]
<image-or-snap-spec>
Print extents that differ since a previous snap, or image creation.
Positional arguments
<image-or-snap-spec> image or snapshot specification
(example:
[<pool-name>/[<namespace>/]]<image-name>[@<snap-name>])
......
示例:
bash
[root@ceph1 ~]# rbd diff rbd/data@snap1 >diff-s1
[root@ceph1 ~]# rbd diff rbd/data@snap2 >diff-s2
[root@ceph1 ~]# rbd diff rbd/data >diff-all

导入 RBD 镜像更改
Ceph 存储提供 rbd import-diff 命令来导入在两个时间点之间对 RBD 镜像的变更。
bash
[root@ceph1 ~]# rbd help import-diff
usage: rbd import-diff [--path <path>] [--pool <pool>]
[--namespace <namespace>] [--image <image>]
[--sparse-size <sparse-size>] [--no-progress]
<path-name> <image-spec>
......
import-diff 操作执行下列有效性检查:
- 如果export-diff指定了起始快照,在目标镜像必须存在相同快照。
- 如果export-diff指定了结束快照,导出成功后,会创建同样的快照。
示例:
-
导入准备:删除所有快照
bash[root@ceph1 ~]# rbd snap purge data -
导入第一个快照
bash# 导入第一个快照 [root@ceph1 ~]# rbd import-diff begin-snap1.data rbd/data Importing image diff: 100% complete...done. [root@ceph1 ~]# rbd snap ls rbd/data SNAPID NAME SIZE PROTECTED TIMESTAMP 8 snap1 1 GiB Fri Aug 22 20:42:23 2025 # 验证第一个快照中内容 [root@ceph1 ~]# rbd map data@snap1 /dev/rbd0 [root@ceph1 ~]# mount /dev/rbd0 /mnt/data mount: /mnt/data: WARNING: device write-protected, mounted read-only. [root@ceph1 ~]# ls /mnt/data/ snap1 [root@ceph1 ~]# cat /mnt/data/snap1 snap1 [root@ceph1 ~]# umount /mnt/data -
导入第二个快照
bash# 导入第二个快照 [root@ceph1 ~]# rbd import-diff snap1-snap2.data rbd/data Importing image diff: 100% complete...done. [root@ceph1 ~]# rbd snap ls data SNAPID NAME SIZE PROTECTED TIMESTAMP 8 snap1 1 GiB Fri Aug 22 20:42:23 2025 9 snap2 1 GiB Fri Aug 22 20:43:30 2025 # 验证第二个快照中内容 [root@ceph1 ~]# rbd map data@snap2 /dev/rbd1 [root@ceph1 ~]# mount /dev/rbd1 /mnt/data mount: /mnt/data: WARNING: device write-protected, mounted read-only. [root@ceph1 ~]# ls /mnt/data/ snap1 snap2 [root@ceph1 ~]# grep . /mnt/data/* /mnt/data/snap1:snap1 /mnt/data/snap2:snap2 [root@ceph1 ~]# umount /mnt/data -
导入第一个快照到最后内容
bash# 导入第一个快照到最后内容 [root@ceph1 ~]# rbd import-diff snap1-end.data rbd/data Importing image diff: 100% complete...done. [root@ceph1 ~]# rbd snap ls data SNAPID NAME SIZE PROTECTED TIMESTAMP 8 snap1 1 GiB Fri Aug 22 20:42:23 2025 9 snap2 1 GiB Fri Aug 22 20:43:30 2025 # 验证当前内容 [root@ceph1 ~]# rbd map data /dev/rbd2 [root@ceph1 ~]# mount /dev/rbd2 /mnt/data/ [root@ceph1 ~]# ls /mnt/data/ laogao snap1 snap2 [root@ceph1 ~]# grep . /mnt/data/* /mnt/data/laogao:laogao /mnt/data/snap1:snap1 /mnt/data/snap2:snap2 [root@ceph1 ~]# umount /mnt/data
配置 RBD Mirrors
RBD Mirrors 介绍
Ceph 存储支持在两个存储集群之间进行 RBD 镜像同步,将 RBD 镜像从一个Ceph 存储集群自动复制到另一个远程集群。如果包含主要 RBD 镜像的集群变得不可用,则可以从远程集群故障转移到次要 RBD 镜像,并重启使用它的应用。
受支持的镜像配置
RBD 镜像功能支持两种配置:
- 单向镜像(主动-被动),在单向模式中,一个集群的 RBD 镜像可以读写模式访问,远程集群中包含镜像。镜像代理在远程集群上运行。这种模式可以支持配置多个次要集群。

- 双向镜像(主动-主动),在双向模式中,Ceph 使来源与目标对(主要与次要)保持同步。此模式允许在两个集群之间进行复制,用户也必须在每个集群上配置镜像代理。

受支持的镜像模式
RBD 镜像功能支持两种模式:
- 池模式,Ceph 自动为被镜像池中的每一个 RBD 镜像启用镜像功能。当用户在来源集群上的池中创建镜像时,Ceph 会在远程集群中创建次要镜像。
- 镜像模式,Ceph 选择性地为被镜像池中的个别 RBD 镜像启用镜像功能。在这种模式中,用户必须显式选择要在两个集群之间复制的 RBD 镜像。
RBD 镜像的镜像状态
在两个Ceph 存储集群之间异步镜像,通过以下模式实现:
- 基于日志的镜像,此模式通过 RBD 日志镜像功能来确保两个Ceph 存储集群之间的时间点和崩溃一致性复制。对 RBD 镜像的每一次写入首先要记录到相关日志中,然后再修改实际镜像。远程集群从此日志中读取,并将更新内容重播到其镜像的本地副本。
- 基于快照的镜像,基于快照的镜像使用定期调度或手动创建的 RBD 镜像快照,在两个Ceph 存储集群之间复制崩溃一致性 RBD 镜像。远程集群确定两个镜像快照之间的数据或元数据更新,并将增量复制到镜像的本地副本。**RBD fast-diff 镜像功能可快速确定更新的数据块,而无需扫描完整的RBD 镜像。**在故障转移场景中,必须先同步两个快照之间的完整增量,然后才能使用。任何部分应用的增量集都会在故障转移时回滚。
RBD Mirrors 配置
存储管理员可通过在ceph存储集群之间镜像数据镜像来提高冗余度,防止数据丢失,如防范站点故障。
要实现 RBD 镜像功能,必须启用 rbd-mirror 守护进程来发现其对等集群,以及使用专用用户帐户注册对等集群。使用 rbd mirror pool peer bootstrap create 命令来自动执行此过程。
rbd-mirror 守护进程的每个实例都必须同时连接到本地和远程 Ceph 集群。此外,两个数据中心之间的网络必须有足够的带宽来处理镜像工作负载。
RBD Mirrors 过程
rbd-mirror 守护进程不要求源集群和目标集群具有唯一的内部名称;两者都可以而且应当自称为 ceph。rbd mirror pool peer bootstrap 命令会利用 --site-name 选项来描述 rbdmirror 守护进程使用的集群。
下表概述了在 prod 和 backup 两个集群之间配置镜像功能所需的步骤:
-
在 prod 和 backup 两个集群中创建一个同名池。
-
在启用 exclusive-lock 和 journaling 功能的情况下,创建或修改 RBD 镜像。
-
在池上启用池模式镜像功能。
-
在 prod 集群中,引导存储集群对等体并保存引导令牌。
-
部署 rbd-mirror 守护进程。
- 对于单向复制,rbd-mirror 守护进程仅在 backup 集群上运行。
- 对于双向复制,rbd-mirror 守护进程会在两个集群上运行。
单向-池模式-配置
在本例中,用户将看到使用 prod 和 backup 集群配置单向镜像所需的分步说明。
- ceph1 所在集群为 prod 集群
- ceph4 所在集群为 backup 集群
简要配置过程如下:
- 确保双集群状态是
HEALTH_OK。 - 双集群同时创建并初始化池。
- prod 集群创建镜像。
- prod 集群启用池模式镜像功能。
- prod 集群创建引导 token并同步到 backup 集群。
- backup 集群部署 rbd-mirror进程,并使用单向(
rx-only)导入 prod 集群token。 - 验证池和镜像状态。
具体配置过程如下:
-
确保双集群状态是
HEALTH_OK。bash[root@ceph1 ~]# ceph health HEALTH_OK [root@ceph4 ~]# ceph health HEALTH_OK -
双集群同时创建并初始化池。
bash# 主集群 [root@ceph1 ~]# ceph osd pool create rbd 32 32 [root@ceph1 ~]# rbd pool init rbd # 备集群 [root@ceph4 ~]# ceph osd pool create rbd 32 32 [root@ceph4 ~]# rbd pool init rbd -
prod 集群创建镜像。
bash[root@ceph1 ~]# rbd create image1 --size 1024 --pool rbd --image-feature=layering,exclusive-lock,journaling #创建image1并开启特性layering, exclusive-lock, journaling [root@ceph1 ~]# rbd ls image1 [root@ceph1 ~]# rbd info image1 rbd image 'image1': size 1 GiB in 256 objects order 22 (4 MiB objects) snapshot_count: 0 id: acaadb9409a3 block_name_prefix: rbd_data.acaadb9409a3 format: 2 features: layering, exclusive-lock, journaling #layering, exclusive-lock, journaling功能已经开启 op_features: flags: create_timestamp: Fri Aug 22 20:55:23 2025 access_timestamp: Fri Aug 22 20:55:23 2025 modify_timestamp: Fri Aug 22 20:55:23 2025 journal: acaadb9409a3 mirroring state: disabled #mirror没开启 -
prod 集群启用池模式镜像功能。
bash[root@ceph1 ~]# rbd mirror pool enable rbd pool #rbd池开启mirror功能,池级别 [root@ceph1 ~]# rbd info image1 rbd image 'image1': size 1 GiB in 256 objects order 22 (4 MiB objects) snapshot_count: 0 id: acaadb9409a3 block_name_prefix: rbd_data.acaadb9409a3 format: 2 features: layering, exclusive-lock, journaling op_features: flags: create_timestamp: Fri Aug 22 20:55:23 2025 access_timestamp: Fri Aug 22 20:55:23 2025 modify_timestamp: Fri Aug 22 20:55:23 2025 journal: acaadb9409a3 mirroring state: enabled #mirror开启 mirroring mode: journal #镜像模式:日志 mirroring global id: df19e4c3-cdd8-4b9f-89c5-f980d5b46c31 mirroring primary: true #主端 -
prod 集群创建引导token,并同步到 backup 集群。
bash[root@ceph1 ~]# rbd mirror pool peer bootstrap create --site-name prod rbd > bootstrap_token_prod [root@ceph1 ~]# rsync -a bootstrap_token_prod root@ceph4: -
backup 集群部署rbd-mirror进程,并导入prod 集群token。
bash[root@ceph4 ~]# ceph orch apply rbd-mirror --placement=ceph4.laogao.cloud Scheduled rbd-mirror update... [root@ceph4 ~]# ceph orch ls rbd-mirror NAME PORTS RUNNING REFRESHED AGE PLACEMENT rbd-mirror 1/1 54s ago 56s ceph4.laogao.cloud [root@ceph4 ~]# rbd mirror pool peer bootstrap import --site-name backup --direction rx-only rbd bootstrap_token_prod -
验证 backup 集群池和镜像的同步状态。
bash[root@ceph4 ~]# rbd mirror pool info rbd Mode: pool Site Name: backup Peer Sites: UUID: be8faee1-d28c-45dd-95d9-9b37099f4c58 Name: prod Direction: rx-only Client: client.rbd-mirror-peer [root@ceph4 ~]# rbd mirror pool status health: OK daemon health: OK image health: OK images: 1 total 1 replaying [root@ceph4 ~]# rbd ls image1 [root@ceph4 ~]# rbd info image1 rbd image 'image1': size 1 GiB in 256 objects order 22 (4 MiB objects) snapshot_count: 0 id: acc0c87c8d2f block_name_prefix: rbd_data.acc0c87c8d2f format: 2 features: layering, exclusive-lock, journaling op_features: flags: create_timestamp: Fri Aug 22 20:58:56 2025 access_timestamp: Fri Aug 22 20:58:56 2025 modify_timestamp: Fri Aug 22 20:58:56 2025 journal: acc0c87c8d2f mirroring state: enabled mirroring mode: journal mirroring global id: df19e4c3-cdd8-4b9f-89c5-f980d5b46c31 mirroring primary: false #mirror从 # 验证镜像同步状态 [root@ceph4 ~]# rbd mirror image status image1 image1: global_id: df19e4c3-cdd8-4b9f-89c5-f980d5b46c31 state: up+replaying description: replaying, {"bytes_per_second":17.5,"entries_behind_primary":0,"entries_per_second":0.2,"non_primary_position":{"entry_tid":3,"object_number":3,"tag_tid":1},"primary_position":{"entry_tid":3,"object_number":3,"tag_tid":1}} service: ceph4.ddmzxf on ceph4.laogao.cloud last_update: 2025-08-22 20:59:22 -
验证 prod 集群池和镜像的同步状态。
bash[root@ceph1 ~]# rbd mirror pool info rbd Mode: pool Site Name: prod Peer Sites: UUID: 2e835b66-1a98-4f2a-a10c-8b6b8af39f54 Name: backup Mirror UUID: 9f354662-3968-4bc3-b809-4d7659f8bc9a Direction: tx-only # 主集群无法看到备用集群的集群状态和rbd-mirror进程状态 [root@ceph1 ~]# rbd mirror pool status health: UNKNOWN daemon health: UNKNOWN image health: OK images: 1 total 1 replaying [root@ceph1 ~]# rbd mirror image status image1 image1: global_id: df19e4c3-cdd8-4b9f-89c5-f980d5b46c31**注意:**在单向模式中,主集群无法看到备用集群的集群状态和rbd-mirror进程状态。备集群中的 RBD 镜像代理会更新状态信息。
清理配置过程如下:
-
删除镜像:优先从创建节点删除。如果同步服务已经终止,则需要强制禁用镜像同步,然后再删除。
bash[root@ceph1 ~]# rbd rm image1 -
删除同步对端
bash# 先在 backup 集群执行 [root@ceph4 ~]# rbd mirror pool peer remove rbd be8faee1-d28c-45dd-95d9-9b37099f4c58 #通过rbd mirror pool info rbd获取对方UUID # 然后在 prod 集群执行 [root@ceph1 ~]# rbd mirror pool peer remove rbd 2e835b66-1a98-4f2a-a10c-8b6b8af39f54 -
禁用池同步
bash[root@ceph1 ~]# rbd mirror pool disable rbd # 如果池中存在同步的镜像,则需要先禁用镜像同步,在禁用池同步 [root@ceph4 ~]# rbd mirror image disable image1 --force [root@ceph4 ~]# rbd mirror pool disable rbd -
删除池
bash[root@ceph1 ~]# ceph config set mon mon_allow_pool_delete true [root@ceph1 ~]# ceph osd pool rm rbd rbd --yes-i-really-really-mean-it [root@ceph4 ~]# ceph config set mon mon_allow_pool_delete true [root@ceph4 ~]# ceph osd pool rm rbd rbd --yes-i-really-really-mean-it -
删除同步进程 rbd-mirror
bash# 禁止自动管理 [root@ceph4 ~]# ceph orch apply rbd-mirror --unmanaged Scheduled rbd-mirror update... # 获取rbd-mirror进程的id [root@ceph4 ~]# systemctl list-units|grep -o ' \brbd-mirror[^ ]* ' rbd-mirror.ceph4.ddmzxf # 删除rbd-mirror进程 [root@ceph4 ~]# ceph orch daemon rm rbd-mirror.ceph4.ddmzxf或者直接删除rbd-mirror服务
bash[root@ceph4 ~]# ceph orch rm rbd-mirror
双向-池模式-配置
全新的双向池模式同步,简要配置过程如下:
- 确保双集群状态是
HEALTH_OK。 - 双集群同时创建并初始化池。
- prod 集群创建镜像。
- prod 集群启用池模式镜像功能。
- prod 集群创建引导 token并同步到 backup 集群。
- backup 集群部署 rbd-mirror进程,并使用双向(
rx-tx)导入 prod 集群token。 - prod 集群部署 rbd-mirror进程。
- 验证池和镜像状态。
基于现有的单向池模式同步更改为双向池模式同步,简要配置过程如下:
- backup 集群创建镜像。
- prod 集群删除原先自动创建的
tx-only对端。 - backup 集群删除原先单方向同步,并使用双向(
rx-tx)导入 prod 集群token。 - prod 集群部署rbd-mirror进程。
- 验证池和镜像状态。
本次演示基于全新的双向同步操作。
具体配置过程如下:
-
确保双集群状态是
HEALTH_OK。bash[root@ceph1 ~]# ceph health HEALTH_OK [root@ceph4 ~]# ceph health HEALTH_OK -
双集群同时创建并初始化池。
bash# 主集群 [root@ceph1 ~]# ceph osd pool create rbd 32 32 [root@ceph1 ~]# rbd pool init rbd # 备集群 [root@ceph4 ~]# ceph osd pool create rbd 32 32 [root@ceph4 ~]# rbd pool init rbd -
prod 集群创建镜像image1、prod 集群创建镜像image2。
bash[root@ceph1 ~]# rbd create image1 --size 1024 --pool rbd --image-feature=layering,exclusive-lock,journaling #ceph1上创建image1 [root@ceph4 ~]# rbd create image2 --size 1024 --pool rbd --image-feature=layering,exclusive-lock,journaling #ceph2上创建image2 -
双集群启用池模式镜像功能。
bash[root@ceph1 ~]# rbd mirror pool enable rbd pool [root@ceph4 ~]# rbd mirror pool enable rbd pool -
prod 集群创建引导 token并同步到 backup 集群。
bash[root@ceph1 ~]# rbd mirror pool peer bootstrap create --site-name prod rbd > bootstrap_token_prod [root@ceph1 ~]# rsync -a bootstrap_token_prod root@ceph4: -
backup 集群部署 rbd-mirror 进程,并使用双向(
rx-tx)导入 prod 集群token。bash[root@ceph4 ~]# ceph orch apply rbd-mirror --placement=ceph4.laogao.cloud Scheduled rbd-mirror update... [root@ceph4 ~]# ceph orch ls rbd-mirror NAME RUNNING REFRESHED AGE PLACEMENT rbd-mirror 1/1 4s ago 16s ceph4.laogao.cloud [root@ceph4 ~]# rbd mirror pool peer bootstrap import --site-name backup --direction rx-tx rbd bootstrap_token_prod -
验证两个集群中池同步状态。
bash# 双集群池的同步状态 [root@ceph4 ~]# rbd mirror pool status health: WARNING daemon health: OK image health: WARNING images: 2 total 2 unknown [root@ceph1 ~]# rbd mirror pool status health: UNKNOWN daemon health: UNKNOWN image health: OK images: 1 total 1 replaying # 双集群池的同步方向是双向 [root@ceph4 ~]# rbd mirror pool info rbd Mode: pool Site Name: backup Peer Sites: UUID: 8f595ed3-49b7-4806-9060-40c8b4849762 Name: prod Mirror UUID: Direction: rx-tx Client: client.rbd-mirror-peer [root@ceph1 ~]# rbd mirror pool info rbd Mode: pool Site Name: prod Peer Sites: UUID: faa7b6b6-b748-4efa-b31e-91c2eb38d689 Name: backup Mirror UUID: 8cdf8c6c-3bd3-47bd-bb45-1bb8239a5e82 Direction: rx-tx Client: client.rbd-mirror-peer -
验证两个集群镜像同步状态。
双集群image1状态
bash[root@ceph1 ~]# rbd mirror image status image1 image1: global_id: bfde0b15-681e-45fc-9ad0-9ceb74f8b585 state: down+unknown description: status not found last_update: peer_sites: name: backup state: up+replaying description: replaying, {"bytes_per_second":0.0,"entries_behind_primary":0,"entries_per_second":0.0,"non_primary_position":{"entry_tid":3,"object_number":3,"tag_tid":1},"primary_position":{"entry_tid":3,"object_number":3,"tag_tid":1}} last_update: 2025-08-23 17:18:22 [root@ceph4 ~]# rbd mirror image status image1 image1: global_id: bfde0b15-681e-45fc-9ad0-9ceb74f8b585 state: up+replaying description: replaying, {"bytes_per_second":0.0,"entries_behind_primary":0,"entries_per_second":0.0,"non_primary_position":{"entry_tid":3,"object_number":3,"tag_tid":1},"primary_position":{"entry_tid":3,"object_number":3,"tag_tid":1}} service: ceph4.jitnqq on ceph4.laogao.cloud last_update: 2025-08-23 17:17:22双集群image2状态
bash[root@ceph4 ~]# rbd mirror image status image2 image2: global_id: b517e528-89f6-4246-a87d-777942b13649 state: up+stopped description: local image is primary service: ceph4.jitnqq on ceph4.laogao.cloud last_update: 2025-08-23 17:19:52 # prod 集群没有rbd-mirror进程,未同步过来 [root@ceph1 ~]# rbd mirror image status image2 rbd: error opening image image2: (2) No such file or directory -
prod 集群部署rbd-mirror进程。
bash[root@ceph1 ~]# ceph orch apply rbd-mirror --placement=ceph1.laogao.cloud Scheduled rbd-mirror update... [root@ceph1 ~]# ceph orch ls rbd-mirror NAME PORTS RUNNING REFRESHED AGE PLACEMENT rbd-mirror 1/1 9s ago 12s ceph1.laogao.cloud -
验证两个集群池同步状态。
bash[root@ceph1 ~]# rbd mirror pool status health: OK daemon health: OK image health: OK images: 2 total 2 replaying [root@ceph4 ~]# rbd mirror pool status health: OK daemon health: OK image health: OK images: 2 total 2 replaying -
验证集群中镜像同步状态。
bash[root@ceph1 ~]# rbd mirror image status image1 image1: global_id: bfde0b15-681e-45fc-9ad0-9ceb74f8b585 state: up+stopped description: local image is primary service: ceph1.umpyob on ceph1.laogao.cloud last_update: 2025-08-23 17:29:28 peer_sites: name: backup state: up+replaying description: replaying, {"bytes_per_second":0.0,"entries_behind_primary":0,"entries_per_second":0.0,"non_primary_position":{"entry_tid":3,"object_number":3,"tag_tid":1},"primary_position":{"entry_tid":3,"object_number":3,"tag_tid":1}} last_update: 2025-08-23 17:29:22 [root@ceph1 ~]# rbd mirror image status image2 image2: global_id: b517e528-89f6-4246-a87d-777942b13649 state: up+replaying description: replaying, {"bytes_per_second":0.0,"entries_behind_primary":0,"entries_per_second":0.0,"non_primary_position":{"entry_tid":3,"object_number":3,"tag_tid":1},"primary_position":{"entry_tid":3,"object_number":3,"tag_tid":1}} service: ceph1.umpyob on ceph1.laogao.cloud last_update: 2025-08-23 17:29:58 peer_sites: name: backup state: up+stopped description: local image is primary last_update: 2025-08-23 17:29:52 [root@ceph4 ~]# rbd mirror image status image1 image1: global_id: bfde0b15-681e-45fc-9ad0-9ceb74f8b585 state: up+replaying description: replaying, {"bytes_per_second":0.0,"entries_behind_primary":0,"entries_per_second":0.0,"non_primary_position":{"entry_tid":3,"object_number":3,"tag_tid":1},"primary_position":{"entry_tid":3,"object_number":3,"tag_tid":1}} service: ceph4.jitnqq on ceph4.laogao.cloud last_update: 2025-08-23 17:30:22 peer_sites: name: prod state: up+stopped description: local image is primary last_update: 2025-08-23 17:30:28 [root@ceph4 ~]# rbd mirror image status image2 image2: global_id: b517e528-89f6-4246-a87d-777942b13649 state: up+stopped description: local image is primary service: ceph4.jitnqq on ceph4.laogao.cloud last_update: 2025-08-23 17:30:22 peer_sites: name: prod state: up+replaying description: replaying, {"bytes_per_second":0.0,"entries_behind_primary":0,"entries_per_second":0.0,"non_primary_position":{"entry_tid":3,"object_number":3,"tag_tid":1},"primary_position":{"entry_tid":3,"object_number":3,"tag_tid":1}} last_update: 2025-08-23 17:30:28在双向模式中:
- prod集群看到自己创建的镜像同步状态:本地是
up+stopped,对端是up+replaying。 - prod集群看到同步过来的镜像同步状态:本地是
up+replaying,对端是up+stopped。
- prod集群看到自己创建的镜像同步状态:本地是
清理配置过程如下:
-
删除镜像:优先从创建节点删除。如果同步服务已经终止,则需要强制禁用镜像同步,然后再删除。
bash[root@ceph1 ~]# rbd rm image1 [root@ceph4 ~]# rbd rm image2 -
删除同步对端
bash# 先在 prod 集群执行 [root@ceph1 ~]# rbd mirror pool peer remove rbd faa7b6b6-b748-4efa-b31e-91c2eb38d689 # 然后在 backup 集群执行 [root@ceph4 ~]# rbd mirror pool peer remove rbd 8f595ed3-49b7-4806-9060-40c8b4849762如果删除同步后,系统还会自动创建单方向同步,需要再次删除。
bash[root@ceph4 ~]# rbd mirror pool info rbd Mode: pool Site Name: backup Peer Sites: UUID: 7a9afa38-6c8a-4b0d-ac1a-ec33e670439c Name: prod Mirror UUID: 19c8d1c0-e541-4064-a328-2cab9291bdaf Direction: tx-only [root@ceph4 ~]# rbd mirror pool peer remove rbd 7a9afa38-6c8a-4b0d-ac1a-ec33e670439c # R1相同 -
禁用池同步
bash[root@ceph1 ~]# rbd mirror pool disable rbd [root@ceph4 ~]# rbd mirror pool disable rbd # 如果池中存在同步的镜像,则需要先强制禁用镜像同步 [root@ceph4 ~]# rbd mirror image disable image1 --force -
删除池
bash[root@ceph1 ~]# ceph config set mon mon_allow_pool_delete true [root@ceph1 ~]# ceph osd pool rm rbd rbd --yes-i-really-really-mean-it [root@ceph4 ~]# ceph config set mon mon_allow_pool_delete true [root@ceph4 ~]# ceph osd pool rm rbd rbd --yes-i-really-really-mean-it -
删除同步进程 rbd-mirror
bash# backup 集群操作 [root@ceph4 ~]# ceph orch apply rbd-mirror --unmanaged [root@ceph4 ~]# systemctl list-units|grep -o ' \brbd-mirror[^ ]* ' rbd-mirror.ceph4.jitnqq [root@ceph4 ~]# ceph orch daemon rm rbd-mirror.ceph4.jitnqq Removed rbd-mirror.ceph4.jitnqq from host 'ceph4.laogao.cloud' # prod 集群操作 [root@ceph1 ~]# ceph orch apply rbd-mirror --unmanaged [root@ceph1 ~]# systemctl list-units|grep -o ' \brbd-mirror[^ ]* ' rbd-mirror.ceph1.umpyob [root@ceph1 ~]# ceph orch daemon rm rbd-mirror.ceph1.umpyob Removed rbd-mirror.ceph1.umpyob from host 'ceph1.laogao.cloud'
第 7 章 Ceph 分布式存储 对象存储管理
对象存储介绍
对象存储简介
对象存储是一个基于对象的存储服务, 提供海量、 安全、 高可靠、 低成本的数据存储能力。
对象存储将数据存储为离散项,每一项也是一个对象。每个对象都具有唯一的对象ID (也称对象密钥),用户可在不了解对象位置的情况下,通过对象ID进行存储或检索。
对象存储中的对象实际是一个文件数据与其相关属性信息的集合体, 包括三个部分:
- Key:键值,即对象的名称,为经过 UTF-8 编码的长度大于0且不超过1024的字符序列。一个桶里的每个对象必须拥有唯一的对象键值。
- Metadata:元数据,即对象的描述信息,包括系统元数据和用户元数据,这些元数据以键值对(Key-Value)的形式被上传到对象存储中。元数据由对象存储产生,在处理对象数据时使用,包括Date, Content-length,Last-modify, ETag等。
- Data:数据,即文件的数据内容。
对象存储在扁平的命名空间中 ,称为桶,是对象存储存储对象的容器。 桶中的所有对象都处于同一逻辑层级, 去除了文件系统中的多层级树形目录结构。每个桶都有自己的存储类别、 访问权限、 所属区域等属性, 用户可以在不同区域创建不同存储类别和访问权限的桶, 并配置更多高级属性来满足不同场景的存储诉求。
对象存储特征
- 接入灵活:支持多种形态客户端,如通过用对象存储接口、 RESTful接口、 SDK等。
- 访问协议简单:使用http或https协议访问。
- 访问网络不受限:通过互联网或局域网都进行访问。
- 结构扁平化:对象直接存放在桶中,无目录结构。
RADOS 网关介绍
RADOS 网关简介
-
RADOS GateWay,也称对象网关 (RGW),**为客户端提供标准对象存储 API 来访问 Ceph 集群。**Ceph 存储支持 Amazon S3(简单存储服务)和 OpenStack Swift(OpenStack 对象存储)两种常用的对象 API。Amazon S3 将对象存储的扁平命名空间称为存储桶,而 OpenStack Swift 则将其称为容器。
-
守护进程 radosgw 在 librados 库的基础上构建,提供基于 Beast HTTP、WebSocket 和网络协议库的 Web 服务接口,作为处理 API 请求的前端。
-
radosgw 是Ceph 存储的客户端,用于访问对象存储中对象。

RADOS 网关中用户只能访问网关,不能像cephx 用户一样直接访问存储集群。提交 Amazon S3 或 OpenStack Swift API 请求时,RADOS 网关客户端会使用这些网关用户帐户进行身份验证。网关用户通过 RADOS 网关完成身份验证后,网关会使用 cephx 凭据向存储集群进行身份验证,以处理对象请求。也可通过集成基于 LDAP 的外部身份验证服务来管理网关用户。
RADOS 网关会为默认区域创建多个池:
- .rgw.root,存储信息记录。
- .default.rgw.control,控制池。
- .default.rgw.meta,存储 user_keys 和其他关键元数据。
- .default.rgw.log,包含所有存储桶/容器和对象操作(如创建、读取和删除)的日志。
- .default.rgw.buckets.index,存储存储桶的索引。
- .default.rgw.buckets.data,存储存储桶数据。
- .default.rgw.buckets.non-ec,用于对象元数据上传。
用户也可以手动创建这些池。建议这些池名称以区域名称为前缀,例如区域名称是 us-east-1,则池名称可以是 .us-east-1.rgw.buckets.data。
RADOS 网关架构
Ceph RADOS 网关支持多站点部署:在多个 Ceph 存储集群之间自动复制对象数据。常见的用例是在地理上分隔的集群之间进行主动/主动复制,以便于灾难恢复。

-
区域(zone),每个区域会关联一个或多个 RADOS 网关,这些网关关联Ceph 存储。
-
区域组(zone group ),区域组是由一个或多个区域的集合。存储在区域组中某个区域中的数据会被复制到该区域组中的所有其他区域。每个区域组中会有一个区域为该组的主区域 ,该组中的其他区域为次要区域。
-
域 (realm) ,代表所有对象和存储桶的全局命名空间。域中含有一个或多个区域组,各自包含一个或多个区域。域中会指定一个区域组为主区域组 ,其他都是次要区域组。域 (realm) 中的所有 RADOS 网关都从位于主区域组中主区域中的 RADOS 网关拉取配置。因为主区域组中的主区域负责处理所有元数据更新,所以创建用户等操作都必须在主区域进行。
每个域有关联的期间 (period),每个期间有关联的时期 (epoch)。
- 期间 (period),用于跟踪特定时间域、区域组和区域的配置状态。每个期间有一个唯一 ID,包含域配置,并且知道前一个期间的 ID。
- 时期 (epoch),用于跟踪特定域期间的配置版本号。
更新规则:
- 更新主区域的配置时,RADOS 网关服务使用当前时间更新期间。这个新期间会变成域的当前期间,该期间的时期值会增加一。
- 至于其他配置更改,只有时期会递增,期间不会变化。
RADOS 网关用例
Ceph 对象存储因其高扩展性、高可靠性和灵活性,适用于多种场景,包括大规模数据存储、云服务、备份归档、大数据分析、多媒体存储、容器存储、灾难恢复、混合云、科学计算和物联网数据存储等。
以下是常见的使用场景及原因:
- 大规模数据存储
- 场景: 适用于需要存储海量非结构化数据的场景,如视频、图片、日志等。
- 原因: Ceph 对象存储能轻松扩展到 PB 甚至 EB 级别,适合处理大规模数据。
- 云存储服务
- 场景: 用于公有云或私有云中的对象存储服务。
- 原因: Ceph 兼容 S3 和 Swift API,便于与现有云平台集成,提供高可用性和持久性。
- 备份和归档
- 场景: 用于长期数据备份和归档。
- 原因: Ceph 提供高可靠性和低成本存储,支持数据压缩和加密,适合长期保存。
- 大数据分析
- 场景: 存储大数据分析中的原始数据或中间结果。
- 原因: Ceph 的高吞吐量和低延迟特性,适合大数据应用的读写需求。
- 多媒体内容存储与分发
- 场景: 用于存储和分发视频、音频等多媒体内容。
- 原因: Ceph 的高并发读写能力,适合内容分发网络(CDN)的需求。
- 容器存储
- 场景: 为 Kubernetes 等容器平台提供持久化存储。
- 原因: Ceph 支持 RBD 和 CephFS,适合容器环境中的动态存储需求。
- 灾难恢复
- 场景: 用于跨地域的数据复制和灾难恢复。
- 原因: Ceph 支持多站点复制,确保数据在灾难发生时的高可用性。
- 混合云存储
- 场景: 在混合云环境中统一管理数据。
- 原因: Ceph 可在私有云和公有云之间无缝迁移数据,提供一致的存储体验。
- 科学计算与高性能计算(HPC)
- 场景: 存储科学计算和 HPC 中的大量数据。
- 原因: Ceph 的高吞吐量和并行访问能力,适合科学计算中的大规模数据处理。
- 物联网(IoT)数据存储
- 场景: 存储物联网设备生成的海量数据。
- 原因: Ceph 的高扩展性和高可靠性,适合处理物联网设备产生的大量数据。
RADOS 网关部署
Ceph 使用 Ceph 编排器来部署 (或删除) RADOS 网关服务 ,用于管理单个集群或多个集群。使用集中式配置数据库中的 client.rgw.* 部分来定义新 RADOS 网关守护进程的参数和特征。
对象存储网关部署流程:
- 创建对象存储域
- 创建对象网关
创建对象存储域
示例:

bash
# 创建 realm
[root@ceph1 ~]# radosgw-admin realm create --rgw-realm=webapp --default
[root@ceph1 ~]# radosgw-admin realm list
{
"default_info": "527e3bea-d51d-462e-92d7-79aaf422a89c",
"realms": [
"webapp"
]
}
# 创建 zonegroup,并将其设置为 master
[root@ceph1 ~]# radosgw-admin zonegroup create --rgw-realm=webapp --rgw-zonegroup=video --master --default
[root@ceph1 ~]# radosgw-admin zonegroup list
{
"default_info": "0fdaf584-33ee-4be7-978c-fb2771181aee",
"zonegroups": [
"video"
]
}
# 创建 zone,并将其设置为 master
[root@ceph1 ~]# radosgw-admin zone create --rgw-realm=webapp --rgw-zonegroup=video --rgw-zone=storage1 --master --default
[root@ceph1 ~]# radosgw-admin zone list
{
"default_info": "76366a48-2ab8-4830-9cf7-f9b2fe432c5a",
"zones": [
"storage1"
]
}
# 提交配置
[root@ceph1 ~]# radosgw-admin period update --rgw-realm=webapp --commit
RADOS 网关部署
RADOS 网关部署-命令行
bash
# 创建 rgw,并和已创建的 realm webapp 进行关联,数量为 3
[root@ceph1 ~]# ceph orch apply rgw webapp --placement="3 ceph1.laogao.cloud ceph2.laogao.cloud ceph3.laogao.cloud" --realm=webapp --zone=storage1 --port=8080
# 查看服务
[root@ceph1 ~]# ceph orch ls rgw
NAME PORTS RUNNING REFRESHED AGE PLACEMENT
rgw.webapp ?:8080 3/3 40s ago 45s ceph1.laogao.cloud;ceph2.laogao.cloud;ceph3.laogao.cloud;count:3
# 查看进程
[root@ceph1 ~]# ceph orch ps --daemon-type rgw| awk '{print $1,$4}'
NAME STATUS
rgw.webapp.ceph1.luxaau running
rgw.webapp.ceph2.hrdzlb running
rgw.webapp.ceph3.pyfond running
验证对象存储是否可以访问
yaml
[root@ceph1 ~]# curl http://ceph1.laogao.cloud:8080
<?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>
[root@ceph1 ~]# curl http://ceph2.laogao.cloud:8080
<?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>
[root@ceph1 ~]# curl http://ceph3.laogao.cloud:8080
<?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>
# RADOS 网关部署-服务文件#跳过
#RADOS 网关-部署
以下示例 YAML 文件中,Ceph 编排器会将 rgw.webapp RADOS 网关服务和3个守护进程部署到单个集群中,并会通过端口 8080 提供该服务。
bash
[root@ceph1 ~]# vim rgw_service.yaml
yaml
service_type: rgw
service_id: webapp
service_name: rgw.webapp
placement:
count: 3
hosts:
- ceph1.laogao.cloud
- ceph2.laogao.cloud
- ceph3.laogao.cloud
spec:
rgw_frontend_port: 8080
服务规范文件说明:
- **count 参数用于设定创建的 RGW 实例数量。**如果在一个主机上创建多个实例,Ceph 编排器会将第一个实例的端口设置为指定的 rgw_frontend_port 或 port 值。对于每个后续实例,端口值加 1。例如:ceph1.laogao.cloud 服务器运行两个 RGW 实例,一个使用端口 8080,另一个使用端口 8081。
- 每个实例都启用自己的唯一端口进行访问,并对请求创建相同的响应。通过部署提供单一服务 IP 地址和端口的负载平衡器服务,为 RADOS 网关配置高可用性。
应用部署:
bash
[root@ceph1 ~]# ceph orch apply -i rgw_service.yaml
Scheduled rgw.webapp update...
**有些参数(如 RGW 实例使用的网络或 ssl 证书内容)只能使用服务规格文件来定义。**在服务规范文件中,域、区域和端口的参数名称与 CLI 使用的参数名称不同。
#RADOS 网关-实例删除
bash
# 更改 rgw.webapp 服务实例为2
[root@ceph1 ~]# vim rgw_service.yaml
yaml
service_type: rgw
service_id: webapp
service_name: rgw.webapp
placement:
count: 2
hosts:
- ceph1.laogao.cloud
- ceph2.laogao.cloud
spec:
rgw_frontend_port: 8080
bash
[root@ceph1 ~]# ceph orch apply -i rgw_service.yaml
#RADOS 网关-实例添加
bash
# 更改 rgw.webapp 服务实例为3
[root@ceph1 ~]# vim rgw_service.yaml
yaml
service_type: rgw
service_id: webapp
service_name: rgw.webapp
placement:
count: 3
hosts:
- ceph1.laogao.cloud
- ceph2.laogao.cloud
- ceph3.laogao.cloud
spec:
rgw_frontend_port: 8080
bash
[root@ceph1 ~]# ceph orch apply -i rgw_service.yaml
#RADOS 网关-配置备份
bash
# 查看当前 RADOS 网关配置
[root@ceph1 ~]# ceph orch ls rgw --format yaml
service_type: rgw
service_id: webapp
service_name: rgw.webapp
placement:
count: 3
hosts:
- ceph1.laogao.cloud
- ceph2.laogao.cloud
- ceph3.laogao.cloud
spec:
rgw_frontend_port: 8080
status:
created: '2023-09-20T03:07:39.524771Z'
running: 0
size: 3
events:
- 2023-09-20T03:01:03.668554Z service:rgw.webapp [INFO] "service was created"
# 备份生成的文件
[root@ceph1 ~]# ceph orch ls rgw --format yaml -o rgw_service.yaml
#RADOS 网关-配置恢复
bash
# 删除status之后所有行记录
[root@ceph1 ~]# sed '/^status/,$d' rgw_service.yaml
yaml
service_type: rgw
service_id: webapp
service_name: rgw.webapp
placement:
count: 3
hosts:
- ceph1.laogao.cloud
- ceph2.laogao.cloud
- ceph3.laogao.cloud
spec:
rgw_frontend_port: 8080
bash
[root@ceph1 ~]# ceph orch apply -i rgw_service.yaml
#RADOS 网关删除-跳过
删除 RADOS 网关服务,将删除 RADOS 网关对应所有进程。
bash
[root@ceph1 ~]# ceph orch rm rgw.webapp
注意:删除RADOS 网关,并不会删除池中数据。
#删除对象存储域
yaml
# 删除 zone
[root@ceph1 ~]# radosgw-admin zone delete --rgw-zone=storage
# 删除 zonegroup
[root@ceph1 ~]# radosgw-admin zonegroup delete --rgw-zonegroup=video
# 删除 realm
[root@ceph1 ~]# radosgw-admin realm delete --rgw-realm=webapp
管理对象网关用户
创建用户
使用 radosgw-admin user create 命令来创建 RADOS 网关用户。
- 必选选项 --uid 和 --display-name ,指定唯一的帐户名和人性化显示名。
- 可选选项 --access-key 和 --secret,指定自定义 AWS 帐户和机密密钥。
示例:
bash
[root@ceph1 ~]# radosgw-admin user create --uid="operator" --display-name="S3 Operator" --email="operator@example.com" --access-key="12345" --secret-key="67890"
{
"user_id": "operator",
"display_name": "S3 Operator",
"email": "operator@example.com",
"suspended": 0,
"max_buckets": 1000,
"subusers": [],
"keys": [
{
"user": "operator",
"access_key": "12345",
"secret_key": "67890"
}
],
......
[root@ceph1 ~]# radosgw-admin user list
[
"operator",
"dashboard"
]
[root@ceph1 ~]# radosgw-admin user info --uid=operator
{
"user_id": "operator",
"display_name": "S3 Operator",
"email": "operator@example.com",
"suspended": 0,
"max_buckets": 1000,
"subusers": [],
"keys": [
{
"user": "operator",
"access_key": "12345",
"secret_key": "67890"
}
],
......
如果未指定访问密钥和机密密钥,则自动生成,并显示在输出中。
bash
[root@ceph1 ~]# radosgw-admin user create --uid=s3user --display-name="Amazon S3 API user"
{
"user_id": "s3user",
"display_name": "Amazon S3 API user",
"email": "",
"suspended": 0,
"max_buckets": 1000,
"subusers": [],
"keys": [
{
"user": "s3user",
"access_key": "ZQI72JZZDTA8BRCQOLGK",
"secret_key": "BN6lMGhqacV61Fx2iEHww9N0ySI3Vvo6jMwCJnxX"
}
],
......
**注意:**radosgw-admin 命令自动生成的访问密钥和机密密钥可能包含 JSON 转义字符(\)。客户端可能无法正确处理此字符。建议重新生成或手动指定密钥以避免此问题。
重新生成密钥
仅重新生成现有用户的机密密钥。
bash
[root@ceph1 ~]# radosgw-admin key create --uid=s3user --access-key="ZQI72JZZDTA8BRCQOLGK" --gen-secret
{
"user_id": "s3user",
"display_name": "Amazon S3 API user",
"email": "",
"suspended": 0,
"max_buckets": 1000,
"subusers": [],
"keys": [
{
"user": "s3user",
"access_key": "ZQI72JZZDTA8BRCQOLGK",
"secret_key": "TJCcwo8rspE4xYyLAZHz4vapWA42YGB8hhrlPUnl"
}
],
......
添加用户访问密钥
若要为现有用户添加访问密钥,请使用 --gen-access-key 选项。创建额外的密钥可以方便地授予同一用户对需要不同或唯一密钥的多个应用的访问权限。
bash
[root@ceph1 ~]# radosgw-admin key create --uid=s3user --gen-access-key
{
"user_id": "s3user",
"display_name": "Amazon S3 API user",
"email": "",
"suspended": 0,
"max_buckets": 1000,
"subusers": [],
"keys": [
{
"user": "s3user",
"access_key": "6WBR1FL8CBFX26KVRPPA",
"secret_key": "UsytqYCeSudSqHKWwVVYZGFDdcS24lPpkXBrD42G"
},
{
"user": "s3user",
"access_key": "ZQI72JZZDTA8BRCQOLGK",
"secret_key": "TJCcwo8rspE4xYyLAZHz4vapWA42YGB8hhrlPUnl"
}
],
......
删除用户密钥
要从用户删除访问密钥和相关的机密密钥,请使用 radosgw-admin key rm --access-key 命令。此操作非常适用于删除单个应用访问权限,并且不会影响使用其他密钥的访问权限。
bash
[root@ceph1 ~]# radosgw-admin key rm --uid=s3user --access-key=6WBR1FL8CBFX26KVRPPA
{
"user_id": "s3user",
"display_name": "Amazon S3 API user",
"email": "",
"suspended": 0,
"max_buckets": 1000,
"subusers": [],
"keys": [
{
"user": "s3user",
"access_key": "ZQI72JZZDTA8BRCQOLGK",
"secret_key": "TJCcwo8rspE4xYyLAZHz4vapWA42YGB8hhrlPUnl"
}
],
......
临时禁用对象网关用户
使用 radosgw-admin user suspend 命令可临时禁用 RADOS 网关用户,用户的子用户也会暂停,无法与 RADOS 网关服务交互。
bash
root@ceph1 ~]# radosgw-admin user suspend --uid=s3user
{
"user_id": "s3user",
"display_name": "Amazon S3 API user",
"email": "",
"suspended": 1, <----看着变成了1
....
注意:suspended的值为1。
临时启用对象网关用户
使用 radosgw-admin user enable 命令可启用 RADOS 网关用户。
bash
root@ceph1 ~]# radosgw-admin user enable --uid=s3user
{
"user_id": "s3user",
"display_name": "Amazon S3 API user",
"email": "",
"suspended": 0,
....
注意:suspended的值为0。
修改用户信息
用户可修改用户信息,如电子邮件、显示名、密钥和访问控制级别。
bash
[root@ceph1 ~]# radosgw-admin user modify --uid=s3user --access=full
--access 选项用于控制子用户访问权限,控制级别有:read、write、 readwrite 和 full。full 访问级别包括 readwrite 级别和访问控制管理功能。
删除用户
若要移除用户,同时删除其对象和存储桶,需使用 --purge-data 选项。
bash
[root@ceph1 ~]# radosgw-admin user list
[
"operator",
"dashboard",
"s3user"
]
[root@ceph1 ~]# radosgw-admin user rm --uid=s3user --purge-data
[root@ceph1 ~]# radosgw-admin user list
[
"operator",
"dashboard"
]
[root@ceph1 ~]#
使用 Amazon S3 API 访问对象存储
Amazon S3 API 介绍
在混合云环境中,用户希望应用可以通过相同的 API 无缝混用私有企业、公共云资源和存储位置。Ceph 存储支持使用 Amazon S3 API 接口管理对象存储资源。
Amazon S3 API 称命名空间为存储桶,用于存储对象。要使用 Amazon S3 API 管理对象和存储桶,应用需通过 RADOS 网关用户进行身份验证。每个用户都有一个识别用户的 access key 和一个对用户进行身份验证的 secret key。
使用 Amazon S3 API 时,需考虑对象和元数据的大小限制:
- 对象大小介于 0B 和 5 TB 之间。
- 单次上传操作的最大大小为 5GB。
- 使用分段上传功能可上传 100MB 以上的对象。
- 单个 HTTP 请求中的元数据大小最大为 16,000 字节。
安装 Amazon S3 API 客户端
Amazon S3 API 客户端有多个,例如 awscli、cloudberry、cyberduck 和 curl。
**这里我们讲解 aws 工具。**aws工具由awscli 软件包提供。
以下演示通过pip方式安装。
bash
# 准备 aliyun 源 pip 仓库
[root@client ~]# mkdir .pip
[root@client ~]# cat > .pip/pip.conf << 'EOF'
[global]
index-url = http://mirrors.aliyun.com/pypi/simple/
[install]
trusted-host=mirrors.aliyun.com
EOF
# 安装软件包
[root@client ~]# pip3 install awscli
使用 Amazon S3 API 客户端
aws 命令帮助信息
bash
[root@client ~]# aws
Note: AWS CLI version 2, the latest major version of the AWS CLI, is now stable and recommended for general use. For more information, see the AWS CLI version 2 installation instructions at: https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html
usage: aws [options] <command> <subcommand> [<subcommand> ...] [parameters]
To see help text, you can run:
aws help
aws <command> help
aws <command> <subcommand> help
aws: error: the following arguments are required: command
配置 AWS CLI 凭据
配置 AWS CLI 工具默认凭据:使用 operator 用户,输入 12345 作为访问密钥,67890 作为机密密钥。
bash
[root@client ~]# aws configure
AWS Access Key ID [None]: 12345
AWS Secret Access Key [None]: 67890
Default region name [None]: `回车`
Default output format [None]: `回车`
配置信息保存在~/.aws目录。
bash
[root@client ~]# ls .aws
config credentials
[root@client ~]# cat .aws/config
[default]
[root@client ~]# cat .aws/credentials
[default]
aws_access_key_id = 12345
aws_secret_access_key = 67890
注意:aws 命令默认使用 default 中凭据。
如果想配置多个凭据,配置如下:#跳过
bash
[root@client ~]# aws configure --profile=ceph
AWS Access Key ID [None]: 12345
AWS Secret Access Key [None]: 67890
Default region name [None]:
Default output format [None]:
[root@client ~]# cat .aws/config
[default]
[profile ceph]
[root@client ~]# cat .aws/credentials
[default]
aws_access_key_id = 12345
aws_secret_access_key = 67890
[ceph]
aws_access_key_id = 12345
aws_secret_access_key = 67890
配置参考:https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html
使用参数 endpoint_url配置服务器位置。
示例:
创建存储桶
环境准备:
client:
bash
[root@client ~]# scp 192.168.108.11:/etc/hosts /etc/hosts
可以通过选项 --profile 指定凭据,--endpoint 指定服务器位置。
bash
[root@client ~]# aws --endpoint=http://ceph1.laogao.cloud:8080 s3 mb s3://webapp
make_bucket: webapp
查看存储桶清单
示例:
bash
[root@client ~]# aws --endpoint=http://ceph1.laogao.cloud:8080 s3 ls
2025-08-25 17:14:05 webapp
radosgw-admin 命令也支持存储桶操作,例如使用 radosgw-admin bucket list 或 radosgw-admin bucket rm 命令。
bash
[root@ceph1 ~]# radosgw-admin buckets list
[
"webapp"
]
上传对象到存储桶
cp 子命令支持三种复制方向:
<LocalPath> <S3Uri>,将本地文件上传到对象存储中。<S3Uri> <LocalPath>,下载对象存储中对象到本地。<S3Uri> <S3Uri>,将对象存储中对象复制到对象存储中。
示例:
bash
[root@client ~]# echo Hello World > Welcome-pub.html
[root@client ~]# echo Hello laogao > Welcome-pri.html
[root@client ~]# aws --endpoint=http://ceph1.laogao.cloud:8080 s3 cp Welcome-pub.html s3://webapp/ --acl=public-read-write
upload: ./Welcome-pub.html to s3://webapp/Welcome-pub.html
[root@client ~]# aws s3 cp Welcome-pri.html s3://webapp --endpoint=http://ceph1.laogao.cloud:8080
upload: ./Welcome-pri.html to s3://webapp/Welcome-pri.html
查看存储桶中对象
bash
[root@client ~]# aws s3 ls s3://webapp --endpoint=http://ceph1.laogao.cloud:8080
2025-08-25 17:23:35 13 Welcome-pri.html
2025-08-25 17:22:18 12 Welcome-pub.html
下载存储桶中对象
bash
# 下载单个
[root@client ~]# aws s3 cp s3://webapp/Welcome-pri.html /tmp --endpoint=http://ceph1.laogao.cloud:8080
download: s3://webapp/Welcome-pri.html to ../tmp/Welcome-pri.html
[root@client ~]# ls /tmp/Welcome-pri.html
/tmp/Welcome-pri.html
# 使用选项 --recursive 递归下载bucket中所有对象
[root@client ~]# aws s3 cp s3://webapp /tmp --recursive --endpoint=http://ceph1.laogao.cloud:8080
download: s3://webapp/Welcome-pri.html to ../tmp/Welcome-pri.html
download: s3://webapp/Welcome-pub.html to ../tmp/Welcome-pub.html
# 使用wget或者curl下载
[root@client ~]# wget http://ceph1.laogao.cloud:8080/webapp/Welcome-pub.html # Welcome-pub.html可以正常下载
[root@client ~]# wget http://ceph1.laogao.cloud:8080/webapp/Welcome-pri.html # Welcome-pri.html不可以下载,因为权限不允许
--2025-08-25 17:36:59-- http://ceph1.laogao.cloud:8080/webapp/Welcome-pri.html
Resolving ceph1.laogao.cloud (ceph1.laogao.cloud)... 192.168.108.11
Connecting to ceph1.laogao.cloud (ceph1.laogao.cloud)|192.168.108.11|:8080... connected.
HTTP request sent, awaiting response... 403 Forbidden
2025-08-25 17:36:59 ERROR 403: Forbidden.
删除存储桶中对象
bash
[root@client ~]# aws s3 rm s3://webapp/Welcome-pri.html --endpoint=http://ceph1.laogao.cloud:8080
delete: s3://webapp/Welcome-pri.html
[root@client ~]# aws s3 ls s3://webapp --endpoint=http://ceph1.laogao.cloud:8080
2025-08-25 17:22:18 12 Welcome-pub.html
删除存储桶
bash
# 非空的存储桶不能删除
[root@client ~]# aws s3 rb s3://webapp --endpoint=http://ceph1.laogao.cloud:8080
remove_bucket failed: s3://webapp argument of type 'NoneType' is not iterable
# 清空存储桶,再次删除
[root@client ~]# aws s3 rm s3://webapp --recursive --include "Welcome-*" --endpoint=http://ceph1.laogao.cloud:8080
delete: s3://webapp/Welcome-pub.html
[root@client ~]# aws s3 rb s3://webapp --endpoint=http://ceph1.laogao.cloud:8080
remove_bucket: webapp
用户配额管理
设置配额可限制用户或存储桶可消耗的存储量。
user 级别
--quota-scope 选项设置为 user 来应用用户配额。
启用用户配额
示例:operator用户的配额设置为最多 1024 个对象。
bash
[root@ceph1 ~]# radosgw-admin quota enable --quota-scope=user --uid=operator
[root@ceph1 ~]# radosgw-admin quota set --quota-scope=user --uid=operator --max-objects=1024
# 查看用户配额
[root@ceph1 ~]# radosgw-admin user info --uid=operator
{
"user_id": "operator",
"display_name": "S3 Operator",
"email": "operator@example.com",
"suspended": 0,
"max_buckets": 1000,
"subusers": [],
"keys": [
{
"user": "operator",
"access_key": "12345",
"secret_key": "67890"
}
],
"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": true,
"check_on_raw": false,
"max_size": -1,
"max_size_kb": 0,
"max_objects": 1024
},
"temp_url_keys": [],
"type": "rgw",
"mfa_ids": []
}
# 查看空间使用情况
[root@ceph1 ~]# radosgw-admin user stats --uid=operator
{
"stats": {
"size": 0,
"size_actual": 0,
"size_kb": 0,
"size_kb_actual": 0,
"num_objects": 0
},
"last_stats_sync": "0.000000",
"last_stats_update": "2025-08-25T09:44:36.609841Z"
}
禁用用户配额
示例:禁用operator用户配额。
bash
[root@ceph1 ~]# radosgw-admin quota set --quota-scope=user --uid=operator --max-objects=-1
[root@ceph1 ~]# radosgw-admin quota disable --quota-scope=user --uid=operator
[root@ceph1 ~]# radosgw-admin user info --uid=operator
{
"user_id": "operator",
"display_name": "S3 Operator",
"email": "operator@example.com",
"suspended": 0,
"max_buckets": 1000,
"subusers": [],
"keys": [
{
"user": "operator",
"access_key": "12345",
"secret_key": "67890"
}
],
"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": []
}
bucket 级别
--quota-scope 选项设置为 bucket 来应用存储桶配额。
启用 bucket 配额
示例:webapp 存储桶被设置为最多 1024 个对象。
bash
[root@client ~]# aws --endpoint=http://ceph1.laogao.cloud:8080 s3 mb s3://webapp
make_bucket: webapp
[root@ceph1 ~]# radosgw-admin quota enable --quota-scope=bucket --bucket=webapp
[root@ceph1 ~]# radosgw-admin quota set --quota-scope=bucket --bucket=webapp --max-objects=1024
# 查看 bucket 配额
[root@ceph1 ~]# radosgw-admin bucket stats --bucket=webapp
{
"bucket": "webapp",
"num_shards": 11,
"tenant": "",
"zonegroup": "0fdaf584-33ee-4be7-978c-fb2771181aee",
"placement_rule": "default-placement",
"explicit_placement": {
"data_pool": "",
"data_extra_pool": "",
"index_pool": ""
},
"id": "76366a48-2ab8-4830-9cf7-f9b2fe432c5a.44325.2",
"marker": "76366a48-2ab8-4830-9cf7-f9b2fe432c5a.44325.2",
"index_type": "Normal",
"owner": "operator",
"ver": "0#1,1#1,2#1,3#1,4#1,5#1,6#1,7#1,8#1,9#1,10#1",
"master_ver": "0#0,1#0,2#0,3#0,4#0,5#0,6#0,7#0,8#0,9#0,10#0",
"mtime": "2025-08-25T10:12:11.164221Z",
"creation_time": "2025-08-25T10:09:12.571418Z",
"max_marker": "0#,1#,2#,3#,4#,5#,6#,7#,8#,9#,10#",
"usage": {},
"bucket_quota": {
"enabled": true,
"check_on_raw": false,
"max_size": -1,
"max_size_kb": 0,
"max_objects": 1024 #webapp 存储桶被设置为最多 1024 个对象。
}
}
禁用 bucket 配额
示例:
bash
[root@ceph1 ~]# radosgw-admin quota set --quota-scope=bucket --bucket=webapp --max-objects=-1
[root@ceph1 ~]# radosgw-admin quota disable --quota-scope=bucket --bucket=webapp
# 查看配额和使用情况
[root@ceph1 ~]# radosgw-admin bucket stats --bucket=webapp
{
"bucket": "webapp",
"num_shards": 11,
"tenant": "",
"zonegroup": "0fdaf584-33ee-4be7-978c-fb2771181aee",
"placement_rule": "default-placement",
"explicit_placement": {
"data_pool": "",
"data_extra_pool": "",
"index_pool": ""
},
"id": "76366a48-2ab8-4830-9cf7-f9b2fe432c5a.44325.2",
"marker": "76366a48-2ab8-4830-9cf7-f9b2fe432c5a.44325.2",
"index_type": "Normal",
"owner": "operator",
"ver": "0#1,1#1,2#1,3#1,4#1,5#1,6#1,7#1,8#1,9#1,10#1",
"master_ver": "0#0,1#0,2#0,3#0,4#0,5#0,6#0,7#0,8#0,9#0,10#0",
"mtime": "2025-08-25T10:13:42.983364Z",
"creation_time": "2025-08-25T10:09:12.571418Z",
"max_marker": "0#,1#,2#,3#,4#,5#,6#,7#,8#,9#,10#",
"usage": {},
"bucket_quota": {
"enabled": false,
"check_on_raw": false,
"max_size": -1,
"max_size_kb": 0,
"max_objects": -1 #取消了配额
}
}
global 级别
全局配额会影响集群中的所有存储桶和所有用户。
针对所有用户的配额:
bash
[root@ceph1 ~]# radosgw-admin global quota set --quota-scope user --max-objects 2048
Global quota changes saved. Use 'period update' to apply them to the staging period, and 'period commit' to commit the new period.
{
"user quota": {
"enabled": false,
"check_on_raw": false,
"max_size": -1,
"max_size_kb": 0,
"max_objects": 2048
}
}
[root@ceph1 ~]# radosgw-admin global quota enable --quota-scope user
Global quota changes saved. Use 'period update' to apply them to the staging period, and 'period commit' to commit the new period.
{
"user quota": {
"enabled": true,
"check_on_raw": false,
"max_size": -1,
"max_size_kb": 0,
"max_objects": 2048
}
}
# 查看配额
[root@ceph1 ~]# radosgw-admin global quota get --quota-scope user
{
"user quota": {
"enabled": true,
"check_on_raw": false,
"max_size": -1,
"max_size_kb": 0,
"max_objects": 2048
}
}
针对所有bucket配额:
bash
[root@ceph1 ~]# radosgw-admin global quota set --quota-scope bucket --max-objects 2048
Global quota changes saved. Use 'period update' to apply them to the staging period, and 'period commit' to commit the new period.
{
"bucket quota": {
"enabled": false,
"check_on_raw": false,
"max_size": -1,
"max_size_kb": 0,
"max_objects": 2048
}
}
[root@ceph1 ~]# radosgw-admin global quota enable --quota-scope bucket
Global quota changes saved. Use 'period update' to apply them to the staging period, and 'period commit' to commit the new period.
{
"bucket quota": {
"enabled": true,
"check_on_raw": false,
"max_size": -1,
"max_size_kb": 0,
"max_objects": 2048
}
}
# 查看配额
[root@ceph1 ~]# radosgw-admin global quota get --quota-scope bucket
{
"bucket quota": {
"enabled": true,
"check_on_raw": false,
"max_size": -1,
"max_size_kb": 0,
"max_objects": 2048
}
}
要在区域和期间配置中实施全局配额:
- 使用 radosgw-admin period update --commit 命令来提交更改来实施配额。
- 重启 RGW 实例来实施配额。
查看配额使用情况
存储管理员通过监控使用情况统计信息来确定存储消耗或用户带宽使用情况。监控还有助于查找不活动的应用或不当的用户配额。
显示用户在特定日期之间的使用情况统计信息。
bash
[root@ceph1 ~]# radosgw-admin usage show --uid=operator --start-date='2023-09-21T07:01:52' --end-date='2023-09-21T07:01:53'
{
"entries": [],
"summary": []
}
查看所有用户的统计信息。这些总体统计数据有助于了解对象存储模式,并规划新实例的部署以扩展 RADOS 网关服务。
bash
[root@ceph1 ~]# radosgw-admin usage show --show-log-entries=false
{
"summary": []
}
使用 Swift API 访问对象存储-跳过
Swift API 介绍
用户还可以通过 OpenStack Swift API 访问 Ceph 存储集群中对象。
OpenStack Swift API 的用户模型与 Amazon S3 API 的不同。
- **Amazon S3 API 授权和身份验证模型是单层设计。**一个用户帐户可能有多个访问密钥和机密,供该用户提供不同类型的访问。
- **OpenStack Swift API 是多层级设计,专为容纳租户和指定用户而构建。**Swift 租户拥有由服务使用的存储及其容器。Swift 用户分配给服务,配置不同的访问权限级别访问存储。
为了容纳 OpenStack Swift API 身份验证和授权模型,RADOS 网关使用子用户。Swift API tenant:user 模型以 user:subuser 形式映射到 RADOS 网关的身份验证系统。
- Swift API 租户 作为 RADOS 网关用户进行处理。
- Swift API 用户 作为 RADOS 网关子用户进行处理。
若要访问Swift API ,需要创建一个 Swift 用户,然后为该 Swift 用户创建一个子用户,该子用户与 RADOS 网关用户和访问密钥相关联。
还原快照做如下操作:
bash
radosgw-admin realm create --rgw-realm=webapp --default
radosgw-admin zonegroup create --rgw-realm=webapp --rgw-zonegroup=video --master --default
radosgw-admin zone create --rgw-realm=webapp --rgw-zonegroup=video --rgw-zone=storage --master --default
ceph orch apply rgw webapp --placement="3 ceph1.laogao.cloud ceph2.laogao.cloud ceph3.laogao.cloud" --realm=webapp --zone=storage --port=8080
radosgw-admin user create --uid="operator" --display-name="swift Operator" --email="operator@example.com" --access_key="12345" --secret="67890"
管理对象网关子用户
创建子用户
bash
# 这里创建 operator 子用户 operator:swift
[root@ceph1 ~]# radosgw-admin subuser create --uid=operator --subuser=operator:swift --access=full --secret=opswift
{
"user_id": "operator",
"display_name": "swift Operator",
"email": "operator@example.com",
"suspended": 0,
"max_buckets": 1000,
"subusers": [
{
"id": "operator:swift",
"permissions": "full-control"
}
],
"keys": [
{
"user": "operator",
"access_key": "12345",
"secret_key": "67890"
}
],
"swift_keys": [
{
"user": "operator:swift",
"secret_key": "opswift"
}
],
"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": []
}
- --access 选项,指定用户的权限(读取、写入、读写、完全)。
- --uid 选项,指定现有的已关联 RADOS 网关用户。
- --subuser=username:swift 选项,指定现有的已关联 RADOS 网关用户的子用户。
创建子用户 key
bash
[root@ceph1 ~]# radosgw-admin key create --uid=operator --subuser=operator:swift --key-type=swift --gen-secret
--key-type 选项接受 swift 或 s3 值。如果要手动指定访问密钥,请使用 --access-key 选项;如果要手动指定机密密钥,请使用 --secret-key 选项。也可以使用 --gen-accesskey 选项仅生成随机访问密钥,或使用 --gen-secret 选项仅生成随机机密。
修改子用户
使用 radosgw-admin subuser modify 命令可修改子用户,例如访问级别、secret等。
bash
[root@ceph1 ~]# radosgw-admin subuser modify --uid=operator --subuser=operator:swift --secret=opswift --access=full
删除子用户key
要删除子用户密钥,请使用 radosgw-admin key rm 命令。
bash
[root@ceph1 ~]# radosgw-admin key rm --subuser=operator:swift
删除子用户
使用 radosgw-admin subuser rm 命令删除子用户。--purge-data 选项可清除与子用户关联的所有数据,--purge-keys 选项可清除所有子用户密钥。
bash
[root@ceph1 ~]# radosgw-admin subuser rm --subuser=operator:swift
准备实验子用户
bash
# 创建用户 swift
[root@ceph1 ~]# radosgw-admin user create --uid=swift --display-name=swift
# 创建子账号 swift_rgw
[root@ceph1 ~]# radosgw-admin subuser create --uid=swift --subuser=swift:swift_rgw --access=full
# 创建的子账号 swift 类型 key
[root@ceph1 ~]# radosgw-admin key create --subuser=swift:swift_rgw --key-type=swift --gen-secret
{
"user_id": "swift",
"display_name": "swift",
"email": "",
"suspended": 0,
"max_buckets": 1000,
"subusers": [
{
"id": "swift:swift_rgw",
"permissions": "full-control"
}
],
"keys": [
{
"user": "swift",
"access_key": "BXK4ZTZLO2A5W2380V8Y",
"secret_key": "ygZS3CTL1x3ja4UJMlY4M6Zb8abOQFZ3A9FOgQcM"
}
],
"swift_keys": [
{
"user": "swift:swift_rgw",
"secret_key": "9KPxNkJSvGP1i5LDs9QV4elDCoHTAjdsPJoszDWj"
}
],
"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": []
}
# 配置完成后,记录下生成的 Key,后续会使用该值进行认证。
# "user": "swift:swift_rgw",
# "secret_key": "9KPxNkJSvGP1i5LDs9QV4elDCoHTAjdsPJoszDWj"
安装 swift 客户端
bash
# 准备 aliyun 源 pip 仓库
[root@client ~]# mkdir .pip
[root@client ~]# cat > .pip/pip.conf << 'EOF'
[global]
index-url = http://mirrors.aliyun.com/pypi/simple/
[install]
trusted-host=mirrors.aliyun.com
EOF
# 安装软件包
[root@client ~]# pip3 install python-swiftclient
# 确认swift版本
[root@client ~]# swift --version
python-swiftclient 4.7.0
配置用户凭据
Swift 客户端与 RADOS 网关通信时,RADOS 网关同时充当数据服务器和 Swift 身份验证守护进程(使用 /auth URL 路径)。
使用环境变量提供凭据
RADOS 网关支持 Internal Swift(版本 1.0)和 OpenStack Keystone(版本2.0)身份验证:
- 如果使用的是 Auth 版本 1.0,则请使用 ST_AUTH、ST_USER 和 ST_KEY 环境变量。
- 如果使用的是 Auth 版本 2.0,则请使用OS_AUTH_URL、OS_USERNAME、OS_PASSWORD、OS_TENANT_NAME 和OS_TENANT_ID 环境变量。
bash
[root@client ~]# vim swift.rc
export ST_AUTH=http://ceph1.laogao.cloud:8080/auth/1.0
export ST_USER=swift:swift_rgw
export ST_KEY=9KPxNkJSvGP1i5LDs9QV4elDCoHTAjdsPJoszDWj #用前面的值替代
[root@client ~]# source swift.rc
[root@client ~]# swift list
使用选项提供凭据
用户认证选项:
- -A 选项,指定Swift 认证 URL。
- -U 选项,指定Swift 子用户。
- -K 选项,指定Swift 子用户对应的机密。
示例:
bash
[root@client ~]# swift -A http://ceph1.laogao.cloud:8080/auth/1.0 -U "swift:swift_rgw" -K 9KPxNkJSvGP1i5LDs9QV4elDCoHTAjdsPJoszDWj list
管理对象
swift 命令帮助信息
bash
[root@client ~]# swift --help
usage: swift [--version] [--help] [--os-help] [--snet] [--verbose]
[--debug] [--info] [--quiet] [--auth <auth_url>]
[--auth-version <auth_version> |
--os-identity-api-version <auth_version> ]
[--user <username>]
[--key <api_key>] [--retries <num_retries>]
[--os-username <auth-user-name>]
[--os-password <auth-password>]
[--os-user-id <auth-user-id>]
[--os-user-domain-id <auth-user-domain-id>]
[--os-user-domain-name <auth-user-domain-name>]
[--os-tenant-id <auth-tenant-id>]
[--os-tenant-name <auth-tenant-name>]
[--os-project-id <auth-project-id>]
[--os-project-name <auth-project-name>]
[--os-project-domain-id <auth-project-domain-id>]
[--os-project-domain-name <auth-project-domain-name>]
[--os-auth-url <auth-url>]
[--os-auth-token <auth-token>]
[--os-auth-type <os-auth-type>]
[--os-application-credential-id
<auth-application-credential-id>]
[--os-application-credential-secret
<auth-application-credential-secret>]
[--os-storage-url <storage-url>]
[--os-region-name <region-name>]
[--os-service-type <service-type>]
[--os-endpoint-type <endpoint-type>]
[--os-cacert <ca-certificate>]
[--insecure]
[--os-cert <client-certificate-file>]
[--os-key <client-certificate-key-file>]
[--no-ssl-compression]
[--force-auth-retry]
<subcommand> [--help] [<subcommand options>]
Command-line interface to the OpenStack Swift API.
Positional arguments:
<subcommand>
delete Delete a container or objects within a container.
download Download objects from containers.
list Lists the containers for the account or the objects
for a container.
post Updates meta information for the account, container,
or object; creates containers if not present.
copy Copies object, optionally adds meta
stat Displays information for the account, container,
or object.
upload Uploads files or directories to the given container.
capabilities List cluster capabilities.
tempurl Create a temporary URL.
auth Display auth related environment variables.
bash_completion Outputs option and flag cli data ready for
bash_completion.
Examples:
swift download --help
swift -A https://api.example.com/v1.0 \
-U user -K api_key stat -v
swift --os-auth-url https://api.example.com/v2.0 \
--os-tenant-name tenant \
--os-username user --os-password password list
swift --os-auth-url https://api.example.com/v3 --auth-version 3\
--os-project-name project1 --os-project-domain-name domain1 \
--os-username user --os-user-domain-name domain1 \
--os-password password list
swift --os-auth-url https://api.example.com/v3 --auth-version 3\
--os-project-id 0123456789abcdef0123456789abcdef \
--os-user-id abcdef0123456789abcdef0123456789 \
--os-password password list
swift --os-auth-url https://api.example.com/v3 --auth-version 3\
--os-application-credential-id d78683c92f0e4f9b9b02a2e208039412 \
--os-application-credential-secret APPLICATION_CREDENTIAL_SECRET \
--os-auth-type v3applicationcredential list
swift --os-auth-token 6ee5eb33efad4e45ab46806eac010566 \
--os-storage-url https://10.1.5.2:8080/v1/AUTH_ced809b6a4baea7aeab61a \
list
swift list --lh
optional arguments:
--version show program's version number and exit
-h, --help
--os-help Show OpenStack authentication options.
-s, --snet Use SERVICENET internal network.
-v, --verbose Print more info.
--debug Show the curl commands and results of all http queries
regardless of result status.
--info Show the curl commands and results of all http queries
which return an error.
-q, --quiet Suppress status output.
-A=AUTH, --auth=AUTH URL for obtaining an auth token.
-V=AUTH_VERSION, --auth-version=AUTH_VERSION, --os-identity-api-version=AUTH_VERSION
Specify a version for authentication. Defaults to
env[ST_AUTH_VERSION], env[OS_AUTH_VERSION],
env[OS_IDENTITY_API_VERSION] or 1.0.
-U=USER, --user=USER User name for obtaining an auth token.
-K=KEY, --key=KEY Key for obtaining an auth token.
-T=TIMEOUT, --timeout=TIMEOUT
Timeout in seconds to wait for response.
-R=RETRIES, --retries=RETRIES
The number of times to retry a failed connection.
--insecure Allow swiftclient to access servers without having to
verify the SSL certificate. Defaults to
env[SWIFTCLIENT_INSECURE] (set to 'true' to enable).
--no-ssl-compression This option is deprecated and not used anymore. SSL
compression should be disabled by default by the
system SSL library.
--force-auth-retry Force a re-auth attempt on any error other than 401
unauthorized
--prompt Prompt user to enter a password which overrides any
password supplied via --key, --os-password or
environment variables.
子命令帮助信息
bash
[root@client ~]# swift upload --help
Usage: swift upload [--changed] [--skip-identical] [--segment-size <size>]
[--segment-container <container>] [--leave-segments]
[--object-threads <thread>] [--segment-threads <threads>]
[--meta <name:value>] [--header <header>] [--use-slo]
[--use-dlo] [--ignore-checksum] [--skip-container-put]
[--object-name <object-name>]
<container> <file_or_directory> [<file_or_directory>] [...]
Uploads specified files and directories to the given container.
Positional arguments:
<container> Name of container to upload to.
<file_or_directory> Name of file or directory to upload. Specify multiple
times for multiple uploads. If "-" is specified, reads
content from standard input (--object-name is required
in this case).
Optional arguments:
-c, --changed Only upload files that have changed since the last
upload.
--skip-identical Skip uploading files that are identical on both sides.
-S, --segment-size <size>
Upload files in segments no larger than <size> (in
Bytes) and then create a "manifest" file that will
download all the segments as if it were the original
file.
--segment-container <container>
Upload the segments into the specified container. If
not specified, the segments will be uploaded to a
<container>_segments container to not pollute the
main <container> listings.
--leave-segments Indicates that you want the older segments of manifest
objects left alone (in the case of overwrites).
--object-threads <threads>
Number of threads to use for uploading full objects.
Default is 10.
--segment-threads <threads>
Number of threads to use for uploading object segments.
Default is 10.
-m, --meta <name:value>
Sets a meta data item. This option may be repeated.
Example: -m Color:Blue -m Size:Large
-H, --header <header:value>
Adds a customized request header. This option may be
repeated. Example: -H "content-type:text/plain"
-H "Content-Length: 4000".
--use-slo When used in conjunction with --segment-size it will
create a Static Large Object. Deprecated; this is now
the default behavior when the cluster supports it.
--use-dlo When used in conjunction with --segment-size it will
create a Dynamic Large Object. May be useful with old
swift clusters.
--ignore-checksum Turn off checksum validation for uploads.
--skip-container-put Assume all necessary containers already exist; don't
automatically try to create them.
--object-name <object-name>
Upload file and name object to <object-name> or upload
dir and use <object-name> as object prefix instead of
folder name.
查看存储状态
bash
[root@client ~]# swift stat
Account: v1
Containers: 0
Objects: 0
Bytes: 0
Objects in policy "default-placement-bytes": 0
Bytes in policy "default-placement-bytes": 0
Containers in policy "default-placement": 0
Objects in policy "default-placement": 0
Bytes in policy "default-placement": 0
X-Timestamp: 1756120916.52301
X-Account-Bytes-Used-Actual: 0
X-Trans-Id: tx000000bdae1b6eec631b5-0068ac4754-ad01-storage
X-Openstack-Request-Id: tx000000bdae1b6eec631b5-0068ac4754-ad01-storage
Accept-Ranges: bytes
Content-Type: text/plain; charset=utf-8
Connection: Keep-Alive
查看认证信息
bash
[root@client ~]# swift auth
export OS_STORAGE_URL=http://ceph1.laogao.cloud:8080/swift/v1
export OS_AUTH_TOKEN=AUTH_rgwtk0f00000073776966743a73776966745f7267771c03132ca7ff9f23e498ad685aaedc2332323e8a316edd865b5d15be670fb35bf3a00a8c
创建容器
bash
[root@client ~]# swift post --help
Usage: swift post [--read-acl <acl>] [--write-acl <acl>] [--sync-to <sync-to>]
[--sync-key <sync-key>] [--meta <name:value>]
[--header <header>]
[<container> [<object>]]
Updates meta information for the account, container, or object.
If the container is not found, it will be created automatically.
Positional arguments:
[<container>] Name of container to post to.
[<object>] Name of object to post.
Optional arguments:
-r, --read-acl <acl> Read ACL for containers. Quick summary of ACL syntax:
.r:*, .r:-.example.com, .r:www.example.com,
account1 (v1.0 identity API only),
account1:*, account2:user2 (v2.0+ identity API).
-w, --write-acl <acl> Write ACL for containers. Quick summary of ACL syntax:
account1 (v1.0 identity API only),
account1:*, account2:user2 (v2.0+ identity API).
-t, --sync-to <sync-to>
Sync To for containers, for multi-cluster replication.
-k, --sync-key <sync-key>
Sync Key for containers, for multi-cluster replication.
-m, --meta <name:value>
Sets a meta data item. This option may be repeated.
Example: -m Color:Blue -m Size:Large
-H, --header <header:value>
Adds a customized request header.
This option may be repeated. Example
-H "content-type:text/plain" -H "Content-Length: 4000"
[root@client ~]# swift post webapp
查看容器清单
bash
[root@client ~]# swift list --help
Usage: swift list [--long] [--lh] [--totals] [--prefix <prefix>]
[--delimiter <delimiter>] [--header <header:value>]
[--versions] [<container>]
Lists the containers for the account or the objects for a container.
Positional arguments:
[<container>] Name of container to list object in.
[root@client ~]# swift list
webapp
上传对象到容器
bash
[root@client ~]# swift upload --help
Usage: swift upload [--changed] [--skip-identical] [--segment-size <size>]
[--segment-container <container>] [--leave-segments]
[--object-threads <thread>] [--segment-threads <threads>]
[--meta <name:value>] [--header <header>] [--use-slo]
[--use-dlo] [--ignore-checksum] [--skip-container-put]
[--object-name <object-name>]
<container> <file_or_directory> [<file_or_directory>] [...]
Uploads specified files and directories to the given container.
Positional arguments:
<container> Name of container to upload to.
<file_or_directory> Name of file or directory to upload. Specify multiple
times for multiple uploads. If "-" is specified, reads
content from standard input (--object-name is required
in this case).
[root@client ~]# echo Hello World > Welcome.html
[root@client ~]# echo Test> test.html
[root@client ~]# swift upload webapp Welcome.html
Welcome.html
用户可使用 --object-name 选项来定义对象名称。
如果使用绝对路径来定义文件位置,对象名称将包含文件路径,包括斜杠字符 /。例如,以下命令将会上传 /etc/hosts 文件到 services 存储桶。
bash
[root@client ~]# swift upload webapp /etc/hostname
etc/hostname
查看容器中对象清单
bash
[root@client ~]# swift list webapp
Welcome.html
etc/hostname
下载容器中对象
bash
[root@client ~]# swift download --help
Usage: swift download [--all] [--marker <marker>] [--prefix <prefix>]
[--output <out_file>] [--output-dir <out_directory>]
[--object-threads <threads>] [--ignore-checksum]
[--container-threads <threads>] [--no-download]
[--skip-identical] [--remove-prefix]
[--version-id <version_id>]
[--header <header:value>] [--no-shuffle]
[<container> [<object>] [...]]
# 下载容器中所有对象
[root@client ~]# swift download webapp
etc/hostname [auth 0.005s, headers 0.009s, total 0.010s, 0.004 MB/s]
Welcome.html [auth 0.005s, headers 0.010s, total 0.010s, 0.002 MB/s]
# 下载容器中单个对象
[root@client ~]# swift download webapp Welcome.html
Welcome.html [auth 0.004s, headers 0.008s, total 0.009s, 0.003 MB/s]
删除容器中对象
bash
[root@client ~]# swift delete --help
Usage: swift delete [--all] [--leave-segments]
[--object-threads <threads>]
[--container-threads <threads>]
[--header <header:value>]
[--prefix <prefix>]
[--versions]
[<container> [<object>] [--version-id <version_id>] [...]]
Delete a container or objects within a container.
Positional arguments:
[<container>] Name of container to delete from.
[<object>] Name of object to delete. Specify multiple times
for multiple objects.
[root@client ~]# swift delete webapp etc/hostname
etc/hostname
删除容器
删除容器,将删除容器中所有对象和容器本身。
bash
[root@client ~]# swift delete webapp
Welcome.html
webapp
桶配额限制
环境准备
bash
[root@client ~]# swift post dbapp
[root@client ~]# swift upload --object-name hosts-1 dbapp /etc/hosts
针对用户进行配额限制
bash
# 对用户 swift 的配额限制
[root@ceph1 ~]# radosgw-admin quota enable --quota-scope=user --uid=swift
# 将用户 swift 可上传的对象数量设置为不超过 3
[root@ceph1 ~]# radosgw-admin quota set --quota-scope=user --uid=swift --max-objects=3
# 查看用户配额信息
[root@ceph1 ~]# radosgw-admin user info --uid=swift
......
"user_quota": {
"enabled": true,
"check_on_raw": false,
"max_size": -1,
"max_size_kb": 0,
"max_objects": 3
},
......
# 上传对象测试:当上传第4个对象时,客户端会收到报错。
[root@client ~]# swift upload --object-name hosts-2 dbapp /etc/hosts
[root@client ~]# swift upload --object-name hosts-3 dbapp /etc/hosts
[root@client ~]# swift upload --object-name hosts-4 dbapp /etc/hosts
Object PUT failed: http://ceph1.laogao.cloud:8080/swift/v1/dbapp/hosts-4 413 Request Entity Too Large b'QuotaExceeded' (txn: tx00000f89584465dec20ff-006603ab85-acdb-webapp)
Consider using the --segment-size option to chunk the object
# 将" --max-objects"设置为-1,取消对象数量配额的限制
[root@ceph1 ~]# radosgw-admin quota set --quota-scope=user --uid=swift --max-objects=-1
# 在客户端重新上传对象,则会顺利上传完成
[root@client ~]# swift upload --object-name hosts-4 dbapp /etc/hosts
思考:除了设置对象数量外,是否还有其他的配额限制方式?
回答:有,除了对象数量,还可以最大上传的容量进行限制。
针对桶进行配额限制
bash
# 启用对桶 dbapp 的配额限制
[root@ceph1 ~]# radosgw-admin quota enable --quota-scope=bucket --bucket=dbapp
# 将桶 dbapp 的最大容量设置为 10M:
[root@ceph1 ~]# radosgw-admin quota set --quota-scope=bucket --bucket=dbapp --max-size=10M
# 查看配额信息
[root@ceph1 ~]# radosgw-admin bucket stats
......
"bucket_quota": {
"enabled": true,
"check_on_raw": true,
"max_size": 10485760,
"max_size_kb": 10240,
"max_objects": -1
}
......
# 在客户端创建一个 6M 的文件 file,进行测试,具体命令为:
[root@client ~]# dd if=/dev/zero of=file bs=1M count=6
# 将文件 file 上传到容器(桶) dbapp 中,当上传第二个时,系统会返回报错
[root@client ~]# swift upload --object-name file-1 dbapp file
file-1
[root@client ~]# swift upload --object-name file-2 dbapp file
Object PUT failed: http://ceph1.laogao.cloud:8080/swift/v1/dbapp/file-2 413 Request Entity Too Large b'QuotaExceeded' (txn: tx000008b826fc312e77202-006603acbd-acdb-webapp)
Consider using the --segment-size option to chunk the object
# 将"--max-size"设置为-1,取消对象容量配额的限制
[root@ceph1 ~]# radosgw-admin quota set --quota-scope=bucket --bucket=dbapp --max-size=-1
# 在客户端重新上传对象,则会顺利上传完成
[root@client ~]# swift upload --object-name file-2 dbapp file
管理多站点对象存储网关
Ceph RADOS 网关支持多站点部署,实现在多个Ceph 存储集群之间自动复制对象数据。常见的用例是在地理上分隔的集群之间进行主动/主动复制,以便于灾难恢复。
多站点架构选择
- multi zone,域(realm)中具有一个区域组(zonegroup)和多个区域(zone)。每个区域由一个或多个 RADOS 网关以及关联一个独立的Ceph 存储集群。一个区域中存储的数据复制到该区域组中所有区域。如果有一个 zone 遭遇到灾难性故障,这可用于进行灾难恢复。
- multi zonegroup,域(realm)中有多个区域组,每个区域组具有一个或多个区域。用户可使用多区域组来管理一个地区中一个或多个区域内 RADOS 网关的地理位置。
- multi realm,配置使得同一硬件可用于支持不同区域组和区域之间通用的多个对象命名空间。
最小的 RADOS 网关多站点部署:
- 需要两个Ceph 存储集群,每个集群具有一个 RADOS 网关。
- 它们存在于同一域中,分配到相同的主区域组。
- 一个 RADOS 网关与该区域组中的主区域关联。另一个与该区域组中的独立次要区域关联。
多站点网关同步流程
RADOS 网关在所有主要区域组和次要区域组集合之间同步元数据和数据操作。
- **元数据操作与存储桶相关:**创建、删除、启用和禁用版本控制,以及管理用户。元主 (meta master) 位于主区域组中的主区域,负责管理元数据更新。
- 数据操作与对象相关。
多站点之间数据同步流程:
- 多站点初始配置后,RADOS 网关会在主区域和次要区域之间执行一次初始的完整同步。随后的更新是增量更新。
- **当 RADOS 网关将数据写入区域组中任何区域时,它会在其他区域组的所有区域之间同步这一数据。**当 RADOS 网关同步数据时,所有活跃的网关会更新数据日志并通知其他网关。
- 当 RADOS 网关因为存储桶或用户操作而同步元数据时,主网关会更新元数据日志并通知其他RADOS 网关。
多站点架构配置流程

部署多站点 RGW-实践
多站点架构如下图所示:

环境准备
部署好主集群和备集群。
配置主集群
bash
# 创建存储域
[root@ceph1 ~]# radosgw-admin realm create --rgw-realm=webapp --default
[root@ceph1 ~]# radosgw-admin zonegroup create --rgw-realm=webapp --rgw-zonegroup=video --master --default
[root@ceph1 ~]# radosgw-admin zone create --rgw-realm=webapp --rgw-zonegroup=video --rgw-zone=storage1 --master --default
[root@ceph1 ~]# radosgw-admin period update --rgw-realm=webapp --commit
# 创建 rgw 服务,这里创建3个(创建一个也够了)
[root@ceph1 ~]# ceph orch apply rgw webapp --placement="3 ceph1.laogao.cloud ceph2.laogao.cloud ceph3.laogao.cloud" --realm=webapp --zone=storage1 --port=8080
# 创建用于同步数据的系统用户:
[root@ceph1 ~]# radosgw-admin user create --uid=system-user --display-name=system-user --access-key=laogao@123 --secret=Huawei12#$ --system
# 将创建好的系统用户绑定给 master zone
[root@ceph1 ~]# radosgw-admin zone modify --rgw-realm=webapp --rgw-zonegroup=video --rgw-zone=storage1 --endpoints 'http://ceph1.laogao.cloud:8080,http://ceph2.laogao.cloud:8080,http://ceph3.laogao.cloud:8080' --access-key=laogao@123 --secret=Huawei12#$ --master --default
# 配置 RGW
[root@ceph1 ~]# ceph auth ls 2>/dev/null |grep 'rgw.*ceph'
client.rgw.webapp.ceph1.qqepfc
client.rgw.webapp.ceph2.iculct
client.rgw.webapp.ceph3.xbrkun
[root@ceph1 ~]# ceph config set client.rgw.webapp.ceph1.qqepfc rgw_realm webapp
[root@ceph1 ~]# ceph config set client.rgw.webapp.ceph1.qqepfc rgw_zonegroup video
[root@ceph1 ~]# ceph config set client.rgw.webapp.ceph1.qqepfc rgw_zone storage1
[root@ceph1 ~]# ceph config set client.rgw.webapp.ceph2.iculct rgw_realm webapp
[root@ceph1 ~]# ceph config set client.rgw.webapp.ceph2.iculct rgw_zonegroup video
[root@ceph1 ~]# ceph config set client.rgw.webapp.ceph2.iculct rgw_zone storage1
[root@ceph1 ~]# ceph config set client.rgw.webapp.ceph3.xbrkun rgw_realm webapp
[root@ceph1 ~]# ceph config set client.rgw.webapp.ceph3.xbrkun rgw_zonegroup video
[root@ceph1 ~]# ceph config set client.rgw.webapp.ceph3.xbrkun rgw_zone storage1
# 提交配置
[root@ceph1 ~]# radosgw-admin period update --commit
# 重启 RGW 服务
[root@ceph1 ~]# ceph orch restart rgw.webapp
配置备集群
bash
# 拉取主分区 realm 的配置信息:
[root@ceph4 ~]# radosgw-admin realm pull --url=http://ceph1.laogao.cloud:8080 --access-key=laogao@123 --secret=Huawei12#$
# 查看是否获取到 realm 和 zonegroup 的信息:
[root@ceph4 ~]# radosgw-admin realm list
[root@ceph4 ~]# radosgw-admin zonegroup list
# 获取 period 信息
[root@ceph4 ~]# radosgw-admin period pull --url=http://ceph1.laogao.cloud:8080 --access-key=laogao@123 --secret=Huawei12#$
# 检查是否获取
[root@ceph4 ~]# radosgw-admin period list
{
"periods": [
"df0d2416-7ee9-465c-a1e5-cebd19b7b468"
]
}
# 创建非 master zone
[root@ceph4 ~]# radosgw-admin zone create --rgw-zonegroup=video --rgw-zone=storage2 --endpoints "http://ceph4.laogao.cloud:8080, http://ceph5.laogao.cloud:8080, http://ceph6.laogao.cloud:8080" --access-key=laogao@123 --secret=Huawei12#$
# 创建 RGW
[root@ceph4 ~]# ceph orch apply rgw webapp --placement="3 ceph4.laogao.cloud ceph5.laogao.cloud ceph6.laogao.cloud" --realm=webapp --zone=storage2 --port=8080
# 设置 RGW 信息
[root@ceph4 ~]# ceph auth ls 2>/dev/null|grep 'rgw.*ceph'
client.rgw.webapp.ceph4.quzfrg
client.rgw.webapp.ceph5.catzsj
client.rgw.webapp.ceph6.aszklt
[root@ceph4 ~]# ceph config set client.rgw.webapp.ceph4.quzfrg rgw_realm webapp
[root@ceph4 ~]# ceph config set client.rgw.webapp.ceph4.quzfrg rgw_zonegroup video
[root@ceph4 ~]# ceph config set client.rgw.webapp.ceph4.quzfrg rgw_zone storage2
[root@ceph4 ~]# ceph config set client.rgw.webapp.ceph5.catzsj rgw_realm webapp
[root@ceph4 ~]# ceph config set client.rgw.webapp.ceph5.catzsj rgw_zonegroup video
[root@ceph4 ~]# ceph config set client.rgw.webapp.ceph5.catzsj rgw_zone storage2
[root@ceph4 ~]# ceph config set client.rgw.webapp.ceph6.aszklt rgw_realm webapp
[root@ceph4 ~]# ceph config set client.rgw.webapp.ceph6.aszklt rgw_zonegroup video
[root@ceph4 ~]# ceph config set client.rgw.webapp.ceph6.aszklt rgw_zone storage2
# 更新 realm
[root@ceph4 ~]# radosgw-admin period update --rgw-realm=webapp --commit
# 重启 RGW 服务
[root@ceph4 ~]# ceph orch restart rgw.webapp
测试
bash
# 查看同步状态
[root@ceph4 ~]# radosgw-admin sync status
realm f1ea35c6-c4b5-46b4-9e4b-62e2c6301217 (webapp)
zonegroup c4f0f536-6651-43f0-b1f3-a1fbaf55775d (video)
zone 9d1339a8-6570-4ad6-88de-172cf3899332 (storage2)
metadata sync syncing
full sync: 0/64 shards
incremental sync: 64/64 shards
metadata is caught up with master
data sync source: 9366405a-6d9b-4897-97d0-9e139304fe64 (storage1)
syncing
full sync: 0/128 shards
incremental sync: 128/128 shards
data is caught up with source
# 对象同步测试---有问题
[root@client ~]# source swift.rc
[root@client ~]# swift post dbapp
[root@client ~]# swift upload --object-name hosts-from-primary dbapp /etc/hosts
# 查看备集群对象(需要稍微等待几秒)
[root@client ~]# source swift-slave.rc
[root@client ~]# swift list dbapp
hosts-from-primary
管理区域故障转移
在多站点部署中,主区域不可用时,次要区域可以继续为读取和写入请求服务。
不过,因为主区域不可用,所以用户无法创建新的存储桶和用户。如果主区域没有立即恢复,则需要对其中一个次要区域升级,以替代主区域。
具体过程如下:
-
将主区域指定为次要区域。
bash[root@ceph4 ~]# radosgw-admin zone modify --master --rgw-zone=storage2 -
更新主区域组端点。
bash[root@ceph4 ~]# radosgw-admin zonegroup modify --rgw-zonegroup=video \ --endpoints=http://ceph4.laogao.cloud:8080 -
提交更改。
bash[root@ceph4 ~]# radosgw-admin period update --commit [root@ceph4 ~]# radosgw-admin sync status realm f1ea35c6-c4b5-46b4-9e4b-62e2c6301217 (webapp) zonegroup c4f0f536-6651-43f0-b1f3-a1fbaf55775d (video) zone 9d1339a8-6570-4ad6-88de-172cf3899332 (storage2) metadata sync no sync (zone is master) data sync source: 9366405a-6d9b-4897-97d0-9e139304fe64 (storage1) syncing full sync: 0/128 shards incremental sync: 128/128 shards data is caught up with source
radosgw-admin 命令
realm 子命令
bash
realm create create a new realm
realm rm remove a realm
realm get show realm info
realm get-default get default realm name
realm list list realms
realm list-periods list all realm periods
realm rename rename a realm
realm set set realm info (requires infile)
realm default set realm as default
realm pull pull a realm and its current period
zonegroup 子命令
zonegroup add add a zone to a zonegroup
zonegroup create create a new zone group info
zonegroup default set default zone group
zonegroup delete delete a zone group info
zonegroup get show zone group info
zonegroup modify modify an existing zonegroup
zonegroup set set zone group info (requires infile)
zonegroup rm remove a zone from a zonegroup
zonegroup rename rename a zone group
zonegroup list list all zone groups set on this cluster
zonegroup placement list list zonegroup's placement targets
zonegroup placement get get a placement target of a specific zonegroup
zonegroup placement add add a placement target id to a zonegroup
zonegroup placement modify modify a placement target of a specific zonegroup
zonegroup placement rm remove a placement target from a zonegroup
zonegroup placement default set a zonegroup's default placement target
zone 子命令
zone create create a new zone
zone rm remove a zone
zone get show zone cluster params
zone modify modify an existing zone
zone set set zone cluster params (requires infile)
zone list list all zones set on this cluster
zone rename rename a zone
zone placement list list zone's placement targets
zone placement get get a zone placement target
zone placement add add a zone placement target
zone placement modify modify a zone placement target
zone placement rm remove a zone placement target
period 子命令
period rm remove a period
period get get period info
period get-current get current period info
period pull pull a period
period push push a period
period list list all periods
period update update the staging period
period commit commit the staging period
常用选项
bash
--uid=<id> user id
--new-uid=<id> new user id
--subuser=<name> subuser name
--email=<email> user's email address
--display-name=<name> user's display name
--system set the system flag on the user
--access-key=<key> S3 access key
--secret/--secret-key=<key> specify secret key
--gen-access-key generate random access key (for S3)
--gen-secret generate random secret key
--key-type=<type> key type, options are: swift, s3
--bucket=<bucket> Specify the bucket name.
--bucket-id=<bucket-id> bucket id
--bucket-new-name=<bucket>
for bucket link: optional new name
--pool=<pool> Specify the pool name.
--object=<object> object name
--period=<id> period id
--url=<url> url for pushing/pulling period/realm
--epoch=<number> period epoch
--commit commit the period during 'period update'
--default set entity (realm, zonegroup, zone) as default
--master set as master
--master-zone=<id> master zone id
--rgw-realm=<name> realm name
--realm-id=<id> realm id
--realm-new-name=<name> realm new name
--rgw-zonegroup=<name> zonegroup name
--zonegroup-id=<id> zonegroup id
--zonegroup-new-name=<name>
zonegroup new name
--endpoints=<list> zone endpoints
--rgw-zone=<name> name of zone in which radosgw is running
--zone-id=<id> zone id
--zone-new-name=<name> zone new name
--source-zone specify the source zone (for data sync)
第 8 章 Ceph 分布式存储 文件系统存储管理
介绍 CephFS
介绍 CephFS
-
Ceph 文件系统 (CephFS) ,构建在 Ceph 存储之上,是一种兼容 POSIX 的文件系统。
-
与 RBD 和 RGW 类似,CephFS 也会作为 librados 的原生接口来实施。
-
Ceph 支持在一个集群中运行多个活动 MDS,以提高元数据性能。为保持高可用性,还可配置备用 MDS,以便在任何活动 MDS 出现故障时,接管其任务。
-
Ceph 支持在一个集群中部署多个活动的 CephFS 文件系统。部署多个 CephFS 文件系统需要运行多个 MDS 守护进程。
不同存储方式对比
- **基于文件的存储:**可以像传统文件系统一样整理用户的数据,并带有目录树层次结构。数据会保存在文件中,文件会有一个名称并包含相关元数据,如修改时间戳、所有者和访问权限。
- 基于块的存储:提供像磁盘一样运作的存储卷,整理到大小相等的区块中。通常而言,基于块的存储卷要么通过文件系统进行格式化,要么是像数据库一样可直接读写的应用。
- **基于对象的存储:**支持将任意数据和元数据作为一个标有唯一标识符的单元存储在扁平存储池中。用户会使用 API 来存储和检索数据,而不会作为块或在文件系统层次结构中访问数据。
元数据服务器
元数据服务器 (MDS) 负责:
- 管理目录层次结构和文件元数据(如所有者、时间戳和权限模式等),提供 CephFS 客户端访问 RADOS 对象所需的信息。
- 访问客户端缓存,并维护客户端缓存一致性。
MDS 以两种运行模式:
- 活动 MDS, 负责管理 CephFS 文件系统上的元数据。
- 备用 MDS, 充当备份,并会在活动 MDS 无响应时切换到活动模式。
CephFS 文件系统至少需要一个活跃的 MDS 服务,最好再部署一个备用 MDS 以确保可用性。
MDS 配置选项:
-
MDS 等级,设置集群中活动 MDS 守护进程的最大数量,由 max_mds 定义。MDS 守护进程在启动时没有等级,MON 守护进程负责为它们分配1个等级,也就是集群中只有一个活动 MDS。
-
卷、子卷和子卷组:
-
CephFS 卷,对应一个 CephFS 文件系统。
-
**CephFS 子卷,对应 CephFS 文件系统子目录。**在创建子卷时,用户可指定更细致的权限管理,如子卷的 UID、GID、文件模式、大小和子卷组。
-
CephFS 子卷组,对应一组子卷。
-
-
**文件系统关联性,将用户的 CephFS 文件系统配置为首选某一个 MDS。**例如,用户可配置为首选在速度更快的服务器上运行的 MDS。文件系统关联性通过 mds_join_fs 选项进行配置。
-
MDS 缓存大小限制 ,通过 mds_cache_memory_limit 选项限制最大内存,mds_cache_size 选项定义最大索引节点数,以限制 MDS 缓存的大小。
-
**配额,配置用户的 CephFS 文件系统,以限制使用配额存储的字节数或文件数。**FUSE 和Kernel 客户端都支持在挂载 CephFS 文件系统时检查配额。这些客户端还负责在用户达到配额限值时,停止向 CephFS 文件系统写入数据。使用 setfattr 命令的 ceph.quota.max_bytes 和ceph.quota.max_files 选项可设置限值。
客户端访问 CephFS 过程
- CephFS 客户端首先会联系 MON 进行身份验证并检索集群映射。
- 完成上一步后,客户端从集群映射中获取到活动 MDS信息。
- 客户端向活动 MDS 索取文件元数据。
- 然后客户端直接与 OSD 通信,使用元数据来访问文件或目录。
部署 CephFS
部署 CephFS 方法:
- 手动部署,步骤多,可以控制每个步骤。
- 卷部署,步骤少,简单方便,无法控制每个步骤。
手动部署 CephFS
部署 CephFS 流程:
- 创建所需池
- 创建 CephFS 文件系统
- 部署 MDS 守护进程
创建 CephFS
要创建 CephFS 文件系统,首先至少要创建两个池,一个用于存储 CephFS 数据,另一个用于存储 CephFS 元数据。这两个池的默认名称分别为 cephfs_data 和 cephfs_meta。
bash
[root@ceph1 ~]# ceph osd pool create cephfs.cephfs1.data.1
[root@ceph1 ~]# ceph osd pool create cephfs.cephfs1.meta
元数据池用于存储文件的位置信息,所以为此池设置更高的复本级别,以避免出现数据错误,导致数据无法访问。CephFS 默认使用复制数据池,也支持使用纠删代码数据池。
bash
[root@ceph1 ~]# ceph osd pool set cephfs.cephfs1.meta size 3
使用 ceph fs new 命令来创建文件系统:
bash
[root@ceph1 ~]# ceph fs new cephfs1 cephfs.cephfs1.meta cephfs.cephfs1.data.1
要将现有池添加为 CephFS 文件系统中的数据池,请使用 ceph fs add_data_pool。
bash
[root@ceph1 ~]# ceph osd pool create cephfs.cephfs1.data.2
[root@ceph1 ~]# ceph fs add_data_pool cephfs1 cephfs.cephfs1.data.2
部署 MDS 服务
bash
[root@ceph1 ~]# ceph orch apply mds cephfs1 --placement="3 ceph1.laogao.cloud ceph2.laogao.cloud ceph3.laogao.cloud"
验证 MDS 服务部署
bash
# 查看文件系统清单
[root@ceph1 ~]# ceph fs ls
name: cephfs1, metadata pool: cephfs.cephfs1.meta, data pools: [cephfs.cephfs1.data.1 cephfs.cephfs1.data.2 ]
# 查看文件系统状态
[root@ceph1 ~]# ceph fs status
cephfs1 - 0 clients
=======
RANK STATE MDS ACTIVITY DNS INOS DIRS CAPS
0 active cephfs1.ceph1.hazpoq Reqs: 0 /s 10 13 12 0
POOL TYPE USED AVAIL
cephfs.cephfs1.meta metadata 96.0k 56.1G
cephfs.cephfs1.data.1 data 0 56.1G
cephfs.cephfs1.data.2 data 0 56.1G
STANDBY MDS
cephfs1.ceph3.kjpzae
cephfs1.ceph2.fdudvc
MDS version: ceph version 16.2.15 (618f440892089921c3e944a991122ddc44e60516) pacific (stable)
# 查看池空间使用状态
[root@ceph1 ~]# ceph df
--- RAW STORAGE ---
CLASS SIZE AVAIL USED RAW USED %RAW USED
hdd 180 GiB 177 GiB 2.6 GiB 2.6 GiB 1.42
TOTAL 180 GiB 177 GiB 2.6 GiB 2.6 GiB 1.42
--- POOLS ---
POOL ID PGS STORED OBJECTS USED %USED MAX AVAIL
device_health_metrics 1 1 0 B 0 0 B 0 56 GiB
cephfs.cephfs1.data.1 3 32 0 B 0 0 B 0 56 GiB
cephfs.cephfs1.meta 4 32 2.3 KiB 22 96 KiB 0 56 GiB
cephfs.cephfs1.data.2 5 32 0 B 0 0 B 0 56 GiB
# 查看mds服务状态
[root@ceph1 ~]# ceph mds stat
cephfs1:1 {0=cephfs1.ceph1.hazpoq=up:active} 2 up:standby
# 查看mds服务守护进程
[root@ceph1 ~]# ceph orch ls mds
NAME PORTS RUNNING REFRESHED AGE PLACEMENT
mds.cephfs1 3/3 6m ago 6m ceph1.laogao.cloud;ceph2.laogao.cloud;ceph3.laogao.cloud;count:3
删除 CephFS
删除流程如下:
- 删除服务
- 删除文件系统
- 删除池
删除过程如下:
bash
# 删除服务
[root@ceph1 ~]# ceph orch rm mds.cephfs1
Removed service mds.cephfs1
# 如果需要删除 CephFS,请先备份所有数据,
# 因为删除 CephFS 文件系统会破坏该文件系统上存储的所有数据。
# 要删除 CephFS,首先要将其标记为 down
[root@ceph1 ~]# ceph fs set cephfs1 down true
cephfs1 marked down.
# 然后删除 CephFS
[root@ceph1 ~]# ceph fs rm cephfs1 --yes-i-really-mean-it
# 删除池
[root@ceph1 ~]# ceph config set mon mon_allow_pool_delete true
[root@ceph1 ~]# ceph osd pool rm cephfs.cephfs1.meta cephfs.cephfs1.meta --yes-i-really-really-mean-it
[root@ceph1 ~]# ceph osd pool rm cephfs.cephfs1.data.1 cephfs.cephfs1.data.1 --yes-i-really-really-mean-it
[root@ceph1 ~]# ceph osd pool rm cephfs.cephfs1.data.2 cephfs.cephfs1.data.2 --yes-i-really-really-mean-it
卷部署 CephFS
创建 CephFS
bash
# 部署三个实例
[root@ceph1 ~]# ceph fs volume create cephfs2 --placement="3 ceph1.laogao.cloud ceph2.laogao.cloud ceph3.laogao.cloud"
# 查看文件系统清单
[root@ceph1 ~]# ceph fs ls
name: cephfs2, metadata pool: cephfs.cephfs2.meta, data pools: [cephfs.cephfs2.data ]
# 查看mds服务状态
[root@ceph1 ~]# ceph mds stat
cephfs2:1 {0=cephfs2.ceph3.irxxar=up:active} 2 up:standby
# 查看mds服务守护进程
[root@ceph1 ~]# ceph orch ls mds
NAME PORTS RUNNING REFRESHED AGE PLACEMENT
mds.cephfs2 3/3 58s ago 62s ceph1.laogao.cloud;ceph2.laogao.cloud;ceph3.laogao.cloud;count:3
删除 CephFS
bash
[root@ceph1 ~]# ceph fs volume ls
[
{
"name": "cephfs2"
}
]
[root@ceph1 ~]# ceph fs volume rm cephfs2 --yes-i-really-mean-it
metadata pool: cephfs.cephfs2.meta data pool: ['cephfs.cephfs2.data'] removed
[root@ceph1 ~]# ceph fs ls
No filesystems enabled
挂载 CephFS 文件系统
环境准备
创建 cephfs1 和 cephfs2。
bash
[root@ceph1 ~]# ceph fs volume create cephfs1 --placement="3 ceph1.laogao.cloud ceph2.laogao.cloud ceph3.laogao.cloud"
[root@ceph1 ~]# ceph fs volume create cephfs2 --placement="3 ceph1.laogao.cloud ceph2.laogao.cloud ceph3.laogao.cloud"
CephFS 挂载方式
用户可使用以下方式挂载 CephFS 文件系统:
- Kernel 挂载,要求 Linux 内核版本达到 4 或以上,从 RHEL 8 开始可用。对于之前的内核版本,请改用FUSE 客户端。
- FUSE 挂载。
这两个挂载方式各有优势和劣势:
- Kernel 挂载,不支持配额,但速度可能较快。
- FUSE 挂载,支持配额和 ACL。 ACL 功能需要在挂载时明确指定该功能以启用。
CephFS 挂载用户
通过 ceph fs authorize 命令,可为 CephFS 文件系统中的不同用户和文件夹提供精细的访问控制。
CephFS 文件系统支持不同访问选项:
- **r:对指定文件夹的读取权限。**如果未指定其他限制,则会向子文件夹授予读取权限。
- **w:对指定文件夹的写入权限。**如果未指定其他限制,则会向子文件夹授予写入权限。
- p:除了 r 和 w 功能外,客户端还需要 p 选项才能使用布局或配额。
- s:除了 r 和 w 功能外,客户端还需要 s 选项才能创建快照。
示例1:允许用户对 / 文件夹具备读取、写入、配额和快照权限,并保存用户凭据。
bash
[root@ceph1 ~]# ceph fs authorize cephfs1 client.cephfs1-all-user / rwps > /etc/ceph/ceph.client.cephfs1-all-user.keyring
示例2:允许用户读取 root 文件夹,并提供对 /dir2 文件夹的读取、写入,并保存用户凭据。
bash
[root@ceph1 ~]# ceph fs authorize cephfs1 client.cephfs1-restrict-user / r /dir2 rw > /etc/ceph/ceph.client.cephfs1-restrict-user.keyring
CephFS 客户端挂载准备
要挂载基于 CephFS 的文件系统,请验证客户端主机是否满足以下条件:
-
安装 ceph-common 软件包。对于 FUSE 客户端,还要安装 ceph-fuse 软件包。
bash[root@client ~]# dnf install -y ceph-common -
复制 Ceph 配置文件到客户端。
bash[root@ceph1 ~]# scp /etc/ceph/ceph.conf root@client:/etc/ceph/ceph.conf -
将用户keyring复制到客户端主机上的 /etc/ceph 文件夹。
bash[root@ceph1 ~]# scp /etc/ceph/ceph.client.{cephfs1-all-user,cephfs1-restrict-user}.keyring root@client:/etc/ceph/
为了方便管理集群,我们将admin凭据复制到client。
bash
[root@ceph1 ~]# scp /etc/ceph/ceph.client.admin.keyring root@client:/etc/ceph/
使用 Kernel 挂载 CephFS
挂载 CephFS
使用 mount.ceph 命令挂载文件系统:
bash
# mount.ceph [src] [mount-point] [-n] [-v] [-o ceph-options]
# 或者
# mount -t ceph [src] [mount-point] [-n] [-v] [-o ceph-options]
用户可以指定逗号分隔的多个 MON 来挂载设备。标准端口 (6789) 为默认值,用户也可在各个MON 名称的后面添加冒号和非标准端口号。建议指定多个 MON,以防文件系统挂载时有些 MON 处于脱机状态。
bash
[root@client ~]# mount.ceph
usage: mount.ceph [src] [mount-point] [-n] [-v] [-o ceph-options]
options:
-h: Print this help
-n: Do not update /etc/mtab
-v: Verbose
ceph-options: refer to mount.ceph(8)
使用 CephFS Kernel 客户端时,可用选项有:
- fs=fs-name,指定要挂载的 CephFS 文件系统名称。未提供值时,它会使用默认文件系统。
- name=name,指定Cephx 客户端 ID。默认为 guest。
- secret=secret_value,指定客户端的机密密钥的值。
- secretfile=secret_key_file,指定包含此客户端机密密钥的文件的路径。
- rsize=bytes,指定最大读取大小,以字节为单位。
- wsize=bytes,指定最大写入大小,以字节为单位。默认为不写入。
示例1:使用不受限账户挂载 cephfs 文件系统。
bash
[root@client ~]# mkdir /mnt/cephfs1
[root@client ~]# mount.ceph ceph1.laogao.cloud:/ /mnt/cephfs1 -o name=cephfs1-all-user,fs=cephfs1
[root@client ~]# df -h /mnt/cephfs1
Filesystem Size Used Avail Use% Mounted on
192.168.108.11:/ 57G 0 57G 0% /mnt/cephfs1
[root@client ~]# mkdir /mnt/cephfs1/{dir1,dir2}
[root@client ~]# echo Hello World > /mnt/cephfs1/dir1/welcome.txt
[root@client ~]# dd if=/dev/zero of=/mnt/cephfs1/dir1/file-100M bs=1M count=100
[root@client ~]# tree /mnt/cephfs1
/mnt/cephfs1
├── dir1
│ ├── file-100M
│ └── welcome.txt
└── dir2
2 directories, 2 files
# 3副本池,创建100M文件,文件系统空间减少100M
[root@client ~]# df -h /mnt/cephfs1
Filesystem Size Used Avail Use% Mounted on
192.168.108.11:/ 57G 100M 56G 1% /mnt/cephfs1
# 3副本池,创建100M文件,cephfs.cephfs_data 池系统空间使用300M
[root@client ~]# ceph fs status
cephfs1 - 1 clients
=======
RANK STATE MDS ACTIVITY DNS INOS DIRS CAPS
0 active cephfs1.ceph1.hpwqgm Reqs: 0 /s 14 17 14 5
POOL TYPE USED AVAIL
cephfs.cephfs1.meta metadata 192k 55.9G
cephfs.cephfs1.data data 300M 55.9G
cephfs2 - 0 clients
=======
RANK STATE MDS ACTIVITY DNS INOS DIRS CAPS
0 active cephfs2.ceph3.nwbhbl Reqs: 0 /s 10 13 12 0
POOL TYPE USED AVAIL
cephfs.cephfs2.meta metadata 96.0k 55.9G
cephfs.cephfs2.data data 0 55.9G
STANDBY MDS
cephfs1.ceph2.notedt
cephfs1.ceph3.qxjqfe
cephfs2.ceph2.hjrvmu
cephfs2.ceph1.yursdd
MDS version: ceph version 16.2.15 (618f440892089921c3e944a991122ddc44e60516) pacific (stable)
# 卸载文件系统
[root@client ~]# umount /mnt/cephfs1
示例2:使用受限账户挂载 cephfs 文件系统。
bash
# 挂载
[root@client ~]# mount.ceph ceph1.laogao.cloud:/ /mnt/cephfs1 -o name=cephfs1-restrict-user,fs=cephfs1
# 验证权限
[root@client ~]# touch /mnt/cephfs1/dir1/cephfs1-restrict-user-file1
touch: cannot touch '/mnt/cephfs1/dir1/cephfs1-restrict-user-file1': Permission denied
[root@client ~]# touch /mnt/cephfs1/dir2/cephfs1-restrict-user-file1
[root@client ~]# tree /mnt/cephfs1/
/mnt/cephfs1/
├── dir1
│ ├── file-100M
│ └── welcome.txt
└── dir2
└── cephfs1-restrict-user-file1
2 directories, 3 files
# 卸载文件系统
[root@client ~]# umount /mnt/cephfs1
挂载特定子目录
通过 CephFS Kernel 客户端,用户可从 CephFS 文件系统挂载特定子目录。
本例从 CephFS 文件系统的 root 中挂载了名为 /dir2 的目录:
bash
[root@client ~]# mount -t ceph ceph1.laogao.cloud:/dir2 /mnt/cephfs1 -o name=cephfs1-restrict-user,fs=cephfs1
[root@client ~]# touch /mnt/cephfs1/cephfs1-restrict-user-file2
[root@client ~]# tree /mnt/cephfs1/
/mnt/cephfs1/
├── cephfs1-restrict-user-file1
└── cephfs1-restrict-user-file2
0 directories, 2 files
# 卸载文件系统
[root@client ~]# umount /mnt/cephfs1
永久挂载文件系统
要使用Kernel 客户端永久挂载 CephFS 文件系统,可以将以下格式条目添加到 /etc/fstab 文件中:
示例:(看看语法,不用操作)
bash
ceph1.laogao.cloud:/dir2 /mnt/cephfs1 ceph name=cephfs1-restrict-user,fs=cephfs1,_netdev 0 0
使用 FUSE 挂载 CephFS
卸载之前挂载的:
bash
[root@client ~]# umount /mnt/cephfs1
以非 root 用户身份使用 FUSE 客户端时,需在 /etc/fuse.conf 配置文件中添加 user_allow_other。
使用 FUSE 挂载 CephFS,需要额外安装ceph-fuse软件:
bash
[root@client ~]# dnf install -y ceph-fuse
挂载 CephFS
使用 FUSE 客户端挂载 CephFS 文件系统语法:
bash
[root@client ~]# ceph-fuse --help
usage: ceph-fuse [-n client.username] [-m mon-ip-addr:mon-port] <mount point> [OPTIONS]
--client_mountpoint/-r <sub_directory>
use sub_directory as the mounted root, rather than the full Ceph tree.
usage: ceph-fuse [options] <mountpoint>
FUSE options:
-h --help print help
-V --version print version
-d -o debug enable debug output (implies -f)
-f foreground operation
-s disable multi-threaded operation
-o clone_fd use separate fuse device fd for each thread
(may improve performance)
-o max_idle_threads the maximum number of idle worker threads
allowed (default: 10)
-o allow_other allow access by all users
-o allow_root allow access by root
-o auto_unmount auto unmount on process termination
--conf/-c FILE read configuration from the given configuration file
--id ID set ID portion of my name
--name/-n TYPE.ID set name
--cluster NAME set cluster name (default: ceph)
--setuser USER set uid to user or uid (and gid to user's gid)
--setgroup GROUP set gid to group or gid
--version show version and quit
示例:
bash
[root@client ~]# ceph-fuse -n client.cephfs1-restrict-user /mnt/cephfs1
2025-08-26T10:13:17.021+0800 7f33347023c0 -1 init, newargv = 0x560cab629680 newargc=13
2025-08-26T10:13:17.021+0800 7f33347023c0 -1 init, args.argv = 0x560cab629830 args.argc=4
ceph-fuse[14462]: starting ceph client
ceph-fuse[14462]: starting fuse
[root@client ~]# tree /mnt/cephfs1
/mnt/cephfs1
├── dir1
│ ├── file-100M
│ └── welcome.txt
└── dir2
├── cephfs1-restrict-user-file1
└── cephfs1-restrict-user-file2
2 directories, 4 files
# 卸载文件系统
[root@client ~]# umount /mnt/cephfs1
挂载特定子目录
CephFS FUSE 客户端默认会挂载所访问文件系统的 root 目录 (/)。用户可使用 ceph-fuse -r directory 命令挂载特定目录。如果 CephFS 卷中不存在该目录,此操作会失效。
bash
[root@client ~]# ceph-fuse -n client.cephfs1-restrict-user -r /dir2 /mnt/cephfs1/
2025-08-26T10:17:20.933+0800 7f46882233c0 -1 init, newargv = 0x562a8edc7c50 newargc=13
2025-08-26T10:17:20.933+0800 7f46882233c0 -1 init, args.argv = 0x562a8edc7e00 args.argc=4
ceph-fuse[16731]: starting ceph client
ceph-fuse[16731]: starting fuse
[root@client ~]# tree /mnt/cephfs1/
/mnt/cephfs1/
├── cephfs1-restrict-user-file1
└── cephfs1-restrict-user-file2
0 directories, 2 files
# 卸载文件系统
[root@client ~]# umount /mnt/cephfs1
用户在配置多个 CephFS 文件系统时,CephFS FUSE 客户端会挂载默认的 CephFS 文件系统。要挂载特定文件系统,使用 --client_fs 选项。
ceph-fuse -n client.cephfs1-restrict-user -r /dir2 --client_fs cephfs1 /mnt/cephfs1
永久挂载文件系统
要使用 FUSE 客户端永久挂载 CephFS 文件系统,可以将以下条目添加到 /etc/fstab 文件中:
bash
ceph1.laogao.cloud /mnt/cephfs1 fuse.ceph ceph.id=cephfs1-restrict-user,_netdev 0 0
**注意:**ceph-fuse方式持久化挂载,不支持挂载特定子目录。
管理 CephFS
实验环境准备
使用受限账户挂载 cephfs。
bash
[root@client ~]# mount.ceph ceph1.laogao.cloud:/dir2 /mnt/cephfs1 -o name=cephfs1-restrict-user,fs=cephfs1
管理快照
CephFS 默认会启用快照功能,这些快照存储在名为 .snap 的隐藏目录中。
启停快照功能
使用 ceph fs set 命令停用特定 CephFS 文件系统快照功能。
bash
[root@client ~]# ceph fs set cephfs1 allow_new_snaps false
disabled new snapshots
使用 ceph fs set 命令启用特定 CephFS 文件系统快照功能。
bash
[root@client ~]# ceph fs set cephfs1 allow_new_snaps true
enabled new snapshots
创建快照
**若要创建快照,在 .snap 目录中创建一个子目录。**快照名称就是新子目录名称。此快照包含 CephFS 文件系统中所有当前文件的副本。
普通用户是没有创建快照权限的。
bash
[root@client ~]# mkdir /mnt/cephfs1/.snap/snap
mkdir: cannot create directory '/mnt/cephfs1/.snap/snap': Permission denied
[root@client ~]# ceph auth get client.cephfs1-restrict-user
[client.cephfs1-restrict-user]
key = AQAWEK1owPSzMhAACJqg9ZF8FBv28UdwTdEu4Q==
caps mds = "allow r fsname=cephfs1, allow rw fsname=cephfs1 path=/dir2"
caps mon = "allow r fsname=cephfs1"
caps osd = "allow rw tag cephfs data=cephfs1"
exported keyring for client.cephfs1-restrict-user
授权客户端s权限为 CephFS 文件系统制作快照。
bash
[root@client ~]# ceph auth caps client.cephfs1-restrict-user \
mds "allow r fsname=cephfs1, allow rws fsname=cephfs1 path=/dir2" \
mon "allow r fsname=cephfs1" \
osd "allow rw tag cephfs data=cephfs1"
重新挂载,再次创建快照
bash
[root@client ~]# umount /mnt/cephfs1
[root@client ~]# mount.ceph ceph1.laogao.cloud:/dir2 /mnt/cephfs1 -o name=cephfs1-restrict-user
[root@client ~]# mkdir /mnt/cephfs1/.snap/snap
[root@client ~]# ls /mnt/cephfs1/.snap/snap/
cephfs1-restrict-user-file1 cephfs1-restrict-user-file2
使用快照恢复文件
要恢复文件,可将其从快照目录复制到另一常规目录中。
bash
[root@client ~]# mkdir /restore
[root@client ~]# cp /mnt/cephfs1/.snap/snap/cephfs1-restrict-user-file1 /restore/
若要从 .snap 目录树中完整恢复快照,可将普通条目替换为所选快照中的副本。
bash
[root@client ~]# rsync -a /mnt/cephfs1/.snap/snap/ /restore/
删除快照
若要丢弃快照,可在 .snap 中删除对应的目录。即使快照目录不为空,rmdir 命令也会成功,无
需使用递归 rm 命令。
bash
[root@client ~]# rmdir /mnt/cephfs1/.snap/snap/
管理 CephFS Mirror
CephFS Mirror 是 CephFS 的一个关键功能,用于在两个或多个 Ceph 集群之间实现文件系统的异步复制(镜像),主要用于灾难恢复和数据备份。
CephFS Mirror 功能是从 Ceph Pacific (v16.2.0) 版本开始支持的。
CephFS Mirror 主要特点
- 异步复制:CephFS Mirror 是异步的,数据会定期从源集群复制到目标集群。
- 基于快照:CephFS Mirror 依赖于 CephFS 的快照功能,通过快照来捕获文件系统的变化并复制到目标集群。
- 多集群支持:支持将数据从一个 CephFS 集群复制到多个目标集群。
- 增量复制:仅复制文件系统中发生变化的部分,减少带宽和存储开销。
实施 CephFS Mirror 前提
- 源集群和目标集群都必须运行 Ceph Pacific (v16.2.0) 或更高版本。
- 需要在源集群和目标集群上配置 CephFS 文件系统。
- 需要在源集群和目标集群之间建立可靠的网络连接。
同步原理

源集群守护进程ceph-mirror使用自己的ceph账户,读取自己集群中cephfs数据,然后使用目标集群的账户凭据将自己集群中cephfs变更数据写入目标集群。
CephFS 镜像功能基于快照实现:
- 第一次快照同步,需要将数据从源集群批量传输到远程集群。
- 然后,镜像守护进程识别本地快照之间修改的文件,并将这些修改的文件同步到远程集群。
对于目录中给定的快照,cephfs-mirror守护进程将依赖 readdir diff 来识别目录树中的更改。差异应用于远程文件系统中的目录,从而仅同步两个快照之间已更改的文件。
环境准备
bash
# 源集群创建Cephfs
[root@ceph1 ~]# ceph fs volume create cephfs --placement="1 ceph1.laogao.cloud"
# 目标群创建Cephfs
[root@ceph4 ~]# ceph fs volume create cephfs --placement="1 ceph4.laogao.cloud"
具体操作步骤如下:
-
在源集群上部署 CephFS 镜像守护进程。
bash[root@ceph1 ~]# ceph orch apply cephfs-mirror ceph1.laogao.cloud Scheduled cephfs-mirror update... [root@ceph1 ~]# ceph orch ls cephfs-mirror NAME RUNNING REFRESHED AGE PLACEMENT cephfs-mirror 1/1 11s ago 18s ceph1.laogao.cloud # 部署 CephFS 镜像守护进程,将会创建一个 cephfs-mirror Ceph 用户 [root@ceph1 ~]# ceph auth ls | grep cephfs-mirror installed auth entries: client.cephfs-mirror.ceph1.yuxcon caps: [mon] profile cephfs-mirror [root@ceph1 ~]# ceph auth get client.cephfs-mirror.ceph1.yuxcon [client.cephfs-mirror.ceph1.yuxcon] key = AQChjK1oOu2WNRAAX7ZFmilo3IMq+/X+K1TWrA== caps mds = "allow r" caps mgr = "allow r" caps mon = "profile cephfs-mirror" caps osd = "allow rw tag cephfs metadata=*, allow r tag cephfs data=*" exported keyring for client.cephfs-mirror.ceph1.yuxcon -
在目标集群上创建Ceph用户。
bash[root@ceph4 ~]# ceph fs authorize cephfs client.cephfs-mirror / rwps [client.cephfs-mirror] key = AQDpjq1ohezRExAA/x2+xHvjgFQm4SJOllbShw== [root@ceph4 ~]# ceph auth get client.cephfs-mirror [client.cephfs-mirror] key = AQDpjq1ohezRExAA/x2+xHvjgFQm4SJOllbShw== caps mds = "allow rwps fsname=cephfs" caps mon = "allow r fsname=cephfs" caps osd = "allow rw tag cephfs data=cephfs" exported keyring for client.cephfs-mirror -
在源集群上启用 mirroring 模块。
bash[root@ceph1 ~]# ceph mgr module enable mirroring -
在源集群特定文件系统上启用 mirroring 功能。
bash[root@ceph1 ~]# ceph fs snapshot mirror enable cephfs -
在目标集群上启用 mirroring 模块。
bash[root@ceph4 ~]# ceph mgr module enable mirroring -
在目标集群节点上创建对等引导。
语法:
$ ceph fs snapshot mirror peer_bootstrap create fs_name client_entity site-name说明:
fs_name,是目标 cephfs 文件系统名称。client_entity,是目标集群Ceph账户,用来同步远端的CephFS。site_name,是用户自定义的目标集群名称。
示例:
bash[root@ceph4 ~]# ceph fs snapshot mirror peer_bootstrap create cephfs client.cephfs-mirror backup {"token": "eyJmc2lkIjogImFhMDUyNzY0LTdmNGUtMTFmMC1hYTM5LTAwMGMyOTZiNGY4ZSIsICJmaWxlc3lzdGVtIjogImNlcGhmcyIsICJ1c2VyIjogImNsaWVudC5jZXBoZnMtbWlycm9yIiwgInNpdGVfbmFtZSI6ICJiYWNrdXAiLCAia2V5IjogIkFRRHBqcTFvaGV6UkV4QUEveDIreEh2amdGUW00U0pPbGxiU2h3PT0iLCAibW9uX2hvc3QiOiAiW3YyOjE5Mi4xNjguMTA4LjE0OjMzMDAvMCx2MToxOTIuMTY4LjEwOC4xNDo2Nzg5LzBdIFt2MjoxOTIuMTY4LjEwOC4xNTozMzAwLzAsdjE6MTkyLjE2OC4xMDguMTU6Njc4OS8wXSBbdjI6MTkyLjE2OC4xMDguMTY6MzMwMC8wLHYxOjE5Mi4xNjguMTA4LjE2OjY3ODkvMF0ifQ=="} -
在源集群上导入目标集群创建的引导令牌。
语法:
ceph fs snapshot mirror peer_bootstrap import source_fs_name token说明:
source_fs_name,是源 cephfs 文件系统名称。token,是目标 cephfs 创建的 token 字符串。
示例:
bash[root@ceph1 ~]# ceph fs snapshot mirror peer_bootstrap import cephfs eyJmc2lkIjogImFhMDUyNzY0LTdmNGUtMTFmMC1hYTM5LTAwMGMyOTZiNGY4ZSIsICJmaWxlc3lzdGVtIjogImNlcGhmcyIsICJ1c2VyIjogImNsaWVudC5jZXBoZnMtbWlycm9yIiwgInNpdGVfbmFtZSI6ICJiYWNrdXAiLCAia2V5IjogIkFRRHBqcTFvaGV6UkV4QUEveDIreEh2amdGUW00U0pPbGxiU2h3PT0iLCAibW9uX2hvc3QiOiAiW3YyOjE5Mi4xNjguMTA4LjE0OjMzMDAvMCx2MToxOTIuMTY4LjEwOC4xNDo2Nzg5LzBdIFt2MjoxOTIuMTY4LjEwOC4xNTozMzAwLzAsdjE6MTkyLjE2OC4xMDguMTU6Njc4OS8wXSBbdjI6MTkyLjE2OC4xMDguMTY6MzMwMC8wLHYxOjE5Mi4xNjguMTA4LjE2OjY3ODkvMF0ifQ== {} # 查看文件系统对端清单 [root@ceph1 ~]# ceph fs snapshot mirror peer_list cephfs {"89e201c4-b3f8-48d4-a647-66e5f4d0948b": {"client_name": "client.cephfs-mirror", "site_name": "backup", "fs_name": "cephfs", "mon_host": "[v2:192.168.108.14:3300/0,v1:192.168.108.14:6789/0] [v2:192.168.108.15:3300/0,v1:192.168.108.15:6789/0] [v2:192.168.108.16:3300/0,v1:192.168.108.16:6789/0]"}} -
在源集群上指定需要快照镜像的目录。
bash# 语法 [root@ceph1 ~]# ceph fs snapshot mirror add FILE_SYSTEM_NAME PATH # 示例 [root@ceph1 ~]# ceph fs snapshot mirror add cephfs /webapp {} -
客户端挂载验证
bash# 源集群 [root@ceph1 ~]# mkdir /mnt/cephfs1 [root@ceph1 ~]# mount.ceph ceph1.laogao.cloud:/ /mnt/cephfs1 -o name=admin [root@ceph1 ~]# mkdir /mnt/cephfs1/webapp [root@ceph1 ~]# echo hello world > /mnt/cephfs1/webapp/index.html # 目标集群 [root@ceph4 ~]# mkdir /mnt/cephfs1 [root@ceph4 ~]# mount.ceph ceph4.laogao.cloud:/ /mnt/cephfs1 -o name=admin [root@ceph4 ~]# ls /mnt/cephfs1/ webapp
使用自己的ceph账户,读取自己集群中cephfs数据,然后使用目标集群的账户凭据将自己集群中cephfs变更数据写入目标集群。
CephFS 镜像功能基于快照实现:
- 第一次快照同步,需要将数据从源集群批量传输到远程集群。
- 然后,镜像守护进程识别本地快照之间修改的文件,并将这些修改的文件同步到远程集群。
对于目录中给定的快照,cephfs-mirror守护进程将依赖 readdir diff 来识别目录树中的更改。差异应用于远程文件系统中的目录,从而仅同步两个快照之间已更改的文件。
环境准备
bash
# 源集群创建Cephfs
[root@ceph1 ~]# ceph fs volume create cephfs --placement="1 ceph1.laogao.cloud"
# 目标群创建Cephfs
[root@ceph4 ~]# ceph fs volume create cephfs --placement="1 ceph4.laogao.cloud"
具体操作步骤如下:
-
在源集群上部署 CephFS 镜像守护进程。
bash[root@ceph1 ~]# ceph orch apply cephfs-mirror ceph1.laogao.cloud Scheduled cephfs-mirror update... [root@ceph1 ~]# ceph orch ls cephfs-mirror NAME RUNNING REFRESHED AGE PLACEMENT cephfs-mirror 1/1 11s ago 18s ceph1.laogao.cloud # 部署 CephFS 镜像守护进程,将会创建一个 cephfs-mirror Ceph 用户 [root@ceph1 ~]# ceph auth ls | grep cephfs-mirror installed auth entries: client.cephfs-mirror.ceph1.yuxcon caps: [mon] profile cephfs-mirror [root@ceph1 ~]# ceph auth get client.cephfs-mirror.ceph1.yuxcon [client.cephfs-mirror.ceph1.yuxcon] key = AQChjK1oOu2WNRAAX7ZFmilo3IMq+/X+K1TWrA== caps mds = "allow r" caps mgr = "allow r" caps mon = "profile cephfs-mirror" caps osd = "allow rw tag cephfs metadata=*, allow r tag cephfs data=*" exported keyring for client.cephfs-mirror.ceph1.yuxcon -
在目标集群上创建Ceph用户。
bash[root@ceph4 ~]# ceph fs authorize cephfs client.cephfs-mirror / rwps [client.cephfs-mirror] key = AQDpjq1ohezRExAA/x2+xHvjgFQm4SJOllbShw== [root@ceph4 ~]# ceph auth get client.cephfs-mirror [client.cephfs-mirror] key = AQDpjq1ohezRExAA/x2+xHvjgFQm4SJOllbShw== caps mds = "allow rwps fsname=cephfs" caps mon = "allow r fsname=cephfs" caps osd = "allow rw tag cephfs data=cephfs" exported keyring for client.cephfs-mirror -
在源集群上启用 mirroring 模块。
bash[root@ceph1 ~]# ceph mgr module enable mirroring -
在源集群特定文件系统上启用 mirroring 功能。
bash[root@ceph1 ~]# ceph fs snapshot mirror enable cephfs -
在目标集群上启用 mirroring 模块。
bash[root@ceph4 ~]# ceph mgr module enable mirroring -
在目标集群节点上创建对等引导。
语法:
$ ceph fs snapshot mirror peer_bootstrap create fs_name client_entity site-name说明:
fs_name,是目标 cephfs 文件系统名称。client_entity,是目标集群Ceph账户,用来同步远端的CephFS。site_name,是用户自定义的目标集群名称。
示例:
bash[root@ceph4 ~]# ceph fs snapshot mirror peer_bootstrap create cephfs client.cephfs-mirror backup {"token": "eyJmc2lkIjogImFhMDUyNzY0LTdmNGUtMTFmMC1hYTM5LTAwMGMyOTZiNGY4ZSIsICJmaWxlc3lzdGVtIjogImNlcGhmcyIsICJ1c2VyIjogImNsaWVudC5jZXBoZnMtbWlycm9yIiwgInNpdGVfbmFtZSI6ICJiYWNrdXAiLCAia2V5IjogIkFRRHBqcTFvaGV6UkV4QUEveDIreEh2amdGUW00U0pPbGxiU2h3PT0iLCAibW9uX2hvc3QiOiAiW3YyOjE5Mi4xNjguMTA4LjE0OjMzMDAvMCx2MToxOTIuMTY4LjEwOC4xNDo2Nzg5LzBdIFt2MjoxOTIuMTY4LjEwOC4xNTozMzAwLzAsdjE6MTkyLjE2OC4xMDguMTU6Njc4OS8wXSBbdjI6MTkyLjE2OC4xMDguMTY6MzMwMC8wLHYxOjE5Mi4xNjguMTA4LjE2OjY3ODkvMF0ifQ=="} -
在源集群上导入目标集群创建的引导令牌。
语法:
ceph fs snapshot mirror peer_bootstrap import source_fs_name token说明:
source_fs_name,是源 cephfs 文件系统名称。token,是目标 cephfs 创建的 token 字符串。
示例:
bash[root@ceph1 ~]# ceph fs snapshot mirror peer_bootstrap import cephfs eyJmc2lkIjogImFhMDUyNzY0LTdmNGUtMTFmMC1hYTM5LTAwMGMyOTZiNGY4ZSIsICJmaWxlc3lzdGVtIjogImNlcGhmcyIsICJ1c2VyIjogImNsaWVudC5jZXBoZnMtbWlycm9yIiwgInNpdGVfbmFtZSI6ICJiYWNrdXAiLCAia2V5IjogIkFRRHBqcTFvaGV6UkV4QUEveDIreEh2amdGUW00U0pPbGxiU2h3PT0iLCAibW9uX2hvc3QiOiAiW3YyOjE5Mi4xNjguMTA4LjE0OjMzMDAvMCx2MToxOTIuMTY4LjEwOC4xNDo2Nzg5LzBdIFt2MjoxOTIuMTY4LjEwOC4xNTozMzAwLzAsdjE6MTkyLjE2OC4xMDguMTU6Njc4OS8wXSBbdjI6MTkyLjE2OC4xMDguMTY6MzMwMC8wLHYxOjE5Mi4xNjguMTA4LjE2OjY3ODkvMF0ifQ== {} # 查看文件系统对端清单 [root@ceph1 ~]# ceph fs snapshot mirror peer_list cephfs {"89e201c4-b3f8-48d4-a647-66e5f4d0948b": {"client_name": "client.cephfs-mirror", "site_name": "backup", "fs_name": "cephfs", "mon_host": "[v2:192.168.108.14:3300/0,v1:192.168.108.14:6789/0] [v2:192.168.108.15:3300/0,v1:192.168.108.15:6789/0] [v2:192.168.108.16:3300/0,v1:192.168.108.16:6789/0]"}} -
在源集群上指定需要快照镜像的目录。
bash# 语法 [root@ceph1 ~]# ceph fs snapshot mirror add FILE_SYSTEM_NAME PATH # 示例 [root@ceph1 ~]# ceph fs snapshot mirror add cephfs /webapp {} -
客户端挂载验证
bash# 源集群 [root@ceph1 ~]# mkdir /mnt/cephfs1 [root@ceph1 ~]# mount.ceph ceph1.laogao.cloud:/ /mnt/cephfs1 -o name=admin [root@ceph1 ~]# mkdir /mnt/cephfs1/webapp [root@ceph1 ~]# echo hello world > /mnt/cephfs1/webapp/index.html # 目标集群 [root@ceph4 ~]# mkdir /mnt/cephfs1 [root@ceph4 ~]# mount.ceph ceph4.laogao.cloud:/ /mnt/cephfs1 -o name=admin [root@ceph4 ~]# ls /mnt/cephfs1/ webapp