IaC/CI CD Tool

ArgoCD Slack Notification 설정 방법

Somaz 2025. 5. 8. 12:07
728x90
반응형

Overview

ArgoCD는 GitOps 기반 Kubernetes 배포 자동화 도구로, 애플리케이션의 배포 상태를 지속적으로 모니터링하고 관리해준다.

특히 배포 실패(Sync Failed), 애플리케이션 비정상(Health Degraded) 같은 상황에서는 빠르게 알람을 받을 수 있어야 장애 대응이 쉬워진다/

오늘은 ArgoCD의 Notification 기능을 이용해, 특정 이벤트 발생 시 Slack 알람을 받는 방법을 정리해보겠다.

 

 

 

 

 

📅 관련 글

2023.05.16 - [IaC/CI CD Tool] - ArgoCD란?

2023.08.09 - [IaC/CI CD Tool] - ArgoCD 설치 AWS & GCP

2023.10.02 - [IaC/CI CD Tool] - ArgoCD ApplicationSet이란? (작성 방법)

2023.10.08 - [Container Orchestration/Kubernetes] - 2. Kustomize + ArgoCD ApplicationSet

2024.02.02 - [IaC/CI CD Tool] - Argo Workflow란?

2024.04.09 - [IaC/CI CD Tool] - ArgoCD SSO 구성 가이드(GCP Oauth)

2025.02.19 - [IaC/CI CD Tool] - ArgoCD SSO 구성 가이드(Gitlab)

 

 


 

 

ArgoCD Notifications란?

ArgoCD의 공식 구성요소로, 특정 이벤트 발생 시 알람을 전송하는 컨트롤러이다.

  • 이벤트 예시: Sync Succeeded, Sync Failed, Health Degraded 등
  • 지원 채널: Slack, Email, Microsoft Teams, Webhook, etc.

ArgoCD Helm Chart를 사용할 경우 `notifications.enabled` 옵션만 켜면 바로 설치된다.

 

 

 

 


 

 

 

 

전체 흐름 정리

 
+------------+     (OutOfSync, Degraded 등 상태 감지)     +----------------+
|  ArgoCD   | ---------------------------------------> | Notifications |
|  App Sync  |                                        |  Controller   |
+------------+                                         +----------------+
                                                          |
                                                          v
                                                +----------------+
                                                |   Slack 알람   |
                                                +----------------+

 

 

 

 


 

 

 

 

 

ArgoCD Slack Notifications 설정

 

준비 단계 - Slack 앱 생성

 

1️⃣ Slack 앱 생성

 

2️⃣ 필요한 권한(Scopes) 추가

  • chat:write (필수)
  • chat:write.customize (아이콘 재정의 권한)

 

3️⃣ OAuth Token 발급

  • Slack 앱에서 Install App to Workspace 진행
  • 발급된 Bot User OAuth Token을 복사 (xoxb-로 시작하는 값)

 

 

 

 


 

 

 

 

 

Helm Values 설정 

 

1️⃣ App 권한 설정

notifications:
  # -- Enable notifications controller
  enabled: true

  secret:
    create: true
    items:
      slack-token: "xoxb-slack-token"
  
  notifiers:
    service.slack: |
      token: $slack-token
      username: ArgoCD
      icon: https://argo-cd.readthedocs.io/en/stable/assets/logo.png
      channel: "#argocd-alarm" # TODO: change to <your-channel-name>

 

 

2️⃣ templates 설정 예시

  templates:
    template.app-deployed: |
      message: |
        :white_check_mark: 애플리케이션 {{.app.metadata.name}}이(가) 성공적으로 배포되었습니다.
      slack:
        attachments: |
          [{
            "title": "{{ .app.metadata.name}} - 배포 성공",
            "title_link":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}",
            "color": "#18be52",
            "fields": [
            {
              "title": "동기화 상태",
              "value": "{{.app.status.sync.status}}",
              "short": true
            },
            {
              "title": "앱 상태",
              "value": "{{.app.status.health.status}}",
              "short": true
            },
            {
              "title": "네임스페이스",
              "value": "{{.app.spec.destination.namespace}}",
              "short": true
            },
            {
              "title": "리비전",
              "value": "{{.app.status.sync.revision}}",
              "short": true
            }
            ]
          }]
 
 # Test 설정
     template.app-healthy: |
      message: |
        :white_check_mark: 애플리케이션 {{.app.metadata.name}}이(가) 정상 상태입니다.
      slack:
        attachments: |
          [{
            "title": "{{ .app.metadata.name}} - 정상 상태",
            "title_link":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}",
            "color": "#18be52",
            "fields": [
            {
              "title": "동기화 상태",
              "value": "{{.app.status.sync.status}}",
              "short": true
            },
            {
              "title": "앱 상태",
              "value": "{{.app.status.health.status}}",
              "short": true
            },
            {
              "title": "네임스페이스",
              "value": "{{.app.spec.destination.namespace}}",
              "short": true
            },
            {
              "title": "리비전",
              "value": "{{.app.status.sync.revision}}",
              "short": true
            }
            ]
          }]

 

 

 

