返回介绍

puppet-ceph

发布于 2025-02-18 00:20:46 字数 15454 浏览 0 评论 0 收藏 0

本节作者:薛飞扬

建议阅读时间 2 小时

Ceph 是一个分布式存储系统,诞生于 2004 年,是最早致力于开发下一代高性能分布式文件系统的项目。随着云计算的发展,ceph 乘上了 OpenStack 的春风,进而成为了开源社区受关注较高的项目之一。

Ceph 基本结构

自下向上,可以将 Ceph 系统分为四个层次:

1.基础存储系统 RADOS(Reliable, Autonomic, Distributed Object Store,即可靠的、自动化的、分布式的对象存储) RADOS 本身也是分布式存储系统,CEPH 所有的存储功能都是基于 RADOS 实现,RADOS 由大量的存储设备节点组成,每个节点拥有自己的硬件资源(CPU、内存、硬盘、网络),并运行着操作系统和文件系统。

2.基础库 librados 这一层的功能是对 RADOS 进行抽象和封装,并向上层提供 API,以便直接基于 RADOS(而不是整个 Ceph)进行应用开发。

3.高层应用接口 这一层包括了三个部分:RADOS GW(RADOS Gateway)、 RBD(Reliable Block Device)和 Ceph FS(Ceph File System),其作用是在 librados 库的基础上提供抽象层次更高、更便于应用或客户端使用的上层接口。 其中,RADOS GW 是一个提供与 Amazon S3 和 Swift 兼容的 RESTful API 的 gateway,以供相应的对象存储应用开发使用。RADOS GW 提供的 API 抽象层次更高,但功能则不如 librados 强大。因此,开发者应针对自己的需求选择使用。 RBD 则提供了一个标准的块设备接口,常用于在虚拟化的场景下为虚拟机创建 volume。目前,Red Hat 已经将 RBD 驱动集成在 KVM/QEMU 中,以提高虚拟机访问性能。 Ceph FS 是一个 POSIX 兼容的分布式文件系统。由于还处在开发状态,因而 Ceph 官网并不推荐将其用于生产环境中

4.应用层 这一层就是不同场景下对于 Ceph 各个应用接口的各种应用方式,例如基于 librados 直接开发的对象存储应用,基于 RADOS GW 开发的对象存储应用,基于 RBD 实现的云硬盘等等。

Ceph 基本组件

  • Osd 用于集群中所有数据与对象的存储。处理集群数据的复制、恢复、回填、再均衡。并向其他 osd 守护进程发送心跳,然后向 Mon 提供一些监控信息。
  • Monitor 监控整个集群的状态,维护集群的 cluster MAP 二进制表,保证集群数据的一致性。ClusterMAP 描述了对象块存储的物理位置,以及一个将设备聚合到物理位置的桶列表。
  • MDS(可选) 为 Ceph 文件系统提供元数据计算、缓存与同步。在 ceph 中,元数据也是存储在 osd 节点中的,mds 类似于元数据的代理缓存服务器。MDS 进程并不是必须的进程,只有需要使用 CEPHFS>时,才需要配置 MDS 节点。

CRUSH 机制

引入 CRUSH 的目的

为了去中心化,避免单点故障,Ceph 使用了 CRUSH(Controlled Replication Under Scalable Hashing)算法,客户端根据它来计算数据被写到哪里去,以及从哪里读取所需数据。

理解 CRUSH 机制

对 Ceph 集群的一个读写操作,客户端首先访问 Ceph monitor 来获取 cluster map 的一分副本,它包含五个 map,分别是 monitor map、OSD map 、 MDS map、CRUSH map 和 PG map.

客户端通过这些 cluster map 知晓 Ceph 集群的状态和配置。通过 CRUSH 算法计算出或获取数据的主(primary)、次(secondary)和再次(tertiary)OSD 的位置。

所有这些计算操作都是在客户端完成的,因此它们不会影响 Ceph 集群服务器端的性能。

