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 สามารถเก็บข้อมูลได้ทั้งหมด