이 글에서 다루는 것
Argo CD Notifications Controller로 Sync/Health 이벤트를 Slack에 실시간 전송하고, Webhook URL을 SealedSecret으로 안전하게 관리하는 GitOps 모니터링 자동화 구조를 다룹니다.
선수지식
- MLOps 운영 고도화 4단계: FastAPI 로그 안정화 — NFS PVC 기반 로그 영속화
이 단계에서 해결하려는 문제
GitOps는 자동으로 잘 돌아가더라도, 지금 무슨 일이 일어나는지 모르면 운영자는 항상 불안하다. Argo CD의 Sync/Health 변화를 즉시 Slack으로 받아보는 GitOps 모니터링 루프를 만들어서, 커밋 이후 어떤 일이 일어나는지 실시간으로 보이게 만든다.
🎯 핵심 요약
- Argo CD Notifications Controller로 Sync/Health 이벤트를 Slack에 실시간 전송
- Webhook URL → SealedSecret → 환경변수 참조로 안전 관리(레포 커밋 OK)
- 템플릿/트리거/구독을 ConfigMap 한 곳에서 선언적으로 관리
- Git 커밋 → Argo Sync → Slack 알림의 자동 루프 완성
1️⃣ 전체 흐름 요약

2️⃣ 폴더/리소스 구조(레포 반영 상태)
mlops-infra/
├─ bootstrap/
│ └─ notifications/
│ ├─ cm.yaml # 템플릿/트리거/구독 선언
│ ├─ secret-sealed.yaml # Slack Webhook(SealedSecret)
│ └─ kustomization.yaml # (선택) 동일 디렉터리 리소스 묶음
└─ apps/
├─ project-notifications.yaml
└─ notifications.yaml
3️⃣ Slack Webhook(SealedSecret) — 안전 주입
# bootstrap/notifications/secret-sealed.yaml
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
name: argocd-notifications-secret
namespace: argocd
spec:
encryptedData:
slack-webhook: AgC...== # kubeseal 결과(키: slack-webhook)
template:
metadata:
name: argocd-notifications-secret
namespace: argocd
type: Opaque
생성 절차(로컬에서 1회)
# 원문 Secret (파일로 출력)
kubectl -n argocd create secret generic argocd-notifications-secret \
--from-literal=slack-webhook='<YOUR_SLACK_WEBHOOK_URL>' \
--dry-run=client -o yaml > /tmp/argocd-noti-secret.yaml
# seal (컨트롤러 이름/네임스페이스는 실제 설치값과 정확히 일치해야 함)
kubeseal --controller-name sealed-secrets \
--controller-namespace kube-system \
-o yaml < /tmp/argocd-noti-secret.yaml \
> bootstrap/notifications/secret-sealed.yaml
기존 레포의 다른 SealedSecret들과 동일하게 controller-name/namespace를 맞춰야 복호화됩니다.
4️⃣ 템플릿/트리거/구독(ConfigMap) — 한 곳에서 일원화
# bootstrap/notifications/cm.yaml (핵심부)
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-notifications-cm
namespace: argocd
data:
context: |
argocdUrl: https://argocd.local
service.webhook.slack_webhook: |
url: $slack-webhook
headers:
- name: Content-Type
value: application/json
# 템플릿: Sync 상태 변경
template.send-slack-status: |
webhook:
slack_webhook:
method: POST
body: |
{
"text": "*[{{.app.metadata.name}}]* Sync *{{.app.status.sync.status}}* → Health *{{.app.status.health.status}}*\n· Rev: `{{.app.status.sync.revision}}`\n<{{.context.argocdUrl}}/applications/{{.app.metadata.name}}|Open in ArgoCD>"
}
# 트리거 + 구독 (동일 ConfigMap 내)
trigger.on-sync-status-change: |
- when: app.status.sync.status in ['Synced', 'OutOfSync']
send: [send-slack-status]
subscriptions: |
- recipients:
- slack_webhook
triggers:
- on-sync-status-change
- on-sync-failed
- on-health-degraded
핵심 포인트:
- Webhook 키 이름은
slack-webhook(SealedSecret의 data 키와 일치)- 수신 대상은 채널명 대신
slack_webhook(service.webhook 식별자)으로 구독
5️⃣ Argo CD Project & Application (GitOps로 관리)
# apps/project-notifications.yaml
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: notifications
namespace: argocd
spec:
description: Project for Argo CD Notifications
sourceRepos:
- 'https://github.com/keonhoban/mlops-infra-gitops'
destinations:
- namespace: argocd
server: https://kubernetes.default.svc
clusterResourceWhitelist:
- group: '*'
kind: '*'
orphanedResources:
warn: true
# apps/notifications.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: notifications
namespace: argocd
annotations:
argocd.argoproj.io/sync-wave: "2"
spec:
project: notifications
source:
repoURL: https://github.com/keonhoban/mlops-infra-gitops
targetRevision: main
path: bootstrap/notifications
destination:
server: https://kubernetes.default.svc
namespace: argocd
syncPolicy:
automated:
prune: true
selfHeal: true
6️⃣ 적용 & 검증 시퀀스
# 1) 프로젝트/앱 적용
kubectl -n argocd apply -f apps/project-notifications.yaml
kubectl -n argocd apply -f apps/notifications.yaml
# 2) 동기화/상태
argocd app sync notifications --grpc-web
argocd app get notifications
# 3) 컨트롤러 로그(이상 시)
kubectl -n argocd logs deploy/argocd-notifications-controller
정상 지표
notifications앱이 Synced/Healthy- 템플릿 변경 → 커밋/푸시 시, Slack에 Sync/Health 메시지 수신
7️⃣ 운영 체크리스트
-
argocd-notifications-secretSealedSecret가argocd네임스페이스에 정상 복호화 - ConfigMap의 service.webhook.slack_webhook ↔ SealedSecret 키(slack-webhook) 일치
- Argo CD Notifications Controller가 실행 중(Argo 2.6+ 기본 포함)
-
context.argocdUrl이 실제 접속 URL과 일치 - (옵션) 앱별로 별도 구독을 두고 싶으면
subscriptions를 다중 항목으로 분리
🧩 팁
- Bot Token 모드로 전환하면 멘션/스레드/이모지 커스터마이징이 쉬워짐 (
service.slack:사용) - 앱별 다른 채널:
service.webhook.slack_teamA,..._teamB추가 후subscriptions분기 - 메시지에 커밋 SHA/링크 포함:
{{.app.status.sync.revision}}사용
설계 판단 (Why This Way?)
ArgoCD Notifications 설정을 ConfigMap 한 장에 모아 Git diff로 변경 이력을 추적하고, Slack Webhook URL은 SealedSecret으로 암호화하여 Git 노출로 인한 임의 메시지 전송을 방지합니다.
다음에 읽을 글
→ MLOps 운영 고도화 6단계: GitOps 고도화 — ArgoCD 동기화 전략 정교화