Kind: uma jornada empolgante com k8s em seu GNU/Linux!
Tags: kubernetes, docker, kind, devops
Published: 2024-04-28 20:40:29

## Introdução

Durante o desenvolvimento e/ou testes de aplicações desenhadas para execução em ambientes baseados no orquestrador _Kubernetes_, surge a necessidade de se ter um _cluster_ disponível. Nem sempre isso está acessível de forma prática e rápida.

Existem várias formas e ferramentas que possibilitam executar um cluster k8s localmente. Aqui vou falar um pouco sobre o [_**Kind**_](https://kind.sigs.k8s.io/) (_Kubernetes in Docker_).

O _**kind**_ de forma resumida é uma forma de executar nodes kubernetes dentro de contêineres docker. Os nodes do _cluster_, na prática são _containers docker_.

## Cenário

Para deixar tudo alinhado, meu ambiente de trabalho é baseado em _GNU/Linux_, distribuição _Dedian Like_. Entretanto, o _Kind_ também tem suporte para Windows e Mac. Assim, apesar de aqui ser demonstrado tudo baseado no meu cenário, isso pode perfeitamente ser adaptado para a sua realidade, basta seguir a documentação oficial.

### Pré-requisitos:
Para execução desse tutorial:
- Distribuição Linux (Debian Like, Ubuntu, por exemplo).
- Docker (é compatível também com Podman).
Para melhor entendimento, recomenda-se ter conhecimento básico prévio sobre:
- Contêineres de aplicação
- Docker
- Kubernetes

## Instalação

Para instalar o _kind_ existem várias maneiras. Aqui será demonstrado conforme a [documentação oficial](https://kind.sigs.k8s.io/docs/user/quick-start#installation), mais especificamente através do método [_**Installing from Release Binaries**_](https://kind.sigs.k8s.io/docs/user/quick-start#installation).

**Etapas**:
- Download do binário (Aqui demonstrado para arquitetura AMD64/x86_64)
```shell
[ $(uname -m) = x86_64 ] && curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.22.0/kind-linux-amd64
```

- Adicionando permissão de execução ao binário
```shell
chmod +x ./kind
```

- Movendo o binário para um path que esteja na variável path do S.O.:
```shell
sudo mv ./kind /usr/local/bin/kind
```

![Instalação do Kind](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ja3o1snegg7es5yda49w.gif)

**Alguns esclarecimentos**:
No primeiro comando, o trecho **[ $(uname -m) = x86_64 ]** é uma condição que está validando se a arquitetura do sistema operacional é x86_64. Ou seja, ele valida se a saída do **uname -m** que está dentro de um subshell "**$()**" é igual a "x86_64", sendo igual, retornará sucesso.

Como após a condição, temos um "&&", a segunda parte só executada se a primeira teve como saída sucesso. É isso que significa o "&&" em uma linha de comando shell, explicando:  **comando1 && comando2**, só será executado o comando2 se o comando1 teve sucesso. No caso aqui, se arquitetura do S.O. for diferente do esperado, nem será realizado o download do binário.

No terceiro comando, caso queira consultar o path do seu S.O. para entender melhor para onde mover, basta digitar no terminal **echo $PATH**. No caso do Ubuntu, pode-se mover para **/usr/local/bin** que é um caminho padrão para instalação de binários adicionais no sistema.

## Criando o primeiro cluster

Para criar um cluster é trivial:
```shell
kind create cluster
```
Ou passando um name para o cluster, sim você consegue criar mais de um cluster inclusive:
```shell
kind create cluser --name euterpe
```
Quando o nome não é passado como parâmetro, será criado um cluster com o nome kind.

O nome é importante, pois será o _**context**_ usado no config que é usado pelo comando **_kubectl_**.

Caso queira listar os clusters criados com o kind:
```shell
kind get clusters
```

Quando tiver mais de um cluster, é necessário indicar ao kubectl o context. Exemplo:
```shell
kubectl cluster-info --context kind
kubectl cluster-info --context euterpe
```

Para excluir um cluster criado pelo kind:
```shell
kind delete cluster -n euterpe
```
Deve-se indicar o nome do cluster que quer excluir com a opção "-n" caso tenha mais de um cluster criado.

## Agora a coisa vai ficar séria!

Está tudo muito bem, mas nada demais até aqui. Agora, vamos criar um cluster com algumas customizações. 

Usando o kind, a forma de fazer isso é via um arquivo de configuração que é passado no momento da criação do cluster.

**Etapas**:
- Criar um arquivo de configuração do cluster no formato yaml (config.yaml):
```yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: euterpe
nodes:
- role: control-plane
  image: kindest/node:v1.27.11@sha256:681253009e68069b8e01aad36a1e0fa8cf18bb0ab3e5c4069b2e65cafdd70843
  kubeadmConfigPatches:
  - |
    kind: InitConfiguration
    nodeRegistration:
      kubeletExtraArgs:
        node-labels: "ingress-ready=true"
  extraPortMappings:
  - containerPort: 80
    hostPort: 80
    protocol: TCP
  - containerPort: 443
    hostPort: 443
    protocol: TCP
- role: worker
  image: kindest/node:v1.27.11@sha256:681253009e68069b8e01aad36a1e0fa8cf18bb0ab3e5c4069b2e65cafdd70843
  extraMounts:
  - hostPath: /opt/kind-data/worker01
    containerPath: /mnt/data
- role: worker
  image: kindest/node:v1.27.11@sha256:681253009e68069b8e01aad36a1e0fa8cf18bb0ab3e5c4069b2e65cafdd70843
  extraMounts:
  - hostPath: /opt/kind-data/worker02
    containerPath: /mnt/data
```

**Alguns pontos sobre o arquivo**:
1. Está sendo definido um cluster com 3 _nodes_, um _control-plane_ e 2 _workers_. Isso é definido nas linhas que contém "**- role:** ";
2. Está sendo definida uma versão específica de k8s, através do que é definido em "**image:** ". Ou seja, através da imagem do container que será usado, é definida a versão do k8s. Mais informações [aqui](https://github.com/kubernetes-sigs/kind/releases).
3. Através dos trechos "**kubeadmConfigPatches**" e "**extraPortMappings**", possibilita-se o uso de _ingress_ _controller_ no cluster local, como por exemplo, o _Nginx Ingress Controller_.
4. Nos _nodes workers_, foi definida uma opção "**extraMounts**", que permite montagem de volume entre os _nodes_ e o _host_ hospedeiro (seu computador). Isso ajuda em alguns cenários de persistência e transferência de dados.

- Criando o cluster a partir do arquivo de configuração criado, por exemplo, _**config.yaml**_ (o nome pode ser qualquer um):
```shell
kind create cluster --config config.yaml
```
Lembre-se que, para que o comando acima funcione, no terminal deverás estar dentro do diretório que contém o arquivo _config.yaml_. Se não, poderá ser passado o caminho completo do arquivo.

Se tudo deu certo, a saída no terminal será:

![Kind - Cluster criado](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gx5j9xvkzg6x9dwtqeyr.png)

Checando os _nodes_:
```shell
kubectl get nodes
```
Saída:
```shell                                                              
NAME                    STATUS   ROLES           AGE   VERSION
euterpe-control-plane   Ready    control-plane   32s   v1.27.11
euterpe-worker          Ready    <none>          9s    v1.27.11
euterpe-worker2         Ready    <none>          15s   v1.27.11
```
Pronto, seu cluster local está pronto!

## Considerações

Mas por que usar o kind?

Algumas razões para eu preferir o kind:
- suporte a clusters de vários nós (incluindo HA);
- suporte a construção de versões de lançamento do Kubernetes;
- suporte para Linux, macOS e Windows;
- é um instalador Kubernetes em conformidade com certificação [CNCF](https://landscape.cncf.io/?selected=kind&item=platform--certified-kubernetes-installer--kind).
- facilidade de uso, visto que é tudo via container, pode facilmente criar e excluir. Ideal para testes rápidos em ambiente de desenvolvimento local.

O kind oferece uma experiência excelente para iniciar clusters mais próximos de ambientes "reais" com kubernetes. 

É possível usar o kind em esteiras de CI/CD para ainda na pipeline subir um cluster com kind e fazer testes em seus manifestos ou charts helm. Assim, é possível validar QA e também testes de segurança, com a aplicação implantada inicialmente em um kind dentro de sua pipeline (github actions, gitlab ci/cd, etc).

Há mais aplicações e utilidades do kind em seu ambiente, tenho certeza.