Manual Avanzado de DevOps

Integración de Ansible, Terraform y KVM con Scripts Bash

Introducción

Este manual cubre el uso avanzado de tres herramientas fundamentales en el mundo DevOps: Ansible para automatización de configuraciones, Terraform para infraestructura como código, y KVM para virtualización. Además, se incluyen scripts bash avanzados para integrar estas tecnologías.

Nota: Este manual asume que tienes conocimientos básicos de Linux, virtualización y conceptos de redes.

Ansible Avanzado

Ansible es una herramienta de automatización que simplifica la gestión de configuraciones, despliegue de aplicaciones y orquestración de tareas.

Instalación y Configuración Inicial

#!/bin/bash
# Instalación de Ansible en Ubuntu/Debian
sudo apt update
sudo apt install -y software-properties-common
sudo apt-add-repository --yes --update ppa:ansible/ansible
sudo apt install -y ansible

# Verificar instalación
ansible --version

# Configuración básica del archivo ansible.cfg
cat <<EOF > ~/ansible.cfg
[defaults]
inventory = ./inventory
host_key_checking = False
retry_files_enabled = False
EOF

Inventario Dinámico

Crear un inventario dinámico que se actualice automáticamente basado en instancias de AWS:

#!/bin/bash
# Script de inventario dinámico para AWS
#!/usr/bin/env python3

import boto3
import json
import argparse

def get_ec2_inventory():
    ec2 = boto3.resource('ec2')
    groups = {}

    for instance in ec2.instances.all():
        for tag in instance.tags or []:
            if tag['Key'] == 'Group':
                group_name = tag['Value']
                if group_name not in groups:
                    groups[group_name] = []
                groups[group_name].append(instance.public_ip_address)

    return groups

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('--list', action='store_true')
    args = parser.parse_args()

    if args.list:
        print(json.dumps(get_ec2_inventory()))

Playbooks Avanzados

Ejemplo de playbook con roles, handlers y templates:

---
- name: Configurar servidor web
  hosts: webservers
  become: yes
  vars:
    http_port: 80
    max_clients: 200
    server_name: example.com

  roles:
    - common
    - web

  tasks:
    - name: Instalar paquetes requeridos
      apt:
        name: "{{ item }}"
        state: present
        update_cache: yes
      loop:
        - nginx
        - php-fpm
        - mysql-client

    - name: Configurar Nginx
      template:
        src: templates/nginx.conf.j2
        dest: /etc/nginx/sites-available/{{ server_name }}
        owner: root
        group: root
        mode: '0644'
      notify:
        - restart nginx

  handlers:
    - name: restart nginx
      service:
        name: nginx
        state: restarted

Uso de Vault para Secrets

#!/bin/bash
# Crear archivo encriptado con Ansible Vault
ansible-vault create secrets.yml

# Editar archivo encriptado
ansible-vault edit secrets.yml

# Ejecutar playbook con archivo encriptado
ansible-playbook site.yml --ask-vault-pass

Terraform Avanzado

Terraform permite definir y provisionar infraestructura como código usando un lenguaje declarativo.

Configuración Básica

#!/bin/bash
# Instalar Terraform en Linux
wget https://releases.hashicorp.com/terraform/1.0.0/terraform_1.0.0_linux_amd64.zip
unzip terraform_1.0.0_linux_amd64.zip
sudo mv terraform /usr/local/bin/
terraform --version

Estructura de un Proyecto

mi-proyecto-terraform/
├── main.tf          # Configuración principal
├── variables.tf     # Variables de entrada
├── outputs.tf       # Valores de salida
├── terraform.tfvars # Valores de variables
└── modules/         # Módulos reutilizables
    └── vpc/         # Ejemplo de módulo VPC
        ├── main.tf
        ├── variables.tf
        └── outputs.tf

Ejemplo de Configuración AWS

# main.tf
provider "aws" {
  region = var.region
}

resource "aws_vpc" "main" {
  cidr_block           = var.vpc_cidr
  enable_dns_hostnames = true
  tags = {
    Name = "main-vpc"
  }
}

resource "aws_subnet" "public" {
  count             = length(var.public_subnets_cidr)
  vpc_id            = aws_vpc.main.id
  cidr_block        = var.public_subnets_cidr[count.index]
  availability_zone = var.azs[count.index]
  tags = {
    Name = "public-subnet-${count.index}"
  }
}

module "ec2_instance" {
  source  = "terraform-aws-modules/ec2-instance/aws"
  version = "~> 3.0"

  name           = "web-server"
  instance_count = 3
  ami            = var.ami_id
  instance_type  = "t3.micro"
  subnet_id      = aws_subnet.public[0].id
  tags = {
    Terraform   = "true"
    Environment = "dev"
  }
}

