Technology
ACME Protocol Post-mortem Analysis | SiamCafe Blog
2025-12-03· อ. บอม — SiamCafe.net· 10,527 คำ

New Relic One กับ Service Mesh ทำงานร่วมกันอย่างไร

New Relic One เป็น Observability Platform ที่รวม Metrics, Events, Logs และ Traces (MELT) ไว้ในที่เดียว รองรับการ monitor infrastructure, application performance และ distributed systems ผ่าน unified UI สามารถสร้าง custom dashboard, ตั้ง alert conditions และวิเคราะห์ข้อมูลด้วย NRQL (New Relic Query Language)

Service Mesh เช่น Istio, Linkerd หรือ Consul Connect เป็น infrastructure layer ที่จัดการ service-to-service communication บน Kubernetes โดยใช้ sidecar proxy (เช่น Envoy) ทำหน้าที่ load balancing, traffic management, mutual TLS encryption และ observability สำหรับทุก request ที่ผ่านระหว่าง services

การนำ New Relic One มาใช้ร่วมกับ Service Mesh จะได้ข้อมูล telemetry ที่ครบถ้วนทั้ง infrastructure metrics จาก Kubernetes nodes, service mesh metrics จาก Envoy proxy, application traces จาก APM agent และ logs จากทุก component ทำให้สามารถ troubleshoot ปัญหาได้ครบ stack ตั้งแต่ network layer จนถึง application layer

สถาปัตยกรรมของระบบประกอบด้วย New Relic Kubernetes Integration ที่เก็บ cluster metrics, Prometheus Remote Write ที่ส่ง Istio metrics ไปยัง New Relic, OpenTelemetry Collector ที่เก็บ traces และ Fluent Bit ที่ส่ง logs

ติดตั้ง New Relic Infrastructure Agent บน Kubernetes

ใช้ Helm Chart สำหรับติดตั้ง New Relic Kubernetes Integration แบบครบชุด

# เพิ่ม Helm Repository
helm repo add newrelic https://helm-charts.newrelic.com
helm repo update

# สร้าง namespace
kubectl create namespace newrelic

# ติดตั้ง New Relic Bundle (รวมทุก component)
helm install newrelic-bundle newrelic/nri-bundle \
  --namespace newrelic \
  --set global.licenseKey="YOUR_NEW_RELIC_LICENSE_KEY" \
  --set global.cluster="production-cluster" \
  --set newrelic-infrastructure.privileged=true \
  --set kube-state-metrics.enabled=true \
  --set kubeEvents.enabled=true \
  --set logging.enabled=true \
  --set prometheus.enabled=true \
  --set newrelic-pixie.enabled=false \
  --set newrelic-prometheus-agent.config.kubernetes.integrations_filter.enabled=false

# ตรวจสอบการติดตั้ง
kubectl get pods -n newrelic
# NAME                                          READY   STATUS
# newrelic-bundle-nri-bundle-xxx                 1/1     Running
# newrelic-bundle-kube-state-metrics-xxx         1/1     Running
# newrelic-bundle-nri-kube-events-xxx            1/1     Running
# newrelic-bundle-newrelic-logging-xxx           1/1     Running

# ตรวจสอบว่าข้อมูลส่งถึง New Relic
kubectl logs -n newrelic -l app.kubernetes.io/name=newrelic-infrastructure --tail=20
# Output: Integration health check from http OK

ตั้งค่า values.yaml สำหรับ production environment

# newrelic-values.yaml
global:
  licenseKey: "YOUR_LICENSE_KEY"
  cluster: "production-cluster"
  lowDataMode: false

newrelic-infrastructure:
  privileged: true
  resources:
    limits:
      memory: 300Mi
      cpu: 200m
    requests:
      memory: 150Mi
      cpu: 100m
  config:
    features:
      docker_enabled: false
    http_server_enabled: true
    passthrough_environment:
      - KUBERNETES_SERVICE_HOST
      - KUBERNETES_SERVICE_PORT

kube-state-metrics:
  enabled: true
  resources:
    limits:
      memory: 256Mi
      cpu: 100m

kubeEvents:
  enabled: true

