콘텐츠로 이동

ArgoCD 치트 시트

## 개요

ArgoCD는 Kubernetes를 위한 선언적인 GitOps 지속적 전달 도구입니다. Git 저장소를 원하는 애플리케이션 상태를 정의하는 진실의 원천으로 사용하고, 애플리케이션을 대상 환경과 자동으로 동기화하는 GitOps 패턴을 따릅니다.

⚠️ 참고: Kubernetes 클러스터 접근이 필요합니다. Kubernetes 1.19+ 버전을 지원합니다.

설치

빠른 시작 설치

Helm 설치

고가용성 설치

CLI 설치

ArgoCD CLI

CLI 인증

기본 명령어

애플리케이션 관리

저장소 관리

클러스터 관리

애플리케이션 구성

기본 애플리케이션 매니페스트

Helm 애플리케이션

Kustomize 애플리케이션

동기화 정책

자동 동기화

옵션이 있는 수동 동기화

동기화 웨이브

프로젝트 및 RBAC

프로젝트 구성

RBAC 구성

멀티 클러스터 관리

외부 클러스터 추가

클러스터 시크릿

애플리케이션 세트

기본 ApplicationSet

Would you like me to continue with the remaining sections and provide more detailed translations for each section?```bash

Create namespace

kubectl create namespace argocd

Install ArgoCD

kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

Wait for pods to be ready

kubectl wait —for=condition=available —timeout=300s deployment/argocd-server -n argocd


### Helm Installation
```bash
# Add ArgoCD Helm repository
helm repo add argo https://argoproj.github.io/argo-helm
helm repo update

# Install with Helm
helm install argocd argo/argo-cd \
  --namespace argocd \
  --create-namespace \
  --set server.service.type=LoadBalancer

High Availability Installation

# argocd-ha.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cmd-params-cm
  namespace: argocd
data:
  server.insecure: "true"
  application.instanceLabelKey: "argocd.argoproj.io/instance"
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: argocd-server
spec:
  replicas: 3
  template:
    spec:
      containers:
      - name: argocd-server
        env:
        - name: ARGOCD_SERVER_INSECURE
          value: "true"

CLI Installation

ArgoCD CLI

# 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

# macOS
brew install argocd

