象網(wǎng)關(guān)RGW搭建實(shí)戰(zhàn):從概念到常見(jiàn)坑)
這個(gè)星期我把Ceph集群上一直缺的那個(gè)對(duì)象網(wǎng)關(guān)補(bǔ)上了——準(zhǔn)確說(shuō)是把RGW的搭建完整趟了一遍流程。RGW這個(gè)組件說(shuō)復(fù)雜不算復(fù)雜說(shuō)簡(jiǎn)單又比很多人以為的多一些門(mén)道。它是Ceph對(duì)外提供對(duì)象存儲(chǔ)能力的那一層讓你能用S3和Swift的API去操作底層的Ceph存儲(chǔ)池而不是為此再單獨(dú)搭一套對(duì)象存儲(chǔ)服務(wù)。在做對(duì)象存儲(chǔ)選型的時(shí)候很多人會(huì)拿它和MinIO這類輕量服務(wù)做對(duì)比如果只是一個(gè)小項(xiàng)目單機(jī)MinIO確實(shí)省事但如果你已經(jīng)有了一套正在運(yùn)行的Ceph集群又想在不額外引入新組件的前提下提供對(duì)象存儲(chǔ)接口RGW就是最順理成章的答案。這篇內(nèi)容主要適合兩類人一類是已經(jīng)用Ceph做塊存儲(chǔ)或文件系統(tǒng)、但對(duì)RGW還停留在概念層面的朋友另一類是打算在生產(chǎn)環(huán)境或測(cè)試環(huán)境里部署RGW想提前避開(kāi)常見(jiàn)坑的運(yùn)維和開(kāi)發(fā)。我會(huì)把集群準(zhǔn)備、賬號(hào)權(quán)限、網(wǎng)關(guān)注冊(cè)、配置參數(shù)、S3客戶端驗(yàn)證這些步驟從頭到尾講清楚重點(diǎn)是每一步背后的原因以及哪些位置容易踩坑。1. 把Ceph對(duì)象網(wǎng)關(guān)想清楚再做1.1 RGW到底解決什么問(wèn)題RGW的全稱是RADOS Gateway在Ceph里并不是一個(gè)“額外組件”而是一個(gè)特殊的守護(hù)進(jìn)程。它把自己偽裝成一塊普通的存儲(chǔ)接口利用librados連接Monitor集群和OSD集群然后把底層的對(duì)象存儲(chǔ)能力通過(guò)RESTful HTTP API暴露出來(lái)。對(duì)外它兼容S3協(xié)議和Swift協(xié)議對(duì)內(nèi)它直接讀寫(xiě)RADOS層的數(shù)據(jù)看起來(lái)就像是一道把本地RADOS翻譯成HTTP的橋。第一次看會(huì)比較繞的地方在于數(shù)據(jù)流。客戶端訪問(wèn)RGW的時(shí)候?qū)嶋H上并不直接跟OSD通信請(qǐng)求流程是這樣的客戶端發(fā)出HTTP請(qǐng)求到RGW的監(jiān)聽(tīng)端口RGW解析請(qǐng)求、校驗(yàn)簽名和權(quán)限然后通過(guò)librados拿到集群運(yùn)行圖再向?qū)?yīng)的OSD發(fā)起讀寫(xiě)。這個(gè)設(shè)計(jì)的好處是RGW自己不需要維護(hù)復(fù)雜的數(shù)據(jù)分布和故障恢復(fù)邏輯全都可以甩給Ceph底層代價(jià)則是網(wǎng)關(guān)節(jié)點(diǎn)的CPU、內(nèi)存和網(wǎng)絡(luò)會(huì)直接影響對(duì)象存儲(chǔ)的性能所以生產(chǎn)環(huán)境通常建議跑多個(gè)RGW實(shí)例前面再掛一層負(fù)載均衡。還有一個(gè)經(jīng)常被忽略的點(diǎn)RGW和“塊存儲(chǔ)”是兩套完全不同的使用方式。RBD是給你一個(gè)塊設(shè)備你當(dāng)普通磁盤(pán)去格式化、掛載而RGW給的是一個(gè)HTTP接口你通過(guò)API去上傳、下載、列出文件和目錄。這兩種場(chǎng)景面對(duì)的操作對(duì)象、存儲(chǔ)結(jié)構(gòu)、甚至對(duì)數(shù)據(jù)一致性的要求都不一樣所以不能把RGW理解為“把RBD變成HTTP”它有自己的元數(shù)據(jù)體系、索引池和數(shù)據(jù)池。1.2 池的規(guī)劃和元數(shù)據(jù)體系RGW在Ceph里會(huì)用到一組專門(mén)的池而且數(shù)量比直覺(jué)上多一些。早期版本可能只需要一個(gè)data pool和一個(gè)index pool但隨著多站點(diǎn)、生命周期管理等功能的加入默認(rèn)池的數(shù)量已經(jīng)變得相對(duì)固定。手動(dòng)部署的時(shí)候如果池沒(méi)建全RGW啟動(dòng)時(shí)雖然會(huì)自動(dòng)嘗試創(chuàng)建但在某些受限環(huán)境里會(huì)直接卡住或者報(bào)錯(cuò)這也是我一直建議先理解池規(guī)劃再動(dòng)手的原因。這些池的邏輯大致是.rgw.root存放區(qū)域和區(qū)域組配置.rgw.control用于控制面消息.rgw.meta里面再拆出用戶、桶等元數(shù)據(jù)對(duì)象.rgw.buckets.index保存桶內(nèi)對(duì)象索引.rgw.buckets.data才是真正存對(duì)象數(shù)據(jù)的池。元數(shù)據(jù)和數(shù)據(jù)分開(kāi)意味著你可以更精細(xì)化地管理性能和冗余策略比如讓元數(shù)據(jù)池跑在更快的盤(pán)上數(shù)據(jù)池用大容量盤(pán)。從Ceph的新版本開(kāi)始RGW還把多站點(diǎn)能力拆成了realm、zonegroup和zone三層模型。如果只有單站點(diǎn)不需要搞得太復(fù)雜直接用默認(rèn)的的zone即可。但如果你計(jì)劃做跨地域容災(zāi)則必須先理清這三層的關(guān)系z(mì)one是不可再分的存儲(chǔ)區(qū)域zonegroup是一組zone的集合realm則是最大的管理邊界。多區(qū)域之間通過(guò)同步日志傳遞對(duì)象變更這個(gè)過(guò)程細(xì)節(jié)很多我一般建議第一輪搭建先用單站點(diǎn)把主鏈路跑通再考慮多活。2. 搭建前的準(zhǔn)備先把地基打牢2.1 集群健康狀態(tài)檢查不能省搭建RGW看起來(lái)只是起一個(gè)進(jìn)程的事但這個(gè)進(jìn)程依賴整個(gè)Ceph集群的健康狀態(tài)。如果你拿到一個(gè)PG狀態(tài)異常的集群就直接起RGW大概率會(huì)出現(xiàn)啟動(dòng)成功但讀寫(xiě)失敗、或者桶列表超時(shí)這類莫名其妙的問(wèn)題。所以我在任何一次RGW部署前都會(huì)先做三件事。第一件執(zhí)行ceph -s確認(rèn)集群狀態(tài)不是HEALTH_WARN。如果輸出里出現(xiàn)了PG_DEGRADED、PG_AVAILABILITY或者M(jìn)ON_DOWN之類的告警先把它們處理干凈。第二件查看ceph osd tree確認(rèn)OSD都在線并且沒(méi)有持續(xù)的rebalance或者scrubbing開(kāi)銷過(guò)大。第三件檢查Mon節(jié)點(diǎn)的時(shí)鐘同步ntp或者chrony必須正常因?yàn)镃eph內(nèi)部對(duì)時(shí)間敏感性很強(qiáng)而S3簽名認(rèn)證對(duì)時(shí)間更敏感網(wǎng)關(guān)節(jié)點(diǎn)和客戶端之間的時(shí)間差也會(huì)影響API調(diào)用。很多人容易忽略的是集群容量。RGW一旦跑起來(lái)往上面?zhèn)鲾?shù)據(jù)的速度可能非常快如果集群本身的可用空間不多很可能會(huì)觸發(fā)full或nearfull狀態(tài)。這種狀態(tài)下RGW的寫(xiě)入會(huì)被拒絕表現(xiàn)成S3返回503或者500錯(cuò)誤排查起來(lái)也很費(fèi)勁。我的經(jīng)驗(yàn)是至少在ceph df里保留20%以上的冗余空間再接入對(duì)象網(wǎng)關(guān)。2.2 網(wǎng)關(guān)運(yùn)行方式選型現(xiàn)在部署RGW主要有兩條路線一條是用Ceph官方推薦的編排工具來(lái)管理比如用cephadm命令直接部署多個(gè)RGW實(shí)例另一條是手動(dòng)在節(jié)點(diǎn)上裝radosgw包再通過(guò)systemd把服務(wù)托管起來(lái)。兩條路線沒(méi)有絕對(duì)的好壞更多取決于你已有集群的部署方式。如果集群本身就是用cephadm建的那就繼續(xù)用編排工具它能自動(dòng)處理證書(shū)、日志收集、服務(wù)重啟這些雜事。如果集群是手工搭建的或者要兼容比較舊的發(fā)行版手動(dòng)部署反而是可控性更高的選擇。手動(dòng)部署有一個(gè)隱含前提你已經(jīng)在某個(gè)節(jié)點(diǎn)上安裝了radosgw二進(jìn)制。Debian系通常叫radosgwRedHat系通常也在ceph-radosgw或ceph-base包里。裝好之后我不會(huì)急著直接跑命令啟動(dòng)而是先確認(rèn)它能找到正確的配置文件。默認(rèn)路徑是/etc/ceph/ceph.conf和/etc/ceph/ceph.client.rgw.keyring但也支持通過(guò)--cluster參數(shù)指定集群名當(dāng)多個(gè)集群共存時(shí)要尤其注意別搞混。另外一個(gè)需要考慮的問(wèn)題是在哪臺(tái)機(jī)器上跑。RGW是一個(gè)有CPU和內(nèi)存開(kāi)銷的進(jìn)程最好別和負(fù)載已經(jīng)很重的Monitor擠在一起。我一般在獨(dú)立的應(yīng)用節(jié)點(diǎn)上起網(wǎng)關(guān)至少保證網(wǎng)絡(luò)帶寬足夠因?yàn)閷?duì)象存儲(chǔ)最吃網(wǎng)絡(luò)大文件上傳下載都會(huì)經(jīng)過(guò)這個(gè)節(jié)點(diǎn)作為轉(zhuǎn)發(fā)。3. 核心配置逐項(xiàng)拆解3.1 ceph.conf里與RGW相關(guān)的參數(shù)Ceph的配置雖然很多但RGW相關(guān)的核心參數(shù)其實(shí)可以收斂到一個(gè)表里。我先把我常用的、踩過(guò)坑的參數(shù)列出來(lái)這些是在基本能跑通的基礎(chǔ)上再做性能和安全調(diào)整的關(guān)鍵。參數(shù)名作用我的常用值說(shuō)明rgw_frontends配置網(wǎng)關(guān)前端協(xié)議和端口beast port7480新版本基本都用beastCivetWeb已經(jīng)不怎么維護(hù)rgw_enable_usage_log是否記錄用戶使用量日志false生產(chǎn)環(huán)境如果不需要計(jì)量建議關(guān)掉省IOrgw_bucket_default_quota_max_objects桶內(nèi)默認(rèn)最大對(duì)象數(shù)1000000防止意外寫(xiě)爆索引池rgw_bucket_default_quota_max_size桶內(nèi)默認(rèn)最大容量10G測(cè)試環(huán)境可以設(shè)小一點(diǎn)避免占滿磁盤(pán)rgw_thread_pool_size網(wǎng)關(guān)線程池大小512并發(fā)高的時(shí)候需要調(diào)大但不要超過(guò)CPU核心數(shù)的4倍rgw_s3_auth_use_rados_cls_user是否啟用新的用戶認(rèn)證接口false不開(kāi)啟也能跑開(kāi)啟后權(quán)限管理更靈活rgw_zone指定當(dāng)前實(shí)例所屬zonedefault單站點(diǎn)默認(rèn)值不用改第一個(gè)參數(shù)rgw_frontends是最直觀的。老資料里經(jīng)常寫(xiě)civetweb port8080但在較新的Ceph版本中CivetWeb已經(jīng)被移除了繼續(xù)用舊參數(shù)會(huì)導(dǎo)致啟動(dòng)直接報(bào)錯(cuò)。切換到beast之后配置更簡(jiǎn)潔性能也更好。端口選擇上我習(xí)慣用7480而不是默認(rèn)的80或443因?yàn)橐苑莚oot方式跑時(shí)要綁定千以下的端口需要額外加capabilities不值當(dāng)。rgw_thread_pool_size這個(gè)參數(shù)很容易被調(diào)壞。官方默認(rèn)值我記得是512但在一臺(tái)只有4核8線程的機(jī)器上開(kāi)512個(gè)線程每個(gè)線程都會(huì)占用??臻g和調(diào)度開(kāi)銷反而會(huì)讓吞吐下降。我的原則是先在默認(rèn)值下把壓力測(cè)試跑一遍用top看CPU有沒(méi)有到瓶頸確實(shí)發(fā)現(xiàn)concurrency不夠了再往上漲。3.2 認(rèn)證體系的層次要分清RGW涉及兩層認(rèn)證很多人在這里繞暈。底層是Ceph自身的Cephx認(rèn)證決定的是RGW進(jìn)程有沒(méi)有權(quán)限去操作存儲(chǔ)池上層是S3/Swift API的認(rèn)證決定的是外部客戶端有沒(méi)有權(quán)限操作桶和對(duì)象。搭建時(shí)這兩層都要配置而且任何一個(gè)環(huán)節(jié)缺失都會(huì)以各種奇怪的現(xiàn)象暴露出來(lái)。底層認(rèn)證做法是給RGW創(chuàng)建一個(gè)專屬的用戶入口在Ceph認(rèn)證體系里被稱為client.rgw.主機(jī)名然后把對(duì)應(yīng)權(quán)限授予它。我通常會(huì)用ceph-authtool生成keyring文件再用ceph auth add注冊(cè)到集群。所需的caps一般是對(duì)mon有allow rwx對(duì)osd有allow rwx。這看起來(lái)權(quán)限給很大但RGW確實(shí)需要具備操作元數(shù)據(jù)池和數(shù)據(jù)池的全部權(quán)限如果刻意收緊caps很容易出現(xiàn)網(wǎng)關(guān)進(jìn)程起來(lái)但讀寫(xiě)失敗的怪問(wèn)題。上層認(rèn)證相對(duì)簡(jiǎn)單。用radosgw-admin user create創(chuàng)建用戶之后會(huì)返回一對(duì)AccessKey和SecretKey這就是S3客戶端使用的憑證。這一層和底層Cephx沒(méi)有關(guān)系你在外部用S3客戶端傳的永遠(yuǎn)是這樣的RGW用戶憑證而不是cephx的client.rgw憑證。4. 從零到一的搭建實(shí)操4.1 創(chuàng)建網(wǎng)關(guān)專用賬號(hào)和認(rèn)證文件我先假定你已經(jīng)有了一套健康的Ceph集群并且在一臺(tái)目標(biāo)節(jié)點(diǎn)上安裝了radosgw相關(guān)包。第一步是先創(chuàng)建keyring文件。實(shí)際操作中我會(huì)在/etc/ceph/目錄下操作保證文件權(quán)限只對(duì)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這里有個(gè)值得注意的細(xì)節(jié)--gen-key生成的是隨機(jī)密鑰而--cap參數(shù)指定了該client在Ceph側(cè)擁有的權(quán)限。為什么還需要cap mgr因?yàn)樾掳鍾GW在部分運(yùn)維操作中會(huì)查詢Manager模塊的運(yùn)行狀態(tài)如果不加這個(gè)cap日志里會(huì)不斷出現(xiàn)mgr訪問(wèn)被拒的報(bào)錯(cuò)。接著把生成的keyring注冊(cè)到集群認(rèn)證庫(kù)里sudo ceph auth add client.rgw.$(hostname) -i /etc/ceph/ceph.client.rgw.keyring再用ceph auth list確認(rèn)一下看到client.rgw.主機(jī)名已經(jīng)存在即可。這種做法在集群有多個(gè)網(wǎng)關(guān)實(shí)例時(shí)也適用每臺(tái)機(jī)器可以有自己的client.rgw.hostname賬號(hào)互相獨(dú)立權(quán)限也不需要改。4.2 啟動(dòng)網(wǎng)關(guān)實(shí)例手動(dòng)啟動(dòng)方式其實(shí)非常簡(jiǎn)單直接執(zhí)行sudo radosgw -f --cluster ceph --name client.rgw.$(hostname) --setuser ceph --setgroup ceph加-f是為了在前臺(tái)運(yùn)行并打印日志方便第一次調(diào)試。日志里如果看到beast listening on :7480這樣的字樣說(shuō)明端口已經(jīng)正常監(jiān)聽(tīng)。此時(shí)可以試著直接在瀏覽器里訪問(wèn)http://節(jié)點(diǎn)IP:7480它應(yīng)該返回一個(gè)簡(jiǎn)潔的XML或者版本信息頁(yè)面這個(gè)頁(yè)面里的內(nèi)容并不是報(bào)錯(cuò)而是證明RGW已經(jīng)在正常響應(yīng)HTTP請(qǐng)求。線上環(huán)境我不會(huì)用前臺(tái)方式而是寫(xiě)一個(gè)systemd unit文件來(lái)托管。這里給一個(gè)我實(shí)際在用的模板直接放到/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里代表主機(jī)名可以自動(dòng)對(duì)應(yīng)到我們?cè)谡J(rèn)證庫(kù)里注冊(cè)的client.rgw.hostname賬號(hào)不用每個(gè)節(jié)點(diǎn)寫(xiě)死name。如果主機(jī)名帶了域名后綴%h和%H有細(xì)微差別我建議先用hostname -s確認(rèn)短主機(jī)名是什么再?zèng)Q定用哪個(gè)占位符。如果你的集群是用cephadm管理的可以直接用編排命令來(lái)部署多個(gè)網(wǎng)關(guān)實(shí)例本質(zhì)上是讓cephadm替你完成了上述所有步驟ceph orch apply rgw myrgw --placement3 node1 node2 node3 --port 7480這個(gè)命令會(huì)創(chuàng)建名為myrgw的RGW服務(wù)并把實(shí)例調(diào)度到三臺(tái)節(jié)點(diǎn)上。它的優(yōu)點(diǎn)是自帶多副本和服務(wù)發(fā)現(xiàn)缺點(diǎn)是如果你還不熟悉cephadm的service模型出了問(wèn)題排錯(cuò)會(huì)比手動(dòng)部署復(fù)雜不少。4.3 初始化默認(rèn)zone并創(chuàng)建S3用戶網(wǎng)關(guān)進(jìn)程起來(lái)之后我們還需要確認(rèn)RGW的zone配置和用戶體系是完整的。單站點(diǎn)模式下默認(rèn)zone會(huì)自動(dòng)創(chuàng)建通常不需要額外操作。但如果消息日志里提示no zone config found之類的錯(cuò)誤就需要手動(dòng)初始化一次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再?gòu)?qiáng)調(diào)一下這條命令在不同版本、不同集群初始化狀態(tài)下需要的次數(shù)不一樣。我遇到過(guò)有環(huán)境在realm create這一步直接報(bào)already exists那就跳過(guò)它繼續(xù)往下做就好。不要因?yàn)閳?bào)錯(cuò)就反復(fù)執(zhí)行認(rèn)真看輸出內(nèi)容再?zèng)Q定下一步。然后創(chuàng)建第一個(gè)S3用戶radosgw-admin user create --uidtestuser --display-nameTest User --emailtestexample.com正常輸出會(huì)包含一對(duì)access_key和secret_key把它們復(fù)制保存好后續(xù)所有S3客戶端配置都要用。如果忘記了也不用重新創(chuàng)建用戶直接執(zhí)行radosgw-admin user info --uidtestuser就能把密鑰重新查出來(lái)。4.4 S3客戶端冒煙測(cè)試網(wǎng)關(guān)是否真正工作最終要看S3客戶端能不能完整地走一遍創(chuàng)建桶、上傳對(duì)象、下載對(duì)象、刪除對(duì)象這條鏈路。我平時(shí)測(cè)試最常用的是s3cmd和boto3因?yàn)樾瑤渲闷饋?lái)足夠簡(jiǎn)單出現(xiàn)問(wèn)題時(shí)錯(cuò)誤信息也相對(duì)友好。先看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這里最關(guān)鍵的配置是host_base和host_bucket。很多初次接觸RGW的人會(huì)照搬AWS的默認(rèn)配置結(jié)果發(fā)現(xiàn)一直連到AWS站點(diǎn)去。RGW是獨(dú)立網(wǎng)關(guān)服務(wù)必須指向你自己的節(jié)點(diǎn)和端口兩處地址要完全一致。另外use_https必須為False才能在測(cè)試環(huán)境走明文HTTP如果你配置了TLS證書(shū)則可以改成True并指定證書(shū)路徑。s3cmd測(cè)試命令如下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如果能依次執(zhí)行成功說(shuō)明桶創(chuàng)建、對(duì)象上傳、下載、刪除這幾條最基本的路徑都沒(méi)有問(wèn)題。此時(shí)可以用radosgw-admin bucket list查看桶是否存在radosgw-admin user info --uidtestuser查看用戶配額和桶數(shù)量是否有變化。如果你用Python做自動(dòng)化測(cè)試那么boto3是更常見(jiàn)的選擇。我給一個(gè)最小可用的腳本注意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時(shí)一直報(bào)簽名不一致最后發(fā)現(xiàn)是沒(méi)用s3v4簽名版本。RGW對(duì)簽名版本的支持比較嚴(yán)格我建議在Config里統(tǒng)一加上signature_versions3v4不然老版本的簽名算法會(huì)讓服務(wù)器驗(yàn)簽失敗。5. 常見(jiàn)問(wèn)題與排查技巧實(shí)錄5.1 經(jīng)典坑速查表這一步我把真實(shí)環(huán)境里經(jīng)常出現(xiàn)的問(wèn)題整理成一個(gè)速查表每一個(gè)都是我自己踩過(guò)或者幫別人排查過(guò)的。它的價(jià)值在于你可以拿現(xiàn)象去對(duì)號(hào)入座而不用從零開(kāi)始猜測(cè)問(wèn)題在哪一層。問(wèn)題現(xiàn)象真正原因解決方法RGW進(jìn)程起不來(lái)日志報(bào)No such file or directorykeyring路徑不對(duì)或文件屬主不對(duì)檢查/etc/ceph/ceph.client.rgw.keyring是否存在chown ceph:ceph后再啟動(dòng)報(bào)Permission deniedcephx的caps沒(méi)配夠確認(rèn)client.rgw.hostname對(duì)mon和osd都有allow rwx端口無(wú)法監(jiān)聽(tīng)端口被占用或者小于1024換高位端口或給進(jìn)程加網(wǎng)絡(luò)capabilitiesS3客戶端報(bào)AccessDenied系統(tǒng)時(shí)間不同步或簽名算法不匹配同步時(shí)鐘在客戶端強(qiáng)制用s3v4簽名create_bucket一直連不上endpoint_url寫(xiě)錯(cuò)或者網(wǎng)段不通確認(rèn)HTTP地址可以被外部訪問(wèn)curl一下網(wǎng)關(guān)端口看響應(yīng)上傳大文件時(shí)收到500錯(cuò)誤集群空間不足或索引池寫(xiě)滿ceph df檢查容量擴(kuò)容或者清理舊數(shù)據(jù)桶內(nèi)對(duì)象列表為空但數(shù)據(jù)確實(shí)存在索引池和元數(shù)據(jù)池不一致用radosgw-admin bucket check --fix --bucket 桶名重建索引第一條看起來(lái)有點(diǎn)弱智但真的很容易發(fā)生。我會(huì)經(jīng)常同時(shí)管理多套環(huán)境配置文件和keyring用scp拷貝過(guò)來(lái)之后屬主沒(méi)有修正結(jié)果進(jìn)程反復(fù)啟動(dòng)失敗。所以我的習(xí)慣是在systemd unit里明確寫(xiě)Userceph并且啟動(dòng)前手動(dòng)執(zhí)行一次chown -R ceph:ceph /etc/ceph/把整個(gè)配置目錄的屬主統(tǒng)一掉這樣省心很多。第二條和簽名問(wèn)題是最常見(jiàn)的兩類。簽名問(wèn)題在上一段里已經(jīng)提過(guò)權(quán)限問(wèn)題則比較隱蔽因?yàn)镃eph的日志級(jí)別默認(rèn)較低不會(huì)把permission denied這種報(bào)錯(cuò)直接鋪滿屏幕。遇到權(quán)限問(wèn)題時(shí)建議臨時(shí)在配置里增加一行debug rgw 20或者查看/var/log/ceph/目錄下的RGW日志報(bào)錯(cuò)里會(huì)有非常明確的AccessDenied信息。5.2 日志與調(diào)試的實(shí)用技巧RGW的日志分布在不同的地方。如果用cephadm部署一般可以通過(guò)ceph -w看到RGW組件的動(dòng)態(tài)也可以用cephadm logs ceph-radosgw.hostname來(lái)查看某個(gè)網(wǎng)關(guān)容器的日志。手動(dòng)部署時(shí)日志一般落在/var/log/ceph/ceph-client.rgw.hostname.log如果沒(méi)找到需要確認(rèn)是不是systemd直接接管了標(biāo)準(zhǔn)輸出。調(diào)試階段建議把日志級(jí)別臨時(shí)調(diào)高在ceph.conf的[client.rgw.hostname]段里加上debug rgw 20 debug librados 5然后重啟服務(wù)日志會(huì)非常冗長(zhǎng)墨水瓶的朋友可能會(huì)被刷屏但這種級(jí)別的信息量對(duì)定位問(wèn)題非常有幫助。調(diào)完之后記得把debug rgw重新改回默認(rèn)值否則生產(chǎn)環(huán)境日志量會(huì)拖垮磁盤(pán)。還有一個(gè)小技巧不用S3客戶端也能快速確認(rèn)網(wǎng)關(guān)狀態(tài)。直接用curl發(fā)一個(gè)匿名請(qǐng)求curl -I http://127.0.0.1:7480如果返回HTTP狀態(tài)碼200或者405甚至403都說(shuō)明RGW本身在正常工作如果返回連接超時(shí)或拒絕連接問(wèn)題大概率在網(wǎng)絡(luò)層或進(jìn)程層而不是在API層。5.3 性能與高可用的進(jìn)一步動(dòng)作基礎(chǔ)搭建完成后很多人的第一反應(yīng)是“是不是再調(diào)一調(diào)性能”。我會(huì)建議分兩步走。第一步是把多個(gè)RGW實(shí)例拉起來(lái)讓并發(fā)請(qǐng)求可以分散到多臺(tái)機(jī)器上這是最直接的吞吐擴(kuò)展方式??梢园褍蓚€(gè)RGW實(shí)例跑在同一臺(tái)機(jī)器上的不同端口也可以分散到不同機(jī)器然后在前面用負(fù)載均衡器將流量均攤。負(fù)載均衡這一層我用的比較順手的方案是直接用Nginx的upstream方式把流媒體請(qǐng)求和普通API請(qǐng)求都代理到后端的RGW端口。關(guān)鍵配置如下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一定要設(shè)置為0否則上傳大文件時(shí)會(huì)被Nginx攔下來(lái)返回413 Request Entity Too Large。這個(gè)坑我踩過(guò)不止一次每次新配環(huán)境都要提醒自己。第二個(gè)方向是調(diào)整RGW本身的數(shù)據(jù)分片和配額。rgw_bucket_default_quota_max_objects和rgw_bucket_default_quota_max_size要跟實(shí)際使用場(chǎng)景匹配。如果是一個(gè)備份系統(tǒng)對(duì)象數(shù)量和單桶容量都要留足余量如果是一個(gè)靜態(tài)站那就要考慮對(duì)象數(shù)量是否會(huì)影響列舉速度。6. 寫(xiě)在搭建之后的話RGW搭建本身不算難每一步都有固定套路真正讓我覺(jué)得有學(xué)習(xí)價(jià)值的是過(guò)程中對(duì)Ceph整個(gè)存儲(chǔ)體系的理解。第一點(diǎn)體會(huì)是不要把RGW當(dāng)成一個(gè)“裝好就能用”的獨(dú)立服務(wù)它跟池的規(guī)劃、集群的健康狀態(tài)、客戶端的簽名方式都耦合得很深任何一個(gè)環(huán)節(jié)疏忽都會(huì)在后續(xù)使用中暴露出來(lái)。第二點(diǎn)是我很推薦先用最樸素的s3cmd把完整鏈路跑通再上自動(dòng)化框架和腳本因?yàn)閟3cmd的報(bào)錯(cuò)信息更直接排查起來(lái)沒(méi)有層層包裝的干擾。最后再分享一個(gè)日常運(yùn)維的小習(xí)慣每次改完RGW相關(guān)配置或者重啟服務(wù)之后我都會(huì)立刻執(zhí)行一次radosgw-admin bucket list和radosgw-admin user info --uidtestuser確認(rèn)網(wǎng)關(guān)進(jìn)程的API側(cè)還活著。這樣即使稍后出現(xiàn)了異常也能快速判斷問(wèn)題是在進(jìn)程層、API層還是底層存儲(chǔ)層。對(duì)象存儲(chǔ)的價(jià)值是讓?xiě)?yīng)用按需讀寫(xiě)數(shù)據(jù)而RGW穩(wěn)定的前提其實(shí)是你對(duì)它的運(yùn)行機(jī)制有足夠的掌控感。