项目简介

cloud-init是一款用于初始化云服务器的工具,它拥有丰富的模块,能够为云服务器提供的能力有:初始化密码、扩容根分区、设置主机名、注入公钥、执行自定义脚本等等,功能十分强大。

目前为止cloud-init是云服务器初始化工具中的事实标准,它几乎适用于所有主流的Linux发行版,也是各大云厂商正在使用的默认工具,社区活跃。基于Python语言使得它能够轻易跨平台、跨架构运行,良好的语法抽象使得它适配新模块、新发行版十分容易。

基本概念

实例数据与数据源

实例数据(Instance data)是cloud-init用来处理并配置实例的数据集合。根据用途,可以将实例数据划分为如下三类:

  • metadata:一系列字典格式的元数据,用作模板渲染、模块运行等等。
  • userdata:启动实例时用户能够指定的数据(单实例数据)
  • vendordata:云基座传入的数据(全局数据)

在openstack中,metadata、userdata均在用户创建实例时通过相应参数传入,而vendordata则由nova-api-metadata服务启动时指定。

这些数据可能来源于许多地方,cloud-init使用数据源一词表示实例数据的来源,目前内置的数据源有:OpenStack、ConfigDrive、Amazon EC2、Azure等等,不同的数据源也表明了不同的实例数据搜索方式。cloud-init在实例内部启动时并不知道从哪里才能够找到实例数据,它会根据预设的一个数据源的列表一个一个查找实例数据,而首个能够找到实例数据的数据源将成为这次启动的数据源。

如果cloud-init指定了OpenStack数据源,那么实例数据将均通过HTTP API请求获取,不同类别的实例数据有着不同的获取方式:

而如果指定了ConfigDrive数据源,那么实例数据将均通过文件获取,cloud-init会搜索标记有CONFIG-2标签的分区,随后将该分区挂载至临时目录中,并读取其中包含实例数据的文件:

  • metadata:file://TMPDIR/openstack/latest/meta_data.json
  • userdata:file://TMPDIR/openstack/latest/user_data
  • vendordata:file://TMPDIR/openstack/latest/vendor_data.json、file://TMPDIR/openstack/latest/network_data.json

所有数据源的参考文档:Datasources — cloud-init 22.1 documentation (cloudinit.readthedocs.io)

启动阶段

在整个系统启动的过程中,cloud-init的执行包括5个阶段,执行阶段从前到后分别为:Generator、Local、Network、Config、Final,每一个阶段都有着它们各自的作用。

Generator

  • systemd服务:/usr/lib/systemd/system-generators/cloud-init-generator
  • 运行于:系统刚启动时

generator是最先运行的阶段,它的功能包括:

  1. 判断是否需要禁止运行cloud-init。generator会根据如下条件判断:

    1. /etc/cloud/cloud-init.disabled文件是否存在。
    2. 内核参数中是否包括有cloud-init=disabled配置项。
  2. 筛选可用的数据源。generator为每个数据源都写了判断函数,运行判断函数后返回可用数据源的列表,存放于datasource_list配置项并写入/run/cloud-init/cloud.cfg中。

部分情况下,generator对/run/cloud-init/cloud.cfg文件的写入会对cloud-init的运行产生影响,此时可以通过修改/etc/cloud/ds-identify.cfg配置文件,从而更改generator的行为。

# /etc/cloud/ds-identify.cfg
# 该策略表示启动cloud-init,但不筛选可用数据源
policy: enabled,found=all,maybe=none,notfound=disabled

Local

  • systemd服务:/usr/lib/systemd/system/cloud-init-local.service
  • 运行于:根目录挂载并可读写后

Local阶段的主要功能为:

  1. 搜索数据源。在datasource_list配置项中搜索第一个可用的数据源,作为本次启动的数据源。数据源搜索细节如下:

    1. 尝试从缓存恢复。若存在obj.pkl缓存,为trust模式或ds.check_instance_id()返回true,则从缓存恢复。
    2. 搜索数据源,遍历datasource_list配置项中的数据源,找出第一个可用的数据源,并返回。
  2. 应用网络配置(不拉起网络)。网络配置的来源如下:
    1. 数据源,使用从数据源获取的网络配置,渲染并写入网络配置至磁盘中。
    2. 回退,如果无数据源,则写入一个默认的dhcp网络配置。
    3. 不应用,如果cloud-init配置文件中有如下配置项:network: {config: disabled},或者存在/var/lib/cloud/data/upgraded-network文件,则不应用网络配置。

