Ssoon

Argo CD in Practice – 3) Argo CD 운영 : 가시성 활성화 본문

CICD Study [1기]

Argo CD in Practice – 3) Argo CD 운영 : 가시성 활성화

구구달스 2025. 10. 19. 19:03

 

🔍 Enabling Observability – Argo CD 모니터링

  • 잘못된 설정, 오래된 버전, immutable 필드 업데이트 시도, 대규모 동기화, SSH 키 누락, 혹은 대형 애플리케이션으로 인한 timeout 문제 등이 발생할 수 있습니다. 이럴 때 필요한 것이 바로  Observability(가시성) 입니다.
  • Observability는 시스템의 상태(health), 성능(performance), 그리고 행동(behavior) 을 이해하는 능력을 제공합니다.

📈 Observability의 핵심 – Argo CD Metrics

  • 다행히 Argo CD는 다양한 metrics를 Prometheus 형식으로 제공합니다.
  • 이를 통해 시스템이 **과부하(Overutilized)**인지 **저활용(Underutilized)**인지 파악할 수 있고, 문제가 발생했을 때 특정 애플리케이션 담당 팀에게 **알림(Alert)**을 보낼 수도 있습니다.
  • Argo CD의 모니터링과 알림은 두 방향으로 구분할 수 있습니다:
    • 운영팀(Operating Team) – Argo CD 자체를 운영 및 유지보수하는 팀
    • 마이크로서비스팀(Microservices Teams) – 각 애플리케이션을 개발하고 배포하는 팀

"Observability는 문제를 사전에 감지하고, 복잡한 환경에서 신속하게 대응할 수 있도록 돕는 운영의 핵심 요소다."


🧠 Monitoring with Prometheus

  • Prometheus는 Kubernetes와 더불어 클라우드 네이티브 모니터링의 표준으로 자리 잡았습니다.
    Kubernetes가 CNCF 첫 번째 프로젝트였다면, Prometheus는 두 번째로 CNCF에 합류한 프로젝트입니다.

🛠️ kube-prometheus-stack 설치

  • Helm 저장소 prometheus-community 추가
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-72C919S:~/my-sample-app$ helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
"prometheus-community" has been added to your repositories
  • 파라미터 파일 생성
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-72C919S:~/my-sample-app$ cat <<EOT > monitor-values.yaml
prometheus:
  prometheusSpec:
    scrapeInterval: "15s"
    evaluationInterval: "15s"
  service:
    type: NodePort
    nodePort: 30002

grafana:
  defaultDashboardsTimezone: Asia/Seoul
  adminPassword: prom-operator
  service:
    type: NodePort
    nodePort: 30003

alertmanager:
  enabled: false
defaultRules:
  create: false
prometheus-windows-exporter:
  prometheus:
    monitor:
      enabled: false
EOT

⚙️ 주요 설정 내용

  • Prometheus (프로메테우스)
    • 수집 주기: 15초마다 메트릭을 수집(scrapeInterval)하고, 15초마다 알림 규칙을 평가(evaluationInterval)합니다.
    • 접속 방식: Prometheus 서비스에 외부에서 접속할 수 있도록 NodePort 타입을 사용하고, 포트 번호를 30002로 고정합니다.
  • Grafana (그라파나)
    • 시간대: 대시보드의 기본 시간대를 **'Asia/Seoul' (서울)**로 설정합니다.
    • 비밀번호: 관리자(admin) 계정의 비밀번호를 **'prom-operator'**로 설정합니다.
    • 접속 방식: Grafana 서비스에 외부에서 접속할 수 있도록 NodePort 타입을 사용하고, 포트 번호를 30003으로 고정합니다.
  • 비활성화하는 기능들
    • Alertmanager: 알림(Alert)을 관리하는 alertmanager 컴포넌트를 비활성화합니다 (enabled: false).
    • 기본 규칙: 차트에 포함된 기본 알림 규칙(defaultRules)을 생성하지 않습니다 (create: false).
    • Windows Exporter: Windows 노드 모니터링(prometheus-windows-exporter) 관련 기능도 비활성화합니다.
  • 배포
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-72C919S:~/my-sample-app$ helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack --version 75.15.1 \
-f monitor-values.yaml --create-namespace --namespace monitoring
NAME: kube-prometheus-stack
LAST DEPLOYED: Sat Nov  8 17:48:44 2025
NAMESPACE: monitoring
STATUS: deployed
REVISION: 1
NOTES:
kube-prometheus-stack has been installed. Check its status by running:
  kubectl --namespace monitoring get pods -l "release=kube-prometheus-stack"