每个 map 的简介如下:

  • monitor map: 它包含监视节点端到端的信息,包括 Ceph 集群 ID、monitor 节点名称(hostname)、IP 地址和端口号等。它还保存自 monitor map 被创建以来的最新版本号(epoch:每种 map 都维护着其历史版本,每个版本被称为一个 epoch,epoch 是一个单调递增的序号),以及最后修改时间等。
    查看 monitor map 命令: ceph mon dump
  • OSD map: 它保存一些常用的信息,包括集群 ID、OSD map 自创建以来的最新版本号(epoch)及其最后修改时间,以及存储池相关的信息,包括存储池名称、ID、类型、副本级别(replication level)和 PG。它还保存着 OSD 的信息,比如数量、状态、权重、最后清理间隔(last clean interval)以及 OSD 节点的信息。
    查看 OSD map 命令:ceph osd dump
  • PG map:它保存的信息包括 PG 的版本、时间戳、OSD map 的最新版本号(epoch)、容量已满百分比,容量将满百分比等。它还记录了每个 PG 的 ID、对象数量、状态、状态时间戳、up OSD sets、acting OSD sets,以及清理的信息。
    查看 PG map 命令: ceph pg dump
  • CRUSH map: 它保存的信息包括集群设备列表、bucket 列表、故障域分层结构、故障域定义的规则等。
    查看 CRUSH map 命令: ceph osd crush dump
  • MDS map:它保存的信息包括 MDS map 当前版本号(epoch)、MDS map 的创建和修改时间、数据和元数据存储池的 ID、集群 MDS 数量以及 MDS 状态。
    查看 MDS map 命令: ceph mds dump

CRUSH Map 的内容

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

CRUSH 图包含 OSD 列表、把设备汇聚为物理位置的“桶”列表和指示 CRUSH 如何复制存储池里的数据的规则列表。

CRUSH 图主要有 4 个主要段落:

1.设备
设备的格式:

#devices
device {num} {osd.name}

2.桶类型: 定义了 CRUSH 分级结构里要用的桶类型( types ) 如:

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

3.桶例程: 定义了桶类型后,还必须声明主机的桶类型、以及规划的其它故障域。 格式:

[bucket-type] [bucket-name] {
        id [a unique negative numeric ID]
        weight [the relative capacity/capability of the item(s)]
        alg [the bucket type: uniform | list | tree | straw ]
        hash [the hash type: 0 by default]
        item [item-name] weight [weight]
}

Ceph 支持四种桶,每种都是性能和组织简易间的折衷。如果你不确定用哪种桶,我们建议 straw 。关于桶类型的详细讨论请参考 http://docs.ceph.org.cn/rados/operations/crush-map

各个桶都用了一种哈希算法,当前 Ceph 仅支持 rjenkins1 ,输入 0 表示哈希算法设置为 rjenkins1 。

例子如下:

定义的桶例程为:

host node1 {
        id -1
        alg straw
        hash 0
        item osd.0 weight 1.00
        item osd.1 weight 1.00
}

host node2 {
        id -2
        alg straw
        hash 0
        item osd.2 weight 1.00
        item osd.3 weight 1.00
}

rack rack1 {
        id -3
        alg straw
        hash 0
        item node1 weight 2.00
        item node2 weight 2.00
}

此例中,机柜桶不包含任何 OSD ,它只包含低一级的主机桶、以及其内条目的权重之和

4.规则: 由选择桶的方法组成。

规则格式如下:

rule <rulename> {

        ruleset <ruleset>
        type [ replicated | erasure ]
        min_size <min-size>
        max_size <max-size>
        step take <bucket-type>
        step [choose|chooseleaf] [firstn|indep] <N> <bucket-type>
        step emit
}

各字段含义如下:

4.1ruleset

描述: 区分一条规则属于某个规则集的手段。给存储池设置规则集后激活。
目的: 规则掩码的一个组件。
类型: Integer
是否必需: Yes
默认值: 0

4.2type

描述: 为硬盘(复制的)或 RAID 写一条规则。
目的: 规则掩码的一个组件。
类型: String
是否必需: Yes
默认值: replicated
合法取值: 当前仅支持 replicated 和 erasure

