En este blog hemos hablado de la importancia que tiene la Infraestructura como Código en entornos Agile.
Hoy veremos cómo hacer uso de Ansible para definir y modelar nuestra infraestructura, en concreto, la infraestructura necesaria para la instalación de OpenShift.
Ansible se está convirtiendo en un estándar para la automatización en IT y esta automatización es un componente esencial en la Transformación Digital de las empresas.
Con Ansible podemos automatizar fácilmente la provisión, el plataformado y la configuración de, prácticamente, cualquier aspecto en nuestra infraestructura.
El ritmo de adopción de Ansible está siendo espectacular pero casi todo el mundo empieza utilizando esta tecnología para la gestión de la configuración.
Infraestructura con Ansible
Ansible va más allá de la simple configuración de máquinas. Es posible que no conozcas el enorme número de módulos existentes para la creación y gestión de infraestructura, por ejemplo:
- Amazon AWS
- Azure
- CloudStack
- Digital Ocean
- Google Cloud
- OpenStack
- Ovirt/RHV
- RackSpace
- VMware
Pero los módulos para nubes públicas y privadas no es todo lo que ofrece, también dispone de numerosos módulos para gestionar sistemas de networking, por ejemplo:
- Aruba
- Cisco
- Citrix
- F5
- Juniper
Infraestructura para OpenShift
Para realizar un ejemplo, vamos a definir con Ansible la infraestructura necesaria para la instalación de OpenShift en Azure.
Para ello vamos a guiarnos por la Arquitectura de Referencia que nos propone Red Hat.
La infraestructura necesaria es sencilla. Como podemos ver, necesitamos más de un máquina de cada tipo para conseguir un clúster en HA.
En concreto, necesitamos las siguientes máquinas:
- 3 nodos Master
- 3 nodos de Infra
- 3 nodos de Aplicación
Adicionalmente, crearemos un máquina denominada Bastion, desde donde instalaremos y gestionaremos OpenShift.
Vamos a crear una red que una todas estas máquinas. Partiremos esta red en 3 sub-redes para tener más control sobre cada tipo de nodo.
Sobre esta red tendrá existirán dos balanceadores, uno para repartir la carga entre los "masters" y el otro para balancear los nodos de "infra".
En los "masters" se expone el API y la Consola Web de OpenShift, por tanto, el balanceador de los "masters" expondrá una IP pública al exterior. De esta manera podremos utilizar OpenShift via CLI y Web. Es recomendable crear un balanceador privado adicional para este mismo propósito pero que se utilizará unicamente de forma interna en OpenShift.
En los nodos de "infra" se encuentran los Routers, proxys inversos que exponen las aplicaciones desplegadas en OpenShift. El otro balanceador se encargará de repartir la carga entre estos "routers". De la misma manera utilizaremos una IP pública para exponer este balanceador al exterior.
Tan sólo nos quedaría asignar una IP pública al nodo Bastion para poder acceder a él desde el exterior usando SSH (sólo para esta demo ya que para acceder via SSH es mejor usar VPNs).
Para simplificar, no montaremos almacenamiento compartido, utilizaremos por ahora el almacenamiento de cada host.
Implementación en Ansible y Azure
Todo el código necesario para esta demo se encuentra en GitHub:
https://github.com/drhelius/ansible-azure-openshift
Para ejecturalo podremos lanzar el siguiente comando:
$ ansible-playbook -e @configuration.yml openshift-infra.yml
Empezaremos con un fichero de configuración para definir nuestras variables:
azure:
location: "East US"
resource_group: "openshift"
image_publisher: "OpenLogic"
image_offer: "CentOS"
image_sku: "7.5"
image_version: "latest"
openshift:
master_nodes: [1,2,3]
master_size: "Standard_B2s"
infra_nodes: [1,2,3]
infra_size: "Standard_B2ms"
app_nodes: [1,2,3]
app_size: "Standard_B2s"
bastion_size: "Standard_B2ms"
admin_domain: "ocp.mydomain.com"
router_domain: "mydomain.com"
Para el dominio podremos hacer uso de algún servicio gratuito de "Dyn DNS" como Duck DNS que nos permite crear wildcard DNS (*.mydomain.com) necesarios para los "routers" de OpenShift.
Antes de empezar tenemos que tener Azure CLI instalado.
También necesitaremos algunas dependencias y configuración de autenticación.
Cuando tengamos todo listo podemos empezar con el código. El primer paso es crear el Resource Group de Azure:
- name: Create resource group
azure_rm_resourcegroup:
name: "{{ azure.resource_group }}"
location: "{{ azure.location }}"
Después las redes, aquí un ejemplo de la red principal y la subred para Masters:
- name: Create main virtual network
azure_rm_virtualnetwork:
resource_group: "{{ azure.resource_group }}"
name: openshift-virtual-network
address_prefixes: "10.0.0.0/16"
- name: Create master subnet
azure_rm_subnet:
resource_group: "{{ azure.resource_group }}"
name: openshift-master-subnet
address_prefix: "10.0.1.0/24"
virtual_network: openshift-virtual-network
Podremos crear ya nuestro Bastion:
- name: Create Bastion VM
azure_rm_virtualmachine:
resource_group: "{{ azure.resource_group }}"
name: openshift-bastion-vm
vm_size: "{{ openshift.bastion_size }}"
storage_account: "{{ openshift_storage_account }}"
admin_username: "{{ openshift.os_user }}"
ssh_password_enabled: false
ssh_public_keys:
- path: "/home/{{ openshift.bastion_admin }}/.ssh/authorized_keys"
key_data: "{{ lookup('file', '../../certs/bastion.pub') }}"
network_interfaces: openshift-bastion-nic
image:
offer: "{{ azure.image_offer }}"
publisher: "{{ azure.image_publisher }}"
sku: "{{ azure.image_sku }}"
version: "{{ azure.image_version }}"
La creación de los Masters es similar, pero utilizaremos un loop asíncrono para crear más de una máquina a la vez:
- name: Create Master vm
azure_rm_virtualmachine:
resource_group: "{{ azure.resource_group }}"
name: "openshift-master-vm-{{ item }}"
availability_set: openshift-master-availability-set
vm_size: "{{ openshift.master_size }}"
storage_account: "{{ openshift_storage_account }}"
admin_username: "{{ openshift.os_user }}"
ssh_password_enabled: false
ssh_public_keys:
- path: "/home/{{ openshift.os_user }}/.ssh/authorized_keys"
key_data: "{{ lookup('file', '../../certs/openshift.pub') }}"
network_interfaces: "openshift-master-nic-{{ item }}"
image:
offer: "{{ azure.image_offer }}"
publisher: "{{ azure.image_publisher }}"
sku: "{{ azure.image_sku }}"
version: "{{ azure.image_version }}"
loop: "{{ openshift.master_nodes }}"
async: 600
poll: 0
register: openshift_master_vm_result
changed_when: False
- name: Wait for Master vm creation
async_status:
jid: "{{ item.ansible_job_id }}"
loop: "{{ openshift_master_vm_result.results }}"
register: openshift_master_vm_creation
until: openshift_master_vm_creation.finished
retries: 120
delay: 5
Este sería el balanceador público de los Masters:
- name: Create Masters public load balancer
azure_rm_loadbalancer:
resource_group: "{{ azure.resource_group }}"
name: openshift-master-public-load-balancer
frontend_ip_configurations:
- name: public
public_ip_address: openshift-master-public-ip
backend_address_pools:
- name: openshift-master-public-address-pool
probes:
- name: master-lb-probe-8443-up
port: 8443
load_balancing_rules:
- name: master-lb-public-rule-8443-8443
frontend_ip_configuration: public
backend_address_pool: openshift-master-public-address-pool
frontend_port: 8443
backend_port: 8443
probe: master-lb-probe-8443-up
register: openshift_master_public_lb_result
TL;DR
Como hemos visto, Ansible es una tecnología potente, muy sencilla de aprender, que nos proporciona una cantidad enorme de herramientas para poder escribir y versionar nuestra Infraestructura como Código para casi cualquier cloud pública o privada.
¡Síguenos en Twitter para estar al día de próximos posts!