KVM--cloud-init 初始化虚拟机(十三)

2022-11-19 09:21:47 浏览数 (2)

cloud-init

cloud-init是云平台为Linux操作系统的虚拟机做系统初始化配置的开源服务软件。阿里云、AWS、Azure和OpenStack等主流云平台均支持cloud-init。cloud-init系统启动阶段完成系统初始化配置。包括但不限于下面的定制化工作

  • 设置默认语言环境
  • 设置实例主机名
  • 添加 ssh keys到 .ssh/authorized_keys
  • 设置用户密码
  • 配置网络安装软件包

为了实现 instance 定制工作,cloud-init 分为 4 个阶段执行任务

  1. local
  2. init
  3. config
  4. 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
代码语言:javascript复制
[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

0 人点赞