DEV Community

Paulo Ponciano
Paulo Ponciano

Posted on • Edited on • Originally published at Medium

GitOps no Amazon EKS com ArgoCD [Lab Session]

intro

Why Argo CD?
Application definitions, configurations, and environments should be declarative and version controlled. Application deployment and lifecycle management should be automated, auditable, and easy to understand.

Source: https://argoproj.github.io/cd/

Infraestrutura

Repositório Terraform (Infraestrutura).

Repositório app de exemplo.


Deploy Amazon EKS

  • Definir variáveis no terraform (variables.tfvars):
## PROJECT BASE

cluster_name = "pegasus"
environment  = "staging"
project      = "devops"
aws_region   = "us-east-2"
az1          = "us-east-2a"
az2          = "us-east-2b"

## CLUSTER OPTIONS

k8s_version = "1.27"

endpoint_private_access = true

instance_type = [
  "t3a.medium"
]

desired_size = "1"
min_size     = "1"
max_size     = "1"

enabled_cluster_log_types = [
  "api", "audit", "authenticator", "controllerManager", "scheduler"
]

addon_cni_version       = "v1.13.4-eksbuild.1"
addon_coredns_version   = "v1.10.1-eksbuild.2"
addon_kubeproxy_version = "v1.27.3-eksbuild.2"
addon_csi_version       = "v1.21.0-eksbuild.1"

## INGRESS OPTIONS (ISTIO NLB)

nlb_ingress_internal         = "false"
enable_cross_zone_lb         = "true"
nlb_ingress_type             = "network"
proxy_protocol_v2            = "false"
grafana_virtual_service_host = "grafana.pauloponciano.pro"
kiali_virtual_service_host   = "kiali.pauloponciano.pro"
jaeger_virtual_service_host  = "jaeger.pauloponciano.pro"
argocd_virtual_service_host  = "argocd.pauloponciano.pro"

## KARPENTER OPTIONS

karpenter_instance_class = [
  "m5",
  "c5",
  "t3a"
]
karpenter_instance_size = [
  "large",
  "2xlarge"
]
karpenter_capacity_type = [
  "spot"
]
karpenter_azs = [
  "us-east-2a",
  "us-east-2b"
]

## NETWORKING

vpc_cidr                = "10.0.0.0/16"
public_subnet_az1_cidr  = "10.0.16.0/20"
public_subnet_az2_cidr  = "10.0.32.0/20"
private_subnet_az1_cidr = "10.0.48.0/20"
private_subnet_az2_cidr = "10.0.64.0/20"
Enter fullscreen mode Exit fullscreen mode
  • Caso utilize um certificado existente do ACM, informe o 'arn' em nlb.tf:
resource "aws_lb_listener" "ingress_443" {
  load_balancer_arn = aws_lb.istio_ingress.arn
  port              = "443"
  #protocol          = "TCP"
  protocol        = "TLS"
  certificate_arn = "arn:aws:acm:us-east-2:accountid:certificate/925700c8-03d1-4f4a-890a-249ffe2fa4f0"
  alpn_policy     = "HTTP2Preferred"

  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.https.arn
  }
}
Enter fullscreen mode Exit fullscreen mode

Caso não utilize certificado nenhum, altere esse bloco para:

resource "aws_lb_listener" "ingress_443" {
  load_balancer_arn = aws_lb.istio_ingress.arn
  port              = "443"
  protocol          = "TCP"
  #protocol        = "TLS"
  #certificate_arn = "arn:aws:acm:us-east-2:accountid:certificate/925700c8-03d1-4f4a-890a-249ffe2fa4f0"
  #alpn_policy     = "HTTP2Preferred"

  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.https.arn
  }
}
Enter fullscreen mode Exit fullscreen mode
  • Executar terraform:

terraform init
terraform plan --var-file variables.tfvars
terraform apply --var-file variables.tfvars

  • Conecte no cluster EKS:

aws eks --region us-east-2 update-kubeconfig --name pegasus

update-kubeconfig

kubectl get nodes

kubectl get pods -A

  • Aqui eu utilizei um domínio público já criado no Route 53 e inseri os registros abaixo apontando para o CNAME do NLB que foi criado pelo terraform:

Route 53

ArgoCD

Na execução da stack terraform dos passos anteriores, já foi feito deploy do Argo e vamos fazer alguns ajustes para acessá-lo e seguir na configuração.

  • Ajuste para terminação do SSL no NLB — Alterando o* ConfigMap* do ArgoCD server:

