当镜像的操作系统不在阿里云所支持的平台列表中,并且不能安装cloud-init时,您可以在导入自定义镜像时选择Customized Linux(定制版镜像)。阿里云将定制版Linux镜像当作无法识别的操作系统,您需要在导入镜像前,根据本文描述在镜像中添加解析脚本,便于初次启动时自动化配置实例。
限制要求
Customized Linux镜像具有如下限制条件:
- 第一个分区必须可以被写入。
- 第一个分区的文件类型只能是FAT32、EXT2、EXT3、EXT4或UFS。
- 虚拟文件的大小必须大于5GiB。
Customized Linux镜像具有如下安全要求:
- 不能存在可被远程利用的高危漏洞。
- 使用控制台的管理终端(VNC)登录实例时,如果存在初始默认密码,您必须在首次登录时修改,修改密码之前不允许进入实例做任何操作。详情请参见通过密码认证登录Linux实例。
- 不支持默认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地址列表,默认用空格分隔 - 专有网络VPC类型实例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