場景介紹:在咱們的IDC中,存在着運行了3-6年的Ceph集羣的服務器,這些服務器性能和容量等都已經沒法知足當前業務的需求,在購入一批高性能機器後,但願將舊機器上的集羣總體遷移到新機器上,固然,是保證業務不中斷的前提下,再將舊機器下架回收。本文就介紹了一種實現業務不中斷的數據遷移方案,並已經在多個生產環境執行。python
本文的環境均爲:Openstack+Ceph 運行虛擬機的場景,即主要使用RBD,不包含RGW,MDS。虛機的系統盤(Nova),雲硬盤(Cinder),鏡像盤(Glance)的塊均保存在共享存儲Ceph中。mysql
環境準備
linux
本文環境爲 Openstack (Kilo) + Ceph(Jewel)git
本文所用的環境包含一套完整的 Openstack 環境,一套 Ceph 環境,其中 Nova/Cinder/Glance 均已經對接到了 Ceph 集羣上,具體節點配置以下:github
主機名 | IP地址 | Openstack 組件 | Ceph 組件 |
---|---|---|---|
con | 192.168.100.110 | nova,cinder,glance,neutron | mon,osd*1 |
com | 192.168.100.111 | nova,neutron | mon,osd*1 |
ceph | 192.168.100.112 | mon,osd*1 |
在集羣總體遷移完後,各個組件分佈以下,也就是說,將運行於 con,com,ceph三個節點的 Ceph 集羣遷移到 new_mon_1,new_mon_2,new_mon_3 這三臺新機器上。算法
主機名 | IP地址 | Openstack 組件 | Ceph 組件 |
---|---|---|---|
con | 192.168.100.110 | nova,cinder,glance,neutron | |
com | 192.168.100.111 | nova,neutron | |
ceph | 192.168.100.112 | ||
new_mon_1 | 192.168.100.113 | mon,osd*1 | |
new_mon_2 | 192.168.100.114 | mon,osd*1 | |
new_mon_3 | 192.168.100.115 | mon,osd*1 |
在遷移以前,咱們建立一個虛機,一個雲盤,上傳一個鏡像,虛機此時正常運行,並將這這塊雲盤掛載到虛機上:sql
[root@con ~(keystone_admin)]# nova list
+--------------------------------------+---------+--------+------------+-------------+-------------------------+
| ID | Name | Status | Task State | Power State | Networks |
+--------------------------------------+---------+--------+------------+-------------+-------------------------+
| 4f52191f-9645-448f-977b-80ca515387f7 | vm-test | ACTIVE | - | Running | provider=192.168.88.111 |
+--------------------------------------+---------+--------+------------+-------------+-------------------------+
[root@con ~(keystone_admin)]# cinder list
+--------------------------------------+--------+--------------+------+-------------+----------+--------------------------------------+
| ID | Status | Display Name | Size | Volume Type | Bootable | Attached to |
+--------------------------------------+--------+--------------+------+-------------+----------+--------------------------------------+
| 39c76d96-0f95-490c-b7db-b3da6d17331b | in-use | cinder-rbd | 1 | None | false | 4f52191f-9645-448f-977b-80ca515387f7 |
+--------------------------------------+--------+--------------+------+-------------+----------+--------------------------------------+
[root@con ~(keystone_admin)]# ip netns exec `ip netns` ssh cirros@192.168.88.111
cirros@192.168.88.111's password:
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
vda 253:0 0 1G 0 disk
`-vda1 253:1 0 1011.9M 0 part /
vdb 253:16 0 1G 0 disk
$
Ceph 集羣狀態:數據庫
[root@ceph cluster]# ceph -s
cluster 166889ab-fa7b-4a07-83da-6dfc92913a3d
health HEALTH_OK
monmap e47: 3 mons at {ceph=192.168.100.112:6789/0,com=192.168.100.111:6789/0,con=192.168.100.110:6789/0}
election epoch 174, quorum 0,1,2 con,com,ceph
osdmap e57: 3 osds: 3 up, 3 in
flags sortbitwise,require_jewel_osds
pgmap v6577: 768 pgs, 3 pools, 45659 kB data, 23 objects
178 MB used, 766 GB / 766 GB avail
768 active+clean
[root@ceph cluster]# ceph osd tree
ID WEIGHT TYPE NAME UP/DOWN REWEIGHT PRIMARY-AFFINITY
-1 0.74876 root default
-2 0.24959 host ceph
0 0.24959 osd.0 up 1.00000 1.00000
-3 0.24959 host con
1 0.24959 osd.1 up 1.00000 1.00000
-4 0.24959 host com
2 0.24959 osd.2 up 1.00000 1.00000
[root@ceph cluster]# ceph osd pool ls detail
pool 1 'volumes' replicated size 2 min_size 1 crush_ruleset 0 object_hash rjenkins pg_num 256 pgp_num 256 last_change 58 flags hashpspool stripe_width 0
removed_snaps [1~3]
pool 2 'vms' replicated size 2 min_size 1 crush_ruleset 0 object_hash rjenkins pg_num 256 pgp_num 256 last_change 59 flags hashpspool stripe_width 0
removed_snaps [1~3]
pool 3 'images' replicated size 2 min_size 1 crush_ruleset 0 object_hash rjenkins pg_num 256 pgp_num 256 last_change 60 flags hashpspool stripe_width 0
removed_snaps [1~9]
本次遷移主要分爲兩個組件的遷移,即 MON 和 OSD,這裏咱們先介紹 OSD 的數據遷移。相比遷移MON來講,OSD的數據遷移步驟更爲單純一些,由於全部操做均在 Ceph 側執行,對 Openstack 來講是透明的。vim
因爲CRUSH算法的僞隨機性,對於一個PG來講,若是 OSD tree 結構不變的話,它所分佈在的 OSD 集合老是固定的(同一棵tree下的OSD結構不變/不增減),即對於兩副原本說: PG 1.0 => [osd.66, osd.33]安全
當副本數減小時,PG 1.0 => [osd.66] ,也就是說會刪除在osd.33上的第二副本,而在 osd.66上的主副本是維持不變的,因此在下降副本數時,底層OSD實際上只刪除了一份副本,而並無發生數據的遷移。
當副本數增長時,PG 1.0 => [osd.66, osd.33, osd.188, osd.111],也就是說四副本的前兩個副本依舊是以前的兩個副本,然後面增長的兩副本會從主副本osd.66將數據backfill到各自的OSD上。
咱們首先會將新的節點的全部OSD初始化完畢,而後將這些OSD 加入到另外一棵osd tree下 (這裏簡稱原先的集羣的osd tree叫作old_tree,新建的包含新OSD的 osd tree 叫作 new_tree),這樣部署完畢後,不會對原有集羣有任何影響,也不會涉及到數據遷移的問題,此時新的OSD下尚未保存數據。
導出 CRUSHMAP,編輯,添加三條 CRUSH rule:
• crush rule 0 (原先默認生成的): 從 old_tree 下選出size副本(這裏size=2)。
• crush rule 1 (新生成的第一條): 從 old_tree 下選出兩副本。對於副本數爲2的集羣來講,crush_rule_0 和 crush_rule_1 選出的兩副本是同樣的。
• crush rule 2 (新生成的第二條): 從 old_tree 下選出兩副本,再從 new_tree 下選出兩副本。由**原理簡介第二段**可知, 因爲 old_tree 下面的 OSD結構不變也沒有增長,因此 crush_rule_0 和 crush_rule_1 選出的前兩副本是**同樣的**。
• crush rule 3 (新生成的第三條): 從 new_tree 下選出兩副本。 因爲crush_rule_1 的第二次選擇爲選出 new_tree下的前兩副本,這和 crush_rule_2 選出兩副本(也是前兩副本)實際上是**同樣的**。
注入新的CRUSHMAP後,咱們作以下操做:
• 將全部pool(固然建議一個pool一個pool來,後面相似) 的 CRUSH RULE 從 crush_rule_0 設置爲 crush_rule_1 ,此時全部PG均保持active+clean,狀態沒有任何變化。
• 將全部pool的副本數設置爲4, 因爲此時各個 pool 的CRUSH RULE 均爲 crush_rule_1 ,而這個 RULE 只能選出兩副本,剩下兩副本不會被選出,因此此時全部PG狀態在從新 peer 以後,變爲 active + undersized + degraded,因爲不會生成新的三四副本,因此集羣沒有任何數據遷移(backfill) 動做,此步驟耗時短暫。
• 將全部pool的 CRUSH RULE 從 crush_rule_1 設置爲 crush_rule_2,此時上一條動做中沒有選出的三四副本會從 new_tree 下選出,而且原先的兩副本不會發生任何遷移,整個過程宏觀來看就是在 old_tree -> new_tree 單向數據複製克隆生成了新的兩副本,而舊的兩副本沒有移動。此時生成新的兩副本耗時較長,取決於磁盤性能帶寬數據量等,可能須要幾天到一週的時間,全部數據恢復完畢後,集羣全部PG變爲 active+clean 狀態。
• 將全部pool的 CRUSH RULE 從 crush_rule_2 設置爲 crush_rule_3,此時全部PG狀態會變爲 active+remapped,發生的另外一個動做是,原先四副本的PG的主副本是在 old_tree 上的某一個OSD上的,如今這個PG的主副本變爲 new_tree下的選出的第一個副本,也就是發生了主副本的切換。好比原先 PG 1.0 => [osd.a, osd.b, osd.c, osd.d] 在這步驟以後會變成 PG 1.0 => [osd.c, osd.d]。原先的第三副本也就是new_tree下的第一副本升級爲主副本。
• 將全部pool的副本數設置爲2,此時PG狀態會很快變爲 active+clean,而後在OSD層開始刪除 old_tree 下的全部數據。此時數據已經所有遷移到新的OSD上。
必定要記住:在部署目錄下的ceph.conf內添加 osd_crush_update_on_start =false,再開始部署新的OSD,而且必定要檢查新節點配置,包括但不限於: yum 源,免祕鑰配置,ceph的版本,主機名,防火牆,selinux,ntp,ntp,ntp,重要的時間對齊說三遍!
部署新的OSD:
### 前往部署目錄
cd /root/cluster
echo "osd_crush_update_on_start = false " >> ceph.conf
ceph-deploy --overwrite-conf osd prepare new_mon_1:sdb new_mon_2:sdb new_mon_3:sdb --zap-disk
ceph-deploy --overwrite-conf osd activate new_mon_1:sdb1 new_mon_2:sdb1 new_mon_3:sdb1
添加完這三個OSD後,集羣總共有六個OSD,此時不會有數據遷移。結構以下:
[root@ceph ~]# ceph osd tree
ID WEIGHT TYPE NAME UP/DOWN REWEIGHT PRIMARY-AFFINITY
-1 0.75000 root default
-2 0.25000 host ceph
0 0.25000 osd.0 up 1.00000 1.00000
-3 0.25000 host con
1 0.25000 osd.1 up 1.00000 1.00000
-4 0.25000 host com
2 0.25000 osd.2 up 1.00000 1.00000
3 0 osd.3 up 1.00000 1.00000
4 0 osd.4 up 1.00000 1.00000
5 0 osd.5 up 1.00000 1.00000
構建新的new_root根節點,並將這三個新的OSD加入到新的根節點下(注意OSD和主機的物理對應關係):
ceph osd crush add-bucket new_root root
ceph osd crush add-bucket new_mon_1 host
ceph osd crush add-bucket new_mon_2 host
ceph osd crush add-bucket new_mon_3 host
ceph osd crush move new_mon_1 root=new_root
ceph osd crush move new_mon_2 root=new_root
ceph osd crush move new_mon_3 root=new_root
ceph osd crush add osd.3 0.25 host=new_mon_1
ceph osd crush add osd.4 0.25 host=new_mon_2
ceph osd crush add osd.5 0.25 host=new_mon_3
此時,新的 TREE 結構以下:
[root@ceph ~]# ceph osd tree
ID WEIGHT TYPE NAME UP/DOWN REWEIGHT PRIMARY-AFFINITY
-5 0.75000 root new_root
-6 0.25000 host new_mon_1
3 0.25000 osd.3 up 1.00000 1.00000
-7 0.25000 host new_mon_2
4 0.25000 osd.4 up 1.00000 1.00000
-8 0.25000 host new_mon_3
5 0.25000 osd.5 up 1.00000 1.00000
-1 0.75000 root default
-2 0.25000 host ceph
0 0.25000 osd.0 up 1.00000 1.00000
-3 0.25000 host con
1 0.25000 osd.1 up 1.00000 1.00000
-4 0.25000 host com
2 0.25000 osd.2 up 1.00000 1.00000
導出CRUSH MAP,並編輯添加三條新的 CRUSH RULE:
### 導出CRUSH MAP
ceph osd getcrushmap -o map
crushtool -d map -o map.txt
### 在map.txt 最後添加如下內容
vim map.txt
# rules
rule replicated_ruleset {
ruleset 0
type replicated
min_size 1
max_size 10
step take default
step chooseleaf firstn 0 type host
step emit
}
>>>>>>>>>>>>>> 添加開始 >>>>>>>>>>
rule replicated_ruleset1 {
ruleset 1
type replicated
min_size 1
max_size 10
step take default
step chooseleaf firstn 2 type host
step emit
}
rule replicated_ruleset2 {
ruleset 2
type replicated
min_size 1
max_size 10
step take default
step chooseleaf firstn 2 type host
step emit
step take new_root
step chooseleaf firstn 2 type host
step emit
}
rule replicated_ruleset3 {
ruleset 3
type replicated
min_size 1
max_size 10
step take new_root
step chooseleaf firstn 2 type host
step emit
}
<<<<<<<<<<<< 添加結束 <<<<<<<<<<<<
# end crush map
### 編譯 CRUSH MAP,並注入到集羣中
crushtool -c map.txt -o map.bin
ceph osd setcrushmap -i map.bin
到目前爲止的全部操做均不會發生數據遷移,對線上業務也就沒有影響,下面咱們要開始經過修改 POOL 的 CRUSH RULESET 和 副本數來實現數據的總體遷移(這裏咱們取 volumes 池來介紹):
###確認當前 volumes 池使用的是 crush_ruleset 0
[root@ceph cluster]# ceph osd pool get volumes crush_ruleset
crush_ruleset: 0
### 將 volumes 池的 crush_ruleset 設置爲 1,設置完後,集羣一切正常,PG均爲active+clean
[root@ceph cluster]# ceph osd pool set volumes crush_ruleset 1
set pool 1 crush_ruleset to 1
### 將 volumes 池的 副本數設置爲4, 設置完後,PG通過短暫 Peer,變爲 active+undersized+degraded
[root@ceph cluster]# ceph osd pool set volumes size 4
set pool 1 size to 4
[root@ceph cluster]# ceph -s
cluster 166889ab-fa7b-4a07-83da-6dfc92913a3d
health HEALTH_WARN
256 pgs degraded
256 pgs undersized
recovery 183984/368006 objects degraded (49.995%)
monmap e47: 3 mons at {ceph=192.168.100.112:6789/0,com=192.168.100.111:6789/0,con=192.168.100.110:6789/0}
election epoch 182, quorum 0,1,2 con,com,ceph
osdmap e106: 6 osds: 6 up, 6 in
flags sortbitwise,require_jewel_osds
pgmap v23391: 768 pgs, 3 pools, 403 MB data, 92011 objects
1523 MB used, 1532 GB / 1533 GB avail
183984/368006 objects degraded (49.995%)
512 active+clean
256 active+undersized+degraded
[root@ceph cluster]# ceph osd pool set volumes crush_ruleset 2
set pool 1 crush_ruleset to 2
### 等到 volumes 池的全部PG均變爲 active+clean 後,將 volumes 池的 crush_ruleset 設置爲3, 此步驟後,volumes 池的 PG狀態變爲 active+remapped。可是不影響集羣IO。
[root@ceph cluster]# ceph osd pool set volumes crush_ruleset 2
set pool 1 crush_ruleset to 2
set pool 1 crush_ruleset to 3
### 此時,將 volumes 池的 副本數 設置爲2 ,此時 PG 狀態通過 peer 以後,很快變爲 active+clean ,volumes 池的兩副本均落在新的節點下,而且後臺在自行刪除以前舊節點上的數據。
[root@ceph cluster]# ceph osd pool set volumes size 2
因爲本次數據遷移是在生產環境上執行的,因此沒有直接執行將數據從舊節點直接 mv
到新節點,而是選擇了執行步驟較爲複雜的上面的方案,先 scp
到新節點,再 rm
掉舊節點的數據。而且每個步驟都是能夠快速回退到上一步的狀態的,對於生產環境的操做,是比較友好的。在本次方案測試過程當中,遇到了以下的一些問題,須要引發充分的注意:
Ceph 版本不一致: 因爲舊的節點的 Ceph 版本爲 0.94.5 ,而新節點安裝了較新版本的 10.2.7, 在副本 2=>4 的過程當中Peer是正常的,而將池的crush_ruleset 設置爲3 ,也就是將新節點的 PG 升級爲主副本後,PG由新節點向舊節點發生Peer,此時會一直卡住,PG始終卡在了 remapped + peering
,致使該 pool 沒法IO。在將新舊節點 Ceph 版本一致後(舊節點升級,新節點降級),此現象得以消除。 爲了確保此現象不會在實際操做中發生,應該在變動以前,新建一個測試pool,對其寫入部分數據,再執行全部數據遷移指令,查看此過程是否順暢,確認無誤後,再對生產pool進行操做!
新節點 OSD 的重啓問題: 若是沒有添加了osd_crush_update_on_start
這個配置參數,那麼當新節點的OSD重啓後,會自動添加到默認的 root=default
下,而後馬上產生數據遷移,所以須要添加這個參數,保證OSD始終位於咱們人爲指定的節點下,並不受重啓影響。這是個基本的Ceph運維常識,可是一旦遺忘了,可能形成較爲嚴重的影響。更不用說防火牆時鐘這些配置了。
集羣性能下降:整體來講,在副本從2克隆爲4這段時間(約2-3天,取決於集羣數據量)內,集羣的實際IO表現下降到變動前的 25%->80% 左右,時間越日後表現越接近變動前,這雖然不會致使客戶端的IO阻塞,但從客戶反饋來看,能夠感知到較爲明顯的卡頓。所以克隆時間應該選擇業務量較低的節假日等。
新節點IP不cluster_network
範圍內:這個比較好解決,只須要增大部署目錄ceph.conf
內的cluster_network
或者 public_network
的掩碼範圍便可,不須要修改舊節點的,固然網絡仍是要通的。
變動的回退:對於生產環境來講,儘管執行步驟幾乎是嚴謹不會出錯的,可是不免會遇到意外狀況,就好比上面的版本不一致致使的 peer 卡住現象。所以咱們須要制定完善的回退步驟,在乎外發生的時候,可以快速將環境回退到上一步集羣正常的情況,而不是在乎外發生時驚出一身冷汗,雙手顫抖得敲指令。。。因此,下面的表格給出了這個變動操做的每一步的回退步驟:
變動步驟 | 實際影響 | 回退指令 | 回退影響 |
---|---|---|---|
ceph osd pool set volumes crush_ruleset 1 | 無 | ceph osd pool set volumes crush_ruleset 0 | 無 |
ceph osd pool set volumes size 4 | PG由active+clean,變爲 active+undersized+degraded | ceph osd pool set volumes size 2 | PG很快恢復active+clean |
ceph osd pool set volumes crush_ruleset 2 | PG 開始 backfill,須要較長時間 | ceph osd pool set volumes crush_ruleset 1 | PG很快恢復到active+undersized+degraded,並刪除在新節點生成的數據。 |
ceph osd pool set volumes crush_ruleset 3 | PG 很快變爲 active+remapped。 | ceph osd pool set volumes crush_ruleset2 | PG很快恢復到 active+clean |
ceph osd pool set volumes size 2 | PG 很快變爲 active+clean,而且後臺刪除舊節點數據。 | ceph osd pool set volumes size 4 | PG 變爲active+remapped。 |
爲什麼不直接遷移數據到新節點?整體來看數據遷移過程,最耗時的地方是數據從兩副本變爲四副本的過程,其他過程是短暫且能夠快速回退的,而若是直接將池的 crush_ruleset 設置爲 3 ,數據開始從舊節點直接backfill到新節點上,其實這麼作也是能夠的,可是這裏咱們就會遇到一個問題,一旦數據複製了一天或者一段時間後,集羣出現了問題,好比性能驟降,要求必須回退到操做以前的狀態,此時已經有部分PG完成了遷移,也就是說舊節點上的兩副本已經刪除了,那麼回退到上一步後,還會發生數據重新節點向舊節點的複製,那麼以前複製了多久的數據,可能就須要多久來恢復舊節點上刪除的數據,這很不友好。而用了咱們的方法來複制數據的話,不會存在這個問題,由於這裏的方法在最後一步將池的副本設置爲2以前,舊節點上的數據始終都是在的,而且不會發生任何遷移,咱們能夠在任意意外狀況下,經過幾條指令將集羣恢復到變動以前的狀態。
相比於 OSD 的數據遷移,MON 的遷移比較省時省力一些,步驟相對簡單,可是裏面涉及的原理比較複雜,操做也須要細心又細心。
首先,咱們的環境爲典型的 Openstack+Ceph的環境,其中 Openstack 的三個組件: Nova/Cinder/Glance 均已經對接到了Ceph集羣中,也就是說虛機系統盤,雲硬盤,鏡像都保存在Ceph中。而這三個客戶端調用Ceph的方式不太同樣:
Glance :上傳下載鏡像等時,須要新建一個調用 librbd 的 Client 來鏈接 Ceph集羣。
Cinder :
建立刪除雲盤時,新建一個調用 librbd 的 Client 來鏈接 Ceph 集羣。
掛載卸載雲盤時,由Nova調用librbd來實現該操做。
Nova : 虛機(qemu-kvm進程)至關於一個始終在調用librbd的Client,而且進程始終都在。
咱們須要知道的是,當一個 Client須要鏈接 Ceph 集羣時,它首先經過本身的用戶名和祕鑰(client.cinder/client.nova...) 來鏈接到 /etc/ceph/ceph.conf
配置文件指定IP的MON,認證成功後,能夠獲取集羣的不少MAP( monmap,osdmap,crushmap...),經過這些 MAP,便可向 Ceph 集羣讀取數據。
對於一個虛機進程(qemu-kvm)來講,虛機啓動之初,它即獲取到了集羣的 monmap, 而當所鏈接 MON 的 IP 變化時,好比這個 MON 掛掉時,它便會嘗試鏈接 monmap 裏面的其餘 IP 的 MON,若是每一個MON都掛了,那麼這個 Client 就不能鏈接上集羣獲取最新的 monmap,osdmap等。下面咱們以一個 pid爲3171的 qemu-kvm 進程來演示這一過程:
[root@con ~(keystone_admin)]# ps -ef|grep kvm
qemu 3171 1 17 14:32 ? 00:31:08 /usr/libexec/qemu-kvm -name guest=instance-0000000b.........
[root@con ~(keystone_admin)]# netstat -tnp |grep 3171|grep 6789
tcp 0 0 192.168.100.110:59926 192.168.100.112:6789 ESTABLISHED 3171/qemu-kvm
能夠看到,這個進程鏈接着IP爲 192.168.100.112
的 MON,而咱們手動將這個IP的 MON 停掉,則會發現這個進程又鏈接到了剩餘兩個IP的MON之一上:
[root@con ~(keystone_admin)]# ssh 192.168.100.112 systemctl stop ceph-mon.target
[root@con ~(keystone_admin)]# netstat -tnp |grep 3171|grep 6789
tcp 0 0 192.168.100.110:48792 192.168.100.111:6789 ESTABLISHED 3171/qemu-kvm
所以,若是咱們每次都增長一個MON,再刪除一個MON,那麼在刪除一個MON以後,以前鏈接到這個MON上的 Client 會自動鏈接到一個其餘MON,而且再獲取最新的monmap。那麼咱們增刪過程就是:
原先有三個MON: con, com, ceph
增長 new_mon_1,變爲四個: con, com, ceph, new_mon_1
刪除con,變爲三個:com, ceph, new_mon_1
增長 new_mon_2,變爲四個: com, ceph, new_mon_1, new_mon_2
刪除com,變爲三個:ceph, new_mon_1, new_mon_2
增長 new_mon_3,變爲四個: ceph, new_mon_1, new_mon_2, new_mon_3
刪除con,變爲三個:new_mon_1, new_mon_2, new_mon_3
在實際操做中,發現了一個問題,會致使虛機沒法重啓等問題。
當虛機掛載一個雲硬盤時,Nova 會將掛載這個雲盤時所鏈接的MON IP 寫入到數據庫中,而在修改完MON的IP後,新的MON IP不會被更新到數據庫中,而虛機啓動時會加載 XML 文件,這個文件由數據庫對應字段生成,因爲沒有更新 MON IP,因此 qemu-kvm 進程在啓動時,會嘗試向舊的MON IP發起鏈接請求,固然,舊MON已經刪除,致使鏈接不上而卡住,最終導致虛機進程啓動了,可是虛機狀態始終不能更新爲 RUNNING。
能夠經過打開客戶端的ceph.conf
內的 debug_rbd=20/20
,查看qemu-kvm進程調用librbd時生成的log發現進程在啓動時始終嘗試鏈接舊的MON IP。
這裏,咱們只能手動修改數據庫中記錄的IP地址來確保虛機重啓後可以鏈接上新的MON,須要注意的是,僅僅修改虛機XML文件是沒法生效的,由於會被數據庫內的字段覆蓋而連上舊MON:
### 具體字段爲:
mysql =>
nova => block_device_mapping => connection_info
*************************** 23. row ***************************
created_at: 2018-03-19 08:50:59
updated_at: 2018-03-26 06:32:06
deleted_at: 2018-03-26 09:20:02
id: 29
device_name: /dev/vdb
delete_on_termination: 0
snapshot_id: NULL
volume_id: 39c76d96-0f95-490c-b7db-b3da6d17331b
volume_size: NULL
no_device: NULL
connection_info: {"driver_volume_type": "rbd", "serial": "39c76d96-0f95-490c-b7db-b3da6d17331b", "data": {"secret_type": "ceph", "name": "volumes/volume-39c76d96-0f95-490c-b7db-b3da6d17331b", "secret_uuid": "0668cc5e-7145-4b27-8c83-6c28e1353e83", "qos_specs": null, "hosts": ["192.168.100.110", "192.168.100.111", "192.168.100.112"], "auth_enabled": true, "access_mode": "rw", "auth_username": "cinder", "ports": ["6789", "6789", "6789"]}}
instance_uuid: 4f52191f-9645-448f-977b-80ca515387f7
deleted: 29
source_type: volume
destination_type: volume
guest_format: NULL
device_type: disk
disk_bus: virtio
boot_index: NULL
image_id: NULL
這裏,咱們使用 ceph-deploy 來增刪 MON 節點,主要是爲了操做的簡潔和安全性着想。
首先,咱們須要將新的三個MON的IP地址加入到全部節點的/etc/ceph/ceph.conf
的mon_host
字段中。保證此時mon_host
內是六個MON的IP地址。
### 添加 new_mon_1
[root@ceph cluster]# ceph-deploy mon add new_mon_1
[root@ceph cluster]# ceph -s
cluster 166889ab-fa7b-4a07-83da-6dfc92913a3d
health HEALTH_OK
monmap e48: 4 mons at {ceph=192.168.100.112:6789/0,com=192.168.100.111:6789/0,con=192.168.100.110:6789/0,new_mon_1=192.168.100.113:6789/0}
### 刪除 con 刪除完後,建議等待1-3min再添加新的MON,使得qemu-kvm進程能夠創建新的socket連接。
[root@ceph cluster]# ceph-deploy mon destroy con
[root@ceph cluster]# ceph -s
cluster 166889ab-fa7b-4a07-83da-6dfc92913a3d
health HEALTH_OK
monmap e49: 3 mons at {ceph=192.168.100.112:6789/0,com=192.168.100.111:6789/0,new_mon_1=192.168.100.113:6789/0}
### 依次添加 new_mon_2 ,刪除 com,添加 new_mon_3 , 刪除 ceph:
[root@ceph cluster]# ceph-deploy mon add new_mon_2
[root@ceph cluster]# ceph-deploy mon destroy com
### 等待1-3min,
[root@ceph cluster]# ceph-deploy mon add new_mon_3
[root@ceph cluster]# ceph-deploy mon destroy ceph
[root@con ~(keystone_admin)]# ceph -s
cluster 166889ab-fa7b-4a07-83da-6dfc92913a3d
health HEALTH_OK
monmap e53: 3 mons at {new_mon_1=192.168.100.113:6789/0,new_mon_2=192.168.100.114:6789/0,new_mon_3=192.168.100.115:6789/0}
此時,將全部節點/etc/ceph/ceph.conf
內的mon_host
字段中原先的MON刪除,只保留三個新的MON IP地址。
無需重啓 Glance 服務。
須要重啓 全部計算節點的 nova-compute 和 控制節點的 Cinder 服務,不然會致使虛機沒法建立等問題。
## 在計算節點
openstack-service restart nova-compute
## 在控制節點
openstack-service restart cinder
因爲 nova 不會更新以前的已經掛載的磁盤所鏈接的MON IP 信息,這會致使虛機在重啓等動做時,嘗試鏈接到舊的已經被摧毀的MON的地址,致使動做卡住,所以這裏要單獨改一下數據庫內的MON IP 信息:
這裏咱們將 192.168.100.110/111/112 改成 192.168.100.113/114/115
mysql >>
use nova;
update block_device_mapping set connection_info=(replace(connection_info,'192.168.100.110','192.168.100.113'));
update block_device_mapping set connection_info=(replace(connection_info,'192.168.100.111','192.168.100.114'));
update block_device_mapping set connection_info=(replace(connection_info,'192.168.100.112','192.168.100.115'));
exit;
更新完數據庫後,此次數據遷移算是大功告成了。爲什麼不須要重啓虛機服務呢,這裏再作一些簡單的介紹:
qemu-kvm 虛機進程是一個長鏈接的 Ceph Client,自虛機啓動後,進程就和 Ceph 集羣保持着鏈接,在咱們更改 MON 後,這些 Client 會自動嘗試重連 monmap 裏面的其餘MON,從而更新 monmap, 來獲取最新的 MON 。修改 /etc/ceph/ceph.conf
不會對虛機進程產生影響,除非虛機重啓等,可是,虛機能夠經過更新 monmap 的方式來感知集羣MON的改變。
[如何更改基於rbd塊設備的虛機的monitor ip] [https://opengers.github.io/openstack/how-to-change-guest-monitor-ip-with-rbd-disk/#%E6%9F%A5%E7%9C%8B%E8%99%9A%E6%8B%9F%E6%9C%BA%E5%BD%93%E5%89%8D%E8%BF%9E%E6%8E%A5%E7%9A%84monitor-ip]
[Ceph Monitor hardcoded IPs in Nova database] [https://bugzilla.redhat.com/show_bug.cgi?id=1414124]