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!