這兩天在調(diào)試一個內(nèi)核版本的問題芹关,準確來說是為了解決給kubernetes的CNI啟用IPSec+Geneve模式遇到的一個坑地消。一開始我在本地實驗IPSec+Geneve模式時很順利速梗,但是放到e2e測試環(huán)境時良蒸,基本的ping連接測試也會失敗舟扎,因為CNI本身只用到了內(nèi)核的OVS,于是懷疑是內(nèi)核的版本不一致導致遥巴,通過uname -a
查看了兩個環(huán)境后發(fā)現(xiàn)的確有小版本的差異千康,可工作的版本是Linux 4.15.0-143-generic
,不工作的版本是Linux 4.15.0-66-generic
,然后又比較了下內(nèi)核自帶的OVS內(nèi)核模塊文件夾,發(fā)現(xiàn)路徑ls -alt /lib/modules/$version/kernel/net/openvswitch/
內(nèi)的文件大小都有差異铲掐,這就更讓我肯定了是內(nèi)核版本的問題拾弃。但是小版本66和143之間還是存在很多個中間版本的,因為需要給用戶準確的文檔說明摆霉,這中間到底是什么時候引入的fix是需要解決的問題豪椿。這里記錄下為了定位到具體版本經(jīng)歷的過程,給以后一些參考携栋。
靈活選擇內(nèi)核版本
為了測試版本差異和效果搭盾,需要安裝不同的內(nèi)核版本,想用舊的內(nèi)核版本婉支,首先需要安裝上舊版本鸯隅,但如果不做特別配置的話,系統(tǒng)默認都是用當前最新的內(nèi)核版本向挖,并不會選擇老版本來啟動機器蝌以。參考了這篇文章后炕舵,我在本地配置了允許用戶靈活選擇內(nèi)核版本。測試的系統(tǒng)版本是Ubuntu 18.04跟畅,具體步驟如下:
編輯文件/etc/default/grub
,注釋掉GRUB_DEFAULT=0
這一行咽筋,然后加上如下三行:
GRUB_DEFAULT=saved
GRUB_SAVEDEFAULT=true
GRUB_DISABLE_SUBMENU=y
GRUB_DEFAULT 設置允許 Grub 使用我們保存的任何值為默認內(nèi)核,而不是硬編碼默認值碍彭。 GRUB_SAVEDEFAULT 告訴 Grub 將默認內(nèi)核設置為我們在菜單中明確選擇的條目晤硕。 GRUB_DISABLE_SUBMENU 選項使菜單結(jié)構(gòu)扁平化悼潭,以便我們可以更輕松地解析它庇忌。
另外需要檢查文件夾/etc/default/grub.d
下名為50-cloudimg-settings.cfg
的文件. 它可能包含覆蓋/etc/default/grub
文件內(nèi)配置的默認選擇。如果有也在GRUB_DEFAULT=0
所在行添加注釋舰褪,改為#GRUB_DEFAULT=0
皆疹。
然后配置變量GRUB_CONFIG:export GRUB_CONFIG='/boot/grub/grub.cfg'
,并運行update-grub
來重新構(gòu)建grub.cfg文件以使前面的更改生效。現(xiàn)在配置已重建且菜單已展平占拍,我們可以解析文件中的可用條目略就。以下命令顯示條目索引號和標題。我們可以使用其中任何一個來引用特定條目晃酒。
grep 'menuentry ' $GRUB_CONFIG | cut -f 2 -d "'" | nl -v 0
這將返回所有可用的引導選項表牢。記下要引導的條目的索引號或標題。
0 Ubuntu, with Linux 4.15.0-151-generic
1 Ubuntu, with Linux 4.15.0-151-generic (recovery mode)
2 Ubuntu, with Linux 4.15.0-141-generic
3 Ubuntu, with Linux 4.15.0-141-generic (recovery mode)
4 Ubuntu, with Linux 4.15.0-140-generic
...
Grub 包括從命令行設置新的默認內(nèi)核的命令贝次。我們可以使用索引號或條目標題來指定引導選項宇整。例如使用索引號:grub-set-default 2
還可以選擇僅適用于下次啟動的臨時啟動選項:grub-reboot 2
,配置結(jié)束后就可以重啟以便于使用配之后的內(nèi)核版本华烟。
查找Ubuntu版本變更
既然是Ubuntu內(nèi)核版本差異導致的,那就要查找內(nèi)核變更,先搜到了Ubuntu的Git源碼位置, 而我本地用的是18.04傻工,對應的是bionic,所以Git路徑是ubuntu-bionic所在地址奶是。為了方便定位具體變更基矮,我把整個源碼克隆到了本地: git clone git://kernel.ubuntu.com/ubuntu/ubuntu-bionic.git
.
我先在log頁面通過log msg
方式查找了geneve關(guān)鍵字,發(fā)現(xiàn)了不少相關(guān)的commit笋轨,另外在tag頁面能夠看到具體的tag以及他們創(chuàng)建的日期時間秆剪。這中間定位到正確的fix commit饒了點彎路,切換不同的內(nèi)核做了一些不必要的測試爵政,最后才定位到是在這個commit里提交的Fix鸟款。然后在本地通過git tag --contains $commit
找到了包含這個commit的所有tag。如果沒有克隆源碼茂卦,也可以在頁面上比較commit提交時間和tag的創(chuàng)建時間何什,在commit提交時間之后創(chuàng)建的tag肯定都會包含相關(guān)的代碼。
其實看tag的歷史可以發(fā)現(xiàn)Linux 4.15.0-66-generic
和Linux 4.15.0-143-generic
之間的時間跨度還是非常大的等龙,如果不是Fix commit在搜索出來的commit列表里的頭幾個处渣,估計我也沒有耐心或者找到更好的方式來定位問題伶贰,希望下次能想到更快更好的方式定位問題。
Ubuntu版本號
4.15.0-66
這個版本號里每個字段包含不同含義罐栈,更多內(nèi)容可以參考這篇博客黍衙,介紹的很詳細。我把其中介紹Ubuntu版本號的部分拷貝到了這里:
Linux localhost 3.2.0-67-generic #101-Ubuntu SMP Tue Jul 15 17:46:11 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
第一個組數(shù)字:3, 主版本號
第二個組數(shù)字:2, 次版本號荠诬,當前為穩(wěn)定版本
第三個組數(shù)字:0, 修訂版本號
第四個組數(shù)字:67琅翻,當前內(nèi)核版本(3.2.0)的第67次微調(diào)patch
generic:當前內(nèi)核版本為通用版本,另有表示不同含義的server(針對服務器)柑贞、i386(針對老式英特爾處理器)
pae(Physical Address Extension):物理地址擴展方椎,為了彌補32位地址在PC服務器應用上的不足而推出,表示此32位系統(tǒng)可以支持超過4G的內(nèi)存
x86_64:采用的是64位的CPU
SMP:對稱多處理機钧嘶,表示內(nèi)核支持多核棠众、多處理器
Tue Jul 15 17:46:11 UTC 2014:內(nèi)核的編譯時間(build date)為 2014/07/15 17:46:11
其他
在調(diào)試中間用到一些命令,記錄在這里:
# 用日期查找git log
git log --date=iso --pretty=format:'%ad%x08%aN %s' | awk '$0 >= "2020-02-28" && $0 <= "2020-04-01"'
# 用日期和作者查找git log
git log --pretty=format:"%ad - %an: %s" --after="2020-02-28" --until="2020-04-01" --author="John Doe"
# 查看tag間差異
git diff Ubuntu-4.15.0-91.92 Ubuntu-4.15.0-96.97 --stat
# 安裝內(nèi)核版本
apt install linux-image-4.15.0-91-generic linux-headers-4.15.0-91-generic
# 刪除內(nèi)核版本
apt remove linux-image-4.15.0-91-generic linux-headers-4.15.0-91-generic
# 搜索內(nèi)核版本
apt list | grep linux-image-4.15.0-
# 標記軟件包狀態(tài)有决,用來禁止更新等
apt-mark hold linux-image-generic linux-headers-generic