Get Grafana 'admin' user password by running:

  kubectl --namespace monitoring get secrets kube-prometheus-stack-grafana -o jsonpath="{.data.admin-password}" | base64 -d ; echo

Access Grafana local instance:

  export POD_NAME=$(kubectl --namespace monitoring get pod -l "app.kubernetes.io/name=grafana,app.kubernetes.io/instance=kube-prometheus-stack" -oname)
  kubectl --namespace monitoring port-forward $POD_NAME 3000

Visit https://github.com/prometheus-operator/kube-prometheus for instructions on how to create & configure Alertmanager and Prometheus instances using the Operator.
  • kube-prometheus-stack: 릴리스 이름입니다. Helm을 통해 설치된 리소스들을 이 이름으로 관리합니다.
  • prometheus-community/kube-prometheus-stack: 설치할 Helm 차트입니다. Prometheus, Grafana, Alertmanager 등을 포함한 통합 모니터링 스택입니다.
  • --version 75.15.1: 특정 버전의 차트를 설치합니다. 안정성과 호환성을 위해 명시한 것으로 보입니다.
  • -f monitor-values.yaml: 사용자 정의 설정 파일을 적용합니다. 앞서 작성한 설정이 여기에 포함됩니다.
  • --create-namespace: 지정한 네임스페이스(monitoring)가 없으면 자동으로 생성합니다.
  • --namespace monitoring: 리소스를 설치할 네임스페이스입니다.

🛠️ Argo CD 구성요소에 대한 ServiceMonitor 생성

  • 테스트용 파드
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-72C919S:~/my-sample-app$ cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx:alpine
    ports:
    - containerPort: 80
EOF
pod/nginx created
  • ServiceMonitor 생성
    • Prometheus가 Argo CD의 메트릭을 수집하도록 설정하는 '규칙'을 생성
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-72C919S:~/my-sample-app$ cat <<EOF | kubectl apply -f -
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: argocd-metrics
  namespace: monitoring
  labels:
    release: kube-prometheus-stack
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: argocd-metrics
  endpoints:
    - port: metrics
  namespaceSelector:
    matchNames:
      - argocd
EOF
servicemonitor.monitoring.coreos.com/argocd-metrics created
  • ServiceMonitor 생성
    • argocd-server-metrics 라는 또 다른 서비스를 Prometheus가 모니터링하도록 추가
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-72C919S:~/my-sample-app$ cat <<EOF | kubectl apply -f -
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: argocd-server-metrics
  namespace: monitoring
  labels:
    release: kube-prometheus-stack
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: argocd-server-metrics
  endpoints:
    - port: metrics
  namespaceSelector:
    matchNames:
      - argocd
EOF
servicemonitor.monitoring.coreos.com/argocd-server-metrics created
  • ServiceMonitor 생성
    • Prometheus가 Argo CD의 repo-server 컴포넌트에서 메트릭을 수집할 수 있도록 설정
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-72C919S:~/my-sample-app$ cat <<EOF | kubectl apply -f -
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: argocd-repo-server-metrics
  namespace: monitoring
  labels:
    release: kube-prometheus-stack
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: argocd-repo-server
  endpoints:
    - port: metrics
  namespaceSelector:
    matchNames:
      - argocd
