「網紅架構師」解決你的Ceph 運維難題

Q1. 環境預準備

絕大多數MON創建的失敗都是由於防火牆沒有關導致的,亦或是SeLinux沒關閉導致的。一定一定一定要關閉每個每個每個節點的防火牆(執行一次就好,沒安裝報錯就忽視):

CentOS

sed -i 's/SELINUX=.*/SELINUX=disabled/' /etc/selinux/config
setenforce 0
systemctl stop firewalld
systemctl disable firewalld
# iptables -F
service iptables stop

Q2. 清理環境

MON部署不上的第二大問題就是在舊的節點部署MON,或者在這個節點部署MON失敗了,然後重新new再mon create-initial,請查看要部署MON的節點上的/var/lib/ceph/mon/目錄下是否為空,如果不為空,說明已經在這個目錄部署過MON,再次部署會檢測子目錄下的done文件,由於有了這個文件,就不會再建立新的MON數據庫,並且不會覆蓋之,導致了部署時的各種異常,這裡就不贅述了,直接給出萬能清理大法:

對於任何需要新部署MON的節點,請到這個節點下執行如下指令,確保環境已經清理乾淨:

ps aux|grep ceph |awk '{print $2}'|xargs kill -9
ps -ef|grep ceph
#確保此時所有ceph進程都已經關閉!!!如果沒有關閉,多執行幾次。
rm -rf /var/lib/ceph/mon/*
rm -rf /var/lib/ceph/bootstrap-mds/*
rm -rf /var/lib/ceph/bootstrap-osd/*
rm -rf /var/lib/ceph/bootstrap-rgw/*
rm -rf /etc/ceph/*
rm -rf /var/run/ceph/*

請直接複製粘貼,遇到過好些個自己打錯打漏刪了目錄的。

Q3. 部署前最後的確認

這裡介紹的都是個案,不過還是需要提一下:

  • 確保每個節點的hostname都設置正確,並且添加至/etc/hosts文件中,然後同步到所有節點下。克隆出來的虛擬機或者批量建的虛擬機有可能發生此情形。
  • 確保以下目錄在各個節點都存在:
  • /var/lib/ceph/
  • /var/lib/ceph/mon/
  • /var/lib/ceph/osd/
  • /etc/ceph/
  • /var/run/ceph/
  • 上面的目錄,如果Ceph版本大於等於jewel,請確認權限均為ceph:ceph,如果是root:root,請自行chown。

Q4. 安裝Ceph

官網指導方法是使用ceph-deploy install nodeX,但是因為是國外的源,速度慢得令人髮指,所以我們換到阿里的源,並且使用yum install的方式安裝,沒差啦其實,這樣反而還快點,畢竟多個節點一起裝。

很多安裝失敗的都是因為沒有添加epel源請在每個存儲節點都執行以下指令,來安裝Ceph:

yum clean all
rm -rf /etc/yum.repos.d/*.repo
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
sed -i '/aliyuncs/d' /etc/yum.repos.d/CentOS-Base.repo
sed -i '/aliyuncs/d' /etc/yum.repos.d/epel.repo
sed -i 's/$releasever/7.2.1511/g' /etc/yum.repos.d/CentOS-Base.repo
echo "
[ceph]
name=ceph
baseurl=http://mirrors.aliyun.com/ceph/rpm-hammer/el7/x86_64/
gpgcheck=0
[ceph-noarch]
name=cephnoarch
baseurl=http://mirrors.aliyun.com/ceph/rpm-hammer/el7/noarch/
gpgcheck=0
" > /etc/yum.repos.d/ceph.repo
yum install ceph ceph-radosgw -y

這裡是安裝的hammer版本的Ceph,如果需要安裝jewel版本的,請執行:

sed -i 's/hammer/jewel/' /etc/yum.repos.d/ceph.repo
yum install ceph ceph-radosgw -y

如果安裝了jewel版本的Ceph,想要換回hammer版本的Ceph,可以執行下面的指令:

卸載Ceph客戶端

rpm -qa |grep `ceph -v |awk '{print $3}'` |xargs rpm -e --nodeps

更改ceph.repo裡面的Ceph版本

sed -i 's/jewel/hammer/' /etc/yum.repos.d/ceph.repo
yum install ceph ceph-radosgw -y

Q5. ceph-deploy

這裡我要開啟話嘮模式:

① Ceph-deploy 是什麼?

Ceph-deploy是Ceph官方給出的用於部署Ceph的一個工具,這個工具幾乎全部是Python寫的腳本,其代碼位於/usr/lib/python2.7/site-packages/ceph_deploy目錄下(1.5.36版本)。最主要的功能就是用幾個簡單的指令部署好一個集群,而不是手動部署操碎了心,敲錯一個地方就可能失敗。所以對於新人來說,或者說以我的經驗,接觸Ceph少於一個月的,又或者說,集群規模不上PB的,都沒有必要手動部署,Ceph-deploy完全足夠了。

② Ceph-deploy怎麼裝?

這個包在ceph的源裡面:

yum install ceph-deploy -y

③Ceph-deploy裝在哪?

既然Ceph-deploy只是個部署Ceph的腳本工具而已,那麼這個工具隨便裝在哪個節點都可以,並不需要單獨為了裝這個工具再搞個節點,我一般習慣放在第一個節點,以後好找部署目錄。

④Ceph-deploy怎麼用?

詳細的指令暫時不介紹,下面會有,在安裝好後,需要在這個節點新建一個目錄,用作部署目錄,這裡是強烈建議建一個單獨的目錄的,比如我習慣在集群的第一個節點下建一個/root/cluster目錄,為了以後好找。Ceph-deploy的所有的指令都需要在這個目錄下執行。包括new,mon,osd等等一切ceph-deploy的指令都需要在這個部署目錄下執行!最後一遍,所有的ceph-deploy的指令都要在部署目錄下執行!否則就會報下面的錯:

[ceph_deploy][ERROR ] ConfigError: Cannot load config: [Errno 2] No such file or directory: 'ceph.conf'; has ceph-deploy new been run in this directory?

⑤ Ceph-deploy怎麼部署集群?

我們暫且把部署目錄所在的節點叫做部署節點。Ceph-deploy通過SSH到各個節點,然後再在各個節點執行本機的Ceph指令來創建MON或者OSD等。所以在部署之前,你需要從部署節點ssh-copy-id到各個集群節點,使其可以免秘鑰登陸。

⑥Ceph-deploy部署的日誌在哪裡?

就在部署目錄下面的ceph-deploy-ceph.log文件,部署過程中產生的所有的日誌都會保存在裡面,比如你大半年前敲的創建OSD的指令。在哪個目錄下執行ceph-deploy指令,就會在這個目錄下生成log,如果你跑到別的目錄下執行,就會在執行目錄裡生成log再記下第四點的錯。當然,這個LOG最有用的地方還是裡面記錄的部署指令,你可以通過cat ceph-deploy-ceph.log |grep "Running command"查看到創建一個集群所需的所有指令,這對你手動建立集群或者創建秘鑰等等等等有著很大的幫助!!!

⑦ Ceph-deploy版本

寫這段時的最新的版本號為1.5.36,下載鏈接為ceph-deploy-1.5.36-0.noarch.rpm, 之前的1.5.35裡面有點bug在這個版本被修復了,如果使用1.5.25部署遇到了問題,可以更新至這個版本,會繞過一些坑。更新到1.5.36之後,腰也不酸了,退了不疼了,Ceph也能部署上了。

Q6. ceph-deploy new 做了什麼

進入部署目錄,執行ceph-deploy new node1 node2 node3,會生成兩個文件(第三個是ceph-deploy-ceph.log,忽視之):

[root@blog cluster]# ls
ceph.conf ceph-deploy-ceph.log ceph.mon.keyring

new後面跟的是你即將部署MON的節點的hostname,推薦三個就夠了,需要是奇數個MON節點。不要因為只有兩個節點就搞兩個MON,兩個節點請用一個MON,因為兩個MON掛掉一個,集群也就掛了,和一個MON掛掉一個效果是一樣的。生成的ceph.conf默認情況下長成這樣:

[root@blog cluster]# cat ceph.conf 
[global]
fsid = 13b5d863-75aa-479d-84ba-9e5edd881ec9
mon_initial_members = blog
mon_host = 1.2.3.4
auth_cluster_required = cephx
auth_service_required = cephx
auth_client_required = cephx

會調用uuidgen生成一個fsid,用作集群的唯一ID,再將new後面的主機加入到mon_initial_members和mon_host裡面,剩下的三行大家都是一樣的,默認開啟CephX認證。下面有一節會專門介紹這個,需要注意的是,

部署的時候,千萬不要動這三行 下面會有一節介紹之。還有一個文件ceph.mon.keyring:

[root@blog cluster]# cat ceph.mon.keyring 
[mon.]
key = AQB1yWRYAAAAABAAhMoAcadfCdy9VtAaY79+Sw==
caps mon = allow *

除了key的內容不一樣,剩下的都會是一樣的。因為是開啟了CephX認證了,所以MON直接的通訊是需要一個秘鑰的,key的內容就是秘鑰。是不是對Ceph裡面的明文認證感到吃驚,有總比沒有強。如果,你再次執行new,會生成新的ceph.conf和新的ceph.mon.keyring,並將之前的這兩個文件給覆蓋掉,新舊文件唯一不同的就是fsid和key的內容,但是對Ceph來說,這就是兩個集群了。這裡說一下我個人非常非常非常反感的一個問題,有的朋友喜歡在/etc/ceph/目錄下面執行ceph-deploy的命令,這麼做和在部署目錄下面做一般是沒有差別的,因為這兩個目錄下面都有ceph.conf和ceph.client.admin.keyring,但是我還是強烈推薦創建獨立的部署目錄,因為/etc/ceph目錄是Ceph節點的運行目錄,為了體現各自的功能性,也為了安全性,請不要在**/etc/ceph**目錄下部署集群!!!