4.3min_size

描述: 如果一个归置组副本数小于此数, CRUSH 将不应用此规则。
类型: Integer
目的: 规则掩码的一个组件。
是否必需: Yes
默认值: 1

4.4max_size

描述: 如果一个归置组副本数大于此数, CRUSH 将不应用此规则。
类型: Integer
目的: 规则掩码的一个组件。
是否必需: Yes
默认值: 10

4.5step take

描述: 选取桶名并迭代到树底。
目的: 规则掩码的一个组件。
是否必需: Yes
实例: step take default

4.6step choose firstn {num} type {bucket-type}

描述: 选取指定类型桶的数量,这个数字通常是存储池的副本数(即 pool size )。
如果 {num} == 0 选择 pool-num-replicas 个桶(所有可用的);
如果 {num} > 0 && < pool-num-replicas 就选择那么多的桶;
如果 {num} < 0 它意为 pool-num-replicas - {num} 。
目的: 规则掩码的一个组件。
先决条件: 跟在 step take 或 step choose 之后。
实例: step choose firstn 1 type row

4.7step chooseleaf firstn {num} type {bucket-type}

描述: 选择 {bucket-type} 类型的一堆桶,并从各桶的子树里选择一个叶子节点。集合内桶的数量通常是存储池的副本数(即 pool size )。
如果 {num} == 0 选择 pool-num-replicas 个桶(所有可用的);
如果 {num} > 0 && < pool-num-replicas 就选择那么多的桶;
如果 {num} < 0 它意为 pool-num-replicas - {num} 。
目的: 规则掩码的一个组件。 它的使用避免了通过两步来选择一设备。
先决条件: Follows step take or step choose.

4.8step emit

描述: 输出当前值并清空堆栈。通常用于规则末尾,也适用于相同规则应用到不同树的情况。
目的: 规则掩码的一个组件。
先决条件: Follows step choose.
实例: step emit

较新版本的 CRUSH (从 0.48 起)为了解决一些遗留值导致几个不当行为,在最前面加入了一些参数值。

一个例子如下:

# begin crush map
tunable choose_local_tries 0 #本地重试次数。以前是 2 ,最优值是 0 。
tunable choose_local_fallback_tries 0 #以前 5 ,现在是 0
tunable choose_total_tries 50 #选择一个条目的最大尝试次数。以前 19 ,后来的测试表明,对典型的集群来说 50 更合适。最相当大的集群来说,更大的值也许必要。
tunable chooseleaf_descend_once 1 #是否重递归叶子选择,或只试一次、并允许最初归置组重试。以前默认 0 ,最优为 1 。
tunable straw_calc_version 1

# devices
device 0 osd.0
device 1 osd.1
device 2 osd.2

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

# buckets
host server-250 {
        id -2           # do not change unnecessarily
        # weight 2.160
        alg straw
        hash 0  # rjenkins1
        item osd.0 weight 0.720
        item osd.1 weight 0.720
        item osd.2 weight 0.720
}
root default {
        id -1           # do not change unnecessarily
        # weight 2.160
        alg straw
        hash 0  # rjenkins1
        item server-250 weight 2.160
}

# rules
rule replicated_ruleset {
        ruleset 0
        type replicated
        min_size 1
        max_size 10
        step take default
        step chooseleaf firstn 0 type osd
        step emit
}

# end crush map

如何编辑 CRUSH map

1.从任意一个 monitor 节点上获取 CRUSH map

ceph osd getcrushmap -o crushmap

2.反编译它,让它成为我们能阅读的格式

crushtool -d crushmap -o crushmap.txt

3.修改相应的内容

vim  crushmap.txt

4.重新编译

crushtool -c crushmap.txt -o newcrushmap

5.将重新编译的 CRUSH map 注入 Ceph 集群

ceph osd setcrushmap -i newcrushmap

puppet-ceph 部署

Ceph 集群有多种部署方式,诸如 Ansible、Puppet 和 Chef 等配置管理工具都可以按照你喜欢的方式来安装和部署 Ceph 集群。这里我们只介绍 Puppet 的部署方式。