EOF
servicemonitor.monitoring.coreos.com/argocd-repo-server-metrics created

 

  • ServiceMonitor 생성
    • ApplicationSet 컨트롤러, Dex 인증 서버, HA Redis 프록시, 그리고 알림 컨트롤러까지 모두 모니터링 하도록 설정
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-72C919S:~/my-sample-app$ cat <<EOF | kubectl apply -f -
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: argocd-applicationset-controller-metrics
  namespace: monitoring
  labels:
    release: kube-prometheus-stack
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: argocd-applicationset-controller
  endpoints:
    - port: metrics
  namespaceSelector:
    matchNames:
      - argocd
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: argocd-dex-server
  namespace: monitoring
  labels:
    release: kube-prometheus-stack
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: argocd-dex-server
  endpoints:
    - port: metrics
  namespaceSelector:
    matchNames:
      - argocd
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: argocd-redis-haproxy-metrics
  namespace: monitoring
  labels:
    release: kube-prometheus-stack
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: argocd-redis-ha-haproxy
  endpoints:
    - port: http-exporter-port
EOF   - argocd:ctor:.io/name: argocd-notifications-controller-metrics
servicemonitor.monitoring.coreos.com/argocd-applicationset-controller-metrics created
servicemonitor.monitoring.coreos.com/argocd-dex-server created
servicemonitor.monitoring.coreos.com/argocd-redis-haproxy-metrics created
servicemonitor.monitoring.coreos.com/argocd-notifications-controller created
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-72C919S:~/my-sample-app$ kubectl get servicemonitors -n monitoring | grep argocd
argocd-applicationset-controller-metrics         31s
argocd-dex-server                                31s
argocd-metrics                                   4m35s
argocd-notifications-controller                  31s
argocd-redis-haproxy-metrics                     31s
argocd-repo-server-metrics                       102s
argocd-server-metrics                            2m56s

  • argo.. 관련 메트릭 확인

"Prometheus Operator를 사용하면 Argo CD의 모든 주요 컴포넌트에서 metrics를 자동으로 수집할 수 있다."


📊 Grafana 대시보드로 시각화하기

  • Prometheus가 metrics를 수집하기 시작하면, Grafana Dashboard를 통해 시각화할 수 있습니다.
  • Argo CD 공식 문서에서는 예시 대시보드를 제공합니다:📎 Argo CD Metrics Dashboard
  • 또한 Grafana의 공식 문서를 참고해 대시보드 import를 수행하면 됩니다. 📎 Grafana Import Dashboard Guide

"Grafana는 Prometheus에서 수집한 데이터를 직관적으로 시각화해 운영자가 즉시 이상 징후를 파악할 수 있게 돕는다."


그라파나 대시보드 추가 후 확인

✅ Grafana 로그인 정보

  • Username: admin
  • Password: prom-operator

https://github.com/argoproj/argo-cd/blob/master/examples/dashboard.json


⚙️ Metrics for the Operating Team

  • 운영팀은 Argo CD의 **핵심 컴포넌트(Repo Server, Controller)**의 상태를 모니터링해야 합니다.
    이 컴포넌트들이 원활하게 작동해야 전체 시스템의 성능이 유지되기 때문입니다.

🚨 OOMKilled 감지

  • 가장 중요한 metric 중 하나는 Argo CD 자체 metric이 아닌, OOMKilled 이벤트입니다.
    이는 노드의 OS가 메모리 초과로 인해 컨테이너를 강제 종료시킬 때 발생합니다.
  • 다음 Prometheus 쿼리는 최근 5분 이내 OOMKilled된 컨테이너를 감지합니다:
sum by (pod, container, namespace) (
  kube_pod_container_status_last_terminated_reason{reason="OOMKilled"}
)
* on (pod,container) group_left
sum by (pod, container) (
  changes(kube_pod_container_status_restarts_total[5m])
) > 0
  • 이 알림이 일주일에 몇 번 정도면 괜찮지만, 하루에 여러 번 발생한다면 조치가 필요합니다.
  • 대응 방안은 다음과 같습니다:
    • Deployment/StatefulSet의 replicas 수 증가 → 부하 분산
    • 컨테이너의 CPU/Memory 자원 상향 조정
    • 병렬 처리 제한 파라미터 조정
      • Repo Server: --parallelismlimit
      • Controller: --kubectl-parallelism-limit

"OOMKilled는 자원 부족이나 과도한 병렬 작업의 신호이며, 시스템 조정을 통해 해결할 수 있다."


