Demonstração de escalonamento horizontal no Aria Automation com NSX e Ansible – parte 2

Demonstração de escalonamento horizontal no Aria Automation com NSX e Ansible – parte 2

No artigo demonstração de escalonamento horizontal no Aria Automation com NSX e Ansible, detalho bem o processo de construção do blueprint, bem como algumas particularidades. Agora serei mais breve, basicamente vou demonstrar novamente o escalonamento horizontal com balanceador de carga do NSX e Ansible, mas o resultado final será uma aplicação específica. É interessante realizar construções para aplicações específicas pelo fato de já ter um padrão pré-definido e com isso conseguimos evitar a generalização do blueprint.

A aplicação em questão trata-se do Homer Web, onde basicamente precisamos de um ou mais servidores web conectados em um balanceador de carga na porta 80. Estes servidores terão 1 GB de RAM e 1 vCPU e irão rodar Apache e PHP. No mesmo blueprint, teremos o servidor de banco de dados que será uma unica máquina com 2 GB de RAM e 2 vCPU. Neste servidor irá rodar o MySQL.

Todos os dados da aplicação serão armazenados no servidor MySQL, ou seja, a quantidade de servidores web pode crescer ou diminuir de forma rápida e simplificada conforme a necessidade.

Agora vem a mágia de não ser um blueprint genérico, ou seja, eu já sei previamente muita coisa e por isso não preciso solicitar estas informações para o usuário. Por exemplo, já sei o tamanho que as instâncias web e de banco de dados precisam ter, já sei a porta, protocolo e algoritmo do balanceador de carga, etc. Enfim, já falei demais. Vamos ao código do blueprint:

name: Homer Web
version: 1
inputs:
  vm_environment:
    type: string
    title: Environment
    oneOf:
      - title: Production
        const: prod
      - title: Development
        const: dev
  vm_web_instances:
    type: integer
    title: Web Server Instances
    default: 2
resources:
  network_web:
    type: Cloud.NSX.Network
    properties:
      networkType: existing
      constraints:
        - tag: ${'environment:' + (input.vm_environment)}
        - tag: service:web
        - tag: network:nsx
  network_db:
    type: Cloud.NSX.Network
    properties:
      networkType: existing
      constraints:
        - tag: ${'environment:' + (input.vm_environment)}
        - tag: service:db
        - tag: network:nsx
  ansible_web:
    type: Cloud.Ansible
    dependsOn:
      - vm_db
    ignoreChanges: true
    properties:
      count: ${input.vm_web_instances}
      host: ${resource.vm_web.*}
      groups:
        - vra_web
      osType: linux
      account: Caverna Ansible
      username: root
      password: ${secret.caverna-linux}
      hostVariables:
        database_ip: ${resource.vm_db.address}
      playbooks:
        provision:
          - /etc/ansible/playbooks/install-homer-web.yml
  ansible_db:
    type: Cloud.Ansible
    ignoreChanges: true
    properties:
      host: ${resource.vm_db.*}
      groups:
        - vra_db
      osType: linux
      account: Caverna Ansible
      username: root
      password: ${secret.caverna-linux}
      playbooks:
        provision:
          - /etc/ansible/playbooks/install-homer-db.yml
      hostVariables:
        database_ip: ${resource.vm_db.address}
  security_web:
    type: Cloud.SecurityGroup
    properties:
      securityGroupType: existing
      constraints:
        - tag: security:web
  security_db:
    type: Cloud.SecurityGroup
    properties:
      securityGroupType: existing
      constraints:
        - tag: security:db
  vm_web:
    type: Cloud.vSphere.Machine
    dependsOn:
      - vm_db
    allocatePerInstance: true
    properties:
      name: CAV-P-WEB-
      image: Ubuntu 22.04
      cpuCount: 1
      totalMemoryMB: 1024
      constraints:
        - tag: ${'environment:' + (input.vm_environment)}
        - tag: service:web
      networks:
        - network: ${resource.network_web.id}
          assignment: static
          securityGroups:
            - ${resource.security_web.id}
      count: ${input.vm_web_instances}
  vm_db:
    type: Cloud.vSphere.Machine
    properties:
      name: CAV-P-DB-
      image: Ubuntu 22.04
      cpuCount: 2
      totalMemoryMB: 2048
      constraints:
        - tag: ${'environment:' + (input.vm_environment)}
        - tag: service:db
      networks:
        - network: ${resource.network_db.id}
          assignment: static
          securityGroups:
            - ${resource.security_db.id}
  lb_web:
    type: Cloud.NSX.LoadBalancer
    properties:
      name: CAV-P-WEB-LB-
      network: ${resource.network_web.id}
      instances: ${resource.vm_web[*].id}
      internetFacing: false
      routes:
        - instancePort: 80
          instanceProtocol: TCP
          port: 80
          protocol: TCP
          algorithm: ROUND_ROBIN
      constraints:
        - tag: nsx:lb-01

