Terraform DigitalOcean

Ésta utilidad nos permite gestionar un negocio de Cloud Contact Center as a Service. Es decir, que podemos desde un único deployer, administrar múltiples instancias de OMniLeads asociadas a diferentes operaciones de Contact Center. A su vez, cuenta con la facilidad para redimensionar cualquier componente del despliegue, ya sea a la hora de escalar o contraer la cantidad de usuarios demandados por cada cliente del SaaS, así como también administrar el aprovisionamiento de actualizaciones desde el enfoque de la infraestructura inmutable.

El código que implementa nuestro deployer, se encuentra en GitLab. Por lo tanto, lo primero que debemos hacer es traernos el repositorio:

git clone --recurse-submodules https://gitlab.com/omnileads/terraform-digitalocean.git

Pre-requisitos

Nuestro deployer, requiere en primera instancia que contemos con:

  • Una cuenta de DigitalOcean: Contar con un usuario capaz de generar recursos en la nube del proveedor.
  • Una clave SSH disponible en nuestra cuenta: Se debe subir una clave SSH, para luego poder asignar a cada VM creada y así ingresar vía SSH a cada Linux host de manera segura.
  • Un token para acceder a la API del proveedor: El token es necesario para poder autenticarse contra la API del proveedor.
  • Un user_key y secret_key para interactuar con SPACES: «Spaces» es el nombre del object storage S3 compatible. Para interactuar con el mismo, se debe generar un id y clave.
  • Un dominio propio, cuyos DNSs apunten hacia los de DigitalOcean: El dominio es utilizado por Terraform a la hora de generar el URL y sus certificados SSL, de manera tal que al invocar dicha URL, resuelva la petición sobre el load-balancer de la instancia. Por lo tanto, se debe configurar en su proveedor del dominio, un redireccionamiento hacia los DNSs de DigitalOcean.

Links de interés:

git clone https://your_tenants_repo_track.git.com instances

El directorio debe llamarse exactamente instances.

Configuración del deployer

Para comenzar a trabajar con nuestros clientes del SaaS, debemos contar con 2 utilidades: Terraform y s3cmd. Dichas herramientas, podrían ser instaladas en MAC, Windows o Linux. Sin embargo, nuestro repositorio contiene un script para ejecutar un container Docker con todo instalado y listo para comenzar a utilizar.

Para lanzar el contenedor deployer, debemos antes generar el archivo .env con una serie de variables:

cp .env_template .env

Una vez generado nuestro archivo, debemos asignar valores a nuestras variables. Por ejemplo:

TF_VAR_ssh_key_fingerprint=
TF_VAR_digitalocean_token=
TF_VAR_spaces_secret_key=
TF_VAR_spaces_key=
TF_VAR_spaces_url=
TF_VAR_domain_name=
TF_VAR_region=

Luego, debemos generar y editar el archivo .s3cfg disponible en la raíz del repositorio:

cp .s3cfg_template .s3cfg
access_key =
host_base =
host_bucket = %(bucket)s.change_me_for_spaces_url
secret_key =

Aquí, se repiten los valores del archivo .env, sólo que cambian los nombres. La relación es: access_key se corresponde con TF_VAR_spaces_key, host_base se corresponde con spaces_url pero quitando la cadena https://, en el parámetro host_bucket se deberá reemplazar la cadena change_me_for_spaces_url por lo mismo que asignamos a host_base, y finalmente scret_key debe contener el mismo valor que pusimos en TF_VAR_spaces_secret_key.

Una vez ajustadas todas las variables, lanzamos nuestro container:

./run_terraform_docker.sh

Éste comando, nos devolverá un prompt que corresponde al container, y donde además se accede desde allí a toda la estructura del repositorio:

_images/install_terraform_run_docker.png

Desde nuestro container, podemos realizar todas las acciones necesarias sobre cada tenant administrado.

Gestión de tenants: deploy

Una vez configurado nuestro deployer, ya podemos comenzar a gestionar nuestras instancias de OMniLeads.

  • Inicializar un tenant:

Para preparar un nuevo tenant se debe correr el siguiente comando:

make init ENV=nombre_de_cliente_referencial DIALER=YES|NO

Como se puede observar, cuando se lanza el comando de inicialización de entorno de nuevo cliente del SaaS, los argumentos necesarios son:

  • ENV: Éste parámetro implica el nombre de referencia que vamos a utilizar para denominar a nuestra instancia de OML. Es el nombre que tomarán los recursos como VM, load-balancer, cluster de PostgreSQL, etc.
  • DIALER: Con éste parámetro, indicamos si el despliegue incluye al componente WombatDialer y su backend DB MySQL. Si la nueva operación no requiere de campañas con discador predictivo, entonces tenemos la posibilidad de ahorrar los recursos correspondientes a dicha funcionalidad.