Network

  • systemd服务:/usr/lib/systemd/system/cloud-init.service
  • 运行于:网络服务启动之后

Network阶段的主要功能为:

  1. self.datasource.setup(),在uesr-data和vendor-data处理之前调用,用于网络启动后再次更新数据源,目前仅用于azure获取fabric数据并填充进fabric_data。
  2. 存储与渲染userdata和vendor_data。
  3. self.datasource.activate(),该方法在user-data和vendor-data渲染后,init_modules执行前调用。
  4. 运行cloud_init_modules中配置的模块。

Config

  • systemd服务:/usr/lib/systemd/system/cloud-config.service
  • 运行于:Network阶段之后

Config阶段的主要功能是运行cloud_config_modules中配置的模块。

Final

  • systemd服务:/usr/lib/systemd/system/cloud-final.service
  • 运行于:Config阶段之后

Config阶段的主要功能是运行cloud_final_modules中配置的模块。

cloud-config

cloud-config是cloud-init的配置文件,它用于控制cloud-init的行为,比如说该运行哪些功能,以及每个功能如何运行等等。和其他软件的配置文件相比,cloud-config具有高度定制化的特点,除了云服务器本身的cloud-config以外,cloud-init还能够从vendordata、userdata甚至内核参数中获取cloud-config,从而使得用户能够方便地利用cloud-init定制自己的云服务器。

模块

模块(Modules)是cloud-init运行的主体,所有我们需要的用来初始化云服务器的功能都是通过执行模块而实现的。以set_hostname模块为例,该模块的功能是设置主机名,当运行该模块时,它会读取cloud-config中的hostname参数,并将其中值设置为云实例的主机名。

每个模块都有名称、运行频率、配置参数这三大要素,其中运行频率表示一个模块该在什么时候运行,通常有两种运行频率:1. once-per-instance,表示仅在实例首次启动时运行;2. always,表示实例每次启动都运行。

是否运行某个模块、何时运行模块、怎么运行模块,这些都可以在cloud-config中配置,下面截取部分cloud-config,可以看到在这个云实例中:

  • network阶段将运行ssh模块,config阶段将运行mounts、locale等模块,final阶段将运行scripts开头的一些模块;
  • set-passwords模块默认的运行频率是once-per-instance,可将其调整为always,表示每次启动云实例时都会设置密码;
  • ssh_pwauth是set-passwords模块的配置项,ssh_deletekeys、ssh_genkeytypes是ssh模块的配置项,它们描述了该如何运行模块。
# /etc/cloud/cloud.cfg
ssh_pwauth: 1
ssh_deletekeys: 1
ssh_genkeytypes: ['rsa', 'ecdsa', 'ed25519'] cloud_init_modules:
- ssh cloud_config_modules:
- mounts
- locale
- [set-passwords,always] cloud_final_modules:
- scripts-per-once
- scripts-per-boot
- scripts-per-instance
- scripts-user

所有模块的参考文档:https://cloudinit.readthedocs.io/en/latest/topics/modules.html

发行版

cloud-init设计支持绝大多数的主流linux发行版,诸如Centos、Ubuntu、Arch、Fedora等等,然而不同的linux发行版可能在使用方式上有着或多或少的不同,因此cloud-init需要针对不同的发行版进行一定程度的抽象,形成一个统一层并提供给上层的模块使用。就算是这样,某些模块也只能提供给特定的发行版使用,比如apk_configure模块只能alpine使用,而apt_configure模块则只能在ubuntu、debian上使用,这点在使用cloud-init的过程中需要稍加注意。

基础用法

我们在使用cloud-init时一般不会特别地去执行cloud-init相关的命令,在云实例的启动过程中操作系统会按正常流程去执行cloud-init,不过当需要开发/调试cloud-init的时候,这些命令会带来很大的帮助。

执行cloud-init的四个阶段:

# local阶段
cloud-init init --local
# network阶段
cloud-init init
# config阶段
cloud-init modules --mode=config
# final阶段
cloud-init modules --mode=final

查询相关:

# 查询cloud-id
cloud-id
# 查询cloud-init执行状态
cloud-init status -l
# 查询metadata
cloud-init query <variable>
cloud-init query -l

清理缓存:

cloud-init clean
rm -rf /var/run/cloud-init/
rm -rf /var/lib/cloud/
rm -rf /var/log/cloud-init.log
rm -rf /etc/sysconfig/network-scripts/ifcfg-*

