天天看點

ceph核心子產品編譯及調試

雖然librbd和librados可以滿足大部分ceph的使用需求,但是在實際使用中(特别是ceph與kubernetes結合),仍需krbd子產品。當然,rbd-nbd也是一種解決方案,在這不多說。

顯然,krbd依賴linux的核心版本,而普遍地,生産環境下的系統很少會更新到最新的核心(畢竟穩定性還是第一位)。這就會造成krbd的代碼跟不上社群版本,有些bug即使修複了也難以應用起來。

是以,本文基于centos7的發行版,簡單介紹如何使用ceph進行修改子產品的編譯和問題調式定位。

同時,如果使用過centos7.0的朋友們應該知道,在kernel-3.10.0-123版本,rbd子產品預設是不安裝的,即隻能通過子產品編譯加載的方式來使用ceph的rbd,否則執行rbd map操作是會失敗的。

linux子產品編譯

linux的子產品編譯在網上很多地方都能夠找到,這裡不描述詳細細節,隻說一下需要注意的事情。

  1. 如果不打算更新核心,那麼子產品編譯時的kernel源碼一定要與目前發行版本的核心一緻。比如,centos7.0對應核心版本為kernel-3.10.0-123,如果不确定,可以使用

    uname -r

    來查詢到(針對rhel系的系統)。一般地,核心源碼可以在rpmsearch中找到。千萬不要将發行版的linux核心和torvalds/linux搞混了。
  2. 手動編譯的核心子產品一般是沒有簽名的(module signing),一般情況是不影響使用的。但如果有特殊需求的環境,比如需要驗證簽名才能加載核心子產品的系統安全設定,則需要手動為子產品增加簽名。詳細的可以參考紅帽的官方說明:signing secure module for secure boot
  3. 當核心源碼包缺少symvers檔案,手動編譯的modules在加載時報

    no symbol version for module_layout

    錯誤.此時,需要做如下操作:

    locate symvers

    ,将symvers檔案拷貝到對應-C目錄下

那麼,我們假設已經從網上或者其它途徑上拿到了linux某個發行版本的核心源碼(這裡使用的是centos7.1 即 kernel-3.10.0-229.el7.src.rpm或者kernel.tar.bz包)。如果是src.rpm包,則還需要

yum install xxx.src.rpm

進行安裝,成功後在/root目錄下會多出一個rpmbuild目錄,該源碼包位置在/root/rpmbuild/SOURCES/linux-3.10.0-514.el7.tar.xz。

如果要編譯整個核心,可以這樣:

1. 通過解壓tar包,擷取源碼

tar xvf kernel.tar.xz

2.

make mrproper

# 清除上次殘留項

3.

make menuconfig

# 需要安裝ncurses 和 ncurses-devel庫,選擇核心需要的子產品

4.

make & make modules_install

5. 在對應的子產品目錄下找到特定的ko檔案

靜靜等待幾個小時編譯即可完成。幸運的是,核心子產品是可以單獨編譯的。通過以下步驟,可以編譯某個子產品,而不用等待所有代碼編譯完成,非常節省時間:

1.

make oldconfig

2.

make prepare

3.

make scripts

4.

make <MODULE>=m -C /usr/src/kernels/{linux-version}/ M=/{src-dir}/{modules_path}/ modules

-C $(KDIR) 指明跳轉到核心源碼目錄下讀取那裡的Makefile,M=$(PWD) 表明然後傳回到目前目錄繼續讀入、執行目前的Makefile

5. 然後再{module_path}路徑中找到對應的ko檔案即可

ceph子產品編譯

ceph的核心子產品主要有三個,包含rbd-nbd的話就有四個,其路徑及子產品名分别是:

1. cephfs核心子產品ceph.ko:CONFIG_CEPH_FS=m,子產品路徑:./fs/ceph/

2. rbd核心子產品rbd.ko:CONFIG_BLK_DEV_RBD=m,子產品路徑:./drivers/block

