Kubernetes — Criando um cluster de estudo com kind e metallb

TL;DR; Vamos aprender a como configurar um cluster de estudos, utilizando o kind e o metallb para habilitar a criação de serviços do tipo load balancer.

Image for post
Image for post

Se você é como eu e gosta de realizar os mais variados testes no seu cluster, já deve ter se deparado com alguns problemas e/ou limitações.

Como fuçar onde não devia e colocar o cluster em um estado meio duvidoso de funcionamento e ter que reconfigurar tudo novamente para voltar aos estudos, aplicar algum tutorial de configuração de serviço da web e descobrir que seu cluster não oferece todo suporte necessário para rodar determinda aplicação, ou simplesmente querer economizar um pouco com essa estrutura rodando em alguma cloud.

Tendo nossos tristes problemas relatados vamos agora as soluções.

Uma nota sobre o ambiente

Todos os passos estão sendo executados utilizando a distribuição mint do linux em sua versão 20 e estou assumindo que você já possui a cli do kubectl e o docker instalado e funcionando corretamente em sua máquina, caso não, pode conferir o passo a passo clicando aqui para o docker e aqui para o kubectl.

Nas distribuições linux baseadas em arch foi necessária a criação do arquivo docker.service.d/service-overrides.conf com o conteúdo

[Service]
Environment=”NO_PROXY=localhost,<nome-do-cluster>,…”

Para que fosse possível dar um nome diferente do default para o cluster, do contrário o kind vai retornar um erro ao criar o control-plane, esse comportamento não ocorreu nem no ubuntu nem no mint.

Configurando o cluster

Na criação do nosso cluster vamos utilizar o kind, acrônimo para Kubernetes IN Docker, cujo instalação você pode verificar na documentação oficial.

A ideia do kind é simples e bem bacana, ele utiliza containers do docker como nós do cluster o que nos da a capacidade de criar e destruir os clusters com relativa facilidade.

Crie um arquivo local com o conteúdo abaixo (O meu será kind-cluster.yaml).

apiVersion: kind.x-k8s.io/v1alpha4
kind: Cluster
nodes:
- role: control-plane
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true"
authorization-mode: "AlwaysAllow"
extraPortMappings:
- containerPort: 80
hostPort: 80
protocol: TCP
- containerPort: 443
hostPort: 443
protocol: TCP
- role: worker

Após instalada a cli do kind execute o comando abaixo:

kind create cluster --name study --config kind-cluster.yaml

Com isso estamos dizendo ao kind para criar um cluster chamado study a partir da especificação contida em kind-cluster.yaml.

Sobre o arquivo kind-cluster.yaml, basicamente estamos definindo dois nós para nosso cluster, um worker e um control-plane (Master), onde no nó master estão sendo mapeadas as portas 80 e 443 para o host.

Além disso estamos definindo a permissão como “aberto” na linha:
authorization-mode: “AlwaysAllow”

e com suporte a objetos do tipo ingress na linha:
node-labels: “ingress-ready=true”

Finalizada a criação, já é possível interagir com nosso cluster. Executando o comando:

kubectl get nodes

Você deve obter uma saída semelhante a essa:

Image for post
Image for post

Temos um nó master em estado Ready e um nó worker que ainda está sendo provisionado, nosso cluster está criado 🙂

Expondo um web server NGINX através de um load balancer

Existem 3 tipos básicos de serviços no kubernetes, são eles:

  • ClusterIp: Opção default, utilizando para acesso/comunicação entre serviços dentro do cluster.

O tipo LoadBalancer tem uma peculiaridade, ele é provisionado pelo ambiente que executa o cluster, AWS, GCP, Azure e etc., cada um deles fornece ips para esse tipo de serviço usando suas própria estratégias.

Mas vamos verificar na prática criando nosso web server NGINX, para isso basta executar os comando abaixo:

kubectl run nginx --image nginx

E para criar nosso serviço load balancer que expõe o pod:

kubectl expose pod/nginx --port 80 --type LoadBalancer

Ao criarmos um serviço do tipo LoadBalancer em nosso cluster, vamos nos deparar com um cenário inusitado, nenhum erro será disparado porém o ip na que deveria nos ser fornecido na seção EXTERNAL-IP do serviço ficará em estado Pending para sempre.

Image for post
Image for post

Para solucionar esse problema e termos nosso próprio “provedor de ips” podemos utilizar o metallb que é uma referência a LoadBalancer In BareMetal.

Configurando MetalLB

No momento desse artigo o metallb se encontra em versão beta (v0.9.3), porém para nossa finalidade de cluster para estudos servirá perfeitamente, mas fica o aviso de cuidado ao optar por colocar essa solução em ambiente de produção.

Vamos instalar os objetos do metallb em nosso cluster, você seguir os passos para instalação disponíveis na documentação oficial, os passos que vou seguir aqui são os da seção Installation By Manifest, a instalação é bem simples, são apenas 3 comandos:

# Criação do namespace metallb-system
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.9.3/manifests/namespace.yaml
# Criação dos objetos do metallb
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.9.3/manifests/metallb.yaml
# Geração de secret requerida pelo metallb
kubectl create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)"

Após criados os objetos do metallb, você deverá ver uma saída como abaixo:

Image for post
Image for post

E pode verificar o estado do pods criados executando o comando:

kubectl get pods -n metallb-system

Isso ainda não é o suficiente para termos nosso serviço funcionando, para isso temos que dizer ao metallb qual o range de ips que ele pode utilizar para serviços do tipo load balancer e faremos isso ao modo kubernetes, criando um configmap.

Crie um arquivo local com com o conteúdo abaixo (O meu será metallb.yaml).

apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: default
protocol: layer2
addresses:
- 172.20.0.100-172.20.0.200

Com atenção especial a chave addresses, é nela que vamos especificar a lista de ips que o metallb poderá associar aos serviços do tipo LoadBalancer, para isso podemos especificar um a um, utilizando a notação CIDR ou especificando um range, no nosso caso vamos especificar um range de ips, mas fique livre para testar os outros modos também.

Para definir o range de ips eu costumo utilizar a mesma “família” do clusters, para isso basta executar o comando:

kubectl get nodes -o wide

O resultado será semelhante a imagem abaixo:

Image for post
Image for post

Observe a seção INTERNAL-IP, no meu caso 172.20.0.X, portante utilizei na chave addresses o range de 172.20.0.100 até 172.20.0.200 para alocar LoadBalancers no cluster.

Feito isso, basta aplicar a configuração executando:

kubectl apply -f metallb.yaml

Com isso já é possível verificar que nosso serviço que estava com EXTERNAL-IP Pending agora possui um ip associado e dentro do range especificado no arquivo, que no meu caso inicou de 172.20.0.100.

Image for post
Image for post

Agora para acessar seu serviço basta executar o comando:

curl 172.20.0.100
Image for post
Image for post

Ou acessar o serviço no browser:

Image for post
Image for post

E pronto, tudo funcionando.

Conclusão

Se você seguiu todos os passos anteriores, agora você tem um cluster kubernetes rodando com docker e com suporte a serviços do tipo LoadBalancer prontinhos para suportar toda sua jornada de aprendizado no mundo kubernetes.

E se quiser simplesmente destruir o cluster que acabamos de criar, basta executar o comando:

kind delete cluster --name study

E pronto, tudo limpo novamente!

Written by

Arquiteto de software, entusiasta de tecnologia e curioso no mundo dos investimentos financeiros.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store