Implementación de Arquitectura HA con Ansible: Nginx, Tomcat y Keepalived

La automatización de infraestructuras críticas requiere herramientas robustas que garanticen consistencia y alta disponibilidad. A continuación, se describe el procedimiento para desplegar un cluster web utilizando Ansible, integrando Nginx como balanceador de carga, Tomcat para la ejecución de aplicaciones Java y Keepalived para la gestión de IPs virtuales (VIP).

Estructura de Directorios del Proyecto

La organización de los roles sigue el estándar de Ansible, separando claramente las tareas, variables, plantillas y archivos estáticos para cada componente.


roles/
├── keepalived
│   ├── files
│   ├── handlers
│   │   └── main.yml
│   ├── tasks
│   │   └── main.yml
│   ├── templates
│   │   ├── keepalived_master.cfg.j2
│   │   └── keepalived_backup.cfg.j2
│   └── vars
│       └── main.yml
├── nginx
│   ├── files
│   │   ├── nginx-source.tar.gz
│   │   └── nginx_unit.service
│   ├── handlers
│   │   └── main.yml
│   ├── tasks
│   │   └── main.yml
│   ├── templates
│   │   └── nginx_main.conf.j2
│   └── vars
│       └── main.yml
├── tomcat
│   ├── files
│   │   ├── jdk_installer.gz
│   │   └── tomcat_binary.tar.gz
│   ├── handlers
│   │   └── main.yml
│   ├── tasks
│   │   └── main.yml
│   ├── templates
│   │   ├── env_java.sh.j2
│   │   ├── catalina_env.sh.j2
│   │   └── tomcat_unit.service.j2
│   └── vars
│       └── main.yml
└── site_playbook.yml

Playbook Principal de Despliegue

El archivo site_playbook.yml orquesta la ejecución de los roles sobre los grupos de inventario definidos. Se separan los nodos balanceadores de los servidores de aplicación.


---
- name: Despliegue de Balanceadores
  hosts: balanceadores
  become: true
  roles:
    - nginx
    - keepalived

- name: Despliegue de Servidores de Aplicación
  hosts: aplicacion
  become: true
  roles:
    - tomcat

Configuración del Rol Nginx

Este rol se encarga de compilar Nginx desde el código fuente e integrar la configuración de balanceo hacia los backend.

Tareas Principales (tasks/main.yml)


- name: Instalar dependencias de compilación
  ansible.builtin.package:
    name: "{{ paquetes_compilacion }}"
    state: installed

- name: Extraer código fuente de Nginx
  ansible.builtin.unarchive:
    src: nginx-source.tar.gz
    dest: /tmp/
    creates: /tmp/nginx-{{ version_nginx }}

- name: Compilar e instalar Nginx
  ansible.builtin.shell: |
    ./configure --prefix={{ ruta_instalacion_nginx }} --with-http_ssl_module
    make && make install
  args:
    chdir: /tmp/nginx-{{ version_nginx }}
  tags:
    - compilar

- name: Desplegar unidad systemd
  ansible.builtin.copy:
    src: nginx_unit.service
    dest: /etc/systemd/system/nginx.service

- name: Recargar daemon de systemd
  ansible.builtin.systemd:
    daemon_reload: true

- name: Generar configuración principal
  ansible.builtin.template:
    src: nginx_main.conf.j2
    dest: {{ ruta_instalacion_nginx }}/conf/nginx.conf
  notify:
    - reiniciar_nginx

- name: Habilitar e iniciar servicio
  ansible.builtin.service:
    name: nginx
    state: started
    enabled: true

Manejadores (handlers/main.yml)


- name: reiniciar_nginx
  ansible.builtin.service:
    name: nginx
    state: reloaded

Variables (vars/main.yml)


version_nginx: "1.16.0"
ruta_instalacion_nginx: "/opt/nginx"
paquetes_compilacion:
  - gcc
  - openssl-devel
  - zlib-devel
  - pcre-devel
backend_1: "192.168.10.5:8080"
backend_2: "192.168.10.6:8080"

Plantilla de Configuración (templates/nginx_main.conf.j2)


worker_processes  {{ ansible_processor_vcpus }};