Q7. 為ceph-deploy添加參數

Ceph-deploy的log還是很有看頭的,查看ceph-deploy new blog(blog是我的一臺主機)的log:

[root@blog cluster]# ceph-deploy new blog
[ceph_deploy.conf][DEBUG ] found configuration file at: /root/.cephdeploy.conf
[ceph_deploy.cli][INFO ] Invoked (1.5.36): /usr/bin/ceph-deploy new blog
[ceph_deploy.cli][INFO ] ceph-deploy options:
[ceph_deploy.cli][INFO ] username : None
[ceph_deploy.cli][INFO ] func :
[ceph_deploy.cli][INFO ] verbose : False
[ceph_deploy.cli][INFO ] overwrite_conf : False
[ceph_deploy.cli][INFO ] quiet : False
[ceph_deploy.cli][INFO ] cd_conf :
[ceph_deploy.cli][INFO ] cluster : ceph
[ceph_deploy.cli][INFO ] ssh_copykey : True
[ceph_deploy.cli][INFO ] mon : ['blog']
[ceph_deploy.cli][INFO ] public_network : None
[ceph_deploy.cli][INFO ] ceph_conf : None
[ceph_deploy.cli][INFO ] cluster_network : None
[ceph_deploy.cli][INFO ] default_release : False
[ceph_deploy.cli][INFO ] fsid : None
[ceph_deploy.new][DEBUG ] Creating new cluster named ceph

