Isso aconteceu no meu laboratório de estudo em 6 de outubro de 2026. Os prints são reais; IDs de conta e e-mail foram borrados.
01 / O OBJETIVO
O pipeline não deveria tocar no cluster.
Eu já tinha a esteira da API funcionando até o ECR. Faltava a última parte: colocar a imagem no Kubernetes. O jeito mais rápido seria dar ao pipeline uma credencial do cluster e rodarkubectl apply. Funciona, mas o pipeline vira dono do cluster, e ninguém sabe ao certo o que está rodando lá dentro.
A REGRA QUE EU SEGUIO Git diz o que deve rodar. Quem aplica é o Argo CD, de dentro do cluster.
02 / O DESENHO
Três peças, cada uma com o seu papel.
Stack do EKS
Rede, cluster e nós. Terraform, como sempre.
Stack do Argo CD
Separada, com state próprio. Instala o Argo CD por Helm, com versão fixa.
Repositório GitOps
Manifests da API (base + overlay por ambiente) e um ApplicationSet.
Pipeline da API
Testa, faz o build, publica no ECR e muda só a tag da imagem no repositório GitOps.
Por que o Argo CD numa stack separada? Porque o provider do Helm precisa falar com o cluster. Criar o cluster e instalar coisas nele no mesmo apply é frágil: no primeiro plan o cluster ainda nem existe. Separando, cada um tem a sua vez.
03 / SUBINDO
O cluster subiu. O kubectl, não.

Com o cluster no ar, rodei kubectl get nodes e recebi um no such host. Fiquei uns segundos olhando para a tela até entender: eu tinha só impresso o comando do kubeconfig, sem executar. O kubectl ainda apontava para o cluster que eu tinha destruído dias antes.
# imprime o comando (não executa)
terraform output -raw kubeconfig_command
# executa direto o que o Terraform imprime
Invoke-Expression (terraform output -raw kubeconfig_command)
kubectl get nodes # 2 nodes ReadyDepois, o Argo CD em si foi a parte mais tranquila: um plan com 2 recursos e uns 2 minutos de apply.

Projetos que limitam o estrago
Criei dois projetos no Argo CD. O plataforma só pode criar ApplicationSets. O estudo, onde ficam os apps, só lê o repositório GitOps e só entra em namespaces terminados em -dev. Se alguém errar um manifest, o estrago fica contido.
04 / O ACESSO AO GIT
O repositório é privado. O Argo CD precisava de uma chave.
Escolhi uma deploy key somente leitura: o Argo CD só precisa ler. Aí vieram dois tropeços:
- 01
Deploy keys desligadas na organização
A própria organização bloqueava deploy keys por política. Precisei liberar nas configurações da org.
- 02
Quase com permissão de escrita
Na primeira tentativa a caixa "Allow write access" ficou marcada. Apaguei e cadastrei de novo, só leitura.
- 03
A chave fora do Git
A chave privada foi direto para o cluster com um comando. Não passa pelo Git nem pelo state do Terraform.
kubectl -n argocd create secret generic repo-gitops-estudo `
--from-literal=type=git `
--from-literal=url=git@github.com:minha-org/gitops-estudo.git `
--from-file=sshPrivateKey="$HOME\.ssh\argocd-gitops-estudo"
kubectl -n argocd label secret repo-gitops-estudo argocd.argoproj.io/secret-type=repositoryA Application raiz continuou Unknown: ela tinha tentado ler o repositório antes de a chave existir e estava esperando para tentar de novo. Um refresh forçado resolveu na hora.
kubectl -n argocd annotate application root-develop argocd.argoproj.io/refresh=hard --overwrite05 / FUNCIONOU
A API apareceu sozinha.
Segundos depois do refresh, o ApplicationSet leu a pasta apps/ e criou o app da API sozinho. Ninguém rodou kubectl apply.


E o log do pod confirma a versão: o SHA do commit foi gravado na imagem no build, e o ambiente dev veio do overlay do GitOps.

06 / NA MÃO x COMO CÓDIGO
A primeira vez que fiz GitOps foi na mão.
Num projeto anterior, montei o Argo CD quase todo na mão, e o token de acesso ao repositório acabou commitado num arquivo. Funcionava, mas recriar o ambiente era lembrar de cada passo. Desta vez:
Argo CD como código terraform apply, versão fixa, mudança por PR.
Acesso ao Git deploy key só leitura, aplicada direto no cluster.
Acesso ao cluster role com token temporário gerado na hora.
Permissões projetos separados, cada um no seu quadrado.
Recriar do zero dois applies e um kubectl. Mais nada.
07 / APRENDIZADOS
O que eu levo dessa.
GitOps não é instalar o Argo CD. É decidir quem pode mudar o que roda e deixar isso escrito. A ferramenta só obedece.
O próximo passo já está desenhado: o pipeline da API fazendo o commit da tag nova sozinho, e a troca do token por um GitHub App, sem dono pessoal. Fica para o próximo artigo.
william@devops:~$ echo $LESSON_LEARNED
"Se não está no Git, não deveria estar rodando."