ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

Ceph对象网关RGW搭建实战:从概念到常见坑

Ceph对象网关RGW搭建实战:从概念到常见坑 这个星期我把Ceph集群上一直缺的那个对象网关补上了——准确说是把RGW的搭建完整趟了一遍流程。RGW这个组件说复杂不算复杂说简单又比很多人以为的多一些门道。它是Ceph对外提供对象存储能力的那一层让你能用S3和Swift的API去操作底层的Ceph存储池而不是为此再单独搭一套对象存储服务。在做对象存储选型的时候很多人会拿它和MinIO这类轻量服务做对比如果只是一个小项目单机MinIO确实省事但如果你已经有了一套正在运行的Ceph集群又想在不额外引入新组件的前提下提供对象存储接口RGW就是最顺理成章的答案。这篇内容主要适合两类人一类是已经用Ceph做块存储或文件系统、但对RGW还停留在概念层面的朋友另一类是打算在生产环境或测试环境里部署RGW想提前避开常见坑的运维和开发。我会把集群准备、账号权限、网关注册、配置参数、S3客户端验证这些步骤从头到尾讲清楚重点是每一步背后的原因以及哪些位置容易踩坑。1. 把Ceph对象网关想清楚再做1.1 RGW到底解决什么问题RGW的全称是RADOS Gateway在Ceph里并不是一个“额外组件”而是一个特殊的守护进程。它把自己伪装成一块普通的存储接口利用librados连接Monitor集群和OSD集群然后把底层的对象存储能力通过RESTful HTTP API暴露出来。对外它兼容S3协议和Swift协议对内它直接读写RADOS层的数据看起来就像是一道把本地RADOS翻译成HTTP的桥。第一次看会比较绕的地方在于数据流。客户端访问RGW的时候实际上并不直接跟OSD通信请求流程是这样的客户端发出HTTP请求到RGW的监听端口RGW解析请求、校验签名和权限然后通过librados拿到集群运行图再向对应的OSD发起读写。这个设计的好处是RGW自己不需要维护复杂的数据分布和故障恢复逻辑全都可以甩给Ceph底层代价则是网关节点的CPU、内存和网络会直接影响对象存储的性能所以生产环境通常建议跑多个RGW实例前面再挂一层负载均衡。还有一个经常被忽略的点RGW和“块存储”是两套完全不同的使用方式。RBD是给你一个块设备你当普通磁盘去格式化、挂载而RGW给的是一个HTTP接口你通过API去上传、下载、列出文件和目录。这两种场景面对的操作对象、存储结构、甚至对数据一致性的要求都不一样所以不能把RGW理解为“把RBD变成HTTP”它有自己的元数据体系、索引池和数据池。1.2 池的规划和元数据体系RGW在Ceph里会用到一组专门的池而且数量比直觉上多一些。早期版本可能只需要一个data pool和一个index pool但随着多站点、生命周期管理等功能的加入默认池的数量已经变得相对固定。手动部署的时候如果池没建全RGW启动时虽然会自动尝试创建但在某些受限环境里会直接卡住或者报错这也是我一直建议先理解池规划再动手的原因。这些池的逻辑大致是.rgw.root存放区域和区域组配置.rgw.control用于控制面消息.rgw.meta里面再拆出用户、桶等元数据对象.rgw.buckets.index保存桶内对象索引.rgw.buckets.data才是真正存对象数据的池。元数据和数据分开意味着你可以更精细化地管理性能和冗余策略比如让元数据池跑在更快的盘上数据池用大容量盘。从Ceph的新版本开始RGW还把多站点能力拆成了realm、zonegroup和zone三层模型。如果只有单站点不需要搞得太复杂直接用默认的的zone即可。但如果你计划做跨地域容灾则必须先理清这三层的关系zone是不可再分的存储区域zonegroup是一组zone的集合realm则是最大的管理边界。多区域之间通过同步日志传递对象变更这个过程细节很多我一般建议第一轮搭建先用单站点把主链路跑通再考虑多活。2. 搭建前的准备先把地基打牢2.1 集群健康状态检查不能省搭建RGW看起来只是起一个进程的事但这个进程依赖整个Ceph集群的健康状态。如果你拿到一个PG状态异常的集群就直接起RGW大概率会出现启动成功但读写失败、或者桶列表超时这类莫名其妙的问题。所以我在任何一次RGW部署前都会先做三件事。第一件执行ceph -s确认集群状态不是HEALTH_WARN。如果输出里出现了PG_DEGRADED、PG_AVAILABILITY或者MON_DOWN之类的告警先把它们处理干净。第二件查看ceph osd tree确认OSD都在线并且没有持续的rebalance或者scrubbing开销过大。第三件检查Mon节点的时钟同步ntp或者chrony必须正常因为Ceph内部对时间敏感性很强而S3签名认证对时间更敏感网关节点和客户端之间的时间差也会影响API调用。很多人容易忽略的是集群容量。RGW一旦跑起来往上面传数据的速度可能非常快如果集群本身的可用空间不多很可能会触发full或nearfull状态。这种状态下RGW的写入会被拒绝表现成S3返回503或者500错误排查起来也很费劲。我的经验是至少在ceph df里保留20%以上的冗余空间再接入对象网关。2.2 网关运行方式选型现在部署RGW主要有两条路线一条是用Ceph官方推荐的编排工具来管理比如用cephadm命令直接部署多个RGW实例另一条是手动在节点上装radosgw包再通过systemd把服务托管起来。两条路线没有绝对的好坏更多取决于你已有集群的部署方式。如果集群本身就是用cephadm建的那就继续用编排工具它能自动处理证书、日志收集、服务重启这些杂事。如果集群是手工搭建的或者要兼容比较旧的发行版手动部署反而是可控性更高的选择。手动部署有一个隐含前提你已经在某个节点上安装了radosgw二进制。Debian系通常叫radosgwRedHat系通常也在ceph-radosgw或ceph-base包里。装好之后我不会急着直接跑命令启动而是先确认它能找到正确的配置文件。默认路径是/etc/ceph/ceph.conf和/etc/ceph/ceph.client.rgw.keyring但也支持通过--cluster参数指定集群名当多个集群共存时要尤其注意别搞混。另外一个需要考虑的问题是在哪台机器上跑。RGW是一个有CPU和内存开销的进程最好别和负载已经很重的Monitor挤在一起。我一般在独立的应用节点上起网关至少保证网络带宽足够因为对象存储最吃网络大文件上传下载都会经过这个节点作为转发。3. 核心配置逐项拆解3.1 ceph.conf里与RGW相关的参数Ceph的配置虽然很多但RGW相关的核心参数其实可以收敛到一个表里。我先把我常用的、踩过坑的参数列出来这些是在基本能跑通的基础上再做性能和安全调整的关键。参数名作用我的常用值说明rgw_frontends配置网关前端协议和端口beast port7480新版本基本都用beastCivetWeb已经不怎么维护rgw_enable_usage_log是否记录用户使用量日志false生产环境如果不需要计量建议关掉省IOrgw_bucket_default_quota_max_objects桶内默认最大对象数1000000防止意外写爆索引池rgw_bucket_default_quota_max_size桶内默认最大容量10G测试环境可以设小一点避免占满磁盘rgw_thread_pool_size网关线程池大小512并发高的时候需要调大但不要超过CPU核心数的4倍rgw_s3_auth_use_rados_cls_user是否启用新的用户认证接口false不开启也能跑开启后权限管理更灵活rgw_zone指定当前实例所属zonedefault单站点默认值不用改第一个参数rgw_frontends是最直观的。老资料里经常写civetweb port8080但在较新的Ceph版本中CivetWeb已经被移除了继续用旧参数会导致启动直接报错。切换到beast之后配置更简洁性能也更好。端口选择上我习惯用7480而不是默认的80或443因为以非root方式跑时要绑定千以下的端口需要额外加capabilities不值当。rgw_thread_pool_size这个参数很容易被调坏。官方默认值我记得是512但在一台只有4核8线程的机器上开512个线程每个线程都会占用栈空间和调度开销反而会让吞吐下降。我的原则是先在默认值下把压力测试跑一遍用top看CPU有没有到瓶颈确实发现concurrency不够了再往上涨。3.2 认证体系的层次要分清RGW涉及两层认证很多人在这里绕晕。底层是Ceph自身的Cephx认证决定的是RGW进程有没有权限去操作存储池上层是S3/Swift API的认证决定的是外部客户端有没有权限操作桶和对象。搭建时这两层都要配置而且任何一个环节缺失都会以各种奇怪的现象暴露出来。底层认证做法是给RGW创建一个专属的用户入口在Ceph认证体系里被称为client.rgw.主机名然后把对应权限授予它。我通常会用ceph-authtool生成keyring文件再用ceph auth add注册到集群。所需的caps一般是对mon有allow rwx对osd有allow rwx。这看起来权限给很大但RGW确实需要具备操作元数据池和数据池的全部权限如果刻意收紧caps很容易出现网关进程起来但读写失败的怪问题。上层认证相对简单。用radosgw-admin user create创建用户之后会返回一对AccessKey和SecretKey这就是S3客户端使用的凭证。这一层和底层Cephx没有关系你在外部用S3客户端传的永远是这样的RGW用户凭证而不是cephx的client.rgw凭证。4. 从零到一的搭建实操4.1 创建网关专用账号和认证文件我先假定你已经有了一套健康的Ceph集群并且在一台目标节点上安装了radosgw相关包。第一步是先创建keyring文件。实际操作中我会在/etc/ceph/目录下操作保证文件权限只对ceph用户可读。sudo ceph-authtool --create-keyring /etc/ceph/ceph.client.rgw.keyring sudo ceph-authtool --gen-key -n client.rgw.$(hostname) \ --cap osd allow rwx --cap mon allow rwx --cap mgr allow rwx \ /etc/ceph/ceph.client.rgw.keyring sudo chown ceph:ceph /etc/ceph/ceph.client.rgw.keyring这里有个值得注意的细节--gen-key生成的是随机密钥而--cap参数指定了该client在Ceph侧拥有的权限。为什么还需要cap mgr因为新版RGW在部分运维操作中会查询Manager模块的运行状态如果不加这个cap日志里会不断出现mgr访问被拒的报错。接着把生成的keyring注册到集群认证库里sudo ceph auth add client.rgw.$(hostname) -i /etc/ceph/ceph.client.rgw.keyring再用ceph auth list确认一下看到client.rgw.主机名已经存在即可。这种做法在集群有多个网关实例时也适用每台机器可以有自己的client.rgw.hostname账号互相独立权限也不需要改。4.2 启动网关实例手动启动方式其实非常简单直接执行sudo radosgw -f --cluster ceph --name client.rgw.$(hostname) --setuser ceph --setgroup ceph加-f是为了在前台运行并打印日志方便第一次调试。日志里如果看到beast listening on :7480这样的字样说明端口已经正常监听。此时可以试着直接在浏览器里访问http://节点IP:7480它应该返回一个简洁的XML或者版本信息页面这个页面里的内容并不是报错而是证明RGW已经在正常响应HTTP请求。线上环境我不会用前台方式而是写一个systemd unit文件来托管。这里给一个我实际在用的模板直接放到/etc/systemd/system/ceph-radosgwrgw.service[Unit] DescriptionCeph RGW Afternetwork-online.target Wantsnetwork-online.target [Service] Userceph Groupceph ExecStart/usr/bin/radosgw -f --cluster ceph --name client.rgw.%H Restarton-failure RestartSec5 LimitNOFILE1048576 [Install] WantedBymulti-user.target注意这里的%H在systemd里代表主机名可以自动对应到我们在认证库里注册的client.rgw.hostname账号不用每个节点写死name。如果主机名带了域名后缀%h和%H有细微差别我建议先用hostname -s确认短主机名是什么再决定用哪个占位符。如果你的集群是用cephadm管理的可以直接用编排命令来部署多个网关实例本质上是让cephadm替你完成了上述所有步骤ceph orch apply rgw myrgw --placement3 node1 node2 node3 --port 7480这个命令会创建名为myrgw的RGW服务并把实例调度到三台节点上。它的优点是自带多副本和服务发现缺点是如果你还不熟悉cephadm的service模型出了问题排错会比手动部署复杂不少。4.3 初始化默认zone并创建S3用户网关进程起来之后我们还需要确认RGW的zone配置和用户体系是完整的。单站点模式下默认zone会自动创建通常不需要额外操作。但如果消息日志里提示no zone config found之类的错误就需要手动初始化一次sudo ceph auth get-or-create client.rgw.$(hostname) mon allow rwx osd allow rwx -o /etc/ceph/ceph.client.rgw.keyring radosgw-admin realm create --rgw-realmdefault radosgw-admin zonegroup create --rgw-zonegroupdefault --rgw-realmdefault radosgw-admin zone create --rgw-zonegroupdefault --rgw-zonedefault --rgw-realmdefault radosgw-admin period update --commit再强调一下这条命令在不同版本、不同集群初始化状态下需要的次数不一样。我遇到过有环境在realm create这一步直接报already exists那就跳过它继续往下做就好。不要因为报错就反复执行认真看输出内容再决定下一步。然后创建第一个S3用户radosgw-admin user create --uidtestuser --display-nameTest User --emailtestexample.com正常输出会包含一对access_key和secret_key把它们复制保存好后续所有S3客户端配置都要用。如果忘记了也不用重新创建用户直接执行radosgw-admin user info --uidtestuser就能把密钥重新查出来。4.4 S3客户端冒烟测试网关是否真正工作最终要看S3客户端能不能完整地走一遍创建桶、上传对象、下载对象、删除对象这条链路。我平时测试最常用的是s3cmd和boto3因为鞋带配置起来足够简单出现问题时错误信息也相对友好。先看s3cmd的配置方式在~/.s3cfg里填入[default] access_key 刚才拿到的AccessKey secret_key 刚才拿到的SecretKey host_base 127.0.0.1:7480 host_bucket 127.0.0.1:7480 use_https False这里最关键的配置是host_base和host_bucket。很多初次接触RGW的人会照搬AWS的默认配置结果发现一直连到AWS站点去。RGW是独立网关服务必须指向你自己的节点和端口两处地址要完全一致。另外use_https必须为False才能在测试环境走明文HTTP如果你配置了TLS证书则可以改成True并指定证书路径。s3cmd测试命令如下s3cmd mb s3://testbucket echo hello ceph rgw hello.txt s3cmd put hello.txt s3://testbucket s3cmd get s3://testbucket/hello.txt /tmp/hello_download.txt s3cmd del s3://testbucket/hello.txt如果能依次执行成功说明桶创建、对象上传、下载、删除这几条最基本的路径都没有问题。此时可以用radosgw-admin bucket list查看桶是否存在radosgw-admin user info --uidtestuser查看用户配额和桶数量是否有变化。如果你用Python做自动化测试那么boto3是更常见的选择。我给一个最小可用的脚本注意endpoint_url必须显式指定RGW地址import boto3 from botocore.client import Config s3 boto3.client( s3, endpoint_urlhttp://127.0.0.1:7480, aws_access_key_id刚才拿到的AccessKey, aws_secret_access_key刚才拿到的SecretKey, configConfig(signature_versions3v4), region_nameus-east-1, ) s3.create_bucket(Bucketmybucket) s3.put_object(Bucketmybucket, Keyhello.txt, BodybHello Ceph RGW) resp s3.get_object(Bucketmybucket, Keyhello.txt) print(resp[Body].read())有位朋友第一次用boto3连RGW时一直报签名不一致最后发现是没用s3v4签名版本。RGW对签名版本的支持比较严格我建议在Config里统一加上signature_versions3v4不然老版本的签名算法会让服务器验签失败。5. 常见问题与排查技巧实录5.1 经典坑速查表这一步我把真实环境里经常出现的问题整理成一个速查表每一个都是我自己踩过或者帮别人排查过的。它的价值在于你可以拿现象去对号入座而不用从零开始猜测问题在哪一层。问题现象真正原因解决方法RGW进程起不来日志报No such file or directorykeyring路径不对或文件属主不对检查/etc/ceph/ceph.client.rgw.keyring是否存在chown ceph:ceph后再启动报Permission deniedcephx的caps没配够确认client.rgw.hostname对mon和osd都有allow rwx端口无法监听端口被占用或者小于1024换高位端口或给进程加网络capabilitiesS3客户端报AccessDenied系统时间不同步或签名算法不匹配同步时钟在客户端强制用s3v4签名create_bucket一直连不上endpoint_url写错或者网段不通确认HTTP地址可以被外部访问curl一下网关端口看响应上传大文件时收到500错误集群空间不足或索引池写满ceph df检查容量扩容或者清理旧数据桶内对象列表为空但数据确实存在索引池和元数据池不一致用radosgw-admin bucket check --fix --bucket 桶名重建索引第一条看起来有点弱智但真的很容易发生。我会经常同时管理多套环境配置文件和keyring用scp拷贝过来之后属主没有修正结果进程反复启动失败。所以我的习惯是在systemd unit里明确写Userceph并且启动前手动执行一次chown -R ceph:ceph /etc/ceph/把整个配置目录的属主统一掉这样省心很多。第二条和签名问题是最常见的两类。签名问题在上一段里已经提过权限问题则比较隐蔽因为Ceph的日志级别默认较低不会把permission denied这种报错直接铺满屏幕。遇到权限问题时建议临时在配置里增加一行debug rgw 20或者查看/var/log/ceph/目录下的RGW日志报错里会有非常明确的AccessDenied信息。5.2 日志与调试的实用技巧RGW的日志分布在不同的地方。如果用cephadm部署一般可以通过ceph -w看到RGW组件的动态也可以用cephadm logs ceph-radosgw.hostname来查看某个网关容器的日志。手动部署时日志一般落在/var/log/ceph/ceph-client.rgw.hostname.log如果没找到需要确认是不是systemd直接接管了标准输出。调试阶段建议把日志级别临时调高在ceph.conf的[client.rgw.hostname]段里加上debug rgw 20 debug librados 5然后重启服务日志会非常冗长墨水瓶的朋友可能会被刷屏但这种级别的信息量对定位问题非常有帮助。调完之后记得把debug rgw重新改回默认值否则生产环境日志量会拖垮磁盘。还有一个小技巧不用S3客户端也能快速确认网关状态。直接用curl发一个匿名请求curl -I http://127.0.0.1:7480如果返回HTTP状态码200或者405甚至403都说明RGW本身在正常工作如果返回连接超时或拒绝连接问题大概率在网络层或进程层而不是在API层。5.3 性能与高可用的进一步动作基础搭建完成后很多人的第一反应是“是不是再调一调性能”。我会建议分两步走。第一步是把多个RGW实例拉起来让并发请求可以分散到多台机器上这是最直接的吞吐扩展方式。可以把两个RGW实例跑在同一台机器上的不同端口也可以分散到不同机器然后在前面用负载均衡器将流量均摊。负载均衡这一层我用的比较顺手的方案是直接用Nginx的upstream方式把流媒体请求和普通API请求都代理到后端的RGW端口。关键配置如下upstream rgw_backend { least_conn; server 192.168.1.10:7480 max_fails3 fail_timeout10s; server 192.168.1.11:7480 max_fails3 fail_timeout10s; } server { listen 80; server_name rgw.example.local; client_max_body_size 0; location / { proxy_pass http://rgw_backend; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }client_max_body_size一定要设置为0否则上传大文件时会被Nginx拦下来返回413 Request Entity Too Large。这个坑我踩过不止一次每次新配环境都要提醒自己。第二个方向是调整RGW本身的数据分片和配额。rgw_bucket_default_quota_max_objects和rgw_bucket_default_quota_max_size要跟实际使用场景匹配。如果是一个备份系统对象数量和单桶容量都要留足余量如果是一个静态站那就要考虑对象数量是否会影响列举速度。6. 写在搭建之后的话RGW搭建本身不算难每一步都有固定套路真正让我觉得有学习价值的是过程中对Ceph整个存储体系的理解。第一点体会是不要把RGW当成一个“装好就能用”的独立服务它跟池的规划、集群的健康状态、客户端的签名方式都耦合得很深任何一个环节疏忽都会在后续使用中暴露出来。第二点是我很推荐先用最朴素的s3cmd把完整链路跑通再上自动化框架和脚本因为s3cmd的报错信息更直接排查起来没有层层包装的干扰。最后再分享一个日常运维的小习惯每次改完RGW相关配置或者重启服务之后我都会立刻执行一次radosgw-admin bucket list和radosgw-admin user info --uidtestuser确认网关进程的API侧还活着。这样即使稍后出现了异常也能快速判断问题是在进程层、API层还是底层存储层。对象存储的价值是让应用按需读写数据而RGW稳定的前提其实是你对它的运行机制有足够的掌控感。
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表