可以看到有很多的參數被列出來了,比如:mon : ['blog'],也有很多參數是False或者None, 這些參數能否被設置呢? 因為這裡我們可以看到有fsid : None 這個參數,難道集群的fsid可以被指定嗎?抱著這些疑惑,我就去看完了ceph-deploy的所有代碼,答案是:可以設置。所有上面的參數都可以使用參數的形式進行設置,只需要在前面加上兩個--,比如對於fsid可以執行:

ceph-deploy new blog --fsid xx-xx-xx-xxxx

如果想要查看每個執行可指定的參數,可以-h:

[root@blog cluster]# ceph-deploy new -h
usage: ceph-deploy new [-h] [--no-ssh-copykey] [--fsid FSID]
[--cluster-network CLUSTER_NETWORK]
[--public-network PUBLIC_NETWORK]
MON [MON ...]
...
optional arguments:
-h, --help show this help message and exit
--no-ssh-copykey do not attempt to copy SSH keys
--fsid FSID provide an alternate FSID for ceph.conf generation
--cluster-network CLUSTER_NETWORK
specify the (internal) cluster network
--public-network PUBLIC_NETWORK
specify the public network for a cluster

這裡就可以看到可以指定--cluster-network,--public-network,等等,如果optional arguments裡面沒有介紹這個參數,可以直接使用--xxarg的方式指定,比如--overwrite-conf,--verbose等等,能不能設置這些參數,自己動手試一下就知道了。需要注意的是,參數的位置根據指令而異,比如--overwrite-conf參數是跟在ceph-deploy後面的,而--public-network是跟在new後面的:

