CI/CD não é novidade no mundo do desenvolvimento de software, no entanto a entrega de manifestos kubernetes apartado da aplicação, é uma prática a ser seguida.
Esse artigo tem por objetivo demonstrar tal situação, através do action github e o argocd.
_Pré-requisito: ter noção sobre docker, kubernetes, java e terraform.
Breve explicação dos recursos utilizados neste exemplo
- Spring boot: framework para aplicações java, que utiliza padrões de projeto para controlar a injeção de dependência, alem de prover objetos para solucionar diversos problemas. A aplicação é executa dentro do seu contexto, alem de possuir um webservice embarcado (modelo imperativo é o apache e reativo é o netty).
- Terraform: utilizado para criar recursos/infraestrutura na nuvem ou local via código. Nesse artigo criaremos um cluster kubernetes utilizando terraform localmente, em conjunto com kind.
- Argocd: ele inspeciona um repositório que possui os manifestos kubernetes, e caso ocorra alguma alteração, o mesmo os aplica. Em resumo ele cuida da entrega dos manifestos kubernetes dentro do cluster.
- GithubActions: recurso do github que cuida do CI/CD. No nosso projeto utilizaremos para efetuar o deploy da aplicação, criação da imagem docker e atualização do repositório dos manifestos.
- Helm: instalador de pacotes dentro do cluster kubernetes. Ele atualizará a imagem dentro do deployment da aplicação.
- docker: container runtime
- Kubernetes: um orquestrador de containers.
Pré requisitos
- instalar a ultima versão do terraform
- instalar o kind, pois através dele criaremos o cluster kubernetes local
- docker instalado
- kubectl (cli kubernetes)
- jdk 17
- helm
- clone dos projetos:
- criação de um token dentro da sua conta github (existe um print dentro do projeto de exemplo ou seguir a orientação do próprio github https://docs.github.com/pt/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token)
Criação do cluster
Nessa etapa criaremos nosso cluster k8s, instalaremos o argocd e por último criaremos a aplicação dentro do argo, onde ele vai monitorar as mudanças no repositório https://github.com/fabriciolfj/customer-service-k8s.
Com o clone do repositório customer-service efetuado, acesse o diretório cluster, nele existe o arquivo main.tf, onde encontra-se o descritivo do que o terraform criará. Dentro do main.tf, vamos olhar para o trecho abaixo e entender o que está ocorrendo.
resource "helm_release" "argocd" {
name = "argocd"
repository = "https://argoproj.github.io/argo-helm"
chart = "argo-cd"
namespace = "argocd"
version = "4.9.7"
create_namespace = true
values = [
file("argocd/application.yaml")
]
}
O trecho acima representa o uso de um módulo dentro do terraform. Onde ele executará as seguintes etapas:
- instalar o argo dentro do cluster, com base na configuração do arquivo application.yaml
- dentro deste arquivo encontra-se as configurações adicionais para criar aplicação dentro do argocd
- quando falamos em criar aplicação dentro do argocd, é o repositório git com os manifestos que serão monitorados.
- qualquer modificação nestes manifestos e submetidos ao repositório git, estes serão re-aplicados dentro do cluster kubernetes.
Abaixo o conteúdo do arquivo application.yaml e em seguida o arquivo que cria a app dentro do argocd (estão no repositório de exemplo salientado acima):
server:
additionalApplications:
- name: cluster-config
namespace: argocd
project: default
source:
repoURL: https://github.com/fabriciolfj/customer-service
targetRevision: HEAD
path: argocd/manifests/cluster #local onde encontra-se o arquivo para criar a app
directory:
recurse: true
destination:
server: https://kubernetes.default.svc
syncPolicy:
automated:
prune: false
selfHeal: false
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: customer
namespace: argocd
spec:
syncPolicy:
syncOptions:
- CreateNamespace=false
automated:
selfHeal: true # sincronizar automaticamente com o repositorio
prune: true # caso exclua algum arquivo, o argo vai excluir o recurso no kubernetes
destination:
server: 'https://kubernetes.default.svc'
namespace: customer
source:
path: helm #por traz usaremos o helm para efetuar o deploy, dentro do cluster
repoURL: 'https://github.com/fabriciolfj/customer-service-k8s' #repositório da app, que o argo aplicará no cluster quando houver commits.
targetRevision: HEAD
helm:
valueFiles:
- values.yaml
project: default
Os demais conteúdos do arquivo main.tf, tem por objetivo criar o cluster k8s local, utilizando kind. obs: está fora do escopo desse artigo o detalhamento desse conteúdos.
Certifique-se que o docker esteja rodando na sua máquina e execute o comando abaixo para inicializar o terraform, com as configurações do projeto, no path aonde encontra-se o arquivo main.tf:
terraform init
Em seguida vamos analisar o que será criado, através do comando:
terraform plan
Teremos o seguinte resultado:
- Plan: 24 to add, 0 to change, 0 to destroy.
Após a criação do cluster, vamos acessar o argocd. Abaixo o script para pegar a senha admin:
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d; echo ``
Para redirecionar a porta:
kubectl port-forward svc/argocd-server -n argocd 8080:80
Acesse localhost:8080, usuário admin e a senha que você pegou conforme o script acima.
Github Actions
Para utilizar o CI/CD do githubactions, precisa constar um arquivo yaml no seguinte path do seu projeto: .github/workflows/commit-stage.yml
Abaixo a explicação de cada etapa que consta no nosso githubactions.
- pipeline disparará a cada commit
name: Commit Stage
on: push
- variáveis de ambiente utilizados dentro desse contexto. obs: a tag version será alimentada pelo hash do commit.
env:
REGISTRY: docker.io
IMAGE_NAME: fabricio211/customer-service
VERSION: ${{ github.sha }}
- job/build que primeiro fará o checkout do nosso código, usando como base uma imagem ubuntu
jobs:
build:
name: Build and Test
runs-on: ubuntu-20.04
permissions:
contents: read
security-events: write
steps:
- name: Checkout source code
uses: actions/checkout@v2
- job/package executará os testes unitários, gerar a imagem docker com base nas variáveis de ambiente e por mim enviará ao registry do docker hub (obs: podemos utilizar o registry do próprio github).
package:
name: Package and Publish
needs: [ build ]
runs-on: ubuntu-20.04
permissions:
contents: read
packages: write
security-events: write
steps:
- name: Checkout source code
uses: actions/checkout@v2
- name: Set up JDK
uses: actions/setup-java@v2
with:
distribution: temurin
java-version: 17
cache: maven
- name: Build container image
run: |
chmod +x ./mvnw
./mvnw clean install spring-boot:build-image -Dspring-boot.build-image.imageName=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
- name: Log into container registry
uses: docker/login-action@v1
with:
registry: ${{ env.REGISTRY }}
username: seu usuario
password: sua senha
- name: Publish container image
run: docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
- name: Publish container image (latest)
run: |
docker tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }} \
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
- por fim atualizaremos a imagem dentro do nosso manifesto, no outro repositório. obs: nesse ponto precisamos do secret do github para executar essa operação (salientado acima como proceder).
- name: Update values.yaml
uses: fjogeleit/yaml-update-action@v0.10.0
with:
valueFile: 'helm/values.yaml'
propertyPath: 'image.tag'
value: ${{ env.VERSION }}
commitChange: true
updateFile: true
token: ${{ secrets.SPRING_FAST }}
targetBranch: main
branch: main
repository: fabriciolfj/customer-service-k8s
Ao realizar algum commit, você verá as seguintes situações.
Aplicação
- execute o script baixo que encontra-se no path raiz do projeto, dentro do namespace customer
kubectl apply -f postgresql.yaml
Top comments (0)