现在支持通过 EDOT Collector 在 Kubernetes 上动态发现工作负载

2025年4月7日   |   by mebius

作者:来自 ElasticChristos MarkouAlexander Wert

%title插图%num

了解 Elastic 的 OpenTelemetry Collector 如何利用 Kubernetes pod 注解提供动态工作负载发现,并改善 Kubernetes 集群的自动化指标和日志收集。

在 Elastic,我们专注于 Kubernetes 作为最重要的可观察性用例之一。我们希望提供基于现实世界 GitOps 最佳实践的最佳入门体验和生命周期管理。

最近,OpenTelemetry 发布了一篇博客,介绍了如何基于 Kubernetes Pods 的 annotations 进行自动发现,使用 OpenTelemetry Collector。

在这篇博客中,我们将讨论如何使用 OpenTelemetry Collector 的这个与 Kubernetes 相关的功能,这个功能已经包含在 Elastic 发行版的 OpenTelemetry (EDOT) Collector 中。

除了这个功能外,在 Elastic,我们在大力投资于将 OpenTelemetry 打造成最佳、标准化的可观察性数据采集解决方案。你可能已经看到我们专注于:

让我们带你通过使用 EDOT Collector 的实操旅程,涵盖你在现实世界中可能遇到的各种用例,突出这个强大功能的能力。

配置 EDOT Collector

这里我们不会过多关注 Collector 的配置,因为根据这个功能的性质,它是最小化的,让工作负载定义如何进行监控。

为了说明这一点,下面是启用日志和指标功能的 Collector 配置片段:

receivers:
    receiver_creator/metrics:
      watch_observers: [k8s_observer]
      discovery:
        enabled: true
      receivers:

    receiver_creator/logs:
      watch_observers: [k8s_observer]
      discovery:
        enabled: true
      receivers:

你可以将上述内容包含在 EDOT Collector 的配置中,特别是在 receivers 部分

由于我们示例中的日志收集将通过发现功能进行,请确保删除静态 filelog 接收器的配置块,并禁用其预设(即设置为 false),以避免日志重复。

确保 k8sobsetgcoderver 已启用,并作为扩展的一部分:

extensions:
  k8s_observer:
    observe_nodes: true
    observe_services: true
    observe_ingresses: true

// ...

service:
  extensions: [k8s_observer]

最后但同样重要的是,确保日志文件的卷正确挂载:

volumeMounts:
 - name: varlogpods
   mountPath: /var/log/pods
   readOnly: true

volumes:
  - name: varlogpods
    hostPath:
      path: /var/log/pods

一旦配置准备就绪,请按照 Kubernetes 快速入门指南部署 EDOT Collector。确保用包含上述修改的文件替换快速入门指南中链接的 values.yaml 文件。

基于注解从移动目标收集指标

在这个示例中,我们有一个包含两个不同容器的 Pod 规范的 Deployment。其中一个容器运行 Redis 服务器,另一个运行 NGINX 服务器。因此,我们希望为这两个目标容器提供不同的提示。

基于注解的发现功能支持这一点,允许我们为每个暴露的容器端口指定指标注解。

