본문 바로가기

Notice
Recent Posts
Link
Calendar
«   2026/05   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
Total
Today
관리 메뉴

ArgoCD Notifications Slack 연동 본문

Kubernetes

ArgoCD Notifications Slack 연동

BinaryNumber 2026. 5. 16. 16:29
반응형
📚 GitOps / ArgoCD 시리즈
  • 1편 — ArgoCD Helm 설치 시 생성되는 컴포넌트 역할 정리
  • 2편 — ArgoCD Application, AppProject 개념 정리
  • 3편 — ApplicationSet으로 멀티 클러스터 배포 자동화
  • 4편 — ArgoCD Notifications Slack 연동 가이드 (현재 글)

ArgoCD는 기본적으로 배포 결과를 알려주지 않습니다. argocd-notifications-controller를 설정하면 Sync 성공/실패, Health 상태 변화를 Slack으로 받을 수 있습니다. 이 글에서는 Slack Webhook 방식으로 알림을 설정하는 방법을 단계별로 정리합니다.

ArgoCD Notifications는 trigger(언제 알릴지) + template(어떻게 알릴지) + subscription(어디로 알릴지) 세 가지 조합으로 동작합니다.

동작 원리

[Application 상태 변화]
       │
       ▼
[trigger 조건 평가] ── 조건 불충족 → 무시
       │ 조건 충족
       ▼
[template으로 메시지 생성]
       │
       ▼
[subscription에 등록된 채널로 발송]
       │
       ▼
[Slack / Email / PagerDuty / ...]

설정 방법

1

Slack Webhook URL 발급

Slack 워크스페이스에서 앱 관리 → Incoming Webhooks → 새 Webhook 추가로 채널별 Webhook URL을 발급합니다.

URL 형식: https://hooks.slack.com/services/T.../B.../...

2

Webhook URL을 Secret으로 저장

kubectl create secret generic argocd-notifications-secret \
  --from-literal=slack-token=https://hooks.slack.com/services/T.../B.../... \
  -n argocd

또는 이미 Secret이 있다면 패치:

kubectl patch secret argocd-notifications-secret \
  -n argocd \
  -p '{"stringData": {"slack-token": "https://hooks.slack.com/services/..."}}'
3

values.yaml에 Notifications 설정 추가

Helm으로 설치했다면 values.yaml에 아래 설정을 추가하고 helm upgrade로 적용합니다.

notifications:
  enabled: true

  secret:
    create: false              # 위에서 직접 만든 Secret 사용

  cm:
    create: true

  # 발송 서비스 설정
  notifiers:
    service.slack: |
      token: $slack-token      # Secret의 slack-token 키 참조

  # Trigger: 언제 알릴지
  triggers:
    trigger.on-sync-succeeded: |
      - when: app.status.operationState.phase in ['Succeeded']
        send: [app-sync-succeeded]

    trigger.on-sync-failed: |
      - when: app.status.operationState.phase in ['Error', 'Failed']
        send: [app-sync-failed]

    trigger.on-health-degraded: |
      - when: app.status.health.status == 'Degraded'
        send: [app-health-degraded]

    trigger.on-deployed: |
      - when: app.status.operationState.phase in ['Succeeded'] and app.status.health.status == 'Healthy'
        send: [app-deployed]

  # Template: 어떻게 알릴지
  templates:
    template.app-sync-succeeded: |
      slack:
        attachments: |
          [{
            "color": "#2eb67d",
            "title": "✅ Sync 성공: {{.app.metadata.name}}",
            "fields": [
              {"title": "환경", "value": "{{.app.spec.destination.server}}", "short": true},
              {"title": "Revision", "value": "{{.app.status.sync.revision}}", "short": true},
              {"title": "시각", "value": "{{.app.status.operationState.finishedAt}}", "short": false}
            ]
          }]

    template.app-sync-failed: |
      slack:
        attachments: |
          [{
            "color": "#e01e5a",
            "title": "❌ Sync 실패: {{.app.metadata.name}}",
            "fields": [
              {"title": "에러", "value": "{{.app.status.operationState.message}}", "short": false},
              {"title": "Revision", "value": "{{.app.status.sync.revision}}", "short": true}
            ]
          }]

    template.app-health-degraded: |
      slack:
        attachments: |
          [{
            "color": "#ff6b35",
            "title": "⚠️ Health Degraded: {{.app.metadata.name}}",
            "fields": [
              {"title": "상태", "value": "{{.app.status.health.status}}", "short": true},
              {"title": "Message", "value": "{{.app.status.health.message}}", "short": false}
            ]
          }]

    template.app-deployed: |
      slack:
        attachments: |
          [{
            "color": "#2eb67d",
            "title": "🚀 배포 완료: {{.app.metadata.name}}",
            "fields": [
              {"title": "Namespace", "value": "{{.app.spec.destination.namespace}}", "short": true},
              {"title": "Revision", "value": "{{.app.status.sync.revision}}", "short": true}
            ]
          }]

  # 기본 Subscription: 모든 Application에 적용
  subscriptions: |
    - recipients:
        - slack:#devops-alerts    # 알림 받을 Slack 채널
      triggers:
        - on-sync-failed
        - on-health-degraded
