1*********************************************** 2Build Your Inventory 3*********************************************** 4 5Running a playbook without an inventory requires several command-line flags. Also, running a playbook against a single device is not a huge efficiency gain over making the same change manually. The next step to harnessing the full power of Ansible is to use an inventory file to organize your managed nodes into groups with information like the ``ansible_network_os`` and the SSH user. A fully-featured inventory file can serve as the source of truth for your network. Using an inventory file, a single playbook can maintain hundreds of network devices with a single command. This page shows you how to build an inventory file, step by step. 6 7.. contents:: 8 :local: 9 10Basic inventory 11================================================== 12 13First, group your inventory logically. Best practice is to group servers and network devices by their What (application, stack or microservice), Where (datacenter or region), and When (development stage): 14 15- **What**: db, web, leaf, spine 16- **Where**: east, west, floor_19, building_A 17- **When**: dev, test, staging, prod 18 19Avoid spaces, hyphens, and preceding numbers (use ``floor_19``, not ``19th_floor``) in your group names. Group names are case sensitive. 20 21This tiny example data center illustrates a basic group structure. You can group groups using the syntax ``[metagroupname:children]`` and listing groups as members of the metagroup. Here, the group ``network`` includes all leafs and all spines; the group ``datacenter`` includes all network devices plus all webservers. 22 23.. code-block:: yaml 24 25 --- 26 27 leafs: 28 hosts: 29 leaf01: 30 ansible_host: 10.16.10.11 31 leaf02: 32 ansible_host: 10.16.10.12 33 34 spines: 35 hosts: 36 spine01: 37 ansible_host: 10.16.10.13 38 spine02: 39 ansible_host: 10.16.10.14 40 41 network: 42 children: 43 leafs: 44 spines: 45 46 webservers: 47 hosts: 48 webserver01: 49 ansible_host: 10.16.10.15 50 webserver02: 51 ansible_host: 10.16.10.16 52 53 datacenter: 54 children: 55 network: 56 webservers: 57 58 59 60You can also create this same inventory in INI format. 61 62.. code-block:: ini 63 64 [leafs] 65 leaf01 66 leaf02 67 68 [spines] 69 spine01 70 spine02 71 72 [network:children] 73 leafs 74 spines 75 76 [webservers] 77 webserver01 78 webserver02 79 80 [datacenter:children] 81 network 82 webservers 83 84 85Add variables to the inventory 86================================================================================ 87 88Next, you can set values for many of the variables you needed in your first Ansible command in the inventory, so you can skip them in the ``ansible-playbook`` command. In this example, the inventory includes each network device's IP, OS, and SSH user. If your network devices are only accessible by IP, you must add the IP to the inventory file. If you access your network devices using hostnames, the IP is not necessary. 89 90.. code-block:: yaml 91 92 --- 93 94 leafs: 95 hosts: 96 leaf01: 97 ansible_host: 10.16.10.11 98 ansible_network_os: vyos.vyos.vyos 99 ansible_user: my_vyos_user 100 leaf02: 101 ansible_host: 10.16.10.12 102 ansible_network_os: vyos.vyos.vyos 103 ansible_user: my_vyos_user 104 105 spines: 106 hosts: 107 spine01: 108 ansible_host: 10.16.10.13 109 ansible_network_os: vyos.vyos.vyos 110 ansible_user: my_vyos_user 111 spine02: 112 ansible_host: 10.16.10.14 113 ansible_network_os: vyos.vyos.vyos 114 ansible_user: my_vyos_user 115 116 network: 117 children: 118 leafs: 119 spines: 120 121 webservers: 122 hosts: 123 webserver01: 124 ansible_host: 10.16.10.15 125 ansible_user: my_server_user 126 webserver02: 127 ansible_host: 10.16.10.16 128 ansible_user: my_server_user 129 130 datacenter: 131 children: 132 network: 133 webservers: 134 135 136Group variables within inventory 137================================================================================ 138 139When devices in a group share the same variable values, such as OS or SSH user, you can reduce duplication and simplify maintenance by consolidating these into group variables: 140 141.. code-block:: yaml 142 143 --- 144 145 leafs: 146 hosts: 147 leaf01: 148 ansible_host: 10.16.10.11 149 leaf02: 150 ansible_host: 10.16.10.12 151 vars: 152 ansible_network_os: vyos.vyos.vyos 153 ansible_user: my_vyos_user 154 155 spines: 156 hosts: 157 spine01: 158 ansible_host: 10.16.10.13 159 spine02: 160 ansible_host: 10.16.10.14 161 vars: 162 ansible_network_os: vyos.vyos.vyos 163 ansible_user: my_vyos_user 164 165 network: 166 children: 167 leafs: 168 spines: 169 170 webservers: 171 hosts: 172 webserver01: 173 ansible_host: 10.16.10.15 174 webserver02: 175 ansible_host: 10.16.10.16 176 vars: 177 ansible_user: my_server_user 178 179 datacenter: 180 children: 181 network: 182 webservers: 183 184Variable syntax 185================================================================================ 186 187The syntax for variable values is different in inventory, in playbooks, and in the ``group_vars`` files, which are covered below. Even though playbook and ``group_vars`` files are both written in YAML, you use variables differently in each. 188 189- In an ini-style inventory file you **must** use the syntax ``key=value`` for variable values: ``ansible_network_os=vyos.vyos.vyos``. 190- In any file with the ``.yml`` or ``.yaml`` extension, including playbooks and ``group_vars`` files, you **must** use YAML syntax: ``key: value``. 191 192- In ``group_vars`` files, use the full ``key`` name: ``ansible_network_os: vyos.vyos.vyos``. 193- In playbooks, use the short-form ``key`` name, which drops the ``ansible`` prefix: ``network_os: vyos.vyos.vyos``. 194 195 196Group inventory by platform 197================================================================================ 198 199As your inventory grows, you may want to group devices by platform. This allows you to specify platform-specific variables easily for all devices on that platform: 200 201.. code-block:: yaml 202 203 --- 204 205 leafs: 206 hosts: 207 leaf01: 208 ansible_host: 10.16.10.11 209 leaf02: 210 ansible_host: 10.16.10.12 211 212 spines: 213 hosts: 214 spine01: 215 ansible_host: 10.16.10.13 216 spine02: 217 ansible_host: 10.16.10.14 218 219 network: 220 children: 221 leafs: 222 spines: 223 vars: 224 ansible_connection: ansible.netcommon.network_cli 225 ansible_network_os: vyos.vyos.vyos 226 ansible_user: my_vyos_user 227 228 webservers: 229 hosts: 230 webserver01: 231 ansible_host: 10.16.10.15 232 webserver02: 233 ansible_host: 10.16.10.16 234 vars: 235 ansible_user: my_server_user 236 237 datacenter: 238 children: 239 network: 240 webservers: 241 242With this setup, you can run ``first_playbook.yml`` with only two flags: 243 244.. code-block:: console 245 246 ansible-playbook -i inventory.yml -k first_playbook.yml 247 248With the ``-k`` flag, you provide the SSH password(s) at the prompt. Alternatively, you can store SSH and other secrets and passwords securely in your group_vars files with ``ansible-vault``. See :ref:`network_vault` for details. 249 250Verifying the inventory 251========================= 252 253You can use the :ref:`ansible-inventory` CLI command to display the inventory as Ansible sees it. 254 255.. code-block:: console 256 257 $ ansible-inventory -i test.yml --list 258 { 259 "_meta": { 260 "hostvars": { 261 "leaf01": { 262 "ansible_connection": "ansible.netcommon.network_cli", 263 "ansible_host": "10.16.10.11", 264 "ansible_network_os": "vyos.vyos.vyos", 265 "ansible_user": "my_vyos_user" 266 }, 267 "leaf02": { 268 "ansible_connection": "ansible.netcommon.network_cli", 269 "ansible_host": "10.16.10.12", 270 "ansible_network_os": "vyos.vyos.vyos", 271 "ansible_user": "my_vyos_user" 272 }, 273 "spine01": { 274 "ansible_connection": "ansible.netcommon.network_cli", 275 "ansible_host": "10.16.10.13", 276 "ansible_network_os": "vyos.vyos.vyos", 277 "ansible_user": "my_vyos_user" 278 }, 279 "spine02": { 280 "ansible_connection": "ansible.netcommon.network_cli", 281 "ansible_host": "10.16.10.14", 282 "ansible_network_os": "vyos.vyos.vyos", 283 "ansible_user": "my_vyos_user" 284 }, 285 "webserver01": { 286 "ansible_host": "10.16.10.15", 287 "ansible_user": "my_server_user" 288 }, 289 "webserver02": { 290 "ansible_host": "10.16.10.16", 291 "ansible_user": "my_server_user" 292 } 293 } 294 }, 295 "all": { 296 "children": [ 297 "datacenter", 298 "ungrouped" 299 ] 300 }, 301 "datacenter": { 302 "children": [ 303 "network", 304 "webservers" 305 ] 306 }, 307 "leafs": { 308 "hosts": [ 309 "leaf01", 310 "leaf02" 311 ] 312 }, 313 "network": { 314 "children": [ 315 "leafs", 316 "spines" 317 ] 318 }, 319 "spines": { 320 "hosts": [ 321 "spine01", 322 "spine02" 323 ] 324 }, 325 "webservers": { 326 "hosts": [ 327 "webserver01", 328 "webserver02" 329 ] 330 } 331 } 332 333.. _network_vault: 334 335Protecting sensitive variables with ``ansible-vault`` 336================================================================================ 337 338The ``ansible-vault`` command provides encryption for files and/or individual variables like passwords. This tutorial will show you how to encrypt a single SSH password. You can use the commands below to encrypt other sensitive information, such as database passwords, privilege-escalation passwords and more. 339 340First you must create a password for ansible-vault itself. It is used as the encryption key, and with this you can encrypt dozens of different passwords across your Ansible project. You can access all those secrets (encrypted values) with a single password (the ansible-vault password) when you run your playbooks. Here's a simple example. 341 3421. Create a file and write your password for ansible-vault to it: 343 344.. code-block:: console 345 346 echo "my-ansible-vault-pw" > ~/my-ansible-vault-pw-file 347 3482. Create the encrypted ssh password for your VyOS network devices, pulling your ansible-vault password from the file you just created: 349 350.. code-block:: console 351 352 ansible-vault encrypt_string --vault-id my_user@~/my-ansible-vault-pw-file 'VyOS_SSH_password' --name 'ansible_password' 353 354If you prefer to type your ansible-vault password rather than store it in a file, you can request a prompt: 355 356.. code-block:: console 357 358 ansible-vault encrypt_string --vault-id my_user@prompt 'VyOS_SSH_password' --name 'ansible_password' 359 360and type in the vault password for ``my_user``. 361 362The :option:`--vault-id <ansible-playbook --vault-id>` flag allows different vault passwords for different users or different levels of access. The output includes the user name ``my_user`` from your ``ansible-vault`` command and uses the YAML syntax ``key: value``: 363 364.. code-block:: yaml 365 366 ansible_password: !vault | 367 $ANSIBLE_VAULT;1.2;AES256;my_user 368 66386134653765386232383236303063623663343437643766386435663632343266393064373933 369 3661666132363339303639353538316662616638356631650a316338316663666439383138353032 370 63393934343937373637306162366265383461316334383132626462656463363630613832313562 371 3837646266663835640a313164343535316666653031353763613037656362613535633538386539 372 65656439626166666363323435613131643066353762333232326232323565376635 373 Encryption successful 374 375This is an example using an extract from a YAML inventory, as the INI format does not support inline vaults: 376 377.. code-block:: yaml 378 379 ... 380 381 vyos: # this is a group in yaml inventory, but you can also do under a host 382 vars: 383 ansible_connection: ansible.netcommon.network_cli 384 ansible_network_os: vyos.vyos.vyos 385 ansible_user: my_vyos_user 386 ansible_password: !vault | 387 $ANSIBLE_VAULT;1.2;AES256;my_user 388 66386134653765386232383236303063623663343437643766386435663632343266393064373933 389 3661666132363339303639353538316662616638356631650a316338316663666439383138353032 390 63393934343937373637306162366265383461316334383132626462656463363630613832313562 391 3837646266663835640a313164343535316666653031353763613037656362613535633538386539 392 65656439626166666363323435613131643066353762333232326232323565376635 393 394 ... 395 396To use an inline vaulted variables with an INI inventory you need to store it in a 'vars' file in YAML format, 397it can reside in host_vars/ or group_vars/ to be automatically picked up or referenced from a play via ``vars_files`` or ``include_vars``. 398 399To run a playbook with this setup, drop the ``-k`` flag and add a flag for your ``vault-id``: 400 401.. code-block:: console 402 403 ansible-playbook -i inventory --vault-id my_user@~/my-ansible-vault-pw-file first_playbook.yml 404 405Or with a prompt instead of the vault password file: 406 407.. code-block:: console 408 409 ansible-playbook -i inventory --vault-id my_user@prompt first_playbook.yml 410 411To see the original value, you can use the debug module. Please note if your YAML file defines the `ansible_connection` variable (as we used in our example), it will take effect when you execute the command below. To prevent this, please make a copy of the file without the ansible_connection variable. 412 413.. code-block:: console 414 415 cat vyos.yml | grep -v ansible_connection >> vyos_no_connection.yml 416 417 ansible localhost -m debug -a var="ansible_password" -e "@vyos_no_connection.yml" --ask-vault-pass 418 Vault password: 419 420 localhost | SUCCESS => { 421 "ansible_password": "VyOS_SSH_password" 422 } 423 424 425.. warning:: 426 427 Vault content can only be decrypted with the password that was used to encrypt it. If you want to stop using one password and move to a new one, you can update and re-encrypt existing vault content with ``ansible-vault rekey myfile``, then provide the old password and the new password. Copies of vault content still encrypted with the old password can still be decrypted with old password. 428 429For more details on building inventory files, see :ref:`the introduction to inventory<intro_inventory>`; for more details on ansible-vault, see :ref:`the full Ansible Vault documentation<vault>`. 430 431Now that you understand the basics of commands, playbooks, and inventory, it's time to explore some more complex Ansible Network examples. 432