Ansible & Docker on the ManagementPi

Posted by MarWinsWorld on Wednesday, March 31, 2021

Contents

After we’ve set up the OS, let’s go ahead and install Ansible and Docker.

Ansible on the ManagementPi

Install Ansible

In real life, you should create an ansible user on your Ansible server to run all the playbooks. For simplicity we skip that on our small management server and just use the already existing ubuntu user. Now we prepare for Ansible by adding the universe-Repository and installing python3-pip.

sudo apt-get update
sudo add-apt-repository universe
sudo apt install -y python3-pip

When we install Ansible it is shipped with many python modules and dependencies. It is good to install Ansible in userspace, so it won’t affect system-wide.

pip3 install ansible --user
echo 'export PATH=$PATH:$HOME/.local/bin' >> ~/.bashrc
source .bashrc
ansible --version

The last command should return something like the following:

ansible 2.10.7
  config file = /home/ubuntu/.ansible.cfg
  configured module search path = ['/home/ubuntu/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/ubuntu/.local/lib/python3.8/site-packages/ansible
  executable location = /home/ubuntu/.local/bin/ansible
  python version = 3.8.6 (default, Jan 27 2021, 15:42:20) [GCC 10.2.0]

Create the Ansible Configuration

Next, you need to create an .ansible.cfg in your home directory which will overwrite the one in /etc/ansible/ansible.cfg. We get an example config directly from the Ansible GitHub repo.

wget https://raw.githubusercontent.com/ansible/ansible/devel/examples/ansible.cfg -O .ansible.cfg

Set the following variables in /home/ubuntu/.ansible.cfg within the [defaults]-chapter at the beginning of the file:

vi ~/.ansible.cfg
inventory       = /home/ubuntu/manager/inventory/hosts.yaml
interpreter_python = auto
log_path = /var/log/ansible.log
display_skipped_hosts = False
stdout_callback = yaml

Create the ssh Keypair for Ansible

Ansible with authentiticate to Linux hosts in your environment using ssh keys. For this we need to create the keys and then add them to the authorized keys on the target machines.

Star with creating a .ssh directory if it is not already existing

mkdir -p ~/.ssh
chmod 700 ~/.ssh

Then, generate ssh-keys without setting a passphrase

ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/ubuntu/.ssh/id_rsa):
Created directory '/home/ubuntu/.ssh'.
Enter passphrase (empty for no passphrase): <DON'T SET A PASSPHRASE HERE>
Enter same passphrase again:
Your identification has been saved in /home/ubuntu/.ssh/id_rsa.
Your public key has been saved in /home/ubuntu/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:1gzgC5QR+tSX6YQsQvBiZKEi4+Ez04b7k5sMwGen7Yk ubuntu@manager
The key's randomart image is:
+---[RSA 2048]----+
|.=o ++.          |
|+o o.+ o o       |
|*o+ + = *        |
|Bo++ o = +       |
|.O =... S o      |
|. O +  .         |
| o ...           |
|  +o+ .          |
|   Eoo           |
+----[SHA256]-----+

There will be two new files within the /home/ubuntu/.ssh-directory, the private and the public part of the keypair just generated.

We will copy the generated public key on the target machines which we’re going to manage with Ansible later on.

Ansible Vault

For all credentials, we will use the ansible-vault. Create a file called .vault-pass.txt in the home directory of the ubuntu-user with a secret password.

echo '<YOUR VERY STRONG PASSWORD>' > ~/.vault-pass.txt
chmod 600 ~/.vault-pass.txt

Ansible Helper Tools (Optional)

Ansible-Lint

The tool ansible-lint helps you to verify, that your Ansible playbooks conform to the specification.

pip3 install -U "ansible-lint[community,yamllint]"

jq

The “Swiss Army Knife” for JSON is, simply put, jq. Install it with the following command:

sudo apt-get install jq

Docker on the ManagementPi

Now, since we’ve set up the OS and Ansible, let’s go for the next step and install Docker.

Install Docker

The installation of Docker on our ManagementPi is pretty straight forward since we can use the helper script provided by Docker. For simplicity we will allow our user ubuntu to run docker commands without sudo. This might not be the most secure way on production systems, though.

curl -fsSL get.docker.com -o get-docker.sh && sudo sh get-docker.sh
sudo usermod -aG docker ubuntu && sudo service docker start
sudo systemctl enable docker

Install Docker-Compose

Compose is a tool for defining and running multi-container Docker applications. On the ManagementPi we will use Compose to define the container stack running locally on our server only. Install it with the following two commands:

sudo apt install -y libffi-dev libssl-dev python3-dev python3 python3-pip
sudo pip3 install docker-compose

The Container Stack on the ManagementPi

For the start, we’re not going to run many containers on the ManagementPi - we stick to Portainer and Watchtower for now. Portainer is a very popular Open Source Container Management GUI which we can use to monitor and manage all our container environments. Watchtower is a process for watching your Docker containers and automatically restarting them whenever their base image is refreshed. As a reference, the watchtower source is located here: https://github.com/containrrr/watchtower.

Create a file called docker-compose.yaml with the following contents in the home directory of your ubuntu-user:

version: "3.2"
services:

# ##########################################################################
# Management
# ##########################################################################

  portainer:
    container_name: portainer
    image: portainer/portainer-ce:latest
    volumes:
      - /home/ubuntu/portainer:/data
      - /var/run/docker.sock:/var/run/docker.sock
      - /etc/localtime:/etc/localtime:ro
      - /etc/timezone:/etc/timezone:ro
    ports:
      - 9000:9000
      #- 8000:8000
    restart: always

  watchtower:
    container_name: watchtower
    image: v2tec/watchtower:latest
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /etc/localtime:/etc/localtime:ro
      - /etc/timezone:/etc/timezone:ro
    command: --interval 300 --cleanup --debug
    restart: always

Next, create the referenced portainer directory where Portainer will store it’s persistent data

mkdir -p /home/ubuntu/portainer

Create the stack with

docker-compose up -d

After a couple of seconds you should be able to point your broser to http://IP:9000, whereby IP should be replaced with the IP of your ManagementPi. We’re going to configure Portainer for remote hosts in one of the following blog posts.