存储集群

存储设备

有两个在磁盘上存储数据的 Ceph 守护程序:

  • Ceph OSD 是大多数数据存储在 Ceph 中的地方。一般而言,每个 OSD 都由单个存储设备支持。OSD 还可以由多种设备组合来支持,例如用于大多数数据的 HDD 和用于某些元数据的 SSD。群集中 OSD 的数量通常取决于存储的数据量,每个存储设备的容量以及冗余(复制或Erasure)的级别和类型
  • Ceph Monitor 管理关键的群集状态,例如群集成员身份和身份验证信息。对于较小的群集,只需要几 GB 的容量,尽管对于较大的群集,监控器数据库可以达到数十或数百GB的容量

OSD 后端

OSD 可以通过两种方式管理它们存储的数据。从 Luminous 12.2.z 版本开始,新的默认(推荐)后端是 BlueStore。在 Luminous 之前,默认(也是唯一的选项)是 FileStore

BlueStore

BlueStore 是专用于存储的后端,专门用于管理 Ceph OSD 中的数据。BlueStore 的主要功能包括:

  • 直接管理存储设备:BlueStore 构建在裸磁盘设备之上,直接使用原始块设备或分区
  • RocksDB 的元数据管理:嵌入 RocksDB 的键/值数据库管理内部元数据,例如从对象名称到磁盘上块位置的映射
  • 完整的数据和元数据校验和:默认情况下,所有写入 BlueStore 的数据和元数据都受到一个或多个校验和的保护。未经验证,不会从磁盘读取任何数据或元数据或将其返回给用户
  • 内联压缩:写入的数据在写入磁盘之前可以选择压缩
  • 多设备元数据分层:BlueStore 允许将其内部日志写入单独的高速设备,以提高性能。如果有大量的快速存储可用,内部元数据也可以存储在更快的设备上
  • 高效的写时复制:RBDCephFS 快照依赖于在 BlueStore 中有效实现的写时复制克隆机制。这将为常规快照和Erasure Code(依赖克隆实现高效的两阶段提交)提供高效的 IO
FILESTORE
  • FileStore 是在 Ceph 中存储对象的传统方法。它依赖于标准文件系统(建议使用 XFS)以及键/值数据库(传统上是 LevelDB,现在是 RocksDB )来处理某些元数据

  • FileStore 经过了充分的测试,并在生产中广泛使用,但是由于其总体设计和对用于存储对象数据的传统文件系统的依赖,因此存在许多性能缺陷

  • 尽管 FileStore 通常能够在大多数 POSIX 兼容文件系统(包括 btrfsext4 )上运行,但是我们仅建议使用 XFSbtrfsext4 都有已知的错误和缺陷,使用它们可能会导致数据丢失。默认情况下,所有 Ceph 工具都使用 XFS

配置 Ceph

当你启动 Ceph 服务时,初始化过程

将激活一系列在后台运行的守护程序。一个 Ceph 的存储集群上运行三种类型的守护程序:

  • Ceph Monitor
  • Ceph Manager
  • Ceph OSD

支持 Ceph File SystemCeph 存储集群至少运行一台 Ceph Metadata Server ;支持 Ceph Object StorageCeph 集群至少运行一个 Gateway 守护程序

配置源

每个 Ceph 守护进程,进程和库都将从以下列出的几个来源中提取其配置。如果同时存在,则列表后面的源将覆盖列表前面的源

  • 编译的默认值
  • 监视器集群的集中式配置数据库
  • 存储在本地主机上的配置文件
  • 环境变量
  • 命令行参数
  • 管理员设置的运行时替代

Ceph 进程在启动时要做的第一件事之一就是解析命令行参数,环境和本地配置文件提供的配置选项。然后,该过程将与监视器群集联系,以检索整个群集集中存储的配置。一旦可获得完整的配置视图,则将继续执行守护程序或进程

配置段

  • 全局配置(global):global 的配置会影响 Ceph 存储集群中的所有守护进程和客户端

  • 监视器配置(mon):影响 ceph-mon,并覆盖相同设置的 global

  • 管理器配置(mgr):影响 ceph-mgr,并覆盖相同设置的 global

  • OSD 配置:影响 ceph-osd,并覆盖相同设置的 global

  • 元数据服务器配置(mds):影响 ceph-mds,并覆盖相同设置的 global

  • client:客户端配置,影响所有的 Ceph 客户端(例如,已安装的 Ceph 文件系统,已安装的 Ceph 块设备等)以及 Rados Gateway 守护程序

使用 CLI 命令配置集群

# 查看集群所有可配置对象
$ ceph config dump

# 获取指定对象的配置信息
$ ceph config get <who>

# 例如查看 mon 的配置信息
$ ceph config get mon

# 修改指定组件的配置
$ ceph config set <who> <option> <value>

