問題表現
在我的 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 語言這種重新寫一個補丁,經測試可行。由於這個元件是為公司開發的,不方便開源,但是歡迎交流。