系列鏈接
- http://www.itdecent.cn/p/f18a1b3a4920 如何用kolla來部署容器化ceph集群
- http://www.itdecent.cn/p/a39f226d5dfb 修復(fù)一些部署中遇到的問題
- http://www.itdecent.cn/p/d520fed237c0 在kolla ceph中引入device classes特性
- http://www.itdecent.cn/p/d6e047e1ad06 支持bcache設(shè)備和iscsi及多路徑設(shè)備
- http://www.itdecent.cn/p/ab8251fc991a 一個(gè)ceph容器化部署編排項(xiàng)目
本篇介紹一些對(duì)kolla ceph中遇到的問題的修復(fù).
--limit bug修復(fù)
commit url : https://review.openstack.org/#/c/648576/
在上篇的部署中我們提到可以使用--limit來限制部署的節(jié)點(diǎn),如果你的mon和osd節(jié)點(diǎn)是分開的,你可以用limit特性來對(duì)特定節(jié)點(diǎn)的服務(wù)進(jìn)行部署. --limit后面既可以跟具體節(jié)點(diǎn)名,也可以使用group名切片的方式,例如storage-osd[0:1], 意思是包括storage-osd組中的前兩個(gè)節(jié)點(diǎn).
比如我們只想修復(fù)node3節(jié)點(diǎn)的osd,就可以用--limit屬性
kolla-ansible/tools/kolla-ansible deploy --configdir ceph-test -i ceph-test/multinode-inventory --passwords ceph-test/passwords.yml --tags ceph -e openstack_release=cephRocky-7.0.2.0002 --limit ceph-node3
但是kolla-ansible會(huì)報(bào)錯(cuò)
TASK [ceph : Fetching Ceph keyrings] ***************************************************************************************************************************************
fatal: [ceph-node3]: FAILED! => {"failed": true, "msg": "'delegate_host' is undefined"}
出錯(cuò)的任務(wù)如下:
- name: Fetching Ceph keyrings
command: docker exec ceph_mon fetch_ceph_keys.py
register: ceph_files_json
changed_when: (ceph_files_json.stdout | from_json).changed
failed_when: (ceph_files_json.stdout | from_json).failed
delegate_to: "{{ delegate_host }}"
run_once: True
因?yàn)閐elegate_host需要在mon節(jié)點(diǎn)讀取,而這次部署只有osd節(jié)點(diǎn),所以該值為空,簡單的調(diào)整如下:
- name: Fetching Ceph keyrings
command: docker exec ceph_mon fetch_ceph_keys.py
register: ceph_files_json
changed_when: (ceph_files_json.stdout | from_json).changed
failed_when: (ceph_files_json.stdout | from_json).failed
delegate_to: "{{ delegate_host if delegate_host is defined else groups['ceph-mon'][0] }}"
run_once: True
如果delegate_host未定義就去第一個(gè)mon節(jié)點(diǎn)獲取.
但是這種做法有個(gè)問題,當(dāng)?shù)谝粋€(gè)mon節(jié)點(diǎn)需要重裝的時(shí)候, 如果使用--limit ceph-node1, 那么 delegate_host 是已定義但是None的狀態(tài),然后groups['ceph-mon'][0]的mon也是無法工作的.
所以最好是循環(huán)檢測一下所有mon的狀態(tài), 如下:
---
- name: Running ceph mon check
become: true
shell: docker exec ceph_mon ceph health --connect-timeout 1
delegate_to: "{{ item }}"
register: ceph_mon_check
changed_when: False
failed_when: False
with_items: "{{ groups['ceph-mon'] }}"
run_once: true
- name: Registering active mon
set_fact:
active_mon: "{{ item.1 }}"
when: item.0.rc is defined and item.0.rc == 0
run_once: true
with_together:
- "{{ ceph_mon_check.results }}"
- "{{ groups['ceph-mon'] }}"
通過這個(gè)active_mon我們可以知道集群有沒有運(yùn)行的mon, 第一個(gè)mon節(jié)點(diǎn)除了集群初始化的時(shí)候生成keyring以外,完全可以把它當(dāng)成普通的mon一樣來部署修復(fù).
- 修復(fù)獲取keyrings的任務(wù)
- name: Fetching Ceph keyrings
command: docker exec ceph_mon fetch_ceph_keys.py
register: ceph_files_json
changed_when: (ceph_files_json.stdout | from_json).changed
failed_when: (ceph_files_json.stdout | from_json).failed
delegate_to: "{{ active_mon if active_mon is defined else delegate_host }}"
run_once: True
這樣就解決了kolla部署ceph必須包含mon節(jié)點(diǎn)的問題, 我們可以用--limit來限制任何要部署的節(jié)點(diǎn).
- kolla中第一個(gè)mon的修復(fù)問題
kolla中, groups['ceph-mon'][0]是個(gè)特殊的mon,當(dāng)檢測到該節(jié)點(diǎn)并沒有對(duì)應(yīng)的卷(ceph_mon_config)之后, 并且其他mon節(jié)點(diǎn)也沒有對(duì)應(yīng)卷,會(huì)啟動(dòng)generate_cluster.yml任務(wù), 重新生成新的keyring和monmap. 所以對(duì)于一個(gè)部署好的集群, 如果第一個(gè)mon有問題, 需要重新安裝mon的時(shí)候, 是不能直接用kolla加 --limit來修復(fù)的, 使用--limit 后kolla部署的第一個(gè)mon節(jié)點(diǎn)無法加入舊的集群中.
有了以上的mon檢測任務(wù), 這個(gè)問題就很好解決了,當(dāng)有運(yùn)行的mon的時(shí)候, 就不用啟動(dòng)這個(gè)任務(wù). 修改如下:
- include_tasks: generate_cluster.yml
when:
- delegate_host == 'None' and inventory_hostname == groups['ceph-mon'][0]
- active_mon is not defined
這樣我們可以直接用kolla來修復(fù)mon.
mon部署問題
commit url : https://review.openstack.org/#/c/652606/
kolla的mon服務(wù)啟動(dòng)的時(shí)候很奇怪, 當(dāng)我使用3個(gè)mon的時(shí)候, 有時(shí)候會(huì)卡住, 有時(shí)候不卡, 這個(gè)卡就是所有mon一直處在選舉的狀態(tài),ceph集群無法訪問.當(dāng)嘗試4個(gè)5個(gè)mon的時(shí)候會(huì)百分百卡住.
我對(duì)比了kolla的mon啟動(dòng)腳本與ceph-deploy的部署日志.
先看kolla的關(guān)于mon初始化的腳本:
if [[ ! -e "${MON_DIR}/keyring" ]]; then
KEYRING_TMP="/tmp/ceph.mon.keyring"
# Generate keyring for current monitor
ceph-authtool --create-keyring "${KEYRING_TMP}" --import-keyring "${KEYRING_ADMIN}"
ceph-authtool "${KEYRING_TMP}" --import-keyring "${KEYRING_MON}"
mkdir -p "${MON_DIR}"
ceph-mon --mkfs -i "${HOSTNAME}" --monmap "${MONMAP}" --keyring "${KEYRING_TMP}"
rm "${KEYRING_TMP}"
fi
重點(diǎn)是mkfs這句, 不管任何情況下都是用monmap, 關(guān)鍵是這個(gè)monmap也不全,只有第一個(gè)節(jié)點(diǎn).
再看ceph-deploy的部署日志:
[root@ceph-node1 ceph-deploy]# ceph-deploy mon create-initial
...
[ceph-node1][INFO ] Running command: ceph-mon --cluster ceph --mkfs -i ceph-node1 --keyring /var/lib/ceph/tmp/ceph-ceph-node1.mon.keyring --setuser 167 --setgroup 167
...
[ceph-node2][DEBUG ] create the monitor keyring file
[ceph-node2][INFO ] Running command: ceph-mon --cluster ceph --mkfs -i ceph-node2 --keyring /var/lib/ceph/tmp/ceph-ceph-node2.mon.keyring --setuser 167 --setgroup 167
###############分割線,添加mon#############
[root@ceph-node1 ceph-deploy]# ceph-deploy mon add ceph-node3
...
[ceph-node3][INFO ] Running command: ceph-mon --cluster ceph --mkfs -i ceph-node3 --monmap /var/lib/ceph/tmp/ceph.ceph-node3.monmap --keyring /var/lib/ceph/tmp/ceph-ceph-node3.mon.keyring --setuser 167 --setgroup 167
ceph-deploy中,當(dāng)集群初始化的時(shí)候, 所有mon節(jié)點(diǎn)都不使用monmap, 只有當(dāng)新加節(jié)點(diǎn)的時(shí)候才添加monmap.
所以修改kolla的初始化mon腳本如下:
if [[ ! -e "${MON_DIR}/keyring" ]]; then
KEYRING_TMP="/tmp/ceph.mon.keyring"
# Generate keyring for current monitor
ceph-authtool --create-keyring "${KEYRING_TMP}" --import-keyring "${KEYRING_ADMIN}"
ceph-authtool "${KEYRING_TMP}" --import-keyring "${KEYRING_MON}"
mkdir -p "${MON_DIR}"
mon_stat=$(ceph mon stat --connect-timeout 1 || true)
mon_check=$(echo $mon_stat | awk '/mons/{print $0}' | wc -l)
if [[ ${mon_check} -eq 0 ]]; then
ceph-mon --mkfs -i "${HOSTNAME}" --keyring "${KEYRING_TMP}"
else
MONMAP_TMP="/tmp/ceph.${HOSTNAME}.monmap"
ceph mon getmap -o "${MONMAP_TMP}"
ceph-mon --mkfs -i "${HOSTNAME}" --monmap "${MONMAP_TMP}" --keyring "${KEYRING_TMP}"
rm "${MONMAP_TMP}"
fi
rm "${KEYRING_TMP}"
fi
首先檢查集群的狀態(tài),如果命令有內(nèi)容輸出,那么肯定有一半多mon在運(yùn)行,這個(gè)時(shí)候就需要獲取monmap并使用.反之,就認(rèn)為是集群初始化,不使用monmap.
這個(gè)修改和上面的修改搭配,基本可以應(yīng)對(duì)mon的問題.
服務(wù)單獨(dú)指定問題
commit url : https://review.opendev.org/#/c/648626/
我們的ceph集群有很多服務(wù),如果只有某一項(xiàng)服務(wù)發(fā)生了變化,我們只想改動(dòng)這個(gè)服務(wù)對(duì)應(yīng)的容器,那么怎么避免其他的服務(wù)發(fā)生變化就是需要解決的問題.
這個(gè)問題最常見的就是某個(gè)osd出現(xiàn)問題了,我們要修復(fù)這個(gè)osd, 雖然可以用--limit來指定節(jié)點(diǎn),但是如果該節(jié)點(diǎn)有其他服務(wù),比如mon/mds/mgr這些,那們?nèi)绾沃蛔尦绦驅(qū)sd進(jìn)行處理:
首先我們可以在all.yml中定義一個(gè)字典:
ceph_install_daemons:
mon-daemon: "yes"
mgr-daemon: "yes"
osd-daemon: "yes"
rgw-daemon: "yes"
mds-daemon: "yes"
nfs-daemon: "yes"
注意和enable來區(qū)分,enable某個(gè)服務(wù)是指這個(gè)ceph集群中啟用了這個(gè)服務(wù),而ceph_install_daemons中包含的項(xiàng)是你這次部署具體想改動(dòng)的項(xiàng).默認(rèn)的包含所有服務(wù),如果你只想改動(dòng)osd,那么在globals.yml修改一下:
ceph_install_daemons:
mon-daemon: "no"
mgr-daemon: "no"
osd-daemon: "yes"
rgw-daemon: "no"
mds-daemon: "no"
nfs-daemon: "no"
這樣我們就達(dá)到了只改動(dòng)osd的目的.
當(dāng)然,在kolla-ansible中你要修改一下ceph的deploy.yml:
---
- include_tasks: config.yml
- include_tasks: bootstrap_mons.yml
when:
- inventory_hostname in groups['ceph-mon']
- ceph_install_daemons['mon-daemon'] | bool
- include_tasks: distribute_keyrings.yml
- include_tasks: start_mons.yml
when:
- inventory_hostname in groups['ceph-mon']
- ceph_install_daemons['mon-daemon'] | bool
- include_tasks: start_mgrs.yml
when:
- inventory_hostname in groups['ceph-mgr']
- ceph_install_daemons['mgr-daemon'] | bool
- include_tasks: start_ceph_dashboard.yml
when:
- enable_ceph_dashboard | bool
- inventory_hostname in groups['ceph-mon']
- include_tasks: start_nfss.yml
when:
- enable_ceph_nfs | bool
- inventory_hostname in groups['ceph-nfs']
- ceph_install_daemons['nfs-daemon'] | bool
- name: configuring client.admin caps
kolla_ceph_keyring:
name: client.admin
caps: "{{ ceph_client_admin_keyring_caps }}"
run_once: True
delegate_to: "{{ groups['ceph-mon'][0] }}"
- include_tasks: bootstrap_osds.yml
when:
- inventory_hostname in groups['ceph-osd']
- ceph_install_daemons['osd-daemon'] | bool
- include_tasks: start_osds.yml
when:
- inventory_hostname in groups['ceph-osd']
- ceph_install_daemons['osd-daemon'] | bool
- include_tasks: start_rgws.yml
when:
- enable_ceph_rgw | bool
- inventory_hostname in groups['ceph-rgw']
- ceph_install_daemons['rgw-daemon'] | bool
- include_tasks: start_rgw_keystone.yml
when:
- enable_ceph_rgw_keystone | bool
- inventory_hostname in groups['ceph-rgw']
- ceph_install_daemons['rgw-daemon'] | bool
- include_tasks: start_mdss.yml
when:
- enable_ceph_mds | bool
- inventory_hostname in groups['ceph-mds']
- ceph_install_daemons['mds-daemon'] | bool
upgrade.yml和reconfigure.yml也要做類似的修改.
有了這個(gè)選項(xiàng), 再加上--limit, 你就可以把改動(dòng)限制到某個(gè)節(jié)點(diǎn)上具體的某個(gè)服務(wù)上,不用擔(dān)心影響全局的ceph集群.
crush map change
commit url : https://review.opendev.org/#/c/647664/
在kolla中, 當(dāng)進(jìn)行osd的bootstrap的時(shí)候, 會(huì)先將host對(duì)應(yīng)的bucket移動(dòng)到default下面. 所以, 如果你安裝了一個(gè)ceph集群, 然后修改了對(duì)應(yīng)的crush map, 比如把host移動(dòng)到rack下面, 這時(shí)問題來了:當(dāng)集群中的一個(gè)osd損壞之后, 如果用kolla重新部署, 那么對(duì)應(yīng)的host又被移動(dòng)到default下面.
ceph osd crush add-bucket "${host_bucket_name}" host
ceph osd crush move "${host_bucket_name}" root=${CEPH_ROOT_NAME:-default}
# Adding osd to crush map
ceph osd crush add "${OSD_ID}" "${OSD_INITIAL_WEIGHT}" host="${HOSTNAME}${CEPH_ROOT_NAME:+-${CEPH_ROOT_NAME}}"
解決問題的辦法就是, 添加一個(gè)判斷, 如果osd對(duì)應(yīng)的host已經(jīng)在crush map中,就不移動(dòng)host對(duì)應(yīng)的bucket.
host_bucket_name="${HOSTNAME}${CEPH_ROOT_NAME:+-${CEPH_ROOT_NAME}}"
host_bucket_check=$(ceph osd tree | awk '/'"${host_bucket_name}"'/{print $0}' | wc -l)
if [[ "${host_bucket_check}" -eq 0 ]]; then
ceph osd crush add-bucket "${host_bucket_name}" host
ceph osd crush move "${host_bucket_name}" root=${CEPH_ROOT_NAME:-default}
fi
# Adding osd to crush map
ceph osd crush add "${OSD_ID}" "${OSD_INITIAL_WEIGHT}" host="${HOSTNAME}${CEPH_ROOT_NAME:+-${CEPH_ROOT_NAME}}"
mon和osd使用hostname
commit url : https://review.opendev.org/654417
用kolla部署的mon和osd, 名稱默認(rèn)都是IP, 有時(shí)候我們想部署成hostname為主的集群,這樣在維護(hù)的時(shí)候可以更直觀的知道是哪臺(tái)節(jié)點(diǎn).
我的修改中增加了對(duì)hostname的支持, 用法很簡單, 在globals.yml中定義如下變量即可.
ceph_mon_host_type: "HOSTNAME"
ceph_osd_host_type: "HOSTNAME"
NOTE: 不要對(duì)已經(jīng)部署好的集群進(jìn)行如下操作, 這樣會(huì)導(dǎo)致舊的集群mon丟失, 因?yàn)閙on在初始化的時(shí)候是以mon對(duì)應(yīng)的節(jié)點(diǎn)名稱命名的,之前使用IP創(chuàng)建的, 現(xiàn)在改成hostname會(huì)造成db丟失. 對(duì)osd的影響則是如果修復(fù)之前損壞的osd,則會(huì)修改之前節(jié)點(diǎn)的crush map.
總結(jié)
通過以上的修復(fù),我們可以做到針對(duì)某一個(gè)ceph組件具體到某一個(gè)節(jié)點(diǎn)上的修改.這個(gè)粒度其實(shí)還不夠小, 后面我會(huì)講一下如何避免同一節(jié)點(diǎn)上多個(gè)osd節(jié)點(diǎn)的重啟. 畢竟osd是集群里最怕重啟的組件.