3️⃣ Triggers & Subscriptions 설정

  triggers:
    trigger.on-deployed: |
      - description: Application is synced and healthy after any operation.
        send:
        - app-deployed
        when: |
          app.status.operationState.phase == 'Succeeded' and 
          app.status.health.status == 'Healthy' and 
          app.status.operationState != null

    trigger.test-notification: |
      - description: 테스트 알림 - 애플리케이션이 정상 상태일 때
        send:
        - app-healthy
        when: "true"  # 항상 트리거됨
 
 
   subscriptions:
    - recipients:
      - slack:#argocd-alarm # TODO: change to <your-channel-name>
      triggers:
      - on-deployed
      - test-notification

 

 

 

test-notification 결과는 아래와 같다.

 

 

 

 

이외에도 다양한 트리거 설정이 가능하다.

    template.app-health-degraded: |
      message: |
        :red_circle: 애플리케이션 {{.app.metadata.name}}의 상태가 저하되었습니다.
      slack:
        attachments: |
          [{
            "title": "{{ .app.metadata.name}} - 상태 저하",
            "title_link":"{{.context.argocdUrl}}/applications/{{.app.metaata.name}}",
            "color": "#E96D76",
            "fields": [
            {
              "title": "동기화 상태",
              "value": "{{.app.status.sync.status}}",
              "short": true
            },
            {
              "title": "앱 상태",
              "value": "{{.app.status.health.status}}",
              "short": true
            },
            {
              "title": "네임스페이스",
              "value": "{{.app.spec.destination.namespace}}",
              "short": true
            }
            {{range $index, $c := .app.status.conditions}}
            ,{
              "title": "{{$c.type}}",
              "value": "{{$c.message}}",
              "short": false
            }
            {{end}}
            ]
          }]
    
    template.app-sync-failed: |
      message: |
        :x: 애플리케이션 {{.app.metadata.name}}의 동기화가 실패했습니다.
      slack:
        attachments: |
          [{
            "title": "{{ .app.metadata.name}} - 동기화 실패",
            "title_link":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}?operation=true",
            "color": "#E96D76",
            "fields": [
            {
              "title": "동기화 상태",
              "value": "{{.app.status.sync.status}}",
              "short": true
            },
            {
              "title": "앱 상태",
              "value": "{{.app.status.health.status}}",
              "short": true
            },
            {
              "title": "네임스페이스",
              "value": "{{.app.spec.destination.namespace}}",
              "short": true
            },
            {
              "title": "오류 메시지",
              "value": "{{.app.status.operationState.message}}",
              "short": false
            }
            ]
          }]
    
    template.app-sync-status-out-of-sync: |
      message: |
        :warning: 애플리케이션 {{.app.metadata.name}}이(가) OutOfSync 상태입니다.
      slack:
        attachments: |
          [{
            "title": "{{ .app.metadata.name}} - OutOfSync",
            "title_link":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}",
            "color": "#f4c030",
            "fields": [
            {
              "title": "동기화 상태",
              "value": "{{.app.status.sync.status}}",
              "short": true
            },
            {
              "title": "앱 상태",
              "value": "{{.app.status.health.status}}",
              "short": true
            },
            {
              "title": "네임스페이스",
              "value": "{{.app.spec.destination.namespace}}",
              "short": true
            },
            {
              "title": "리비전",
              "value": "{{.app.status.sync.revision}}",
              "short": true
            }
            ]
          }]
    
    template.app-health-missing: |
      message: |
        :question: 애플리케이션 {{.app.metadata.name}}의 상태 정보가 없습니다.
      slack:
        attachments: |
          [{
            "title": "{{ .app.metadata.name}} - 앱 상태 정보 없음",
            "title_link":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}",
            "color": "#808080",
            "fields": [
            {
              "title": "동기화 상태",
              "value": "{{.app.status.sync.status}}",
              "short": true
            },
            {
              "title": "네임스페이스",
              "value": "{{.app.spec.destination.namespace}}",
              "short": true
            }
            ]
          }]
  triggers:
    trigger.on-deployed: |
      - description: Application is synced and healthy after any operation.
        send:
        - app-deployed
        when: |
          app.status.operationState.phase == 'Succeeded' and 
          app.status.health.status == 'Healthy' and 
          app.status.operationState != null
    trigger.on-health-degraded: |
      - description: Application has degraded
        send:
        - app-health-degraded
        when: app.status.health.status == 'Degraded'
    trigger.on-sync-failed: |
      - description: Application syncing has failed
        send:
        - app-sync-failed
        when: app.status.operationState.phase in ['Error', 'Failed']
    trigger.on-sync-status-out-of-sync: |
      - description: Application sync status is 'OutOfSync'
        send:
        - app-sync-status-out-of-sync
        when: |
          app.status.sync.status == 'OutOfSync' and 
          app.status.health.status not in ['Progressing', 'Healthy'] and 
          (app.metadata.creationTimestamp == null or 
            time.Now().Sub(time.Parse(app.metadata.creationTimestamp)).Minutes() > 5) and
          ((app.status.operationState == null) or 
          (app.status.operationState != null and 
            app.status.operationState.phase != 'Running' and 
            app.status.operationState.finishedAt != null and
            time.Now().Sub(time.Parse(app.status.operationState.finishedAt)).Seconds() > 60))
    trigger.on-health-missing: |
      - description: Application health status is missing
        send:
        - app-health-missing
        when: app.status.health.status == 'Missing'
    trigger.on-restarted: |
      - description: Application has been restarted
        send:
        - app-restarted
        when: app.status.health.status == 'Progressing'

 

 

 

 

