作者:来自 Elastic Christos Markou 及 Alexander Wert
了解 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 配置片段:
yaml
`
1. receivers:
2. receiver_creator/metrics:
3. watch_observers: [k8s_observer]
4. discovery:
5. enabled: true
6. receivers:
8. receiver_creator/logs:
9. watch_observers: [k8s_observer]
10. discovery:
11. enabled: true
12. receivers:
`AI写代码
你可以将上述内容包含在 EDOT Collector 的配置中,特别是在 receivers 部分。
由于我们示例中的日志收集将通过发现功能进行,请确保删除静态 filelog 接收器的配置块,并禁用其预设(即设置为 false
),以避免日志重复。
确保 k8sobserver 已启用,并作为扩展的一部分:
yaml
`
1. extensions:
2. k8s_observer:
3. observe_nodes: true
4. observe_services: true
5. observe_ingresses: true
7. // ...
9. service:
10. extensions: [k8s_observer]
`AI写代码
最后但同样重要的是,确保日志文件的卷正确挂载:
yaml
`
1. volumeMounts:
2. - name: varlogpods
3. mountPath: /var/log/pods
4. readOnly: true
6. volumes:
7. - name: varlogpods
8. hostPath:
9. path: /var/log/pods
`AI写代码
一旦配置准备就绪,请按照 Kubernetes 快速入门指南部署 EDOT Collector。确保用包含上述修改的文件替换快速入门指南中链接的 values.yaml 文件。
基于注解从移动目标收集指标
在这个示例中,我们有一个包含两个不同容器的 Pod 规范的 Deployment。其中一个容器运行 Redis 服务器,另一个运行 NGINX 服务器。因此,我们希望为这两个目标容器提供不同的提示。
基于注解的发现功能支持这一点,允许我们为每个暴露的容器端口指定指标注解。
以下是完整的规范文件示例:
yaml
``
1. apiVersion: v1
2. kind: ConfigMap
3. metadata:
4. name: nginx-conf
5. data:
6. nginx.conf: |
7. user nginx;
8. worker_processes 1;
9. error_log /dev/stderr warn;
10. pid /var/run/nginx.pid;
11. events {
12. worker_connections 1024;
13. }
14. http {
15. include /etc/nginx/mime.types;
16. default_type application/octet-stream;
18. log_format main '$remote_addr - $remote_user [$time_local] "$request" '
19. '$status $body_bytes_sent "$http_referer" '
20. '"$http_user_agent" "$http_x_forwarded_for"';
21. access_log /dev/stdout main;
22. server {
23. listen 80;
24. server_name localhost;
26. location /nginx_status {
27. stub_status on;
28. }
29. }
30. include /etc/nginx/conf.d/*;
31. }
32. ---
33. apiVersion: apps/v1
34. kind: Deployment
35. metadata:
36. name: redis-deployment
37. labels:
38. app: redis
39. spec:
40. replicas: 1
41. selector:
42. matchLabels:
43. app: redis
44. template:
45. metadata:
46. labels:
47. app: redis
48. annotations:
49. # redis container port hints
50. io.opentelemetry.discovery.metrics.6379/enabled: "true"
51. io.opentelemetry.discovery.metrics.6379/scraper: redis
52. io.opentelemetry.discovery.metrics.6379/config: |
53. collection_interval: "20s"
54. timeout: "10s"
56. # nginx container port hints
57. io.opentelemetry.discovery.metrics.80/enabled: "true"
58. io.opentelemetry.discovery.metrics.80/scraper: nginx
59. io.opentelemetry.discovery.metrics.80/config: |
60. endpoint: "http://`endpoint`/nginx_status"
61. collection_interval: "30s"
62. timeout: "20s"
63. spec:
64. volumes:
65. - name: nginx-conf
66. configMap:
67. name: nginx-conf
68. items:
69. - key: nginx.conf
70. path: nginx.conf
71. containers:
72. - name: webserver
73. image: nginx:latest
74. ports:
75. - containerPort: 80
76. name: webserver
77. volumeMounts:
78. - mountPath: /etc/nginx/nginx.conf
79. readOnly: true
80. subPath: nginx.conf
81. name: nginx-conf
82. - image: redis
83. imagePullPolicy: IfNotPresent
84. name: redis
85. ports:
86. - name: redis
87. containerPort: 6379
88. protocol: TCP
``AI写代码
当这个工作负载部署后,Collector 会自动发现它并识别特定的注解。之后,两个不同的接收器将启动,每个接收器负责各自的目标容器。
从多个目标容器收集日志
基于注解的发现功能还支持根据提供的注解收集日志。在下面的示例中,我们再次有一个包含两个不同容器的 Pod 的 Deployment,其中我们希望应用不同的日志收集配置。我们可以为每个容器名称指定作用域的注解:
markdown
`
1. apiVersion: apps/v1
2. kind: Deployment
3. metadata:
4. name: busybox-logs-deployment
5. labels:
6. app: busybox
7. spec:
8. replicas: 1
9. selector:
10. matchLabels:
11. app: busybox
12. template:
13. metadata:
14. labels:
15. app: busybox
16. annotations:
17. io.opentelemetry.discovery.logs.lazybox/enabled: "true"
18. io.opentelemetry.discovery.logs.lazybox/config: |
19. operators:
20. - id: container-parser
21. type: container
22. - id: some
23. type: add
24. field: attributes.tag
25. value: hints-lazybox
26. io.opentelemetry.discovery.logs.busybox/enabled: "true"
27. io.opentelemetry.discovery.logs.busybox/config: |
28. operators:
29. - id: container-parser
30. type: container
31. - id: some
32. type: add
33. field: attributes.tag
34. value: hints-busybox
35. spec:
36. containers:
37. - name: busybox
38. image: busybox
39. args:
40. - /bin/sh
41. - -c
42. - while true; do echo "otel logs from busybox at $(date +%H:%M:%S)" && sleep 5s; done
43. - name: lazybox
44. image: busybox
45. args:
46. - /bin/sh
47. - -c
48. - while true; do echo "otel logs from lazybox at $(date +%H:%M:%S)" && sleep 25s; done
`AI写代码
上述配置启用了两个不同的 filelog 接收器实例,每个实例应用一个独特的解析配置。当我们知道如何解析特定技术日志时,例如 Apache 服务器访问日志,这非常有用。
同时收集指标和日志
在我们的第三个示例中,我们展示了如何在同一个工作负载上定义指标和日志注解。这使我们能够从发现的工作负载中收集这两种信号。以下是一个包含 Redis 服务器和一个执行虚拟日志写入的 BusyBox 容器的 Pod 的 Deployment。我们可以将注解定向到端口和容器级别,从 Redis 服务器收集指标(使用 Redis 接收器),并从 BusyBox 收集日志(使用 filelog 接收器)。以下是配置方法:
yaml
`
1. apiVersion: apps/v1
2. kind: Deployment
3. metadata:
4. name: redis-deployment
5. labels:
6. app: redis
7. spec:
8. replicas: 1
9. selector:
10. matchLabels:
11. app: redis
12. template:
13. metadata:
14. labels:
15. app: redis
16. annotations:
17. io.opentelemetry.discovery.metrics.6379/enabled: "true"
18. io.opentelemetry.discovery.metrics.6379/scraper: redis
19. io.opentelemetry.discovery.metrics.6379/config: |
20. collection_interval: "20s"
21. timeout: "10s"
23. io.opentelemetry.discovery.logs.busybox/enabled: "true"
24. io.opentelemetry.discovery.logs.busybox/config: |
25. operators:
26. - id: container-parser
27. type: container
28. - id: some
29. type: add
30. field: attributes.tag
31. value: hints
32. spec:
33. containers:
34. - image: redis
35. imagePullPolicy: IfNotPresent
36. name: redis
37. ports:
38. - name: redis
39. containerPort: 6379
40. protocol: TCP
41. - name: busybox
42. image: busybox
43. args:
44. - /bin/sh
45. - -c
46. - while true; do echo "otel logs at $(date +%H:%M:%S)" && sleep 15s; done
`AI写代码
在 Elastic 中探索和分析来自动态目标的数据
一旦目标 Pods 被发现并且 Collector 开始从它们收集遥测数据,我们就可以在 Elastic 中探索这些数据。在 Discover 中,我们可以搜索 Redis 和 NGINX 的指标,以及从 BusyBox 容器收集的日志。以下是展示的样子:
总结
以上示例展示了我们的 OpenTelemetry Collector 用户如何利用这个新功能 ------ 我们在开发过程中发挥了重要作用。
为此,我们借鉴了在 Metricbeat 、Filebeat 和 Elastic-Agent 中已支持的类似功能的多年经验。这让我们非常高兴和自信,因为它弥合了 Elastic 特定监控代理和 OpenTelemetry Collector 之间的功能差距 ------ 让它变得更好。