ceph-deploy --overwrite-conf --verbose new blog --fsid a-a-a-a
[root@blog cluster]# cat ceph.conf |grep fsid
fsid = a-a-a-a

Q8. Public VS Cluster

如果非要在剛剛生成的ceph.conf裡面添加什麼的話,那麼可能就要加public_network或者cluster_network了。那麼這兩個配置項有什麼用呢?這裡簡單得介紹下Ceph的Public(外網或者叫公網或者前端網)和Cluster(內網或者叫集群網或者叫後端網)這兩個網絡,在Ceph中,存在以下三種主要的網絡通訊關係:

  • client-> mon =>public : 也就是客戶端獲取集群狀態,或者叫客戶端與MON通訊走的網絡,是走的外網。
  • client-> osd => public : 也就是客戶端向OSD直接寫入數據走的也是外網。
  • osd osd => cluster :也就是OSD之間的數據克隆,恢復走的是內網,客戶端寫第一份數據時通過外網寫,對於三副本剩下的兩個副本OSD之間通過內網完成數據複製。當OSD掛掉之後產生的recover,走的也是內網。

通常,我們會將外網配置為千兆網,而內網配置成萬兆網,這是有一定原因的:

  • 客戶端可能由成百上千的計算節點組成,外網配成萬兆成本太高。
  • 存儲節點一般只有幾個到幾十個節點,配置了萬兆內網可以大大加快故障恢復速度,而且剩餘的兩副本寫速度會大大加快,萬兆網的性價比極高。舉個例子,集群壞掉一個OSD千兆需要一小時,那麼萬兆網只需要五六分鐘,一定程度上增加了集群的安全性。

借用官網的這張圖來說明集群的網絡走勢:再假設你的節點有兩個網段172.23.0.1和3.3.4.1,還記得我們上一節ceph-deploy new的時候是可以指定public_network和cluster_network的嗎!如果不指定這兩個參數,那麼ceph-deploy怎麼知道用哪個IP作為這個節點的mon_host的IP呢,其實他是隨便選的,如果它選了172網段但是你想使用3.3網段作為這個節點的mon_host的IP,那麼只需要指定--public-network 172.23.0.0/24 就可以了,其中的/24就相當於一個掩碼,表示前面的IP的前24位,也就是172.23.0.XXX,只要你的主機上有一個處於這個範圍內的IP,那麼就會選擇這個IP作為公網IP。類似的,/16表示範圍:172.23.XXX.XXX。 如果想指定內網IP,那麼只要指定--cluster-network 3.3.4.1/24就可以了。

