Provisionando um cluster Kubernetes no GCP usando Terraform e Kubepray
September 23, 2024
Provisionando um cluster Kubernetes no GCP usando Terraform e Kubespray
Introdução e motivação
Já fazia algum tempo que eu estava usando OpenShift e Rancher para gerenciar clusters Kubernetes. Dentre esses clusters, existia um para ferramentas que estava usando RKE (Rancher Kubernetes Engine). Ele estava consumindo bastante recursos, principalmente disco e memória, então resolvi testar o Kubespray para instalação do meu cluster Kubernetes vanilla (padrão).
Kubespray
Kubespray é um projeto da CNCF (Cloud Native Computing Foundation), focado em automatizar a instalação de clusters Kubernetes vanilla usando Ansible. É altamente customizável e suporta diversas plataformas de nuvem e on-premise.
Como ele provisiona um Kubernetes vanilla, ele tende a ser mais leve.
Pré-requisitos
Instalação do Terraform
A instalação do Terraform CLI é muito bem documentada no próprio site do fabricante, usando Chocolatey no Windows, Homebrew no Mac e apt no Linux.
Instalação do gcloud
Podemos seguir a documentação oficial do Google para instalação do gcloud CLI.
Você também precisa de uma conta, com o nível gratuito você tem US$ 300 de crédito.
Após a instalação e criação da sua conta, é necessário que você faça login com o comando:
gcloud auth application-default login
Instalação do Ansible
A instalação do Ansible é bem “amarrada” para o Kubespray, essa é a parte mais complicada, mas vamos lá.
Você precisa do Python na versão de 3.9
a 3.12
, isso é obrigatório para a versão que eu estou utilizando.
Após a instalação do python3.12
, vamos clonar o repositório do projeto Kubespray:
git clone https://github.com/kubernetes-sigs/kubespray.git
Depois vamos instalar o Ansible:
VENVDIR=kubespray-venv
KUBESPRAYDIR=kubespray
python3.12 -m venv $VENVDIR
source $VENVDIR/bin/activate
cd $KUBESPRAYDIR
pip3.12 install -U -r requirements.txt
pip3.12 install ruamel.yaml
Código Terraform
Escrevi o código usado para subir as máquinas no GCP (Google Cloud Platform) e disponibilizei em https://github.com/fbrunoviana/terraform-kubepray-gpc. Então vamos fazê-lo rodar.
git clone https://github.com/fbrunoviana/terraform-kubepray-gpc.git
cd terraform-kubepray-gpc
Avalie todas as variáveis, mas principalmente project_name
e chave_ssh
. Mude para o seu nome de projeto no GCP e a sua chave pública. Após as mudanças necessárias, suba o cluster.
terraform init
terraform plan -out=plan
terraform apply "plan"
E lá vamos nós 🧹 Se tudo der certo, você criou três máquinas no Google Cloud, prontas para o Kubespray.
Login SSH
Você receberá como output IPs públicos para acesso, como o exemplo abaixo:
kubernetes_instances = [
"controller-0: 34.21.26.210",
"worker-0: 34.16.91.179",
"worker-1: 35.225.1.235",
]
Faça o login em cada uma das máquinas, esse passo é importante para a troca de chaves. Caso tenha limpado a tela, é possível executar o comando terraform output
e ver novamente os IPs. Anote cada um dos IPs privados e salve em um bloco de notas.
# volte uma pasta para prosseguir
cd ..
Usando o Kubespray
Certifique-se que está no diretório que clonamos do Kubespray com o pwd
, feito isso vamos copiar o inventário como manda a documentação.
cp -rfp inventory/sample inventory/mycluster
Depois criar dinamicamente os IPs:
declare -a IPS=($(gcloud compute instances list --filter="tags.items=kubernetes-the-kubespray-way" --format="value(EXTERNAL_IP)" | tr '\n' ' '))
CONFIG_FILE=inventory/mycluster/hosts.yaml python3.12 contrib/inventory_builder/inventory.py ${IPS[@]}
É importante revisar a configuração:
vim inventory/mycluster/hosts.yaml
- Apague todos os
access_ip
- No campo
ip
adicione os IPs privados de cada host. - Em
kube_control_plane:
adicione apenas o control-plane. - Em
kube_node:
deixe apenas os workers. - Em
etcd:
adicione apenas o control-plane. - Salve e saia
:wq
Vamos agora explorar o arquivo que nos fará acessar fora da rede.
vim inventory/mycluster/group_vars/k8s_cluster/k8s_cluster.yml
- Altere o valor de
supplementary_addresses_in_ssl_keys
para o IP público do seu control plane, ex:supplementary_addresses_in_ssl_keys: [34.29.26.210]
- Salve e saia
:wq
Vamos adicionar as métricas no nosso cluster alterando o arquivo:
vim inventory/mycluster/group_vars/k8s_cluster/addons.yml
- Mude para
true
o valor demetrics_server_enabled
- Salve e saia
:wq
Apertando o botão do spray
Just do it!
ansible-playbook -i inventory/mycluster/hosts.yaml -u ubuntu -b -v --private-key=~/.ssh/id_rsa cluster.yml
O meu cluster com 6 máquinas demorou cerca de 28 minutos.
Acessando o cluster K8s
Volte para o diretório do Terraform e acesse o control plane, vamos precisar dar permissão no arquivo kubespray-do.conf
e trazê-lo para nossa máquina local:
cd terraform-kubepray-gpc
ssh ubuntu@$(terraform output -raw controller_0_ip)
# Na máquina acessada
sudo chown -R ubuntu:ubuntu /etc/kubernetes/admin.conf
exit
# Na sua máquina
scp ubuntu@$(terraform output -raw controller_0_ip):/etc/kubernetes/admin.conf kubespray-do.conf
sed -i 's/127.0.0.1/$(terraform output -raw controller_0_ip)/g' kubespray-do.conf
export KUBECONFIG=$PWD/kubespray-do.conf
Alô som, testando
Testando os hosts
Vamos iniciar os testes agora.
kubectl get nodes
Output
NAME STATUS ROLES AGE VERSION
controller-0 Ready master 47m v1.30.0
controller-1 Ready master 46m v1.30.0
controller-2 Ready master 46m v1.30.0
worker-0 Ready <none> 45m v1.30.0
worker-1 Ready <none> 45m v1.30.0
worker-2 Ready <none> 45m v1.30.0
kubectl top nodes
Output
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
controller-0 191m 10% 1956Mi 26%
controller-1 190m 10% 1828Mi 24%
controller-2 182m 10% 1839Mi 24%
worker-0 87m 4% 1265Mi 16%
worker-1 102m 5% 1268Mi 16%
worker-2 108m 5% 1299Mi 17%
Testando a rede
kubectl run myshell1 -it --rm --image busybox -- sh
hostname -i
# Rode o myshell2 em outro terminal, exporte novamente o arquivo conf
ping <hostname myshell2>
kubectl run myshell2 -it --rm --image busybox -- sh
hostname -i
ping <hostname myshell1>
Output
PING 10.233.108.2 (10.233.108.2): 56 data bytes
64 bytes from 10.233.108.2: seq=0 ttl=62 time=2.876 ms
64 bytes from 10.233.108.2: seq=1 ttl=62 time=0.398 ms
64 bytes from 10.233.108.2: seq=2 ttl=62 time=0.378 ms
^C
--- 10.233.108.2 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.378/1.217/2.876 ms
Deployments
Vamos gerenciar um Deployment. Crie um deployment do nginx web server:
kubectl create deployment nginx --image=nginx
Liste os Deployments:
kubectl get pods -l app=nginx
Output
NAME READY STATUS RESTARTS AGE
nginx-86c57db685-bmtt8 1/1 Running 0 18s
Service
Expor para fora do cluster
Vamos exportar o nginx usando um Service.
Exponha o deployment nginx
usando um serviço NodePort:
kubectl expose deployment nginx --port 80 --type NodePort
NODE_PORT=$(kubectl get svc nginx \
--output=jsonpath='{range .spec.ports[0]}{.nodePort}')
Vamos criar uma regra no firewall para liberar a porta:
gcloud compute firewall-rules create kubernetes-the-kubespray-way-allow-nginx-service \
--allow=tcp:${NODE_PORT} \
--network kubernetes-the-kubespray-way
EXTERNAL_IP=$(gcloud compute instances describe worker-0 \
--format 'value(networkInterfaces[0].accessConfigs[0].natIP)')
curl -I http://${EXTERNAL_IP}:${NODE_PORT}
Destruindo
Então é isso, é bem rápido e fácil de replicar um cluster usando o Kubespray.
Se você fez um laboratório igual ao meu, e se for da sua vontade, é possível destruir com o comando:
terraform destroy
Exclua também a regra de firewall que criamos.
gcloud compute firewall-rules delete kubernetes-the-kubespray-way-allow-nginx-service
Créditos:
- https://github.com/kubernetes-sigs/kubespray/blob/master/docs/getting_started/setting-up-your-first-cluster.md