Aller au contenu principal
GitOpsArgoCDKubernetesCI/CD

ArgoCD : installation et Application CRD

30 min de lecture GitOps & ArgoCD — Chapitre 3

Architecture ArgoCD, installation production-ready avec Helm, Application CRD et AppProject pour l'isolation et le RBAC.

🎯 Objectif : Installer ArgoCD en production, maîtriser les Application CRD et AppProject, configurer les sync policies, gérer le multi-cluster, et utiliser les ApplicationSet pour scaler.

⏱️ Durée estimée : 55 minutes


Architecture ArgoCD

Avant d’installer, comprends les composants :

graph LR
  Title["ARCHITECTURE ARGOCD"]
  Title --> N0["ARGOCD SERVER"]
  Title --> N1["API Server"]
  Title --> N2["Repo Server"]
  Title --> N3["Application"]
  Title --> N4["Controller"]
  Title --> N5["- REST API"]
  Title --> N6["- Clone Git"]
  Title --> N7["- gRPC API"]
  Title --> N8["- Render"]
  Title --> N9["- Watch Git"]
  Title --> N10["- Web UI"]
  Title --> N11["manifests"]
  style Title fill:#7f1d1d,stroke:#dc2626,color:#f1f5f9
  style N0 fill:#1e3a5f,stroke:#3b82f6,color:#f1f5f9
  style N1 fill:#1a2332,stroke:#22c55e,color:#f1f5f9
  style N2 fill:#1a2332,stroke:#f59e0b,color:#f1f5f9
  style N3 fill:#1a2332,stroke:#a855f7,color:#f1f5f9
  style N4 fill:#7f1d1d,stroke:#dc2626,color:#f1f5f9
  style N5 fill:#1a2332,stroke:#3b82f6,color:#f1f5f9
  style N6 fill:#1e3a5f,stroke:#3b82f6,color:#f1f5f9
  style N7 fill:#1a2332,stroke:#22c55e,color:#f1f5f9
  style N8 fill:#1a2332,stroke:#f59e0b,color:#f1f5f9
  style N9 fill:#1a2332,stroke:#a855f7,color:#f1f5f9
  style N10 fill:#7f1d1d,stroke:#dc2626,color:#f1f5f9
  style N11 fill:#1a2332,stroke:#3b82f6,color:#f1f5f9

Rôle de chaque composant