logging:
  enabled: true
  fluentBit:
    config:
      inputs: |
        [INPUT]
            Name tail
            Tag kube.*
            Path /var/log/containers/*.log
            Parser cri
            Mem_Buf_Limit 5MB
            Skip_Long_Lines On
      filters: |
        [FILTER]
            Name kubernetes
            Match kube.*
            Merge_Log On
            Keep_Log Off
            K8S-Logging.Parser On
            K8S-Logging.Exclude On

prometheus:
  enabled: true
  config:
    scrape_configs:
      - job_name: istio-mesh
        kubernetes_sd_configs:
          - role: endpoints
            namespaces:
              names: ["istio-system"]
        relabel_configs:
          - source_labels: [__meta_kubernetes_service_name]
            regex: istio-telemetry
            action: keep

# ติดตั้งด้วย values file
# helm install newrelic-bundle newrelic/nri-bundle \
#   --namespace newrelic -f newrelic-values.yaml

ตั้งค่า Istio Telemetry Integration กับ New Relic

ตั้งค่า Prometheus Remote Write เพื่อส่ง Istio metrics ไปยัง New Relic โดยตรง

# prometheus-remote-write.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: prometheus-config
  namespace: istio-system
data:
  prometheus.yml: |
    global:
      scrape_interval: 15s
      evaluation_interval: 15s

    remote_write:
      - url: "https://metric-api.newrelic.com/prometheus/v1/write?prometheus_server=istio-mesh"
        authorization:
          credentials: "YOUR_NEW_RELIC_LICENSE_KEY"
        write_relabel_configs:
          - source_labels: [__name__]
            regex: "istio_requests_total|istio_request_duration_milliseconds.*|istio_tcp_.*|envoy_.*"
            action: keep

    scrape_configs:
      - job_name: envoy-stats
        metrics_path: /stats/prometheus
        kubernetes_sd_configs:
          - role: pod
        relabel_configs:
          - source_labels: [__meta_kubernetes_pod_container_port_name]
            regex: ".*-envoy-prom"
            action: keep
          - source_labels: [__meta_kubernetes_pod_name]
            target_label: pod_name
          - source_labels: [__meta_kubernetes_namespace]
            target_label: namespace

      - job_name: istio-mesh
        kubernetes_sd_configs:
          - role: endpoints
            namespaces:
              names: ["istio-system"]
        relabel_configs:
          - source_labels: [__meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
            action: keep
            regex: istio-telemetry;prometheus

      - job_name: istiod
        kubernetes_sd_configs:
          - role: endpoints
            namespaces:
              names: ["istio-system"]
        relabel_configs:
          - source_labels: [__meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
            action: keep
            regex: istiod;http-monitoring

ตั้งค่า OpenTelemetry Collector สำหรับเก็บ traces จาก Istio

# otel-collector.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: otel-collector-config
  namespace: istio-system
data:
  config.yaml: |
    receivers:
      otlp:
        protocols:
          grpc:
            endpoint: 0.0.0.0:4317
          http:
            endpoint: 0.0.0.0:4318
      zipkin:
        endpoint: 0.0.0.0:9411

    processors:
      batch:
        timeout: 5s
        send_batch_size: 1000
      memory_limiter:
        check_interval: 1s
        limit_mib: 512
        spike_limit_mib: 128
      attributes:
        actions:
          - key: environment
            value: production
            action: upsert
          - key: service.mesh
            value: istio
            action: upsert

    exporters:
      otlp:
        endpoint: "otlp.nr-data.net:4317"
        headers:
          api-key: "YOUR_NEW_RELIC_LICENSE_KEY"
        compression: gzip

    service:
      pipelines:
        traces:
          receivers: [otlp, zipkin]
          processors: [memory_limiter, batch, attributes]
          exporters: [otlp]
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: otel-collector
  namespace: istio-system
spec:
  replicas: 2
  selector:
    matchLabels:
      app: otel-collector
  template:
    metadata:
      labels:
        app: otel-collector
    spec:
      containers:
        - name: otel-collector
          image: otel/opentelemetry-collector-contrib:0.96.0
          args: ["--config=/etc/otel/config.yaml"]
          ports:
            - containerPort: 4317
            - containerPort: 4318
            - containerPort: 9411
          volumeMounts:
            - name: config
              mountPath: /etc/otel
          resources:
            requests:
              memory: 256Mi
              cpu: 200m
            limits:
              memory: 512Mi
              cpu: 500m
      volumes:
        - name: config
          configMap:
            name: otel-collector-config

สร้าง Dashboard สำหรับ Service Mesh Observability

ใช้ NRQL เพื่อสร้าง dashboard ที่แสดงข้อมูล Service Mesh ทั้งหมด

# NRQL Queries สำหรับ Service Mesh Dashboard

# 1. Request Rate per Service
SELECT rate(sum(istio_requests_total), 1 MINUTE) AS 'Requests/min'
FROM Metric
WHERE instrumentation.provider = 'prometheus'
FACET destination_service_name
SINCE 1 hour ago
TIMESERIES

# 2. P99 Latency per Service
SELECT percentile(istio_request_duration_milliseconds, 99) AS 'P99 Latency (ms)'
FROM Metric
WHERE instrumentation.provider = 'prometheus'
AND response_code = '200'
FACET destination_service_name
SINCE 1 hour ago
TIMESERIES

# 3. Error Rate per Service
SELECT (filter(count(*), WHERE response_code >= '500') / count(*)) * 100 AS 'Error Rate %'
FROM Metric
WHERE metricName = 'istio_requests_total'
FACET destination_service_name
SINCE 1 hour ago
TIMESERIES

# 4. Service Mesh Topology (Service Map)
SELECT count(*)
FROM Metric
WHERE metricName = 'istio_requests_total'
FACET source_workload, destination_workload
SINCE 30 minutes ago

# 5. mTLS Status
SELECT latest(istio_tcp_connections_opened_total) AS 'Connections'
FROM Metric
WHERE connection_security_policy = 'mutual_tls'
FACET destination_service_name
SINCE 1 hour ago

# 6. Envoy Proxy Resource Usage
SELECT average(envoy_server_memory_allocated) / 1e6 AS 'Memory (MB)',
       average(envoy_server_total_connections) AS 'Connections'
FROM Metric
FACET pod_name
SINCE 1 hour ago
TIMESERIES

สร้าง Dashboard ผ่าน NerdGraph API

# สร้าง Dashboard ด้วย NerdGraph API
curl -X POST 'https://api.newrelic.com/graphql' \
  -H 'Content-Type: application/json' \
  -H 'API-Key: YOUR_USER_API_KEY' \
  -d '{
    "query": "mutation { dashboardCreate(accountId: YOUR_ACCOUNT_ID, dashboard: { name: \"Service Mesh Overview\", permissions: PRIVATE, pages: [{ name: \"Mesh Traffic\", widgets: [{ title: \"Request Rate by Service\", layout: { column: 1, row: 1, width: 6, height: 3 }, visualization: { id: \"viz.line\" }, rawConfiguration: { nrqlQueries: [{ accountId: YOUR_ACCOUNT_ID, query: \"SELECT rate(sum(istio_requests_total), 1 MINUTE) FROM Metric FACET destination_service_name TIMESERIES SINCE 1 hour ago\" }] } }, { title: \"P99 Latency\", layout: { column: 7, row: 1, width: 6, height: 3 }, visualization: { id: \"viz.line\" }, rawConfiguration: { nrqlQueries: [{ accountId: YOUR_ACCOUNT_ID, query: \"SELECT percentile(istio_request_duration_milliseconds, 99) FROM Metric FACET destination_service_name TIMESERIES SINCE 1 hour ago\" }] } }] }] }) { entityResult { guid } } }"
  }'

ตั้งค่า Distributed Tracing ข้าม Service Mesh

Istio สามารถส่ง trace data ไปยัง New Relic ผ่าน OpenTelemetry Collector โดยตั้งค่า Istio MeshConfig

# istio-meshconfig.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  meshConfig:
    enableTracing: true
    defaultConfig:
      tracing:
        sampling: 100.0
        zipkin:
          address: otel-collector.istio-system:9411
        custom_tags:
          environment:
            literal:
              value: "production"
          cluster:
            literal:
              value: "prod-cluster-01"
    extensionProviders:
      - name: otel-tracing
        opentelemetry:
          service: otel-collector.istio-system.svc.cluster.local
          port: 4317

# Apply configuration
# istioctl install -f istio-meshconfig.yaml -y

# ตรวจสอบว่า tracing ทำงาน
kubectl exec -it deploy/productpage -c istio-proxy -- \
  curl -s localhost:15000/config_dump | \
  python3 -c "import sys, json; c=json.load(sys.stdin); print(json.dumps([x for x in c['configs'] if 'tracing' in str(x)], indent=2))"

NRQL สำหรับวิเคราะห์ Distributed Traces

# ดู Trace ที่ช้าที่สุด
SELECT * FROM Span
WHERE service.mesh = 'istio'
AND duration.ms > 1000
SINCE 1 hour ago
LIMIT 20

# วิเคราะห์ Trace โดยแยกตาม Service
SELECT average(duration.ms), percentile(duration.ms, 95, 99),
       count(*) AS 'Total Spans'
FROM Span
WHERE service.mesh = 'istio'
FACET service.name
SINCE 1 hour ago

# หา Bottleneck Service
SELECT average(duration.ms) AS 'Avg Duration'
FROM Span
WHERE service.mesh = 'istio'
AND span.kind = 'server'
FACET service.name
SINCE 1 hour ago
ORDER BY average(duration.ms) DESC

Alert Policies และ Anomaly Detection สำหรับ Mesh Traffic

ตั้งค่า Alert Conditions ที่ตรวจจับปัญหาใน Service Mesh อัตโนมัติ

# สร้าง Alert Policy ด้วย NerdGraph API
curl -X POST 'https://api.newrelic.com/graphql' \
  -H 'Content-Type: application/json' \
  -H 'API-Key: YOUR_USER_API_KEY' \
  -d '{
    "query": "mutation { alertsPolicyCreate(accountId: YOUR_ACCOUNT_ID, policy: { name: \"Service Mesh Alerts\", incidentPreference: PER_CONDITION }) { id name } }"
  }'

# สร้าง NRQL Alert Condition: High Error Rate
curl -X POST 'https://api.newrelic.com/graphql' \
  -H 'Content-Type: application/json' \
  -H 'API-Key: YOUR_USER_API_KEY' \
  -d '{
    "query": "mutation { alertsNrqlConditionStaticCreate(accountId: YOUR_ACCOUNT_ID, policyId: POLICY_ID, condition: { name: \"High Error Rate in Mesh\", enabled: true, nrql: { query: \"SELECT (filter(count(*), WHERE response_code >= chr(53)+chr(48)+chr(48)) / count(*)) * 100 FROM Metric WHERE metricName = chr(105)+chr(115)+chr(116)+chr(105)+chr(111)+chr(95)+chr(114)+chr(101)+chr(113)+chr(117)+chr(101)+chr(115)+chr(116)+chr(115)+chr(95)+chr(116)+chr(111)+chr(116)+chr(97)+chr(108) FACET destination_service_name\" }, terms: { threshold: 5, thresholdDuration: 300, thresholdOccurrences: ALL, operator: ABOVE, priority: CRITICAL }, signal: { aggregationWindow: 60, aggregationMethod: EVENT_FLOW, aggregationDelay: 120 }, expiration: { closeViolationsOnExpiration: true, expirationDuration: 600 } }) { id } }"
  }'

ตั้งค่า Anomaly Detection ด้วย New Relic Applied Intelligence

# terraform configuration สำหรับ New Relic Alerts
# main.tf
terraform {
  required_providers {
    newrelic = {
      source  = "newrelic/newrelic"
      version = "~> 3.0"
    }
  }
}

provider "newrelic" {
  account_id = var.newrelic_account_id
  api_key    = var.newrelic_api_key
  region     = "US"
}

resource "newrelic_alert_policy" "mesh_policy" {
  name                = "Service Mesh Critical Alerts"
  incident_preference = "PER_CONDITION_AND_TARGET"
}

resource "newrelic_nrql_alert_condition" "high_latency" {
  account_id                   = var.newrelic_account_id
  policy_id                    = newrelic_alert_policy.mesh_policy.id
  type                         = "static"
  name                         = "P99 Latency Above 2s"
  enabled                      = true
  violation_time_limit_seconds = 3600

  nrql {
    query = <<-NRQL
      SELECT percentile(istio_request_duration_milliseconds, 99)
      FROM Metric
      WHERE instrumentation.provider = 'prometheus'
      FACET destination_service_name
    NRQL
  }

  critical {
    operator              = "above"
    threshold             = 2000
    threshold_duration    = 300
    threshold_occurrences = "all"
  }

  warning {
    operator              = "above"
    threshold             = 1000
    threshold_duration    = 300
    threshold_occurrences = "all"
  }
}

resource "newrelic_nrql_alert_condition" "anomaly_requests" {
  account_id                   = var.newrelic_account_id
  policy_id                    = newrelic_alert_policy.mesh_policy.id
  type                         = "baseline"
  name                         = "Anomalous Request Rate"
  enabled                      = true
  violation_time_limit_seconds = 3600
  baseline_direction           = "upper_and_lower"

  nrql {
    query = <<-NRQL
      SELECT rate(sum(istio_requests_total), 1 MINUTE)
      FROM Metric
      FACET destination_service_name
    NRQL
  }

  critical {
    operator              = "above"
    threshold             = 3
    threshold_duration    = 300
    threshold_occurrences = "all"
  }
}

resource "newrelic_notification_channel" "slack" {
  name           = "mesh-alerts-slack"
  type           = "SLACK"
  destination_id = var.slack_destination_id
  product        = "IINT"

  property {
    key   = "channelId"
    value = var.slack_channel_id
  }
}

# terraform init && terraform apply

FAQ คำถามที่พบบ่อย

Q: New Relic กับ Datadog สำหรับ Service Mesh Monitoring ต่างกันอย่างไร?

A: New Relic ใช้ NRQL ที่มีความยืดหยุ่นสูงในการ query ข้อมูล มี NerdGraph API สำหรับ automation และมี pricing model แบบ per-user ส่วน Datadog มี built-in Service Mesh integration ที่ตั้งค่าง่ายกว่า แต่ pricing แบบ per-host อาจแพงกว่าสำหรับ cluster ขนาดใหญ่

Q: ใช้ Prometheus อย่างเดียวไม่พอหรือ ทำไมต้องมี New Relic?

A: Prometheus เก็บข้อมูลได้แค่ระยะสั้น (15-30 วัน) และต้องจัดการ storage เอง New Relic เก็บข้อมูลได้นานกว่า (13 เดือนสำหรับ metrics) ไม่ต้อง manage infrastructure และมีฟีเจอร์เพิ่มเติมเช่น Anomaly Detection, Distributed Tracing Correlation และ AI-powered Insights

Q: Sampling Rate ควรตั้งเท่าไหร่สำหรับ Production?

A: สำหรับ production ที่มี traffic สูง แนะนำ 1-10% สำหรับ traces เพื่อลดค่าใช้จ่ายและ overhead แต่สำหรับ metrics ควรเก็บ 100% เพราะ aggregated metrics ใช้ storage น้อยและให้ข้อมูลที่แม่นยำกว่า ใช้ tail-based sampling ใน OTel Collector เพื่อเก็บ traces ที่มี error หรือ latency สูงแบบ 100%

Q: New Relic รองรับ Service Mesh ตัวไหนบ้าง?

A: รองรับทุก Service Mesh หลักได้แก่ Istio, Linkerd, Consul Connect และ AWS App Mesh ผ่าน Prometheus Remote Write สำหรับ metrics และ OpenTelemetry สำหรับ traces ไม่ว่า mesh จะใช้ Envoy หรือ proxy ตัวอื่น New Relic สามารถเก็บข้อมูลได้ทั้งหมด

📖 บทความที่เกี่ยวข้อง

IS-IS Protocol Post-mortem Analysisอ่านบทความ → PlanetScale Vitess Post-mortem Analysisอ่านบทความ → Kotlin Ktor Post-mortem Analysisอ่านบทความ → Linux eBPF XDP Post-mortem Analysisอ่านบทความ → Linux Cgroups v2 Post-mortem Analysisอ่านบทความ →

📚 ดูบทความทั้งหมด →