OpenTelemetry в K8S

Описание

OpenTelemetry Operator позволяет:

  1. Создавать инстансы Collector в различных режимах.
  2. Создавать шаблон sidecar контейнера который будет запущен в тех подах на которые повесим нужную аннотацию.
  3. Создавать объекты instrumentation которые (при соответствующей аннотации) автоматически настроят код сервиса на работу с OTEL.

Установка

cert-manager

kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.2/cert-manager.yaml

OpenTelemetry Operator

kubectl apply -f https://github.com/open-telemetry/opentelemetry-operator/releases/latest/download/opentelemetry-operator.yaml 

Jaeger

Это лишь бэкенд для хранения метрик. Можно настроить любую другую систему

apiVersion: v1
kind: Namespace
metadata:
  name: opentelemetry
---
apiVersion: v1
kind: Service
metadata:
  name: jaeger-all-in-one
  namespace: opentelemetry
  labels:
    app: opentelemetry
    component: otel-collector
spec:
  ports:
    - port: 4317
      protocol: TCP
      targetPort: grpc
  selector:
    component: otel-collector
---
apiVersion: v1
kind: Service
metadata:
  name: jaeger-all-in-one-ui
  namespace: opentelemetry
  labels:
    app: opentelemetry
    component: otel-collector
spec:
  ports:
    - name: jaeger
      port: 16686
      protocol: TCP
      targetPort: 16686
  selector:
    component: otel-collector
  type: LoadBalancer
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: jaeger-all-in-one
  namespace: opentelemetry
  labels:
    app: opentelemetry
    component: otel-collector
spec:
  replicas: 1
  selector:
    matchLabels:
      app: opentelemetry
      component: otel-collector
  template:
    metadata:
      labels:
        app: opentelemetry
        component: otel-collector
    spec:
      containers:
        - image: jaegertracing/all-in-one:1.52
          name: jaeger
          ports:
            - containerPort: 16686
            - containerPort: 14268
            - containerPort: 14250
            - containerPort: 4317
              name: grpc

Otelcoll

Этот коллектор otel в текущем примере будет являться общим шлюзом получающим данные от sidecar контейнеров. Таким образом достаточно поменять лишь его настройки, а основную систему не трогать.

apiVersion: opentelemetry.io/v1alpha1
kind: OpenTelemetryCollector
metadata:
  name: otel-collector
  namespace: opentelemetry
  labels:
    app: opentelemetry
    component: otel-collector
spec:
  ports:
    - port: 4318
      name: "grpc"
  config: |
    receivers:
      otlp:
        protocols:
          grpc:
          http:
    exporters:
      otlp:
        endpoint: jaeger-all-in-one.opentelemetry.svc.cluster.local:4317
        tls:
          insecure: true
      logging:
    processors:
      batch:
      resource:
        attributes:
          - key: test.key
            value: "test-value"
            action: insert
    extensions:
      health_check:
      zpages:
        endpoint: :55679
    service:
      telemetry:
        logs:
          level: "debug"
      extensions: [zpages, health_check]
      pipelines:
        traces:
          receivers: [otlp]
          processors: [batch, resource]
          exporters: [logging, otlp]

SIdecar

Это в своём роде шаблон контейнера который будет запускаться внутри каждого пода имеющего соответствующую аннотацию.

apiVersion: opentelemetry.io/v1alpha1
kind: OpenTelemetryCollector
metadata:
  name: sidecar
spec:
  mode: sidecar
  config: |
    receivers:
      otlp:
        protocols:
          grpc:
          http:
    processors:
      batch:
    exporters:
      logging:
      otlp:
        endpoint: "http://otel-collector-collector.opentelemetry.svc.cluster.local:4317"
        tls:
          insecure: true
    service:
      telemetry:
        logs:
          level: "debug"
      pipelines:
        traces:
          receivers: [otlp]
          processors: []
          exporters: [logging, otlp]

Instrumentation

Ресурс k8s, что определяет настройки otel которые будут вставлены в запущенный сервис. Иными словами например Инициализация OTEL в Golang не требуется. Достаточно создать такой объект и повесить нужные аннотации.

apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
  name: demo-instrumentation
spec:
  propagators:
    - tracecontext
    - baggage
  sampler:
    type: parentbased_traceidratio
    argument: "1"

Аннотации сервиса

  • sidecar.opentelemetry.io/inject: "sidecar" - подключит в pod sidecar.
  • instrumentation.opentelemetry.io/inject-java: "true" - подключит код внутрь запущенного сервиса. На Golang у меня не завелось.

Deployment целиком

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: rules-generator
  labels:
    app: rules-generator
spec:
  replicas: 1
  selector:
    matchLabels:
      app: rules-generator
  template:
    metadata:
      labels:
        app: rules-generator
      annotations:
        sidecar.opentelemetry.io/inject: "sidecar"
        instrumentation.opentelemetry.io/inject-java: "true"
    spec:
      containers:
        - name: rules-generator
          image: maksim77/rules:0.0.1
          ports:
            - containerPort: 12346
            - containerPort: 9999
---
apiVersion: v1
kind: Service
metadata:
  name: rules-generator-service
  labels:
    app: rules-generator
spec:
  selector:
    app: rules-generator
  type: NodePort
  ports:
    - protocol: TCP
      port: 9999
      targetPort: 9999