文章

ceph l版RGW对象存储

ceph l版RGW对象存储

本文档介绍 Ceph Luminous (L版) 中 RGW (RADOS Gateway) 对象存储的安装、配置和使用方法。

Ceph 对象存储概述

RADOS Gateway (RGW) 作为 RADOS 的客户端,是用户访问 Ceph 集群的接口(可以理解为客户端),提供 HTTP RESTful 接口。RGW 兼容了通用的对象存储接口,分别是亚马逊的 S3 和 OpenStack 的 Swift,可以用 Swift 或者 S3 的客户端来访问 RGW。

测试环境

本文档的测试环境为 3 台 CentOS 7.5 的虚拟机:

  • 10.224.100.51 ceph01 - mon, osd, rgw(radosgw 安装在 ceph01 上)
  • 10.224.100.52 ceph02 - mon, osd
  • 10.224.100.53 ceph03 - mon, osd

一、安装 RGW

方式一:使用 ceph-deploy 安装

在 ceph 集群的安装目录下,执行:

ceph-deploy install --rgw ceph01 ceph-deploy rgw create ceph01 ceph-deploy admin ceph01

注意:执行了 ceph-deploy 后,Ceph 会自动创建相应的对象存储池,但参数可能不符合要求(默认的 pg_num 是 8)。建议在系统创建 pool 后,再手动调整副本数和 pg_num 的数量。

使用到的存储池介绍

[root@ceph01 ~]# rados lspools

主要存储池说明:

  • .rgw.root - 存放 region 和 zone 信息,集群命名空间名称
  • default.rgw.control - 利用 librados 提供的对象 watch-notify 功能,当有数据更新时,通知其他 RGW 刷新 cache(cache control)
  • default.rgw.meta - 整合了用户相关的信息等,使用 namespace(Luminous 新版本功能)
  • default.rgw.log - 记录数据操作日志
  • default.rgw.buckets.index - bucket index 记录 bucket 和 object 的一种映射关系,对数据的操作要先查询 index 索引,官方推荐使用 SSD(解决查询的性能瓶颈)
  • default.rgw.buckets.non-ec - data_extra_pool
  • default.rgw.buckets.data - 对象数据存储的 pool

注意:L 版用 namespace 整合了用户相关的信息(uid, key, email, swift)到 default.rgw.meta pool,以前的版本分开用的多个 pool。(L 版才开始出现的 namespace 的概念,主要用来减少 pool 的数量)

查看 namespace:

[root@ceph01 ~]# rados ls -p default.rgw.meta --all

root .bucket.meta.bucket01:2a154b0b-96c7-49c0-94ad-d4108bf26b5c.4272.5 root .bucket.meta.958c4a00d8da46e3978ac90d83667778:aaaa:2a154b0b-96c7-49c0-94ad-d4108bf26b5c.194177.8 root bucket02 users.uid testuser.buckets users.keys 70JS57E0GRRAJ1167A78 root 95f10e18ccac484b92e9b8df11610b3e/glance root bucket01 users.uid 958c4a00d8da46e3978ac90d83667778$958c4a00d8da46e3978ac90d83667778 root .bucket.meta.registry:2a154b0b-96c7-49c0-94ad-d4108bf26b5c.194331.1 users.uid testuser users.uid 95f10e18ccac484b92e9b8df11610b3e$95f10e18ccac484b92e9b8df11610b3e root registry root 95f10e18ccac484b92e9b8df11610b3e/test01 root .bucket.meta.95f10e18ccac484b92e9b8df11610b3e:test01:2a154b0b-96c7-49c0-94ad-d4108bf26b5c.194331.4 users.swift testuser:swift users.uid fa36cda49dea4acf9ffd0bf4f8d20098$fa36cda49dea4acf9ffd0bf4f8d20098.buckets root .bucket.meta.bucket02:2a154b0b-96c7-49c0-94ad-d4108bf26b5c.4272.6 users.uid fa36cda49dea4acf9ffd0bf4f8d20098$fa36cda49dea4acf9ffd0bf4f8d20098

方式二:手动安装(不使用 ceph-deploy)

安装步骤

  1. 安装 radosgw 软件包:
yum install -y ceph-radosgw
  1. 创建 RGW 用户和 keyring:
ceph-authtool --create-keyring /etc/ceph/ceph.client.radosgw.keyring chmod +r /etc/ceph/ceph.client.radosgw.keyring
  1. 生成 ceph-radosgw 服务对应的用户和 key:
ceph-authtool /etc/ceph/ceph.client.radosgw.keyring -n client.radosgw.gateway --gen-key ceph-authtool -n client.radosgw.gateway --cap osd 'allow rwx' --cap mon 'allow rwx' /etc/ceph/ceph.client.radosgw.keyring
  1. 导入 keyring 到集群中:
ceph -k /etc/ceph/ceph.client.admin.keyring auth add client.radosgw.gateway -i /etc/ceph/ceph.client.radosgw.keyring
  1. 创建对象存储相应的 pool(pg_num 按实际调整):
ceph osd pool create pool pg_num
  1. 修改 /etc/ceph/ceph.conf,添加:
[client.radosgw.gateway] host = ceph01 keyring = /etc/ceph/ceph.client.radosgw.keyring log file = /var/log/ceph/client.radosgw.gateway.log rgw_frontends = civetweb port=80 # Civetweb 默认端口 7480,这里改成了 80 端口 rgw print continue = false
  1. 启动服务并设置开机启动:
systemctl enable ceph-radosgw@rgw.ceph01.service systemctl start ceph-radosgw@rgw.ceph01.service
  1. 验证 radosgw 安装完成:
[root@ceph01 ~]# curl -I http://10.224.100.51:80 HTTP/1.1 200 OK x-amz-request-id: tx0000000000000000000f4-005c779780-2f681-default Content-Type: application/xml Content-Length: 0 Date: Thu, 28 Feb 2019 08:10:40 GMT

二、访问接口

Ceph 的对象存储提供了两种访问接口:一种是 S3 API,另一种是 OpenStack 的 Swift API 接口。

1. S3 API 接口

安装配置 s3cmd 客户端工具

  1. 安装 s3cmd:
yum -y install s3cmd [root@ceph01 ~]# s3cmd --version s3cmd version 2.0.2
  1. 创建 S3 用户:

使用 radosgw-admin 工具为 S3 访问 Ceph 创建一个用户:

radosgw-admin user create --uid="testuser" --display-name="First User"

会得到返回信息,记录其中的 access_keysecret_key,相当于 S3 用户的账号和密码:

YOUR_PASSWORD “access_key”: “70JS57E0GRRAJ1167A78”, “secret_key”: “JP6a72YPLJNppBP50DrJBHL5mqNzGT1uaqOaOXLT”