Workspaces y Backends Remotos

#!/bin/bash
# Crear y seleccionar workspace
terraform workspace new dev
terraform workspace select dev

# Configurar backend remoto en S3
cat <<EOF > backend.tf
terraform {
  backend "s3" {
    bucket         = "my-terraform-state-bucket"
    key            = "global/s3/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "terraform-locks"
    encrypt        = true
  }
}
EOF

Virtualización con KVM

Kernel-based Virtual Machine (KVM) es una solución de virtualización completa para Linux.

Instalación y Configuración

#!/bin/bash
# Instalar KVM en Ubuntu/Debian
sudo apt update
sudo apt install -y qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils virt-manager

# Agregar usuario a grupos necesarios
sudo usermod -aG libvirt $(whoami)
sudo usermod -aG kvm $(whoami)

# Verificar instalación
sudo systemctl status libvirtd
sudo virsh list --all

Creación de Máquinas Virtuales

Script avanzado para crear VMs automáticamente:

#!/bin/bash
# Script para crear múltiples VMs en KVM

# Variables configurables
VM_COUNT=3
VM_NAME_PREFIX="vm"
VM_RAM="2048"
VM_CPUS=2
VM_DISK_SIZE="20G"
VM_OS_TYPE="linux"
VM_OS_VARIANT="ubuntu20.04"
NETWORK="default"
ISO_PATH="/var/lib/libvirt/images/ubuntu-20.04.3-live-server-amd64.iso"

# Verificar requisitos
if ! command -v virt-install > /dev/null; then
    echo "virt-install no está instalado. Instale libvirt-clients."
    exit 1
fi

# Crear VMs
for i in $(seq 1 $VM_COUNT); do
    VM_NAME="${VM_NAME_PREFIX}${i}"
    DISK_PATH="/var/lib/libvirt/images/${VM_NAME}.qcow2"

    # Crear disco virtual
    qemu-img create -f qcow2 $DISK_PATH $VM_DISK_SIZE

    # Instalar VM
    virt-install \
        --name $VM_NAME \
        --memory $VM_RAM \
        --vcpus $VM_CPUS \
        --disk path=$DISK_PATH,size=$VM_DISK_SIZE \
        --os-type $VM_OS_TYPE \
        --os-variant $VM_OS_VARIANT \
        --network network=$NETWORK \
        --graphics none \
        --console pty,target_type=serial \
        --location $ISO_PATH \
        --extra-args "console=ttyS0,115200n8 serial" \
        --noautoconsole \
        --noreboot

    echo "VM $VM_NAME creada. Puedes iniciarla con: virsh start $VM_NAME"
done

Gestión de Redes

Crear una red puente (bridged network) para las VMs:

#!/bin/bash
# Crear red puente en KVM

# Detener el servicio de red
sudo systemctl stop NetworkManager

# Configurar interfaz de red
cat <<EOF | sudo tee /etc/sysconfig/network-scripts/ifcfg-br0
DEVICE=br0
TYPE=Bridge
BOOTPROTO=static
IPADDR=192.168.1.100
NETMASK=255.255.255.0
GATEWAY=192.168.1.1
DNS1=8.8.8.8
DNS2=8.8.4.4
ONBOOT=yes
DELAY=0
EOF

# Modificar interfaz física para usar el puente
cat <<EOF | sudo tee /etc/sysconfig/network-scripts/ifcfg-enp3s0
DEVICE=enp3s0
TYPE=Ethernet
BOOTPROTO=none
ONBOOT=yes
BRIDGE=br0
EOF

# Reiniciar servicios de red
sudo systemctl restart NetworkManager
sudo systemctl restart libvirtd

# Verificar la red puente
ip addr show br0
brctl show

Integración de Tecnologías

Combinar Ansible, Terraform y KVM para un flujo de trabajo completo de infraestructura como código.

Provisionar Infraestructura con Terraform y Configurar con Ansible

#!/bin/bash
# Script para provisionar infraestructura y configurarla automáticamente

# Paso 1: Inicializar y aplicar Terraform
echo "Inicializando Terraform..."
terraform init

echo "Aplicando configuración de Terraform..."
terraform apply -auto-approve

# Paso 2: Obtener IPs de las instancias creadas
echo "Obteniendo IPs de las instancias..."
INSTANCE_IPS=$(terraform output -json instance_ips | jq -r '.[]')

# Paso 3: Crear inventario dinámico para Ansible
echo "Creando inventario de Ansible..."
cat <<EOF > inventory
[webservers]
$INSTANCE_IPS

