Starting with Ansible in Raspberry Pi
Tags: docker, tutorial, raspberrypi, ansible
Published: 2020-02-12 19:39:17

I have been thinking about starting to test Ansible in order to learn some of the basics, so what better way to do it in a easy to access system as a Raspberry Pi.

We won't be doing anything amazing here, just some basics processes on how to start with Ansible.

***Lets start!!***

Like I was mentioning earlier, lets use a small Raspberry Pi 2:

    Linux raspi-2 4.19.97-v7+ #1294 SMP Thu Jan 30 13:15:58 GMT 2020 armv7l
    
    The programs included with the Debian GNU/Linux system are free software;
    the exact distribution terms for each program are described in the
    individual files in /usr/share/doc/*/copyright.
    
    Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
    permitted by applicable law.
    Last login: Fri Feb  7 15:10:01 2020 from 192.168.0.21
        .',;:cc;,'.    .,;::c:,,.    P-42@raspi-2
       ,ooolcloooo:  'oooooccloo:    OS: Raspbian 10 buster
       .looooc;;:ol  :oc;;:ooooo'    Kernel: armv7l Linux 4.19.97-v7+
         ;oooooo:      ,ooooooc.     Uptime: 4d 23h 1m
           .,:;'.       .;:;'.       Packages: 635
           .... ..'''''. ....        Shell: 25900
         .''.   ..'''''.  ..''.      WM: Not Found
         ..  .....    .....  ..      CPU: ARMv7 rev 5 (v7l) @ 4x 900MHz
        .  .'''''''  .''''''.  .     GPU: BCM2708
      .'' .''''''''  .'''''''. ''.   RAM: 193MiB / 926MiB
      '''  '''''''    .''''''  '''
      .'    ........... ...    .'.
        ....    ''''''''.   .''.
        '''''.  ''''''''. .'''''
         '''''.  .'''''. .'''''.
          ..''.     .    .''..
                .'''''''
                 ......
    P-42@raspi-2:~#
    '


## Installing Ansible
We can use `apt` or your particular distro package manager, but doing that, we risk no getting the latest version available.
In some cases, I have to agree that is good idea, we make sure system is kept stable and the packages has been tested enough, but in technologies like Ansible, which is still changing so rapidly, I recommend you to go ahead in your tests and get the latest version, that way  you will also learn to use those latest versions, which have some modules usage differences.

Lets see the version installed using `apt` in Raspbian

    P-42@raspi-2:~#sudo apt-get update
    Get:1 http://archive.raspberrypi.org/debian buster InRelease [25.1 kB]
    Get:2 http://raspbian.raspberrypi.org/raspbian buster InRelease [15.0 kB]
    [....]
    Fetched 13.3 MB in 17s (806 kB/s)
    Reading package lists... Done
    
    
   P-42@raspi-2:~#sudo apt list ansible
    Listing... Done
    ansible/stable,now 2.7.7+dfsg-1 all [residual-config]
    P-42@raspi-2:~#

Lets compare it with the version we get using `pip3`

    P-42@raspi-2:~#pip3 search "ansible"
    [...]
    ansible (2.9.4)               - Radically simple IT automation

As you can see ,there are some difference, so I really recommend you to use pip for the installation

To Install Ansible using `pip3`, install `pip3` first and then lets install Ansible for your current user:

    P-42@raspi-2:~#sudo apt-get install python3-pip
    Reading package lists... Done
    Building dependency tree
    Reading state information... Done
    The following packages were automatically installed and are no longer required:
      ieee-data libsodium23 python3-bcrypt python3-httplib2 python3-jinja2 python3-jmespath 
      [....]
      Setting up libpython3-dev:armhf (3.7.3-1) ...
    Processing triggers for mime-support (3.62) ...
    P-42@raspi-2:~#


    P-42@raspi-2:~#pip3 install --user ansible
    Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
    Collecting ansible
      Using cached https://files.pythonhosted.org/packages/d7/d7/5afcb906038cd8a217ac57110055e27000c5cfe05ecafe969aaa119d1652/ansible-2.9.4.tar.gz
    Requirement already satisfied: PyYAML in /usr/lib/python3/dist-packages (from ansible) (3.13)
    Requirement already satisfied: cryptography in /usr/lib/python3/dist-packages (from ansible) (2.6.1)
    Requirement already satisfied: jinja2 in /usr/lib/python3/dist-packages (from ansible) (2.10)
    Building wheels for collected packages: ansible
      Running setup.py bdist_wheel for ansible ... done
      Stored in directory: /home/P-42/.cache/pip/wheels/f2/8a/6e/a433065001168c4ecbb5eb34224ec0af954e2a12aefe3da2cb
    Successfully built ansible
    Installing collected packages: ansible
    Successfully installed ansible-2.9.4
    P-42@raspi-2:~#

Installing Ansible using the `--user` option, will make that the binary will be available directly under your user home, and not in your root bin directory `(/bin,/usr/bin..)`

    P-42@raspi-2:~#which ansible
    /home/P-42/.local/bin/ansible
    P-42@raspi-2:~#

For that, I recommend you to add your `$user_home/.local/bin` to your `PATH` environment:

    P-42@raspi-2:~#env |grep bin
    SHELL=/bin/bash
    PATH=/home/P-42/gems/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games:/home/P-42/.local/bin
    _=/usr/bin/env
    P-42@raspi-2:~#

## Ansible Project Configuration


Now that we have Ansible installed, lets set some basic configuration.

Create a directory for our first project where we are going to set the different configuration files and Ansible playbooks

    P-42@raspi-2:~#mkdir Ansible
    mkdir: created directory 'Ansible'
    P-42@raspi-2:~# 

First file we are going to create, is an Ansible configuration file. This will make sure we are using correct inventory file and some specific options for this project. 
In this case, we will use the inventory file in the local directory and will be connecting to the remote server as root. Additionally, will disable ssh-key check so we can connect to the servers without doing first ssh-key handshake (is a security risk, but will help us to destroy and deploy containers and VMs more rapidly in the future)


    P-42@raspi-2:~/Ansible#cat ansible.cfg
    [defaults]
    # host_key_check diabled to avoid issues connecting to the Servers *Is a security risk*
    host_key_checking = False
    
    # Make user we are using local inventory and not the default one
    inventory=./inventory
    
    # Set default user to root
    remote_user=root
    P-42@raspi-2:~/Ansible#

Using `--version` attribute, will allow us to make sure we are suing correct configuration file:

    P-42@raspi-2:~/Ansible#ansible --version
    ansible 2.9.4
      config file = /home/P-42/Ansible/ansible.cfg
      configured module search path = ['/home/P-42/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
      ansible python module location = /home/P-42/.local/lib/python3.7/site-packages/ansible
      executable location = /home/P-42/.local/bin/ansible
      python version = 3.7.3 (default, Dec 20 2019, 18:57:59) [GCC 8.3.0]
    P-42@raspi-2:~/Ansible#

Lets create the inventory file with the list of hosts we will use for our project

    P-42@raspi-2:~/ansible#cat inventory
    [all]
    server[1:4]
    
    [webservers]
    server1
    server2

We can list all the hosts from our inventory

    P-42@raspi-2:~/Ansible#ansible all --list-hosts
      hosts (4):
        server1
        server2
        server3
        server4
    P-42@raspi-2:~/Ansible#


** These servers we are using are Docker containers we created using the following tutorial: [https://dev.to/project42/install-and-deploy-docker-in-raspberry-pi-14kj](https://dev.to/project42/install-and-deploy-docker-in-raspberry-pi-14kj)

If we try the command `ansible ping` we will have errors, since we can not actually connect to our servers using ssh public keys


    P-42@raspi-2:~/Ansible#ansible all -m ping
    server2 | UNREACHABLE! => [
        "changed": false,
        "msg": "Failed to connect to the host via ssh: root@server2: Permission denied (publickey,password).",
        "unreachable": true
    ]
    server1 | UNREACHABLE! => [
        "changed": false,
        "msg": "Failed to connect to the host via ssh: root@server1: Permission denied (publickey,password).",
        "unreachable": true
    ]
    server3 | UNREACHABLE! => [
        "changed": false,
        "msg": "Failed to connect to the host via ssh: root@server3: Permission denied (publickey,password).",
        "unreachable": true
    ]
    server4 | UNREACHABLE! => [
        "changed": false,
        "msg": "Failed to connect to the host via ssh: root@server4: Permission denied (publickey,password).",
        "unreachable": true
    ]
    P-42@raspi-2:~/Ansible#

## Deploying our first Playbook


 Lets deploy the following Ansible Playbook in order to add our ssh public key to all servers root user


    P-42@raspi-2:~/Ansible#cat ssh-key.yml
    ---
    - name: Set authorized key for user root copying it from current user
      hosts: all
      tasks:
      - name: Install ssh-key
        authorized_key:
          user: root
          state: present
          key: "[ lookup('file', lookup('env','HOME') + '/.ssh/id_rsa.pub') ]]"
    P-42@raspi-2:~/Ansible#


In order to use Ansible without having ssh-keys in the different servers, we will need to install the package `sshpass` first


    P-42@raspi-2:~/Ansible#sudo apt-get install sshpass -y
    Reading package lists... Done
    Building dependency tree
    Reading state information... Done
    The following packages were automatically installed and are no longer required:
      ieee-data libsodium23 python3-bcrypt python3-httplib2 python3-jinja2 python3-jmespath python3-kerberos python3-libcloud python3-lockfile
      python3-markupsafe python3-nacl python3-netaddr python3-ntlm-auth python3-paramiko 
      [....]
    Processing triggers for man-db (2.8.5-2) ...
    P-42@raspi-2:~/Ansible#

Lets now deploy the playbook `ssh-key.yml` using the option `-k` so ansible will ask for the root password before connecting to the systems, allowing it to get the ssh-key added:




    P-42@raspi-2:~/Ansible#ssh root@server1
    Welcome to Ubuntu 16.04.6 LTS (GNU/Linux 4.19.97-v7+ armv7l)
    
     * Documentation:  https://help.ubuntu.com
     * Management:     https://landscape.canonical.com
     * Support:        https://ubuntu.com/advantage
    
    Last login: Wed Feb 12 18:20:18 2020 from 172.168.0.1
    root@server1:~#

    P-42@raspi-2:~/Ansible#ansible-playbook -k ssh-key.yml
    SSH password:
    
    PLAY [Set authorized key for user root copying it from current user] **************************************************************************
    
    TASK [Gathering Facts] ************************************************************************************************************************
    [DEPRECATION WARNING]: Distribution Ubuntu 16.04 on host server1 should use /usr/bin/python3, but is using /usr/bin/python for backward
    compatibility with prior Ansible releases. A future Ansible release will default to using the discovered platform python for this host. See
    https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information. This feature will be removed in
    version 2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
    ok: [server1]
    [DEPRECATION WARNING]: Distribution Ubuntu 16.04 on host server4 should use /usr/bin/python3, but is using /usr/bin/python for backward
    compatibility with prior Ansible releases. A future Ansible release will default to using the discovered platform python for this host. See
    https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information. This feature will be removed in
    version 2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
    ok: [server4]
    [DEPRECATION WARNING]: Distribution Ubuntu 16.04 on host server2 should use /usr/bin/python3, but is using /usr/bin/python for backward
    compatibility with prior Ansible releases. A future Ansible release will default to using the discovered platform python for this host. See
    https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information. This feature will be removed in
    version 2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
    ok: [server2]
    [DEPRECATION WARNING]: Distribution Ubuntu 16.04 on host server3 should use /usr/bin/python3, but is using /usr/bin/python for backward
    compatibility with prior Ansible releases. A future Ansible release will default to using the discovered platform python for this host. See
    https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information. This feature will be removed in
    version 2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
    ok: [server3]
    
    TASK [Install ssh-key] ************************************************************************************************************************
    changed: [server2]
    changed: [server4]
    changed: [server1]
    changed: [server3]
    
    PLAY RECAP ************************************************************************************************************************************
    server1                    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    server2                    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    server3                    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    server4                    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    
    P-42@raspi-2:~/Ansible#

and ***voila!*** we got our ssh-keys deployed and we can connect the systems without using the root password
(We can ignore does warning by enabling `deprecation_warnings=False` in ansible.cfg, but I recommend you to leave them to learn new things and get better usage of Ansible)

    P-42@raspi-2:~/Ansible#ansible all -m ping
    [DEPRECATION WARNING]: Distribution Ubuntu 16.04 on host server3 should use /usr/bin/python3, but is using /usr/bin/python for backward
    compatibility with prior Ansible releases. A future Ansible release will default to using the discovered platform python for this host. See
    https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information. This feature will be removed in
    version 2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
    server3 | SUCCESS => [
        "ansible_facts": [
            "discovered_interpreter_python": "/usr/bin/python"
        ],
        "changed": false,
        "ping": "pong"
    ]
    [DEPRECATION WARNING]: Distribution Ubuntu 16.04 on host server2 should use /usr/bin/python3, but is using /usr/bin/python for backward
    compatibility with prior Ansible releases. A future Ansible release will default to using the discovered platform python for this host. See
    https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information. This feature will be removed in
    version 2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
    server2 | SUCCESS => [
        "ansible_facts": [
            "discovered_interpreter_python": "/usr/bin/python"
        ],
        "changed": false,
        "ping": "pong"
    ]
    [DEPRECATION WARNING]: Distribution Ubuntu 16.04 on host server4 should use /usr/bin/python3, but is using /usr/bin/python for backward
    compatibility with prior Ansible releases. A future Ansible release will default to using the discovered platform python for this host. See
    https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information. This feature will be removed in
    version 2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
    server4 | SUCCESS => [
        "ansible_facts": [
            "discovered_interpreter_python": "/usr/bin/python"
        ],
        "changed": false,
        "ping": "pong"
    ]
    [DEPRECATION WARNING]: Distribution Ubuntu 16.04 on host server1 should use /usr/bin/python3, but is using /usr/bin/python for backward
    compatibility with prior Ansible releases. A future Ansible release will default to using the discovered platform python for this host. See
    https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information. This feature will be removed in
    version 2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
    server1 | SUCCESS => [
        "ansible_facts": [
            "discovered_interpreter_python": "/usr/bin/python"
        ],
        "changed": false,
        "ping": "pong"
    ]
    P-42@raspi-2:~/Ansible#


Like a mentioned, this is just a simple example of how to get started with Ansible in Raspberry Pi.