Fala pessoal, tudo bem?
Eu particularmente gosto bastante de compartilhar laboratórios, pq assim além de vermos a teoria, já vemos também a prática de algo funcionando.
Mas afinal, o que é CI/CD em uma cultura DevOps?
CI/CD é o conjunto de práticas que automatiza o caminho do código, desde o commit até estar rodando em produção. Na cultura DevOps, ele é o “motor” que permite entregar mudanças pequenas, rápidas e com segurança.
O que significa cada parte
CI (Integração Contínua): cada vez que alguém envia código ao repositório, um pipeline automático faz o build e roda os testes. O objetivo é descobrir erros em minutos, e não dias depois, quando várias mudanças já se misturaram. Isso incentiva commits pequenos e frequentes na branch principal.
CD tem dois significados:
- Entrega Contínua (Continuous Delivery): todo código que passa nos testes fica pronto para ir a produção, mas o deploy final depende de uma aprovação manual (um clique).
- Implantação Contínua (Continuous Deployment): vai além, e o deploy em produção acontece automaticamente, sem aprovação humana, desde que todos os testes passem.
Qual o papel na cultura DevOps
DevOps não é uma ferramenta, é uma cultura que une desenvolvimento (Dev) e operações (Ops) em torno de responsabilidade compartilhada pelo ciclo completo do software. O CI/CD é a materialização técnica dessa cultura:
- Automação no lugar de processos manuais: deploys deixam de ser eventos arriscados, feitos “na mão” e só por quem sabe o passo a passo.
- Feedback rápido: o time sabe logo se uma mudança quebrou algo.
- Mudanças pequenas e frequentes: quanto menor a mudança, menor o risco e mais fácil o rollback.
- Responsabilidade compartilhada: quem escreve o código também acompanha o que acontece quando ele chega a produção.
- Tudo como código: pipeline, infraestrutura e manifests ficam versionados no Git (pipeline as code, IaC, GitOps), o que dá rastreabilidade e reprodutibilidade.
- Qualidade e segurança embutidas: testes, análise de código e scan de vulnerabilidades rodam em todo commit (o chamado shift left, ou DevSecOps).
Benefícios medidos
Times de alta performance costumam acompanhar as métricas DORA:
Para esse lab, eu pensei no seguinte:
Então, nosso primeiro passo, será preparar algumas coisas.
Isso mesmo...
Mesmo sendo um processo automatizado, em algum momento existem partes disso que precisam ser configuradas inicialmente para que na sequência tudo possa ocorrer de forma automática, rápida e em escala.
Primeiro passo - Criar nosso cluster kubernetes usando o kind
Alguns passos eu vou resumir um pouco para que o post não fique muito extenso.
Kind = Kubernetes in Docker
É uma solução que executa um cluster k8s localmente em nosso computador, através do Docker. Então para isso, vc precisará ter instalado o Docker e também o app do kind.
Sempre que possível para esses procedimentos, consultem a documentação oficial.
Instalação do Docker - https://docs.docker.com/desktop/setup/install/windows-install/
Instalação do Kind - https://kind.sigs.k8s.io/docs/user/quick-start/
Perfeito!!!
Tudo instalado, vamos criar o cluster no kind e conforme nossa arquitetura proposta:
Nesse passo, nós vamos usar o seguinte arquivo com as premissas:
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: k8s-local
nodes:
- role: control-plane
- role: worker
- role: worker
Na hora de salvar, o nome que dei para o arquivo foi: k8s-cluster.yaml
O nome, vc pode escolher o que achar melhor dentro da sua organização, mas a extensão .yaml é obrigatória.
Só lembrando, que para o próximo passo funcionar, o Docker precisa estar rodando no seu computador.
Para criar o cluster, vamos abrir a linha de comando.
kind create cluster --config k8s-cluster.yaml
Enquanto ele vai criando o cluster, vamos fazer um resumo do que foi adicionado neste arquivo:
- O tipo para informar que é um Cluster;
- apiVersion é a API que o kind irá usar para poder criar o Cluster;
- name é o nome que queremos dar para nosso Cluster;
- nodes/role, são as informações pertinentes ao control-plane e workers que vamos criar. No nosso caso, não estamos criando nenhuma role;
Voltando ao terminal, dando tudo certo devemos ter algo assim:
Agora, para que possamos administrar nosso cluster k8s, precisamos ter instalado o kubectl através do kubeadm - https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/
Com as ferramentas administrativas instaladas, vamos ver como está nosso cluster com o comando:
kubectl get nodes
Tudo funcionando. Os nossos 2 workers (Ready), nosso control-plane (Ready), todos na versão 1.37.0.
Já temos a base da infraestrutura onde nossa aplicação ou aplicações irão rodar.
Segundo passo - Criar repositório no GitHub
Para isso, vamos acessar a URL - https://github.com, autenticar com a nossa conta (caso não tenha, vc precisará criar uma).
Aparecendo a nossa home, no canto superior direito - New repository
Na tela seguinte, precisaremos informar o nome do repositório e se ele será público ou privado.
Aqui vale destacar que cada cenário pode ser de um jeito, tanto quanto a organização de nomes quanto a ser público ou privado.
Eu vou seguir uma lógica da seguinte forma:
- Será um repositório por site/empresa, então a convenção do nome será "site-nome_da_empresa"
- Por padrão e segurança, repositório privado
Assim que criarmos, recebemos algumas informações do próprio GitHub para iniciarmos o uso do nosso repositório.
Por enquanto, vamos salvar essas informações que estão aparecendo ao criar o repositório. Iremos usá-las mais pra frente.
Terceiro passo - Preparando o GitHub Actions
Agora vem um detalhe importante.
Como nosso lab, o nosso cluster do kubernetes está rodando localmente, temos limitações de comunicação a ele.
Deste modo, ao invés de usarmos o GitHub Actions direto no site do GitHub iremos usar o modelo Self-hosted runner.
O self-hostes runner consiste em disponibilizarmos o runner do actions em nosso próprio ambiente. Ele será a ponte de comunicação entre nosso repositório, o workflow do CI/CD e por fim, com nosso cluster kubernetes.
Para configurar o runner, vamos no nosso repositório, clicar em Settings - Actions - Runners
Depois vamos clicar em "New self-hosted ruuner
Agora o GitHub irá fornecer os próximos passos de configuração, por que irá depender do ambiente que estamos utilizando.
Deste modo, essa parte eu vou fazer de acordo com meu ambiente que é linux.
Mas basta cada um seguir exatamente como está no procedimento que dará certo.
Assim que o processo de start do runner finalizar, ele está pronto em listening para esperar as actions que terá que executar.
Quarto passo - Preparando nossa aplicação e workflow de deploy
Agora, vamos preparar em um diretório do nosso computador os arquivos do site, os arquivos do workflow que o actions irá usar e os arquivos de deploy no kubernetes.
Crie uma pasta chamada site-engenharia e dentro dela, vamos criar a seguinte estrutura
Uma pasta chamada k8s;
Um arquivo chamado Dockerfile;
Um arquivo chamado index.html;
Dentro da pasta k8s
Vamos criar um arquivo chamado deployment.yaml com o seguinte conteúdo:
apiVersion: apps/v1
kind: Deployment
metadata:
name: site-engenharia
spec:
replicas: 2
selector:
matchLabels:
app: site-engenharia
template:
metadata:
labels:
app: site-engenharia
spec:
containers:
- name: nginx
image: IMAGE_PLACEHOLDER
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
Esse será o arquivo utilizado no kubernetes para subir nosso Pod com as labels de identificação para "site-engenharia" com um container nginx e a imagem que iremos fornece futuramente no Dockerfile, respondendo na porta 80.
Agora na mesma pasta do k8s, vamos criar o arquivo de deploy do service. Vamos chamá-lo de service.yaml com o seguinte conteúdo:
apiVersion: v1
kind: Service
metadata:
name: site-engenharia
spec:
selector:
app: site-engenharia
ports:
- port: 80
targetPort: 80
Isso fará com que nosso serviço do site-engenharia esteja "exposto" pelo kubernetes.
Agora, vamos voltar para a pasta raiz site-engenharia e criar o arquivo Dockerfile com o seguinte conteúdo:
FROM nginx:alpine
COPY index.html /usr/share/nginx/html/
Isso instruirá nosso deploy a usar a imagem do nginx:alpine e copiar o nosso arquivo index.html para o path que o nginx irá ler dentro do Pod.
Neste momento, vamos utilizar uma imagem pública do nginx mesmo, mas é possível futuramente começar a usar nossas próprias imagens.
Agora, vamos criar o arquivo do nosso site, o index.html com o seguinte conteúdo:
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<title>Meu Site</title>
</head>
<body>
<h1>Meu site está rodando no Kubernetes!</h1>
</body>
</html>
Neste primeiro momento, será bem simples mesmo.
E por fim, vamos criar um diretório oculto e dentro dele o arquivo do workflow que o runner irá consumir.
Diterório .github/workflows/
Dentro dele o arquivo deploy-site-engenharia.yml (isso mesmo, aqui é yml)
O conteúdo dele será:
name: deploy-site-engenharia
on:
push:
branches: [main]
paths:
- "site-engenharia/**"
- "Dockerfile"
- "k8s/**"
workflow_dispatch:
jobs:
deploy:
runs-on: self-hosted
env:
IMAGE: site:${{ github.sha }}
steps:
- uses: actions/checkout@v4
- name: Build da imagem
run: docker build -t $IMAGE .
- name: Carregar imagem no kind
run: kind load docker-image $IMAGE --name k8s-local
- name: Deploy
run: |
sed "s|IMAGE_PLACEHOLDER|$IMAGE|" k8s/deployment.yaml | kubectl apply -f -
kubectl apply -f k8s/service.yaml
kubectl rollout status deployment/site-engenharia --timeout=60s
Quinto passo - Mandando nossa aplicação para o GitHub
Ao enviarmos tudo para o GitHub, iremos enviar também o arquivo do actions, e ele fará com que o deploy se inicie.
Isso vai acontecer por que foi a condição que criamos no nosso actions. Na maioria do ambientes, ainda mais em larga escala e com várias dependências, possa ser necessário mudar isso para que seja feito o start manualmente e através de fluxo de mudança.
Para enviar os arquivos, vamos entrar na pasta site-engenharia e vamos rodar os comandos que salvamos quando criamos o repositório no GitHub... lembra?
Mas antes disso, precisamos autenticar nosso repo local a nossa conta do GitHub, para isso, basta vc instalar o utiitário gh e rodar o comando
gh auth login
Esse comando fará com que seja aberto seu navegador, e dê permissão para acessar seu repo, informando o número que ele vai gerar na linha de comando e uma confirmação por e-mail (tudo pela segurança).
Rodar os comandos
git config --global user.email "seu email"
git config --global user.name "seu nome"
Agora sim, pode rodar os comandos que o seu repo te passou.
Isso vai fazer com que seja enviado o seu primeiro commit para lá, enviando apenas o arquivo REAME.md.
Agora, vamos enviar realmente todos os arquivos.
Para isso
git add .
git commit -m "Enviando site e actions"
git push
Volte no seu repo no site do GitHub e clique em Actions
Você verá que o actions começou a trabalhar no deploy.
Clicando no nome do action (que adota o nome do comentário do commit), e deploy, vc verá toda sequência do que está sendo feito.
E se vai dar certo ou não rsrs
Na minha primeira tentativa, deu erro, eu acabei digitando uma informação errada no arquivo de yml do workflow que o actions usa...efetuei a correção e rodei o workflow manualmente.
Feito tudo isso, com eu faço o teste para ver se o site foi publicado?
No kubernetes, vamos expor a porta do service site-engenharia da seguinte forma
kubectl port-forward services/site-engenharia 9999:80
O retorno na linha de comando, deve ser assim:
Forwarding from 127.0.0.1:9999 -> 80
Forwarding from [::1]:9999 -> 80
Agora faça acesso ao site no seu navegador digitando o endereço http://localhost:9999
Lembra que no deploy estamos pedindo 2 réplicas?
Será que o kubernetes fez isso?
Rode o comando
kubectl get pods
Temos o seguinte fluxo funcionando com o conceito DevOps de CI/CD - Integração Contínua e Entrega Contínua.
Fazendo uma nova alteração no site ou mesmo no deploymento da aplicação para aumentar o número de réplicas, isso ativará o gatilho para a automação iniciar e aplicar o que mudou.
O lab de hoje é isso.
Espero que tenham gostado e que este pequeno how-to seja útil e inspire vcs a testarem e fazerem ajustes para suas necessidades.
Por que não testar mudando as réplicas? Ou colocar um site mais "maneiro" no ar ... ou até mesmo uma aplicação diferente que necessite de alguma outra imagem que não a do nginx ...
Testem sempre...
E para não ser muito raso, esse conceito vai ainda muito além disso na prática.
Existem mais coisas a serem implementadas como validações, questões de segurança que precisam estar sempre juntas tanto no Dev quanto no Ops... o que chamamos de DevSecOps.
Integração com mais ferramentas, segregações de ambientes e por aí vai ...
Abs e até mais!!!
Nenhum comentário:
Postar um comentário