Vou compartilhar os playbooks do Ansible também. Estes playbooks são responsáveis por instalar e configurar os servidores web e de banco de dados. Abaixo vemos o playbook install-homer-db.yml. Este playbook instala o MySQL, cria um banco de dados, uma tabela, um usuário e por fim reinicia o serviço do MySQL.

- name: "Install MySQL - Homer Web"
  hosts: all
  become: yes
  tasks:
    - name: "Install latest version of MySQL"
      apt:
        name: mysql-server
        update_cache: yes
        state: latest

    - name: "Install PyMySQL"
      apt:
        name: python3-pymysql
        state: present

    - name: "Create a MySQL database"
      mysql_db:
        name: homer_db
        state: present
        login_host: localhost
        login_unix_socket: /var/run/mysqld/mysqld.sock

    - name: "Create a table"
      mysql_query:
        login_host: localhost
        login_unix_socket: /var/run/mysqld/mysqld.sock
        query: "CREATE TABLE IF NOT EXISTS homer_db.thumbs (code INT AUTO_INCREMENT PRIMARY KEY, status VARCHAR(50), date TIMESTAMP DEFAULT CURRENT_TIMESTAMP);"

    - name: "Create a MySQL user"
      mysql_user:
        name: homer
        password: homerJayS123
        priv: '*.*:ALL'
        host: '%'
        state: present
        login_host: localhost
        login_unix_socket: /var/run/mysqld/mysqld.sock

    - name: "Grant privileges to the user on the database"
      mysql_user:
        name: homer
        priv: 'homer_db.*:ALL'
        host: '%'
        state: present
        login_host: localhost
        login_unix_socket: /var/run/mysqld/mysqld.sock

    - name: "Update MySQL configuration to allow external connections"
      lineinfile:
        path: /etc/mysql/mysql.conf.d/mysqld.cnf
        regexp: '^bind-address\s*='
        line: 'bind-address = {{ database_ip }}'

    - name: "Restart MySQL service"
      service:
        name: mysql
        state: restarted

Já o playbook install-homer-web.yml é responsável por instalar o Apache e PHP, além de obter a aplicação do github e configura-la no diretório do Apache. É interessante observar a parte que é configurado o endereço IP do banco de dados, pois isso é uma variável do Ansible que configuramos dinamicamente no blueprint.

- name: "Install Apache and PHP - Homer Web"
  hosts: all
  become: yes
  tasks:
    - name: "Install latest version of Apache"
      apt: name=apache2 update_cache=yes state=latest

    - name: "Install latest version of PHP"
      apt: name=php update_cache=yes state=latest

    - name: "Install latest version of PHP MySQL"
      apt: name=php-mysql update_cache=yes state=latest

    - name: "Restart Apache service"
      service: name=apache2 state=restarted

    - name: "Remove index.html file"
      file:
        path: "/var/www/html/index.html"
        state: absent

    - name: "Clone repository"
      git:
        repo: "https://github.com/ricardoconzatti/demo.git"
        dest: "/tmp/homer-web"

    - name: "Copy files to Apache folder"
      shell: cp -r /tmp/homer-web/homer-web-v2/* /var/www/html/

    - name: "Change connection database file"
      shell: echo '<?php $dbcon = mysqli_connect("{{ database_ip }}", "homer", "homerJayS123", "homer_db"); ?>' > /var/www/html/cnx.php

Agora vou solicitar este item de catálogo. Apenas seleciono o ambiente de produção e inicialmente com duas instâncias web.

Após o deployment com sucesso, basta abrir o endereço do balanceador de carga no navegador e voilà. It’s alive!

Agora poderia atualizar o deployment aumentando ou diminuindo a quantidade de servidores web para atender a demanda.

Deixei todos os arquivos no github. É isso aí, pessoal. Até a próxima!

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *