为保证运行镜像的ECS实例能成功完成初始化配置,建议您在制作Linux类型自定义镜像时,在源服务器上安装cloud-init。本文介绍安装阿里云版cloud-init和社区版cloud-init的操作步骤。
背景信息
cloud-init是云平台为Linux操作系统的虚拟机做系统初始化配置的开源服务软件。阿里云、AWS、Azure和OpenStack等主流云平台均支持cloud-init。阿里云版cloud-init能在ECS实例启动阶段完成系统初始化配置,包括NTP、软件源、主机名和SSH密钥对等,同时执行实例自定义数据(User data)脚本。更多信息,请参见cloud-init官方文档。
- 准备迁移上云的,但未安装cloud-init的Linux服务器。 说明 不准备迁移上云的服务器需谨慎安装。
- 已安装cloud-init,但版本低于0.7.9的Linux服务器。
- 已在阿里云运行的,但未安装cloud-init的ECS实例。
版本说明
不同云平台及不同版本之间的cloud-init不完全兼容,请选择合适的版本并配置合适的数据源(datasource)。其中,阿里云cloud-init的最新版本为19.1.21,数据源为Aliyun
。您可以在cloud-init官方网站自行下载其他版本的cloud-init。
Aliyun
)。- 0.7.6a版本:初期的阿里云版本cloud-init,在Python环境上依赖于Python 2.7。部分低版本操作系统的公共镜像仍旧保持该版本cloud-init。如果您所使用的镜像需要安装cloud-init 0.7.6a版本,请参见(可选)安装阿里云版cloud-init 0.7.6a15。说明 由于Python社区停止对Python 2.7的技术支持,建议您尽量使用高版本cloud-init,避免依赖库隐患。
- 低于社区0.7.9版本:初期的社区版cloud-init,不适用于初始化ECS实例,必须升级至较高版本。
- 18版本:高于18版本的cloud-init会自动完成网络的初始化配置,自动配置的网络为
BOOTPROTO=dhcp DEVICE=eth0 ONBOOT=yes STARTMODE=auto TYPE=Ethernet USERCTL=no
。如果您安装了cloud-init后有自定义网络配置的需求,请参见(可选)自定义网络配置。 - 19.1版本:阿里云公共镜像将逐步升级到cloud-init 19.1版本,在Python环境上依赖于Python 3.6。
检查cloud-init版本
- 登录源服务器。
- 运行以下命令检查是否已安装cloud-init。
which cloud-init
无路径输出信息表示未安装,您需要安装阿里云版cloud-init。
- 运行以下命令检查cloud-init版本号。
cloud-init --version
如果返回版本低于社区0.7.9版本,您需要安装阿里云版cloud-init 19.1.21。 - 完成服务器数据备份。
(推荐)安装阿里云版cloud-init 19.1.21
按以下步骤,下载数据源为Aliyun
的19.1.21版本cloud-init。
- 确保源服务器已安装Python PIP依赖库。以安装python3-pip依赖库为例,Linux部分发行版的安装命令如下。
- CentOS/Red Hat Enterprise Linux:
yum -y install python3-pip
- Ubuntu/Debian:
apt-get -y install python3-pip
- OpenSUSE/SUSE:
zypper -n install python3-pip
- CentOS/Red Hat Enterprise Linux:
- 运行以下命令下载阿里云版cloud-init。
wget https://ecs-image-tools.oss-cn-hangzhou.aliyuncs.com/cloudinit/cloud-init-19.1.21.tgz
- 运行以下命令解压cloud-init安装包到当前目录。
tar -zxvf cloud-init-19.1.21.tgz
- 进入cloud-init目录下,并安装依赖库。
cd ./cloud-init-19.1.21 pip3 install -r ./requirements.txt
- 进入cloud-init的tools目录。
cd ./tools
- 运行以下命令执行安装cloud-init的脚本deploy.sh。
deploy.sh脚本的参数说明和取值示例如下:bash ./deploy.sh <issue> <major_version>
例如,您当前的操作系统为CentOS 7,则需要运行的命令为参数 说明 示例 <issue> 操作系统平台类型。取值范围:centos | redhat |rhel | debian | ubuntu | opensuse | sles。参数取值均大小写敏感,其中sles表示SUSE/SLES。 centos <major_version> 操作系统平台主要版本号。 说明 ubuntu 14不支持安装阿里云版cloud-init 19.1.21。CentOS 7.6的主要版本号为7 bash ./deploy.sh centos 7
。 - 确认cloud-init是否安装成功。若返回
"description": "success"
,表示安装成功。
- CentOS 7/8
# 检查安装python3-pip if ! python3 -c 'import setuptools' >& /dev/null; then yum -y install python3-pip fi # 备份旧版cloud-init test -d /etc/cloud && mv /etc/cloud /etc/cloud-old # 下载并解压阿里云版cloud-init wget https://ecs-image-tools.oss-cn-hangzhou.aliyuncs.com/cloudinit/cloud-init-19.1.21.tgz tar -zxvf ./cloud-init-19.1.21.tgz # 安装cloud-init issue_major=$( cat /etc/redhat-release | grep -Eo '[0-9]+\.?[0-9]+' | head -1 | awk -F'.' '{printf $1}') bash ./cloud-init-*/tools/deploy.sh centos "$issue_major"
- Red Hat Enterprise Linux 7/8
# 检查安装python3-pip if ! python3 -c 'import setuptools' >& /dev/null; then yum -y install python3-pip fi # 备份旧版cloud-init test -d /etc/cloud && mv /etc/cloud /etc/cloud-old # 下载并解压阿里云版cloud-init wget https://ecs-image-tools.oss-cn-hangzhou.aliyuncs.com/cloudinit/cloud-init-19.1.21.tgz tar -zxvf ./cloud-init-19.1.21.tgz # 安装cloud-init issue_major=$( cat /etc/os-release | grep VERSION_ID | grep -Eo '[0-9]+\.?[0-9]+' | head -1 | awk -F'.' '{printf $1}') bash ./cloud-init-*/tools/deploy.sh rhel "$issue_major"
- Ubuntu 16/18/20
# 检查安装python3-pip if ! python3 -c 'import setuptools' >& /dev/null; then apt-get install python36 python3-pip -y fi # 备份旧版cloud-init test -d /etc/cloud && mv /etc/cloud /etc/cloud-old # 下载并解压阿里云版cloud-init wget https://ecs-image-tools.oss-cn-hangzhou.aliyuncs.com/cloudinit/cloud-init-19.1.21.tgz tar -zxvf ./cloud-init-19.1.21.tgz # 安装cloud-init issue_major=$( cat /etc/os-release | grep VERSION_ID | grep -Eo '[0-9]+\.?[0-9]+' | head -1 | awk -F'.' '{printf $1}') bash ./cloud-init-*/tools/deploy.sh ubuntu "$issue_major"
- Debian 9/10
# 检查安装python3-pip if ! python3 -c 'import setuptools' >& /dev/null; then apt-get -y install python3-pip fi # 备份旧版cloud-init test -d /etc/cloud && mv /etc/cloud /etc/cloud-old # 下载并解压阿里云版cloud-init wget https://ecs-image-tools.oss-cn-hangzhou.aliyuncs.com/cloudinit/cloud-init-19.1.21.tgz tar -zxvf ./cloud-init-19.1.21.tgz # 安装cloud-init issue_major=$( cat /etc/os-release | grep VERSION_ID | grep -Eo '[0-9]+\.?[0-9]+' | head -1 | awk -F'.' '{printf $1}') bash ./cloud-init-*/tools/deploy.sh debian "$issue_major"
- SUSE 12/15
# 检查安装python3-pip if ! python3 -c 'import setuptools'>& /dev/null; then zypper -n install python3-pip fi # 备份旧版cloud-init test -d /etc/cloud && mv /etc/cloud/etc/cloud-old # 下载并解压阿里云版cloud-init wget https://ecs-image-tools.oss-cn-hangzhou.aliyuncs.com/cloudinit/cloud-init-19.1.21.tgz tar -zxvf ./cloud-init-19.1.21.tgz # 安装cloud-init issue_major=$( cat /etc/os-release | grep VERSION_ID | grep -Eo '[0-9]+\.?[0-9]+' | head -1 | awk -F'.' '{printf $1}') bash ./cloud-init-*/tools/deploy.sh sles "$issue_major"
- OpenSUSE 15
# 检查安装python3-pip if ! python3 -c 'import setuptools'>& /dev/null; then zypper -n install python3-pip fi # 备份旧版cloud-init test -d /etc/cloud && mv /etc/cloud/etc/cloud-old # 下载并解压阿里云版cloud-init wget https://ecs-image-tools.oss-cn-hangzhou.aliyuncs.com/cloudinit/cloud-init-19.1.21.tgz tar -zxvf ./cloud-init-19.1.21.tgz # 安装cloud-init issue_major=$( cat /etc/os-release | grep VERSION_ID | grep -Eo '[0-9]+\.?[0-9]+' | head -1 | awk -F'.' '{printf $1}') bash ./cloud-init-*/tools/deploy.sh opensuse"$issue_major"
(可选)安装阿里云版cloud-init 0.7.6a15
cloud-init-0.7.6a15
。如果您需要进行测试,请先运行命令mv /etc/cloud/cloud.cfg /etc/cloud/cloud.cfg_bak备份配置文件。- 运行以下命令,检查操作系统的版本为CentOS 6、Debian 9及SUSE Linux Enterprise Server 12。
cat /etc/issue
- 运行以下命令,下载并解压阿里云版cloud-init 0.7.6a15。
wget https://ecs-image-tools.oss-cn-hangzhou.aliyuncs.com/cloud-init-0.7.6a15.tgz tar -zxvf cloud-init-0.7.6a15.tgz
- 进入cloud-init的tools目录。
cd cloud-init-0.7.6a15/tools/
- 运行以下命令。安装cloud-init。
deploy.sh脚本的参数说明和取值示例如下:bash ./deploy.sh <issue> <major_version>
例如,您当前的操作系统为CentOS 6,则需要运行的命令为参数 说明 示例 <issue> 操作系统平台类型。取值范围:centos | debian | sles。参数取值均大小写敏感,其中sles表示SUSE/SLES。 centos <major_version> 操作系统平台主要版本号。 CentOS 6.5的主要版本号为6 bash ./deploy.sh centos 6
。
(可选)安装社区版cloud-init
- 确保源服务器已安装Git、Python和Python PIP依赖库。以安装Git、python3.6和python3-pip依赖库为例,Linux部分发行版的安装命令如下。
- CentOS/Red Hat Enterprise Linux:
yum -y install git python36 python3-pip
- Ubuntu/Debian:
apt-get -y install git python36 python3-pip
- OpenSUSE/SUSE:
zypper -n install git python36 python3-pip
- CentOS/Red Hat Enterprise Linux:
- 运行以下命令使用Git下载cloud-init源码包。
git clone https://git.launchpad.net/cloud-init
- 进入cloud-init目录。
cd ./cloud-init
- 运行以下命令安装所有依赖库。
sudo pip3 install -r ./requirements.txt
- 运行以下命令安装cloud-init。
python3 setup.py install
- 修改配置文件cloud.cfg。
(可选)自定义网络配置
- 安装cloud-init后,打开/etc/cloud/cloud.cfg文件。
vim /etc/cloud/cloud.cfg
- 按i进入编辑模式,在
Example datasource config
之前增加disabled配置。network: config: disabled
说明 增加该配置之后,cloud-init不会管理/etc/sysconfig/network-scripts/下网络配置,需要您自行管理。 - 编辑完成后,按Esc键退出编辑模式,然后输入
:wq
并回车,保存退出文件。
(可选)不修改主机名以及/etc/hosts配置文件
cloud-init的配置文件中,默认设置了不保留主机名。如果您不希望实例的主机名以及/etc/hosts配置文件被修改,可以参考以下操作修改cloud-init的配置文件。
- 安装cloud-init后,打开/etc/cloud/cloud.cfg文件。
vim /etc/cloud/cloud.cfg
- 按i进入编辑模式,将
preserve_hostname: false
修改为preserve_hostname: true
。 - 编辑完成后,按Esc键退出编辑模式,然后输入
:wq
并回车,保存退出文件。当preserve_hostname: true
时,cloud-init将不会自动修改主机名以及/etc/hosts配置文件。
故障排查
通过Python 3安装cloud-init时,缺少依赖库怎么处理?
不同镜像缺少的库可能不同,您都可以通过pip安装,之后再次安装cloud-init。cloud-init运行异常,提示报错信息,如何处理?
如果系统默认软件包管理器(例如yum)和pip管理器分别安装过不同版本的依赖库,可能造成库版本冲突,导致cloud-init运行异常。建议您根据报错信息按需下载依赖库。报错信息 原因 排错命令 no setuptools module in python
缺失模块python setuptools 以python3.6为例: - CentOS/Red Hat:
yum -y install python3-pip
- Ubuntu/Debian:
apt-get -y install python3-pip
- OpenSUSE/SUSE:
zypper -n install python3-pip
File "/home/testuser/cloud-init/cloudinit/log.py", line 19, in <module> import six ImportError: No module named six )
缺失依赖库six pip3 install six
File "/home/testuser/cloud-init/cloudinit/url_helper.py", line 20, in <module> import oauthlib.oauth1 as oauth1 ImportError: No module named oauthlib.oauth1 )
缺失依赖库oauthlib pip3 install oauthlib
报错时没有明确缺少的依赖库 未映射相关错误信息 根据cloud-init的requirements.txt文件里显示的库,运行以下命令安装所有依赖库: pip3 install -r requirements.txt
- CentOS/Red Hat:
如何确定cloud-init已成功安装且版本正确?
当您安装好cloud-init后,可以使用cloud-init --version命令查看cloud-init的版本信息,如果符合预期版本,则表示cloud-init已成功安装。例如,您安装的是阿里云版cloud-init 19.1.21。安装完成后,如果运行cloud-init --version命令的回显信息包含19.1.21
,则表示cloud-init 19.1.21已成功安装。实例中安装了新版本的Python 3导致了cloud-init执行异常,如何处理?
如果您在实例中安装了新版本的Python 3(例如Python 3.9),并将新版本的Python 3设置为默认版本(即已为新版Python 3创建了软链接,例如,ln -s /usr/bin/python3.9 /usr/bin/python3),则会导致已安装的cloud-init执行异常。例如,运行cloud-init --version将会报错:
您可以通过以下任一方式解决该问题:$cloud-init --version Traceback (most recent call last): File "/usr/local/bin/cloud-init", line 33, in <module> sys.exit(load_entry_point('cloud-init==19.1.9', 'console_scripts', 'cloud-init')()) File "/usr/local/bin/cloud-init", line 22, in importlib_load_entry_point for entry_point in distribution(dist_name).entry_points File "/usr/lib64/python3.9/importlib/metadata.py", line 524, in distribution return Distribution.from_name(distribution_name) File "/usr/lib64/python3.9/importlib/metadata.py", line 187, in from_name raise PackageNotFoundError(name) importlib.metadata.PackageNotFoundError: cloud-init
- 方式一:使用新版的Python 3重新安装cloud-init。
- 方式二:修改cloud-init执行文件,将Python解释器对应的路径修改为历史版本的Python 3。以Python 3.6为例,修改cloud-init执行文件中解释器的操作如下:
- 运行以下命令,打开cloud-init文件。
vim /usr/local/bin/cloud-init
- 按i进入编辑模式,将文件开头
#!
后的内容修改为Python 3.6所在的路径。修改后,对应的#!
行内容如下所示:#!/usr/bin/python3.6
- 按Esc键退出编辑模式,然后输入
:wq
并回车,保存退出文件。
- 运行以下命令,打开cloud-init文件。
安装cloud-init后,在创建实例时设置的实例元数据中的自定义数据(user-data)不执行或者执行失败,如何处理?
- 在实例内,运行以下命令,检查实例元数据中的user-data是否存在。
curl http://100.100.100.200/latest/user-data
检查结果说明:- 如果已设置了user-data,则会返回对应的user-data信息。您需要继续下一步进行问题排查。
- 如果没有返回信息,则表示您没有设置user-data。
- 通过多种方式,排查user-data不执行或执行失败的原因。
- 检查user-data数据格式是否准确。
user-data的数据由cloud-init执行,您需要确保数据格式准确无误。例如,user-data的首行必须以
#!
开头。更多信息,请参见使用实例自定义数据(Linux实例)。 - 检查在创建实例时,是否选择了仅加固模式。
如果选择了仅加固模式,将导致cloud-init组件初始化配置失败,影响实例的元数据、自定义数据等配置。更多信息,请参见查看实例元数据。
- 通过cloud-init的日志文件/var/log/cloud-init.log,查看user-data执行结果,并根据报错信息排查问题。日志文件记录信息示例如下:
util.py[DEBUG]: Running command ['/var/lib/cloud/instance/scripts/part-001'] with allowed return codes [0] (shell=False, capture=False)
- 查看user-data执行过程的标准输出以及标准错误输出。在Linux系统初始化工具systemd中,user-data由系统服务cloud-final.service执行,您可以运行以下命令查看user-data执行过程的标准输出以及标准错误输出,并根据输出内容排查问题。
journalctl -u cloud-final.service
- 如果以上方式均无法定位user-data不执行或者执行失败的原因,建议您将user-data内容拷贝到本地主机进行调试,查看是否可以成功执行。
- 检查user-data数据格式是否准确。
- 在实例内,运行以下命令,检查实例元数据中的user-data是否存在。
- 安装cloud-init后,但系统初始化配置和实例自定义数据(User data)脚本无法正常执行,如何处理?
- 运行以下命令,检查cloud-init的四个服务是否设置为开机自启动。
如果出现报错信息或者systemctl is-enabled cloud-init-local.service systemctl is-enabled cloud-init.service systemctl is-enabled cloud-config.service systemctl is-enabled cloud-final.service
disabled
信息,表示cloud-init未设置开机自启动。 - 运行以下命令,设置cloud-init开机自启动。
systemctl enable cloud-init-local.service systemctl enable cloud-init.service systemctl enable cloud-config.service systemctl enable cloud-final.service
- 运行以下命令,检查cloud-init的四个服务是否设置为开机自启动。
- 在创建实例时对系统盘进行扩容,但在实例内部发现根分区大小并没有自动扩容,如何处理?Linux实例分区自动扩容由cloud-init提供支持,需要确保系统安装growpart工具且cloud.cfg文件中配置正确。
- 运行以下命令,检查系统是否安装growpart工具。
which growpart
- 可选:如果没有安装,运行以下命令,安装growpart工具。
- RHEL系列:
sudo yum -y install cloud-utils-growpart
- Debian系列:
sudo apt -y install cloud-guest-utils
- RHEL系列:
- 运行以下命令,查看/etc/cloud/cloud.cfg文件中是否存在如下图中的内容。
cat /etc/cloud/cloud.cfg
- 可选:如果不存在,添加该内容到/etc/cloud/cloud.cfg文件中。
- 运行以下命令,检查系统是否安装growpart工具。
后续步骤
- 对于准备迁移上云的Linux服务器:
- 对于已在阿里云上运行Linux自定义镜像的ECS实例: 您可以重启系统验证结果。如果系统自动配置了主机名、软件源和NTP等配置,则表示已成功安装cloud-init。例如,查看网络配置文件。
[testuser@iZbp1ios3psx4hoi******Z ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0 # Created by cloud-init on instance boot automatically, do not edit. # BOOTPROTO=dhcp DEVICE=eth0 ONBOOT=yes STARTMODE=auto TYPE=Ethernet USERCTL=no