csmart.virt_infra
Ansible 角色:虚拟基础设施
该角色旨在定义和管理一个或多个 KVM 主机上的网络和客户机。Ansible 的 --limit
选项允许您单独或作为一个组进行管理。
它主要用于开发工作,其中 KVM 主机是您的本地机器,您具有 sudo
权限,并通过 libvirtd
与 qemu:///system
进行交互,但它也可以在远程主机上工作。
支持将客户机状态设置为 运行中_、_关闭_、_销毁 或 _未定义_(用于删除和清理)。
您可以为客户机设置所需的内存、CPU、磁盘和网卡,无论是通过主机组还是单独设置。支持多种类型的磁盘,包括 scsi_、_sata_、_virtio 甚至 _nvme_(在支持的发行版上)。
您可以在 KVM 主机上创建私有 NAT libvirt 网络,并将虚拟机放置在其中的任意数量上。客户机可以使用这些 libvirt 网络或现有的 Linux 桥接设备(例如 br0
)以及 KVM 主机上的 Open vSwitch (OVS) 桥接(这不会在主机上创建桥接,但会检查桥接接口是否存在)。如果需要,您可以为每个接口指定网卡型号及其 MAC 地址,但默认情况下会基于主机名生成一个幂等的地址。
此外,您还可以在 KVM 主机上创建路由 libvirt 网络,并将虚拟机放置在其中的任意数量上。在这种情况下,将创建一个新桥接,并按照您指定的名称(例如 br1
)连接到现有接口(例如 eth0
)。如果需要,您可以为每个接口指定 MAC 地址。
该角色支持多种发行版,并使用它们的 qcow2 云镜像 以方便使用(尽管您可以使用自己的镜像)。我测试了 CentOS Stream、Debian、Fedora、openSUSE、RHEL 和 Ubuntu。
对于 RHEL,当准备磁盘时,需要设置 virt_infra_sm_creds
变量(可能来自一个保险库)以临时将机器注册到 Red Hat 门户。其格式遵循 virt-builder 的格式,例如:
- virt_infra_sm_creds: MYUSER:password:MYPASSWORD
用于客户机的 qcow2 基础镜像在库存中作为变量指定,并应存在于 libvirt 镜像目录下(默认是 /var/lib/libvirt/images/
)。也就是说,角色不会自动为您下载镜像。
客户机 qcow2 启动镜像是从这些基础镜像创建的。默认情况下,使用云镜像作为后备文件,但也支持克隆。您可以根据需要创建其他磁盘。如果希望,可以选择在虚拟机未定义时保留任何磁盘镜像,而不是删除它。cloud-init ISO 自动创建并附加到客户机,以在启动时进行配置。
默认情况下,时区将设置为与 KVM 主机匹配,ansible 用户将用作客户机用户,并使用您在 KVM 主机上的公有 SSH 密钥(您可以重写该设置)。主机条目会添加到 KVM 主机的 /etc/hosts
文件,并且它还会修改 ansible 用户的 SSH 配置并将指纹添加到 known_hosts
,以便您可以直接 SSH 登录(这作为部署的一部分进行测试)。如果您真的想要,可以设置根密码。
通过这些设置,您可以定义和管理 OpenStack/Swift/Ceph 集群,支持不同的规模、多种网络、磁盘甚至不同的发行版!
需求
所需的主要是一个能够运行 KVM 的 Linux 主机、一些客户镜像和基本库存。Ansible 将自动处理其他部分(在支持的发行版上)。
需要一个工作中的 x86_64 KVM 主机,运行 Ansible 的用户可以通过 sudo
与 libvirtd
通信。
它要求 CPU 支持 KVM 的硬件,以便我们能够创建加速的客户机并通过 CPU 传递(支持嵌套虚拟化)。
您可能需要 Ansible 和 Jinja >= 2.8,因为这些工具会比较内容。
我已在 CentOS Stream 8、Fedora 3x、Debian 10、Ubuntu Bionic/Eoan 和 openSUSE 15 主机上进行了测试,但其他 Linux 机器可能也能正常工作。
在 KVM 主机上至少需要一对 SSH 密钥(如果缺失,Ansible 会生成一对)。用于客户机的 SSH 密钥不应要求 SSH 密码,如果在远程 KVM 主机上。如果在本地,则确保您已将其添加到 SSH 代理。
KVM 主机上还需要一些用户空间工具(Ansible 会在支持的主机上安装这些工具):
- qemu-img
- osinfo-query
- virsh
- virt-customize
- virt-sysprep
下载您要使用的客户机镜像(这是我下载的)并将其放置在 libvirt 镜像路径下(通常是 /var/lib/libvirt/images/
)。它将检查您指定的镜像是否存在,并在未找到时报告错误。
KVM 主机
以下是配置 KVM 主机的一些说明,以防您需要:
注意: 该角色将为您完成所有这些设置,包括在支持的发行版上安装 KVM、libvirtd 和其他所需的软件包,并确保 libvirtd 正在运行。
还有一个变量 virt_infra_host_pkgs_custom
,该变量接受要在主机上安装的软件包列表,以便在需要时让角色为您安装一些额外的软件包。
请注意,该变量必须是一个列表,并且主机必须能够安装这些包,也就是说,包名称必须正确,对于运行 RHEL 的主机,必须已注册。
Fedora
# 如果没有 SSH 密钥,请创建一个(如果是远程 KVM 主机,请不要设置密码)
ssh-keygen
# libvirtd
sudo dnf install -y @virtualization
sudo systemctl enable --now libvirtd
# Ansible
sudo dnf install -y ansible
# 其他依赖(由 playbook 安装)
sudo dnf install -y \
git \
genisoimage \
libguestfs-tools-c \
libosinfo \
python3-libvirt \
python3-lxml \
qemu-img \
virt-install
CentOS 7
CentOS 7 直到我们得到了 libselinux-python3
包(将在 7.8 版本中提供)才能工作...
- https://bugzilla.redhat.com/show_bug.cgi?id=1719978
- https://bugzilla.redhat.com/show_bug.cgi?id=1756015
以下是(希望是)可用的其他步骤。
# 如果没有 SSH 密钥,请创建一个
ssh-keygen
# libvirtd
sudo yum groupinstall -y "Virtualization Host"
sudo systemctl enable --now libvirtd
# Ansible 和其他依赖
sudo yum install -y epel-release
sudo yum install -y python36
pip3 install --user ansible
sudo yum install -y \
git \
genisoimage \
libguestfs-tools-c \
libosinfo \
python36-libvirt \
python36-lxml \
libselinux-python3 \
qemu-img \
virt-install
CentOS Stream 8
# 如果没有 SSH 密钥,请创建一个
ssh-keygen
# libvirtd
sudo dnf groupinstall -y "Virtualization Host"
sudo systemctl enable --now libvirtd
# Ansible
sudo dnf install -y epel-release
sudo dnf install -y ansible
# 其他依赖(由 playbook 安装)
sudo dnf install -y \
git \
genisoimage \
libguestfs-tools-c \
libosinfo \
python3 \
python3-libvirt \
python3-lxml \
qemu-img \
virt-install
Debian
# 如果没有 SSH 密钥,请创建一个
ssh-keygen
# libvirtd
sudo apt update
sudo apt install -y --no-install-recommends qemu-kvm libvirt-clients libvirt-daemon-system
sudo systemctl enable --now libvirtd
# Ansible
sudo apt install -y gnupg2
echo 'deb http://ppa.launchpad.net/ansible/ansible/ubuntu trusty main' | sudo tee -a /etc/apt/sources.list
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 93C4A3FD7BB9C367
sudo apt update
sudo apt install -y ansible
# 其他依赖(由 playbook 安装)
sudo apt install -y --no-install-recommends \
cloud-image-utils \
dnsmasq \
git \
genisoimage \
libguestfs-tools \
libosinfo-bin \
python3-libvirt \
python3-lxml \
qemu-utils \
virtinst
Ubuntu
# 如果没有 SSH 密钥,请创建一个
ssh-keygen
# libvirtd
sudo apt update
sudo apt install -y --no-install-recommends libvirt-clients libvirt-daemon-system qemu-kvm
sudo systemctl enable --now libvirtd
# Ansible
sudo apt install -y software-properties-common
sudo apt-add-repository --yes --update ppa:ansible/ansible
sudo apt install -y ansible
# 其他依赖(由 playbook 安装)
sudo apt install -y --no-install-recommends \
dnsmasq \
git \
genisoimage \
libguestfs-tools \
libosinfo-bin \
python3-libvirt \
python3-lxml \
qemu-utils \
virtinst
openSUSE
如果您运行的是 JeOS,我们需要将内核更改为 kernel-default
,因为 JeOS 附带的 kernel-default-base
缺少 KVM 模块。
# 如果没有 SSH 密钥,请创建一个
ssh-keygen
# 安装合适的内核
sudo zypper install kernel-default
sudo reboot
重启后继续。
# libvirtd
sudo zypper install -yt pattern kvm_server kvm_tools
sudo systemctl enable --now libvirtd
# Ansible
sudo zypper install -y ansible
# 其他依赖(由 playbook 安装)
sudo zypper install -y \
git \
guestfs-tools \
libosinfo \
mkisofs \
python3-libvirt-python \
python3-lxml \
qemu-tools \
virt-install
使用路由网络
您可以通过指定转发 类型:路由 来路由流量到新创建的桥接。此代码支持自动创建一个名为 bridge_dev
的新桥接,该桥接将连接到主机中由参数 host_dev
指定的现有接口。
以下示例展示了如何创建一个支持 IPv4 和 IPv6 的桥接:
kvmhost:
hosts:
localhost:
ansible_connection: local
ansible_python_interpreter: /usr/bin/python3
virt_infra_host_libvirt_url: qemu:///system
vars:
virt_infra_host_networks:
present:
- name: example
domain: f901.example.com
type: route
host_dev: eth0
bridge_dev: virbr1
bridge_stp: on
bridge_delay: 0
mac: 52:54:00:f9:01:00
ip_address: 10.249.1.1
ip_netmask: 255.255.255.0
dhcp_start: 10.249.1.11
dhcp_end: 10.249.1.254
ip6_address: 2001:0db8::f901:1
ip6_prefix: 64
dhcp6_start: 2001:0db8::f901:0000
dhcp6_end: 2001:0db8::f901:00ff
注意事项:
上述 IPv6 块 2001:0db8/32 仅为文档目的提供。您需要用您的 IPv6 提供商提供的 /48 块(一般)或通过如 Hurricane Electric 的隧道代理服务 的 IPv6-over-IPv4 隧道解决方案进行替代。
强烈建议您使用
ip6_prefix: 64
,因为这是 libvirt 文档中的推荐设置。
使用 NetworkManager 配置桥接
此代码支持将虚拟机连接到 Linux 和 Open vSwitch 桥接,但它们必须已经存在于 KVM 主机上。
以下是如何将现有以太网设备转换为桥接。进行此操作时,如果您远程连接并且只有一个连接,请小心!请确保有其他方式进行登录(例如控制台),或添加其他接口。
首先,导出要转换的设备,以便之后容易引用(例如 eth1
)。
export NET_DEV="eth1"
现在列出当前 NetworkManager 连接,以便我们知道稍后需要禁用什么。
sudo nmcli con |egrep -w "${NET_DEV}"
这可能是 System eth1
或 Wired connection 1
,我们也导出来方便后续引用。
export NM_NAME="Wired connection 1"
Linux 桥接
以下是使用 NetworkManager 创建持久 Linux 桥接的示例。它将把设备(如 eth1
,视需要而定)转换为桥接。
记住从上面获得的设备的现有 NetworkManager 连接名称,您将在下面使用它(如 Wired connection 1
)。
export NET_DEV=eth1
export NM_NAME="Wired connection 1"
sudo nmcli con add ifname br0 type bridge con-name br0
sudo nmcli con add type bridge-slave ifname "${NET_DEV}" master br0
现在您有了桥接设备!请注意,桥接将有不同于基础设备的 MAC 地址,因此,如果您期望它获得特定地址,需要更新 DHCP 静态租约。
sudo ip link show dev br0
禁用设备的当前 NetworkManager 配置,以便不与桥接冲突(暂时不要删除,您可能在使用 SSH 时失去连接)。
sudo nmcli con modify id "${NM_NAME}" ipv4.method disabled ipv6.method disabled
现在,您可以选择重启,或以一条命令停止当前接口并启动桥接。请记住,桥接将有一个新的 MAC 地址,因此会获得新的 IP,除非您更新了 DHCP 静态租约!
sudo nmcli con down "${NM_NAME}" ; sudo nmcli con up br0
如上所述,默认情况下,Linux 桥接将通过 DHCP 获取地址。如果您不希望它连接到网络(您可能有其他专用接口),则禁用它的 DHCP。
sudo nmcli con modify id br0 ipv4.method disabled ipv6.method disabled
在库存中使用 Linux 桥接
在 kvmhost
的库存中无需进行任何操作。
对于任何您希望连接到桥接的客户机,只需在它们的库存中指定它即可。使用 br0
作为 virt_infra_networks
下网络的 name
,类型为 bridge
。
virt_infra_networks:
- name: br0
type: bridge
Open vSwitch (OVS) 桥接
以下是使用 NetworkManager 创建持久 OVS 桥接的示例。它将把设备(如 eth1
,视需要而定)转换为 ovs-bridge。
您需要安装 openvswitch 及其 OVS NetworkManager 插件(根据您的发行版进行替换)。
sudo dnf install -y NetworkManager-ovs openvswitch
sudo systemctl enable --now openvswitch
sudo systemctl restart NetworkManager
现在我们可以创建 OVS 桥接(假设您的设备是 eth1
,现有的 NetworkManager 配置为 Wired connection 1
,视需要替换)。
export NET_DEV=eth1
export NM_NAME="Wired connection 1"
sudo nmcli con add type ovs-bridge conn.interface ovs-bridge con-name ovs-bridge
sudo nmcli con add type ovs-port conn.interface port-ovs-bridge master ovs-bridge
sudo nmcli con add type ovs-interface slave-type ovs-port conn.interface ovs-bridge master port-ovs-bridge
sudo nmcli con add type ovs-port conn.interface ovs-port-eth master ovs-bridge con-name ovs-port-eth
sudo nmcli con add type ethernet conn.interface "${NET_DEV}" master ovs-port-eth con-name ovs-int-eth
禁用设备的当前 NetworkManager 配置,以便不与桥接冲突(暂时不要删除,您可能在使用 SSH 时失去连接)。
sudo nmcli con modify id "${NM_NAME}" ipv4.method disabled ipv6.method disabled
现在,您可以选择重启,或以一条命令停止当前接口并启动桥接。
sudo nmcli con down "${NM_NAME}" ; sudo nmcli con up ovs-slave-ovs-bridge
默认情况下,OVS 桥接将通过 DHCP 获取地址。如果您希望它不连接到网络(您可能有其他专用接口),则禁用它的 DHCP。
sudo nmcli con modify id ovs-slave-ovs-bridge ipv4.method disabled ipv6.method disabled
使用 OVS 工具显示交换机配置和桥接。
sudo ovs-vsctl show
在库存中使用 ovs-bridge
现在您可以在 kvmhost
库存的 virt_infra_host_networks
项中将 ovs-bridge
用作 an ovs
桥接的 device
,它将为您创建 OVS libvirt 网络。您可以设置多个 VLAN,并将一个设置为默认原生 VLAN(如果需要)。
VLAN 范围通过定义为列表来支持。
virt_infra_host_networks:
present:
- name: ovs-bridge
bridge_dev: ovs-bridge
type: ovs
portgroup:
# 这是一个具有多个 VLAN 的端口组
# 它是原生 VLAN 1,并且允许带有 VLAN 99 的流量
- name: ovs-trunk
trunk: true
native_vlan: 1
vlan:
- 1
- [20,29]
- 99
# 这是仅适用于原生 VLAN 1 的端口组
- name: default
native_vlan: 1
vlan:
- 1
# 这是仅适用于原生 VLAN 99 的端口组
- name: other
native_vlan: 99
vlan:
- 99
然后,您可以指定您的虚拟机在特定的端口组中,libvirt 会自动为您和您的虚拟机设置端口。
virt_infra_networks:
- name: ovs-bridge
portgroup: default
type: ovs
一旦您的虚拟机正在运行,您可以使用 sudo ovs-vsctl show
查看它们的 OVS 端口。
客户机云镜像
这是设计用于使用各种发行版提供的标准云镜像的(OpenStack 提供一些 建议)。
确保您指定的客户机镜像已经存在于您的 libvirt 存储目录下(默认在 _/var/lib/libvirt/images/_)。
我成功测试了以下客户机:
- CentOS 7
- CentOS Stream 8
- Fedora 33
- Fedora 34
- Debian 10
- Ubuntu 18.04 LTS
- Ubuntu 20.04 LTS
- openSUSE 15.3 JeOS
这样我们就可以配置客户机并获取其 IP, cloud-init
和 qemu-guest-agent
将自动安装到您的客户机镜像中,以防万一。
这可以通过使用 virt_infra_guest_deps
变量进行更改或重写,该变量为一个列表。
还会在客户机镜像上运行 Sysprep,以确保其没有旧的 MAC 地址等。
角色变量
角色默认值在 defaults/main.yml 文件中设置。
这些可以根据需要在主机或主机组级别重写。然而,角色设计的目标是尽可能开箱即用(只要您有默认的 CentOS Stream 8 镜像)。
---
# virt-infra Ansible 角色的默认设置
# 被注释掉的值是可选的
## 客户机相关
# 有效的客户机状态有:运行中,关机,销毁或未定义
virt_infra_state: "running"
# 客户机在启动时不会自动启动
virt_infra_autostart: "no"
# 客户机用户,默认设置为与 KVM 主机用户相同的用户
virt_infra_user: "{{ hostvars[kvmhost].ansible_env.USER }}"
# 默认用户的密码(如果需要安全密码,请考虑使用保险库)
# 默认无根密码
virt_infra_password: "password"
#virt_infra_root_password:
# 客户机的 VM 规格
# 请参阅 virt-install man页面以获取支持的值
virt_infra_ram: "1024"
virt_infra_ram_max: "{{ virt_infra_ram }}"
virt_infra_cpus: "1"
virt_infra_cpus_max: "{{ virt_infra_cpus }}"
virt_infra_cpu_model: "host-passthrough"
virt_infra_machine_type: "q35"
# SSH 密钥是列表,您可以添加多个
# 如果未指定,我们默认使用 KVM 主机上的所有公钥
virt_infra_ssh_keys: []
# 如果未指定或在 KVM 主机上找不到 SSH 密钥,则使用此密钥生成一对
virt_infra_ssh_key_size: "2048"
virt_infra_ssh_key_type: "rsa"
# 是否启用 SSH 密码验证
virt_infra_ssh_pwauth: true
# 是否使用 cloud-init 在客户机上配置网络
virt_infra_network_config: false
# 网络是一个列表,您可以添加多个
# "type" 是可选的,支持 "nat" 和 "bridge"
# - "nat" 是默认类型,应该是 libvirt 网络
# - "bridge" 类型要求桥接接口作为名称(例如 name: "br0"),这个在 KVM 主机上也必须已设置
# "model" 也是可选的
virt_infra_networks:
- name: "default"
type: "nat"
model: "virtio"
# 磁盘,支持各种 libvirt 选项
# 通常我们不设置它们,而是留给 Hypervisor 的默认值
# 请参阅 virt-install man 页面以获得支持的值
virt_infra_disk_size: "20"
virt_infra_disk_bus: "scsi"
virt_infra_disk_io: "threads"
virt_infra_disk_cache: "writeback"
# 磁盘是一个列表,您可以添加多个
# 如果覆盖这个,您仍须在列表中包含 'boot' 设备
# 仅需 'name' 是必需的,其他都是可选的(默认大小为 20GB)
# 所有客户机至少需要一个引导驱动(这是默认值)
virt_infra_disks:
- name: "boot"
size: "{{ virt_infra_disk_size }}"
bus: "{{ virt_infra_disk_bus }}"
# io: "{{ virt_infra_disk_io }}"
# cache: "{{ virt_infra_disk_cache }}"
# 默认发行版是 CentOS Stream 8,在客户机或组中覆盖
virt_infra_distro_image: "CentOS-Stream-GenericCloud-8-20210603.0.x86_64.qcow2"
# 使用命令 "osinfo-query os" 确定 KVM 主机上支持的变体
# 这实际上不会对客户机产生太大影响,可能会略有不同的总线
# 如果您想,您可能只需设置为 "centos7.0"
#virt_infra_variant: "centos7.0"
# 这些发行版变量在这里仅供参考和方便
virt_infra_distro: "centos-stream"
virt_infra_distro_release: "8"
virt_infra_distro_image_url: "https://cloud.centos.org/centos/8-stream/x86_64/images/CentOS-Stream-GenericCloud-8-20210603.0.x86_64.qcow2"
virt_infra_distro_image_checksum_url: "https://cloud.centos.org/centos/8-stream/x86_64/images/CHECKSUM"
## KVM 主机相关
# 连接到系统 libvirt 实例
virt_infra_host_libvirt_url: "qemu:///system"
# 存放磁盘镜像的路径
virt_infra_host_image_path: "/var/lib/libvirt/images"
# 默认情况下禁用 qemu 安全驱动
# 这在特定于发行版的变量中被重写
virt_infra_security_driver: "none"
# 虚拟 BMC 默认情况下禁用
virt_infra_vbmc: false
# 默认情况下,我们使用 pip 安装,但如果您希望手动安装,可以将其设置为 false
virt_infra_vbmc_pip: true
# 默认 vbmc 服务,如果在您的发行版上不同,请覆盖此项
virt_infra_vbmc_service: vbmcd
# KVM 主机上的网络是一个列表,您可以添加多个
# 您可以在 kvmhost 上创建和删除 NAT 网络(创建桥接不支持)
# 'default' 网络是随 libvirt 一起提供的标准网络
# 默认情况下,我们不删除任何网络(空的 absent 列表)
virt_infra_host_networks:
absent: []
present:
- name: "default"
type: "nat"
ip_address: "192.168.122.1"
subnet: "255.255.255.0"
dhcp_start: "192.168.122.2"
dhcp_end: "192.168.122.254"
# 创建 ISO 镜像的命令
virt_infra_mkiso_cmd: genisoimage
# 在 KVM 主机上检查的一系列二进制文件
virt_infra_host_deps:
- qemu-img
- osinfo-query
- virsh
- virt-customize
- virt-sysprep
# 用于客户机磁盘的逗号分隔的软件包列表
virt_infra_guest_deps:
- cloud-init
- qemu-guest-agent
依赖
无
示例库存
独立的 virt-infra 仓库 提供了示例库存文件和调用角色的站点 playbook,这可能会很有帮助。
最好的做法是将库存分成多个文件,以便于管理,放在一个 inventory 目录下。建议一个通用的 _kvmhost.yml_,然后为每组客户机创建独立的库存文件,例如 _openstack.yml_。在运行 ansible 时,您将整个目录包含为库存源。
与该角色一起使用的库存必须包括名为 kvmhost 的主机组和其他客户机的主机组。
可定制的设置可以为每个主机或主机组提供。
要创建一个新的客户机组以进行管理,请在库存目录下创建一个新的 yml 文件。例如,如果您想要一组用于 OpenStack 的客户机,您可以创建一个 openstack.yml 文件并按需填充它。
要管理特定主机或主机组,只需使用 Ansible 的 --limit
选项指定主机或主机组(还必须包括 kvmhost 组)。这样,您可以使用一个库存管理很多不同的客户机并分别管理它们。
KVM 主机是创建 libvirt 网络的地方,因此在该主机组下指定为变量。
以下是一个名为 kvmhost.yml 的 YAML 格式库存示例。它将 kvmhost 指定为 localhost,并使用本地连接。请注意,创建了两个网络(default 和 _example_),并删除了一个网络(_other_)。
---
## 基于 YAML 的库存,见:
## https://docs.ansible.com/ansible/latest/plugins/inventory/yaml.html
#
kvmhost:
hosts:
# 在这里放置您的 KVM 主机连接和设置
localhost:
ansible_connection: local
ansible_python_interpreter: /usr/bin/python3
vars:
# 网络是一个列表,您可以添加多个
# 您可以在 kvmhost 上创建和删除 NAT 网络(创建桥接不支持)
# 'default' 网络是随 libvirt 一起提供的标准网络
# 默认情况下,我们不删除任何网络(空的 absent 列表)
virt_infra_host_networks:
absent:
- name: "other"
present:
- name: "default"
ip_address: "192.168.112.1"
subnet: "255.255.255.0"
dhcp_start: "192.168.112.2"
dhcp_end: "192.168.112.254"
- name: "example"
ip_address: "192.168.113.1"
subnet: "255.255.255.0"
dhcp_start: "192.168.113.2"
dhcp_end: "192.168.113.99"
这是一个名为 simple.yml 的客户机库存示例,定义了 CentOS Stream 8 客户机在一个名为 simple 的组中,使用角色默认值。
---
## 基于 YAML 的库存,见:
## https://docs.ansible.com/ansible/latest/plugins/inventory/yaml.html
#
simple:
hosts:
centos-simple-[0:2]:
ansible_python_interpreter: /usr/libexec/platform-python
如果您希望一组虚拟机都相同,请在主机组级别设置变量。如果需要,您仍可以使用特定主机的个别变量重写主机组变量。
这是一个设置各种主机组和个别主机变量的示例。
---
## 基于 YAML 的库存,见:
## https://docs.ansible.com/ansible/latest/plugins/inventory/yaml.html
#
example:
hosts:
centos-7-example:
virt_infra_state: shutdown
virt_infra_timezone: "Australia/Melbourne"
ansible_python_interpreter: /usr/bin/python
virt_infra_networks:
- name: "br0"
type: bridge
- name: "extra_network"
type: nat
model: e1000
- name: ovs-bridge
portgroup: ovs-portgroup
type: ovs
virt_infra_disks:
- name: "boot"
- name: "nvme"
size: "100"
bus: "nvme"
centos-8-example:
virt_infra_timezone: "Australia/Adelaide"
ansible_python_interpreter: /usr/libexec/platform-python
opensuse-15-example:
virt_infra_distro: opensuse
virt_infra_distro_image: openSUSE-Leap-15.1-JeOS.x86_64-15.1.0-OpenStack-Cloud-Current.qcow2
virt_infra_variant: opensuse15.1
virt_infra_disks:
- name: "boot"
bus: "scsi"
ubuntu-eoan-example:
virt_infra_cpu: 2
virt_infra_distro: ubuntu
virt_infra_distro_image: eoan-server-cloudimg-amd64.img
virt_infra_variant: ubuntu18.04
vars:
virt_infra_ram: 1024
virt_infra_disks:
- name: "boot"
- name: "data"
bus: "sata"
virt_infra_networks:
- name: "example"
type: nat
多个 KVM 主机
您还可以指定多个 KVM 主机。
---
kvmhost:
hosts:
kvmhost1:
kvmhost2:
kvmhost3:
vars:
ansible_python_interpreter: /usr/bin/python3
virt_infra_host_networks:
absent: []
present:
- name: "default"
ip_address: "192.168.112.1"
subnet: "255.255.255.0"
dhcp_start: "192.168.112.2"
dhcp_end: "192.168.112.254"
要让虚拟机落到指定的 KVM 主机上,您必须添加变量 kvmhost
,其值与 kvmhost
组中的某个 KVM 主机匹配。
例如,您可以在三个 KVM 主机上跨六个 CentOS Stream 8 客户机如下设置:
---
simple:
hosts:
simple-centos-[1:2]:
kvmhost: kvmhost1
simple-centos-[3:4]:
kvmhost: kvmhost2
simple-centos-[5:6]:
kvmhost: kvmhost3
vars:
ansible_python_interpreter: /usr/libexec/platform-python
virt_infra_distro_image: "CentOS-Stream-GenericCloud-8-20210603.0.x86_64.qcow2"
如果没有为虚拟机指定 kvmhost,它将默认落到 kvmhost
组中的第一个 KVM 主机(即 kvmhost[0]),这与角色的原始行为保持一致。
验证检查已更新,以确保所有的 KVM 主机都是有效的,并且为虚拟机指定的任何 KVM 主机都在 kvmhost
组中。
为了将虚拟机分组在某些 KVM 主机上,建议创建子组并在子组级别指定 kvmhost。
例如,再次针对 CentOS Stream 8 客户机:
---
simple:
hosts:
simple-centos-[1:6]:
vars:
ansible_python_interpreter: /usr/libexec/platform-python
virt_infra_distro_image: "CentOS-Stream-GenericCloud-8-20210603.0.x86_64.qcow2"
children:
simple_kvmhost1:
hosts:
simple-centos-[1:2]:
vars:
kvmhost: kvmhost1
simple_kvmhost2:
hosts:
simple-centos-[3:4]:
vars:
kvmhost: kvmhost2
simple_kvmhost3:
hosts:
simple-centos-[5:6]:
vars:
kvmhost: kvmhost3
示例 Playbook
我尽量保持 Ansible 简单,逻辑步骤清晰,而不是复杂的。在此基础上,playbook 还是比较具体的。
有些任务只能在 KVM 主机上运行,其他则需要按照特定顺序进行。
以下代码将通过在 KVM 主机和客户机配置中运行一系列验证检查,以捕获任何问题。
以下是一个名为 virt-infra.yml 的示例 playbook,调用了该角色。
---
- hosts: all
gather_facts: no
roles:
- ansible-role-virt-infra
下载云镜像
在运行 playbook 之前,下载 CentOS Stream 8 云镜像。
curl -O https://cloud.centos.org/centos/8/x86_64/images/CentOS-Stream-GenericCloud-8-20210603.0.x86_64.qcow2
sudo mv -iv CentOS-Stream-GenericCloud-8-20210603.0.x86_64.qcow2 /var/lib/libvirt/images/
运行 playbook
现在使用上面的库存对 kvmhost 和 simple 组中的客户机运行 Ansible playbook(请注意,我们限制到 kvmhost 和 simple 主机组)。
ansible-playbook \
--ask-become-pass \
--inventory ./inventory.d \
--limit kvmhost,simple \
./virt-infra.yml
您还可以在命令行中重写多个客户机设置。
ansible-playbook \
--ask-become-pass \
--limit kvmhost,simple \
./virt-infra.yml \
-e virt_infra_root_password=password \
-e virt_infra_disk_size=100 \
-e virt_infra_ram=4096 \
-e virt_infra_ram_max=8192 \
-e virt_infra_cpus=8 \
-e virt_infra_cpus_max=16 \
-e '{ "virt_infra_networks": [{ "name": "br0", "type": "bridge" }] }' \
-e virt_infra_state=running
清理
要删除主机组中的客户机,您可以使用 --limit
指定它们(或特定主机),并传入 virt_infra_state=undefined 作为命令行额外参数。
这将覆盖客户机状态为未定义,如果存在,它们将被删除。
例如,可以删除 simple 主机组中的所有虚拟机。
ansible-playbook \
--ask-become-pass \
--inventory simple.yml \
--limit kvmhost,simple \
--extra-vars virt_infra_state=undefined \
./virt-infra.yml
如果您只想关闭它们,则可以尝试使用 _virt_infra_state=shutdown_。
例如,要关闭仅 simple-centos-2 主机。
ansible-playbook \
--ask-become-pass \
--inventory simple.yml \
--limit kvmhost,simple-centos-2 \
--extra-vars virt_infra_state=shutdown \
./virt-infra.yml
后期设置配置
一旦您设置了基础设施,可以使用相同的库存运行另一个 playbook,对这些机器执行您想要的操作...
---
- hosts: all,!kvmhost
tasks:
- name: 升级所有软件包
package:
name: '*'
state: latest
become: true
register: result_package_update
retries: 30
delay: 10
until: result_package_update is succeeded
- name: 安装软件包
package:
name:
- git
- tmux
- vim
state: present
become: true
register: result_package_install
retries: 30
delay: 10
until: result_package_install is succeeded
许可
GPLv3
作者信息
Chris Smart https://blog.christophersmart.com