Kubernetes Labs

Nas conversas informais do dia a dia quando se fala em cluster Kubernetes uma coisa é unânime, todo mundo concorda que é uma excelente ferramenta e é para onde toda infraestrutura deve ser migranda. Kubernetes ficou famoso, virou hype, virou uma buzzword, todo mundo quer usá-lo para tudo, mesmo que ele não se encaixe nas necessidades do projeto, mesmo assim ele tem gerado uma bastante demanda de instalação e gestão em muitos times de TI.

Outra coisa bem fácil de ouvir em qualquer conversa informal em “tribos” de TI, Kubernetes é difícil de aprender e complicado de gerenciar. Hummmm!!! Isso depende, se estiver falando de um cluster com muitos nós em múltiplas localidades, com múltiplas finalidades, com múltiplos modelos de armazenamento de dados e múltiplos requisitos de disponibilidade e de segurança, realmente vai ficando mais e mais complexo e sem dúvida requer uma mão de obra igualmente especializada. Por outro lado, quando se fala em dar os primeiros passos no mundo do Kubernetes não é necessário nada complicado, basta uma instalação de apenas um nó para validar os conceitos mais básicos e se familiarizar com suas funcionalidades e APIs.

Este post é justamente para isso, matar esse medo inicial de ter contato com Kubernetes e testar funcionalidades básicas abrindo o caminho para futuras configurações mais complexas. Vamos ver isso então?!!!

Infraestrutura Kubernetes LAB

Para esse ambiente foi preparada uma VM com Vagrant mais VirtualBox instalado o Minikube. Caso não conheça o Vagrant recomendo a leitura de um posto antigo Conhecendo o Vagrant. Minikube é uma versão do Kubernetes feita pra ser executada em uma VM dentro de um laptop, com ele é possível simular manipulação de DNS, NodePorts, ConfigMaps and Secrets, Ingress entre outras funcionalidades.

Todas as configurações do laboratório estão no Vagrantfile, para iniciar a sequência de criação baixe os arquivos Vagrantfile e Ansible playbook para sua máquina e execute o seguinte comando:

vagrant up --provision
Vagrantfile 

 1# -*- mode: ruby -*-
 2# vi: set ft=ruby :
 3
 4
 5Vagrant.configure("2") do |config|
 6
 7  hostname = "minikube"
 8  config.vm.box = "bento/ubuntu-18.04"
 9  config.vm.hostname = hostname
10  config.vm.box_url = "bento/ubuntu-18.04"
11  config.vm.boot_timeout = 3600
12  config.vm.network "private_network", type: "dhcp"
13  config.vm.network :forwarded_port, id:"IaC regra 01", guest:22, host: 2291 , guest_ip: '10.0.2.15' , host_ip: '127.0.0.1', auto_correct: true
14  config.vm.network :forwarded_port, id:"IaC regra 02", guest:80, host: 8091 , guest_ip: '10.0.2.15' , host_ip: '127.0.0.1', auto_correct: true
15  config.vm.provider :virtualbox do |v|
16   v.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
17   v.customize ["modifyvm", :id, "--memory", 2048]
18   v.customize ["modifyvm", :id, "--name", hostname ]
19   v.customize ["modifyvm", :id, "--cpus", 2]
20  end
21  config.vm.provision "shell",
22   inline: "sudo apt update ; sudo apt install python3-pip -y; sudo pip3 install ansible; \
23   sudo ansible-playbook -i localhost /vagrant/minikube_playbook.yaml"
24end
25
26#EOF

Referência: Vagrantfile

Na sequência de criação será chamado um playbook Ansible para realizar a configuração do ambiente.

Ansible playbook

 1- name: -= Minikube set up =-
 2 hosts: localhost
 3 vars:
 4  local_user: infraascode
 5  kubectl_version: "v1.18.3"
 6 become: true
 7
 8 tasks:
 9  - name: -= Install packages =-
10   package:
11    name: "{{ item }}"
12    state: present
13   with_items:
14    - docker
15    - docker.io
16    - docker-containerd
17    - yamllint
18    - conntrack
19
20  - name: -= Add the user Infra as code =-
21   user:
22    name: "{{ local_user }}"
23    comment: Infra as code
24    password: $1$ZMzmP4r5$XRc0/vgQh2TNaPh8s092V.
25    shell: /bin/bash
26    groups: docker
27    append: yes
28
29  - name: -= Add sudo to user {{ local_user }} =-
30   lineinfile:
31    path: "/etc/sudoers.d/99_{{ local_user }}"
32    line: "{{ local_user }} ALL=(ALL:ALL) NOPASSWD:ALL"
33    create: yes
34
35  - name: -= How to start minikube =-
36   blockinfile:
37    path: /home/{{ local_user }}/.bashrc
38    insertafter: EOF
39    block: |
40     clear
41     echo "####################################"
42     echo " "
43     echo minikube start --vm-driver=docker
44     echo " "
45     echo "####################################"
46  - name: -= Download Minikube and Kubectl =-
47   get_url:
48    url: "{{ item.url }}"
49    dest: "/usr/local/bin/{{ item.name }}"
50    mode: '0775'
51   with_items:
52    - { url: 'https://storage.googleapis.com/kubernetes-release/release/{{ kubectl_version }}/bin/linux/amd64/kubectl', name: 'kubectl' }
53    - { url: 'https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64', name: 'minikube' }
54
55#EOF

