教程:使用 Ansible 配置 Azure 资源的动态清单

重要

运行本文中的示例 playbook 需要 Ansible 2.8(或更高版本)。

Ansible 动态清单功能消除了维护静态清单文件的负担。

在本教程中,你将使用 Azure 的 dynamic-inventory 插件来填充 Ansible 清单。

在本文中,学习如何:

  • 配置两个测试虚拟机。
  • 将标记添加到 Azure 虚拟机
  • 生成动态库存
  • 使用 conditional 组和 keyed 组填充组成员身份
  • 针对动态库存内的组运行 playbook

先决条件

  • Azure 订阅:如果没有 Azure 订阅,请在开始之前创建一个免费帐户。
  • Azure 服务主体创建服务主体,记下以下值:appIddisplayNamepasswordtenant

创建 Azure VM

  1. 登录到 Azure 门户

  2. 打开 Cloud Shell

  3. 创建一个 Azure 资源组,用于保存本教程创建的虚拟机。

    重要

    在此步骤中创建的 Azure 资源组必须具有完全小写的名称。 否则,生成动态清单将会失败。

    az group create --resource-group ansible-inventory-test-rg --location eastus
    
  4. 使用以下方法之一在 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 动态清单插件

以下步骤将引导你使用插件:

  1. 创建名为 myazure_rm.yml 的动态库存

    plugin: azure_rm
    include_vm_resource_groups:
      - ansible-inventory-test-rg
    auth_source: auto
    

    要点:

    • Ansible 使用库存文件的名称和扩展名来标识要使用哪个库存插件。 若要使用 Azure 动态库存插件,该文件必须以 azure_rm 结尾,且扩展名为 ymlyaml
  2. 运行以下命令,查询资源组中的 VM:

    ansible-inventory -i myazure_rm.yml --graph
    
  3. 运行命令后,将出现类似于以下输出的结果:

    @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

将动态库存创建的组用作目标子组。

  1. 使用以下内容创建名为 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:
    
  2. 运行 win_ping.yml playbook。

    ansible-playbook win_ping.yml -i myazure_rm.yml
    

    出现提示时,请输入 Azure Windows VM 的 usernamepassword

    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"

  3. 使用以下内容创建名为 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:
    
  4. 运行 ping.yml playbook。

    ansible-playbook ping.yml -i myazure_rm.yml
    

    出现提示时,请输入 Azure Linux VM 的 usernamepassword

    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  
    

清理资源

  1. 运行 az group delete 以删除资源组。 将删除资源组内的所有资源。

    az group delete --name <resource_group>
    
  2. 使用 az group show 验证资源组是否已删除。

    az group show --name <resource_group>
    

后续步骤