Terraform AWS

La instalación de OMniLeads para AWS nos permite gestionar un negocio de Cloud Contact Center as a Service. Es decir que podemos administrar múltiples instancias de OMniLeads asociadas a diferentes suscriotores/operaciones de Contact Center. A su vez se 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 la aprovisión 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-aws.git

Pre-requisitos

Es indispensable contar con cada uno de los items listados a continuación:

  • Una cuenta en Amazon Web Services

  • Un usuario con acceso programático (access_key & secret key)

  • Una clave SSH RSA pub disponible para asociar a AWS

  • Adquirir un dominio público a través de por ejemplo: AWS-Route53

    El dominio es utilizado por Terraform a la hora de generar cada URL de cliente y su certificado SSL, de manera tal que al invocar dicha URL se resuelva la petición sobre la instancia de OMniLeads correspondiente a dicho tenant.

  • Generar un nuevo directorio llamado *instances* en la raíz del repositorio

    Idealmente debería ser a partir de clonar un repositorio sobre el cual trabajaremos a nivel GIT cada tenant gestionado. (Más adelante volveremos sobre esto).

    cd terraform-aws
    git clone https://your_tenants_repo instances
    

    Nota

    El directorio DEBE llamarse exactamente instances

Configuración del deployer

Para comenzar a trabajar con nuestros clientes del SaaS debemos contar Terraform y aws-cli instalado, estas utilidades pueden correr en MAC, Windows o Linux, sin embargo nuestro repositorio continiene 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 las siguientes variables:

# Container variables
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=

# Variables for terrafom
TF_VAR_domain_name=your_public_domain
TF_VAR_aws_region=your_aws_region
TF_VAR_pstn_trunks=["X.X.X.X/32"]
TF_VAR_shared_env=shared-common-infra-name
TF_VAR_s3_access_key=
TF_VAR_s3_secret_key=
TF_VAR_aws_ssh_key=

Una vez ajustadas todas las variables, lanzamos el container deployer:

Este comando nos devolverá un promp dentro del container, además se accede desde allí a toda la estructura del repositorio:

_images/install_terraform_run_docker.png

Desde nuestro container vamos a realizar todas las acciones necesarias sobre cada tenant administrado así como también sobre la infraestructura de networking, almacenamiento y componentes común a cada tenant.

Nota

Vamos a volver sobre la variable TF_VAR_shared_env más adelante.

Organización del código Terraform

Antes de avanzar con la gestión de infraestructura común y tenants, vamos a aclarar la estructura del código Terraform.

Infraestructura shared

Por un lado se contiene el código que despliega la infraestructura compartida (de ahora en más: shared) por todas las instancias de OMniLeads de cada cliente (de ahora en más: tenant), es decir:

  • Networking: VPC, IGW, NAT-GW, sub-red publica y privada, grupos de seguridad, etc.
  • Componentes compartidos de OMniLeads: RTPengine y Asterisk PSTN-Gateway con ip publica Fija.
_images/install_terraform_aws_shared_infra.png

La matriz de código Terraform que implementa la infraestructura shared se puede inspeccionar dentro de la carpeta hcl_template/shared

_images/install_terraform_aws_shared_infra_code.png

Infraestructura tenant

Por otro lado tenemos el código que materializa cada instancia de la App destinada para cada Tenant suscripto a nuestro SaaS:

  • Instancias EC2 para cada componente de la App (Redis, Django, Asterisk, Kamailio y opcionalmente Wombat Dialer)
  • Instancia de RDS PosgreSQL
  • Bucket AWS-S3 para almacenar grabaciones y logs
  • Balanceadores de carga
_images/install_terraform_aws_tenant_infra.png

Importante

Tener en cuenta que hay dos componentes que se administran utilizando auto-scalling group de AWS, estos son OMLapp y Wombat Dialer. Mientras que kamailio, asterisk y redis son simplemente instancias de EC2 ordinarias.

La matriz de código Terraform que implementa la infraestructura tenant se puede inspeccionar dentro de la carpeta hcl_template/shared