events {
    worker_connections  2048;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  70;

    upstream cluster_tomcat {
        server {{ backend_1 }};
        server {{ backend_2 }};
    }

    server {
        listen       80;
        server_name  _;
        location / {
            proxy_pass http://cluster_tomcat;
            proxy_set_header Host $host;
        }
    }
}

Configuración del Rol Tomcat

Este rol prepara el entorno Java y despliega el contenedor de servlets, configurando las variables de entorno necesarias para su ejecución como servicio.

Tareas Principales (tasks/main.yml)


- name: Descomprimir JDK
  ansible.builtin.unarchive:
    src: jdk_installer.gz
    dest: /opt/

- name: Crear enlace simbólico Java
  ansible.builtin.file:
    src: /opt/jdk1.8.0_144
    path: {{ ruta_java_home }}
    state: link

- name: Configurar variables de entorno globales
  ansible.builtin.template:
    src: env_java.sh.j2
    dest: /etc/profile.d/java_env.sh

- name: Descomprimir Tomcat
  ansible.builtin.unarchive:
    src: tomcat_binary.tar.gz
    dest: /opt/

- name: Crear enlace simbólico Tomcat
  ansible.builtin.file:
    src: /opt/apache-tomcat-8.5.37
    path: {{ ruta_tomcat_home }}
    state: link

- name: Ajustar script de clase Java
  ansible.builtin.template:
    src: catalina_env.sh.j2
    dest: {{ ruta_tomcat_home }}/bin/setclasspath.sh

- name: Instalar unidad systemd para Tomcat
  ansible.builtin.template:
    src: tomcat_unit.service.j2
    dest: /etc/systemd/system/tomcat.service

- name: Activar e iniciar Tomcat
  ansible.builtin.service:
    name: tomcat
    state: started
    enabled: true

Variables (vars/main.yml)


ruta_java_home: "/opt/java"
ruta_tomcat_home: "/opt/tomcat"

Servicio Systemd (templates/tomcat_unit.service.j2)


[Unit]
Description=Servidor de Aplicaciones Apache Tomcat
After=network.target

[Service]
Type=forking
Environment=JAVA_HOME={{ ruta_java_home }}
ExecStart={{ ruta_tomcat_home }}/bin/startup.sh
ExecStop={{ ruta_tomcat_home }}/bin/shutdown.sh
User=root

[Install]
WantedBy=multi-user.target

Configuración del Rol Keepalived

Keepalived gestiona la IP flotante. La configuración diferancia entre nodo maestro y respaldo mediante variables dinámicas.

Tareas Principales (tasks/main.yml)


- name: Instalar paquete Keepalived
  ansible.builtin.package:
    name: keepalived
    state: installed

- name: Desplegar configuración según rol
  ansible.builtin.template:
    src: "{{ archivo_configuracion_keepalived }}"
    dest: /etc/keepalived/keepalived.conf
  notify:
    - reiniciar_keepalived

- name: Asegurar estado del servicio
  ansible.builtin.service:
    name: keepalived
    state: started
    enabled: true

Variables Condicionales (vars/main.yml)

Se utiliza una variable tipo_nodo_ha definida en el inventario para seleccionar la plantilla adecuada.


vip_flotante: "192.168.10.100"
id_router_maestro: "MASTER_NODE"
id_router_respaldo: "BACKUP_NODE"
prioridad_maestro: 100
prioridad_respaldo: 90

Plantilla Maestro (templates/keepalived_master.cfg.j2)


vrrp_instance VI_Cluster {
    state MASTER
    interface {{ ansible_default_ipv4.alias }}
    virtual_router_id 51
    priority {{ prioridad_maestro }}
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass secret_ha
    }
    virtual_ipaddress {
        {{ vip_flotante }}
    }
}

Plantilla Respaldo (templates/keepalived_backup.cfg.j2)


vrrp_instance VI_Cluster {
    state BACKUP
    interface {{ ansible_default_ipv4.alias }}
    virtual_router_id 51
    priority {{ prioridad_respaldo }}
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass secret_ha
    }
    virtual_ipaddress {
        {{ vip_flotante }}
    }
}

Manejadores (handlers/main.yml)


- name: reiniciar_keepalived
  ansible.builtin.service:
    name: keepalived
    state: restarted

Etiquetas: Ansible Nginx tomcat Keepalived alta-disponibilidad

Publicado el 10-6 04:16