Skip to content

Como subir um novo app

Como subir um novo app

Guia passo a passo para adicionar um app ao cluster. O fluxo completo e: criar manifests → criar Application ArgoCD → criar rota Traefik → push.

Leia docs/infraestrutura.md primeiro para entender a arquitetura.


Pre-requisitos

  • Acesso de escrita ao repositorio Git
  • Conhecer: nome do app, imagem Docker, porta(s), dominio desejado
  • Para Helm charts: URL do repositorio do chart e versao

Passo 1 — Manifests do app

Criar apps/<nome>/ com os manifests ou values Helm.

Se Helm (mais comum):

apps/<nome>/values.yaml

Se manifests puros (sem Helm):

apps/<nome>/deployment.yaml
apps/<nome>/service.yaml

O Service deve expor uma porta acessivel. Anotar a porta — vai precisar no passo 3.

Se Kustomize (manifests gerados por ferramenta externa, ex: Tutor/Open edX):

apps/<nome>/
kustomization.yml # com configMapGenerator, namespace, labels
k8s/ # deployments, services, volumes, jobs
apps/ # configs que viram ConfigMaps automaticamente

Quando o diretorio contem kustomization.yml, o ArgoCD detecta e usa Kustomize automaticamente. ConfigMaps sao gerados via configMapGenerator — nao precisa criar manualmente.

Diferencas do padrao:

  • Upgrades: re-gerar manifests com a ferramenta, copiar para o repo, revisar diff
  • Namespace: definido no kustomization.yml (nao no deployment)
  • Labels: aplicados globalmente via labels e commonAnnotations

Exemplo completo: apps/tutor-openedx/ — ver docs/tutor-openedx.md.

Dica: copiar de um app existente e ajustar. Bons exemplos:

  • Helm com chart externo: apps/airflow/, apps/authentik/
  • Manifests puros: apps/dashboard/, apps/invenio/
  • Kustomize (gerado): apps/tutor-openedx/

Passo 2 — Application ArgoCD

Criar apps/argocd/<nome>.yaml.

Para Helm chart externo (chart vem de outro repo):

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: <nome>
namespace: argocd
spec:
project: default
sources:
- repoURL: <URL_DO_CHART_REPO>
chart: <nome-do-chart>
targetRevision: "<versao>"
helm:
valueFiles:
- $values/apps/<nome>/values.yaml
- repoURL: https://github.com/colabhd/devops.git
targetRevision: HEAD
ref: values
destination:
server: https://kubernetes.default.svc
namespace: <nome>
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true

Para manifests puros (tudo no nosso repo):

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: <nome>
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/colabhd/devops.git
targetRevision: main
path: apps/<nome>
destination:
server: https://kubernetes.default.svc
namespace: <nome>
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true

IMPORTANTE: prune: true e selfHeal: true sao obrigatorios. Isso garante que:

  • Recurso removido do Git → removido do cluster
  • Edicao manual no cluster → revertida automaticamente

Passo 3 — Rota no Traefik

Criar config/traefik/routes/<nome>.yaml.

Para apps HTTP/HTTPS (maioria dos casos):

apiVersion: v1
kind: Service
metadata:
name: <nome>-backend
namespace: traefik
spec:
ports:
- port: <PORTA>
targetPort: <NODEPORT>
---
apiVersion: v1
kind: Endpoints
metadata:
name: <nome>-backend
namespace: traefik
subsets:
- addresses:
- ip: 192.168.0.51 # vm-cpps-02
ports:
- port: <NODEPORT>
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: <nome>
namespace: traefik
spec:
entryPoints: [websecure]
routes:
- match: Host(`<nome>.cppsunesp.org`)
kind: Rule
services:
- name: <nome>-backend
port: <PORTA>
tls:
certResolver: letsencrypt

Substituir:

  • <nome>: nome do app
  • <PORTA>: porta do service (ex: 8080)
  • <NODEPORT>: NodePort exposto pelo K3s (ex: 32000)

Dica: copiar config/traefik/routes/airflow.yaml e ajustar host + porta.

DNS Cloudflare: criar CNAME apontando para traefik-afq-franca.cppsunesp.org:

Terminal window
source .env
curl -X POST -H "Authorization: Bearer $CF_DNS_API_TOKEN" \
-H "Content-Type: application/json" \
"https://api.cloudflare.com/client/v4/zones/70cd39241c7861ecdf4644477069bf3c/dns_records" \
-d '{"type":"CNAME","name":"<nome>.cppsunesp.org","content":"traefik-afq-franca.cppsunesp.org","ttl":1,"proxied":false}'

