Colocando Infra ágil em prática !

segunda-feira, 29 de outubro de 2018

Colocando Infra ágil em prática !


Olá jovens mancebos, como estão ?

Ultimamente tenho focado muito no termo "DevOps", mas afinal, como dizer que você está implementando DevOps efetivamente ?
É complicado afirmar isto sem estar em um ambiente 100% dinâmico, onde há times multidisciplinares que executam de diversas demandas de agilidade e inovação.

Foi aí que encontrei uma resposta para a minha pergunta. Como sou nascido sysadmin, percebi que estou implementando infraestrutura ágil com metodologias aliadas, como SCRUM, KanBan e automatização de recursos e processos.
Me senti auto sabotado quando dei uma palestra em uma universidade sobre DevOps e me encontrei falando só sobre infra, integração entre times e CI/CD.

Por isso decidi trazer para vocês um pouco mais sobre infra ágil e como implementar IaC (Infra as Code) e deixar de lado um pouco o conceito DevOps, transformando-o simplesmente em "Integração entre times".

Pode ser um post mais extenso hoje, mas preferi explicar cada componente além do processo.





Docker Swarm Cluster na GCP com Terraform e Ansible

Caso deseje o código deste post, o mesmo se encontra no meu github.


Terraform

Para o pessoal que não está familiarizado, Terraform é uma ferramenta da HashiCorp que viabiliza a "scriptação" de criação e configuração de componentes de recursos de uma cloud (as quatro principais pelo menos) através da linguagem HCL.
Ou seja, o Terraform te permite programar a infraestrutura de uma cloud, criando as máquinas, firewalls, endpoints de apps e etc..

Ansible