# Windows (PowerShell)
$version = (Invoke-RestMethod https://api.github.com/repos/argoproj/argo-cd/releases/latest).tag_name
Invoke-WebRequest -Uri "https://github.com/argoproj/argo-cd/releases/download/$version/argocd-windows-amd64.exe" -OutFile "argocd.exe"

CLI Authentication

# Port forward to access ArgoCD server
kubectl port-forward svc/argocd-server -n argocd 8080:443

# Get initial admin password
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d

# Login via CLI
argocd login localhost:8080 --username admin --password <password> --insecure

# Change admin password
argocd account update-password

Basic Commands

Application Management

# List applications
argocd app list

# Get application details
argocd app get myapp

# Create application
argocd app create myapp \
  --repo https://github.com/myorg/myrepo \
  --path manifests \
  --dest-server https://kubernetes.default.svc \
  --dest-namespace default

# Sync application
argocd app sync myapp

# Delete application
argocd app delete myapp

Repository Management

# Add Git repository
argocd repo add https://github.com/myorg/myrepo \
  --username myuser \
  --password mytoken

# List repositories
argocd repo list

# Remove repository
argocd repo rm https://github.com/myorg/myrepo

Cluster Management

# Add cluster
argocd cluster add my-cluster-context

# List clusters
argocd cluster list

# Remove cluster
argocd cluster rm https://kubernetes.default.svc

Application Configuration

Basic Application Manifest

# application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: myapp
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/myorg/myrepo
    targetRevision: HEAD
    path: manifests
  destination:
    server: https://kubernetes.default.svc
    namespace: myapp
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
    - CreateNamespace=true

Helm Application

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: nginx-helm
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://charts.bitnami.com/bitnami
    chart: nginx
    targetRevision: 13.2.23
    helm:
      parameters:
      - name: service.type
        value: LoadBalancer
      - name: ingress.enabled
        value: "true"
      values: |
        replicaCount: 3
        resources:
          limits:
            cpu: 100m
            memory: 128Mi
  destination:
    server: https://kubernetes.default.svc
    namespace: nginx
  syncPolicy:
    automated: {}

Kustomize Application

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: kustomize-app
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/myorg/myrepo
    targetRevision: HEAD
    path: overlays/production
    kustomize:
      images:
      - myapp:v1.2.3
      patchesStrategicMerge:
      - deployment-patch.yaml
  destination:
    server: https://kubernetes.default.svc
    namespace: production

Sync Policies

Automated Sync

syncPolicy:
  automated:
    prune: true      # Delete resources not in Git
    selfHeal: true   # Revert manual changes
    allowEmpty: false # Don't sync if no resources
  syncOptions:
  - CreateNamespace=true
  - PrunePropagationPolicy=foreground
  - PruneLast=true
  retry:
    limit: 5
    backoff:
      duration: 5s
      factor: 2
      maxDuration: 3m

Manual Sync with Options

# Sync with prune
argocd app sync myapp --prune

# Dry run sync
argocd app sync myapp --dry-run

# Force sync (ignore differences)
argocd app sync myapp --force

# Sync specific resources
argocd app sync myapp --resource apps:Deployment:myapp

Sync Waves

# Use annotations to control sync order
apiVersion: apps/v1
kind: Deployment
metadata:
  name: database
  annotations:
    argocd.argoproj.io/sync-wave: "1"
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
  annotations:
    argocd.argoproj.io/sync-wave: "2"
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
  annotations:
    argocd.argoproj.io/sync-wave: "3"

Projects and RBAC

Project Configuration

apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: myproject
  namespace: argocd
spec:
  description: My application project
  sourceRepos:
  - 'https://github.com/myorg/*'
  destinations:
  - namespace: 'myproject-*'
    server: https://kubernetes.default.svc
  clusterResourceWhitelist:
  - group: ''
    kind: Namespace
  - group: 'rbac.authorization.k8s.io'
    kind: ClusterRole
  namespaceResourceWhitelist:
  - group: 'apps'
    kind: Deployment
  - group: ''
    kind: Service
  roles:
  - name: admin
    description: Admin access
    policies:
    - p, proj:myproject:admin, applications, *, myproject/*, allow
    groups:
    - myorg:team-leads

RBAC Configuration

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-rbac-cm
  namespace: argocd
data:
  policy.default: role:readonly
  policy.csv: |
    p, role:admin, applications, *, */*, allow
    p, role:admin, clusters, *, *, allow
    p, role:admin, repositories, *, *, allow
    
    p, role:developer, applications, get, */*, allow
    p, role:developer, applications, sync, */*, allow
    
    g, myorg:admins, role:admin
    g, myorg:developers, role:developer

Multi-Cluster Management

Adding External Clusters

# Add cluster with service account
kubectl create serviceaccount argocd-manager -n kube-system
kubectl create clusterrolebinding argocd-manager-binding \
  --clusterrole=cluster-admin \
  --serviceaccount=kube-system:argocd-manager

# Get service account token
TOKENNAME=$(kubectl -n kube-system get serviceaccount/argocd-manager -o jsonpath='{.secrets[0].name}')
TOKEN=$(kubectl -n kube-system get secret $TOKENNAME -o jsonpath='{.data.token}' | base64 --decode)

# Add cluster to ArgoCD
argocd cluster add my-cluster \
  --server https://my-cluster-api-server \
  --service-account argocd-manager \
  --system-namespace kube-system

Cluster Secrets

apiVersion: v1
kind: Secret
metadata:
  name: my-cluster-secret
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: cluster
type: Opaque
stringData:
  name: my-cluster
  server: https://my-cluster-api-server
  config: |
    {
      "bearerToken": "eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9...",
      "tlsClientConfig": {
        "insecure": false,
        "caData": "LS0tLS1CRUdJTi..."
      }
    }

Application Sets

Basic ApplicationSet

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: cluster-addons
  namespace: argocd
spec:
  generators:
  - clusters: {}
  template:
    metadata:
      name: '{{name}}-addons'
    spec:
      project: default
      source:
        repoURL: https://github.com/myorg/cluster-addons
        targetRevision: HEAD
        path: '{{name}}'
      destination:
        server: '{{server}}'
        namespace: kube-system
      syncPolicy:
        automated: {}

Git Generator

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: microservices
  namespace: argocd
spec:
  generators:
  - git:
      repoURL: https://github.com/myorg/microservices
      revision: HEAD
      directories:
      - path: services/*
  template:
    metadata:
      name: '{{path.basename}}'
    spec:
      project: default
      source:
        repoURL: https://github.com/myorg/microservices
        targetRevision: HEAD
        path: '{{path}}'
      destination:
        server: https://kubernetes.default.svc
        namespace: '{{path.basename}}'
      syncPolicy:
        automated: {}

List Generator

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: environments
  namespace: argocd
spec:
  generators:
  - list:
      elements:
      - cluster: dev
        url: https://dev-cluster
        namespace: myapp-dev
      - cluster: staging
        url: https://staging-cluster
        namespace: myapp-staging
      - cluster: prod
        url: https://prod-cluster
        namespace: myapp-prod
  template:
    metadata:
      name: 'myapp-{{cluster}}'
    spec:
      project: default
      source:
        repoURL: https://github.com/myorg/myapp
        targetRevision: HEAD
        path: manifests/{{cluster}}
      destination:
        server: '{{url}}'
        namespace: '{{namespace}}'

Monitoring and Observability

Metrics Configuration

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-server-config
  namespace: argocd
data:
  application.instanceLabelKey: argocd.argoproj.io/instance
  server.metrics.enabled: "true"
  controller.metrics.enabled: "true"
  reposerver.metrics.enabled: "true"

Prometheus Integration

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: argocd-metrics
  namespace: argocd
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: argocd-metrics
  endpoints:
  - port: metrics
    interval: 30s
    path: /metrics

Grafana Dashboard

# Import ArgoCD dashboard
# Dashboard ID: 14584 (ArgoCD Operational)
# Dashboard ID: 19993 (ArgoCD Application)

# Key metrics to monitor:
# - Application sync status
# - Sync frequency
# - Repository connection status
# - Controller performance
# - API server response times

Notifications

Notification Configuration

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-notifications-cm
  namespace: argocd
data:
  service.slack: |
    token: $slack-token
  template.app-deployed: |
    message: |
      {{if eq .serviceType "slack"}}:white_check_mark:{{end}} Application {{.app.metadata.name}} is now running new version.
  template.app-health-degraded: |
    message: |
      {{if eq .serviceType "slack"}}:exclamation:{{end}} Application {{.app.metadata.name}} has degraded.
  trigger.on-deployed: |
    - description: Application is synced and healthy
      send:
      - app-deployed
      when: app.status.operationState.phase in ['Succeeded'] and app.status.health.status == 'Healthy'
  trigger.on-health-degraded: |
    - description: Application has degraded
      send:
      - app-health-degraded
      when: app.status.health.status == 'Degraded'

Slack Integration

apiVersion: v1
kind: Secret
metadata:
  name: argocd-notifications-secret
  namespace: argocd
stringData:
  slack-token: xoxb-your-slack-bot-token
---
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: myapp
  annotations:
    notifications.argoproj.io/subscribe.on-sync-succeeded.slack: my-channel
    notifications.argoproj.io/subscribe.on-health-degraded.slack: alerts-channel

Security

TLS Configuration

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-server-config
  namespace: argocd
data:
  tls.config: |
    certificates:
    - |
      -----BEGIN CERTIFICATE-----
      ...
      -----END CERTIFICATE-----
    - |
      -----BEGIN CERTIFICATE-----
      ...
      -----END CERTIFICATE-----

OIDC Integration

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
data:
  oidc.config: |
    name: OIDC
    issuer: https://your-oidc-provider.com
    clientId: argocd
    clientSecret: $oidc.clientSecret
    requestedScopes: ["openid", "profile", "email", "groups"]
    requestedIDTokenClaims: {"groups": {"essential": true}}
  url: https://argocd.example.com

Repository Credentials

apiVersion: v1
kind: Secret
metadata:
  name: private-repo
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: repository
stringData:
  type: git
  url: https://github.com/myorg/private-repo
  password: ghp_xxxxxxxxxxxxxxxxxxxx
  username: not-used

Troubleshooting

Common Issues

# Application stuck in sync
argocd app get myapp --hard-refresh
argocd app sync myapp --force

# Check application events
kubectl describe application myapp -n argocd

# View controller logs
kubectl logs -n argocd deployment/argocd-application-controller

# Check repository connection
argocd repo get https://github.com/myorg/myrepo

Debug Commands

# Enable debug logging
kubectl patch configmap argocd-cmd-params-cm -n argocd --patch '{"data":{"controller.log.level":"debug"}}'

# Check sync status
argocd app wait myapp --health

# Validate manifests
argocd app manifests myapp --source live

# Compare desired vs live state
argocd app diff myapp

Performance Tuning

# Controller configuration
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cmd-params-cm
  namespace: argocd
data:
  controller.status.processors: "20"
  controller.operation.processors: "10"
  controller.self.heal.timeout.seconds: "5"
  controller.repo.server.timeout.seconds: "60"

Best Practices

Repository Structure

# Recommended structure:
apps/
├── base/
   ├── kustomization.yaml
   └── deployment.yaml
├── overlays/
   ├── dev/
   ├── staging/
   └── production/
└── argocd/
    └── applications/

GitOps Workflow

# 1. Developers commit code changes
# 2. CI pipeline builds and pushes images
# 3. CI updates manifest repository
# 4. ArgoCD detects changes and syncs
# 5. Applications updated automatically

Security Best Practices

# - Use least privilege RBAC
# - Enable TLS for all connections
# - Regularly rotate credentials
# - Monitor access logs
# - Use signed commits
# - Implement admission controllers

Resources

Documentation

Community

교육

Notes:

  • I preserved the markdown formatting
  • Kept technical terms like “GitHub”, “ArgoCD”, “GitOps”, and “Kubernetes” in their original English form
  • Maintained the same structure and punctuation
  • Translated general words like “Training” to Korean