准备工作

在 puppet master module 目录下下载 puppet-ceph 模块,下载地址为 https://github.com/openstack/puppet-ceph/tree/stable/hammer

openstack/puppet-ceph 使用 ceph 版本为 hammer

此例中,我们部署一个 mon 节点,两个 osd 节点,hostname 分别为:test-ceph-1,test-ceph-2,test-ceph-3

部署指南

各节点加载的类:

node /^test-ceph-1$/ {
$ceph_pools = ['test']
ceph::pool { $ceph_pools: }
class { '::ceph::profile::mon': }
}
node /^test-ceph-[2-3]$/ {
class { '::ceph::profile::osd': }
}

传的 hieradata:

common/ceph.yaml:

---
######## Ceph
ceph::profile::params::release: 'hammer'

######## Ceph.conf
ceph::profile::params::fsid: '4b5c8c0a-ff60-454b-a1b4-9747aa737d19'
ceph::profile::params::authentication_type: 'cephx'
ceph::profile::params::mon_initial_members: 'test-ceph-1'
ceph::profile::params::mon_host: '10.0.86.23:6789'
ceph::profile::params::osd_pool_default_size: '2'

######## Keys
ceph::profile::params::mon_key: 'AQATGHJTUCBqIBAA7M2yafV1xctn1pgr3GcKPg=='
ceph::profile::params::client_keys:
  'client.admin':
    secret: 'AQATGHJTUCBqIBAA7M2yafV1xctn1pgr3GcKPg=='
    mode: '0600'
    cap_mon: 'allow *'
    cap_osd: 'allow *'
    cap_mds: 'allow *'
  'client.bootstrap-osd':
    secret: 'AQATGHJTUCBqIBAA7M2yafV1xctn1pgr3GcKPg=='
    keyring_path: '/var/lib/ceph/bootstrap-osd/ceph.keyring'
    cap_mon: 'allow profile bootstrap-osd'

test-ceph-2.yaml:

ceph::profile::params::osds:
  '/dev/sdb':
    journal: ''

test-ceph-3.yaml:

ceph::profile::params::osds:
  '/dev/sdc':
    journal: ''

参数说明

puppet 会执行 ceph-disk prepare /dev/sdc ,如果 journal 为空,它会把自动把这块盘分成两个分区,一个为 ceph data ,一个为 ceph journal。journal 分区大小默认为 5G,剩下的 都分给 ceph data.

Journal 的作用类似于 mysql innodb 引擎中的事物日志系统。当有突发的大量写入操作时,ceph 可以先把一些零散的,随机的 IO 请求保存到缓存中进行合并,然后再统一向内核发起 IO 请求。journal 的 io 是非常密集的,很大程度上也损耗了硬件的 io 性能,所以通常在生产环境中,推荐使用 ssd 来单独存储 journal 文件以提高 ceph 读写性能。

journal 也可以使用单独的数据盘,只需要在 hieradata 中传递相应的设备名即可。

openstack/puppet-ceph 传 osds 参数不支持 wwn 的方式,因为 ceph-disk 当前不支持使用 wwn 来作为磁盘标识的输入参数。

如果重启了 mon 节点,需要执行:

service ceph start mon.server-250

如果重启了 osd 节点,需要执行:

ceph-disk activate-all

activate-all 靠 /dev/disk/by-parttype-uuid/$typeuuid.$uuid 发现所有分区

parttype-uuid 是在执行 activate-prepare 时生成的。通过 parttypeuuid,在本机插拔 osd 盘完全不会导致故障。

puppet 执行过程分析

创建 mon 的大致过程如下:

1.安装包

package { $::ceph::params::packages :
    ensure => $ensure,
    tag    => 'ceph'
  }

.是否开启认证

