ArgoCD
Arquitetura de Cluster
O ArgoCD roda in-cluster no cluster de gerenciamento. Gerencia serviços de plataforma localmente e cargas de trabalho de app em clusters remotos via secrets de cluster registrados.
cluster-mgmt (cluster de gerenciamento)
├── argocd/ ← ArgoCD — namespace fixo, não convenção
├── crossplane-system/ ← Crossplane — namespace fixo, não convenção
├── platform-mgmt-monitoring/
└── platform-mgmt-logging/
cluster-dev / cluster-staging / cluster-prod ← gerenciados remotamente
Instalação e Registro de Cluster
kubectl create namespace argocd
kubectl apply -n argocd \
-f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
argocd cluster add dev-context --name dev
argocd cluster add staging-context --name staging
argocd cluster add prod-context --name prod
Adicione a label env a cada secret de cluster para que o gerador de cluster possa filtrar por ambiente:
metadata:
labels:
argocd.argoproj.io/secret-type: cluster
env: prod # dev / staging / prod / mgmt
AppProject — Limite de Domínio
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: payments
namespace: argocd
spec:
sourceRepos:
- https://github.com/myorg/payments-gitops
destinations:
- namespace: payments-*
server: https://k8s-dev.internal
- namespace: payments-*
server: https://k8s-staging.internal
- namespace: payments-*
server: https://k8s-prod.internal
- namespace: payments-*-infra # Claims Crossplane
server: https://kubernetes.default.svc
clusterResourceWhitelist:
- {group: '', kind: Namespace}
roles:
- name: domain-admin
policies:
- p, proj:payments:domain-admin, applications, *, payments/*, allow
groups: [team-payments]
- name: readonly
policies:
- p, proj:payments:readonly, applications, get, payments/*, allow
syncWindows:
- kind: deny
schedule: '0 22 * * 1-5'
duration: 8h
applications: ['*-prod-*']
manualSync: true # permite sync manual de emergência
AppProject — Limite de Plataforma
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: platform
namespace: argocd
spec:
sourceRepos:
- https://github.com/myorg/platform-gitops
destinations:
- namespace: platform-*
server: https://kubernetes.default.svc
- namespace: crossplane-system
server: https://kubernetes.default.svc
- namespace: argocd
server: https://kubernetes.default.svc
- namespace: platform-*
server: https://k8s-dev.internal
- namespace: platform-*
server: https://k8s-staging.internal
- namespace: platform-*
server: https://k8s-prod.internal
clusterResourceWhitelist:
- {group: '', kind: Namespace}
- {group: rbac.authorization.k8s.io, kind: ClusterRole}
- {group: rbac.authorization.k8s.io, kind: ClusterRoleBinding}
- {group: apiextensions.crossplane.io, kind: CompositeResourceDefinition}
- {group: apiextensions.crossplane.io, kind: Composition}
- {group: pkg.crossplane.io, kind: Provider}
ApplicationSet — Cargas de Trabalho de App (Gerador Matriz)
# platform-gitops/argocd/applicationsets/payments-gateway.yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: gateway
namespace: argocd
spec:
generators:
- matrix:
generators:
- list:
elements: [] # serviços adicionados aqui pelo template create-service
- clusters:
selector:
matchExpressions:
- key: env
operator: In
values: [dev, staging, prod]
template:
metadata:
name: gateway-{{service}}-{{name}}
labels:
project: payments
system: gateway
service: "{{service}}"
env: "{{name}}"
backstage.io/domain: payments
backstage.io/system: gateway
backstage.io/component: gateway-{{service}}
argocd/app-set: gateway
spec:
project: payments
source:
repoURL: https://github.com/myorg/payments-gitops
targetRevision: HEAD
path: k8s/{{name}}/{{service}}
destination:
server: "{{server}}"
namespace: payments-{{name}}-{{service}}
syncPolicy:
automated: {prune: true, selfHeal: true}
syncOptions: [CreateNamespace=true, ServerSideApply=true]
retry:
limit: 5
backoff: {duration: 5s, factor: 2, maxDuration: 3m}
ignoreDifferences:
- group: apps
kind: Deployment
jsonPointers: [/spec/replicas]
# Sobrescreve prod para sync manual quando a política é automated-prod-manual
templatePatch: |
{{- if eq .env "prod" }}
spec:
syncPolicy:
syncOptions: [CreateNamespace=true]
{{- end }}
Application — Plataforma Crossplane
# platform-gitops/argocd/applications/platform-crossplane.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: platform-crossplane
namespace: argocd
annotations:
argocd.argoproj.io/sync-wave: "-10"
spec:
project: platform
source:
repoURL: https://github.com/myorg/platform-gitops
targetRevision: HEAD
path: crossplane/
directory:
recurse: true
destination:
server: https://kubernetes.default.svc
namespace: crossplane-system
syncPolicy:
automated: {prune: true, selfHeal: true}
syncOptions: [CreateNamespace=true, ServerSideApply=true]
ApplicationSet — Claims Crossplane (Gerador de Diretório Git)
# platform-gitops/argocd/applicationsets/crossplane-claims.yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: crossplane-claims
namespace: argocd
spec:
generators:
- matrix:
generators:
- git:
repoURL: https://github.com/myorg/platform-gitops
revision: HEAD
directories:
- path: crossplane/claims/*/* # crossplane/claims/{env}/{resource}
- clusters:
selector:
matchLabels:
env: mgmt # Claims sempre apontam para o cluster de gerenciamento
template:
metadata:
name: crossplane-claims-{{path.basenameNormalized}}
annotations:
argocd.argoproj.io/sync-wave: "0" # após plataforma Crossplane (wave -10)
spec:
project: platform
source:
repoURL: https://github.com/myorg/payments-gitops
targetRevision: HEAD
path: "{{path}}"
destination:
server: "{{server}}"
namespace: payments-{{path[2]}}-infra # payments-prod-infra
syncPolicy:
automated:
prune: false # nunca auto-deletar Claims de infraestrutura
selfHeal: true
syncOptions: [CreateNamespace=true, ServerSideApply=true]
Bootstrap — App of Apps
Um único kubectl apply manual inicializa todo o resto:
kubectl apply -f argocd/bootstrap.yaml -n argocd
app-of-apps sincroniza argocd/projects/ → AppProjects: platform, payments, ...
↓
app-of-apps sincroniza argocd/applications/ e argocd/applicationsets/
├── platform-crossplane (wave -10) → Providers + XRDs + Compositions
├── platform-services → Applications de plataforma
├── gateway → Applications de payments
└── crossplane-claims (wave 0) → Applications de Claims
↓
ApplicationSets geram Applications via geradores de cluster + git
├── gateway-api-dev → payments-dev-api
├── gateway-api-prod → payments-prod-api
└── crossplane-claims-prod-cloudsql-main → Claim → Cloud SQL
↓
Applications sincronizam → namespaces e cargas de trabalho criadas em cada cluster