_images/install_terraform_aws_tenant_infra_code.png

Nota

Por defecto se despliega dentro de la infraestructura shared una instancia de Asterisk puro, de manera tal que pueda ser opcionalmente utilizado como un gateway de borde con una IP pública fija, ya que el enfoque de infraestructura inmutable que se aplica para los despliegues de los componentes de tenant implica que la IP del componente Asterisk de OMniLeads cambie cada vez que hay una actualición al destruirse la instancia EC2 y lanzar una nueva en cada actualizacion. Muchos proveedores SIP exigen direcciones IP públicas fijas para otorgar un troncal, por eso la razón de ser de dicho Asterisk shared

Gestión de infraestructura Shared

La infraestructura shared se despliega en una determinada Region de AWS (por ej: us-east-1) por única en vez al momento de comenzar nuestro negocio de CCenter as a Service, ya que como se introdujo se trata de los componentes en común utilizados luego por cada una de las instancias de OMniLeads destinadas a cada nuevo Tenant que vayamos dando de alta como suscriptor.

Nota

Debemos gestionar un despliegue shared por cada región del mundo en donde luego querramos desplegar tenants.

A continuación los pasos necesarios para llevar a cabo el deploy de la infraestructura shared.

  • Lanzar el container

En la raíz del repositorio lanzar el script run_terraform.sh

./run_terraform.sh
  • Inicializar entorno shared

En este punto se debe considerar un condicionamiento respecto al nombre permitido para asignarle a la vairbale ENV que se utiliza como argumento a la hora de indicar una inicialización de un nuevo entorno. El nombre debe empezar con la cadena shared, por ejemplo sharedinfras:

make init ENV=shared-infras

Importante

La cadena asignada como parámetro ENV debe comenzar con la palabra shared y NO se permiten caracteres especiales NI TAMPOCO «- ó _»

Luego de finalizar la ejecución del comando, se dispone de una nueva carpeta bajo el directorio instances llamada con el nombre asignado como parámtro ENV. Bajo esa carpeta encontraremos el código terraform que despliega la infraestructura shared.

  • Ajustar variables

Dentro de la nueva carpeta tendremos un archivo de variables que debemos repasar y ajustar. Entre los componentes shared existen RTPengine y Asterisk-PSTNGW que son instancias EC2 dentro de la subred pública, las variables disk_size y ec2_size corresponden al tamaña de disco EBS y tamaño de instancia.

# AstSBC  variables
disk_size_astsbc        = 50
ec2_size_astsbc         = "t3.small"

# RTPengine  variables
disk_size_rtpengine     = 40
ec2_size_rtpengine      = "t3.small"
  • Disparar el deploy de la infraestructura

Ahora si podemos disparar un plan y posteriormente un apply para desplegar nuestra infraestructura.

make apply ENV=shared-infras

Una vez finalizado el procedimiento, deberíamos observar una salida similar a:

_images/install_terraform_aws_shared_infra_deployed.png

Usted podrá comprobar toda la infraestructura generada a través de su interfaz web de AWS.

Gestión de tenants: deploy

Una vez desplegada la infraestructura shared, podemos comenzar a gestionar tenants bajo suscripción. Para ello debemos inicializar, ajustar variables, planificar y finalmente desplegar la instancias de OMniLeads asignada como nuevo Tenant.

Nota