3. 通用子產品libceph.ko:CONFIG_CEPH_LIB=m,子產品路徑:./net/ceph/ ./include/linux/ceph/ ./include/linux/crush/

4. nbd子產品nbd.ko: CONFIG_BLK_DEV_NBD=m,子產品路徑:./drivers/block

以rbd核心子產品編譯為例子,其步驟如下:

1.

make CONFIG_BLK_DEV_RBD=m -C /usr/src/kernels/3.10.0-229.el7.x86_64/ M=/root/linux-3.10.0-229/ modules

2. 在

/root/linux-3.10.0-229/drivers/block

目錄下找到rbd.ko檔案

3. 放置到

/usr/lib/modules/3.10.0-229.el7.x86_64/kernel/drivers/block/rbd.ko

位置。

4.

depmod -a

更新所有子產品依賴,也可以執行

rmmod rbd

,然後

modprobe rbd

或者

insmod rbd

PS: cephfs放置到

/usr/lib/modules/3.10.0-229.el7.x86_64/kernel/fs/ceph/ceph.ko

, libceph放置到

/usr/lib/modules/3.10.0-229.el7.x86_64/kernel/net/ceph/libceph.ko

ceph核心子產品調試

ceph的核心調試其實就是linux的核心日志輸出調試吧。其所有的輸出一般會列印在kern.log上,使用内置的debugfs和dynamic_debug。dynamic_debug允許使用者手動打開/關閉核心輸出資訊,更詳細的可自行參考相關資料(因為我不是核心開發,對其調試工具不太熟悉,就不班門弄斧了)。

如果不打開核心的printk等級,那麼我們預設在/var/log/message中隻會看到少量的消息,比如

rbd map

時,其消息如下:

Mar  :: devp kernel: Key type dns_resolver registered
Mar  :: devp kernel: Key type ceph registered
Mar  :: devp kernel: libceph: loaded (mon/osd proto /)
Mar  :: devp kernel: rbd: loaded (major )
Mar  :: devp kernel: libceph: mon2 : session established
Mar  :: devp kernel: libceph: client24119 fsid e91b954b--da2-a18be2d5c74d
Mar  :: devp kernel: rbd: rbd0: capacity  features 
           

然而這些消息并不能夠準确追蹤具體的運作情況,特别是在需要調試或者定位bug的時候。是以,需要将kernel中printk的信日志列印出來。如下步驟所示:

1.確定系統可以使用dynamic_debug功能:

sudo cat /boot/config-`uname -r` | grep DYNAMIC_DEBUG

,其執行結果為:CONFIG_DYNAMIC_DEBUG=y表明功能可以使用

2.挂載debugfs, 并打開想要輸出日志的子產品

mount -o rw.remount -t debugfs none /sys/kernel/debug/
echo "module libceph +p" >/sys/kernel/debug/dynamic_debug/control
echo "module rbd +p" >/sys/kernel/debug/dynamic_debug/control
           

3.通過

echo "7 7 7 7" > /proc/sys/kernel/printk

設定核心列印日志級别 0~7, 預設 4 4 1 7。其級别消息如下所示:

#define KERN_EMERG 0    /*緊急事件消息,系統崩潰之前提示,表示系統不可用*/
#define KERN_ALERT 1    /*報告消息,表示必須立即采取措施*/
#define KERN_CRIT 2     /*臨界條件,通常涉及嚴重的硬體或軟體操作失敗*/
#define KERN_ERR 3      /*錯誤條件,驅動程式常用KERN_ERR來報告硬體的錯誤*/
#define KERN_WARNING 4  /*警告條件,對可能出現問題的情況進行警告*/
#define KERN_NOTICE 5   /*正常但又重要的條件,用于提醒。常用于與安全相關的消息*/
#define KERN_INFO 6     /*提示資訊,如驅動程式啟動時,列印硬體資訊*/
#define KERN_DEBUG" 7   /*調試級别的消息*/
           