kubectl edit cm argocd-cmd-params-cm -n argocd

Inserir:

data:
  server.insecure: 'true'
Enter fullscreen mode Exit fullscreen mode

argocd-cmd-params-cm

Reciclar:

kubectl rollout restart deployment argocd-server -n argocd

  • Acessando o Argo UI:

  • Recuperar senha inicial para login:

kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d; echo

  • Já conectado no Argo, adicionamos um novo repositório em 'Settings'. Esse respositório é onde o Argo fica olhando e buscando por diferenças/alterações nos manifestos do kubernetes:

Connect Repo

O repositório sendo privado no GitHub, é necessário gerar um PAT (Personal Access Token) para informar como password no momento de conectar através do Argo.

Repositories

  • Ainda em *'Settings', criamos um novo 'Project':

  • Em 'Applications', criamos uma nova especificando o path dos manifestos kubernetes dentro do repositório adicionado anteriormente:

Rapidamente o Argo entrega a aplicação rodando no cluster, pois o Auto sync já está habilitado neste caso:

Applications

Application (webgo)

  • O app de exemplo está acessível:

GitHub / Actions

Agora na prática, vamos alcançar o cenário ilustrado abaixo utilizando GitHub Actions:

No repositório do app e manifestos existe essa estrutura:

.github/workflows/cd.yaml

name: CD
on:
  push:
    branches: [main]
    paths-ignore:
      - 'k8s/**'
jobs: 
  build: 
    name: Build
    runs-on: ubuntu-latest
    steps: 
      - name: checkout 
        uses: actions/checkout@v3

      - name: Login to Docker Hub
        uses: docker/login-action@v2
        with:
          username: ${{ secrets.DOCKER_USER }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - name: build image and push to docker hub
        uses: docker/build-push-action@v4
        with: 
          context: .
          push: true
          tags: paulofponciano/webgo:${{ github.sha }}, paulofponciano/webgo:latest

  deploy:
    name: Deploy
    runs-on: ubuntu-latest
    needs: build
    steps:
      - name: checkout
        uses: actions/checkout@v3

      - name: kustomize
        uses: imranismail/setup-kustomize@v2
        with: 
          kustomize-version: v5.1.1

      - name: update k8s
        run: |
          cd k8s
          kustomize edit set image webgo=paulofponciano/webgo:${{ github.sha }}
          cat kustomization.yaml

      - name: commit
        run: | 
          git config --local user.email "paulofponciano@gmail.com"
          git config --local user.name "Paulo"
          git commit -am "actions change image tag"

      - name: push
        uses: ad-m/github-push-action@master
Enter fullscreen mode Exit fullscreen mode

Basicamente sempre que houver um push na branch 'main' que não seja no diretório de manifestos 'k8s', as actions serão executadas. Isso significa que alguém está querendo entregar uma alteração na aplicação e uma nova imagem docker será criada para essa entrega.

  • No GitHub precisamos configurar os Repository secrets necessários para push da imagem no Docker Hub e Workflow permissions:

Actions secrets and variables

Settings > Actions > General > Workflow permissionsSettings > Actions > General > Workflow permissions

  • Acionando as actions através de uma alteração no 'main.go':

Push para o repositório:

  • Actions:

O resultdo do job chamado de ‘Build’, é o push de uma nova imagem no docker hub. Os parâmetros para o build da imagem estão no Dockerfile.

Docker hub

No job chamado de 'Deploy', é atualizado o manifesto kustomization.yaml para inserir a nova tag da imagem docker (usando o sha), é assim que o Argo vai saber que houve uma alteração e que é necessário um Sync:

- name: kustomize
  uses: imranismail/setup-kustomize@v2
  with: 
    kustomize-version: v5.1.1

- name: update k8s
  run: |
    cd k8s
    kustomize edit set image webgo=paulofponciano/webgo:${{ github.sha }}
    cat kustomization.yaml

- name: commit
  run: | 
    git config --local user.email "paulofponciano@gmail.com"
    git config --local user.name "Paulo"
    git commit -am "actions change image tag"

- name: push
  uses: ad-m/github-push-action@master
Enter fullscreen mode Exit fullscreen mode

kustomization.yaml

  • Sync no Argo:

  • Nova versão do app:

Lembrando que nossa unica ação manual até aqui, foi realizar o push da alteração que fizemos no main.go \o/

Happy building!

Top comments (0)