13년차의 서버실

서버, 인프라, 홈랩 기술 블로그

[태그:] 인프라 모니터링

  • [Cloud] Datadog 비용 최적화 전략: 불필요한 지출 줄이기

    [Cloud] Datadog 비용 최적화 전략: 불필요한 지출 줄이기

    Datadog 비용 최적화 전략: 불필요한 지출을 줄이는 운영 방법론

    Datadog 비용 최적화는 모니터링을 약하게 만드는 일이 아닙니다. 장애를 설명하는 신호는 끝까지 남기고, 아무도 보지 않는 반복 신호는 수집 전이나 색인 단계에서 줄이는 작업에 가깝습니다. 이 선을 먼저 정해두면 비용도 줄고, 운영자가 불안해하지 않더라고요.

    Datadog 비용이 커지는 조직을 보면 공통점이 있습니다. 기능을 많이 써서라기보다 수집 정책의 기본값이 운영 정책처럼 굳어져 있습니다. Docker stdout은 전부 로그로 들어오고, Kubernetes의 짧게 뜨는 Job도 서비스처럼 취급되고, DEBUG 로그는 릴리스가 끝난 뒤에도 계속 색인됩니다.

    홈랩에서 Kubernetes와 VM을 섞어 굴릴 때도 비슷했습니다. 서비스 몇 개만 올렸는데 health check 로그, readiness probe 로그, 테스트 Job 출력, DEBUG 로그가 생각보다 빨리 쌓이더라고요. 그때 깨달은 건 단순했습니다. 비용을 줄이려면 UI에서 필터 몇 개 만지는 것보다 수집, 태깅, 색인, 보관, 알림의 경계를 먼저 정해야 합니다.

    Datadog 비용 최적화 전체 흐름을 보여주는 아키텍처 다이어그램

    Datadog 비용 최적화는 한 번의 정리 작업이 아니라 운영 루프입니다. 저는 보통 귀속 → 차단 → 샘플링 → 보관 → 검증 순서로 봅니다. 이 순서를 지키면 무엇을 줄였는지와 무엇을 아직 볼 수 있는지가 같이 남습니다.

    1. Datadog 비용 최적화는 제품명이 아니라 의사결정 단위로 보기

    Datadog 지출을 볼 때 “로그가 비싸다”, “APM이 비싸다”처럼 제품명으로만 보면 조치가 흐려집니다. 실무에서는 다음 질문으로 쪼개야 합니다.

    • 누가 만들었나: team, service, env 태그로 소유자를 찾을 수 있는가?
    • 어디에서 늘었나: host, container, custom metric, indexed log, ingested log, trace 중 어느 축인가?
    • 장애 대응에 쓰였나: 최근 인시던트에서 실제로 검색하거나 알림 조건에 사용했는가?
    • 줄이면 무엇을 잃나: 원인 분석 시간, 보안 감사, 규제 보관, SLO 계산에 영향이 있는가?

    제가 가장 먼저 확인하는 화면과 지표는 아래입니다.

    • Usage Attribution: 설정한 태그 키를 기준으로 사용량을 나눠 봅니다. 다만 모든 제품 사용량이 모든 태그 기준으로 완벽히 분해되지는 않습니다.
    • Estimated Usage Metrics: datadog.estimated_usage.* 메트릭으로 증가 추세를 봅니다. 실시간 추정치라 청구서와 1:1로 맞추는 용도보다는 변화 감지에 더 적합합니다.
    • Log Indexes: 어떤 로그가 검색 가능한 상태로 저장되는지, 어떤 exclusion filter를 통과하는지 확인합니다.
    • Retention: prod 오류 로그와 dev access log가 같은 기간 저장되고 있지 않은지 봅니다.

    비용 절감 작업에서 가장 위험한 말은 “일단 Agent 꺼보죠”입니다. Agent를 끄면 비용은 줄어든 것처럼 보이지만 장애 때 시스템이 침묵합니다. 먼저 소유권과 경로를 잡고, 그다음 수집량을 줄이는 편이 안전합니다.

    2. 태그 표준화: 비용 보고서가 아니라 운영 계약으로 다루기

    Datadog에서 태그는 검색 편의 기능을 넘어 비용 통제의 단위입니다. 태그가 흔들리면 Usage Attribution도 흔들리고, 팀별 비용 대화도 금방 흐려집니다. 저는 최소한 아래 4개를 기본 계약으로 둡니다.

    env:prod | env:staging | env:dev
    service:api | service:worker | service:nginx
    team:platform | team:billing | team:checkout
    cost_center:shared | cost_center:revenue | cost_center:internal

    중요한 건 태그 이름보다 태그가 붙는 위치입니다. 애플리케이션 로그에는 service가 붙었는데 컨테이너 메트릭에는 빠지고, APM trace에는 다른 서비스명이 들어가면 비용 분석이 갈라집니다. 가능하면 애플리케이션, 컨테이너 label, Helm values, Agent 설정에서 같은 네이밍을 유지하세요.

    Kubernetes에서는 Pod label과 Datadog 태그를 연결하는 규칙을 명확히 두는 편이 좋습니다. 예를 들어 Helm values에서 공통 태그를 관리하면 배포마다 태그가 빠지는 실수를 줄일 수 있습니다.

    # datadog-values.yaml 예시
    datadog:
      tags:
        - env:prod
        - team:platform
        - cost_center:shared
      logs:
        enabled: true
        containerCollectAll: false
      apm:
        portEnabled: true

    containerCollectAll: false는 모든 컨테이너 로그를 기본 수집하지 않겠다는 선택입니다. 이 값 하나로 비용이 마법처럼 줄지는 않지만, “로그를 보내려면 의도를 표시한다”는 문화를 만들 수 있습니다. 다만 초기 도입기나 장애가 잦은 시스템에서는 너무 빨리 닫으면 디버깅이 어려워집니다.

    3. Agent 단계에서 버릴 것과 Datadog 안에서 줄일 것 구분하기

    로그 비용 최적화의 첫 갈림길은 “Agent에서 보내지 않을 것인가, Datadog에는 보내되 색인하지 않을 것인가”입니다. 둘은 완전히 다른 결정입니다.

    선택지 언제 쓰나 장점 위험
    Agent 단계 제외 health check, readiness probe, 로컬 개발 Job처럼 분석 가치가 낮고 반복적인 로그 전송과 ingestion 자체를 줄입니다. 나중에 Datadog에서 복구할 수 없습니다.
    Index exclusion filter 들어오긴 해야 하지만 검색 저장은 줄이고 싶은 로그 수집 후 라우팅과 샘플링을 조정할 수 있습니다. ingestion은 계속 발생합니다.
    별도 Index 분리 보관 기간, 접근 권한, 검색 목적이 다른 로그 prod, audit, dev 로그의 보관 정책을 다르게 가져갑니다. 라우팅 쿼리와 순서를 문서화해야 합니다.
    애플리케이션 로그 레벨 수정 DEBUG/TRACE가 prod에서 계속 발생하는 경우 가장 근본적인 해결입니다. 릴리스 관찰에 필요한 신호까지 사라질 수 있습니다.

    제 기준은 간단합니다. 절대 다시 보지 않을 로그는 Agent에서 제외하고, 상황에 따라 필요할 수 있는 로그는 Datadog에 보낸 뒤 색인 정책으로 조절합니다. 보안, 감사, 결제, 인증 실패 로그는 비용만 보고 Agent 단계에서 버리면 안 됩니다.

    4. Datadog Agent 로그 수집을 실제로 줄이는 설정

    먼저 Agent가 무엇을 수집하는지 확인합니다. 비용 최적화 전에 이 명령어 결과를 남겨두면 변경 전후 비교가 쉽습니다.

    sudo datadog-agent status
    sudo datadog-agent configcheck
    sudo datadog-agent flare --local

    컨테이너로 Agent를 운영한다면 아래처럼 확인합니다.

    docker exec -it datadog-agent agent status
    docker exec -it datadog-agent agent configcheck

    NGINX access log에서 health check만 제외하려면 서비스별 conf에서 log_processing_rules를 씁니다. 패턴은 Go 정규식 문법을 따르므로, 운영 반영 전에 샘플 로그로 꼭 검증하세요.

    # /etc/datadog-agent/conf.d/nginx.d/conf.yaml
    logs:
      - type: file
        path: /var/log/nginx/access.log
        service: nginx
        source: nginx
        log_processing_rules:
          - type: exclude_at_match
            name: exclude_healthcheck
            pattern: 'GET /health(?:\s|\?)'

    GET /health처럼 단순 문자열만 쓰면 의도치 않은 경로까지 걸릴 수 있습니다. 비용 필터는 일부러 좁게 잡는 편이 낫습니다. 비용을 아끼려다 필요한 장애 로그를 버리면 복구 비용이 더 커지거든요.

    반대로 특정 로그만 보내고 싶다면 include_at_match를 쓸 수 있습니다. 다만 이 방식은 나머지를 모두 버리는 성격이라 dev나 특정 배치 Job처럼 목적이 좁은 곳에만 권합니다.

    # 특정 배치 Job에서 ERROR/WARN만 Datadog으로 전송
    logs:
      - type: file
        path: /var/log/batch/job.log
        service: settlement-batch
        source: java
        log_processing_rules:
          - type: include_at_match
            name: include_warn_error_only
            pattern: '"level":"(WARN|ERROR)"|\b(WARN|ERROR)\b'
    Datadog Agent 로그 필터링으로 옵저버빌리티 비용 절감하는 구성도

    Agent 단계 필터는 효과가 빠르지만 되돌릴 수 있는 데이터가 없습니다. 그래서 저는 health check, liveness probe, 성공한 정적 파일 요청처럼 장애 설명력이 낮고 재현 가능한 로그부터 제외합니다.

    5. Docker와 Kubernetes: 전체 수집보다 명시 수집을 기본값으로 만들기

    컨테이너 환경에서 비용이 흔들리는 이유는 서비스 수보다 수명 짧은 워크로드와 stdout 기본 수집 때문입니다. CronJob, migration Job, 임시 테스트 컨테이너가 모두 같은 규칙으로 수집되면 비용 그래프가 운영 트래픽과 무관하게 튑니다.

    Docker Compose에서는 Datadog Agent가 자기 자신이나 개발용 컨테이너 로그를 물고 들어가지 않게 제외 규칙을 둡니다. Compose의 environment list 문법에서는 값 전체를 불필요하게 따옴표로 감싸지 않는 편이 읽기도 좋습니다.

    services:
      datadog-agent:
        image: gcr.io/datadoghq/agent:latest
        environment:
          - DD_LOGS_ENABLED=true
          - DD_LOGS_CONFIG_CONTAINER_COLLECT_ALL=true
          - DD_CONTAINER_EXCLUDE_LOGS=name:datadog-agent image:^local-dev-tool:.* name:^tmp-.*
          - DD_CONTAINER_EXCLUDE_METRICS=name:^tmp-.*
        volumes:
          - /var/run/docker.sock:/var/run/docker.sock:ro
          - /var/lib/docker/containers:/var/lib/docker/containers:ro
          - /proc/:/host/proc/:ro
          - /sys/fs/cgroup/:/host/sys/fs/cgroup:ro

    DD_CONTAINER_EXCLUDE는 전역 제외에 가깝고, DD_CONTAINER_EXCLUDE_LOGS와 DD_CONTAINER_EXCLUDE_METRICS는 로그와 메트릭을 따로 다룰 때 씁니다. 저는 보통 로그부터 줄입니다. 메트릭은 장애 대응의 기본 뼈대라서, 임시 Job이 아닌 이상 너무 공격적으로 빼지 않습니다.

    Kubernetes에서는 namespace나 label 정책을 섞어야 합니다. 예를 들어 dev namespace 전체 로그를 줄이고, 꼭 필요한 Pod만 annotation으로 수집하는 방식이 관리하기 편합니다.

    # 로그를 수집할 Pod에만 명시적으로 Autodiscovery annotation 부여
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: api
      namespace: prod
    spec:
      template:
        metadata:
          labels:
            app: api
            tags.datadoghq.com/env: prod
            tags.datadoghq.com/service: api
            tags.datadoghq.com/team: checkout
          annotations:
            ad.datadoghq.com/api.logs: >-
              [{"source":"java","service":"api","log_processing_rules":[{"type":"exclude_at_match","name":"drop_health","pattern":"GET /health(?:\\s|\\?)"}]}]
        spec:
          containers:
            - name: api
              image: registry.example.com/api:stable

    여기서 흔한 실패 모드는 컨테이너 이름 불일치입니다. annotation의 ad.datadoghq.com/api.logs에서 api는 컨테이너 이름과 맞아야 합니다. Deployment 이름이나 Kubernetes Service 이름으로 착각하면 설정이 조용히 빗나갑니다.

    6. Log Index와 Exclusion Filter: 비용 최적화의 진짜 손잡이

    Datadog 로그는 ingestion과 indexing을 나눠 봐야 합니다. 들어온 로그 전체가 곧 검색 가능한 로그는 아닙니다. Index exclusion filter를 쓰면 Datadog에는 로그가 들어오지만, 특정 조건의 로그를 색인하지 않거나 샘플링할 수 있습니다.

    제가 자주 쓰는 판단은 이렇습니다.

    • 2xx access log: 전체 요청 추세는 메트릭으로 보고, 로그는 샘플링합니다.
    • 4xx log: 로그인, 결제, API gateway는 보존 쪽에 무게를 둡니다. 정적 리소스 404는 샘플링 후보입니다.
    • 5xx log: 기본 보존입니다. 줄이고 싶다면 먼저 중복 메시지와 애플리케이션 재시도 폭주를 고칩니다.
    • DEBUG/TRACE: prod 기본 색인은 피합니다. 릴리스 관찰 기간에는 만료 시간을 두고 켭니다.
    • audit/security: 비용 최적화의 첫 대상이 아닙니다. 보관 기간과 접근 권한을 별도 Index로 관리합니다.
    로그 유형 추천 정책 쓰면 좋은 도구 피해야 할 접근
    Health check, readiness probe Agent에서 제외 exclude_at_match, DD_CONTAINER_EXCLUDE_LOGS 검색 UI에서만 숨기고 ingestion을 계속 두기
    정상 2xx access log 샘플링 또는 낮은 보관 기간 Index exclusion filter, log-based metric 모든 2xx를 장기 색인
    오류 5xx, panic, exception 보존 별도 Index, Error Tracking, alert 비용 급증 원인이라는 이유만으로 일괄 제외
    개발/스테이징 로그 수집 범위 제한, 짧은 보관 namespace 정책, env 태그, index routing prod와 같은 Index/retention 적용
    보안/감사 로그 별도 정책으로 보호 전용 Index, RBAC, retention 정책 일반 access log와 같은 exclusion filter 공유

    Index filter에서 특히 조심할 점은 순서입니다. 넓은 라우팅 규칙이 앞에 있으면 뒤의 세밀한 규칙은 기대처럼 작동하지 않을 수 있습니다. prod 오류 로그는 먼저 분리하고, 제외 규칙은 더 좁게 두는 편이 안전합니다.

    7. Estimated Usage Metrics로 변화 감시하기

    비용 최적화는 적용보다 검증이 더 중요합니다. 저는 변경 전후에 아래 메트릭을 대시보드에 올려 둡니다.

    datadog.estimated_usage.logs.ingested_bytes
    datadog.estimated_usage.logs.ingested_events
    datadog.estimated_usage.logs.truncated_count
    datadog.estimated_usage.containers
    datadog.estimated_usage.hosts
    datadog.estimated_usage.metrics.custom

    최근 Metric Name Pricing을 쓰는 조직은 datadog.estimated_usage.metrics.custom 대신 datadog.estimated_usage.metrics.points.ingested, datadog.estimated_usage.metrics.points.indexed, datadog.estimated_usage.billable.metrics 같은 메트릭을 확인해야 할 수 있습니다. 계약과 과금 모델에 따라 보이는 지표가 달라질 수 있으니 Plan & Usage 화면과 함께 검증하세요.

    로그 사용량 메트릭은 service, status, datadog_index, datadog_is_excluded 같은 태그와 함께 볼 수 있습니다. 이 태그들이 비어 있거나 N/A로 보이면 라우팅이나 태깅이 기대대로 되지 않는다는 신호일 수 있습니다.

    모니터는 절대값보다 변화율에 먼저 둡니다. 계약과 트래픽이 조직마다 달라서 “몇 GB 이상이면 문제” 같은 숫자를 박아 넣는 건 오히려 위험합니다. 대신 운영 이벤트와 연결해서 봅니다.

    • 배포 직후 특정 service의 로그 이벤트가 급증했는가?
    • 주말이나 야간에도 env:dev 로그가 계속 색인되는가?
    • datadog_is_excluded:false 비율이 갑자기 늘었는가?
    • status:debug가 prod에서 계속 증가하는가?
    • truncated_count가 늘어 긴 로그가 잘리고 있지는 않은가?
    예시 모니터 쿼리 방향
    sum:datadog.estimated_usage.logs.ingested_events{service:api,env:prod,status:debug}.as_count()
    
    예시 대시보드 분해 기준
    sum:datadog.estimated_usage.logs.ingested_bytes{*} by {service,env,datadog_index,datadog_is_excluded}

    Estimated Usage Metrics는 청구 금액 계산기가 아니라 조기 경보 장치로 쓰는 게 맞습니다. 최종 비용은 계약, 제품별 과금 기준, 보관 정책에 따라 달라지므로 숫자를 단정하지 마세요.

    Datadog 사용량 대시보드에서 비용 최적화 결과를 확인하는 화면

    전후 비교는 총량보다 service, env, team, datadog_index별 변화로 보는 쪽이 실무적입니다. 총량만 보면 트래픽 증가와 낭비 증가를 구분하기 어렵습니다.

    8. 재현 가능한 시나리오: DEBUG 로그가 prod 비용을 밀어 올릴 때

    실제로 자주 보는 장면입니다. 신규 릴리스 후 service:api에서 DEBUG 로그가 켜진 채로 prod에 올라갑니다. 장애는 없는데 로그 색인량만 계속 늘고, 개발팀은 “문제 생기면 보려고 켜둔 것”이라고 말합니다. 이때 바로 DEBUG를 전부 버리면 또 다른 문제가 생깁니다.

    1. Log Explorer에서 env:prod service:api status:debug로 검색합니다.
    2. 상위 message pattern을 확인합니다. 같은 메시지가 반복되면 코드 경로를 찾습니다.
    3. trace_id, request_id, user_id 같은 고카디널리티 필드가 불필요하게 facet이나 태그로 승격됐는지 봅니다.
    4. 릴리스 관찰 목적이면 종료 시각을 정하고, 그 이후에는 INFO 이상으로 되돌립니다.
    5. 즉시 비용 방어가 필요하면 Index exclusion filter로 DEBUG 색인을 줄이되, ERROR/WARN과 특정 릴리스 태그는 보존합니다.
    6. 사후에는 배포 파이프라인에 prod 로그 레벨 검증을 넣습니다.

    애플리케이션 쪽에서 막을 수 있다면 그게 제일 좋습니다. 예를 들어 Kubernetes 배포에 로그 레벨 환경 변수를 명시하고, prod에서 DEBUG가 들어가지 않게 리뷰 규칙을 둡니다.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: api
    spec:
      template:
        metadata:
          labels:
            app.kubernetes.io/version: "1.2.3"
        spec:
          containers:
            - name: api
              image: registry.example.com/api:stable
              env:
                - name: LOG_LEVEL
                  value: INFO
                - name: DD_SERVICE
                  value: api
                - name: DD_ENV
                  value: prod
                - name: DD_VERSION
                  valueFrom:
                    fieldRef:
                      fieldPath: metadata.labels['app.kubernetes.io/version']

    운영에서 “DEBUG는 무조건 나쁘다”는 식으로 접근하면 팀이 우회합니다. 제가 선호하는 정책은 기본은 INFO, DEBUG는 티켓과 만료 시간을 가진 예외입니다. 이거 진짜 편하더라고요. 비용도 줄고, 필요한 디버그 관찰도 정당하게 할 수 있습니다.

    9. 커스텀 메트릭과 태그 카디널리티 관리

    Datadog 비용 최적화에서 로그만 보고 끝내면 절반만 본 겁니다. 커스텀 메트릭은 태그 조합이 늘어날수록 관리가 어려워집니다. 특히 user_id, request_id, session_id, pod_uid 같은 값이 태그로 들어가면 카디널리티가 급격히 커질 수 있습니다.

    제가 보는 기준은 단호합니다. 집계해서 의사결정하지 않을 값은 메트릭 태그로 올리지 않습니다. 로그 필드로 남기는 것과 메트릭 태그로 승격하는 것은 비용과 쿼리 성능 면에서 다른 선택입니다.

    필드 메트릭 태그 적합성 이유 대안
    env 높음 집계와 알림 분리에 계속 사용됩니다. 공통 태그로 유지
    service 높음 소유권과 장애 범위를 나누는 기본 축입니다. APM, 로그, 메트릭 모두 동일 명칭 사용
    team 중간~높음 비용 귀속과 운영 책임에 유용합니다. 조직 개편 시 매핑 관리
    user_id 낮음 고카디널리티가 되기 쉽습니다. 로그 필드 또는 샘플링 이벤트로 유지
    request_id 낮음 거의 모든 요청마다 값이 달라집니다. trace/log correlation에 사용

    StatsD나 DogStatsD를 쓰는 서비스라면 코드 리뷰에서 태그 추가를 가볍게 보지 마세요. 새 태그 하나가 대시보드 필터를 편하게 만들 수도 있지만, 반대로 비용과 쿼리 성능을 계속 압박할 수도 있습니다.

    # 피하고 싶은 예: request_id가 태그로 들어감
    statsd.increment('checkout.payment_attempt', tags=[
        'env:prod',
        'service:checkout',
        f'request_id:{request_id}'
    ])
    
    # 더 나은 예: 집계 가능한 축만 태그로 사용
    statsd.increment('checkout.payment_attempt', tags=[
        'env:prod',
        'service:checkout',
        f'payment_method:{payment_method}',
        f'result:{result}'
    ])

    10. APM과 Trace: 샘플링을 비용 절감 버튼처럼만 보지 않기

    APM 비용이 부담될 때 흔한 반응은 “샘플링 낮추자”입니다. 그런데 trace는 로그보다 더 조심해야 합니다. 낮은 샘플링은 비용을 줄이지만, 희귀한 장애 경로와 긴 꼬리 지연을 놓칠 수 있습니다.

    제가 쓰는 선택 기준은 이렇습니다.

    • 트래픽은 많고 정상 경로가 반복적: 샘플링을 낮추고 RED 지표는 메트릭으로 봅니다.
    • 오류율은 낮지만 비즈니스 영향이 큼: 오류 trace와 특정 service/resource는 더 오래 보존합니다.
    • 릴리스 직후: 일정 시간 샘플링을 넓히고, 안정화 뒤 기본값으로 되돌립니다.
    • 비용 급증: span tag에 고카디널리티 값이 붙었는지, 새 instrumentation이 과도한 span을 만들었는지 먼저 봅니다.

    즉 APM 최적화의 핵심은 “적게 남기기”가 아니라 희귀하지만 중요한 경로를 보존하고, 반복적인 정상 경로를 얇게 보는 것입니다.

    11. 트러블슈팅: 최적화 뒤 관측성이 깨지는 대표 원인

    비용 최적화 후 “로그가 안 보여요”가 나오면 대부분 아래 원인 중 하나입니다. 겉으로는 비슷해 보여도 근본 원인이 다르므로 확인 순서를 정해두는 게 좋습니다.

    증상 가능한 원인 확인 방법 조치
    특정 Pod 로그가 전혀 안 보임 container exclude 규칙 또는 annotation 이름 불일치 agent configcheck, Agent 로그, Pod container name 확인 annotation의 컨테이너명과 실제 container name을 맞춥니다.
    로그는 들어오는데 검색이 안 됨 Index routing 또는 exclusion filter에 걸림 datadog_index, datadog_is_excluded 태그 확인 Index 순서와 필터 쿼리를 좁힙니다.
    오류 로그까지 줄어듦 Agent exclude 패턴이 너무 넓음 변경된 regex와 샘플 로그 비교 ERROR/WARN 예외를 먼저 분리하거나 Agent 제외 대신 Index 정책으로 옮깁니다.
    비용은 줄었는데 대시보드가 비어 보임 로그 기반 메트릭 또는 facet 의존성 누락 대시보드 쿼리의 데이터 소스 확인 로그를 줄이기 전 필요한 메트릭을 별도로 생성합니다.
    변경했는데 효과가 없음 Agent 재시작 누락, DaemonSet 미롤아웃, 다른 설정 경로 우선 rollout status, agent status 롤아웃과 적용된 최종 설정을 확인합니다.

    Agent 설정을 바꾼 뒤에는 아래 순서로 확인합니다.

    sudo systemctl restart datadog-agent
    sudo datadog-agent configcheck
    sudo datadog-agent status
    sudo journalctl -u datadog-agent --since '10 minutes ago' --no-pager

    Kubernetes라면 DaemonSet 롤아웃과 Agent Pod 로그를 같이 봅니다.

    kubectl -n datadog rollout status daemonset/datadog-agent
    kubectl -n datadog get pods -l app=datadog-agent -o wide
    kubectl -n datadog logs daemonset/datadog-agent --tail=200

    12. 운영 체크리스트: 한 번 줄이고 끝내지 않기

    Datadog 비용은 한 번 정리해도 다시 자랍니다. 새 서비스, 새 로그 필드, 새 대시보드, 새 tracer가 계속 들어오기 때문입니다. 그래서 저는 월 1회 또는 큰 릴리스 뒤에 아래 체크리스트를 돌립니다.

    • env, service, team 태그가 Usage Attribution에 충분히 반영되는가?
    • 지난 7일 또는 지난 릴리스 이후 사용량이 급증한 service가 있는가?
    • prod에서 DEBUG/TRACE 로그가 계속 색인되는가?
    • dev/staging 로그가 prod와 같은 보관 정책을 쓰고 있지 않은가?
    • Index exclusion filter 순서가 문서와 일치하는가?
    • 커스텀 메트릭 태그에 고카디널리티 값이 새로 들어오지 않았는가?
    • APM trace 샘플링이 중요한 오류 경로를 놓치지 않는가?
    • 비용 절감 후 대시보드, SLO, 알림이 정상 동작하는가?
    Datadog 비용 최적화 체크리스트 요약 인포그래픽

    체크리스트는 문서로만 두면 잘 안 봅니다. 저는 대시보드에 “이번 달 사용량 증가 Top service”와 “prod DEBUG 로그”를 같이 올려둡니다. 팀이 자기 사용량을 직접 보게 만드는 편이 중앙 플랫폼팀이 계속 말하는 것보다 훨씬 오래 갑니다.

    FAQ: Datadog 비용 최적화에서 자주 막히는 지점

    로그를 줄이면 장애 대응이 느려지지 않나요?

    무작정 줄이면 느려집니다. 그래서 error, warn, security, audit 로그는 먼저 지키고, health check, 반복 2xx access log, prod DEBUG 같은 후보부터 줄입니다. 필요한 신호를 메트릭으로 승격한 뒤 로그 색인을 줄이는 방식도 좋습니다.

    가장 먼저 손볼 곳은 어디인가요?

    대부분은 로그 색인 정책과 컨테이너 로그 수집 범위부터 보는 게 빠릅니다. 그다음 커스텀 메트릭 카디널리티, APM sampling과 retention을 봅니다. host 수를 줄이는 건 인프라 구조와 연결되어 있어 단기 비용 최적화 카드로는 조심스럽습니다.

    Agent에서 제외하는 것과 Index에서 제외하는 것 중 무엇이 더 좋나요?

    다시 볼 일이 없는 반복 로그는 Agent에서 제외하세요. 나중에 검색할 가능성이 있거나 운영 정책이 바뀔 수 있는 로그는 Datadog에 보낸 뒤 Index exclusion filter나 retention으로 다루는 편이 안전합니다.

    Usage Attribution이 팀별로 깔끔하게 안 나뉩니다. 왜 그런가요?

    계측 단계에서 태그가 빠졌거나, 제품별 사용량이 모든 태그 기준으로 완벽히 분해되지 않을 수 있습니다. 그래서 비용 보고서를 만들기 전에 공통 태그가 로그, 메트릭, trace, 컨테이너에 일관되게 들어가는지 먼저 확인해야 합니다.

    마무리: 줄일 데이터와 지킬 신호를 분리하세요

    Datadog 비용 최적화의 핵심은 “덜 보기”가 아니라 장애를 설명하는 신호만 더 선명하게 남기는 것입니다. 운영 환경이라면 Usage Attribution + 태그 표준화 + Log Index 필터를 먼저 잡으세요. 개발/스테이징 비용이 문제라면 Agent 수집 범위와 컨테이너 제외 규칙부터 손보는 게 빠릅니다.

    이럴 땐 이렇게 가면 됩니다. health check와 반복 정상 로그는 Agent에서 제외하세요. prod 오류, 보안, 감사 로그는 보존하세요. 2xx access log는 샘플링하거나 짧게 보관하세요. DEBUG 로그는 기본 비활성화하고, 필요할 때만 만료 시간을 두고 켜세요. 커스텀 메트릭에는 집계 가능한 태그만 올리세요.

    마지막으로 변경 전후를 꼭 같은 대시보드로 보세요. 감으로 줄였다고 말하지 말고, service, env, team, datadog_index별 사용량 변화로 확인하는 겁니다. 관련 글로는 로그 레벨 운영 정책, Kubernetes 관측성 태그 표준화, 클라우드 모니터링 비용 관리 글을 함께 연결하면 독자가 다음 단계로 이동하기 좋습니다.

  • [Cloud] New Relic 사용 후기: 1년 APM 운영하며 배운 성능 모니터링 실전 경험

    [Cloud] New Relic 사용 후기: 1년 APM 운영하며 배운 성능 모니터링 실전 경험

    New Relic 사용 후기: 1년 APM 운영하며 배운 성능 모니터링 실전 경험

    New Relic 사용 후기를 찾는 분들은 대개 비슷한 시점에 오시더라고요. 서비스가 어느 정도 커졌는데, 장애는 꼭 새벽에 터지고, CPU나 메모리만 봐서는 원인을 못 찾겠고, 개발팀이랑 인프라팀이 서로 “어디서 느린 거지?” 하고 로그만 뒤집는 상황 말입니다. 저도 13년차 인프라 엔지니어로 일하면서 이런 구간을 여러 번 겪었고, 실제로 지난 1년 동안 New Relic을 운영 환경에 붙여 보면서 APM(Application Performance Monitoring, 애플리케이션 성능 관리)이 왜 필요한지 몸으로 배웠거든요.

    처음엔 솔직히 “모니터링 툴이 다 거기서 거기 아닌가?” 싶었는데요. 실제로 써보니까 New Relic은 단순히 그래프 예쁘게 보여주는 도구라기보다, 문제를 좁혀 가는 순서 자체를 바꿔 주는 도구에 가깝더라고요. 이번 글에서는 화려한 성공담보다는, 제가 직접 해보니 좋았던 점과 불편했던 점, 그리고 삽질했던 포인트까지 같이 정리해보겠습니다.

    New Relic 사용 후기와 함께 보는 전체 서비스 모니터링 아키텍처 이미지

    애플리케이션, 데이터베이스, 외부 API, 사용자 요청 흐름 위에 New Relic이 어떻게 관측 지점을 만드는지 보여주는 개요 이미지입니다.

    1. APM이 필요했던 이유: 성능 모니터링의 빈칸

    예전에는 Node Exporter나 cAdvisor 같은 인프라 지표 위주로 많이 봤습니다. 물론 그것만으로도 기본 체력은 확인할 수 있죠. 그런데 실제 장애 대응에서는 그다음 질문이 꼭 나옵니다. “그래서 어느 요청이 느렸고, 어떤 쿼리가 문제였고, 외부 호출 중 어디서 시간이 새는 건데?” 여기서부터 일반적인 서버 모니터링과 애플리케이션 성능 관리가 갈립니다.

    쉽게 말해 인프라 모니터링은 서버가 아픈지를 보는 거고, APM은 서비스 요청이 어디서 아픈지를 보여주는 쪽입니다. CPU 40%인데 사용자는 느리다고 할 수 있거든요. 저도 처음엔 이 간극이 좀 답답했습니다. 특히 마이크로서비스처럼 서비스가 여러 개로 나뉘면, 한 군데만 봐서는 절대 안 보입니다.

    • 인프라 지표: CPU, 메모리, 디스크, 네트워크 중심
    • APM 및 성능 모니터링: 트랜잭션 응답 시간, 에러율, 외부 호출, DB 쿼리, 분산 추적 중심
    • 운영 관점 핵심: “서버 상태”보다 “사용자 경험”에 더 가깝게 본다는 점

    2. New Relic 사용 후기를 시작하기 전에: 핵심 개념

    New Relic은 애플리케이션 안에 에이전트(agent)를 심거나 연동해서 요청 흐름과 성능 데이터를 수집하고 분석하는 플랫폼입니다. 처음 접하면 메뉴가 많아서 조금 압도적이긴 한데요. 저도 처음엔 “이게 뭔가” 싶었는데 하루 이틀 만져보니 핵심은 의외로 단순했습니다.

    1. 애플리케이션에 에이전트를 붙입니다.
    2. 트래픽이 들어오면 트랜잭션 단위로 데이터를 수집합니다.
    3. 응답 시간, 에러, 외부 호출, 데이터베이스 구간을 나눠 보여줍니다.
    4. 이상 징후가 보이면 알림(alert)과 대시보드로 추적합니다.

    여기서 중요한 포인트! New Relic 사용 후기를 읽을 때 꼭 봐야 할 건 “기능이 많다”가 아니라, 문제 분석 시간이 실제로 줄었는가입니다. 저한테는 이게 가장 컸습니다. 예전에는 로그를 먼저 보고 추측했는데, New Relic을 붙인 뒤에는 느린 엔드포인트부터 보고 그다음 로그를 보는 순서로 바뀌었습니다.

    항목 인프라 모니터링 New Relic APM
    관점 서버/컨테이너 상태 요청과 코드 실행 흐름
    주요 질문 서버가 바쁜가? 왜 이 요청이 느린가?
    장애 대응 자원 병목 추정 문제 지점 구간화
    협업 효과 인프라팀 중심 개발팀-운영팀 공통 언어 제공

    3. 실전 적용: New Relic 도입 시작하기

    실전에서는 거창하게 시작하지 않는 게 중요합니다. 처음부터 모든 서비스에 다 붙이려 하면 운영팀이 먼저 지칩니다 ㅎㅎ 저는 트래픽이 많고 문의가 자주 들어오던 핵심 API부터 시작했습니다.

    3-1. 애플리케이션 연결 전 체크 포인트

    • 어떤 서비스가 가장 중요한지 우선순위를 정합니다.
    • 운영 환경 변수 관리 방식을 먼저 정리합니다.
    • 로그, 메트릭, 트레이스 중 무엇을 먼저 볼지 결정합니다.
    • 알림을 누구에게 어떤 채널로 보낼지 정합니다.

    3-2. Docker 환경에서 기본 연결 예시

    아래는 개념적으로 가장 많이 쓰는 방식입니다. 실제 변수명이나 연동 방식은 언어와 런타임에 따라 조금씩 다를 수 있으니, 운영 중인 스택에 맞춰 공식 문서를 같이 보시는 게 좋습니다.

    export NEW_RELIC_LICENSE_KEY="YOUR_LICENSE_KEY"
    export NEW_RELIC_APP_NAME="my-production-api"
    export NEW_RELIC_ENVIRONMENT="production"
    
    docker run -d \
      --name my-api \
      -e NEW_RELIC_LICENSE_KEY="$NEW_RELIC_LICENSE_KEY" \
      -e NEW_RELIC_APP_NAME="$NEW_RELIC_APP_NAME" \
      -e NEW_RELIC_ENVIRONMENT="$NEW_RELIC_ENVIRONMENT" \
      my-api-image:latest

    쿠버네티스(Kubernetes, 컨테이너 오케스트레이션) 환경이라면 보통 Secret과 Deployment에 나눠 넣게 됩니다.

    apiVersion: v1
    kind: Secret
    metadata:
      name: newrelic-secret
    type: Opaque
    stringData:
      NEW_RELIC_LICENSE_KEY: "YOUR_LICENSE_KEY"
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: my-api
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: my-api
      template:
        metadata:
          labels:
            app: my-api
        spec:
          containers:
            - name: my-api
              image: my-api:latest
              env:
                - name: NEW_RELIC_LICENSE_KEY
                  valueFrom:
                    secretKeyRef:
                      name: newrelic-secret
                      key: NEW_RELIC_LICENSE_KEY
                - name: NEW_RELIC_APP_NAME
                  value: "my-production-api"
                - name: NEW_RELIC_ENVIRONMENT
                  value: "production"

    이 단계에서 제가 느낀 건 하나였습니다. 성능 모니터링 도입 자체는 생각보다 어렵지 않은데, 이름 규칙과 태깅 전략을 대충 잡으면 나중에 대시보드가 금방 지저분해진다는 점입니다. 서비스명, 환경명, 팀 구분 태그는 초반에 깔끔하게 맞춰두는 게 좋습니다.

    컨테이너 기반 서비스에 New Relic 환경 변수와 에이전트가 연결되는 흐름을 보여주는 구성 다이어그램입니다.

    4. 실제로 가장 많이 본 화면: 성능 모니터링의 3대 지표

    New Relic을 1년 정도 쓰면서 가장 자주 본 건 화려한 종합 대시보드가 아니라, 결국 느린 트랜잭션 상세 화면이었습니다. 장애나 성능 저하가 오면 순서는 거의 비슷했습니다.

    1. 응답 시간이 튄 시간대를 확인합니다.
    2. 어떤 엔드포인트가 느렸는지 봅니다.
    3. DB(Database, 데이터베이스) 구간인지, 외부 API 호출인지 나눕니다.
    4. 필요하면 로그와 애플리케이션 코드로 내려갑니다.

    예를 들어 API 평균 응답 시간이 갑자기 늘었는데 CPU는 멀쩡한 경우가 있었거든요. 처음엔 애플리케이션 내부 로직 문제인 줄 알았습니다. 근데 실제로 써보니까 외부 결제 API 호출 구간이 길어지고 있더라고요. 만약 APM이 없었다면 앱 서버 스케일 아웃부터 했을 수도 있습니다. 그런 의미에서 New Relic은 문제 해결의 방향을 틀리지 않게 해주는 장치였습니다.

    이 부분이 바로 제가 말하고 싶은 New Relic 사용 후기의 핵심입니다. 대시보드가 예쁜 것보다, 장애 대응에서 잘못된 가설을 빨리 버리게 해주는 게 훨씬 중요합니다.

    5. ⚠️ 1년 쓰면서 겪은 성능 모니터링의 실제 어려움

    좋은 얘기만 하면 블로그 글이 너무 광고 같잖아요. 실제 운영에서는 분명히 아쉬운 점도 있었습니다. 저도 삽질 좀 했습니다 ㅎㅎ

    5-1. 데이터가 많아지면 처음엔 어디를 봐야 할지 헷갈립니다

    메뉴가 다양하고 기능도 넓어서, 초반에는 오히려 “뭘 봐야 하지?” 상태가 옵니다. 이건 도구의 문제라기보다 온보딩 문제에 가깝더라고요.

    해결법: 처음부터 모든 기능을 다 보지 말고 아래 4가지만 먼저 익히는 게 좋았습니다.

    • APM 서비스 목록
    • 트랜잭션 응답 시간
    • 에러율
    • 알림 조건(Alert Condition)

    5-2. 에이전트만 붙였다고 끝이 아닙니다

    간혹 “붙였는데 데이터가 생각보다 의미가 없다”는 경우가 있습니다. 이유는 보통 서비스명 혼선, 환경 태그 누락, 로그와 추적의 연결 부족이더라고요.

    kubectl get pods -n production
    kubectl describe deployment my-api -n production
    kubectl logs deploy/my-api -n production --tail=200

    이런 기본 점검을 통해 환경 변수가 빠졌는지, 배포가 꼬였는지 먼저 확인했습니다. 은근히 단순한 실수가 많습니다.

    5-3. 경고 임계치(alert threshold)를 너무 예민하게 잡으면 피로해집니다

    이건 정말 많이 겪었습니다. 처음엔 에러율이나 응답 시간을 민감하게 잡아야 잘 잡히는 줄 알았거든요. 근데 새벽에 의미 없는 알림이 반복되면 팀이 결국 무시하게 됩니다. 그러면 진짜 장애 때도 놓치게 되죠.

    해결법: 비즈니스 영향이 있는 지표부터 우선순위를 줬습니다. 예를 들면 핵심 API 응답 시간, 결제 실패율, 로그인 오류율처럼요.

    5-4. 로그만 믿던 습관을 버리는 데 시간이 걸렸습니다

    이건 도구보다 사람의 습관 문제였어요. 저도 처음엔 장애 나면 바로 로그부터 열었는데, 나중엔 APM에서 느린 구간을 먼저 확인한 뒤 로그를 보는 방식이 훨씬 빨랐습니다. 혹시 지금도 로그 검색부터 시작하고 계신다면, 이 순서 한번 바꿔보세요. 생각보다 체감이 큽니다.

    New Relic 사용 후기에서 다루는 응답 시간과 에러율 분석 대시보드 이미지

    트랜잭션 분석 화면에서 병목 구간과 에러 추세를 확인하는 모습을 시각화한 이미지입니다.

    6. 검증: 1년 New Relic 운영으로 실제 어떻게 바뀌었나

    수치를 지어내서 말하고 싶지는 않습니다. 다만 운영 체감은 분명했습니다. 가장 큰 변화는 문제 확인까지 걸리는 시간이 줄었다는 점이었습니다. 예전에는 느리다는 제보가 오면 서버 지표, 로드밸런서, 로그, DB를 순서 없이 왔다 갔다 했는데요. New Relic을 붙인 뒤에는 병목 후보를 먼저 좁힌 뒤 확인하는 흐름이 자리 잡았습니다.

    • 장애 대응 회의에서 추측성 발언이 줄었습니다.
    • 개발팀과 운영팀이 같은 화면을 보고 이야기하게 됐습니다.
    • “서버는 안 바쁜데 왜 느리지?” 같은 상황에서 방향을 빨리 잡았습니다.
    • 릴리스 직후 성능 변화도 이전보다 빨리 감지했습니다.

    특히 애플리케이션 성능 관리가 필요한 팀이라면, 배포 직후의 미묘한 성능 저하를 잡는 데 도움이 됩니다. 장애가 아니라서 그냥 지나칠 수 있는 수준의 지연도 추세로 보면 보이거든요. 이건 나중에 큰 장애를 막는 데 꽤 중요했습니다.

    # 배포 직후 기본 확인 루틴 예시
    kubectl rollout status deployment/my-api -n production
    kubectl top pods -n production
    kubectl logs deploy/my-api -n production --since=10m

    그리고 New Relic 화면에서 같은 시간대의 응답 시간과 에러율을 같이 보면, 배포 영향인지 외부 의존성 문제인지 감이 빨리 옵니다. 드디어 됐다! 싶은 순간이 이런 데서 나오더라고요.

    7. New Relic 도입이 잘 맞는 경우와 기대를 버려야 할 부분

    모든 도구가 그렇듯 New Relic도 만능은 아닙니다. 그래서 기대치를 현실적으로 잡는 게 중요합니다.

    잘 맞는 경우 주의할 점
    여러 서비스가 연결된 구조 단일 정적 서비스만 운영하면 체감이 작을 수 있음
    개발팀과 운영팀이 함께 장애 대응 팀 내 공통 해석 기준이 없으면 화면만 늘어남
    배포 후 성능 영향 확인이 중요 알림 설계를 대충 하면 노이즈가 많아짐
    DB, 외부 API 병목이 자주 발생 에이전트 연결만으로 모든 원인이 자동 설명되진 않음

    즉, New Relic 사용 후기를 한 줄로 요약하면 이렇습니다. 문제를 자동으로 해결해주진 않지만, 문제를 훨씬 빨리 이해하게 해줍니다. 이 차이가 운영에서는 꽤 큽니다.

    New Relic 사용 후기 기반의 도입 전후 문제 해결 흐름 비교 인포그래픽

    도입 전후의 장애 대응 방식, 협업 흐름, 분석 속도 차이를 한눈에 보여주는 비교 이미지입니다.

    8. 정리: APM과 성능 모니터링의 현실적 결론

    1년 정도 운영하면서 느낀 결론은 분명합니다. 성능 모니터링은 단순히 그래프를 쌓는 작업이 아니라, 장애 대응의 사고방식을 바꾸는 작업이었습니다. 저도 처음엔 기능이 많아서 약간 부담스러웠는데, 실제로 써보니까 핵심은 복잡하지 않았습니다. 중요한 서비스부터 작게 시작하고, 알림을 다듬고, 팀이 같은 지표를 보게 만드는 것. 결국 이 세 가지가 제일 중요하더라고요.

    혹시 지금 APM 도입을 고민 중이시라면, 처음부터 거창하게 가지 마세요. 가장 느리다고 의심되는 API 하나, 에러가 자주 나는 서비스 하나부터 붙여보시면 됩니다. 그리고 인프라 지표와 애플리케이션 지표를 분리해서 보지 말고 함께 보셔야 합니다. 그 순간부터 운영이 꽤 달라집니다.

    다음 글에서는 로그(Log, 애플리케이션 기록)와 트레이스(Trace, 요청 흐름 추적)를 같이 볼 때 어떤 식으로 운영 효율이 올라가는지 정리해보려고 합니다. 이전 글에서 다뤘던 Kubernetes 리소스 관찰 전략과도 연결되는 내용이라, 같이 보시면 더 이해가 잘 되실 겁니다.

    자주 묻는 질문

    • Q. New Relic은 인프라 모니터링만으로 대체 가능한가요?
      A. 어렵습니다. 인프라 지표는 서버 상태를, APM은 요청 흐름과 병목 지점을 보여주기 때문에 역할이 다릅니다.
    • Q. 성능 모니터링 도입 초반에 가장 중요한 설정은 뭔가요?
      A. 서비스 이름 규칙, 환경 구분, 핵심 알림 조건입니다. 이 세 가지가 엉키면 나중에 데이터 해석이 힘들어집니다.
    • Q. 개발팀 없이 운영팀만 써도 효과가 있나요?
      A. 있습니다. 다만 코드 레벨 원인 분석까지 빨리 가려면 개발팀과 같은 화면을 보며 협업하는 편이 훨씬 좋습니다.