OpenStack 下 CentOS6.X 映象網路初始化失敗問題排查

神王攻大人發表於2024-07-03

問題表現

在我的 OpenStack 叢集上遷移了一批老舊的映象(從其他三方雲平臺過來的)發現這批映象在使用 ConfigDrive 的方式注入配置初始化時無法對非首張網路卡映象初始化(後經過測試非 ConfigDrive 的資料來源也不行)。

排查路徑

首先檢查 cloud-init 是否是正常工作的
例項化映象檢視 cloud-init 服務, 以及相關日誌。

systemctl status cloud-init
systemctl status cloud-init-local

服務均正常啟用。
再檢視 Cloud-init 的初始化日誌

[   19.254076] cloud-init[1483]: Cloud-init v. 0.7.5 finished at Tue, 02 Jul 2024 06:28:30 +0000. Datasource DataSourceConfigDriveNet [net,ver=2][source=/dev/sr0].  Up 19.24 seconds

可以看到有類似讀取到資料來源並例項化的日誌。基本上可以可以排除 cloud-init 執行不正常的情況。

cloud-init 除錯

只能細化cloud-init初始化的流程。
關於cloud-init 執行階段的講述推薦這篇文章,我此處不多贅述。https://www.cnblogs.com/frankming/p/16281447.html
此處給出快速重重跑初始化的指令碼

# centos7
#! /bin/bash
cloud-init clean
rm -rf /var/run/cloud-init/
rm -rf /var/lib/cloud/
rm -rf /etc/sysconfig/network-scripts/ifcfg-*

# local 階段資料來源準備
cloud-init init --local

# 網路階段, 渲染資料
cloud-init init

# 執行模組
cloud-init modules --mode=config
# centos6
#! /bin/bash
rm -rf /var/run/cloud-init/
rm -rf /var/lib/cloud/
rm -rf /etc/sysconfig/network-scripts/ifcfg-*

# local 階段資料來源準備
cloud-init init --local

# 網路階段, 渲染資料
cloud-init init

# 執行模組
cloud-init modules --mode=config

很遺憾,在重跑初始化流程中未看出端疑,對比可以初始化多張網路卡的日誌(CentOS7系統上),總感覺 CentOS6 在網路卡配置階段無任務操作。於是拖下了 Cloud-init 的原始碼碼進行靜態審計+Print大發。
原始碼路徑:

/usr/lib/python2.6/site-packages/cloudinit

定位到 Cloud-init 7.5 的這個位置

...
# sources/DataSourceConfigDrive.py +166
def read_config_drive(source_dir, version="2012-08-10"):
    reader = openstack.ConfigDriveReader(source_dir)
    finders = [
        (reader.read_v2, [], {'version': version}),
        (reader.read_v1, [], {}),
    ]
    excps = []
    for (functor, args, kwargs) in finders:
        try:
            return functor(*args, **kwargs)
        except openstack.NonReadable as e:
            excps.append(e)
    raise excps[-1]
...
...
# sources/DataSourceConfigDrive.py +59
    def get_data(self):
        found = None
        md = {}
        results = {}
        if os.path.isdir(self.seed_dir):
            try:
                results = read_config_drive(self.seed_dir)
                found = self.seed_dir
            except openstack.NonReadable:
                util.logexc(LOG, "Failed reading config drive from %s",
                            self.seed_dir)
        if not found:
            for dev in find_candidate_devs():
                try:
                    results = util.mount_cb(dev, read_config_drive)
                    found = dev
                except openstack.NonReadable:
...

可以看到在掛載 /dev/sr0 裝置後,cloud-init 0.7.5 版本使用的是 2012-08-10 資料來源
手動掛載並檢視

[root@aa home]# mount /dev/sr0 /mnt/
mount: /dev/sr0 is write-protected, mounting read-only
[root@aa home]# ls /mnt/
ec2  openstack
[root@aa home]# ls /mnt/openstack/2012-08-10/
meta_data.json  user_data

好哇,根本沒有network_data.json這種東西。看相關網路配置的初始化,驗證網路初始邏輯只給ubuntu做了適配。得出結果,Cloud-init 0.7.5 版本過低,centos7支援差導致。

解決方案

解決方案大致有兩種:

1. 升級 Cloud-init
2. 手工實現 Cloud-init 網路初始化部分的邏輯

解決方案一

升級的話首選需要升級Python版本,本人未採用升級的方案,所以不多贅述,但是是一定可行的,推薦手動升級Python 並原始碼安裝 Cloud-init。

解決方案二

推薦像本人一樣參考高版本的 cloud-init 驅動實現邏輯手工用 go 或者 C 語言這種重新寫一個補丁,經測試可行。由於這個元件是為公司開發的,不方便開源,但是歡迎交流。

相關文章