Usando o Ansible para instalar, configurar e configurar um cluster Kubernetes do Google (GKE) na Google Cloud Platform (GCP).
Automatizando a configuração de um cluster GKE
Como eu descrevi brevemente neste artigo, a Infraestrutura como Código (IaC)¹ é fundamental para manter a consistência em diferentes ambientes. A IaC resolve o problema de divergência de ambiente, onde cada ambiente possui configurações exclusivas que não são reproduzíveis automaticamente.
O código usado para criar este tutorial está disponível neste repositório.
O Ansible² é a ferramenta de escolha para implementar este tutorial. Ele nos ajuda a criar o código necessário para provisionar um cluster Kubernetes básico na GCP (GKE)³ de forma automatizada.
Estrutura de Diretórios do Ansible
A seguir está a estrutura de diretórios com a qual estaremos trabalhando ao longo deste tutorial.
.
└── ansible # top-level folder
├── ansible.cfg # config file
├── create-k8s.yml # playbook to provision env
├── destroy-k8s.yml # playbook to destroy env
├── inventory
│ └── gcp.yml # inventory file
└── roles
├── destroy_k8s # role to remove k8s cluster
│ └── tasks
│ └── main.yml
├── destroy_network # role to remove VPC
│ └── tasks
│ └── main.yml
├── k8s # role to create k8s cluster
│ └── tasks
│ └── main.yml
└── network # role to create VPC
└── tasks
└── main.yml
Inventário do Ansible
Para começar, crie um arquivo yaml na pasta ansible/inventory. Este arquivo de inventário do Ansible define as variáveis que estarão disponíveis para o nosso código.
Aqui está um arquivo de exemplo:
all:
vars:
# use this section to enter GCP related information
zone: europe-west2-c
region: europe-west2
project_id: <gcp-project-id>
gcloud_sa_path: "~/gcp-credentials/service-account.json"
credentials_file: "{{ lookup('env','HOME') }}/{{ gcloud_sa_path }}"
gcloud_service_account: service-account@project-id.iam.gserviceaccount.com
# use the section below to enter k8s cluster related information
cluster_name: <name for your k8s cluster>
initial_node_count: 1
disk_size_gb: 100
disk_type: pd-ssd
machine_type: n1-standard-2
Ansible Roles
Após o arquivo de inventário, utilize Ansible roles⁵ para configurar as tarefas do Ansible para provisionar nosso cluster. Para este tutorial, criei duas funções:
ansible/roles/network - para provisionar uma Virtual Private Cloud (VPC)
ansible/roles/k8s - para provisionar o cluster Kubernetes
Não é obrigatório ter uma rede separada para o seu cluster. Eu a criei porque não queria usar a rede padrão.
Abaixo está o arquivo de configuração yaml para a network role:
---
- name: create GCP network
google.cloud.gcp_compute_network:
name: network-{{ cluster_name }}
auto_create_subnetworks: 'true'
project: "{{ project_id }}"
auth_kind: serviceaccount
service_account_file: "{{ credentials_file }}"
state: present
register: network
A tarefa utiliza o plugin google.cloud.gcp_compute_network para criar a rede VPC.
As variáveis Jinja2 - {{ }} - são substituídas pelos valores inseridos no arquivo de inventário criado anteriormente.
Na variável network, é registrado a saída desta tarefa usando a palavra-chave register. A variável network é necessária durante a criação do cluster.
A próxima tarefa é aquela que provisiona o cluster Kubernetes. Essa tarefa usa dois plugins: google.cloud.gcp_container_cluster e google.cloud.gcp_container_node_pool.
O primeiro cria o cluster Google Kubernetes Engine, e o último cria os node pools. Node pools são um conjunto de nodes, ou seja, máquinas virtuais, com uma configuração e especificações comuns sob o controle do mestre do cluster.
Abaixo está o arquivo de configuração yaml para a k8s role:
---
- name: create k8s cluster
google.cloud.gcp_container_cluster:
name: "{{ cluster_name }}"
initial_node_count: "{{ initial_node_count }}"
location: "{{ zone }}"
network: "{{ network.name }}"
project: "{{ project_id }}"
auth_kind: serviceaccount
service_account_file: "{{ credentials_file }}"
state: present register: cluster
- name: create k8s node pool
google.cloud.gcp_container_node_pool:
name: "node-pool-{{ cluster_name }}"
initial_node_count: "{{ initial_node_count }}"
cluster: "{{ cluster }}"
config:
disk_size_gb: "{{ disk_size_gb }}"
disk_type: "{{ disk_type }}"
machine_type: "{{ machine_type }}"
location: "{{ zone }}"
project: "{{ project_id }}"
auth_kind: serviceaccount
service_account_file: "{{ credentials_file }}"
state: present
Observe que o valor do parâmetro network na tarefa de criação do cluster k8s é obtido a partir da saída registrada na role network.
Ansible Playbook
O último passo é criar um Ansible playbook⁸ para executar ambos roles. Na pasta ansible, criei um arquivo chamado create-k8s.yml:
---
- name: create infra
hosts: localhost
gather_facts: false
environment:
GOOGLE_CREDENTIALS: "{{ credentials_file }}"
roles:
- network
- k8s
Agora, podemos provisionar nosso cluster Kubernetes com o seguinte comando:
ansible-playbook ansible/create-gke.yml -i ansible/inventory/<your-inventory-filename>
Saída:
PLAY [create infra] ****************************************************************
TASK [network : create GCP network] ****************************************************************
changed: [localhost]
TASK [k8s : create k8s cluster] ****************************************************************
changed: [localhost]
TASK [k8s : create k8s node pool] ****************************************************************
changed: [localhost]
PLAY RECAP ****************************************************************
localhost: ok=3 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Conectando ao cluster Kubernetes
Use a ferramenta de linha de comando gcloud⁹ para se conectar ao cluster Kubernetes:
gcloud container clusters get-credentials <cluster_name> --zone <zone> --project <project_id>
Nota: substitua as variáveis pelos valores usados no arquivo de inventário. Além disso, é possível recuperar este comando no console do GCP.
Saída:
Fetching cluster endpoint and auth data.
kubeconfig entry generated for <project_id>.
Usando o cluster Kubernetes
Após se conectar ao cluster, use a ferramenta de linha de comando kubectl¹⁰ para controlar o cluster ou o console do Google Cloud.
kubectl get nodes
NAME STATUS ROLES AGE VERSION
gke-<cluster_name>-node-pool-e058a106-zn2b Ready <none> 10m v1.18.12-gke.1210
Removendo as configurações
Para excluir o cluster Kubernetes, crie uma estrutura semelhante com um playbook, papéis e tarefas.
Basicamente, a única alteração necessária é que o estado em cada tarefa deve ser definido como absent (ausente).
Arquivo de playbook criado em ansible/destroy-k8s.yml:
---
- name: destroy infra
hosts: localhost
gather_facts: false
environment:
GOOGLE_CREDENTIALS: "{{ credentials_file }}"
roles:
- destroy_k8s
- destroy_network
Configurar diferentes roles e tasks para network e k8s nos permite destruir o Kubernetes e preservar a VPC, se desejarmos.
Roles e tasks criadas em ansible/roles:
destroy_network/tasks:
---
- name: destroy GCP network
google.cloud.gcp_compute_network:
name: network-{{ cluster_name }}
auto_create_subnetworks: 'true'
project: "{{ project_id }}"
auth_kind: serviceaccount
service_account_file: "{{ credentials_file }}"
state: absent
destroy_k8s/tasks:
- name: destroy k8s cluster
google.cloud.gcp_container_cluster:
name: "{{ cluster_name }}"
location: "{{ zone }}"
project: "{{ project_id }}"
auth_kind: serviceaccount
service_account_file: "{{ credentials_file }}"
state: absent
Execute o playbook para apagar os recursos network e k8s:
ansible-playbook ansible/destroy-gke.yml -i ansible/inventory/<your-inventory-filename>
Saída:
PLAY [destroy infra] *****************************************************************
TASK [destroy_k8s : destroy k8s cluster] *****************************************************************
changed: [localhost]
TASK [destroy_network : destroy GCP network] *****************************************************************
changed: [localhost]
PLAY RECAP *****************************************************************
localhost: ok=2 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Conclusāo
Este tutorial demonstrou como usar Infraestrutura como Código para instalar, configurar e configurar um cluster Kubernetes simples na Google Cloud Platform. Também foram mostrados conceitos essenciais do Ansible, como roles e playbook, e como configurá-los e estruturá-los para provisionar e remover recursos criados na nuvem.
Muito mais é possível com o Ansible. Use este tutorial como ponto de partida para organizar suas configurações do Kubernetes, como namespaces, deployments e policies como código. Acesse a página de documentação do Ansible para obter mais informações e expandir seu conhecimento e uso do Ansible.
Referências
https://docs.microsoft.com/en-us/azure/devops/learn/what-is-infrastructure-as-code
https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html
https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html
https://docs.ansible.com/ansible/latest/user_guide/basic_concepts.html#tasks
https://docs.ansible.com/ansible/latest/collections/google/cloud/index.html
https://docs.ansible.com/ansible/latest/user_guide/playbooks_intro.html
Comentários