# 例如修改配置以允许用户删除 pool
$ ceph config set mon "mon_allow_pool_delete" true

# 查看当前组件的运行时配置信息
$ ceph config show <who>

# 例如查看 osd 组件信息
$ ceph config show osd.0

# 将从输入文件中提取配置文件,并将所有有效选项移至监视器的配置数据库。监视器无法识别,无效或无法控制的任何设置都将在输出文件中存储的简短配置文件中返回 。此命令对于从旧版配置文件过渡到基于集中式监视器的配置很有用。
$ ceph config assimilate-conf -i <input file> -o <output file>

# 查看指定组件的所有选项
$ ceph config show-with-defaults <who>

# 例如查看 osd 组件支持的所有选项
$ ceph config show osd.0

用户授权

Ceph 在启用身份验证和授权的情况下运行(默认情况下启用)时,您必须指定用户名和包含指定用户的私钥的密钥环(通常是通过命令行)。如果您未指定用户名,则 Cephclient.admin 用作默认用户名。如果您未指定密钥环,则 Ceph 将通过 keyringCeph 的设置中寻找密钥环。例如,如果在不指定用户或密钥环的情况下执行命令:ceph health

$ ceph health

# ceph 将解释如下
$ ceph -n client.admin --keyring=/etc/ceph/ceph.client.admin.keyring health

# 或者, 可以使用 CEPH_ARGS 环境变量来避免重新输入用户名和密码

无论 Ceph 客户端的类型是什么(例如,块设备,对象存储,文件系统,本机 API 等),Ceph 都将所有数据存储作为对象在 pool 中。Ceph 用户必须有权访问 pool 才能读取和写入数据。此外,Ceph 用户必须具有执行权限才能使用 Ceph 的管理命令

用户

Ceph 用户具有用户类型 Type 的概念。出于用户管理的目的,类型始终为 client

Ceph 识别用户分隔形式由用户类型和用户 ID 组成:例如,TYPE.IDclient.admin,或 client.user1

引入用户类型的原因是因为 Ceph 监视器,OSDMetadata Servers 也使用 Cephx 协议,但它们不是客户端。区分用户类型有助于区分客户端用户和其他用户-简化访问控制,用户监控和可追溯性

在使用 Ceph 命令行时,如果指定 --user--id 则可省略用户类型,如果指定 --name-n 则必须指定类型和名称

对象存储和文件系统

Ceph 存储群集用户Ceph 对象存储用户和 Ceph 文件系统用户不同

Ceph 对象网关使用 Ceph 存储群集用户在网关守护程序和存储群集之间进行通信,但是网关对最终用户具有自己的用户管理功能

Ceph 文件系统使用 POSIX 语义,与 Ceph 文件系统关联的用户空间与 Ceph 存储集群用户不同

授权

Ceph 使用 caps 来描述授权经过身份验证的用户行使监视器,OSDMDS 的功能

caps 可以根据应用程序标记来限制对池中数据,池中的名称空间或一组池的访问。Ceph 管理用户在创建或更新用户时设置用户的 caps

caps 语法格式:

{daemon-type} '{cap-spec}[, {cap-spec} ...]'

监控器授权:

# mon cap 包括 r, w, x 访问设置 或 profile {name}

$ mon 'allow {access-spec} [network {network/prefix}]'

$ mon 'profile {name}'

# {access-spec} 语法
$ * | all | [r][w][x]

# 可选的 [network {network/prefix}] 表示限制授权客户端网络来源(例如10.3.0.0/16)

OSD授权:

# OSD cap 包括 r, w, x, class-read, class-write 访问设置 或 profile {name}; 此外 OSD 还支持 pool 和 namespace 的设置

$ osd 'allow {access-spec} [{match-spec}] [network {network/prefix}]'

$ osd 'profile {name} [pool={pool-name} [namespace={namespace-name}]] [network {network/prefix}]'

# {access-spec} 语法是以下情况之一
$ * | all | [r][w][x] [class-read] [class-write]
$ class {class name} [{method name}]

# {match-spec} 语法是以下情况之一
$ pool={pool-name} [namespace={namespace-name}] [object_prefix {prefix}]
$ [namespace={namespace-name}] tag {application} {key}={value}

Manager 授权:

# mgr cap 包括 r, w, x 访问设置 或 profile {name}

$ mgr 'allow {access-spec} [network {network/prefix}]'

$ mgr 'profile {name} [{key1} {match-type} {value1} ...] [network {network/prefix}]'

# 还可以为特定命令, 内置管理器服务导出的所有命令或特定附加模块导出的所有命令指定管理器功能
$ mgr 'allow command "{command-prefix}" [with {key1} {match-type} {value1} ...] [network {network/prefix}]'

$ mgr 'allow service {service-name} {access-spec} [network {network/prefix}]'