如果沒有效果,可以使用

echo 9 > /proc/sysrq-trigger

的方式,sysrq-trigger的使用是比較極端的,但有時也挺好用,需要謹慎使用,因為其會直接觸發核心系統的修改。其具體參數如下(rhel_sysrq-trigger):

• r — Disables raw mode for the keyboard and sets it to XLATE (a limited 
keyboard mode which does not recognize modifiers such as Alt, Ctrl, 
or Shift for all keys).
• k — Kills all processes active in a virtual console. Also called Secure 
Access Key (SAK), it is often used to verify that the login prompt is spawned 
from init and not a trojan copy designed to capture usernames and passwords.
• b — Reboots the kernel without first unmounting file systems or syncing 
disks attached to the system.
• c — Crashes the system without first unmounting file systems or syncing 
disks attached to the system.
• o — Shuts off the system.
• s — Attempts to sync disks attached to the system.
• u — Attempts to unmount and remount all file systems as read-only.
• p — Outputs all flags and registers to the console.
• t — Outputs a list of processes to the console.
• m — Outputs memory statistics to the console.
•  through  — Sets the log level for the console.
• e — Kills all processes except init using SIGTERM.
• i — Kills all processes except init using SIGKILL.
• l — Kills all processes using SIGKILL (including init). The system is 
unusable after issuing this System Request Key code.
• h — Displays help text.
           

4.配置rsyslog,在/etc/rsyslog.conf 中設定

kern.* /var/log/kern.log

, 然後重新開機rsyslog:

systemctl restart rsyslog

更加詳細的dynamic-debug的資訊,可以參考:dynami-debug-howto文檔。

至此,我們可以從/var/log/kern.log中擷取到libceph和rbd子產品的所有輸出,如下所示:

Mar 26 22:01:59 devp kernel: libceph:  init
Mar 26 22:01:59 devp kernel: libceph:  msgpool osd_op init
Mar 26 22:01:59 devp kernel: libceph:  ceph_msg_new ffff88007dd080f0 front 4096
Mar 26 22:01:59 devp kernel: libceph:  msgpool_alloc (null) ffff88007dd080f0
Mar 26 22:01:59 devp kernel: libceph:  ceph_msg_new ffff88007dd0b660 front 4096
Mar 26 22:01:59 devp kernel: libceph:  msgpool_alloc (null) ffff88007dd0b660
Mar 26 22:01:59 devp kernel: libceph:  ceph_msg_new ffff88007dd0b570 front 4096
Mar 26 22:01:59 devp kernel: libceph:  msgpool_alloc (null) ffff88007dd0b570
Mar 26 22:01:59 devp kernel: libceph:  ceph_msg_new ffff88007dd0b480 front 4096
Mar 26 22:01:59 devp kernel: libceph:  msgpool_alloc (null) ffff88007dd0b480
Mar 26 22:01:59 devp kernel: libceph:  ceph_msg_new ffff88007dd09d10 front 4096
Mar 26 22:01:59 devp kernel: libceph:  msgpool_alloc (null) ffff88007dd09d10
Mar 26 22:01:59 devp kernel: libceph:  ceph_msg_new ffff88007dd0b390 front 4096
Mar 26 22:01:59 devp kernel: libceph:  msgpool_alloc (null) ffff88007dd0b390
Mar 26 22:01:59 devp kernel: libceph:  ceph_msg_new ffff88007dd08e10 front 4096
Mar 26 22:01:59 devp kernel: libceph:  msgpool_alloc (null) ffff88007dd08e10
           

參考文檔連結

https://ceph.com/geen-categorie/ceph-collect-kernel-rbd-logs/

https://www.kernel.org/doc/html/v4.14/admin-guide/dynamic-debug-howto.html

http://www.selinuxplus.com/?p=540

https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/system_administrators_guide/sect-signing-kernel-modules-for-secure-boot

繼續閱讀