graph TB
  API["API Server
UI, CLI, API, Auth, RBAC"] Repo["Repo Server
Clone repos, render manifests
Helm/Kustomize, cache"] AppCtrl["App Controller
Watch CRDs, compare states
trigger syncs, health check"] Redis["Redis
Cache pour Repo Server"] Dex["Dex
OIDC SSO GitHub/Google/LDAP"] Notif["Notification Controller
Slack, Teams, webhook"] API --> Repo API --> AppCtrl Repo --> Redis API --> Dex AppCtrl --> Notif style API fill:#1a2332,stroke:#dc2626,color:#f1f5f9 style Repo fill:#1e3a5f,stroke:#3b82f6,color:#f1f5f9 style AppCtrl fill:#1a2332,stroke:#dc2626,color:#f1f5f9 style Redis fill:#1a2332,stroke:#f59e0b,color:#f1f5f9 style Dex fill:#1a2332,stroke:#a855f7,color:#f1f5f9 style Notif fill:#1e3a5f,stroke:#3b82f6,color:#f1f5f9

---

## Installation production-ready

### Méthode 1 : Manifests officiels

```bash
# Créer le namespace
kubectl create namespace argocd

# Installation HA (High Availability) pour la production
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/ha/install.yaml

# Vérifier le déploiement
kubectl get pods -n argocd
# NAME                                               READY   STATUS
# argocd-application-controller-0                    1/1     Running
# argocd-dex-server-xxx                              1/1     Running
# argocd-notifications-controller-xxx                1/1     Running
# argocd-redis-ha-server-0                           2/2     Running
# argocd-repo-server-xxx                             1/1     Running
# argocd-server-xxx                                  1/1     Running

# Récupérer le mot de passe admin initial
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d

Méthode 2 : Helm (recommandé pour la personnalisation)

# Ajouter le repo Helm
helm repo add argo https://argoproj.github.io/argo-helm
helm repo update

# Installation avec valeurs personnalisées
helm install argocd argo/argo-cd \
    --namespace argocd \
    --create-namespace \
    --values argocd-values.yaml
# argocd-values.yaml
global:
  domain: argocd.company.com

server:
  replicas: 2
  ingress:
    enabled: true
    ingressClassName: nginx
    annotations:
      cert-manager.io/cluster-issuer: letsencrypt-prod
      nginx.ingress.kubernetes.io/ssl-passthrough: "true"
      nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
    tls: true

  config:
    # OIDC pour SSO
    oidc.config: |
      name: GitHub
      issuer: https://token.actions.githubusercontent.com
      clientID: $oidc.github.clientID
      clientSecret: $oidc.github.clientSecret
      requestedScopes:
        - openid
        - profile
        - email

  rbacConfig:
    policy.default: role:readonly
    policy.csv: |
      g, org:engineering, role:admin
      g, org:devs, role:readonly
      p, role:deployer, applications, sync, */*, allow
      p, role:deployer, applications, get, */*, allow

controller:
  replicas: 1
  resources:
    requests:
      cpu: 500m
      memory: 512Mi
    limits:
      cpu: "2"
      memory: 2Gi
  metrics:
    enabled: true
    serviceMonitor:
      enabled: true  # Pour Prometheus

repoServer:
  replicas: 2
  resources:
    requests:
      cpu: 250m
      memory: 256Mi

redis-ha:
  enabled: true

notifications:
  enabled: true
  argocdUrl: https://argocd.company.com
  notifiers:
    service.slack: |
      token: $slack-token
  templates:
    template.app-sync-succeeded: |
      slack:
        attachments: |
          [{
            "title": "{{.app.metadata.name}} synced",
            "text": "Application {{.app.metadata.name}} sync succeeded",
            "color": "#18be52"
          }]
  triggers:
    trigger.on-sync-succeeded: |
      - when: app.status.operationState.phase in ['Succeeded']
        send: [app-sync-succeeded]

Installer le CLI ArgoCD

# macOS
brew install argocd

# Linux
curl -sSL -o argocd-linux-amd64 https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64
sudo install -m 555 argocd-linux-amd64 /usr/local/bin/argocd
rm argocd-linux-amd64

# Se connecter
argocd login argocd.company.com --sso
# ou
argocd login argocd.company.com --username admin --password <password>

# Changer le mot de passe admin
argocd account update-password

Application CRD : le cœur d’ArgoCD

L’Application est la ressource centrale d’ArgoCD. Elle définit :

  • Source : d’où viennent les manifests (Git repo, Helm chart, OCI)
  • Destination : où les déployer (cluster + namespace)
  • Sync Policy : comment synchroniser (auto/manual, prune, self-heal)

Application basique

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: myapp-production
  namespace: argocd
  # Finalizer pour le cleanup automatique
  finalizers:
    - resources-finalizer.argocd.argoproj.io
spec:
  # Projet ArgoCD (isolation et RBAC)
  project: production

  # Source des manifests
  source:
    repoURL: https://github.com/org/gitops-repo.git
    targetRevision: main
    path: environments/production

  # Destination de déploiement
  destination:
    server: https://kubernetes.default.svc
    namespace: production

  # Sync policy
  syncPolicy:
    automated:
      prune: true       # Supprime les ressources orphelines
      selfHeal: true    # Corrige le drift automatiquement
    syncOptions:
      - CreateNamespace=true
      - PrunePropagationPolicy=foreground
      - PruneLast=true
    retry:
      limit: 5
      backoff:
        duration: 5s
        factor: 2
        maxDuration: 3m

Application avec Helm

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: prometheus
  namespace: argocd
spec:
  project: infrastructure
  source:
    # Chart depuis un Helm repo
    repoURL: https://prometheus-community.github.io/helm-charts
    chart: kube-prometheus-stack
    targetRevision: 56.0.0
    helm:
      releaseName: prometheus
      # Values inline
      values: |
        prometheus:
          prometheusSpec:
            retention: 30d
            storageSpec:
              volumeClaimTemplate:
                spec:
                  storageClassName: gp3
                  resources:
                    requests:
                      storage: 100Gi
        grafana:
          enabled: true
          adminPassword: <vault-injected>
          ingress:
            enabled: true
            hosts:
              - grafana.company.com
      # Ou values depuis un fichier dans le repo
      valueFiles:
        - values-production.yaml

  destination:
    server: https://kubernetes.default.svc
    namespace: monitoring

  syncPolicy:
    automated:
      prune: true
      selfHeal: true

Application avec Kustomize

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: myapp-staging
  namespace: argocd
spec:
  project: staging
  source:
    repoURL: https://github.com/org/gitops-repo.git
    targetRevision: main
    path: environments/staging
    kustomize:
      # Override d'images
      images:
        - ghcr.io/org/myapp:abc123def
      # Patches inline
      patches:
        - target:
            kind: Deployment
            name: myapp
          patch: |
            - op: replace
              path: /spec/replicas
              value: 2
      # Namespace prefix
      namePrefix: staging-
      # Common labels
      commonLabels:
        environment: staging
  destination:
    server: https://kubernetes.default.svc
    namespace: staging

Multi-source Application

# Combiner plusieurs sources (Helm chart + valeurs depuis Git)
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: myapp-with-config
  namespace: argocd
spec:
  project: default
  sources:
    # Source 1 : le Helm chart
    - repoURL: https://charts.company.com
      chart: myapp
      targetRevision: 2.1.0
      helm:
        valueFiles:
          - $values/environments/production/values.yaml
    # Source 2 : les values depuis un repo Git
    - repoURL: https://github.com/org/gitops-repo.git
      targetRevision: main
      ref: values  # Référencé comme $values ci-dessus
  destination:
    server: https://kubernetes.default.svc
    namespace: production

AppProject : isolation et RBAC

Les AppProject permettent de regrouper les applications et de contrôler finement les permissions.

graph TB
  subgraph Projects["APPPROJECTS"]
    subgraph Prod["production"]
      PS["Sources: github.com/org/gitops-repo
charts.company.com"] PD["Destinations: production-cluster
ns: production, monitoring"] PR["Resources: Deployment, Service, Ingress
Interdit: ClusterRole, Namespace"] Apps["myapp / api / worker -production"] end subgraph Stag["staging"] S1["Permissions plus larges
devs ont acces"] end subgraph Infra["infrastructure"] I1["Seuls les SRE
resources: tout"] end end style Projects fill:#1a2332,stroke:#3b82f6,color:#f1f5f9 style Prod fill:#7f1d1d,stroke:#dc2626,color:#f1f5f9 style Stag fill:#1a2332,stroke:#f59e0b,color:#f1f5f9 style Infra fill:#1e3a5f,stroke:#3b82f6,color:#f1f5f9 style PS fill:#1a2332,stroke:#a855f7,color:#f1f5f9 style PD fill:#1a2332,stroke:#22c55e,color:#f1f5f9 style PR fill:#1a2332,stroke:#dc2626,color:#f1f5f9 style Apps fill:#1a2332,stroke:#3b82f6,color:#f1f5f9 style S1 fill:#1a2332,stroke:#f59e0b,color:#f1f5f9 style I1 fill:#1a2332,stroke:#3b82f6,color:#f1f5f9
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: production
  namespace: argocd
spec:
  description: "Production applications"

  # Sources Git/Helm autorisées
  sourceRepos:
    - 'https://github.com/org/gitops-repo.git'
    - 'https://charts.company.com'
    - 'https://prometheus-community.github.io/helm-charts'

  # Destinations autorisées
  destinations:
    - server: https://production-cluster.internal
      namespace: production
    - server: https://production-cluster.internal
      namespace: monitoring
    - server: https://production-cluster.internal
      namespace: ingress-nginx

  # Ressources K8s autorisées (whitelist)
  clusterResourceWhitelist:
    - group: ''
      kind: Namespace
  namespaceResourceWhitelist:
    - group: 'apps'
      kind: Deployment
    - group: 'apps'
      kind: StatefulSet
    - group: ''
      kind: Service
    - group: ''
      kind: ConfigMap
    - group: ''
      kind: Secret
    - group: 'networking.k8s.io'
      kind: Ingress
    - group: 'autoscaling'
      kind: HorizontalPodAutoscaler

  # Ressources interdites (blacklist)
  namespaceResourceBlacklist:
    - group: ''
      kind: ResourceQuota
    - group: ''
      kind: LimitRange

  # Roles du projet
  roles:
    - name: deployer
      description: "Can sync applications"
      policies:
        - p, proj:production:deployer, applications, sync, production/*, allow
        - p, proj:production:deployer, applications, get, production/*, allow
        - p, proj:production:deployer, logs, get, production/*, allow
      groups:
        - org:sre-team

    - name: viewer
      description: "Read-only access"
      policies:
        - p, proj:production:viewer, applications, get, production/*, allow
        - p, proj:production:viewer, logs, get, production/*, allow
      groups:
        - org:engineering

  # Fenêtres de sync autorisées
  syncWindows:
    # Autorise les syncs en semaine 8h-18h
    - kind: allow
      schedule: '0 8 * * 1-5'
      duration: 10h
      applications:
        - '*'
    # Bloque les syncs le weekend
    - kind: deny
      schedule: '0 0 * * 0,6'
      duration: 48h
      applications:
        - '*'
    # Sauf urgences (tag manual-override)
    - kind: allow
      schedule: '* * * * *'
      duration: 24h
      manualSync: true
      applications:
        - '*'


➡️ La suite : Chapitre suivant

À toi de jouer

Exercice 1 — Installe ArgoCD

Installe ArgoCD dans un cluster Kubernetes (minikube ou kind) :

kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
kubectl -n argocd get pods
# Récupère le mot de passe admin
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d

Accède à l’UI via port-forward.

Exercice 2 — Déploie une Application

Crée une Application ArgoCD qui pointe vers un repo Git contenant un déploiement Nginx :

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: nginx-demo
  namespace: argocd
spec:
  destination:
    server: https://kubernetes.default.svc
    namespace: default
  source:
    repoURL: https://github.com/ton-user/gitops-demo
    path: base
  syncPolicy:
    automated: {}

Exercice 3 — AppProject et RBAC

Crée un AppProject qui limite les déploiements à un namespace spécifique et à certains repos Git seulement. Teste qu’une Application hors scope est refusée par ArgoCD.

🖥️ Pratique sur ton propre serveur

Pour suivre GitOps & ArgoCD en conditions réelles, tu as besoin d'un VPS. DigitalOcean offre 200$ de crédit gratuit pour démarrer.

Obtenir 200$

Articles liés