$ mgr 'allow module {module-name} [with {key1} {match-type} {value1} ...] {access-spec} [network {network/prefix}]'

# {access-spec} 语法
$ * | all | [r][w][x]

# {service-name} 语法是以下情况之一
mgr | osd | pg | py

# {match-type} 语法是以下情况之一
= | prefix | regex

用户管理

添加用户

添加用户会创建一个用户名和一个秘钥。用户的密钥使用户可以通过 Ceph 存储群集进行身份验证。用户授权使用户在 ceph-monceph-osdceph-mds 上进行读取,写入或执行

添加用户的方式有以下几种:

  • ceph auth add:此命令是添加用户的规范方法。它将创建用户,生成秘钥并添加指点权限
  • ceph auth get-or-creat:创建用户并返回用户名和密钥。如果用户已存在,则返回用户名和密钥
  • ceph auth get-or-create-key:创建用户并返回密钥。如果用户已存在,返回密钥

一般情况下,一个用户至少需要在 ceph-mon 上具有读取功能,在 ceph-osd 上具有读写功能

示例:

[root@ceph01 ~]# ceph auth add client.john mon 'allow r' osd 'allow rw pool=liverpool'
added key for client.john

[root@ceph01 ~]# ceph auth get-or-create client.paul mon 'allow r' osd 'allow rw pool=liverpool'
[client.paul]
        key = AQBn5/peFEb0NhAA1PNAW7BNdW98xsIEsSyh1A==

[root@ceph01 ~]# ceph auth get-or-create client.george mon 'allow r' osd 'allow rw pool=liverpool' -o george.keyring

[root@ceph01 ~]# cat george.keyring 
[client.george]
        key = AQB75/peKljJCBAAmXGwZJHVVGbQ/jFKnHQH/A==

[root@ceph01 ~]# ceph auth get-or-create-key client.ringo mon 'allow r' osd 'allow rw pool=liverpool' -o ringo.key

[root@ceph01 ~]# cat ringo.key
AQCT5/peSuHhJxAAr8sgvdoYO6iQnSr48NG3lA==
查看用户
# 列出当前集群中的所有用户
[root@ceph01 ~]# ceph auth ls
installed auth entries:

client.admin
        key: AQCiA/heKdmdBxAAfmu1yxvJA0DAZWx1gOB1lQ==
        caps: [mds] allow *
        caps: [mgr] allow *
        caps: [mon] allow *
        caps: [osd] allow *
......

# 查看指定用户的信息
[root@ceph01 ~]# ceph auth get client.admin
exported keyring for client.admin
[client.admin]
        key = AQCiA/heKdmdBxAAfmu1yxvJA0DAZWx1gOB1lQ==
        caps mds = "allow *"
        caps mgr = "allow *"
        caps mon = "allow *"
        caps osd = "allow *"

# 导出用户
[root@ceph01 ~]# ceph auth export client.admin -o client.admin
export auth(key=AQCiA/heKdmdBxAAfmu1yxvJA0DAZWx1gOB1lQ==)

[root@ceph01 ~]# cat client.admin 
[client.admin]
        key = AQCiA/heKdmdBxAAfmu1yxvJA0DAZWx1gOB1lQ==
        caps mds = "allow *"
        caps mgr = "allow *"
        caps mon = "allow *"
        caps osd = "allow *" 

# 打印用户秘钥
[root@ceph01 ~]# ceph auth print-key client.admin
AQCiA/heKdmdBxAAfmu1yxvJA0DAZWx1gOB1lQ==
修改用户权限
# 语法
$ ceph auth caps USERTYPE.USERID {daemon} 'allow [r|w|x|*|...] [pool={pool-name}] [namespace={namespace-name}]' [{daemon} 'allow [r|w|x|*|...] [pool={pool-name}] [namespace={namespace-name}]']

# 示例
# 获取当前用户信息
[root@ceph01 ~]# ceph auth get client.john
exported keyring for client.john
[client.john]
        key = AQBU5/pew+gMLBAAbBj2BK+nrqt8Gm7zk/xRug==
        caps mon = "allow r"
        caps osd = "allow rw pool=liverpool"

# 修改 mon 权限为 rw, osd 权限为 rwx, 添加 mgr 只读权限
[root@ceph01 ~]# ceph auth caps client.john mon 'allow rw' osd 'allow rwx pool=liverpool' mgr 'allow r'
updated caps for client.john

[root@ceph01 ~]# ceph auth get client.john
exported keyring for client.john
[client.john]
        key = AQBU5/pew+gMLBAAbBj2BK+nrqt8Gm7zk/xRug==
        caps mgr = "allow r"
        caps mon = "allow rw"
        caps osd = "allow rwx pool=liverpool"  