# [*authentication_type*] Activate or deactivate authentication
#   Optional. Default to cephx.
#   Authentication is activated if the value is 'cephx' and deactivated
#   if the value is 'none'. If the value is 'cephx', at least one of
#   key or keyring must be provided.
if $authentication_type == 'cephx' {
      ceph_config {
        'global/auth_cluster_required': value => 'cephx';
        'global/auth_service_required': value => 'cephx';
        'global/auth_client_required':  value => 'cephx';
        'global/auth_supported':        value => 'cephx';
      }

3.生成 mon 密钥

cat > ${keyring_path} << EOF
[mon.]
key = ${key}
caps mon = \"allow *\"
EOF
chmod 0444 ${keyring_path}

4.生成/etc/ceph/ceph.client.admin.keyring 文件

touch /etc/ceph/${cluster_name}.client.admin.keyring

5.初始化 monitor 服务,创建 done,sysvinit 空文件

mon_data=\$(ceph-mon ${cluster_option} --id ${id} --show-config-value mon_data)
if [ ! -d \$mon_data ] ; then
  mkdir -p \$mon_data
  if ceph-mon ${cluster_option} \
        --mkfs \
        --id ${id} \
        --keyring ${keyring_path} ; then
    touch \$mon_data/done \$mon_data/${init} \$mon_data/keyring
  else
    rm -fr \$mon_data
  fi
fi

6.启动 mon 服务:

service ceph start mon.test-ceph-xue-1

建 osd 的大致过程如下:

1.安装包

package { $::ceph::params::packages :
    ensure => $ensure,
    tag    => 'ceph'
  }

2.是否开启认证

# [*authentication_type*] Activate or deactivate authentication
#   Optional. Default to cephx.
#   Authentication is activated if the value is 'cephx' and deactivated
#   if the value is 'none'. If the value is 'cephx', at least one of
#   key or keyring must be provided.
if $authentication_type == 'cephx' {
      ceph_config {
        'global/auth_cluster_required': value => 'cephx';
        'global/auth_service_required': value => 'cephx';
        'global/auth_client_required':  value => 'cephx';
        'global/auth_supported':        value => 'cephx';
      }

3.创建 keyring file

if ! defined(File[$keyring_path]) {
    file { $keyring_path:
      ensure  => file,
      owner   => $user,
      group   => $group,
      mode    => $mode,
      require => Package['ceph'],
    }
  }

4.生成管理员密钥环,生成 client.admin 用户并加入密钥环

ceph-authtool \$NEW_KEYRING --name '${name}' --add-key '${secret}' ${caps}

5.把 client.admin 密钥加入 ceph.mon.keyring

ceph ${cluster_option} ${inject_id_option} ${inject_keyring_option} auth import -i ${keyring_path}"

6.ceph 0.94 版本下禁用 udev rules,否则可能会导致 ceph-disk activate 失败

mv -f ${udev_rules_file} ${udev_rules_file}.disabled && udevadm control --reload

7.使用 ceph-disk prepare 做预处理 预处理用作 Ceph OSD 的目录、磁盘。它会创建 GPT 分区、给分区打上 Ceph 风格的 uuid 标记、创建文件系统、把此文件系统标记为已就绪、使用日志磁盘的整个分区并新增一>分区。可单独使用,也可由 ceph-deploy 用。

if ! test -b ${data} ; then
mkdir -p ${data}
fi
ceph-disk prepare ${cluster_option} ${data} ${journal}
udevadm settle

8.激活 Ceph OSD 激活 Ceph OSD 。先把此卷挂载到一临时位置,分配 OSD 惟一标识符(若有必要),重挂载到正确位置

ceph-disk activate ${data}

小结

在这里,我们介绍了 Ceph 的一些基础知识和 puppet-ceph 搭建过程,本篇文章没有涉及到但是需要我们注意的是,在搭建 ceph 集群之前,要先对集群的硬件进行合理的规划,包括故障域和潜在的性能问题。

动手练习

  1. 通过 puppet 部署了 ceph 集群之后,在本机插拔 osd 盘,再执行 ceph-disk activate-all 命令,观察 ceph 集群状态
  2. 导出 ceph 集群的 crush map 图,理解其含义。
  3. 学习并使用 rbd 命令创建、显示、对照(introspect)和移除块设备镜像。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文