Seguindo na linha de explicações, vamos falar de Ansible !
Para quem não conhece, Ansible é uma ferramenta adquirida pela falecida Red Hat (comprada pela IBM ontem :'( ) que permite a gerência de configuração via SSH.
Ou seja, você possui 50 servidores Linux e precisa alterar o timezone de todos. Vai fazer na mão um por um ? Claro que não né Jamelão !  Você vai utilizar o Ansible, criando um script em YAML, com uma sintaxe bem simples e com um inventário (lista de hosts que sofrerão as alterações). O Ansible irá se conectar via SSH com as credenciais que você disponibilizou em um arquivo de variáveis dele e executar o que seu script YAML ordena que ele faça.

Docker Swarm

O Docker Swarm é um ORQUESTRADOR de containers, ou seja, um orquestrador de Docker, assim como o Kubernetes. Ele é responsável por gerenciar as diversas máquinas incluídas em um cluster swarm (master e nodes) e distribuir os containers criados entre eles em alta disponibilidade.
O Docker Swarm encara os containers como serviços, permitindo gerar réplicas destes containers entre os nodes.

Mão Na Massa !

O nosso deploy (entrega) será feito na seguinte ordem:

  • [Terraform] Deploy da infraestrutura na cloud Google (regras de firewall e criação das máquinas)
  • [Terraform] Criar um arquivo de inventário Ansible de acordo com as máquinas criadas
  • [Ansible]     Instalar Docker e Configurar o Swarm

Download Terraform

Para fazer download do terraform é bem simples.
Execute os comandos abaixo para ter sucesso:
cd /opt
wget https://releases.hashicorp.com/terraform/0.11.10/terraform_0.11.10_linux_amd64.zip
unzip terraform_0.11.10_linux_amd64.zip
sudo ln -s /opt/terraform /usr/bin/terraform

Download Ansible

Para realizar o download do Ansible é bem simples, ele está contido em todos os repositórios oficiais do Ubuntu e CentOs.
Basta realizar o comando do seu gerenciador de pacotes para instalar Ansible.

Scripts Terraform

Crie os arquivos 01-gce-infra.tf      02-create-inv.tf        variables.tf
Vamos montar o arquivo variables.tf que será o arquivo onde o Terraform lerá certas variáveis utilizadas nos demais arquivos para configuração dos ambientes:
##Variáveis Gerais
##Variável do Usuário SSH para as máquinas
variable "ssh_user" {
  default = "ubuntu"
}
##Variável para incluir dentro das máquinas criadas a chave de acesso SSH para conexão
variable "public_key_path" {
  default = "/home/keep.linux/.ssh/id_rsa.pub"
}
##Variável para definir o caminho da chave privada utilizada para conexão
variable "private_key_path" {
  default = "/home/keep.linux/.ssh/id_rsa"
}

##Variáveis Específicas Google Cloud
##Variável de contagem de quantos master Swarm desejo
variable "gce_master_count" {
  default = 1
}
##Variável de contagem de quantos nodes Swarm desejo variable "gce_worker_count" {   default = 2 } ##Variável apontando para o path onde está o arquivo JSON de conexão com minha Google Cloud ##Pesquise como gerar um arquivo JSON com a chave do projeto dentro do Console Google Cloud variable "gce_creds_path" {   default = "/home/keep.linux/cred_gcp.json" } ##Variável para definir o ID do projeto já criado na GCP variable "gce_project" {   default = "keep-terraform" } ##Variável para definir a região que serão criadas as máquinas variable "gce_region" {   default = "us-central1" } ##Variável para definir o tamanho (flavor) das máquinas variable "gce_instance_size" {   default = "n1-standard-1" }

Feito isso, precisamos criar o arquivo 01-gce-infra.tf  que irá ler os arquivos de variáveis, conectar em nosso projeto na GCP e criar as máquinas e regras de firewall:

##Definindo Credenciais GCP
provider "google" {
  credentials = "${file("${var.gce_creds_path}")}"
  project     = "${var.gce_project}"
  region      = "${var.gce_region}"
}

##Criando regras de firewall
resource "google_compute_firewall" "swarm_sg" {
  name    = "swarm-sg"
  network = "default"

  allow {
    protocol = "udp"
    ports    = ["7946"]
  }

  allow {
    protocol = "tcp"
    ports    = ["22", "2377", "7946", "4789"]
  }
}

##Criando Máquina Master Swarm
resource "google_compute_instance" "gce-swarm-masters" {
  depends_on   = ["google_compute_firewall.swarm_sg"]
  name         = "swarm-masters-${count.index}"
  machine_type = "${var.gce_instance_size}"
  zone         = "${var.gce_region}-a"
  count        = "${var.gce_master_count}"

  boot_disk {
    initialize_params {
        image = "ubuntu-os-cloud/ubuntu-1604-lts"
    }
  }

  scratch_disk {
  }

  network_interface {
    network       = "default"
    access_config = {}
  }

  metadata {
    ssh-keys = "ubuntu:${file("${var.public_key_path}")}"
  }
}

##Criando Máquinas Nodes Swarm
resource "google_compute_instance" "gce-swarm-members" {
  depends_on   = ["google_compute_firewall.swarm_sg"]
  name         = "swarm-member-${count.index}"
  machine_type = "${var.gce_instance_size}"
  zone         = "${var.gce_region}-a"
  count        = "${var.gce_worker_count}"

  boot_disk {
    initialize_params {
        image = "ubuntu-os-cloud/ubuntu-1604-lts"
    }
  }

  scratch_disk {
  }

  network_interface {
    network       = "default"
    access_config = {}
  }

##Definindo chave SSH para conexão do Ansible
  metadata {
    ssh-keys = "ubuntu:${file("${var.public_key_path}")}"
  }
}

No script acima nós criamos 2 tipos de máquinas, master e nodes, lembrando que a quantidade é definida no nosso arquivo de variáveis.
Além disso criamos também as regras de firewall para possibilitar a comunicação entre as máquinas.

Agora vamos criar o script 02-create-inv.tf que irá criar o inventário para o Ansible de acordo com os IP's públicos e nomes das máquinas criadas automaticamente:

resource "null_resource" "ansible-provision" {
  depends_on = ["google_compute_instance.gce-swarm-masters", "google_compute_instance.gce-swarm-members"]

  provisioner "local-exec" {
    command = "echo \"[swarm-master]\" >> swarm-inventory"
  }

  provisioner "local-exec" {
    command = "echo \"${join("\n",formatlist("%s ansible_ssh_user=%s", google_compute_instance.gce-swarm-masters.*.network_interface.0.access_config.0.assigned_nat_ip, var.ssh_user))}\" >> swarm-inventory"
  }

  provisioner "local-exec" {
    command = "echo \"[swarm-nodes]\" >> swarm-inventory"
  }

  provisioner "local-exec" {
    command = "echo \"${join("\n",formatlist("%s ansible_ssh_user=%s", google_compute_instance.gce-swarm-members.*.network_interface.0.access_config.0.assigned_nat_ip, var.ssh_user))}\" >> swarm-inventory"
  }

  provisioner "local-exec" {
    command = "echo \"[all:vars]\" >> swarm-inventory"
  }

  provisioner "local-exec" {
    command = "echo \"ansible_ssh_user=ubuntu\" >> swarm-inventory"
  }

  provisioner "local-exec" {
    command = "echo \"ansible_ssh_private_key_file=./keys/id_rsa\" >> swarm-inventory"
  }

}

Implantando o IaC

Agora que já temos nossos scripts Terraform criados e devidamente configurados, vamos por em prática a infraestrutura como código e ver a mágica acontecer!
Execute o comando terraform init dentro da pasta onde estão os scripts, para que o terraform identifique os plugins necessários (provider google) e realize a preparação da ferramenta para que a mágica aconteça.

Em seguida, execute o comando terraform apply para ver a mágica acontecer e suas máquinas serem criadas em seu projeto na Google Cloud Platform.
Caso ocorra algum erro por configuração, execute o comando terraform destroy para realizar o rollback.

Para confirmar, verifique se existe o arquivo swarm-inventory. Nele estarão contidos os dados para o Ansible conectar nas máquinas.

Configurando Docker Swarm !

Agora que temos nossa infraestrutura criada, vamos configurá-la para ter o Docker Swarm !
Crie o arquivo swarm.yml:
- name: Install Ansible Prereqs
  hosts: swarm-master:swarm-nodes
  gather_facts: no
  become: yes
  tasks:
    - raw: "apt-get update && DEBIAN_FRONTEND=noninteractive && apt-get install -y python-minimal python-pip"

- name: Install Docker Prereqs
  hosts: swarm-master:swarm-nodes
  gather_facts: yes
  become: yes
  tasks:
    - package:
        name: "{{item}}"
        state: latest
      with_items:
        - apt-transport-https
        - ca-certificates
        - curl
        - software-properties-common
    - apt_key:
        url: "https://download.docker.com/linux/ubuntu/gpg"
        state: present
    - apt_repository:
        repo: "deb [arch=amd64] https://download.docker.com/linux/ubuntu xenial stable"
        state: present

- name: Install Docker
  hosts: swarm-master:swarm-nodes
  gather_facts: yes
  become: yes
  tasks:
    - package:
        name: "docker-ce"
        state: latest
    - user:
        name: "{{ ansible_ssh_user }}"
        groups: docker
        append: yes

- name: Initialize Swarm Master
  hosts: swarm-master
  gather_facts: yes
  become: yes
  tasks:
    - command: "docker swarm init --advertise-addr {{inventory_hostname}}"
    - command: "docker swarm join-token -q worker"
      register: swarm_token
    - set_fact: swarmtoken="{{swarm_token.stdout}}"

- name: Join Swarm Nodes
  hosts: swarm-nodes
  gather_facts: yes
  become: yes
  tasks:
    - command: "docker swarm join --advertise-addr {{inventory_hostname}} --token {{hostvars[groups['swarm-master'][0]].swarmtoken}} {{hostvars[groups['swarm-master'][0]].inventory_hostname}}:2377"



Este script Ansible irá conectar nas máquinas contidas no arquivo swarm-inventory e instalar o Docker e configurar o Docker Swarm.
Complete o setup configurando o ansible para que ignore os avisos de "novo host" inserindo a chave ansible_host_key_checking=false dentro do arquivo /etc/ansible/ansible.cfg
Agora execute o comando Ansible para efetuar as configurações nos nodes docker:

ansible-playbook -i swarm-inventory swarm.yml


E pronto ! Temos nosso cluster Docker Swarm configurado na Google Cloud !

Caso queira fazer um teste com serviços, conecte-se via SSH com a chave informada nas variáveis na máquina MASTER do docker swarm e execute os comandos:
# Irá listar os nodes presentes neste Docker Swarm
docker node ls

# Irá criar um serviço com a imagem Linux alpine realizando o comando "ping google.com" com 5 réplicas de serviços dentro do Swarm com o nome de helloworld
docker service create --replicas 5 --name helloworld alpine ping google.com

# Irá listar o serviço helloworld e suas réplicas
docker service ps helloworld

Destruindo Tudo !

Para destruir tudo, basta executar o comando terraform destroy.

0 comentários :

Postar um comentário