一般情況下,會在new生成的ceph.conf文件里加入public_network配置項以指定公網IP。當然你的MON主機上需要有至少一個IP在公網範圍內。除了在生成的ceph.conf文件中加入公網IP的方式,我們還可以使用參數的方式來指定公網IP:

[root@ceph-1 cluster]# ceph-deploy new ceph-1 --public-network 172.23.0.0/24
[ceph_deploy.cli][INFO ] Invoked (1.5.36): /usr/bin/ceph-deploy new ceph-1 --public-network 172.23.0.0/24
[ceph_deploy.cli][INFO ] ceph-deploy options:
...
[ceph_deploy.cli][INFO ] public_network : 172.23.0.0/24
...
[ceph-1][DEBUG ] IP addresses found: [u'172.23.0.101', u'10.0.2.15']
[ceph_deploy.new][DEBUG ] Resolving host ceph-1
[ceph_deploy.new][DEBUG ] Monitor ceph-1 at 172.23.0.101
[ceph_deploy.new][DEBUG ] Monitor initial members are ['ceph-1']
[ceph_deploy.new][DEBUG ] Monitor addrs are [u'172.23.0.101']
[ceph_deploy.new][DEBUG ] Writing monitor keyring to ceph.mon.keyring...
[ceph_deploy.new][DEBUG ] Writing initial config to ceph.conf...
[root@ceph-1 cluster]# cat ceph.conf
[global]
fsid = d2a2bccc-b215-4f3e-922b-cf6019068e76
public_network = 172.23.0.0/24
mon_initial_members = ceph-1
mon_host = 172.23.0.101
auth_cluster_required = cephx
auth_service_required = cephx
auth_client_required = cephx

查看部署log可以發現參數配置已經生效,而這個節點有兩個IP,public_nwtwork這個參數限定了公網IP的搜索範圍,生成的ceph.conf文件內也包含了public_network這個參數。

Q9. 參數是下劃線還是空格分隔

這裡只是簡單的提一下這個小困惑,對於以下的兩個參數書寫方式,哪種會有問題呢:

public_network = 172.23.0.1/24
public network = 172.23.0.1/24
osd_journal_size = 128
osd journal size = 128

這兩種參數的書寫方式其實都是正確的,說到底是因為底層調用的是Python的argparse模塊。這兩種方式都是等效的,所以不需要擔心。

Q10. ceph-deploy mon create-initial如何一次性通過

這一步坑哭了多少迫切加入Ceph世界的新人,看到的最多的就是5s,10s,10s, 15s,20s。。。然後報了錯。再執行,再報錯。所以這裡給出以下的預檢清單,如果被報錯失敗所煩惱,請認真執行各個子項,尤其是失敗後要執行清理環境:

  1. 請確保所有節點都安裝了Ceph。
  2. 請確保所有節點的防火牆等都關閉了。參考環境預準備一節
  3. 請前往各個MON節點清理乾淨,不論你是否相信這個節點是乾淨的。參考清理環境一節。
  4. 請確保各個MON節點下存在以下目錄,並且對於Jewel版本及之後的請確保目錄權限為ceph:ceph。參考
    部署前最後的確認一節。
  5. 請在ceph-deploy new生成的ceph.conf內添加public_network配置項,參考Public VS Cluster一節。

這些總結來之不易,我幫過上百個人解決過部署問題和集群故障。我相信在認真確認過之後是肯定可以通過的(反正前三點如果有問題一般是不會建好MON的,為什麼不認真確認下呢),我遇到過絕大多數都是因為防火牆沒關,或者手動刪除了一些目錄,或者沒有修改權限導致的問題。

相對來說,新環境只要關了防火牆就可以一次性通過,舊環境或者失敗的環境只要清理環境就可以通過了。

Q11. mon create-initial 做了什麼

簡單介紹下流程:

  • ceph-deploy讀取配置文件中的
