cloud-init
cloud-init是云平台为Linux操作系统的虚拟机做系统初始化配置的开源服务软件。阿里云、AWS、Azure和OpenStack等主流云平台均支持cloud-init。cloud-init系统启动阶段完成系统初始化配置。包括但不限于下面的定制化工作
- 设置默认语言环境
- 设置实例主机名
- 添加 ssh keys到 .ssh/authorized_keys
- 设置用户密码
- 配置网络安装软件包
为了实现 instance 定制工作,cloud-init 分为 4 个阶段执行任务
- local
- init
- config
- final
Install cloud-init
在虚拟机内安装cloud-init
代码语言:javascript复制yum install cloud-init -y
配置文件在/etc/cloud目录,主配置文件为/etc/cloud/cloud.cfg
查看cloud-init版本
代码语言:javascript复制cloud-init -v
/usr/bin/cloud-init 19.4
cloud-init 安装后将以下 4 个阶段执行的任务以服务的形式注册到系统中,比如在 systemd 的环境下,能够看到4个阶段分别对应的服务
- local - cloud-init-local.service
- init - cloud-init.service
- config - cloud-config.service
- final - cloud-final.service
[root@kvm_host01 system]# ls /etc/systemd/system/cloud*
cloud-config.service cloud-final.service cloud-init-local.service cloud-init.service
local 阶段
cloud-init 阶段为执行的第一个阶段,此时不知道该如何配置网卡cloud-init 的任务就是从config drive 中获取配置信息,然后写入 /etc/network/interfaces 文件(如果是 centos 则写入 /etc/sysconfig/network-scripts/ifcfg-xxx)。如果没有 config drive,则将所有网卡配置成 dhcp 模式。非常关键的一步,只有当网卡正确配置后,才能获取到 metadata。
init config 和 final 阶段
正常情况下,在这三个阶段执行之前 instance 网络完成配置,并且已经成功获取到 metadata。cloud-init 的配置文件 /etc/cloud/cloud.cfg 定义了三个阶段分别要执行的任务,任务以 module 形式指定。instance 定制工作就是由module 完成的。module 决定做哪些定制化工作,而 metadata 则决定最终定制化的结果。
举个例子,如果 cloud.cfg 中指定了set_hostname 的 module,则意味着 cloud-init 会设置 instance 的主机名,而具体设置成哪个主机名则由 metadata 中hostname参数决定。有些 module 是有默认行为的,比如growpart,如果 metadata 中没有特别指定,它会自动扩展/分区。
cloud-init 典型应用
设置 hostname
cloud-init 默认会将 instance 的名字设置为 hostname。可利用 cloud-init 的set_hostname模块实现。set_hostname查询 metadata 中 hostname 信息,默认值就是 instance 的名字,配置指定hostname
代码语言:javascript复制cloud-init:
#cloud-config
hostname: kvm_host01
fqdn: kvm_host01.example.com
manage_etc_hosts: true
参数说明如下
- cloud-init 只会读取以**#cloud-config**开头的数据,这一行配置尤为关键。hostname: kvm_host01 参数传入 cloud-init 将 hostname 设置为kvm_host01 。
- manage_etc_hosts: true 参数传入 cloud-init 更新 /etc/hosts 文件。
定制用户初始密码
用set-passwords模块为用户设置密码并启用密码登录。
代码语言:javascript复制#cloud-config
ssh_pwauth: true
disable_root: false
chpasswd:
list: |
root:q1w2E#R$
centos:newpassword
expire: False
参数说明如下
- root 和 ubuntu 用户密码设置为 q1w2E#R$和newpassword。
- ssh_pwauth 启用密码登录
KVM使用cloud-init 初始化虚拟机
1,虚拟机安装cloud-init
代码语言:javascript复制yum install cloud-init -y
检查Cloud-Init工具相关配置是否成功
执行以下命令无错误发生,说明Cloud-Init配置成功
代码语言:javascript复制[root@kvm-node1 mnt]# cloud-init init --local
Cloud-init v. 19.4 running 'init-local' at Sun, 12 Jun 2022 08:13:55 0000. Up 2258404.99 seconds.
注意:在多次使用cloud-init 初始化虚拟机时需要提前删除虚拟机/var/lib/cloud目录下产生的旧数据,否则cloud-init 初始化无法重新执行!!!
2,创建 ssh 密钥对
生成名为“id_rsa”和“id_rsa.pub”的文件
代码语言:javascript复制ssh-keygen -t rsa -b 4096 -f id_rsa -C kvm -N "" -q
ssh-keygen常用参数
-t:指定生成密钥的类型,默认使用SSH2d的rsa
-f:指定生成密钥的文件名,默认id_rsa(私钥id_rsa,公钥id_rsa.pub)
-P:提供旧密码,空表示不需要密码(-P ‘’)
-N:提供新密码,空表示不需要密码(-N ‘’)
-b:指定密钥长度(bits),RSA最小要求768位,默认是2048位;DSA密钥必须是1024位(FIPS 1862标准规定)
-C:提供一个新注释
-R hostname:从known_hosta(第一次连接时就会在家目录.ssh目录下生产该密钥文件)文件中删除所有属于hostname的密钥
3,创建cloud init 虚拟机初始化文件
代码语言:javascript复制#cloud-config
hostname: kvm_host01
fqdn: kvm_host01.example.com
manage_etc_hosts: true
users:
- name: centos
sudo: ALL=(ALL) NOPASSWD:ALL
groups: where
home: /home/centos
shell: /bin/bash
lock_passwd: false
ssh_authorized_keys:
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDZXq7aQtDGwf3UDhQJxxuBJlCQzVxqSBlALTj1v87dRE8shuCOh3T5N42nSH71p xSrCUp8ZZNVnrosS9P9wQl5unwKwJ7R1PAZJl19doNawvWh5NoYPRRKrtap9QrOyfPWGJ2pqYhoBZ5cnX/IQ1QtcX4 LdZ4kZgDkjo5VZNkuS16sRskvf8c5hsjZKyxHujfgeigxosR4ibGL5BpOHs1vgIJBzO1c64pKaZuHv5wZKFQNrc1E08zWRv wESsdd4S9Svoc2WxWNTlwE2DuYtAC WabggUkGmorfSWf8U2yn8xrwqegmCiJWE9i aX1rIFOeQVsnbVhcmx4Y9TMpj root@kvm-node1
- name: root
ssh_authorized_keys:
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDZXq7aQtDGwf3UDhQJxxuBJlCQzVxqSBlALTj1v87dRE8shuCOh3T5N42nSH71p xSrCUp8ZZNVnrosS9P9wQl5unwKwJ7R1PAZJl19doNawvWh5NoYPRRKrtap9QrOyfPWGJ2pqYhoBZ5cnX/IQ1QtcX4 LdZ4kZgDkjo5VZNkuS16sRskvf8c5hsjZKyxHujfgeigxosR4ibGL5BpOHs1vgIJBzO1c64pKaZuHv5wZKFQNrc1E08zWRv wESsdd4S9Svoc2WxWNTlwE2DuYtAC WabggUkGmorfSWf8U2yn8xrwqegmCiJWE9i aX1rIFOeQVsnbVhcmx4Y9TMpj root@kvm-node1
# only cert auth via ssh (console access can still login)
ssh_pwauth: true
disable_root: false
chpasswd:
list: |
root:q1w2E#R$
centos:newpassword
expire: False
package_update: true
packages:
- vim-enhanced
- net-tools
- tcpdump
- sysstat
timezone: Asia/Shanghai
# manually set BOOTPROTO for static IP
# older cloud-config binary has bug?
runcmd:
- [ sh, -c, 'sed -i s/BOOTPROTO=static/BOOTPROTO=dhcp/ /etc/sysconfig/network-scripts/ifcfg-eth0' ]
- [ sh, -c, 'ifdown eth0 && sleep 1 && ifup eth0 && sleep 1 && ip a' ]
# written to /var/log/cloud-init.log, /var/log/messages
final_message: "The system is finally up, after $UPTIME seconds"
4,封装cloud_init数据镜像
(1)制作镜像需要cloud-localsd命令,默认没有安装
代码语言:javascript复制yum install cloud-utils -y
(2)制作cloud_init 镜像
代码语言:javascript复制#生成初始化镜像
cloud-localds -m local cloudinit.img cloud_init.cfg
#查看镜像信息
[root@kvm-node1 system]# qemu-img info /mnt/cloudinit.img
image: /mnt/cloudinit.img
file format: raw
virtual size: 366K (374784 bytes)
disk size: 36K
-m指定的cloud-init的工作模式,local的意思是不需要依赖网络,我们没有使用metadata service,所以不需要网络。
5,创建虚拟机
代码语言:javascript复制# create guest VM
virt-install --name guest-rhel7
--virt-type kvm --memory 2048 --vcpus 2
--boot hd,menu=on
--disk path=cloudinit.img ,device=cdrom
--disk path=/kvm/img/node01.img,format=qcow2,bus=virtio
--os-type Linux --os-variant rhel7
--network bridge=br0,model=virtio
--graphics vnc,listen=0.0.0.0 --noautoconsole
6,访问虚拟机
代码语言:javascript复制ssh centos@192.168.100.108 -i /mnt/id_rsa
7,查看cloud-init日志
代码语言:javascript复制# cloud logs
sudo less /var/log/cloud-init.log
# cloud logs output
sudo grep cloud-init /var/log/messages
8,禁用cloud-init初始化系统
主机名、网络配置、软件包初始化完成后,在虚拟机中禁用 cloud-init服务
代码语言:javascript复制# flag that signals that cloud-init should not run
sudo touch /etc/cloud/cloud-init.disabled
# optional, remove cloud-init completely
sudo yum remove cloud-init
# shutdown VM so CDROM seed can be ejected
sudo shutdown -h now
9,虚拟机弹出cloud-init 磁盘
虚拟机重新打开电源时,将不再调用 cloud-init
代码语言:javascript复制# get name of target path
targetDrive=$(virsh domblklist guest-rhel7 | grep cloudinit.img | awk {' print $1 '})
# force ejection of CD
virsh change-media guest-rhel7 --path $targetDrive --eject --force