> ~ biozz / Blog

Ansible #1 - Preparations 2020-07-12

Ansible Tutorial - Part 1 - Preparations

Reading time: 3m (529 words)

UPDATE 2023-07-02

I released this and the other parts of the Ansible tutorial (announcement) on ansible.biozz.dev. It is much nicer to read and follow, please read it instead.

Definitions

Control node - any computer on which Ansible is installed. You can run commands and playbooks from it.

Managed nodes - devices/servers on a network that can be managed by Ansible. Sometimes referred to as “host”. Ansible is not installed on them.

Inventory - A list of managed hosts/nodes. Sometimes the inventory is called a hostfile. IP addresses of servers are specified there. You can group hosts in the inventory for easy deployment.

Modules - A unit of code that Ansible executes. Can customize the system, can be combined into “tasks”, can be executed within a playbook.

Tasks - unit of action that Ansible can perform. You can execute one-off tasks using ad-hoc commands.

Playbooks - an ordered list of tasks. May include variables. Written in YAML.

Folders

Create a ansible folder, it will contain all configs and a starting point for commands.

Create a containers folder in the ansible folder.

Ansible

Install ansible:

> pip install ansible

I use pyenv to work with virtualenv, so I had these commands executed beforehand: pyenv virtualenv virtualenv 3.8.2 ansible-3.8.2 and pyenv local ansible-3.8.2.

Hosts

We will have two Debian hosts as Docker containers. Since Ansible will not like passwords when connecting via SSH, we set up key authorization right away. The container configuration files are taken almost one-to-one from the Praqma/alpine-sshd repository.

Create Dockerfile:

FROM debian:10.4
RUN apt-get update \
    && apt-get install -y openssh-server python3.7 \
    && mkdir /var/run/sshd\ 
    && mkdir /root/.ssh \
    && chmod 0700 /root/.ssh \
    && ssh-keygen -A \
    && sed -i s/^#PasswordAuthentication\ yes/PasswordAuthentication\ no/ /etc/ssh/sshd_config
COPY docker-entrypoint.sh /
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["/usr/sbin/sshd", "-D"]

Create docker-entrypoint.sh:

#!/bin/sh
if [ -z "${AUTHORIZED_KEYS}" ]; then
  echo "Need your ssh public key as AUTHORIZED_KEYS env variable. Abnormal exit ..."
  exit 1
fi
echo "Populating /root/.ssh/authorized_keys with the value from AUTHORIZED_KEYS env variable ..."
echo "${AUTHORIZED_KEYS}" > /root/.ssh/authorized_keys
# Execute the CMD from the Dockerfile:
exec "$@"

Create docker-compose.yml:

version: "3"

services:
  deb1:
    build: .
    environment:
      AUTHORIZED_KEYS: ${AUTHORIZED_KEYS}
    ports:
      - "2222:22"
  deb2:
    build: .
    environment:
      AUTHORIZED_KEYS: ${AUTHORIZED_KEYS}
    ports:
      - "2223:22"

Set the environment variable for ssh keys, build the images and run:

> export AUTHORIZED_KEYS=$(cat ~/.ssh/id_rsa.pub)
> docker-compose up --build

If everything is ok, the output will be something like this at the end of the output:

Creating containers_deb1_1 ... done
Creating containers_deb2_1 ... done
Attaching to containers_deb2_1, containers_deb1_1
deb2_1  | Populating /root/.ssh/authorized_keys with the value from AUTHORIZED_KEYS env variable ...
deb1_1  | Populating /root/.ssh/authorized_keys with the value from AUTHORIZED_KEYS env variable ...

Check ssh connection:

> ssh root@localhost -p 2222
> ssh root@localhost -p 2223

Basic inventory

Create inventory.yml:

---
debs:
  hosts:
    deb1:
      ansible_port: 2222
      ansible_host: localhost
      ansible_user: root
      ansible_python_interpreter: /usr/bin/python3.7
    deb2:
      ansible_port: 2223
      ansible_host: localhost
      ansible_user: root
      ansible_python_interpreter: /usr/bin/python3.7

Ansible config

Create ansible.cfg:

[defaults]
inventory = /path/to/inventory.yml

The final result

├── containers
│   ├── Dockerfile
│   ├── docker-compose.yml
│   └── docker-entrypoint.sh
├── ansible.cfg
└── inventory.yml

Materials used in this part

Translations: ru