项目简介

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. 【MySQL】从入门到精通5-一对多-外键

    上期:[MySQL]从入门到掌握4-主键与Unique 第一章:创建角色表 啥是一对多啊? 一个账号可以有多个角色,但是一个角色只能属于一个账号. 举个例子,我们之前创建的是玩家的账号数据库. 但是一 ...

  2. QFile 对文件进行读写操作

    QFile 对文件进行读写操作 1 QFile 进行读写操纵 2 QFile file(pah ) 文件路径 3 读  file.open(打开方式)  file.readAll(). file.re ...

  3. Android蓝牙线控切歌、连接状态监听(无线耳机也适用)

    1. 监听蓝牙设备(音频)连接状态 所有代码已测试在Android11也能正常使用 (Android SDK 30) 首先新建一个广播类 BluetoothStateReceiver /** * @a ...

  4. 【Traefik二次开发】服务 Service 开发

    Service 定义 https://doc.traefik.io/traefik/routing/services/ The Services are responsible for configu ...

  5. 总在用户态调试 C# 程序,终还是搭了一个内核态环境

    一:背景 一直在用 WinDbg 调试用户态程序,并没有用它调试过 内核态,毕竟不是做驱动开发,也没有在分析 dump 中需要接触用内核态的需求,但未知的事情总觉得很酷,加上最近在看 <深入解析 ...

  6. noip 2014 提高组初赛

    noip 2014 提高组初赛 一. TCP协议属于哪一层协议( ) A. 应用层 B. 传输层 C. 网络层 D. 数据链路层 B TCP(传输控制协议) 若有变量int a; float: x, ...

  7. 【设计模式】Java设计模式 - 观察者模式

    [设计模式]Java设计模式 - 观察者模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 @一个有梦有戏的人 @怒放吧德德 分享学习心得,欢迎指正,大家一起学习成长 ...

  8. 【读书笔记】C#高级编程 第五章 泛型

    (一)泛型概述 泛型不仅是C#编程语言的一部分,而且与程序集中的IL代码紧密地集成.泛型不仅是C#语言的一种结构,而且是CLR定义的.有了泛型就可以创建独立于被包含类型的类和方法了. 1.性能 泛型的 ...

  9. 超详细的格式化输出(format的基本玩法)

    一.format的基本玩法 一.什么是format format是字符串内嵌(字符串内嵌:字符串中再嵌套字符串,加入双引号或单引号)的一个方法,用于格式化字符串.以大括号{}来标明被替换的字符串 fo ...

  10. KMP&Z函数详解

    KMP 一些简单的定义: 真前缀:不是整个字符串的前缀 真后缀:不是整个字符串的后缀 当然不可能这么简单的,来个重要的定义 前缀函数: 给定一个长度为\(n\)的字符串\(s\),其 \(前缀函数\) ...