删除用户
# 语法
$ ceph auth del {TYPE}.{ID}

# 删除 client.john
[root@ceph01 ~]# ceph auth del client.john
updated

# 查看用户, 发现已经不存在
[root@ceph01 ~]# ceph auth get client.john
Error ENOENT: failed to find client.john in keyring
导入用户
# 语法
$ ceph auth import -i /etc/ceph/ceph.keyring

# 示例
[root@ceph01 ~]# ceph auth import -i /etc/ceph/ceph.keyring

# 注意:ceph 存储集群将添加新用户, 生成其密钥和权限; 并将更新现有用户和密钥即权限

池(pool)管理

poolceph 存储数据时的逻辑分区,它起到 namespace 的作用。每个 pool 包含一定数量的 PGPG 里的对象被映射到不同的 OSD 上,因此 pool 是分布到整个集群的

除了隔离数据,我们也可以分别对不同的 pool 设置不同的策略,比如副本数、数据清洗次数、数据块及对象大小等

查看池
# 列出集群中的所有池
[root@ceph01 ~]# ceph osd lspools
1 device_health_metrics
2 cephfs_data
3 cephfs_metadata
......

# 查看池的规则
[root@ceph01 ~]# ceph osd pool get cephfs_data crush_rule
crush_rule: replicated_rule

# 列出集群中池的详细信息
[root@ceph01 ~]# ceph osd dump
创建池
# 创建池
# 语法
$ ceph osd pool create {pool-name} [{pg-num} [{pgp-num}]] [replicated] \
     [crush-rule-name] [expected-num-objects]
$ ceph osd pool create {pool-name} [{pg-num} [{pgp-num}]]   erasure \
     [erasure-code-profile] [crush-rule-name] [expected_num_objects] [--autoscale-mode=<on,off,warn>]

# 示例
[root@ceph01 ~]# ceph osd pool create test_pool 16 16
pool 'test_pool' created
  • {pool-name}pool 名称,集群唯一
  • {pg-num}pool 放置组总数,默认为 8,不适用于大多数情况
  • {pgp-num}pool 用于放置目的的放置组总数,这应等于展示位置组的总数,默认为 8
  • {replicated|erasure}replicated 类型通过保留对象的多个副本(默认是3),以便 OSD 发生故障时恢复; erasure 类型实现类似于 RAID5 功能。replicated 需要更多存储空间,但比 erasure 更加安全,erasure 需要较少的存储空间且性能相对较好,安全性相对较差。默认为 replicated
  • [crush-rule-name]:用于此池的 CRUSH 规则的名称。指定的规则必须存在
  • [erasure-code-profile=profile]:仅用于 erasure pool
  • --autoscale-mode=&lt;on,off,warn&gt;:自动缩放模式,如果将自动缩放模式设置为 onwarn,则可以让系统根据实际使用情况自动调整或建议对池中的放置组数量进行更改,默认行为由 osd pool default pg autoscale mode 选项控制,使用 ceph config get osd osd_pool_default_pg_autoscale_mode 查看
  • [expected-num-objects]pool 预期对象数
关联池
#  将 pool 关联到应用程序。池在使用前需要与应用程序关联
[root@ceph01 ~]# ceph osd pool application enable test_pool rbd
enabled application 'rbd' on pool 'test_pool'
删除池
# 设置 mon 参数, 运行删除 pool
[root@ceph01 ~]# ceph config set mon mon_allow_pool_delete true

# 删除 pool, 要求指定两次 pool 以确定
[root@ceph01 ~]# ceph osd pool delete test_pool test_pool --yes-i-really-really-mean-it
pool 'test_pool' removed
pool 参数
# 设置 pool 参数, 语法如下
$ ceph osd pool set {pool-name} {key} {value}

# 具体参数设置参考 https://ceph.readthedocs.io/en/latest/rados/operations/pools/#set-pool-values

# 获取 pool 参数, 语法如下
$ ceph osd pool get {pool-name} {key}

# 可获取 key 信息参考 https://ceph.readthedocs.io/en/latest/rados/operations/pools/#get-pool-values

# 设置对象副本数
$ ceph osd pool set {poolname} size {num-replicas}

# 设置最小副本数
$ ceph osd pool set {poolname} min_size 2

# 获取对象副本数
$ ceph osd dump | grep 'replicated size'
常用管理命令
# 重命名池
$ ceph osd pool rename {current-pool-name} {new-pool-name}

# 列出集群中所有池的使用信息
$ rados df

# 获得集群中所有池或指定池的 I/O 信息
$ ceph osd pool stats [{pool-name}]

# 创建快照
$ ceph osd pool mksnap {pool-name} {snap-name}

# 查看快照
$ rados lssnap -p {pool-name}

# 删除快照
$ ceph osd pool rmsnap {pool-name} {snap-name}