Você já ouviu o ditado: cão de dois donos ou passa fome ou come de mais? A Infraestrutura das empresas é mantida por vários donos; pessoas com experiências diversas, capazes de resolver problemas de inúmeras maneiras. Agora, como garantir que a nossa estrutura não vai “morrer de fome” ou manter um padrão mínimo de conformidade? Existem várias boas práticas que o mercado recomenda. Uma delas é a adoção de GitOps, implementado por uma das mais famosas ferramentas: O ArgoCD. Hoje nós vamos aprender o que é GitOps na prática com ArgoCD.
E para começar, vamos entender o que são alguns conceitos, começando pelos famosos manifestos.
O que são manifestos?
Você provavelmente já se deparou com eles, mas não sabia do que se tratavam; ou nunca refletiu a respeito do nome que carregam. Para começar a abrir nossa mente, observe o yaml à seguir:
apiVersion: v1
kind: Namespace
metadata:
name: monitoringAgora me responda:
- Algum verbo foi utilizado?
- O
yamlacima está implementando algum algoritmo? - Existe alguma condicional no conteúdo?
Manifestos são assim: Eles não descrevem nem o como e nem o porquê. Eles apenas descrevem como as coisas devem ser. E nós, ou as ferramentas que usamos, por sua vez, é que temos todo o trabalho de planejar e executar as mudanças no ambiente, refletindo o que foi expresso no manifesto. Pense neles como “decretos de vossa majestade”: A vontade real foi expressa. A gente que lute.
Para você, que ficou curioso, o manifesto acima apenas diz ao kubernetes: “Deve existir um namespace e o nome dele é monitoring“. Só faltou um “Cumpra-se e faça-se cumprir”.
O que é GitOps?
Sua majestade mudou de ideia e emitiu novo decreto. Como notificar todos os seus súditos que a vontade real mudou e que a realidade precisa ser alterada para corresponder aos desígnios da égide real? Várias pessoas do Reino tem em mãos cópias de vários decretos. Como saber qual foi a última expressão da vontade do trono?
apiVersion: v1
kind: Namespace
metadata:
name: robespierreÉ aqui que GitOps entra.
Este conceito determina que a fonte da verdade deve ser o repositório onde o estado do ambiente está versionado. E toda vez que um novo commit for adicionado ao repositório, o estado do ambiente precisa corresponder a essas modificações. Essa conciliação é feita automaticamente, por meio de ferramentas que escutam essas mudanças e as aplicam no ambiente.
Por exemplo: Não há nada que nos diga, se considerarmos apenas este manifesto, se estamos renomeando o namespace monitoring para robespierre ou se estamos criando um novo namespace chamado robespierre (inquilinos da Bastilha que se cuidem!). É parte desse processo de conciliação entender, de acordo com as mudanças sofridas pelos manifestos, o que precisa ser feito no ambiente.
Vantagens do GitOps
- Auditoria: a simples adoção de versionamento, já traz consigo a auditoria e rastreabilidade. Não é necessário ferramentas de logs robustas e etc. Só fazer o blame do commit; fazer o diff com a versão anterior e procurar pelos aprovadores/as do PR.
- Diminui o número de usuários com acesso privilegiado: Idealmente apenas a ferramenta de GitOps precisa ter acesso para modificar o ambiente, exceto apenas alguns poucos – e poderosos – membros da corte. Assim você diminui a “superfície do estrago” e a preocupação com governança de acesso.
- Ambiente sem “Drift”: Nada de “oh, meu deus! É o Braia”. Se alguém modificar manualmente o seu ambiente, as ferramentas de GitOps identificam a mudança e voltam o ambiente para o estado anterior, assegurando a fonte de verdade única;
- Previsibilidade e reprodução: Se o seu node pool pegar fogo, ou se quiser compartilhar a sua infra com um amigo, basta instalar a ferramenta, vincular o projeto e em instantes o cluster estará com a mesma configuração anterior.
- Única fonte de verdade: Essa pra mim é a principal vantagem, e não apenas porque é ela quem viabiliza todas as anteriores. Eu já passei por cenários em que precisava consultar pessoas para recuperar um determinado histórico. Pessoas esquecem, mudam de trabalho, se confundem. Uma única fonte de verdade, além de deixar tudo mais simples, aumenta a confiabilidade. É o cão com um dono só.
Mas como revoluções não tem apenas um lado positivo?
Desvantagens do GitOps
- Menor flexibilidade para mudanças: O sistema está fora do ar. A probe de healthcheck está errada e um mero path no deployment é o suficiente para tudo voltar pro ar. Idealmente, com GitOps você não pode fazer atualizações manuais (zero drift, lembra?). E dependendo de como for o seu processo git, “seguir a cartilha” pode fazer com que a mudança demore para ser executada, representando um possível impacto financeiro.
- Aumento no custo de Debug: GitOps adiciona algumas camadas de falha ao seu processo. Então, quando um pod não entrar no ar, você deve se perguntar: Alguém aprovou o PR? O Git está disponível? A aplicação está OutOfSync? Tem algum problema na ordem de execução dos scripts?
- Gestão de segredos: Segredos no Kubernetes são um problema difícil de resolver. E fica ainda mais impossível se você versiona certificados, senhas, e qualquer outro segredo no código. Você vai precisar de algum CRD para fazer essa gestão de senhas por você. Coloco como uma desvantagem porque sempre há a possibilidade de digitar o kubectl criando a secret e ter amnésia cinco minutos depois.
Além do Git, que outra ferramenta poderia nos ajudar a implementar todos esses conceitos? Vamos conhecer o ArgoCD.
O que é o ArgoCD?
Agora que temos os manifestos do nosso cluster versionados, precisamos que uma ferramenta aplique esses manifestos automaticamente sempre que o repositório for atualizado. E é exatamente isso que o ArgoCD faz. Nele você consegue definir projetos, que por sua vez possuem aplicações. E as aplicações também podem possuir outras aplicações (o já famoso app-of-apps).
Só que o ArgoCD faz muito mais do que apenas sincronizar repositórios. Se não fosse assim, um simples hook no git já seria suficiente. Por isso, eu recomendo que você dê uma olhada na documentação para descobrir todo o potencial da ferramenta.
Disclaimer
Eu gosto muito de sempre poder fornecer pra vocês, código que se aproximem do mundo real. No entanto, nem sempre isso será verdade quando falamos de DevOps. Ambientes produtivos exigem alguns recursos que eu não tenho à disposição e/ou que são impossíveis de fazer em um home lab.
Por isso, antes de pensar em executar os scripts em produção, reveja cada um e considere fortemente as questões de segurança. Embora eu esteja usando SSL gerado por um cert-manager, os manifestos à seguir estão longe de atenderem os requisitos de segurança exigidos em um ambiente real e produtivo.
Instalando o ArgoCD
Instalar o ArgoCD é trivial:
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yamlAguarde os pods estabilizarem e o ArgoCD estará disponível. Use o comando abaixo para aguardar o argocd-server estar disponível.
kubectl wait pods --timeout=120s --for=condition=Ready -n argocd -l app.kubernetes.io/name=argocd-serverPara descobrir a senha inicial do sistema, verifique o valor da secret:
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -dQuando você instala o ArgoCD, além dos manifestos mais comuns, uma série de novas CRDs são adicionadas ao kubernetes, permitindo que você aplique manifestos como o abaixo no seu cluster:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: cluster-bootstrap
namespace: argocd
spec:
project: default
source:
repoURL: git@github.com:blogdoft/k3s-apps.git
targetRevision: HEAD
path: bootstrap
directory:
recurse: true
destination:
server: https://kubernetes.default.svc
namespace: argocd
syncPolicy:
automated:
prune: true
selfHeal: truePara acessar, você ainda vai precisar de um proxy para o serviço. Ou, pode ser esperto e configurar um ingress para acessar direto do navegador, sem a necessidade de proxy.
---
#Need to configure argocd to server.insecure: "true"
#https://argo-cd.readthedocs.io/en/stable/operator-manual/ingress/#traefik-v22
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cmd-params-cm
namespace: argocd
labels:
app.kubernetes.io/name: argocd-cmd-params-cm
app.kubernetes.io/part-of: argocd
data:
server.insecure: "true"
# Removed server.basehref and server.rootpath to serve from root
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: argocd-ingress
namespace: argocd
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true"
spec:
ingressClassName: traefik
rules:
- host: argocd.home.arpa
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: argocd-server
port:
name: httpConsidere que estou utilizando Traefik como ingress e tenho um cert-manager para controle e geração de certificados. Se quiser uma opção via http, altere para:
traefik.ingress.kubernetes.io/router.entrypoints: web
traefik.ingress.kubernetes.io/router.tls: "false"Como você alterou um ConfigMap, vai ser obrigado a reiniciar os serviços também.
kubectl -n argocd rollout restart deploy argocd-serverAguarde todos os deployments ficarem ready outra vez e está pronto!
É realmente simples assim instalar o ArgoCD.
Deployando aplicações com ArgoCD
Antes do primeiro deploy, você precisa entender alguns conceitos:
- AppProject: Define um agrupamento, estabelecendo limites e permissões para as aplicações vinculadas ao projeto. Você pode dizer, por exemplo, quais repositórios podem ser acessados, quais endpoints podem ser criados e até mesmo que tipo de artefatos k8s podem ser manipulados.
- Application: É um deployable no kubernetes. Nele você define tudo o que precisa para que uma aplicação seja entregue: repositório dos manifestos, endereço do helm, namespace, se deve ser “drift proof” ou não, se deve ser atualizada automaticamente ou não.
- App of Apps: É idêntico ao Application, com a diferença que ele não entrega nada no ambiente de fato. Apenas agrupa outras aplicações, facilitando processos que deveriam ocorrer em lote.
Uma palavra sobre conciliação
Um ponto importante sobre o Application: Lembra do nosso exemplo inicial, em que a simples leitura do manifesto não seria suficiente para saber se é uma adição ou renomeação? O recurso Application fornece esse tipo de contexto para o ArgoCD durante a conciliação de um novo commit do seu repositório.
Porém preciso destacar um ponto de atenção importante: De fato, não há possibilidade de renomear recursos no kubernetes. Se você renomear um namespace, o que provavelmente irá acontecer é o ArgoCD apagar o namespace atual e criar um novo. Pode imaginar o estrago que isso faria no seu ambiente? Por isso tome muito cuidado com as modificações que você faz. Sempre revise bem os manifestos e pense estrategicamente antes de aplicar uma alteração destrutiva.
Você pode criar AppProjects, Applications e até App of Apps através da interface ou do CLI do ArgoCD. Mas a forma mais indicada é através de manifestos. Vamos dizer que estamos fazendo o deploy dos componentes de segurança do nosso cluster. Vamos instalar o KeyCloak e o OpenBao.
Criando um AppProject no ArgoCD
Vamos dar uma olhada no manifesto que cria um AppProject
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: security
namespace: argocd
annotations:
argocd.argoproj.io/sync-wave: "10"
spec:
description: Segurança e identidade (Keycloak/OpenBao/etc.)
sourceRepos:
- git@github.com:blogdoft/k3s-apps.git
destinations:
- server: https://kubernetes.default.svc
namespace: keycloak
- server: https://kubernetes.default.svc
namespace: openbao
clusterResourceWhitelist:
- group: "*"
kind: "*"
namespaceResourceWhitelist:
- group: "*"
kind: "*"A maior parte dos campos é auto-explicativa. Quero chamar a atenção para alguns apenas:
sourceRepos: Define quais repositórios podem ser utilizados dentro do project;destinations: Você pode criar opções para deploy em diferentes clusters (dev/stg/prd);clusterResourceWhiteList: Diz quais recursos você pode manipular nas suas aplicações.
Para maiores detalhes, consulte a documentação.
Agora vejamos como seria o deploy de uma aplicação
Criando uma Application no ArgoCD
Observe o manifesto à seguir:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: keycloak
namespace: argocd
annotations:
argocd.argoproj.io/sync-wave: "30"
spec:
project: security
source:
repoURL: git@github.com:blogdoft/k3s-apps.git
path: artifacts/security/keycloak/manifests
targetRevision: HEAD
destination:
server: https://kubernetes.default.svc
namespace: keycloak
syncPolicy:
automated:
prune: true
selfHeal: true
enabled: true
syncOptions:
- CreateNamespace=trueNesse manifesto, estou definindo como será a aplicação keycloak. Na linha 9, por exemplo, digo que ela irá pertencer ao AppProject security, ficando, portanto, restrita ao que for definido nesse projeto. Perceba, também, que a propriedade source é levemente diferente da anterior. Aqui eu defino um repositório, mas também defino um caminho de pasta e qual a branch/commit do ArgoCD precisa observar as mudanças.
As linhas 17 em diante definem o comportamento do ArgoCD para quando ele identificar mudanças. As três opções, estando como true dá todo o controle de gestão ao ArgoCD. Se um recurso sumir do repositório, o ArgoCD irá destruí-lo no cluster (prune), se alguma modificação manual for feita, o ArgoCD deverá trazer o cluster para o estado desejado (selfHeal) e quando modificações forem feitas no repositório, elas devem ser aplicadas pelo ArgoCD (enabled).
O caminho artifacts/security/keycloak/manifests no repostório git@github.com:blogdoft/k3s-apps.git aponta para uma pasta cheia de manifestos do k3s
Eu posso usar Helm no ArgoCD?
Sim, o ArgoCD dá suporte a configurações por helms. E por um lado é bastante positivo isso, já que você mantém menos arquivos versionados. Entretanto, nem sempre o .values de um helm é suficientemente poderoso para permitir todas as personalizações demandadas. Ou ainda, por um processo de auditoria, você precisa identificar o que foi alterado entre as diversas versões do helm.
Por conta desses pontos, eu prefiro fazer um “unpack” do helm. E quando atualizar, eu consigo ver pelo diff do git, o que foi realmente modificado.
Eu posso ter execuções mais dinâmicas?
Além de manifestos puros e Helm, o ArgoCD também oferece suporte para Kustomize – uma “versão nativa” de helm no k8s – além de plugins que podem te ajudar a adicionar maior inteligência ao ArgoCD. Eu entendo a vontade de automatizar algumas coisas. Penso, por exemplo, que poderia ser uma boa para aplicar as secrets no cluster, por exemplo (spoiler: Não é).
Agora pense aqui comigo: Por mais que uma automação jure que irá garantir idempotência na geração dos scripts, a ideia do GitOps é ter o repositório como fonte de verdade. Se existirem intermediários entre o repositório e o cluster modificando os manifestos, concorda que o git deixou de ser a origem única do estado o seu cluster? É como se você estivesse jogando no lixo uma das principais vantagens do GitOps. Por isso, nem tudo que pode ser feito, deve ser feito. Pense bem.
Colocando pra rodar
Está com a ansiedade lá no alto, não é?
A documentação do ArgoCD já disponibiliza um pequeno projeto “Olá Mundo” para você fazer o deploy. No entanto, se você quiser brincar comigo, eu estou compartilhando o meu repositório também. Lá você vai instalar o cert-manager, flagr, kafbat.ui, keycloak, longhorn, openbao e rancher. Combinando com scripts, eu consigo levantar todo o meu cluster em menos de dez minutos. https://github.com/blogdoft/k3s-apps/tree/main

Enquanto escrevo esse artigo, ainda não resolvi o problema de carga de secrets. Por isso, entre os scripts que levantam o meu cluster, há alguns arquivos de ambiente de onde são extraídas todas as minhas secrets.
O que eu estou achando do ArgoCD?
Alguém pode dizer que ter o ArgoCD em um Home Lab é over engineering. Mas cá para nós, ter um kubernetes rodando em casa já é um over engineering, não acha?
Eu gostei bastante. Dava um certo trabalho levantar todas as aplicações manualmente no meu pequeno cluster. Só de usar o ArgoCD, consegui reduzir o trabalho de horas para minutos. Com certeza a ferramenta ajudou nesse processo, mas o simples fato de me educar a commitar todas as alterações, já trouxe alguma estabilidade para o meu ambiente.
Ainda quero avançar em alguns pontos na configuração dele. Seria ótimo se ele utilizasse o keycloak como SSO, por exemplo. Também espero contornar cenários de “quem veio primeiro”. Afinal, é o ArgoCD que instala o meu Keycloak. E as secrets precisam estar no openbao – que também é “mantido” pelo ArgoCD. Enfim… Alimentar o cachorro corretamente, enquanto vive a revolução francesa não deve ter sido fácil.