以下是完整的规范文件示例:

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-conf
data:
  nginx.conf: |
    user  nginx;
    worker_processes  1;
    ertgcoderor_log  /dev/stderr warn;
    pid        /var/run/nginx.pid;
    events {
      worker_connections  1024;
    }
    http {
      include       /etc/nginx/mime.types;
      default_type  application/octet-stream;

      log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                        '$status $body_bytes_sent "$http_referer" '
                        '"$http_user_agent" "$http_x_forwarded_for"';
      access_log  /dev/stdout main;
      server {
          listen 80;
          server_name localhost;

          location /nginx_status {
              stub_status on;
          }
      }
      include /etc/nginx/conf.d/*;
    }
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-deployment
  labels:
    app: redis
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
      annotations:
        # redis container port hints
        io.opentelemetry.discovery.metrics.6379/enabled: "true"
        io.opentelemetry.discovery.metrics.6379/scraper: redis
        io.opentelemetry.discovery.metrics.6379/config: |
          collection_interval: "20s"
          timeout: "10s"

        # nginx container port hints
        io.opentelemetry.discovery.metrics.80/enabled: "true"
        io.opentelemetry.discovery.metrics.80/scraper: nginx
        io.opentelemetry.discovery.metrics.80/config: |
          endpoint: "http://`endpoint`/nginx_status"
          collection_interval: "30s"
          timeout: "20s"
    spec:
      volumes:
      - name: nginx-conf
        configMap:
          name: nginx-conf
          items:
            - key: nginx.conf
              path: nginx.conf
      containers:
        - name: webserver
          image: nginx:latest
          ports:
            - containerPort: 80
              name: webserver
          volumeMounts:
            - mountPath: /etc/nginx/nginx.conf
              readOnly: true
              subPath: nginx.conf
              name: nginx-conf
        - image: redis
          imagePullPolicy: IfNotPresent
          name: redis
          ports:
            - name: redis
              containerPort: 6379
              protocol: TCP

当这个工作负载部署后,Collector 会自动发现它并识别特定的注解。之后,两个不同的接收器将启动,每个接收器负责各自的目标容器。

从多个目标容器收集日志

基于注解的发现功能还支持根据提供的注解收集日志。在下面的示例中,我们再次有一个包含两个不同容器的 Pod 的 Deployment,其中我们希望应用不同的日志收集配置。我们可以为每个容器名称指定作用域的注解:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: busybox-logs-deployment
  labels:
    app: busybox
spec:
  replicas: 1
  selector:
    matchLabels:
      app: busybox
  template:
    metadata:
      labels:
        app: busybox
      annotations:
        io.opentelemetry.discovery.logs.lazybox/enabled: "true"
        io.opentelemetry.discovery.logs.lazybox/config: |
          operators:
            - id: container-parser
              type: container
            - id: some
              type: add
              field: attributes.tag
              value: hints-lazybox
        io.opentelemetry.discovery.logs.busybox/enabled: "true"
        io.opentelemetry.discovery.logs.busybox/config: |
          operators:
            - id: container-parser
              type: container
            - id: some
              type: add
              field: attributes.tag
              value: hints-busybox
    spec:
      containers:
        - name: busybox
          image: busybox
          args:
            - /bin/sh
            - -c
            - while true; do echo "otel logs from busybox at $(date +%H:%M:%S)" && sleep 5s; done
        - name: lazybox
          image: busybox
          args:
            - /bin/sh
            - -c
            - while true; do echo "otel logs from lazybox at $(date +%H:%M:%S)" && sleep 25s; done

上述配置启用了两个不同的 filelog 接收器实例,每个实例应用一个独特的解析配置。当我们知道如何解析特定技术日志时,例如 Apache 服务器访问日志,这非常有用。

同时收集指标和日志

在我们的第三个示例中,我们展示了如何在同一个工作负载上定义指标和日志注解。这使我们能够从发现的工作负载中收集这两种信号。以下是一个包含 Redis 服务器和一个执行虚拟日志写入的 BusyBox 容器的 Pod 的 Deployment。我们可以将注解定向到端口和容器级别,从 Redis 服务器收集指标(使用 Redis 接收器),并从 BusyBox 收集日志(使用 filelog 接收器)。以下是配置方法:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-deployment
  labels:
    app: redis
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
      annotations:
        io.opentelemetry.discovery.metrics.6379/enabled: "true"
        io.opentelemetry.discovery.metrics.6379/scraper: redis
        io.opentelemetry.discovery.metrics.6379/config: |
          collection_interval: "20s"
          timeout: "10s"

        io.opentelemetry.discovery.logs.busybox/enabled: "true"
        io.opentelemetry.discovery.logs.busybox/config: |
          operators:
            - id: container-parser
              type: container
            - id: some
              type: add
              field: attributes.tag
              value: hints
    spec:
      containers:
        - image: redis
          imagePullPolicy: IfNotPresent
          name: redis
          ports:
            - name: redis
              containerPort: 6379
              protocol: TCP
        - name: busybox
          image: busybox
          args:
            - /bin/sh
            - -c
            - while true; do echo "otel logs at $(date +%H:%M:%S)" && sleep 15s; done

在 Elastic 中探索和分析来自动态目标的数据

一旦目标 Pods 被发现并且 Collector 开始从它们收集遥测数据,我们就可以在 Elastic 中探索这些数据。在 Discover 中,我们可以搜索 Redis 和 NGINX 的指标,以及从 BusyBox 容器收集的日志。以下是展示的样子:

%title插图%num

%title插图%num

总结

以上示例展示了我们的 OpenTelemetry Collector 用户如何利用这个新功能 —— 我们在开发过程中发挥了重要作用。

为此,我们借鉴了在 MetricbeatFilebeatElastic-Agent 中已支持的类似功能的多年经验。这让我们非常高兴和自信,因为它弥合了 Elastic 特定监控代理和 OpenTelemetry Collector 之间的功能差距 —— 让它变得更好。

想了解更多吗?访问文档,并通过我们的 EDOT 快速入门指南tgcode尝试一下。

原文:Dynamic workload discovery on Kubernetes now supported with EDOT Collector — Elastic Observability Labs

文章来源于互联网:现在支持通过 EDOT Collector 在 Kubernetes 上动态发现工作负载

相关推荐: Elasticsearch:在 Elastic 中玩转 DeepSeek R1 来实现 RAG 应用

在这个春节,如一声春雷,DeepSeek R1 横空出世。现在人人都在谈论 DeepSeek R1。这个大语言模型无疑在中国及世界的人工智能发展史上留下了重要的里程碑。那么我们改如何结合 DeepSeek R1 及 Elasticsearch 来实现 RAG …

Tags: , , , ,