“網紅架構師”解決你的Ceph 運維難題

騰訊雲加社群發表於2018-10-15

歡迎大家前往騰訊雲+社群,獲取更多騰訊海量技術實踐乾貨哦~

本文由Tstack發表於雲+社群專欄

本文為長篇連續劇,將分多個篇幅發表,主要介紹了從動手部署環境到後期運營故障處理過程中常見的問題,內容由淺入深,是居家旅行運維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失敗了,然後重新newmon 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_membersmon_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,並將之前的這兩個檔案給覆蓋掉,新舊檔案唯一不同的就是fsidkey的內容,但是對Ceph來說,這就是兩個叢集了。這裡說一下我個人非常非常非常反感的一個問題,有的朋友喜歡在/etc/ceph/目錄下面執行ceph-deploy的命令,這麼做和在部署目錄下面做一般是沒有差別的,因為這兩個目錄下面都有ceph.confceph.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                          : <function new at 0x288e2a8>
[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.conf.cephdeploy.Conf instance at 0x28eccf8>
[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_networkcluster_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

相關閱讀

RMAN 配置、監控與管理

Hadoop學習11--Ha叢集配置啟動

rsync 服務部署詳解

【每日課程推薦】機器學習實戰!快速入門線上廣告業務及CTR相應知識

此文已由作者授權騰訊雲+社群釋出,更多原文請點選

搜尋關注公眾號「雲加社群」,第一時間獲取技術乾貨,關注後回覆1024 送你一份技術課程大禮包!

海量技術實踐經驗,盡在雲加社群

相關文章