mon_initial_members
  • 的各個主機,然後依次SSH前往各個主機:
  1. 部署目錄下的ceph.conf推送到新節點的/etc/ceph/目錄下。
  2. 創建/var/lib/ceph/mon/$cluster-$hostname/目錄。
  3. 檢查MON目錄下是否有done文件,如果有則直接跳到第6步。
  4. 將ceph.mon.keyring拷貝到新節點,並利用該秘鑰在MON目錄下建立MON數據庫。
  5. 在MON目錄下建立done文件,防止重新建立MON。
  6. 啟動MON進程。
  7. 查看/var/run/ceph/$cluster-mon.$hostname.asokSOCKET文件,這個是由MON進程啟動後生成的,輸出MON狀態。
  • 在所有的MON都建立好後,再次前往各個主機,查看所有主機是否運行並且到達法定人群(quorum)。如果有沒到到的,直接結束報錯。如果都到達了,執行下一步。
  • 調用
auth get-or-create
  • 方法創建(如果不存在)或者拉取(已經存在)MON節點上的以下幾個keyring到
  • 部署目錄
  • 中:
  • ceph.bootstrap-mds.keyring
  • ceph.bootstrap-osd.keyring
  • ceph.bootstrap-rgw.keyring
  • ceph.client.admin.keyring
  • 指令結束。

Q12. mon create-initial 為什麼會失敗

我不喜歡講怎麼做,我願意花很大的篇幅介紹為什麼會造成各種各樣的問題,如果知道了原因,你自然知道該怎麼做,所以才會理解Ceph,而不是機械的去敲指令。

綜合上面的所有小節,我來總結下這一步失敗的基本上所有可能的原因:

  • 所謂MON的quorum,相當於多個MON形成的一個群體,它們之間需要通過網絡發送數據包來通訊達成某種協議,如果打開了防火牆,會阻斷數據交流。所以不能構成群體,一直等待(5s->10s->10s->15s->20s)其他MON的數據包,既然被阻斷了這樣的等待是沒有意義的,等了30s還沒有正常,就可以直接ctrl+z去檢查了。
  • 我在配置文件裡面添加了pubilc_network,但是有個主機的所有IP都不在公網IP段內,那麼這個MON是建不好的,因為沒有IP用作MON使用,public_network相當於一個過濾器
  • 搭好了一臺虛擬機後,直接克隆了兩臺,沒有修改主機名,導致socket文件路徑名識別錯誤,報了異常,不過這很少發生。
  • 如果在舊的MON節點上再次部署新的MON,再又沒有清理環境,之前的MON數據庫會保留著done文件,MON數據庫裡面還是記錄著之前fsid,keyring等等,和新集群是兩套完全不同的,所以這個節點的MON自然到達不了MON群體。
  • 即使你單單刪除了/var/lib/ceph/mon下的東西,而沒有清理那些keyring,也有可能會因為收集了舊集群的秘鑰而發生稀奇古怪的問題。
  • 對於Jewel,你一不小心刪除了/var/lib/ceph/mon目錄,或者其他的OSD目錄或者/var/run/ceph目錄,然後又重建了目錄,依然部署不上,是因為Jewel的所有Ceph指定都是運行在ceph:ceph用戶下的,自然不能在root權限目錄下建立任何文件,修改權限即可。
  • Ceph生成MON數據庫是依照主機的hostname來命名至目錄/var/lib/ceph/mon/${cluster}-${hostname}的,而檢測SOCKET文件則是用ceph.conf裡面的mon_initial_members裡面的名字來檢測的 ,如果mon_initial_members裡面的名字和真是的主機名不一致,就會報錯。

​ 一旦你運行了ceph-deploy mon create-initial指令,並且失敗了,有極大的可能性已經在某些節點建立好了MON的數據庫,再次執行可能會因為舊的環境導致再次失敗,所以如果失敗了,執行一下第二節中的清理環境即可。清理完畢後,再執行ceph-deploy mon create-initial。


分享到:


相關文章: