TL;DR; Vamos aprender a criar um cluster de Kubernetes em cloud da forma mais simples possível utilizando o kubeadm. No fim desse tutorial você terá uma aplicação em Node.js entregue e replicada no cluster para ser consumida externamente via API.

Não teremos a preocupação de abordar conceitos básicos do funcionamento do Kubernetes. Para entender a arquitetura de um cluster de uma forma mais detalhada, você pode conferir a documentação nesse link mágico.

Arquitetura Básica

A ideia desse tutorial é não focar em um provedor de cloud específico, você terá que levar em conta todas as peculiaridades de cada um na hora de provisionar a infra base necessária.

Nesse tutorial, teremos a seguinte estrutura:

  • 1 servidor master; responsável por orquestrar as operações do cluster, realizar deploys, comandar os healthchecks e etc.
  • 2 servidores workers; estes serão responsáveis por receber os pods da aplicação, fazer proxy entre os mesmos e garantir a quantidade de containers solicitada rodando entre eles.

Bootstrap Inicial das Máquinas do Cluster

Precisamos rodar algumas coisinhas pra fazer o Kubernetes funcionar, como o Docker e alguns CLI’s de bootstrap e administração, como o kubectl e o mágico kubeadm. Execute esses passos em todas as máquinas do cluster, tanto master quanto os nodes.

Instalando o Docker

Vamos fazer o download do Docker na versão mais recente.

apt-get update
apt-get install -y apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
add-apt-repository "deb https://download.docker.com/linux/$(. /etc/os-release; echo "$ID") $(lsb_release -cs) stable"
apt-get update && apt-get install -y docker-ce=$(apt-cache madison docker-ce | grep 17.03 | head -1 | awk '{print $3}')

Instalando as ferramentas do Kubernetes

O Kubernetes possui uma gama muito grande de plugins, extensões e CLI’s de produtividade. Nesse exemplo, o principal agente da criação do cluster será o kubeadm, ele irá abstrair toda a dificuldade da criação de clusters.

Mais em detalhes:

  • kubeadm — Tool para realizar o bootstrap do Cluster
  • kubelet — Tool que roda em todos os nodes gerenciando os papéis, iniciando pods, containers e mantendo os mesmos saudáveis.
  • kubectl — Tool para realizar a comunicação com o cluster e executar todas as operações de orquestração.
apt-get update && apt-get install -y apt-transport-https curl
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
cat </etc/apt/sources.list.d/kubernetes.list
deb http://apt.kubernetes.io/ kubernetes-xenial main
EOF
apt-get update
apt-get install -y kubelet kubeadm kubectl

Iniciando o Node Master

Vamos iniciar o cluster utilizando o mágico kubeadm . Conecte-se no node master do cluster, após realizar a instalação do Docker e das ferramentas de CLI, e execute o comando:

kubeadm init

Após o termino do comando, ele irá cuspir alguns outros comandos a serem executados para finalizar a configuração, e principalmente o comando que iremos utilizar para ingressar os nodes no nosso cluster.

Your Kubernetes master has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/
You can now join any number of machines by running the following on each node
as root:
Your Kubernetes master has initialized successfully!
To start using your cluster, you need to run the following as a regular user:

mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/
You can now join any number of machines by running the following on each node
as root:

kubeadm join 172.31.85.6:6443 --token izzg7r.ueqzp7ndzxp8g5xq --discovery-token-ca-cert-hash sha256:e0244a52257be9e8cba49303e0472eb25020c6bd6c68f583653ed1700260fd0a

Agora temos que fazer algo bem importante, que é fazer deploy da rede do cluster. Neste exemplo, vamos utilizar o Project Calico para gerenciar a rede do nosso cluster.

kubectl apply -f https://docs.projectcalico.org/v2.6/getting-started/kubernetes/installation/hosted/kubeadm/1.6/calico.yaml

Iniciando os Nodes

Após instalarem o Docker e os CLI’s do Kubernetes em todos os nodes vamos rodar o comando informado na inicialização do cluster. Ele é baseado na seguinte estrutura.

kubeadm join :6443 --token   --discovery-token-ca-cert-hash sha256:

No caso do exemplo é só entrar em todos os nodes e executar

kubeadm join 172.31.85.6:6443 --token izzg7r.ueqzp7ndzxp8g5xq --discovery-token-ca-cert-hash sha256:e0244a52257be9e8cba49303e0472eb25020c6bd6c68f583653ed1700260fd0a