3. 配置 s3cmd 客户端: 执行配置命令: ```bash s3cmd --configure

需要输入之前记录的账号和密码:

  • access_key: YOUR_ACCESS_KEY
  • secret_key: YOUR_SECRET_KEY
  • Test access with supplied credentials? [Y/n] n

执行完 s3cmd --configure 命令之后,需要编辑 /root/.s3cfg,修改以下选项:

cloudfront_host = 10.224.100.51:80 signature_v2 = True # 使用 V4 会报错 host_base = 10.224.100.51:80 host_bucket = 10.224.100.51:80/%(bucket)
  1. 测试 s3cmd 连接 Ceph:
# 创建一个存储桶 s3cmd mb s3://bucket01 # 列出所有存储桶 [root@ceph01 ~]# s3cmd ls 2019-02-22 08:32 s3://bucket01 2019-02-25 02:38 s3://bucket02 2019-02-22 05:44 s3://my-new-bucket

s3cmd 常用指令

创建新 Bucket:

s3cmd mb s3://bucket01

列出当前 bucket:

s3cmd ls

列出 bucket 中的文件:

s3cmd --recursive ls s3://mybucket2 # --recursive 递归列举 s3cmd --recursive ls s3://mybucket2/rgw

文件上传:

# 上传单个文件 s3cmd put demo.xml s3://mybucket2/demo.xml # 上传目录(目标目录不用提前创建,上传时会自动创建) s3cmd put --recursive dir1 dir2 s3://mybucket2/dir1

文件下载:

# 下载单个文件 s3cmd get s3://mybucket2/demo.xml demo2.xml # 下载目录 s3cmd get --recursive s3://mybucket2/dir1 # 带目录树下载 s3cmd get --recursive s3://mybucket2/dir1/*

删除:

# 删除文件 s3cmd del s3://mybucket2/demo.xml # 删除整个目录树 s3cmd del --recursive s3://mybucket2/dir1/

删除 bucket:

s3cmd rb s3://mybucket2 # bucket 必须为 empty,否则需要带 --force 强制删除

同步:

# 同步当前目录下所有文件 s3cmd sync ./ s3://mybucket2 # 会删除本地不存在的文件 s3cmd sync --delete-removed ./ s3://mybucket2 # 不进行 MD5 校验,直接跳过本地已存在的文件 s3cmd sync --skip-existing ./ s3://mybucket2

使用 Python boto 模块测试

也可以使用 Python 的 boto 模块来调用测试:

yum install python-boto

创建测试脚本 s3test.py

#!/usr/bin/python import boto import boto.s3.connection access_key = 'YOUR_KEY' # 之前记录的账号和密码 secret_key = 'YOUR_SECRET' conn = boto.connect_s3( aws_access_key_id = access_key, aws_secret_access_key = YOUR_KEY host = 'ceph01', port = 80, is_secure=False, calling_format = boto.s3.connection.OrdinaryCallingFormat(), ) for bucket in conn.get_all_buckets(): print "{name}\t{created}".format( name = bucket.name, created = bucket.creation_date,) # bucket = conn.create_bucket('bucket01') for key in bucket.list(): print "{name}\t{size}\t{modified}".format( name = key.name, size = key.size, modified = key.last_modified,)

执行测试:

[root@ceph01 ~]# python s3test.py bucket01 2019-02-22T08:32:30.352Z bucket02 2019-02-25T02:38:21.091Z my-new-bucket 2019-02-22T05:44:31.980Z
  1. 测试swift接口

(1) 安装客户端软件包

yum install python-setuptools easy_install pip pip install –upgrade setuptools pip install –upgrade python-swiftclient

(2) 要先创建一个swift的子用户

[root@ceph01 ~]# radosgw-admin subuser create –uid=testuser –subuser=testuser:swift –access=full

(3) 创建key

[root@ceph01 ~]# radosgw-admin key create –subuser=testuser:swift –key-type=swift –gen-secret { “user_id”: “testuser”, “display_name”: “First User”, “email”: “”, “suspended”: 0, “max_buckets”: 1000, “auid”: 0, “subusers”: [ { “id”: “testuser:swift”, “permissions”: “full-control” } ], “keys”: [ { “user”: “testuser”, “access_key”: “70JS57E0GRRAJ1167A78”, “secret_key”: “JP6a72YPLJNppBP50DrJBHL5mqNzGT1uaqOaOXLT” } ], “swift_keys”: [ { “user”: “testuser:swift”, “secret_key”: “rKWBqBAt5zW0pTmwKVNuoTdPblmf6WzkJNokpnrh” } ], “caps”: [], “op_mask”: “read, write, delete”, “default_placement”: “”, “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” }

记录好user和secret_key,验证时需要输入的用户名和密码: YOUR_PASSWORD [ { “user”: “testuser:swift”, “secret_key”: “rKWBqBAt5zW0pTmwKVNuoTdPblmf6WzkJNokpnrh” }

调用swift验证

[root@ceph01 ~]# swift -A http://example.com/auth/1.0 -U testuser:swift -K “rKWBqBAt5zW0pTmwKVNuoTdPblmf6WzkJNokpnrh” list bucket01 bucket02 my-new-bucket registry

三、配置ceph 对象存储与OpenStack Rocky的keystone集成:

  1. 编辑/etc/ceph/ceph.conf,加入如下配置:

[client.rgw.ceph01] rgw_frontends = “civetweb port=80” rgw keystone api version = 3 rgw keystone url = http://10.224.100.33:5000 rgw keystone admin user = admin rgw keystone admin password = admin rgw keystone admin domain = Default rgw keystone admin project = admin rgw keystone accepted roles = SwiftOperator,admin,member, project_admin, user1,service rgw keystone token cache size = 500 rgw keystone revocation interval = 60 rgw keystone implicit tenants = true rgw s3 auth use keystone = true rgw keystone verify ssl = false

systemctl restart ceph-radosgw@rgw.ceph01.service

  1. 创建对象存储服务主体,创建 endpoint ,需要配置为指向 Ceph 对象网关。

openstack service create –name=swift –description=”Swift Service” object-store

openstack endpoint create –region RegionOne swift public “http://10.224.100.51:80/swift/v1” openstack endpoint create –region RegionOne swift admin “http://10.224.100.51:80/swift/v1” openstack endpoint create –region RegionOne swift internal “http://10.224.100.51:80/swift/v1”

四、ceph rgw 使用的相关参数优化:

内核参数的调整

数据预读

echo “8192” > /sys/block/vda/queue/read_ahead_kb I/O Scheduler,SSD用noop,SATA/SAS使用deadline。 echo “deadline” > /sys/block/sd[x]/queue/scheduler echo “noop” > /sys/block/sd[x]/queue/scheduler

[root@ceph01 ~]# cat /etc/ceph/ceph.conf [global] rgw_dynamic_resharding = false #默认是true,手动设置resharding rgw_override_bucket_index_max_shards = 2 #rgw bucket index object的最大shards数,增大这个值能提升bucket index object的访问时间,但也会加大bucket的ls时间;(这个值要按实际业务调整) max open files = 131072 [client.rgw.ceph01] rgw_frontends = “civetweb port=80” #rgw_frontends:rgw的前端配置,一般配置为使用轻量级的civetweb;prot为访问rgw的端口,根据实际情况配置; rgw_thread_pool_size = 512 #rgw前端web的线程数

rgw_num_rados_handles = 8

rgw_max_chunk_size = 1048576 #rgw最大chunk size,针对大文件的对象存储场景可以把这个值调大; rgw_cache_lru_size = 10000 #rgw的lru cache size,对于读较多的应用场景,调大这个值能加快rgw的响应速度;

####osd相关##############

[osd] osd_mkfs_type = xfs osd_mkfs_options_xfs = -f filestore_xattr_use_omap = true filestore_min_sync_interval = 10 filestore_max_sync_interval = 15 filestore_queue_max_ops = 25000 filestore_queue_max_bytes = 10485760 filestore_queue_committing_max_ops = 5000 filestore_queue_committing_max_bytes = 10485760000 osd_max_write_size = 512 osd_client_message_size_cap = 2147483648 osd_deep_scrub_stride = 131072 osd_op_threads = 8 osd_disk_threads = 4 osd_map_cache_size = 1024 osd_map_cache_bl_size = 128 osd_mount_options_xfs = “rw,noexec,nodev,noatime,nodiratime,nobarrier” [client] rbd_cache = true rbd_cache_size = 268435456 rgw_override_bucket_index_max_shards 说明: 当外部向一个Bucket上传一个对象时,RGW执行的步骤大致为:

  1. 在对应的Bucket Index写上一条pending的entry
  2. 存入用户数据
  3. 把刚才的pending的entry改为complete 如果对象不大的话,Bucket Index上所承受的IOPS甚至远超用于写入用户数据的IOPS。 在Ceph RGW 0.80里,由于一个Bucket的Index只存在一个对象中,于是,当对一个Bucket进行并发修改时,Bucket Index就成了瓶颈。这种瓶颈在recovery/backfill的时候表现得尤其显著。当一个对象在被recovery/backfill时,所有对该对象的读写都将被挡住。由于客户端一般都有超时设置,而且可能不太长,但Ceph RGW 0.80中大的Bucket Index对象可能需要很长的时间才能完成recovery/backfill,所以在客户端看来,操作在一段时间内就是一直都超时失败。 Ceph RGW 0.94后的版本引入了Bucket Index Sharding的机制(把原来一个Bucket Index对象切成多个)。通过配置较大的shard数,Bucket Index的瓶颈效应的到了很大改善。目前推荐单个shard存储的Object信息条目在10-15W左右,过多则需要对相应的bucket做单独reshard操作(注意这个是高危操作,谨慎使用)。比如预计单个bucket最多存储100W个Object,那么100W/8=12.5W,设置shard数为8是比较合理的。业务层面控制好每个bucket的Object上限,按每个shard文件平均10-15W Object为宜。
本文由作者按照 CC BY 4.0 进行授权