當鏡像的作業系統不在阿里雲所支援的平台列表中,並且不能安裝cloud-init時,您可以在匯入自訂鏡像時選擇Customized Linux(定製版鏡像)。阿里雲將定製版Linux鏡像當作無法識別的作業系統,您需要在匯入鏡像前,根據本文描述在鏡像中添加解析指令碼,便於初次啟動時自動化配置執行個體。
限制要求
Customized Linux鏡像具有如下限制條件:
- 第一個分區必須可以被寫入。
- 第一個分區的檔案類型只能是FAT32、EXT2、EXT3、EXT4或UFS。
- 虛擬檔案的大小必須大於5GiB。
Customized Linux鏡像具有如下安全要求:
- 不能存在可被遠程利用的高危漏洞。
- 使用控制台的管理終端(VNC)登入執行個體時,如果存在初始預設密碼,您必須在首次登入時修改,修改密碼之前不允許進入執行個體做任何操作。詳情請參見使用VNC登入執行個體。
- 不支援預設SSH金鑰組,初始SSH金鑰組必須由阿里雲產生。
配置方法
os.conf檔案樣本
- 傳統網路類型執行個體os.conf檔案樣本。
樣本中各參數說明如下表所示。hostname=<yourHostName> password=<yourPassword> eth0_ip_addr=10.0.0.2 eth0_mac_addr=00:xx:xx:xx:xx:23 eth0_netmask=255.255.255.0 eth0_gateway=10.0.0.1 eth0_route="10.0.0.0/8 10.0.0.1;172.16.0.0/12 10.0.0.1" eth1_ip_addr=42.0.0.2 eth1_mac_addr=00:xx:xx:xx:xx:24 eth1_netmask=255.255.255.0 eth1_gateway=42.0.0.1 eth1_route="0.0.0.0/0 42.0.0.1" dns_nameserver="7.7.7.7 8.8.8.8"
參數名稱 參數說明 hostname 主機名稱參數 password 密碼參數,Base64編碼的字串 eth0_ip_addr eth0網卡IP地址 eth0_mac_addr eth0網卡MAC地址 eth0_netmask eth0網卡掩碼 eth0_gateway eth0網卡預設閘道 eth0_route eth0內網路由列表,預設用半形分號分隔 eth1_ip_addr eth1網卡IP地址 eth1_mac_addr eth1網卡MAC地址 eth1_netmask eth1網卡掩碼 eth1_gateway eth1網卡預設閘道 eth1_route eth1公網路由列表,預設用半形分號分隔 dns_nameserver DNS地址清單,預設用空格分隔 - Virtual Private Cloud類型執行個體os.conf檔案樣本。
樣本中各參數說明如下表所示。hostname=<yourHostName> password=<yourPassword> eth0_ip_addr=10.0.0.2 eth0_mac_addr=00:xx:xx:xx:xx:23 eth0_netmask=255.255.255.0 eth0_gateway=10.0.0.1 eth0_route="0.0.0.0/0 10.0.0.1" dns_nameserver="7.7.7.7 8.8.8.8"
參數名稱 參數說明 hostname 主機名稱參數 password 密碼參數,Base64編碼的字串 eth0_ip_addr eth0網卡IP地址 eth0_mac_addr eth0網卡MAC地址 eth0_netmask eth0網卡掩碼 eth0_gateway eth0網卡預設閘道 eth0_route eth0內網路由列表,預設用半形分號分隔 dns_nameserver DNS地址清單,預設用空格分隔
解析指令碼注意事項
執行個體初次啟動時,正常情況下阿里雲自動將配置項的相關資訊寫入第一個分區的根目錄下aliyun_custom_image目錄的os.conf檔案中。配置Customized Linux鏡像必須要在鏡像中建立預定義解析指令碼,用以從os.conf檔案中讀取執行個體配置資訊並完成執行個體配置。
解析指令碼需要滿足的條件,如下表所示。
需滿足的條件 | 配置說明 |
開機啟動 | 解析指令碼需要設定成開機自啟動,例如,將解析指令碼存放在/etc/init.d/目錄下。 |
配置項取值規則 | 如os.conf 檔案樣本的配置項所述,VPC與傳統網路類型執行個體的配置項數量和部分配置項的取值規則均有所不同。 |
設定檔讀取路徑 | Customized Linux鏡像在建立I/O最佳化執行個體或非I/O最佳化執行個體時,為第一個分區所分配的裝置名稱預設不一樣。所以在解析指令碼中建議使用uuid 或label 識別第一個分區的裝置。使用者密碼為Base64編碼的字串,設定密碼時需要做相關處理。 |
判斷VPC或傳統網路 | 解析指令碼判斷該網路類型時,可以查看是否存在eth1_route或其他eth1相關的配置項。判斷出當前執行個體的網路類型後再有針對性地解析和處理。
|
配置最佳化 | os.conf檔案中的配置在執行個體的整個生命週期中執行一次即可,解析指令碼執行成功後建議刪除os.conf檔案。同時解析指令碼如果沒有讀取到os.conf檔案配置,則不執行檔案中的配置。 |
自訂鏡像處理 | 根據Customized Linux鏡像建立的執行個體再製作自訂鏡像時,鏡像中也會包含這個開機啟動指令碼。阿里雲會在執行個體第一次啟動時寫入os.conf配置,解析指令碼在檢測到該配置時即可執行相關配置。 |
修改相關配置時的處理 | 當執行個體的配置資訊通過阿里雲的控制台或API發生變更時,阿里雲將相關資訊寫入到os.conf檔案中,解析指令碼將被再次執行從而下發這些更改。 |
解析指令碼樣本
解析指令碼以CentOS作業系統為例,僅供您參考。實際操作時,請根據作業系統類型調整指令碼內容。使用指令碼前,務必在鏡像中調試指令碼,並保證調試通過。
#!/bin/bash
### BEGIN INIT INFO
# Provides: os-conf
# Required-Start: $local_fs $network $named $remote_fs
# Required-Stop:
# Should-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: The initial os-conf job, config the system.
### END INIT INFO
first_partition_dir='/boot/'
os_conf_dir=${first_partition_dir}/aliyun_custom_image
os_conf_file=${os_conf_dir}/os.conf
load_os_conf() {
if [[ -f $os_conf_file ]]; then
. $os_conf_file
return 0
else
return 1
fi
}
cleanup() {
# ensure $os_conf_file is deleted, to avoid repeating config system
rm $os_conf_file >& /dev/null
# ensure $os_conf_dir exists
mkdir -p $os_conf_dir
}
config_password() {
if [[ -n $password ]]; then
password=$(echo $password | base64 -d)
if [[ $? == 0 && -n $password ]]; then
echo "root:$password" | chpasswd
fi
fi
}
config_hostname() {
if [[ -n $hostname ]]; then
sed -i "s/^HOSTNAME=.*/HOSTNAME=$hostname/" /etc/sysconfig/network
hostname $hostname
fi
}
config_dns() {
if [[ -n $dns_nameserver ]]; then
dns_conf=/etc/resolv.conf
sed -i '/^nameserver.*/d' $dns_conf
for i in $dns_nameserver; do
echo "nameserver $i" >> $dns_conf
done
fi
}
is_classic_network() {
# vpc: eth0
# classic: eth0 eth1
grep -q 'eth1' $os_conf_file
}
config_network() {
/etc/init.d/network stop
config_interface eth0 ${eth0_ip_addr} ${eth0_netmask} ${eth0_mac_addr}
config_route eth0 "${eth0_route}"
if is_classic_network ; then
config_interface eth1 ${eth1_ip_addr} ${eth1_netmask} ${eth1_mac_addr}
config_route eth1 "${eth1_route}"
fi
/etc/init.d/network start
}
config_interface() {
local interface=$1
local ip=$2
local netmask=$3
local mac=$4
interface_cfg="/etc/sysconfig/network-scripts/ifcfg-${interface}"
cat << EOF > $interface_cfg
DEVICE=$interface
IPADDR=$ip
NETMASK=$netmask
HWADDR=$mac
ONBOOT=yes
BOOTPROTO=static
EOF
}
config_default_gateway() {
local gateway=$1
sed -i "s/^GATEWAY=.*/GATEWAY=$gateway/" /etc/sysconfig/network
}
config_route() {
local interface=$1
local route="$2"
route_conf=/etc/sysconfig/network-scripts/route-${interface}
> $route_conf
echo $route | sed 's/;/\n/' | \
while read line; do
dst=$(echo $line | awk '{print $1}')
gw=$(echo $line | awk '{print $2}')
if ! grep -q "$dst" $route_conf 2> /dev/null; then
echo "$dst via $gw dev $interface" >> $route_conf
fi
if [[ "$dst" == "0.0.0.0/0" ]]; then
config_default_gateway $gw
fi
done
}
################## sysvinit service portal ####################
start() {
if load_os_conf ; then
config_password
config_network
config_hostname
config_dns
cleanup
return 0
else
echo "not load $os_conf_file"
return 0
fi
}
RETVAL=0
case "$1" in
start)
start
RETVAL=$?
;;
*)
echo "Usage: $0 {start}"
RETVAL=3
;;
esac
exit $RETVAL