[webservers:vars]
ansible_user=ubuntu
ansible_ssh_private_key_file=~/.ssh/terraform.pem
EOF

# Paso 4: Ejecutar playbook de Ansible
echo "Ejecutando playbook de Ansible..."
ansible-playbook -i inventory playbook.yml

Crear VMs en KVM y Configurarlas con Ansible

#!/bin/bash
# Script para crear VMs en KVM y configurarlas con Ansible

# Paso 1: Crear VMs
echo "Creando VMs en KVM..."
./create_kvm_vms.sh

# Paso 2: Esperar a que las VMs obtengan IP
echo "Esperando a que las VMs arranquen..."
sleep 120

# Paso 3: Obtener IPs de las VMs
echo "Obteniendo IPs de las VMs..."
VM_IPS=$(virsh net-dhcp-leases default | grep ipv4 | awk '{print $5}' | cut -d'/' -f1)

# Paso 4: Crear inventario de Ansible
echo "Creando inventario de Ansible..."
cat <<EOF > inventory
[kvm_vms]
$VM_IPS

[kvm_vms:vars]
ansible_user=root
ansible_ssh_private_key_file=~/.ssh/id_rsa
EOF

# Paso 5: Ejecutar playbook de configuración
echo "Configurando VMs con Ansible..."
ansible-playbook -i inventory kvm_setup.yml

Scripts Bash Avanzados

Colección de scripts bash útiles para automatizar tareas complejas.

Monitorización de Recursos

#!/bin/bash
# Script para monitorear recursos del sistema y VMs

# Variables
THRESHOLD_CPU=80
THRESHOLD_MEM=80
THRESHOLD_DISK=85
LOG_FILE="/var/log/system_monitor.log"

# Función para loggear eventos
log_event() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> $LOG_FILE
}

# Monitorear CPU
check_cpu() {
    local cpu_usage=$(top -bn1 | grep "Cpu(s)" | sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | awk '{print 100 - $1}')
    if (( $(echo "$cpu_usage > $THRESHOLD_CPU" | bc -l) )); then
        log_event "ALERTA: Uso de CPU alto - ${cpu_usage}%"
    fi
}

# Monitorear memoria
check_memory() {
    local mem_total=$(free -m | awk '/Mem:/ {print $2}')
    local mem_used=$(free -m | awk '/Mem:/ {print $3}')
    local mem_usage=$((mem_used * 100 / mem_total))
    
    if [ $mem_usage -gt $THRESHOLD_MEM ]; then
        log_event "ALERTA: Uso de memoria alto - ${mem_usage}%"
    fi
}

# Monitorear disco
check_disk() {
    local disk_usage=$(df -h / | awk '/\// {print $5}' | tr -d '%')
    if [ $disk_usage -gt $THRESHOLD_DISK ]; then
        log_event "ALERTA: Uso de disco alto - ${disk_usage}%"
    fi
}

# Monitorear VMs KVM
check_vms() {
    local running_vms=$(virsh list --state-running | grep -v "Id\|---" | wc -l)
    local total_vms=$(virsh list --all | grep -v "Id\|---" | wc -l)
    
    if [ $running_vms -lt $total_vms ]; then
        log_event "ALERTA: No todas las VMs están corriendo ($running_vms/$total_vms)"
    fi
}

# Ejecutar checks
check_cpu
check_memory
check_disk
check_vms

Backup Automático de Configuraciones

#!/bin/bash
# Script para hacer backup de configuraciones importantes

# Configuración
BACKUP_DIR="/backup/configs"
DATE=$(date +%Y%m%d)
RETENTION_DAYS=30

# Directorios a respaldar
DIRS_TO_BACKUP=(
    "/etc/ansible"
    "/etc/libvirt"
    "/root/.terraform.d"
    "/etc/ssh"
)

# Crear directorio de backup si no existe
mkdir -p "$BACKUP_DIR/$DATE"

# Función para comprimir directorios
compress_dir() {
    local src=$1
    local dest="$BACKUP_DIR/$DATE/$(basename $src).tar.gz"
    tar -czf "$dest" "$src" >/dev/null 2>&1
    echo "Backup de $src completado: $dest"
}

# Hacer backup de cada directorio
for dir in "${DIRS_TO_BACKUP[@]}"; do
    if [ -d "$dir" ]; then
        compress_dir "$dir"
    else
        echo "Advertencia: $dir no existe, omitiendo..."
    fi
done

# Limpiar backups antiguos
find "$BACKUP_DIR" -type d -mtime +$RETENTION_DAYS -exec rm -rf {} \;
echo "Backups antiguos (más de $RETENTION_DAYS días) eliminados"