아래와 같이 다른 값들도 전달해줄 수 있다.

  templates:
    template.app-deployed: |
      message: |
        :white_check_mark: 애플리케이션 {{.app.metadata.name}}이(가) 성공적으로 배포되었습니다.
      slack:
        attachments: |
          [{
            "title": "{{ .app.metadata.name}} - 배포 성공",
            "title_link":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}",
            "color": "#18be52",
            "fields": [
            {
              "title": "동기화 상태",
              "value": "{{.app.status.sync.status}}",
              "short": true
            },
            {
              "title": "앱 상태",
              "value": "{{.app.status.health.status}}",
              "short": true
            },
            {
              "title": "네임스페이스",
              "value": "{{.app.spec.destination.namespace}}",
              "short": true
            },
            {
              "title": "배포 시간",
              "value": "{{.app.status.operationState.finishedAt}}",
              "short": true
            },
            {
              "title": "작업자",
              "value": "{{if .app.status.operationState.operation.initiatedBy.username}}{{.app.status.operationState.operation.initiatedBy.username}}{{else}}자동{{end}}",
              "short": true
            },
            {
              "title": "대상 서버",
              "value": "{{.app.spec.destination.server}}",
              "short": true
            }
            {{range $index, $image := .app.status.summary.images}}
            ,{
              "title": "이미지",
              "value": "{{$image}}",
              "short": false
            }
            {{end}}
            ]
          }]

 

 

 

 

 


 

 

 

 

마무리

  • 이제 ArgoCD의 중요한 상태 변화는 Slack으로 바로 알람을 받을 수 있다.
  • 특히 운영 환경에서는 Sync 실패나 Health Degraded 같은 문제를 실시간으로 감지하는 게 매우 중요하기 때문에, ArgoCD Notifications + Slack 연동은 필수 구성이라고 할 수 있다.

 

 

➡️ 여러분의 ArgoCD도 지금 바로 Slack과 연결해서 장애 대응 속도를 높여보세요!

 

 

 

 

 

 


Reference

https://argo-cd.readthedocs.io/en/stable/operator-manual/notifications/services/slack/

728x90
반응형