Referência: Ansible playbook

Validando a instalação

Para realizar a validação da instalação deve-se dar um ssh para a VM criada utilizando como login: infraascode e senha: infraascode.

ssh infraascodebr@localhost -p 2291

Kubernetes LAB

Iniciando o cluster Kubernetes

Iniciar o Kubernetes leva-se aproximadamente de 3 a 5 minutos dependendo da velocidade da sua conexão com a Internet e da velocidade do seu laptop.

Iniciando o minikube

infraascodebr@minikube:~$ minikube start --vm-driver=docker

😄 minikube v1.11.0 on Ubuntu 18.04 (vbox/amd64)
✨ Using the docker driver based on user configuration
👍 Starting control plane node minikube in cluster minikube
🚜 Pulling base image ...
💾 Downloading Kubernetes v1.18.3 preload ...
  > preloaded-images-k8s-v3-v1.18.3-docker-overlay2-amd64.tar.lz4: 526.01 MiB
🔥 Creating docker container (CPUs=2, Memory=1993MB) ...
🐳 Preparing Kubernetes v1.18.3 on Docker 19.03.2 ...
  ▪ kubeadm.pod-network-cidr=10.244.0.0/16
🔎 Verifying Kubernetes components...
❗ Executing "docker container inspect minikube --format={{.State.Status}}" took an unusually long time: 11.794389432s
💡 Restarting the docker service may improve performance.
❗ Executing "docker container inspect minikube --format={{.State.Status}}" took an unusually long time: 11.755167669s
💡 Restarting the docker service may improve performance.
❗ Executing "docker container inspect minikube --format={{.State.Status}}" took an unusually long time: 7.561670361s
💡 Restarting the docker service may improve performance.
🌟 Enabled addons: default-storageclass, storage-provisioner
🏄 Done! kubectl is now configured to use "minikube"

Verificando o status do Minikube

infraascodebr@minikube:~$ minikube status
minikube
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured

Verificando o status do Kubernetes

infraascodebr@minikube:~$ kubectl get nodes
NAME    STATUS  ROLES  AGE   VERSION
minikube  Ready  master  4m58s  v1.18.3

Criando um namespace

infraascodebr@minikube:~$ kubectl get namespaces
NAME       STATUS  AGE
default      Active  50m
kube-node-lease  Active  50m
kube-public    Active  50m
kube-system    Active  50m
infraascodebr@minikube:~$ kubectl create namespace infraascode
namespace/infraascode created
infraascodebr@minikube:~$ kubectl get namespaces
NAME       STATUS  AGE
default      Active  50m
infraascode    Active  4s   <<< Criado com sucesso!
kube-node-lease  Active  50m
kube-public    Active  50m
kube-system    Active  50m
infraascodebr@minikube:~$

Referência: Namespace Mais informações em https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/

Criando um deployment

infraascodebr@minikube:~$ kubectl create deployment --image nginx nginx-infraascode -n infraascode
deployment.apps/nginx-infraascode created

infraascodebr@minikube:~$ kubectl get deployment -n infraascode
NAME        READY  UP-TO-DATE  AVAILABLE  AGE
nginx-infraascode  0/1   1      0      16s

infraascodebr@minikube:~$ kubectl describe deployment nginx-infraascode -n infraascode
Name:          nginx-infraascode
Namespace:       infraascode
CreationTimestamp:   Sun, 31 May 2020 16:31:10 +0000
Labels:         app=nginx-infraascode
Annotations:      deployment.kubernetes.io/revision: 1
Selector:        app=nginx-infraascode
Replicas:        1 desired | 1 updated | 1 total | 1 available | 0 unavailable
StrategyType:      RollingUpdate
MinReadySeconds:    0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
 Labels: app=nginx-infraascode
 Containers:
  nginx:
  Image:    nginx
  Port:     <none>
  Host Port:  <none>
  Environment: <none>
  Mounts:    <none>
 Volumes:    <none>