Após executar o comando gerado na criação to cluster em todos os Nodes, podemos a partir do master listar todos os nodes vinculados ao cluster.

kubectl get nodes

O output deverá ser parecido com:

root@k8s-master:/home/ubuntu# kubectl get nodes
NAME           STATUS    ROLES     AGE       VERSION
k8s-master     Ready     master    1h        v1.10.4
k8s-worker01   Ready     xyz       15m       v1.10.4
k8s-worker02   Ready     xyz       15m       v1.10.4
root@k8s-master:/home/ubuntu#

Realizando o Deploy de uma aplicação no Cluster

Captura de Tela 2018-06-18 às 15.26.13

Vamos fazer deploy de uma aplicação simples que eu criei para esse exemplo.

Crie um arquivo chamado deploy.yml. Nele vamos criar um Replication Controller para garantir a quantidade de pods que queremos rodando no cluster. Nele vamos export a porta 3000 dos containers.

Depois criar um Service de NodePort que irá mapear a porta do host para o container. Vamos fazer um mapeamento da porta 30001 dos nodes para a 3000 do containers. Funciona como um load balancer/proxy simplificado. Bem simples.

apiVersion: v1
kind: ReplicationController
metadata:
  name: microapi
spec:
  replicas: 5
  template:
    metadata:
      labels:
        app: microapi
    spec:
      containers:
      - name: microapi
        image: msfidelis/micro-api:latest
        imagePullPolicy: Always
        ports:
        - containerPort: 3000

---

apiVersion: v1
kind: Service
apiVersion: v1
metadata:
  name: microapi
spec:
  type: NodePort
  ports:
    - port: 3000
      nodePort: 30001
  selector:
    app: microapi  

Agora vamos aplicar as modificações.

kubectl apply -f deploy.yml

O output deverá ser parecido com esse:

replicationcontroller "microapi" created
service "microapi-ports" created

Agora vamos listar nossos pods existentes no cluster para conferir se está tudo ok:

kubectl get pods

O output deverá ser parecido com esse, mostrando 5 pods que estão rodando a nossa aplicação.

NAME       DESIRED   CURRENT   READY     AGE
microapi   5         5         5         3m
NAME             READY     STATUS    RESTARTS   AGE
microapi-4xgj9   1/1       Running   0          3m
microapi-h255v   1/1       Running   0          3m
microapi-h9wrj   1/1       Running   0          3m
microapi-hk7th   1/1       Running   0          3m
microapi-lxv2h   1/1       Running   0          3m
root@k8s-master:/home/ubuntu#

Desse modo, podemos fazer uma requisição para qualquer um dos nodes na porta 30001 para acessar os recursos da nossa API.

curl -i http://localhost:30001/system #oooou
curl -i http://ip-do-node:30001/system

O output deverá apresentar informações do sistema em que o container está rodando. Faça várias requisições e veja a variação da key hostname, para validar como o proxy entre os nodes está funcionando.

HTTP/1.1 200 OK
content-type: application/json; charset=utf-8
cache-control: no-cache
content-length: 322
accept-ranges: bytes
Date: Mon, 18 Jun 2018 18:12:57 GMT
Connection: keep-alive
{"hostname":"microapi-h255v","os":{"type":"Linux","platform":"linux","release":"4.4.0-1060-aws","arch":"x64"},"resources":{"memory":{"limit":1038864384,"free":174473216},"cpus":[{"model":"Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz","speed":2400,"times":{"user":1117800,"nice":51400,"sys":419300,"idle":82950000,"irq":0}}]}}

Esse modo exposição do serviço usando NodePorts é muito bacana caso você tenha algum outro balanceador de carga na frente dos nodes do seu cluster, como o ALB ou ELB da AWS. Funciona que é bala 🙂

  • Esse exemplo foi construído em cima de máquinas EC2 na AWS. A ideia era não focar em nenhum provider de cloud em especifico, porém nesse caso, você vai ter que liberar o tráfego total entre os nodes para garantir um bom funcionamento.
  • Uma dica é criar um Security Group para o cluster e liberar todo o tráfego entre todas as portas para conexões que compartilhem o mesmo security group, dessa forma:

Captura de Tela 2018-06-18 às 15.21.03

 

Espero ter ajudado!