教程:使用 Ansible 配置 Azure 资源的动态清单
重要
运行本文中的示例 playbook 需要 Ansible 2.8(或更高版本)。
Ansible 动态清单功能消除了维护静态清单文件的负担。
在本教程中,你将使用 Azure 的 dynamic-inventory 插件来填充 Ansible 清单。
在本文中,学习如何:
- 配置两个测试虚拟机。
- 将标记添加到 Azure 虚拟机
- 生成动态库存
- 使用 conditional 组和 keyed 组填充组成员身份
- 针对动态库存内的组运行 playbook
先决条件
- Azure 订阅:如果没有 Azure 订阅,请在开始之前创建一个免费帐户。
- Azure 服务主体:创建服务主体,记下以下值:appId、displayName、password 和 tenant。
安装 Ansible - 执行以下任一选项:
- 在 Linux 虚拟机上安装和配置 Ansible
- 配置 Azure Cloud Shell,另外,如果无法访问 Linux 虚拟机,请使用 Ansible 创建虚拟机。
创建 Azure VM
登录到 Azure 门户。
打开 Cloud Shell。
创建一个 Azure 资源组,用于保存本教程创建的虚拟机。
重要
在此步骤中创建的 Azure 资源组必须具有完全小写的名称。 否则,生成动态清单将会失败。
az group create --resource-group ansible-inventory-test-rg --location eastus
使用以下方法之一在 Azure 上创建两个 Linux 虚拟机:
Ansible playbook - 文章使用 Ansible 在 Azure 中创建基本的 Linux 虚拟机和使用 Ansible 在 Azure 中创建基本的 Windows 虚拟机说明了如何利用 Ansible playbook 创建虚拟机。
Azure CLI - 在 Cloud Shell 中发出以下每条命令,以创建两个虚拟机:
az vm create \ --resource-group ansible-inventory-test-rg \ --name win-vm \ --image MicrosoftWindowsServer:WindowsServer:2019-Datacenter:latest \ --admin-username azureuser \ --admin-password <password> az vm create \ --resource-group ansible-inventory-test-rg \ --name linux-vm \ --image Ubuntu2204 \ --admin-username azureuser \ --admin-password <password>
将
<password>
替换为你的密码。
添加应用程序角色标记
标记用于对 Azure 资源进行组织和分类。 通过为 Azure VM 分配应用程序角色,可在 Azure 动态库存中使用相应的标记作为组名。
若要更新 VM 标记,请运行以下命令:
az vm update \
--resource-group ansible-inventory-test-rg \
--name linux-vm \
--set tags.applicationRole='message-broker'
az vm update \
--resource-group ansible-inventory-test-rg \
--name win-vm \
--set tags.applicationRole='web-server'
请在定义标记策略中了解有关 Azure 标记策略的详细信息。
生成动态库存
Ansible 提供 Azure 动态清单插件。
以下步骤将引导你使用插件:
创建名为
myazure_rm.yml
的动态库存plugin: azure_rm include_vm_resource_groups: - ansible-inventory-test-rg auth_source: auto
要点:
- Ansible 使用库存文件的名称和扩展名来标识要使用哪个库存插件。 若要使用 Azure 动态库存插件,该文件必须以
azure_rm
结尾,且扩展名为yml
或yaml
。
- Ansible 使用库存文件的名称和扩展名来标识要使用哪个库存插件。 若要使用 Azure 动态库存插件,该文件必须以
运行以下命令,查询资源组中的 VM:
ansible-inventory -i myazure_rm.yml --graph
运行命令后,将出现类似于以下输出的结果:
@all: |--@ungrouped: | |--linux-vm_cdb4 | |--win-vm_3211
这两个 VM 都属于 ungrouped
组,该组是 Ansible 库存中 all
组的子组。
要点:
- 默认情况下,Azure 动态库存插件会返回全局唯一名称。 因此,VM 名称可能包含额外的字符。 可以通过向动态清单添加
plain_host_names: yes
来禁用该行为。
查找 Azure VM hostvars
运行以下命令,查看所有 hostvars
:
ansible-inventory -i myazure_rm.yml --list
{
"_meta": {
"hostvars": {
"linux-vm_cdb4": {
"ansible_host": "52.188.118.79",
"availability_zone": null,
"computer_name": "linux-vm",
"default_inventory_hostname": "linux-vm_cdb4",
"id": "/subscriptions/<subscriptionid>/resourceGroups/ansible-inventory-test-rg/providers/Microsoft.Compute/virtualMachines/linux-vm",
"image": {
"offer": "0001-com-ubuntu-server-jammy",
"publisher": "Canonical",
"sku": "22_04-lts-gen2",
"version": "latest"
},
...,
"tags": {
"applicationRole": "message-broker"
},
...
},
"win-vm_3211": {
"ansible_host": "52.188.112.110",
"availability_zone": null,
"computer_name": "win-vm",
"default_inventory_hostname": "win-vm_3211",
"id": "/subscriptions/<subscriptionid>/resourceGroups/ansible-inventory-test-rg/providers/Microsoft.Compute/virtualMachines/win-vm",
"image": {
"offer": "WindowsServer",
"publisher": "MicrosoftWindowsServer",
"sku": "2019-Datacenter",
"version": "latest"
},
...
"tags": {
"applicationRole": "web-server"
},
...
}
}
},
...
}
}
动态库存可通过从 Azure 中提取信息,为每个 Azure VM 填充 hostvars
。 然后,这些 hostvars
将确定 Ansible 库存中的 VM 组成员身份。
使用 conditional_groups 分配组成员身份
每个 conditional 组都由两部分组成。 组的名称和添加组成员的条件。
使用属性 image.offer
为 linux-vm 创建 conditional 组成员身份。
打开 myazure_rm.yml
动态库存并添加以下 conditional_group
:
plugin: azure_rm
include_vm_resource_groups:
- ansible-inventory-test-rg
auth_source: auto
conditional_groups:
linux: "'ubuntu' in image.offer"
windows: "'WindowsServer' in image.offer"
运行带有 --graph
选项的 ansible-inventory
:
ansible-inventory -i myazure_rm.yml --graph
@all:
|--@linux:
| |--linux-vm_cdb4
|--@ungrouped:
|--@windows:
| |--win-vm_3211
从输出中可以看到,VM 不再与 ungrouped
组关联。 相反,每个 VM 都被分配给动态清单创建的新组。
要点:
- 使用 conditional 组可以命名库存中的特定组,并使用
hostvars
来填充它们。
使用 keyed_groups 分配组成员身份
keyed 组分配组成员身份的方式与 conditional 组相同,但使用 keyed 组时,组名也会被动态填充。
将以下 keyed_group 添加到 myazure_rm.yml
动态库存:
plugin: azure_rm
include_vm_resource_groups:
- ansible-inventory-test-rg
auth_source: auto
conditional_groups:
linux: "'ubuntu' in image.offer"
windows: "'WindowsServer' in image.offer"
keyed_groups:
- key: tags.applicationRole
运行带有 --graph
选项的 ansible-inventory
:
ansible-inventory -i myazure_rm.yml --graph
@all:
|--@_message_broker:
| |--linux-vm_cdb4
|--@_web_server:
| |--win-vm_3211
|--@linux:
| |--linux-vm_cdb4
|--@ungrouped:
|--@windows:
| |--win-vm_3211
从输出中,可以看到另外两个组 _message_broker
和 _web_server
。 通过使用键控组,applicationRole
标记将填充组名称和组成员身份。
要点:
- 默认情况下,keyed 组包含分隔符。 若要删除分隔符,请在 key 属性下添加
separator: ""
。
用组名称模式运行 playbook
将动态库存创建的组用作目标子组。
使用以下内容创建名为
win_ping.yml
的 playbook:--- - hosts: windows gather_facts: false vars_prompt: - name: username prompt: "Enter local username" private: false - name: password prompt: "Enter password" vars: ansible_user: "{{ username }}" ansible_password: "{{ password }}" ansible_connection: winrm ansible_winrm_transport: ntlm ansible_winrm_server_cert_validation: ignore tasks: - name: run win_ping win_ping:
运行
win_ping.yml
playbook。ansible-playbook win_ping.yml -i myazure_rm.yml
出现提示时,请输入 Azure Windows VM 的
username
和password
。Enter local username: azureuser Enter password: PLAY [windows] ************************************************************************************************************************************** TASK [run win_ping] ********************************************************************************************************************************* ok: [win-vm_3211] PLAY RECAP ****************************************************************************************************************************************** win-vm_3211 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
重要
如果出现错误
winrm or requests is not installed: No module named 'winrm'
,请使用以下命令安装 Pywinrm:pip install "pywinrm>=0.3.0"
使用以下内容创建名为
ping.yml
的第二个 playbook:--- - hosts: all gather_facts: false vars_prompt: - name: username prompt: "Enter ssh user" - name: password prompt: "Enter password for ssh user" vars: ansible_user: "{{ username }}" ansible_password: "{{ password }}" ansible_ssh_common_args: '-o StrictHostKeyChecking=no' tasks: - name: run ping ping:
运行
ping.yml
playbook。ansible-playbook ping.yml -i myazure_rm.yml
出现提示时,请输入 Azure Linux VM 的
username
和password
。Enter ssh username: azureuser Enter password for ssh user: PLAY [linux] ******************************************************************************************************* TASK [run ping] **************************************************************************************************** ok: [linux-vm_cdb4] PLAY RECAP ********************************************************************************************************* linux-vm_cdb4 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
清理资源
运行 az group delete 以删除资源组。 将删除资源组内的所有资源。
az group delete --name <resource_group>
使用 az group show 验证资源组是否已删除。
az group show --name <resource_group>