美文网首页
在 Kubernetes 中无侵入安装 OpenTelemetr

在 Kubernetes 中无侵入安装 OpenTelemetr

作者: 云原生指北 | 来源:发表于2023-12-12 09:46 被阅读0次

    背景

    OpenTelemetry 探针

    OpenTelemetry(简称 Otel,最新的版本是 1.27) 是一个用于观察性的开源项目,提供了一套工具、APIs 和 SDKs,用于收集、处理和导出遥测数据(如指标、日志和追踪信息)。应用程序遥测数据(如追踪、指标和日志)的收集是通过探针来完成的,探针通常以库的形式集成到应用程序中,自动捕获重要信息协助监控和调试。OpenTelemetry 探针支持市面上大多数的编程语言,探针的安装(通常被称为插桩,Instrumentation)分为手动和自动两种方式。

    • 手动插桩:指开发者直接在其应用程序代码中显式地添加遥测数据收集的代码,需要手动完成 SDK 初始化、插入追踪点、添加上下文信息等一系列操作。
    • 自动插桩:利用 OpenTelemetry 提供的库自动捕获应用程序的遥测数据,无需或只需很少的代码更改。比如,Java 通过 javaagent 实现探针的自动安装

    二者各有优劣:手动插桩适用于需要高度定制和精确控制遥测数据收集的场景;自动插桩适合快速启动和简化集成,特别是在使用标准框架和库的应用程序中。

    OpenTelemetry Operator 介绍

    OpenTelemetry Operator 是一个为了简化 OpenTelemetry 组件在 Kubernetes 环境中的部署和管理而设计的 Kubernetes Operator。

    OpenTelemetry Operator 通过 CRD(OpenTelemetryCollectorInstrumentationOpAMPBridge) 实现在 Kubernetes 集群中自动部署和管理 OpenTelemetry Collector;在工作负载中自动安装 OpenTelemetry 探针。

    今天我们就将体验如何使用 OpenTelemetry Operator 自动安装探针,实现链路跟踪。

    演示

    架构

    这是演示的架构,Otel 提供了 多种语言的 instrumentation SDK,这篇文章中我们将使用 Java 和 Go 两种语言的应用。这两种语言会使用全自动和半自动的注入安装:

    • Java 全自动注入安装,Otel Operator 通过使用 init container 引入 sdk ,并通过 JAVA_TOOL_OPTIONS 来指定 javaagent 来插桩。这里将使用 pinakispecial/spring-boot-rest 镜像来运行一个简单的 Spring Boot REST 服务。
    • Go 半自动注入安装,为什么是半自动?Go 的全自动是通过 eBPF 的方式实现的:在 Pod 注入独立的容器,加载 BPF 程序。但是 eBPF 的实现对内核要求十分苛刻 5.4 - 5.14。这里演示半自动的方式:手动引入 Go instrumentation SDK自动注入配置

    Jaeger

    为了便于演示这里使用 jaegertracing/all-in-one 镜像来部署 Jaeger,这个镜像包含了 Jaeger 收集器、内存存储、查询服务和 UI 等组件,非常适合开发和测试使用。

    通过环境变量 COLLECTOR_OTLP_ENABLED 启动对 OTLP(OpenTelemetry Protocol) 的支持。

    kubectl apply -f - <<EOF
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: jaeger
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: jaeger
      template:
        metadata:
          labels:
            app: jaeger
        spec:
          containers:
          - name: jaeger
            image: jaegertracing/all-in-one:latest
            env:
            - name: COLLECTOR_OTLP_ENABLED
              value: "true"
            ports:
            - containerPort: 16686
            - containerPort: 14268
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: jaeger
    spec:
      selector:
        app: jaeger
      type: ClusterIP
      ports:
        - name: ui
          port: 16686
          targetPort: 16686
        - name: collector
          port: 14268
          targetPort: 14268
        - name: http
          protocol: TCP
          port: 4318
          targetPort: 4318
        - name: grpc
          protocol: TCP
          port: 4317
          targetPort: 4317      
    EOF
    

    安装 cert-manager

    Otel Operator 依赖 cert-manager 进行证书的管理,安装 operator 之前需要安装 cert-manager。

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

    安装 OpenTelemetry Operator

    执行下面命令安装 Otel Operator

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

    配置 OpenTelemetry Collector

    通过创建 CR OpenTelemetryCollector 来配置 Otel 的采集器,这里我们配置了:

    • otel 接收器:支持 grpc(端口 4317)和 http(端口 4318
    • memory_limiterbatch 处理器,但是为了方便快速查看数据,这两个并没有启用,仅作展示用。
    • debugotlp/jaeger 的输出器,分别用于在标准输出中打印信息和使用 otlp 协议输出到 Jaeger。
    • pipeline 服务,用于配置跟踪数据的处理流程:接收、处理和输出。
    kubectl apply -f - <<EOF
    apiVersion: opentelemetry.io/v1alpha1
    kind: OpenTelemetryCollector
    metadata:
      name: otel
    spec:
      config: |
        receivers:
          otlp:
            protocols:
              grpc:
              http:
        processors:
          memory_limiter:
            check_interval: 1s
            limit_percentage: 75
            spike_limit_percentage: 15
          batch:
            send_batch_size: 10000
            timeout: 10s
    
        exporters:
          debug:
          otlp/jaeger:
            endpoint: "jaeger.default:4317"
            tls:
              insecure: true
    
        service:
          pipelines:
            traces:
              receivers: [otlp]
              processors: []
              exporters: [debug,otlp/jaeger]
    EOF
    

    创建 CR OpenTelemetryCollector 后,Otel Operator 会创建一个 deployment 和 多个 service。

    kubectl get deployment,service -l app.kubernetes.io/component=opentelemetry-collector
    NAME                             READY   UP-TO-DATE   AVAILABLE   AGE
    deployment.apps/otel-collector   1/1     1            1           12h
    
    NAME                                TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                               AGE
    service/otel-collector              ClusterIP   10.43.152.81    <none>        4317/TCP,4318/TCP,8889/TCP,9411/TCP   12h
    service/otel-collector-headless     ClusterIP   None            <none>        4317/TCP,4318/TCP,8889/TCP,9411/TCP   12h
    service/otel-collector-monitoring   ClusterIP   10.43.115.103   <none>        8888/TCP                              12h
    

    Collector 部署的四种部署模型 Deployment、DaemonSet、StatefulSet、Sidecar,默认为 Deployment。

    配置 Instrumentation

    Instrumentation 是 Otel Operator 的另一个 CRD,用于自动安装 Otel 探针和配置:

    • propagators 用于配置跟踪信息在上下文的传递方式。
    • sampler 采样器
    • env[language].env 添加到容器的环境变量

    更多配置说明,请参考 Instrumentation API 文档

    kubectl apply -f - <<EOF
    apiVersion: opentelemetry.io/v1alpha1
    kind: Instrumentation
    metadata:
      name: instrumentation-sample
    spec:
      propagators:
        - tracecontext
        - baggage
        - b3
      sampler:
        type: parentbased_traceidratio
        argument: "1"
      env:
        - name: OTEL_EXPORTER_OTLP_ENDPOINT
          value: otel-collector.default:4318
      java:    
        env:
          - name: OTEL_EXPORTER_OTLP_ENDPOINT
            value: http://otel-collector.default:4317   
    EOF
    

    Java 示例应用

    为 Pod 添加注解 instrumentation.opentelemetry.io/inject-java: "true" 通知 Otel Operator 该应用的类型以便注入正确的探针。

    kubectl apply -f - <<EOF
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: java-sample
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: java-sample
      template:
        metadata:
          labels:
            app: java-sample
          annotations:
            instrumentation.opentelemetry.io/inject-java: "true"
        spec:
          containers:
          - name: java-sample
            image: pinakispecial/spring-boot-rest
            ports:
            - containerPort: 8080
    EOF
    

    可以看到 Otel Operator 向 Pod 中注入了一个 otel 的初始化容器。

    以及在 java 容器中注入了一系列的环境变量进行配置。

    Go 示例应用

    前面提到 Go 语言的自动注入演示使用半自动的方式,与本文的标题不符,属于嵌入式的。我写了一个 简单的 Go 应用,使用手动的方式来安装 Otel 探针,有兴趣的可以查看源码。

    kubectl apply -f https://raw.githubusercontent.com/addozhang/http-sample/main/manifests/service-v1.yaml
    

    查看 Pod 同样可以看到通过环境变量的方式注入的 Otel 配置。

    测试

    pod_name="$(kubectl get pod -n default -l app=service-a -o jsonpath='{.items[0].metadata.name}')"
    kubectl port-forward $pod_name 8080:8080 &
    
    curl localhost:8080
    service-a(version: v1, ip: 10.42.0.68, hostname: service-a-5bf98748f5-l9pjw) -> service-b(version: v1, ip: 10.42.0.70, hostname: service-b-676c56fb98-rjbwv) -> service-c(version: v1, ip: 10.42.0.69, hostname: service-c-79985dc75d-bh68k)
    

    发送请求后,打开 Jaeger UI。

    jaeger_pod="$(kubectl get pod -l app=jaeger -o jsonpath='{.items[0].metadata.name}')"
    kubectl port-forward $jaeger_pod 16686:16686 &
    

    Bingo!

    访问 Jaeger UI 就可以看到这个访问的链路信息了。

    相关文章

      网友评论

          本文标题:在 Kubernetes 中无侵入安装 OpenTelemetr

          本文链接:https://www.haomeiwen.com/subject/vsrvgdtx.html