Conditions:
 Type      Status Reason
 ----      ------ ------
 Available   True  MinimumReplicasAvailable
 Progressing  True  NewReplicaSetAvailable
OldReplicaSets: <none>
NewReplicaSet:  nginx-infraascode-df6b47fc (1/1 replicas created)
Events:
 Type  Reason       Age  From          Message
 ----  ------       ---- ----          -------
 Normal ScalingReplicaSet 35s  deployment-controller Scaled up replica set nginx-infraascode-df6b47fc to 1
infraascodebr@minikube:~$ 

Aumentando para três (03) o número de pods dessa aplicação

infraascodebr@minikube:~$ kubectl get service -n infraascode
No resources found in infraascode namespace.
infraascodebr@minikube:~$ kubectl get deployments -n infraascode
NAME        READY  UP-TO-DATE  AVAILABLE  AGE
nginx-infraascode  1/1   1      1      9m9s
infraascodebr@minikube:~$ kubectl get pods -n infraascode
NAME                READY  STATUS  RESTARTS  AGE
nginx-infraascode-df6b47fc-fz82c  1/1   Running  0     9m35s

infraascodebr@minikube:~$ kubectl scale deployment --replicas 3 nginx-infraascode -n infraascode
deployment.apps/nginx-infraascode scaled
infraascodebr@minikube:~$ kubectl get pods -n infraascode
NAME                READY  STATUS       RESTARTS  AGE
nginx-infraascode-df6b47fc-dqb9d  0/1   ContainerCreating  0     4s
nginx-infraascode-df6b47fc-fz82c  1/1   Running       0     9m55s
nginx-infraascode-df6b47fc-mhx7c  0/1   ContainerCreating  0     4s

Referência Deployment

Criando um service

Criando um serviço e tornando disponível para o mundo externo.

infraascodebr@minikube:~$ kubectl expose deployment nginx-infraascode --port=80 --type=LoadBalancer -n infraascode service/nginx-infraascode exposed

infraascodebr@minikube:~$ kubectl get services -n infraascode
NAME        TYPE      CLUSTER-IP    EXTERNAL-IP  PORT(S)    AGE
nginx-infraascode  LoadBalancer  10.102.212.151  <pending>   80:30811/TCP  17s

Perceba que LoadBalancer está com status de < pending >, isso acontece porque no Minikube esse tipo de serviço só é disponível via comando » minikube service «, vejamos como fica.

infraascodebr@minikube:~$ minikube service nginx-infraascode
💣 Service 'nginx-infraascode' was not found in 'default' namespace.
You may select another namespace by using 'minikube service nginx-infraascode -n <namespace>'. Or list out all the services using 'minikube service list'
infraascodebr@minikube:~$ minikube service nginx-infraascode -n infraascode
|-------------|-------------------|-------------|-------------------------|
| NAMESPACE |    NAME    | TARGET PORT |      URL      |
|-------------|-------------------|-------------|-------------------------|
| infraascode | nginx-infraascode |     80 | http://172.17.0.3:30811 |
|-------------|-------------------|-------------|-------------------------|
🎉 Opening service infraascode/nginx-infraascode in default browser...
👉 http://172.17.0.3:30811
infraascodebr@minikube:~$ curl http://172.17.0.3:30811
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
  body {
    width: 35em;
    margin: 0 auto;
    font-family: Tahoma, Verdana, Arial, sans-serif;
  }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
infraascodebr@minikube:~$

Aplicação foi validada com sucesso!!

Referência Service

Criando uma aplicação de demonstração

A infra está pronta!!! Agora é sua vez meu jovem!! ;) ;) .. Siga os passos desse exemplo Deploying PHP Guestbook application with Redis para exercitar os conceitos apresentados!!!!

Mais exercícios:

Conclusão

O Minikube em uma VM é uma alternativa de baixo custo financeiro e computacional, em conjunto com os scripts fornecidos neste post é um bom ponto de partida para treinar o básico perder o medo e partir para conhecimentos mais profundo do Kubernetes.

Uma vez familiarizado com o básico do Kubernetes recomendo buscar mais informações na documentação oficial e conhecer os componentes do Kubernetes e explorar os tutoriais oficiais.

REFERÊNCIAS


Eu adoraria ouvir suas outras histórias e situações semelhantes ao que acabei de escrever neste post, você pode me encontrar em @infraascode_br ou linkedin.com/in/leonardoml/ .

Te convido a ver os outros posts do blog Infra-as-Code garanto que tem coisas legais lá!!


--- --- IMPORTANTE --- ---
As opiniões aqui expressas são pessoais e de responsabilidade única e exclusiva do autor, elas não refletem necessariamente a posição das empresas que eu trabalho(ei) e/ou presto(ei) serviço.