El comando make init se encarga de generar el directorio $ENV dentro de instances, es decir que luego de la ejecución vamos a encontrar dentro del directorio instances, un nuevo directorio con el nombre que hemos utilizado como ENV.

_images/install_terraform_make_init.png

Además, se genera el bucket de SPACES que será utilizado para almacenar el archivo tfstate y las grabaciones de las llamadas correspondientes a nuestro nuevo tenant.

_images/install_terraform_make_init_bucket.png
  • Ajustar variables del despliegue:

En este punto, nos toca definir los tamaños de las instancias Linux que alojarán los diferentes componentes. Para ellos nos movemos hasta el nuevo directorio generado con el make init, y allí editamos el archivo vars.auto.tfvars.

 ## SIZING VARS ## SIZING VARS ## SIZING VARS
 ## SIZING VARS ## SIZING VARS ## SIZING VARS
 # OMLapp component droplet size
 droplet_oml_size = "s-2vcpu-4gb"
 # Asterisk component droplet size
 droplet_asterisk_size = "s-1vcpu-1gb"
 # RTPengine componenet droplet size
 droplet_rtp_size = "s-1vcpu-1gb"
 # REDIS component droplet size
 droplet_redis_size = "s-1vcpu-1gb"
 # Wombat dialer component droplet size
 droplet_dialer_size = "s-1vcpu-2gb"
 droplet_mariadb_size = "s-1vcpu-1gb"
 # Kamailio component droplet size
 droplet_kamailio_size = "s-1vcpu-1gb"
 # Websocket component droplet size
 droplet_websocket_size = "s-1vcpu-1gb"
 # HAproxy component droplet size
 pgsql_size = "db-s-1vcpu-2gb"
 cluster_db_nodes = "1"

Usted podrá definir el tamaño en términos de CPU y memoria RAM de cada VM en dicha sección del archivo nombrado.
# ********************* OMniLeads App variables
# Asterisk SIP Trunks allowed ips
sip_allowed_ip = ["190.19.150.8/32"]
# Time Zone to apply on Django
oml_tz = "America/Argentina/Cordoba"


# Asterisk AMI USER for OMLApp manager connections
ami_user = "omnileadsami"
# Asterisk AMI PASS for AMI USER OMLApp manager connections
ami_password = "5_MeO_DMT"
# Wombat API user to login from OMLapp
dialer_user = "demoadmin"
# Wombat API password to login from OMLapp
dialer_password = "demo"
# PGSQL database name
pg_database = "omnileads"
# PGSQL username for OMLapp
pg_username = "omnileads"
# PGSQL password for OMLapp
pg_password = "098098ZZZ"
# Session cookie age
sca = "3600"
init_environment = "false"

# Wombat dialer Component vars
wombat_database = "wombat"
wombat_database_username = "wombat"
wombat_database_password = "admin123"

También, debemos ajustar las Variables de instalación del componente OMLApp. No se listan todas, ya que algunas de ellas son aprovisionadas por el propio Terraform, como es el caso de las variables _host.

  • Comprobar integridad:

El comando make plan, nos sirve de ayuda para comprobar la integridad de nuestro código de deploy.

make plan ENV=nombre_de_cliente
_images/install_terraform_make_plan.png
  • Aplicar despliegue:

El comando make apply, acciona la aplicación del deploy sobre nuestro proveedor. Puede durar entre 5 a 10 minutos hasta finalizar la creación de todos los recursos de infraestructura, para luego lanzar la instalación de cada componente, tomando alrededor de 30 minutos para comenzar a operar con nuestra URL (https://nombre_del_tenant.su_dominio).

make apply ENV=nombre_de_cliente
_images/install_terraform_make_apply.png _images/install_terraform_make_apply_fin.png

Una vez finalizada la creación de los recursos, se avanza con el deploy de los componentes de software de OMniLeads sobre dichos recursos.

_images/install_terraform_make_apply_resources.png

Finalmente, nuestra URL de cliente estará disponible para comenzar a operar.

_images/install_terraform_make_apply_url.png
  • Commit y push de nuestro nuevo cliente sobre el repositorio de tenants:

Como se introdujo más arriba la carpeta instances es donde nuestro deployer ubica el código/configuración pertinente a cada tenant de nuestro SaaS, como se trata de un repositorio Git, debemos generar un commit de manera tal que el equipo de DevOps que se encarga de la gestión del SaaS disponga de los cambios realizados por cualquier miembro del equipo.

_images/install_terraform_git_tenant.png

Nota

Por supuesto que nuestro repositorio contenedor de código de tenants tiene que ser privado!

_images/install_terraform_git_repo.png

Almacenamiento de grabaciones y backups

Una de las ventajas que posee trbajar en la nube es el hecho de utilizar la tecnología S3 - object storage para almacenar grandes volumenes de datos. En el caso que nos compete serían grabaciones de llamadas y backups automáticos generados a partir de tareas programadas.

Nota

Por defecto el deploy de los componentes Asterisk y OMLApp genera un CRON que se ejecuta a las 23:50 todos los días para correr un proceso de backup que es alojado en la raíz del Bucket donde además se almacenan las grabaciones de llamadas.

Gestión de tenants: actualizaciones

Al estar trabajando bajo el concepto de infraestructura inmutable, el proceso de actualización se considera como un despliegue de una nueva versión de la App, por lo tanto el proceso implica que las instancias EC2 candidatas a ser actualizadas en realidad serán destruidas y en su lugar se lanzarán nuevas instancias a las cuales se les aprovisionará la versión del componente indicada como actualización en el archivo de variables de cada tenant.

Importante

A la hora del deploy de la nueva versión en el nuevo EC2, el proceso de instalación comprueba variables orientadas al restore del backup correspondiente. Por lo que es importante ejecutar un backup manualmente antes del proceso de actualización, en caso de que el backup nocturno generado de manera automática no contenga los últimos cambios. Si ese es el caso, lo remitimos a la sección de actualizaciones.

Vamos a asumir que se utilizan los backups de Asterisk y OMLApp auto generados por el CRON. Entonces simplemente debemos ubicar el nombre de cada archivo, ya que debe ser indicado en las variables del tenant antes disparar el procedimiento.

Pasamos entonces a modificar la versión de cada componente (OMLApp, Asterisk, Kamailio ó Redis) que se desea actualizar, luego indicar como true la auto restauración de backups y además indicar el nombre del backup de Asterisk y OMLApp. Todo esto dentro del archivo tenant.auto.tfvars:

# Braches release to deploy
oml_app_branch          ="release-1.19.0"
oml_redis_branch        ="210714.01"
oml_kamailio_branch     ="210714.01"
oml_acd_branch          ="210802.01"

# Backup/Restore params
oml_auto_restore        = "true"
oml_app_backup_filename = "211201-115100-oml-backup"
oml_acd_backup_filename = "211201-145223-oml-backup"

reset_admin_pass        = "false"

Nota

Tomar en cuenta que el nombre de los archivos de backup no contienen la extensión .tar.gz. Recordar llevar a false los parámetros que blanquean la password de admin.

Una vez ajustado el archivo, se procede con un make plan y si no se presentan problemas se prosigue con un make apply. Este último se encargará de destruir las instancias Linux que poseen versiones divergentes respecto a lo provisto en el archivo de variables, para luego recrear dichas instancias y aprovisionar la instalación de cada componente sobre la versión deseada.

El hecho de contar con PostgreSQL sobre un cluster del proveedor Cloud y las grabaciones sobre un Bucket-S3, nos permite operar bajo este concepto de infraestructura inmutable con la ventaja de olvidarnos de los procedimientos de actualizaciones basados en paquetes y dependencias.

Gestión de tenants: re-sizing

A la hora de redimensionar un tenant, simplemente debemos ajustar el archivo de variables:

droplet_oml_size = "s-2vcpu-4gb"
droplet_asterisk_size = "s-1vcpu-1gb"
droplet_rtp_size = "s-1vcpu-1gb"
droplet_redis_size = "s-1vcpu-1gb"
droplet_kamailio_size = "s-1vcpu-1gb"
droplet_websocket_size = "s-1vcpu-1gb"
pgsql_size = "db-s-1vcpu-2gb"
cluster_db_nodes = "1"
droplet_dialer_size = "s-1vcpu-2gb"
droplet_mariadb_size = "s-1vcpu-1gb"

Seleccionamos el tamaño de instancia para cada componente, guardamos cambios y simplemente como siempre debemos lanzar un make plan y si no se presentan errores proseguir con el make apply para impactar los cambios sobre los recursos.

Gestión de tenants: destroy

Con el comando make destroy procedemos con la destrucción de nuestro tenant. Todos los recursos de infraestructura serán destruidos. No obstante es menester dejar vacío el bucket de grabaciones y logs ya que el procedimiento de destrucción fallará si los buckets contienen información. Este comportamiento responde al hecho de prevenir pérdida de datos valiosos.

make destroy ENV=nombre_de_cliente
_images/install_terraform_aws_make_destroy.png _images/install_terraform_aws_make_destroy_2.png