Tech/OSS/Ansible/Guide

From lathama
< Tech‎ | OSS‎ | Ansible
Jump to navigation Jump to search

I started a 101 class thing at https://lathama.net/git/lathama/Ansible101 but was not getting to it often. It may be better as wiki pages.

Ansible Guide

Introduction

A basic setup to teach people how to get started without making a mess. This is written for use on a modern Linux system.

Installation

Installation via the Python PIP tool looks like:

lathama@desky:~/Ansible101$ python3 -m pip install -qq --user --upgrade ansible

To break down this command into its parts:

  • python3 -m pip is the current best practice for scripts. pip3 should work the same from the CLI
  • install -qq quietly install and answer yes to prompts
  • --user install in the user home (no root user required)
  • --upgrade upgrade the package or dependencies if installed

Confirm the install with:

lathama@desky:~/Ansible101$ ansible --version
ansible [core 2.14.4]
  config file = /home/lathama/Ansible101/ansible.cfg
  configured module search path = ['/home/lathama/Ansible101/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/lathama/.local/lib/python3.9/site-packages/ansible
  ansible collection location = /home/lathama/Ansible101/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/lathama/.local/bin/ansible
  python version = 3.9.2 (default, Feb 28 2021, 17:03:44) [GCC 10.2.1 20210110] (/usr/bin/python3)
  jinja version = 3.1.2
  libyaml = True

In some cases you may need to completely log out and log back in to have the PATH set correctly

Configs and Setup

Note the included ansible.cfg that sets the paths for this demo. A vault passphrase is the only thing missing from the demo by default.

lathama@desky:~/Ansible101$ echo "topsecret" > .ansible_vault

Command Line Interface (CLI)

Ansible has many CLI tools

  • ansible
  • ansible-community
  • ansible-config
  • ansible-connection
  • ansible-console
  • ansible-doc
  • ansible-galaxy
  • ansible-inventory
  • ansible-playbook
  • ansible-pull
  • ansible-test
  • ansible-vault

References

Ad hoc

Ad hoc commands are useful. By default Ansible will create a python script. The ansiballz script will be sent to the host to execute.

Confirm SSH first

We will start with localhost. If you have issues connecting to localhost then further Ansible setup will be difficult/impossible. We are assuming you have the user password or have SSH keys setup.

lathama@desky:~/Ansible101$ ssh localhost whoami
lathama

Raw command does not need Python Interpreter on target

lathama@desky:~/Ansible101$ ansible localhost -m raw -a whoami
localhost | CHANGED | rc=0 >>
lathama
Shared connection to localhost closed.

Simple command using Python ansiballz

lathama@desky:~/Ansible101$ ansible localhost -a whoami
localhost | CHANGED | rc=0 >>
lathama

Target tmp empty

lathama@desky:~/Ansible101$ ls ~/.ansible/tmp

Keep remote file

lathama@desky:~/Ansible101$ ANSIBLE_KEEP_REMOTE_FILES=1 ansible localhost -a whoami

Target tmp ansiballz

As a learning moment, have a look at the ansiballz that is created on the target

lathama@desky:~/Ansible101$ ls ~/.ansible/tmp
ansible-tmp-1681314397.595484-476223-48384824394074
lathama@desky:~/Ansible101$ cat ~/.ansible/tmp/ansible-tmp-id/AnsiballZ_command.py | wc -l
259
lathama@desky:~/Ansible101$ grep whoami ~/.ansible/tmp/ansible-tmp-id/AnsiballZ_command.py
    ANSIBALLZ_PARAMS = '{"ANSIBLE_MODULE_ARGS": {"_raw_params": "whoami", "_ansible_check_mode": false,
    "_ansible_no_log": false, "_ansible_debug": false, "_ansible_diff": false, "_ansible_verbosity": 0,
    "_ansible_version": "2.14.4", "_ansible_module_name": "ansible.legacy.command",
    "_ansible_syslog_facility": "LOG_USER", "_ansible_selinux_special_fs": ["fuse", "nfs", "vboxsf",
    "ramfs", "9p", "vfat"], "_ansible_string_conversion_action": "warn", "_ansible_socket": null,
    "_ansible_shell_executable": "/bin/sh", "_ansible_keep_remote_files": true,
    "_ansible_tmpdir": "/home/lathama/.ansible/tmp/ansible-tmp-id/",
    "_ansible_remote_tmp": "~/.ansible/tmp"}}'

References


New and Old

To demonstrate some flexibility we will connect to a very old Cisco switch. You may not have a device like this. You will find situations when you need to automate a legacy device so understanding this will help.

Validate via SSH

First we will validate via SSH on the CLI. Note the options we must pass to enable old ciphers for this host.


lathama@desky:~/Ansible101$ ssh -o KexAlgorithms=+diffie-hellman-group1-sha1 -o HostKeyAlgorithms=+ssh-dss -c aes256-cbc cisco@192.168.1.9
Password: 
SGM-DEN-PSW-011.LATHAMA.NET#dir
Directory of flash:/

    2  -rwx    11832064   Jan 1 1970 00:20:44 +00:00  c2960-lanbasek9-mz.150-2.SE10.bin
    3  -rwx        1806   Sep 1 2020 17:55:47 +00:00  config.text
    4  -rwx       15556   Sep 1 2020 17:55:47 +00:00  private-config.text
    5  -rwx        3096   Sep 1 2020 17:55:47 +00:00  multiple-fs

27998208 bytes total (16046080 bytes free)
SGM-DEN-PSW-011.LATHAMA.NET#exit
Connection to 192.168.1.9 closed.

Inventory

An example from the inventory/inventory.yml

---

oldcisco:
  ansible_ssh_common_args: '-o KexAlgorithms=+diffie-hellman-group1-sha1 -c aes256-cbc'
  ansible_host: '192.168.1.9'
  ansible_user: 'cisco'
  ansible_password: 'topsecret'

A playbook

An example from playbooks/legacy.yml

---

# login to a really old Cisco switch and get some info
# using the raw command to list the directory
# we are making no changes so we ignore changes
# printing out the result we only want the stdout_lines

- name: 'Legacy device info'
  hosts: oldcisco
  gather_facts: false
  tasks:
    - name: 'List filesystem'
      ansible.builtin.raw: 'dir'
      changed_when: false
      register: result
    - name: 'Print out the directory'
      ansible.builtin.debug:
        var: result.stdout_lines


Run the playbook

lathama@desky:~/Ansible101$ ansible-playbook playbooks/legacy.yml 

PLAY [Legacy device info] ****************************************************************************************

TASK [List filesystem] *******************************************************************************************
ok: [oldcisco]

TASK [Print out the directory] ***********************************************************************************
ok: [oldcisco] => {
    "result.stdout_lines": [
        "Directory of flash:/",
        "",
        "    2  -rwx    11832064   Jan 1 1970 00:20:44 +00:00  c2960-lanbasek9-mz.150-2.SE10.bin",
        "    3  -rwx        1806   Sep 1 2020 17:55:47 +00:00  config.text",
        "    4  -rwx       15556   Sep 1 2020 17:55:47 +00:00  private-config.text",
        "    5  -rwx        3096   Sep 1 2020 17:55:47 +00:00  multiple-fs",
        "",
        "27998208 bytes total (16046080 bytes free)"
    ]
}

PLAY RECAP *******************************************************************************************************
oldcisco                   : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Conclusion

Note how simple it is to add a unique legacy system to the inventory and work with it.

References

Files

Terms

Idempotent / Idempotence
https://en.wikipedia.org/wiki/Idempotence
Andrew says "After initial use, the operation makes no changes in additional runs"