⚡ System Load Metrics

  • 시스템의 부하 상태를 파악하기 위한 대표적인 metric은 두 가지입니다.

🧩 Repo Server 부하 지표

  • Repo Server는 Git 리포지토리에서 내용을 가져와 템플릿을 렌더링합니다.
    이때 대기 중인 요청 수를 나타내는 metric은 다음과 같습니다:
argocd_repo_pending_request_total
  • 이 수치는 가능한 한 0에 가까워야 합니다.
    단기간 증가하는 것은 괜찮지만, 지속적으로 높은 수치를 보인다면 성능 문제가 있을 수 있습니다.

참고: HPA를 통한 자동 스케일링은 간단하지 않으므로 관련 논의는 이슈 #2559를 참고하세요.

🧠 Application Controller 부하 지표

  • Application Controller는 apply 및 auth 명령을 실행합니다.
    현재 대기 중인 명령의 수는 아래 metric으로 확인할 수 있습니다:
argocd_kubectl_exec_pending
  • 이 값이 --kubectl-parallelism-limit 설정값과 같거나 높은 상태가 오랫동안 지속되면 동기화 지연 문제가 발생할 수 있습니다.

"부하 지표는 시스템의 병목을 조기에 감지해 성능 저하를 예방할 수 있는 중요한 신호다."


👩‍💻 Metrics for Microservices Teams

  • 플랫폼 팀이 개발팀에게 셀프서비스 환경을 제공하려면, 각 개발팀도 자신들의 Argo CD Application 상태를 모니터링하고
    문제 발생 시 직접 알림을 받을 수 있어야 합니다.
  • 대표적인 두 가지 metric은 다음과 같습니다:
    • Application Synchronization Status
    • Application Health Status

🔁 Application Synchronization Status

  • 이 metric은 애플리케이션의 동기화 실패 여부를 감지합니다.
    다음 쿼리는 최근 5분 내 Failed 상태로 변경된 Application을 찾아냅니다.
sum by (name) (
  changes(argocd_app_sync_total{
    phase="Failed",
    exported_namespace="argocd",
    name=~"accounting.*"
  }[5m])
) > 0
  • 이 쿼리는 argocd 네임스페이스 내에서 이름이 accounting으로 시작하는 애플리케이션만 필터링합니다.

"동기화 실패 알림을 통해 개발팀은 배포 실패를 즉시 인지하고 빠르게 대응할 수 있다."


❤️ Application Health Status

  • 이 metric은 **애플리케이션이 비정상 상태(Degraded)**인지 여부를 추적합니다. 이는 동기화 이벤트와 별개로 발생할 수 있습니다.
  • 예를 들어, 3개의 replica를 요청했지만 2개만 실행 중이라면 Degraded 상태로 표시됩니다.
  • 다음 쿼리는 argocd 네임스페이스에서 이름이 prod로 시작하고 app으로 끝나지 않는 애플리케이션 중 Degraded 상태인 것을 감지합니다:
argocd_app_info{
  health_status="Degraded",
  exported_namespace="argocd",
  name=~"prod.*",
  name!~".*app"
}

"Degraded 상태는 프로덕션 환경에서 성능 저하나 장애를 의미하므로 즉시 점검이 필요하다."


📌 핵심 요약

  • Observability는 복잡한 Kubernetes 환경에서 시스템의 상태를 명확히 파악하기 위한 필수 요소
  • Prometheus Operator로 Argo CD의 metrics를 손쉽게 수집
  • ServiceMonitor를 통해 Application Controller, API Server, Repo Server의 데이터를 모니터링
  • Grafana Dashboard로 시각화하여 실시간으로 상태 확인
  • 운영팀은 OOMKilled, Repo Load, Controller Load 지표를 주로 모니터링
  • 개발팀은 Sync StatusHealth Status를 기반으로 배포 안정성을 확인
  • 마지막으로 Argo CD Notifications를 통해 자동 알림을 설정하면 완벽한 모니터링 체계 구축 가능

"모니터링은 단순한 데이터 수집이 아니라, 빠른 문제 인지와 지속 가능한 운영을 위한 전략적 도구다."

Comments