일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- deploy
- scraping
- eks
- DevOps
- Monitoring
- CI
- helm
- Resource
- 크롤링
- Service Mesh
- CD
- 스크레이핑
- Crawling
- opentelemetry
- Grafana
- Prometheus
- Jenkins
- sonarqube
- Kubernetes
- ECR
- argocd
- 웹 취약점
- linkerd
- CI/CD
- GitLab
- gitlab ci
- 모의해킹
- 웹 해킹
- gitlab cd
- docker
- Today
- Total
ㅡ.ㅡ
[K8S] Opentelemetry 본문
OpenTracing
분산 시스템 및 마이크로서비스 아키텍처에서 애플리케이션 간 트레이싱을 구현하기 위한 벤더 중립적인 API와 도구의 표준으로 애플리케이션의 다양한 구성 요소에서 분산된 트랜잭션의 흐름을 추적하기 위한 추상화 계층을 제공하여 여러 서비스 간의 요청-응답 흐름을 따라가고, 각 단계에서 걸리는 시간을 측정하며, 이를 통해 성능 문제를 분석하고 최적화할 수 있다.
Trace
분산 시스템 전체에 걸쳐 이동하는 하나의 트랜잭션의 값으로 여러개의 Span으로 구성된다.
Span
trace의 논리적 실행 단위로 하나의 서비스의 작업을 의미하며 한 Span 내 작업을 처리하는 함수와 같은것들을 Child Span으로 구성된다.
- Operation Name : 실행되는 Span의 이름
- TimeStamp : Span의 시작과 종료되는 시간
- Tags : 트레이싱되는 정보를 필터링 하거나, 쿼리하기 위한 Key:Value 형태의 값
- Logs : 로그 메시지와, 디버깅 및 정보를 출력하는데 사용되는 Key:Value 형태의 값
- Context : 다음 서비스로의 네트워크 혹은 메시지 버스를 통해 전달하는 정보의 집합체로 Trace ID, SpaniD, Baggage(Key/Value 형태의 데이터 저장 공간)로 구성된다
HTTP Header(W3C/Trace Context)
Traceparent 헤더는 분산 추적을 위한 표준 방법으로 W3C에서 제안된 헤더로 HTTP, AMQP, gRPC 등 다양한 프로토콜에서 사용된다. trace에 대한 고유 ID 및 trace당 span에 대한 unique ID를 갖고 있어 클라이언트의 요청이 타 시스템을 경유 할때마다 Traceparent 헤더를 포함하여 전송하며 각 시스템에서는 Traceparent 헤더에 포함된 정보를 기반으로 request에 대한 trace를 생성한다.
Traceparent: {version}-{trace-id}-{span-id}-{trace-flags}
- version: 현재 버전 정보
- trace-id: 16진수 인코딩으로 된 고유 Trace ID입니다. 32자로 구성되어 있으며, 대소문자와 숫자로 이루어져 있습니다.
- span-id: 16진수 인코딩으로 된 고유 Span ID입니다. 16자로 구성되어 있으며, 대소문자와 숫자로 이루어져 있습니다.
- trace-flags: trace 활성화 관련 flag를 표시합니다
No Collector Pattern
이 패턴은 텔레메트리 신호(추적, 메트릭, 로그)를 백엔드로 직접 내보내는 OpenTelemetry SDK로 계측하는 애플리케이션으로 구성
장점
- 간편한 사용(특히 개발/테스트 환경에서)
- 작동하기 위해 추가로 움직이는 부품이 없음(프로덕션 환경)
단점
- 수집, 처리, 수집이 변경되면 코드를 변경해야 함
- 애플리케이션 코드와 백엔드 간의 강력한 결합
- 언어 구현당 내보내기의 수가 제한됨
Node.js
APP(package.json)
트레이스값 추출 및 전달에사용되는 모듈 추가
{
...
"dependencies": {
...
"@opentelemetry/auto-instrumentations-node": "^0.37",
"@opentelemetry/api": "^1.4"
}
}
Logging
TraceID관련 로깅 필드 추가
import * as winston from "winston";
import { format } from "winston";
const logger = winston.createLogger({
format: format.combine(
format.timestamp({ format: "YYYY-MM-DD HH:mm:ss.SSS" }),
format.printf(
({ level, message, timestamp, trace_id, trace_flags, span_id }) => {
const logData = {
timestamp,
level,
trace_id,
trace_flags,
span_id,
message,
};
return JSON.stringify(logData);
}
)
),
transports: [new winston.transports.Console()],
});
Helm(app)
앱 배포시 환경변수로 opentelemetry agent 활성화 및 설정값들 추가
extraEnv:
- name: OTEL_TRACES_EXPORTER
value: "otlp"
- name: OTEL_EXPORTER_OTLP_ENDPOINT
value: <Grafana Tempo>
- name: OTEL_NODE_RESOURCE_DETECTORS
value: "env,host,os"
- name: OTEL_SERVICE_NAME
value: "test-app"
- name: NODE_OPTIONS
value: "--require @opentelemetry/auto-instrumentations-node/register"
Java
Dockerfile
앱에서 트레이스값을 생성하고 전달하기위한 에이전트(https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases) 추가
COPY lib /home
COPY --from=builder /root/.gradle/caches ./gradle-caches
COPY --from=jar-layer application/dependencies .
COPY --from=jar-layer application/spring-boot-loader .
COPY --from=jar-layer application/snapshot-dependencies .
COPY --from=jar-layer application/application .
Logging
TraceID관련 로깅 필드 추가
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds">
<property name="LOG_PATTERN"
value="%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread, %X{traceId:-}, %X{spanId:-}] [%logger{0}:%line] - %msg%n"/>
helm(app)
앱 배포시 환경변수로 opentelemetry agent 활성화 및 설정값들 추가
extraEnv:
- name: JAVA_TOOL_OPTIONS
value: "-javaagent:/home/opentelemetry-javaagent.jar"
- name: OTEL_TRACES_EXPORTER
value: "otlp"
- name: OTEL_EXPORTER_OTLP_ENDPOINT
value: <Grafana Tempo>
- name: OTEL_SERVICE_NAME
value: "traceapp1"
- name: OTEL_EXPORTER_OTLP_PROTOCOL
value: "http/protobuf"
- name: OTEL_TRACES_SAMPLER
value: "traceidratio"
- name: OTEL_TRACES_SAMPLER_ARG
value: "0.3"
Agent Collector Deployment Pattern
애플리케이션과 함께 실행되는 수집기 인스턴스 또는 애플리케이션과 동일한 호스트(예: 사이드카 또는 데몬 세트)에서 텔레메트리 신호를 전송하는 기타 수집기(OTLP 내보내기 사용)로 구성된 애플리케이션(OpenTelemetry 프로토콜을 사용하는 OpenTelemetry SDK로 계측) 또는 애플리케이션과 함께 실행되는 수집기 인스턴스로 구성됩니다.
장점
- 간편한 시작
- 애플리케이션과 수집기 간의 명확한 1:1 매핑
단점
- 확장성(인력 및 부하 측면)
- 유연하지 않음
Opentelemetry-Operator
OpenTelemetry 프로젝트를 쿠버네티스(Kubernetes) 환경에서 CRD를 사용하여 OpenTelemetry의 구성 요소를 배포 및 관리하기 쉽게 설치 및 관리하는 도구이다.
OpenTelemetry 구성 요소
- OpenTelemetry Collector
- auto-instrumentation of the workloads using OpenTelemetry instrumentation libraries
Helm Install
helm install --namespace opentelemetry-operator-system \ opentelemetry-operator open-telemetry/opentelemetry-operator
Opentelemetry-Collector
application이 보낸 데이터를 수집(receivers)하고 가공(processors)하여 저장소로 내보내는(expporters) 역할로 수집과 저장의 라이브러리 간 결합도를 없애고 표준화된 API를 사용하기 때문에 수집을 위한 라이브러리와 저장을 위한 라이브러리 각각의 변경에 부담이 없어지게 된다.
배포 방식
DaemonSet, Sidecar, Deployment 모드 지원가능 하며 LB를 붙여 gateway 패턴으로도 사용할 수 있다
주요 구성 요소
Receivers
데이터를 수집하는 소스로 다양한 형식의 데이터를 수신할 수 있다.
receivers:
otlp:
protocols:
grpc:
http:
- OTLPReceiver
OpenTelemetry 프로토콜을 사용하여 데이터를 수신합니다. - JaegerReceiver
Jaeger 형식의 추적 데이터를 수신합니다. - PrometheusReceiver
Prometheus 메트릭 데이터를 수신합니다.
Processors
수신된 데이터에 대해 변환, 조작 또는 필터링을 수행한다.
BatchProcessor
데이터를 일정 기간동안 누적한 후, 한 번에 전송합니다.- timeout: 배치를 전송하기 전까지 대기하는 최대 시간
- send_batch_size: 한 번에 보낼 수 있는 스팬의 최대 개수
processors: batch: send_batch_size: 10000 # 한 번에 보낼 데이터의 최대 개수 timeout: 10s # 데이터를 기다리는 최대 시간 retry_on_failure: true #
MemoryLimiter
메모리 사용량을 조정하여 리소스 할당을 통제합니다.processors: memory_limiter: check_interval: 5s limit_mib: 4000 limit_percentage: 75 spike_limit_mib: 500 spike_limit_percentage: 15
- check_interval: 메모리 사용량을 확인하는 데 사용되는 간격
- limit_(mib/percentage) : 메모리 사용량의 최대 값
- spike_limit_(mib/percentage): 메모리 사용량이 급격하게 증가했을 때 허용되는 값
AttributeProcessor
추적 데이터의 속성을 추가, 업데이트, 복제, 삭제하는 작업을 처리합니다.- actions: 수행할 작업 목록 (add, update, delete 등)과 관련 있는 키-값 쌍
processors: attributes: actions: - key: environment value: production action: insert - key: db.statement action: delete - key: email action: hash # Data sources: traces span: name: to_attributes: rules: - ^\/api\/v1\/document\/(?P<documentId>.*)\/update$ from_attributes: [db.svc, operation] separator: '::'
ResourceProcessor
데이터를 애플리케이션에 연결된 리소스 속성으로 변환하여 동일한 시스템에서 받은 메트릭을 추적하는 것이 용이하게 합니다.
attributes: 측정한 리소스에 매핑될 속성 목록을 포함합니다.processors: resource: attributes: - key: cloud.zone value: zone-1 action: upsert - key: k8s.cluster.name from_attribute: k8s-cluster action: insert - key: redundant-attribute action: delete
Tail Sampling Processor
각 추적의 완전한 추적 정보가 수집된 후에 필터링을 적용하여 자식 span까지 제외 시킬 수 있다.tail_sampling: decision_wait: 30s policies: - name: disabled-healthckeck1 type: string_attribute string_attribute: key: http.route values: ['/health', '/metrics', '/healthcheck'] enabled_regex_matching: true invert_match: true # 매칭되지 않는것만 수집 - name: disabled-healthckeck3 type: string_attribute string_attribute: key: http.user_agent values: ['ELB-HealthChecker.*','kube-probe.*'] enabled_regex_matching: true invert_match: true
기타 프로세서 리스트
https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor
Exporters
수집한 데이터를 다른 시스템에 전달하는 역할을 합니다.
# Data sources: traces, metrics, logs
otlp:
endpoint: otelcol2:4317
tls:
cert_file: cert.pem
key_file: cert-key.pem
# Data sources: traces, metrics
otlphttp:
endpoint: https://example.com:4318
# Data sources: metrics
prometheus:
endpoint: prometheus:8889
namespace: default
- OTLPExporter
GRPC/OpenTelemetry 프로토콜을 사용하여 데이터를 다른 시스템으로 내보냅니다. - OTLPHttpExporter
- HTTP/OpenTelemetry 프로토콜을 사용하여 데이터를 다른 시스템으로 내보냅니다.
- JaegerExporter
Jaeger 형식의 추적 데이터를 다른 시스템으로 내보냅니다. - PrometheusExporter
Prometheus 메트릭 데이터를 다른 시스템으로 내보냅니다.
Connectors
한 파이프라인의 끝에서 수집된 데이터를 내보내는 exporter로 동작하고 다른 파이프라인의 시작점에서 데이터를 수신하는 receiver로 동작하여 두 파이프라인을 연결하는 역할을 합니다.
receivers:
foo:
exporters:
bar:
connectors:
count:
service:
pipelines:
traces:
receivers: [foo]
exporters: [count]
metrics:
receivers: [count]
exporters: [bar]
forward
입력된 데이터를 그대로 전달하는 기본 커넥터입니다connectors: forward:
count
주어진 조건에 따라 데이터(event)를 세는 작업을 수행하는 커넥터입니다.
spanevents : 이벤트에 대한 카운터 이름 및 설명, 그리고 조건들을 설정합니다connectors: count: spanevents: my.prod.event.count: description: The number of span events from my prod environment. conditions: - 'attributes["env"] == "prod"' - 'name == "prodevent"'
spanmetrics
분산 추적 데이터에서 히스토그램 값을 생성하여 메트릭으로 전환하는 커넥터입니다.connectors: spanmetrics: histogram: explicit: buckets: [100us, 1ms, 2ms, 6ms, 10ms, 100ms, 250ms] dimensions: - name: http.method default: GET - name: http.status_code dimensions_cache_size: 1000 aggregation_temporality: 'AGGREGATION_TEMPORALITY_CUMULATIVE'
- histogram: 히스토그램 유형과 버킷을 설정합니다.
- dimensions: 메트릭 데이터의 차원 및 기본값을 설정합니다.
- dimensions_cache_size: 캐시 크기를 프로세서에 설정합니다.
- aggregation_temporality: 데이터 집계의 시간 속성을 설정합니다.
servicegraph
서비스 간 관계를 모니터링하고 추적하는 워크플로를 표현하는 커넥터입니다.connectors: servicegraph: latency_histogram_buckets: [1, 2, 3, 4, 5] dimensions: - dimension-1 - dimension-2 store: ttl: 1s max_items: 10
- latency_histogram_buckets: 지연 시간 히스토그램의 버킷 값을 설정합니다.
- dimensions: 사용할 차원을 설정합니다.
- store: 저장 구성에 대한 TTL 및 최대 항목 수를 설정합니다.
Extensions
Collector의 기능을 확장하거나 도와주는 부가적인 서비스입니다.
extensions:
health_check:
pprof:
zpages:
memory_ballast:
size_mib: 512
- health_check
OpenTelemetry Collector의 상태를 확인하는 기능을 제공하며, 주로 로드 밸런서에서 사용됩니다. - pprof
Collector 프로세스의 Golang 프로파일링 데이터를 제공합니다.- endpoint: pprof 엔드포인트를 설정합니다(예: 127.0.0.1:5555)
- block_profile_fraction: 블록 프로파일 작성을 위한 세분화 정도를 설정합니다.
- zpages
특정 웹 페이지 내에 프로세스의 로그 및 메트릭 정보를 표시하는 서비스입니다.- endpoint: zpages 엔드포인트를 설정합니다(예: 127.0.0.1:5678)
- memory_ballast
Collector 프로세스의 메모리 사용량에 미리 할당된 블록을 추가하여 메모리 할당 및 해제(GC)와 관련한 오버헤드를 줄여 프로세스의 성능을 향상시키는 역할을 합니다.
service
Collector의 실행 및 구성을 관리하는 데 사용되는 구성 요소로 전반적인 동작 및 구성을 정의합니다.
service:
extensions:
- health_check
- pprof
- zpages
pipelines:
traces:
receivers: [otlp, zipkin]
processors: [batch, queued_retry]
exporters: [jaeger, otlp]
metrics:
receivers: [otlp, prometheus]
processors: [batch]
exporters: [prometheus, otlphttp]
- extensions
Collector의 부가적인 기능을 향상시키며, 추가 작업을 수행합니다. - pipelines
traces, metrics, 및 logs와 같은 데이터 유형에 대해 파이프라인을 정의하고, receivers, processors, 및 exporters 사이의 데이터 흐름을 구성합니다.
opentelemetry-collector(daemonset)
daemonset으로 배포하는 CRD
apiVersion: opentelemetry.io/v1alpha1
kind: OpenTelemetryCollector
metadata:
name: otel-daemonset
namespace: opentelemetry
spec:
mode: daemonset
config: |
receivers:
otlp:
protocols:
grpc:
http:
processors:
# 파일 시스템 스팬 드랍
filter/spans:
spans:
exclude:
match_type: regexp
span_names: ['.*fs.*']
# 헬스체크 스팬 드랍
tail_sampling:
decision_wait: 30s
policies:
- name: disabled-healthckeck
type: string_attribute
string_attribute:
key: http.route
values: ['/health', '/metrics', '/healthcheck']
enabled_regex_matching: true
invert_match: true
groupbytrace/custom:
wait_duration: 1s
num_traces: 5000
num_workers: 4
memory_limiter:
check_interval: 1s
limit_percentage: 75
spike_limit_percentage: 30
# 배치 및 그룹핑
batch:
send_batch_size: 512
send_batch_max_size: 1024
groupbyattrs:
keys:
- host.name
resource:
attributes:
- key: k8s.cluster.name
value: ${opentelemetryConfig.name}
action: insert
exporters:
otlphttp:
endpoint: <Grafana Tempo>
service:
telemetry:
logs:
level: "info"
pipelines:
traces:
receivers: [otlp]
processors: [memory_limiter, groupbytrace/custom, batch, groupbyattrs, filter/spans, tail_sampling, resource]
exporters: [otlphttp]
servicemonitor
opentelemetry-collector의 메트릭을 수집하는 Service-monitor
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: otel-collector-service-monitor
namespace: opentelemetry
spec:
selector:
matchLabels:
app.kubernetes.io/name: otel-daemonset-collector-monitoring
app.kubernetes.io/instance: opentelemetry.otel-daemonset
app.kubernetes.io/component: opentelemetry-collector
namespaceSelector:
matchNames:
- opentelemetry
endpoints:
- interval: 30s
port: monitoring
Opentelemetry-Instrumentation
init container를 통해 자동으로 에이전트를 실행시키는 CRD
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
name: ${eksenv}-otel-instrumentation-grpc
namespace: opentelemetry
spec:
exporter:
endpoint: <Opentelemetry-Collector>
propagators:
- tracecontext
- baggage
sampler:
type: parentbased_traceidratio
argument: '1'
java:
image: ghcr.io/open-telemetry/opentelemetry-operator/autoinstrumentation-java:1.30.0
env:
- name: OTEL_ENV
value: ${eksenv}
- name: OTEL_APP_NAME
valueFrom:
fieldRef:
fieldPath: metadata.labels['app.kubernetes.io/name']
- name: OTEL_SERVICE_NAME
value: $(OTEL_ENV)-$(OTEL_APP_NAME)
- name: OTEL_METRICS_EXPORTER
value: 'prometheus'
- name: OTEL_EXPORTER_PROMETHEUS_HOST
value: '0.0.0.0'
- name: OTEL_EXPORTER_PROMETHEUS_PORT
value: '9090'
- name: OTEL_LOGS_EXPORTER
value: 'none'
- name: OTEL_LOG_LEVEL
value: info
nodejs:
image: ghcr.io/open-telemetry/opentelemetry-operator/autoinstrumentation-nodejs:0.41.1
env:
- name: OTEL_ENV
value: ${eksenv}
- name: OTEL_APP_NAME
valueFrom:
fieldRef:
fieldPath: metadata.labels['app.kubernetes.io/name']
- name: OTEL_SERVICE_NAME
value: $(OTEL_ENV)-$(OTEL_APP_NAME)
- name: OTEL_METRICS_EXPORTER
value: 'prometheus'
- name: OTEL_EXPORTER_PROMETHEUS_HOST
value: '0.0.0.0'
- name: OTEL_EXPORTER_PROMETHEUS_PORT
value: '9090'
- name: OTEL_LOGS_EXPORTER
value: 'none'
- name: OTEL_LOG_LEVEL
value: info
propagators
서로 다른 시스템 간의 일관된 추적을 유지할 수 있게 컨텍스트 전파를 담당하며, 분산 추적에 사용되는 tracing headers와 관련된 정보를 전달합니다.
- B3: Zipkin과 호환되는 전파 형식이다.
- Baggage : 사용자 정의 데이터를 분산된 시스템 전반에 걸쳐 전달할 수 있게 해준다.
- Jaeger : B3 전파 형식을 기반으로 하며, Jaeger와 함께 사용될 때 사용한다.
- TraceContext : W3C Trace Context 표준을 준수하는 전파 형식이다.
sampler
추적 데이터를 샘플링하여 일부 데이터만 저장하거나 전송하는 역할을 담당한다.
- AlwaysOn
- AlwaysOff
- Parent
- TraceIdRatio
exporter
수집한 추적 데이터, 메트릭 데이터 또는 로그 데이터를 원격 시스템에 전송하는 역할을 담당한다.
Pod Trace 값 수집 활성화 설정(Annotation)
- 지원 종류
go, dotnet, java, nodejs, python, apacheHttp, ,nginx(디폴트 설정에는 있음) - CRD와 수집 대상이 동일 네임스페이스일 경우
instrumentation.opentelemetry.io/inject-<지원종류>: "true" - CRD와 수집 대상이 다른 네임스페이스일 경우
instrumentation.opentelemetry.io/inject-<지원종류>: "<CRD 네임스페이스/CRD이름>"
Reference
'Observabillity' 카테고리의 다른 글
[Tracing] Grafana Tempo (0) | 2023.12.20 |
---|---|
[Monitoring] JVM Exporter(Micrometer) (0) | 2022.01.20 |
[Monitoring] Prometheus-Stack (0) | 2021.10.31 |
[Logging] APP Logging/Fluentd&Fluentbit (0) | 2021.10.17 |
[K8S] Kubernetes Dashboard (0) | 2021.01.30 |