Me lembro como se fosse hoje quando comecei a virtualizar o meu ambiente de desenvolvimento. Antes rodava tudo em uma VM do VirtualBox montando o diretório do meu projeto na VM. Com o passar dos tempos acabei conhecendo o Vagrant e mais a frente o Docker que foi amor à primeira vista! Desde então passei a gerenciar meu ambiente de desenvolvimento com docker-compose.
Participei de um movimento de migrar aplicações que rodam no heroku para o Google Cloud utilizando o serviço Kubernetes Engine o GKE. Nesse projeto eu trabalhei bem superficialmente com k8s, apelido do kubernetes. Atualmente venho trabalhando diariamente com essa ferramenta e neste artigo vou contar como foi todo o meu aprendizado e sintetizar os principais casos do dia a dia.
É um gerenciador de containers onde utilizamos uma sintaxe declarativa para criar nossos serviços na cloud. O kubernetes veio nessa era de containers para facilitar todas as operações e boas práticas que temos hoje disponíveis em cloud para deployar suas aplicações. Com isso foi sendo construído um ecossistema em volta dessa tecnologia com muitos serviços e plugins tais como recursos de monitoração, autoscale, blue-green deployments, service discovery e muitos outros disponíveis pela comunidade.
Fonte: kubernetes.io
De forma resumidamente o k8s é uma aplicação em Go que se comunica através de uma API. O Docker não consegue gerenciar containers de maneira remota e é aí que o k8s passa a fazer sentido. Essa arquitetura acima foi retirada do site oficial do kubernetes e pode ser acessada aqui onde temos a documentação que detalha esse processo por inteiro. Mas para vocês entenderem de uma forma geral, temos 2 nodes onde em 1 temos rodando a API do k8s com todo os seus componentes como etcd que é o banco de chave valor onde ficam salvas todas as configurações e no segundo node temos o kubelet que é o cliente responsável em se comunicar com a API do k8s e aplicar as alterações nos containers que rodam em cada máquina.
O objetivo desse artigo é ser um guia prático de como você pode executar os serviços em ambiente local ou até mesmo em cloud, não vou entrar em detalhes de como funciona todos os componentes do kubernetes. Para isso você pode e deve ler a documentação para entender como essa ferramenta irá te ajudar no dia a dia. Neste link você confere a documentação do Kubernetes que é bem completa e repleta de exemplos.
Agora precisamos instalar o nosso ambiente de trabalho que basicamente vai precisar do Docker, Kubernetes e algumas outras aplicações para deployar o nosso sistema.
Vamos precisar instalar o kubectl e o minikube para quem tem linux. No mac, o próprio docker já tem um suporte para subir um cluster k8s. Caso você esteja rodando no mac, segue um tutorial de como levantar um cluster local nesse link aqui.
Para você já sair executando os comandos do kubectl recomendo esses playgrounds:
Agora que já temos um um cluster rodando, vamos iniciar dar uma explorada nos principais comandos do k8s que vamos utilizar durante o desenvolvimento.
O k8s permite que você gerencie diversos clusters e por isso e sempre bom ver os que estão configurados com o comando kubectl config get-contexts
. Exemplo:
$ kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
docker-desktop docker-desktop docker-desktop
* docker-for-desktop docker-desktop docker-desktop
Para selecionar um contexto você roda o seguinte comando:
$ kubectl config use-context docker-for-desktop
Esses passos são importantes principalmente se você já tem acesso a um cluster k8s na sua máquina para não criar nada em cluster que já exista ;)
Vamos subir agora um Pod com o Wordpress baseado em uma imagem do Docker que está disponível no hub docker do wordpress para testar alguns dos comandos do k8s. Não se preocupe com o arquivo abaixo vamos entender ele melhor mais a frente ;)
Crie o arquivo wp-dumb.yaml com o seguinte conteudo abaixo:
apiVersion: v1
kind: Pod
metadata:
name: meu-blog
labels:
app: wordpress
spec:
containers:
- name: meu-blog-wp-1
image: wordpress:php7.2-fpm
ports:
- containerPort: 9000
Agora vamos subir o nosso primeiro Pod! Para isso vamos rodar o seguinte comando:
$ kubectl apply -f wp-dumb.yaml
Acima vimos o nosso primeiro comando o kubectl apply como vocês já viram, ele é responsável em aplicar alterações feita no arquivo wp-dumb.yaml. Após ele aplicar essa alteração o k8s se encarrega em subir um Pod com a configuração descrita no manifesto do aquivo wp-dumb.yaml. Agora podemos rodar outros comandos para visualizar como esta este Pod recem criado.
Para listar todos os pods rodando vamos executar o kubectl get:
$ kubectl get pods
#resultado
NAME READY STATUS RESTARTS AGE
meu-blog 1/1 Running 0 59s
O comando get diz como está o nosso Pod em nosso cluster. Veja em detalhes:
Aqui na documentação do k8s você tem todos os exemplos dos comandos a serem executados. Mas vamos falar dos que mais rodamos no dia a dia.
# para buscar um pod por nome
$ kubectl get pods meu-blog
# para buscar um pod por label
$ kubectl get pods -l app=wordpress
# para retornar em outro formato de output
$ kubectl get pods -l app=wordpress -o yaml
$ kubectl get pods -l app=wordpress -o json
Também podemos acessar esse Pod rodando o kubectl exec:
$ kubectl exec -it meu-blog bash
root@meu-blog:/var/www/html#
Descrição desse Pod rodando o kubectl describe:
$ kubectl describe pods -l app=wordpress
$ kubectl describe pods meu-blog
Copiando arquivos para o container ou do container para a sua máquina com o comando cp rodando o kubectl cp:
# criando um arquivo qualquer
$ echo "lala" > arquivo-lala.txt
# copiando um arquivo para o container
$ kubectl cp arquivo-lala.txt meu-blog:/var/www/html
# copiando um arquivo do container para sua maquina
$ kubectl cp meu-blog:/var/www/html/arquivo-lala.txt arquivo-lele.txt
Verificando CPU e Memoria com o comando top rodando o kubectl top:
$ kubectl top pods -l app=wordpress
$ kubectl top pods meu-blog
Remover um Pod rodando o kubectl delete:
$ kubectl delete pods -l app=wordpress
$ kubectl delete pods meu-blog
Se você chegou até aqui MEUS PARABÉNS você conseguiu subir um pod e principalmente executar uns dos comandos que mais utilizamos no dia a dia! Na documentação oficial, temos uma parte muito interessante com os “macetes” para servir como um guia quando você não se lembrar exatamente como é cada comando do k8s que é o kubectl Cheat Sheet.
Nosso aplicação que irá rodar no kubernetes vai ser um wordpress um dos principais cms do mundo. Teremos a seguinte arquitetura:
No exemplo anterior a gente utilizou o objeto Pod que é o objeto mais genérico do k8s. Aqui na documentação você tem todos os detalhes. Agora nesse exemplo vamos utilizar o Deployment para criar um Pod mais inteligente dizendo em seu manifesto a quantidade de réplicas que devem sempre executar em nosso cluster. Isso mesmo, o k8s com base no manifesto vai gerenciar a execução desse pod podendo remover e recriar o mesmo caso alguma coisa de errado aconteça. Vamos a esse manifesto:
Crie o arquivo wp-deployment.yaml com o seguinte conteúdo abaixo:
apiVersion: apps/v1
kind: Deployment
metadata:
name: meu-blog-escalavel
labels:
app: wordpress-escalavel
spec:
replicas: 3
selector:
matchLabels:
app: wordpress-escalavel
template:
metadata:
labels:
app: wordpress-escalavel
spec:
containers:
- name: wordpress
image: wordpress:5.4.2-php7.2-apache
ports:
- containerPort: 80
Agora vamos subir o nosso primeiro deployment!
$ kubectl apply -f wp-deployment.yaml
Sim temos 3 pods em execução vamos olhar rodando o comando get:
$ kubectl get pods -l app=wordpress-escalavel
NAME READY STATUS RESTARTS AGE
meu-blog-escalavel-69f498dc5b-25zb7 1/1 Running 0 19s
meu-blog-escalavel-69f498dc5b-7dx4z 1/1 Running 0 19s
meu-blog-escalavel-69f498dc5b-zbtvs 1/1 Running 0 19s
Agora vamos brincar com o k8s vamos deletar o um dos Pods criados e ficar dando o get para ver o que esta irá acontecer.
$ kubectl delete pod meu-blog-escalavel-69f498dc5b-c7hvd
pod "meu-blog-escalavel-69f498dc5b-c7hvd" deleted
$ kubectl get pods -l app=wordpress-escalavel
NAME READY STATUS RESTARTS AGE
meu-blog-escalavel-69f498dc5b-7dx4z 1/1 Running 0 4m33s
meu-blog-escalavel-69f498dc5b-c7hvd 0/1 Terminating 0 36s
meu-blog-escalavel-69f498dc5b-jb424 1/1 Running 0 6s
meu-blog-escalavel-69f498dc5b-zbtvs 1/1 Running 0 4m33s
Caso algum pode seja deletado o k8s sobe outro o mais rápido possível e mantém sempre o que está configurado no manifesto do arquivo wp-deployment.yaml. Agora vamos explorar novos comandos que os deployments tem que é o kubectl scale.
$ kubectl scale deployment meu-blog-escalavel --replicas=5
$ kubectl get pods -l app=wordpress-escalavel
NAME READY STATUS RESTARTS AGE
meu-blog-escalavel-69f498dc5b-66bbr 1/1 Running 0 7s
meu-blog-escalavel-69f498dc5b-7dx4z 1/1 Running 0 22h
meu-blog-escalavel-69f498dc5b-jb424 1/1 Running 0 22h
meu-blog-escalavel-69f498dc5b-x57f8 1/1 Running 0 7s
meu-blog-escalavel-69f498dc5b-zbtvs 1/1 Running 0 22h
Pronto nosso sistema do wordpress está escalável podendo subir ou diminuir réplicas. Agora falta a gente configurar o nosso load balancer, que no caso do k8s será o Service. Este é responsável em localizar o nosso deployment e expor o serviço do mesmo através de um endereço tendo o funcionamento comparado ao de um load balancer distribuindo a carga. Vamos a esse manifesto:
Crie o arquivo wp-service.yaml com o seguinte conteúdo abaixo:
apiVersion: v1
kind: Service
metadata:
name: meu-blog-escalavel-service
spec:
type: LoadBalancer
selector:
app: wordpress-escalavel
ports:
- protocol: TCP
port: 8080
targetPort: 80
Agora vamos subir o nosso primeiro service!
$ kubectl apply -f wp-service.yaml
Para visualizar o nosso service executando rodamos o comando get mas agora incluindo o tipo service. Sim o k8s segue um padrão e trocando o kind você lista somente os pods de um tipo específico.
$ kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
meu-blog-escalavel-service ClusterIP 10.102.166.220 localhost 8080/TCP 7m57s
Agora todos os nossos deployments ficam acessíveis através do service recém criado que consegue localizar os pods por conta da configuração de selector que utiliza o label aplicado a um pod para localizar para onde a requisição deve chegar. Agora basta chamar localhost:8080 que vamos bater no service e o mesmo redireciona o tráfego para os nossos deployments como um load balancer. Agora que já temos o nosso LB e wordpress de pé precisamos subir o nosso banco de dados. Vamos a esse manifesto:
Crie o arquivo wp-mariadb.yaml com o seguinte conteúdo abaixo:
apiVersion: apps/v1
kind: Deployment
metadata:
name: mariadb-wp
spec:
selector:
matchLabels:
app: mariadb-wp
strategy:
type: Recreate
template:
metadata:
labels:
app: mariadb-wp
spec:
containers:
- name: mariadb-wp
image: rtancman/mariadb-local
imagePullPolicy: "Always"
env:
- name: MYSQL_ROOT_PASSWORD
value: adminroot
- name: MYSQL_USER
value: wp-user
- name: MYSQL_PASSWORD
value: q1w2e3r4
- name: MYSQL_DATABASE
value: wp-k8s
ports:
- containerPort: 3306
name: mariadb-wp
Com isso agora como já sabemos, falta criar o nosso service e vamos lá! Crie o arquivo wp-mariadb-service.yaml com o seguinte conteúdo abaixo:
apiVersion: v1
kind: Service
metadata:
name: mariadb-service
spec:
type: LoadBalancer
selector:
app: mariadb-wp
ports:
- protocol: TCP
port: 3306
targetPort: 3306
Agora vamos dar apply em todos os manifestos recém criados:
$ kubectl apply -f wp-mariadb.yaml
$ kubectl apply -f wp-mariadb-service.yaml
Agora temos o nosso banco rodando! Com isso vamos alterar o nosso manifesto do wp-deployment.yaml para incluir as variáveis de ambiente que tem o acesso ao banco de dados.
Altere o arquivo wp-deployment.yaml com o seguinte conteúdo abaixo:
apiVersion: apps/v1
kind: Deployment
metadata:
name: meu-blog-escalavel
labels:
app: wordpress-escalavel
spec:
replicas: 3
selector:
matchLabels:
app: wordpress-escalavel
template:
metadata:
labels:
app: wordpress-escalavel
spec:
containers:
- name: wordpress
image: wordpress:5.4.2-php7.2-apache
env:
- name: WORDPRESS_DB_HOST
value: mariadb-service
- name: WORDPRESS_DB_USER
value: wp-user
- name: WORDPRESS_DB_PASSWORD
value: q1w2e3r4
- name: WORDPRESS_DB_NAME
value: wp-k8s
ports:
- containerPort: 80
MEUS PARABÉNS! Você acabou de configurar a nossa arquitetura proposta no exemplo e tudo esta deve estar rodando normalmente se você acessar o http://localhost:8080/ deve cair na página de configuração do wordpress e seguindo os passos você terá o mesmo rodando no seu cluster k8s \o/.
Kubernetes é uma ferramenta com muitos plugins e serviços e irei fazer um novo post melhorando essa nossa arquitetura utilizando outros objetos do k8s como o Secrets, Configmap, PersistentVolume e PersistentVolumeClaim.
Referências:
Grande abraço xD