Es impresindible asegurarse de que la variable de entorno TF_VAR_shared_env del container deployer posea el valor correcto de acuerdo al nombre utilizado en el despliegue de la infraestructura shared sobre la cual se desea desplegar el nuevo Tenant

  • Inicializar un tenant:

    Para preparar un nuevo tenant se debe correr el comando:

    make init ENV=nombre_de_cliente 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: este parámetro implica al nombre de referencia que vamos a utilizar para denominar a nuestra instancia de OML. Es el nombre que tomarán los recursos como VM, loadbalancer, cluster de postgres, etc.
    • DIALER: con este parámetro indicamos si el despliegue incluye al componente Wombat dialer 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 donde residirá el código * Terraform* asociado a este neuvo tenant, dentro de instances. Es decir que luego de la ejecución vamos a disponer dentro del directorio instances un nuevo directorio con el nombre que hemos utilizado para el parámetro ENV.

    Importante

    El nombre asignado al parámetro ENV, NO debe contener el caracter «-«.

  • Ajustar variables del despliegue

    En este punto nos toca definir los tamaños de las instancias EC2 que alojarán los diferentes componentes, así como también el cluster pgsql RDS. Para ellos nos movemos hasta el nuevo directorio generado con el make init y allí editamos el archivo tenant.auto.tfvars.

    ## SIZING VARS ## SIZING VARS ## SIZING VARS
    # Components ec2 size
    ec2_oml_size          = "t2.medium"
    ec2_asterisk_size     = "t2.micro"
    ec2_redis_size        = "t2.micro"
    ec2_kamailio_size     = "t2.micro"
    pg_rds_size           = "db.t3.micro"
    

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.

# 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"

# Customer variables
ami_user                = "omnileadsami"
ami_password            = "5_MeO_DMT"
pg_database             = "chanaes_oml"
pg_username             = "chanaes_pg"
pg_password             = "admin123"
ECCTL                   = "28800"
SCA                     = "3600"
TZ                      = "America/Argentina/Cordoba"

# Wombat Dialer variables used if DIALER=yes if DIALER=no these variables doesn't care
mysql_rds_size          = "db.t3.micro"
ec2_dialer_size         = "t2.micro"
dialer_user             = "demoadmin"
dialer_password         = "demo"
mysql_database          = "wombat"
mysql_password          = "admin123"
wombat_version          = "20.02.1-271"
  • Comprobar integridad:

    El comando make plan nos sirve de ayuda para comprobar la integridad de nuestro deploy:

    make plan ENV=nombre_de_cliente
    
    _images/install_terraform_aws_tenant_make_plan.png

Si el plan no arrojó errores, entonces estamos listos para ejecutar un apply !

  • Aplicar despliegue:

    El comando make apply dispara la ejecución del deploy de nuestra instancia/tenant. 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 como alrededor 30 minutos para comenzar a operar con nuestra URL: https://nombre_del_tenant.su_dominio.

    make apply ENV=nombre_de_cliente
    
    _images/install_terraform_aws_tenant_make_apply.png

Como podemos visualizar, el make apply nos solicita introducir dos parámetros (init_environment y reset_admin_pass):

var.init_environment
Enter a value:

var.reset_admin_pass
Enter a value:

ambas variables explicadas aquí Variables de instalación del componente OMLApp

_images/install_terraform_aws_make_apply_fin.png

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

_images/install_terraform_aws_make_apply_resources.png

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

_images/install_terraform_aws_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 donde nuestro deployer ubica el código y configuración pertinente a cada cliente de nuestro SaaS es un repositorio Git. Por lo tanto debemos generar un commit hacia nuestro repositorio de tenants de manera tal que el equipo de DevOps que se encarga de la gestión de nuestro SaaS, disponga de los cambios realizados por cualquier miembro del team.

    _images/install_terraform_git_tenant.png _images/install_terraform_git_repo.png

    Nota

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

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.17.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.

Importante

Como las instancias de wombat dialer y OMLApp están basadas en auto-scalling group, para que la actualización se termine de materializar debemos ejecutar un terminate manualmente desde la interfaz web de admistración AWS.

_images/install_terraform_aws_upgrade_terminate.png

Gestión de tenants: re-sizing

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

# OMLapp component ec2 size
ec2_oml_size            = "t2.medium"
# Asterisk component ec2 size
ec2_asterisk_size       = "t2.micro"
# REDIS component ec2 size
ec2_redis_size          = "t2.micro"
# Wombat dialer component ec2 size
ec2_dialer_size         = "t2.micro"
# Kamailio component ec2 size
ec2_kamailio_size       = "t2.micro"
# PGSQL component digitalocean-cluster size
pg_rds_size             = "db.t3.micro"

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