其他命令:

# 创建一个包含cloud-config(config.yaml)和shell脚本(script.sh)的userdata
cloud-init devel make-mime -a config.yaml:cloud-config -a script.sh:x-shellscript > userdata

使用案例

重置密码

cloud-config方式:

##template: jinja
#cloud-config runcmd:
# OpenStack数据源在local阶段无法获取数据,network阶段由于是trust模式,直接从缓存读取数据,无法获取更新后metadata,因此需要事先删除缓存。
- DIR=/var/lib/cloud/scripts/per-boot/ && mkdir -p $DIR && cd $DIR && echo '#!/bin/bash' > 99-clean-cloudinit-cache.sh && echo 'rm -f /var/lib/cloud/instance/obj.pkl' >> 99-clean-cloudinit-cache.sh && chmod +x 99-clean-cloudinit-cache.sh
# ConfigDrive数据源无法获取更新后metadata,需在首次启动后修改为OpenStack数据源。
- echo 'datasource_list: [OpenStack]' > /etc/cloud/cloud.cfg.d/90_openstack_datasource.cfg
# 首次启动后禁止写入网络配置,防止ConfigDrive中的bond配置被覆盖。
- touch /var/lib/cloud/data/upgraded-network {% if ds.meta_data.meta.admin_pass is defined %}
chpasswd:
list: |
root:{{ds.meta_data.meta.admin_pass}}
expire: false
ssh_pwauth: [true] phone_home:
url: http://169.254.169.254/openstack/latest/phone_home?unset=admin_pass
post:
- instance_id
tries: 5 cloud_config_modules:
- [set-passwords,always]
- [phone_home,always]
- ssh
- runcmd
{% endif %}
{% endif %}

获取更新后metadata的方法,除删除缓存之外,也可实现setup方法,在该方法中获取metadata并填充进数据源中(参考azure数据源)。

将set-passwords和phone_home模块设为always的方法,出了在vendor-data中指定外,也可在activate方法中实现,删除执行这两个模块的信号(参考exoscale数据源)。

ssh公钥注入

使用如下userdata注入ssh公钥:

##template: jinja
#cloud-config ssh_authorized_keys:
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDIe6oWYfMB4m9TDSmyVlONj2UakYKkAnpTsZnYXWHUd6zLQDvCLkeXmLiBTuJ51Dh6nolL4rZETj1wLJpXqcMvDhhOZyA0Ji3ENbeJj0URWNjDpRUc3eUApDOzpa3gHm8yRwXDZsZbFMpqcL5vQjlZJ9K+SmLCvbfk6sG04uJWLsIFrjSkxlRxdWwHwdvMH9tAo3UeQGnzRxdnF4zxrob+vAV7PPqJ9u4J6GwXWykTtS+cmvoPOBWQHL5gULxp2FVt/xTF5xY2IRHpzfNmJlCd4G7HGow/PVD+jsIN57iNwvxU7dvTzg0PVUXGQImJvQ8pkHD6//ghXcLleUQz3f+7Brlc6yEZuDdEy2NFEnYW8CoEymPSXVZaBykiggP2XSGp6gQa1gtT7yy44EEB5kjX9epi+jAwiCRaLDrgSLBWQmJp8435dtoOALZOXb1Br0uOA0a3G3KZr+7v11f09NZgFPzJTrY2d4ZNtOUILOcQkUAhtW6yOwuCiuxVeKM8cjE= webssh@hikcloud

