Skip to content

Ansible

Ansible es una herramienta para orquestar el despliegue de configuración e instalación de maquinas virtuales e infraestructura de modo automatizado. Primero se leindica un inventarios que consiste básicamente en un listado de IP's o dominios, y luego, para definir la estructura de tareas y comandos de configuración se utilizan archivos con formato YAML, conocido como receta (playbook).

Puede decirse que Ansible nos ofrece los siguientes aspectos:

  • Agentless: No requiere instalación en hosts remotos
  • Idempotente: Ejecutar múltiples veces produce el mismo resultado
  • YAML: Sintaxis simple y legible
  • Extensible: Miles de módulos disponibles
  • Multiplataforma: Linux, Windows, redes, cloud
  • Escalable: Desde un servidor hasta miles
  • Open Source: Gratuito con comunidad activa

Conceptos claves

  • Inventory: Se trata de una lista de hosts a gestionar
  • Playbook: Un archivo YAML con tareas
  • Task: La acción individual a ejecutar
  • Module: Funcionalidad específica (copy, service, etc.)
  • Role: Conjunto reutilizable de tareas
  • Handler: Tipo de tarea específica que se ejecuta cuando hay cambios

Basicamente en playbook tienes la receta de tasks (sentencias descriptivas) y handlers, y en inventory las conexiones a servidores

Instalación de Ansible

Ansible está diseñado principalmente para sistemas Linux, por lo que si piensas usarlo en Windows 10+ se debe tener instalado WSL (Windows Subsystem for Linux). Los comandos de instalación para Ubuntu son los siguientes:

bash
sudo apt update
sudo add-apt-repository -y --update ppa:ansible/ansible
sudo apt install -y ansible
ansible --version

Para macOS ejecuta: brew install ansible
Ansible está escrito en Python, por lo que requiere su uso (en la instación se incluye)

Alternativamente, puedes instalar Ansible ejecutando:

bash
pip install ansible

Comprendiendo Ansible con un Ejemplo

Teniendo instalado Ansible, planteemos desplegar en un servidor Linux remoto una app o servicio con su binario (ejemplo: wdb) usando ssh con una clave privada, por ejemplo, ssh -i ~/.ssh/private.key [email protected].

Definimos la siguiente estructura de archivos para gestionar Ansible:

  ____
./iac/
├── inventory.yml
├── playbook.yml
├── files/
│   └── wdb.service
└── dist/
    └── wdb

El contenido para el archivo inventory.yml sería como el siguiente:

yaml
all:
  hosts:
    my-server:
      ansible_host: 111.111.111.1
      ansible_user: user
      ansible_ssh_private_key_file: ~/.ssh/private.key
      ansible_ssh_common_args: "-o StrictHostKeyChecking=no"

Debes reemplazar por tu user, host y private.key, de ese modo funcionará como ssh. La última línea es opcional.

El contenido para el archivo playbook.yml sería como el siguiente:

yaml
---
- name: Deploy WDB
  hosts: my-server
  become: true                # uses sudo when necesary
  vars:
    app_name: wdb
    app_dir: /opt/wdb
    app_user: user
    app_binary: wdb

  tasks:
    - name: Create app directory
      ansible.builtin.file:
        path: "{{ app_dir }}"
        state: directory
        owner: "{{ app_user }}"
        group: "{{ app_user }}"
        mode: '0755'

    - name: Copy binary program (wdb)
      ansible.builtin.copy:
        src: "./dist/{{ app_binary }}"
        dest: "{{ app_dir }}/{{ app_binary }}"
        owner: "{{ app_user }}"
        group: "{{ app_user }}"
        mode: '0755'
      notify: Reinit service

    - name: Copy service for systemd
      ansible.builtin.copy:
        src: "files/{{ app_name }}.service"
        dest: "/etc/systemd/system/{{ app_name }}.service"
        owner: root
        group: root
        mode: "0644"
      notify:
        - Reload systemd
        - Reinit service

    - name: Check service is running
      ansible.builtin.systemd_service:
        name: "{{ app_name }}"
        enabled: yes
        state: started
        daemon_reload: yes

  handlers:
    - name: Reload systemd
      ansible.builtin.systemd_service:
        daemon_reload: yes

    - name: Reinit servicio
      ansible.builtin.systemd_service:
        name: "{{ app_name }}"
        state: restarted

En playbook.yml se indica la receta de forma declarativa a partir de tasks y handlers.
Para las variables (vars) se usan llaves dobles y la expresion o variable se incluye dentro.

El archivo para files/wdb.service consiste en configuración de servicio para inicio en Linux con systemd y no es parte de Ansible como tal pero ilustra sus capacidades.

ini
[Unit]
Description=WDB Service
After=network.target

[Service]
Type=simple
User=user
WorkingDirectory=/opt/wdb
ExecStart=/opt/wdb/wdb
Restart=always
RestartSec=3

LimitNOFILE=65535
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

Suponiendo que el binario es de Go, puedes generarlo con: GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o ./iac/dist/wdb .

Y para ejecutar Ansible se usan las siguientes sentencias:

bash
cd iac
ansible-playbook -i inventory.yml playbook.yml

La primera vez puede requerir confirmación host, y para las siguientes veces puede ser mas rápido usando: ansible-playbook -i inventory.yml playbook.yml --diff

Ansible simplifica así la automatización de infraestructura y despliegues, siendo ideal para Configuration Management, Application Deployment y Orchestration.