Terraform AWS¶
La instalación de OMniLeads para AWS nos permite gestionar un negocio de 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:
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.
La matriz de código Terraform que implementa la infraestructura shared se puede inspeccionar dentro de la carpeta hcl_template/shared
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
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
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 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 # OMLapp component ec2 size ec2_oml_size = "t2.medium" customer_root_disk_type = "standard" customer_root_disk_size = 20 ebs_volume_size = 10 # Asterisk component ec2 size ec2_asterisk_size = "t2.micro" asterisk_root_disk_size = 50 # REDIS component ec2 size ec2_redis_size = "t2.micro" # Kamailio component ec2 size ec2_kamailio_size = "t2.micro" kamailio_root_disk_size = 25 # Websockets component ec2 size ec2_websockets_size = "t2.micro" websockets_root_disk_size = 25 # RDS PGSQL cluster size 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.24.0" oml_redis_branch = "210714.01" oml_kamailio_branch = "210714.01" oml_acd_branch = "210802.01" oml_websockets_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
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
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
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.
Finalmente nuestra URL de cliente estará disponible para comenzar a operar.
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.
Nota
Por supuesto que nuestro repositorio contenedor de código de tenants tiene que ser privado!
Gestión de tenants: actualizaciones¶
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, asi como tambien audios o musica en espera subida a traves de los modulos de omnileads, por lo que cada instancia EC2 simplemente se aprovisiona con variables de entorno y comienza a funcionar, ya que las bases de datos y archivos importantes se encuentran persistidos y alcanzables a nivel TCP/IP.
Esto nos permite abrazar 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.
Pasamos entonces a modificar la versión de cada componente (OMLApp, Asterisk, Kamailio ó Redis) que se desea actualizar: Todo esto dentro del archivo tenant.auto.tfvars:
# Braches release to deploy
oml_app_branch = "release-1.25.0"
oml_redis_branch = "210714.01"
oml_kamailio_branch = "210714.01"
oml_acd_branch = "210802.01"
oml_websockets_branch = "210802.01"
reset_admin_pass = "false"
Nota
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.
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.
Gestión de tenants: re-sizing¶
A la hora de redimensionar un tenant, simplemente debemos ajustar el archivo de variables:
## SIZING VARS ## SIZING VARS ## SIZING VARS
# OMLapp component ec2 size
ec2_oml_size = "t2.medium"
customer_root_disk_type = "standard"
customer_root_disk_size = 20
ebs_volume_size = 10
# Asterisk component ec2 size
ec2_asterisk_size = "t2.micro"
asterisk_root_disk_size = 50
# REDIS component ec2 size
ec2_redis_size = "t2.micro"
# Kamailio component ec2 size
ec2_kamailio_size = "t2.micro"
kamailio_root_disk_size = 25
# Websockets component ec2 size
ec2_websockets_size = "t2.micro"
websockets_root_disk_size = 25
# RDS PGSQL 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