kolla-ceph 2: 修復(fù)一些部署中遇到的問題

系列鏈接

  1. http://www.itdecent.cn/p/f18a1b3a4920 如何用kolla來部署容器化ceph集群
  2. http://www.itdecent.cn/p/a39f226d5dfb 修復(fù)一些部署中遇到的問題
  3. http://www.itdecent.cn/p/d520fed237c0 在kolla ceph中引入device classes特性
  4. http://www.itdecent.cn/p/d6e047e1ad06 支持bcache設(shè)備和iscsi及多路徑設(shè)備
  5. 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是集群里最怕重啟的組件.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容