O Zone ID 70cd39241c7861ecdf4644477069bf3c e do dominio colabh.org. Para cppsunesp.org, usar o Zone ID correspondente (verificar com curl -H "Authorization: Bearer $CF_DNS_API_TOKEN" "https://api.cloudflare.com/client/v4/zones?name=cppsunesp.org").

Futuro: considerar ExternalDNS para criar registros DNS automaticamente a partir das IngressRoutes. Hoje nao compensa (poucos dominios).

Para apps com HTTPS no backend (ex: ArgoCD, Rancher):

Adicionar ServersTransport com insecureSkipVerify: true e referenciar no service. Ver config/traefik/routes/argocd.yaml como exemplo.

Para apps TCP (ex: banco de dados externo):

Usar IngressRouteTCP em vez de IngressRoute. Ver config/traefik/routes/mongodb.yaml como exemplo. Neste caso, tambem precisa de regra NAT no VyOS (passo 4).


Passo 4 — VyOS (so se necessario)

Necessario APENAS quando:

  • O app usa protocolo nao-HTTP (TCP/UDP direto, ex: MongoDB, PostgreSQL)
  • O app precisa de porta externa especifica (ex: MQTT 1883)

Para apps web normais (HTTP/HTTPS): NAO precisa mexer no VyOS. As portas 80 e 443 ja redirecionam para o Traefik.

Se necessario, adicionar NAT destination rule no playbook VyOS:

config/vyos/playbook.yaml → nova regra DNAT

Ver docs/rede.md para as regras NAT existentes.


Passo 5 — Segredos (se houver)

As credenciais ficam diretamente nos values/manifests do app. Isso e necessario porque o ArgoCD com selfHeal: true aplica exatamente o que esta no Git — se estivesse CHANGEME, o app quebraria.

  1. Colocar a credencial real no values/manifests:

    password: "minha-senha-forte"
  2. Adicionar o arquivo ao allowlist do gitleaks (.gitleaks.toml, secao paths):

    paths = [
    # ...
    '''apps/<nome>/values.yaml''',
    ]
  3. Manter o .env.example atualizado com placeholder para documentacao:

    Terminal window
    # <NOME> — apps/<nome>/values.yaml
    <NOME>_DB_PASSWORD=CHANGEME

Situacao atual: credenciais em plaintext no Git com gitleaks allowlist temporario. Fase 1 do roadmap: migrar para SOPS/age — encripta os values no repo, ArgoCD decripta no deploy. Quando implementado, as credenciais ficam encriptadas e o allowlist do gitleaks e removido.


Passo 6 — Commit e push

Terminal window
git add apps/<nome>/ apps/argocd/<nome>.yaml config/traefik/routes/<nome>.yaml
git commit -m "feat: adicionar <nome>"
git push

ArgoCD sincroniza automaticamente (~3 min):

  • App no K3s de vm-cpps-02
  • Rota no Traefik da debian-proxy

Passo 7 — Verificar

  1. ArgoCD UI (https://argocd.colabh.org): app aparece como Synced + Healthy
  2. Browser: https://<nome>.cppsunesp.org responde
  3. Se nao funciona: ArgoCD UI mostra o erro (sync failed, pod crashloop, etc.)

Troubleshooting rapido:

  • Pod nao sobe → ver logs no Rancher ou kubectl logs -n <nome>
  • Rota nao funciona → verificar NodePort correto, IngressRoute com Host certo
  • TLS nao funciona → Traefik gera certificado automaticamente (pode levar ~1 min)

Checklist rapido

[ ] apps/<nome>/ — manifests, values ou kustomization.yml
[ ] apps/argocd/<nome>.yaml — selfHeal: true, prune: true
[ ] config/traefik/routes/<nome>.yaml — IngressRoute + Service + Endpoints
[ ] config/vyos/ (so se protocolo nao-HTTP) — NAT rule
[ ] .env / .env.example (se tem segredos) — CHANGEME nos manifests
[ ] Testado no browser

Remover um app

  1. Deletar apps/argocd/<nome>.yaml — ArgoCD remove o app do cluster
  2. Deletar apps/<nome>/ — manifests
  3. Deletar config/traefik/routes/<nome>.yaml — ArgoCD remove a rota
  4. Remover variaveis do .env e .env.example
  5. git push — pronto, ArgoCD limpa tudo (prune: true)

Atualizar um app

  • Mudar versao: editar targetRevision no apps/argocd/<nome>.yaml ou tag no values
  • Mudar config: editar apps/<nome>/values.yaml
  • Mudar dominio: editar Host(...) no config/traefik/routes/<nome>.yaml

Em todos os casos: editar, commit, push. ArgoCD aplica automaticamente.