云实例初始化工具cloud-init简介的更多相关文章

  1. 云实例初始化工具cloud-init源码分析

    源码分析 代码结构 cloud-init的代码结构如下: cloud-init ├── bash_completion # bash自动补全文件 │   └── cloud-init ├── Chan ...

  2. JavaSE面试题:类初始化和实例初始化等

    类初始化过程 1.一个类要创建实例需要先加载并初始化该类 main方法所在的类需要先加载和初始化 2.一个子类要初始化需要先初始化父类 3.一个类初始化就是执行<clinit>()方法 & ...

  3. Java类初始化和实例初始化过程

    1.类初始化过程 一个类要创建实例需要先加载并初始化该类 main方法所在的类需要先加载和初始化 一个子类要初始化需要先初始化父类 一个类初始化就是执行<client>()方法(编译器生成 ...

  4. JAVA类初始化和实例初始化

    一.类初始化过程 1.一个类要创建实例需要先创建和加载 (1) main方法所在的类需要先加载和实例化 2.一个子类要初始化,需要先初始化父类 3.一个类初始化就是执行<clinit>方法 ...

  5. .NET DLL 保护措施应用实例(百度云批量保存工具)

    最近做了个小工具,将保护措施思路全部应用到了此工具中. 点我下载   百度云批量保存工具是一款专门用于自动批量保存百度云分享的软件. 本软件特点:1:完全模拟人工操作:2:可以批量保存百度分享的文件( ...

  6. 002-Spring Cloud 功能简介

    一.主要功能 分布式/版本化配置.服务注册与发现.路由.服务间调用.负载均衡.断路器.分布式消息传递 1.云本地应用[Cloud Native Applications] Spring Cloud C ...

  7. 亚马逊AWS EC2云实例AMI安装LNMP环境(3)——Mysql5.5

    概括:这里选择亚马逊EC2的Linux AMI实例,该Linux服务器是亚马逊预配置的Linux环境,内置多个YUM源,属于亚马逊首推的稳定Linux服务器.默认登录用户名为ec2-user,执行ro ...

  8. vue 源码学习二 实例初始化和挂载过程

    vue 入口 从vue的构建过程可以知道,web环境下,入口文件在 src/platforms/web/entry-runtime-with-compiler.js(以Runtime + Compil ...

  9. 通过阿里云命令行工具 aliyuncli 购买服务器

    开始想通过 aliyuncli 的 golang 源码进行编译安装(注:python 版的 aliyuncli 已不再维护),但没成功,详见 通过 golang 源码编译阿里云命令行工具 aliyun ...

随机推荐

  1. Linux上安装jdk 1.8

    1.下载jdk1.8 这里贴个oracle官网链接 https://www.oracle.com/java/technologies/downloads/  里面的jdk版本基本都有 2.将压缩包上传 ...

  2. MAC上PKG打包

    pkg是Mac平台上非常常见的一种安装包格式,如果你想要快速将软件制作为pkg文件,就千万不要错过Packages Mac版,Packages Mac版是Mac平台上能够快速为您生成pkg程序包的一款 ...

  3. kingbaseES V8R6集群备份恢复案例之---备库作为repo主机执行物理备份

    ​ 案例说明: 此案例是在KingbaseES V8R6集群环境下,当主库磁盘空间不足时,执行sys_rman备份,将集群的备库节点作为repo主机,执行备份,并将备份存储在备库的磁盘空间. 集群架构 ...

  4. KingbaseES V8R6单实例外部备份故障案例

    案例说明: 在KingbaseES V8R6单实例环境,配置外部备份服务器使用sys_backup.sh物理备份时,出现以下"WAL segment xxx was not archived ...

  5. KingbaseES R6 集群修改物理IP和VIP案例

    在用户的实际环境里,可能有时需要修改主机的IP,这就涉及到集群的配置修改.以下以例子的方式,介绍下KingbaseES R6集群如何修改IP. 一.案例测试环境 操作系统: [KINGBASE@nod ...

  6. Jmeter中的JSON提取器用法

    一.使用前提 一般来说JSON提取器只适用于响应结果中返回的是json数据 二.需求 在下一个接口调用上一个接口的数据,如:请求1返回的结果,处理以后作为请求2的参数使用. 首先需要下载JSON Ex ...

  7. UEC++ 代理/委托

    代理: 代理可以帮助我们解决一对一或是一对多的任务分配工作.主要可以帮助我们解决通知问题.我们可以通过代理完成调用某一个对象的一个函数,而不直接持有该对象的任何指针. 代理就是为你跑腿送信的,你可以不 ...

  8. aardio + AutoHotkey 混合编程

    本文主要介绍 aardio + AutoHotkey 混合编程. 在 aardio 中可以调用很多编程语言,例如 C语言.C++.C#.Java.Python.R.Javascript.Node.Js ...

  9. 货币转换I

    A=input() if A[0] in ['U','u']: RMB=(eval(A[3:]))*6.78 print("RMB{:.2f}".format(RMB)) else ...

  10. C#-01 关于C#中传入参数的一些用法

    实验环境 实验所处环境位于vs2019环境中 学习内容 一.最基础的参数传入:值参数 对于这种传入,和其他的c,c++编程语言参数传入一样,没有太大差别,在这里给如下例子: 虽然这里并没有进行传参但是 ...