4

Helm upgrade로 적용

helm upgrade argocd argo/argo-cd \
  -n argocd \
  -f values.yaml

Slack 알림 미리보기

위 template 설정을 적용하면 Slack에서 이렇게 보입니다.

✅ Sync 성공: my-app-production
환경 https://prod.example.com
Revision a1b2c3d
시각 2026-05-16T10:32:00Z
❌ Sync 실패: my-app-production
에러 Failed to create resource: namespaces "production" not found
Revision d4e5f6g

Application별 채널 분리 — Subscription 어노테이션

Helm values의 subscriptions는 전체 기본값입니다. 특정 Application에만 다른 채널로 알림을 보내려면 Application 매니페스트에 어노테이션을 추가합니다.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app
  namespace: argocd
  annotations:
    # 이 Application은 별도 채널로 알림 수신
    notifications.argoproj.io/subscribe.on-sync-failed.slack: backend-alerts
    notifications.argoproj.io/subscribe.on-deployed.slack: backend-deploys
    notifications.argoproj.io/subscribe.on-health-degraded.slack: backend-alerts

ApplicationSet으로 생성하는 경우 template에 어노테이션을 추가합니다:

  template:
    metadata:
      name: "my-app-{{env}}"
      annotations:
        notifications.argoproj.io/subscribe.on-sync-failed.slack: "{{team}}-alerts"
        notifications.argoproj.io/subscribe.on-deployed.slack: "{{team}}-deploys"

Trigger 조건 커스터마이징

Trigger는 expr-lang 문법을 사용합니다. 주요 조건 예시입니다.

조건설명
app.status.operationState.phase in ['Succeeded']Sync 성공
app.status.operationState.phase in ['Error', 'Failed']Sync 실패
app.status.health.status == 'Degraded'Health Degraded
app.status.health.status == 'Healthy'Health 정상
app.metadata.labels['env'] == 'production'production 레이블 Application만
time.Now().Sub(time.Parse(app.status.operationState.startedAt)).Minutes() >= 10Sync가 10분 이상 걸린 경우

운영 환경만 알림 받기

triggers:
  trigger.on-sync-failed: |
    - when: >
        app.status.operationState.phase in ['Error', 'Failed'] and
        app.metadata.labels['env'] == 'production'
      send: [app-sync-failed]

알림 동작 테스트

설정 후 실제로 알림이 가는지 CLI로 테스트할 수 있습니다.

# 특정 Application에 대해 알림 강제 발송 테스트
argocd admin notifications trigger run on-sync-failed my-app \
  --recipient slack:devops-alerts \
  -n argocd

# 현재 구독 목록 확인
argocd admin notifications service list -n argocd

자주 하는 실수

Secret 키 이름이 틀린 경우

service.slack에서 $slack-token으로 참조할 때, Secret의 키 이름이 정확히 slack-token이어야 합니다. 키 이름이 다르면 알림 컨트롤러 로그에 secret not found 에러가 납니다.

확인 명령: kubectl get secret argocd-notifications-secret -n argocd -o jsonpath='{.data}' | base64 -d
알림이 안 올 때 확인할 것

  1. notifications-controller 파드 로그 확인: kubectl logs -n argocd -l app.kubernetes.io/name=argocd-notifications-controller
  2. ConfigMap 확인: kubectl get cm argocd-notifications-cm -n argocd -o yaml
  3. Application 어노테이션에 subscription이 제대로 달려있는지 확인
  4. Slack Webhook URL이 유효한지 curl로 직접 테스트
알림 피로도 줄이기

기본 subscription에는 on-sync-failedon-health-degraded만 걸어두고, 성공 알림(on-deployed)은 팀 채널에만 선택적으로 구독하는 것을 권장합니다. 모든 Application의 Sync 성공 알림이 오면 알림 피로도가 높아집니다.

마치며

ArgoCD Notifications는 trigger + template + subscription 세 가지만 이해하면 충분히 원하는 형태로 커스터마이징할 수 있습니다. 처음에는 on-sync-failedon-health-degraded만 설정해서 시작하고, 필요에 따라 trigger와 채널을 추가해가는 것을 권장합니다.

📚 시리즈 완결
  • 1편 — ArgoCD Helm 설치 시 생성되는 컴포넌트 역할 정리
  • 2편 — ArgoCD Application, AppProject 개념 정리
  • 3편 — ApplicationSet으로 멀티 클러스터 배포 자동화
  • 4편 — ArgoCD Notifications Slack 연동 가이드
Comments