使用 OpenTelemetry Collector 采集 Kubernetes 指标数据

WilliamGates
发布于 2023-11-22 14:57
浏览
0收藏

使用 OpenTelemetry Collector 采集 Kubernetes 指标数据-鸿蒙开发者社区

Kubernetes 已成为一个被广泛采用的行业工具,对可观测性工具的需求也在不断增加。为此,OpenTelemetry 创建了许多不同的工具,来帮助 Kubernetes 用户观察他们的集群和服务。

接下来我们将开始使用 OpenTelemetry 监控 Kubernetes 集群,将专注于收集 Kubernetes 集群、节点、pod 和容器的指标和日志,并使集群能够支持发出 OTLP 数据的服务。

Kubernetes 以多种不同的方式暴露了许多重要的遥测数据。它具有用于许多不同对象的日志、事件和指标,以及其工作负载生成的数据。 为了收集这些数据,我们将使用 OpenTelemetry Collector。该收集器可以高效地收集所有这些数据。


为了收集所有的数据,我们将需要安装两个收集器,一个作为 Daemonset,一个作为 Deployment。收集器的 DaemonSet 将用于收集服务、日志和节点、Pod 和容器的指标,而 Deployment 将用于收集集群的指标和事件。

为了安装收集器,我们这里将使用 OpenTelemetry Collector Helm 图表(​​https://github.com/open-telemetry/opentelemetry-helm-charts/tree/main/charts/opentelemetry-collector​​),该图表带有一些配置选项,可以更轻松地配置收集器。

首先需要添加 OpenTelemetry Helm 仓库:

$ helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts
$ helm repo update

收集 Kubernetes 遥测数据的第一步是部署一个 OpenTelemetry Collector 的 DaemonSet 实例,以收集与节点和运行在这些节点上的工作负载相关的遥测数据。使用 DaemonSet 可以确保此收集器实例被安装在所有节点上。每个 DaemonSet 中的收集器实例将仅从其运行的节点收集数据。

通过 OpenTelemetry Collector Helm Chat 配置所有这些组件非常简单,它还会处理所有与 Kubernetes 相关的细节,例如 RBAC、挂载和主机端口等。不过需要注意的是,默认情况下这个 Chart 图表不会将数据发送到任何后端。

指标采集

我们这里首先创建一个 Prometheus 实例来收集指标数据,如下所示,我们使用 Helm Chart 来快速部署 Prometheus:

$ helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
$ helm repo update

然后创建一个 ​​prometheus-values.yaml​​ 文件来配置 Prometheus Helm Chart:

# prometheus-values.yaml
kubeStateMetrics:
  enabled: false

nodeExporter:
  enabled: false

kubelet:
  enabled: false

kubeApiServer:
  enabled: false

kubeControllerManager:
  enabled: false

coreDns:
  enabled: false

kubeDns:
  enabled: false

kubeEtcd:
  enabled: false

kubeScheduler:
  enabled: false

kubeProxy:
  enabled: false

sidecar:
  datasources:
    label: grafana_datasource
    labelValue: "1"
  dashboards:
    enabled: true

prometheus:
  prometheusSpec:
    enableFeatures:
      - remote-write-receiver

prometheusOperator:
  enabled: true
  admissionWebhooks:
    patch:
      enabled: true
      image:
        registry: cnych
        repository: ingress-nginx-kube-webhook-certgen
        tag: v20221220-controller-v1.5.1-58-g787ea74b6

grafana:
  ingress:
    enabled: true
    ingressClassName: nginx
    hosts:
      - grafana.k8s.local

注意这里我们没有定制任何 Exporter,因为我们将使用 OpenTelemetry Collector 来收集指标数据,然后再将其发送到 Prometheus 中。此外为了能够将收集器指标发送到 Prometheus ,我们需要启用远程写入功能,正常只需要在 Prometheus 启动参数中指定 ​​--web.enable-remote-write-receiver​​​ 即可,但是我们这里是通过 Prometheus Operator 方式部署的,所以我们需要去修改 Prometheus 的 CR 实例对象,启用 ​​remote-write-receiver​​​ 特性。另外我们还为 Grafana 启用了 Ingress,这样我们就可以通过 ​​grafana.k8s.local​​​ 来访问 Grafana 了,默认用户名为 ​​admin​​,密码为 ​​prom-operator​​。

接下来直接使用下面的命令一键部署 Prometheus 即可:

$ helm upgrade --install prometheus prometheus-community/kube-prometheus-stack -f prometheus-values.yaml --namespace kube-otel --create-namespace
Release "prometheus" does not exist. Installing it now.

NAME: prometheus
LAST DEPLOYED: Wed Aug 23 09:42:23 2023
NAMESPACE: kube-otel
STATUS: deployed
REVISION: 1
NOTES:
kube-prometheus-stack has been installed. Check its status by running:
  kubectl --namespace kube-otel get pods -l "release=prometheus"

Visit https://github.com/prometheus-operator/kube-prometheus for instructions on how to create & configure Alertmanager and Prometheus instances using the Operator.

部署后的资源对象如下所示:

$ kubectl get pods -n kube-otel
NAME                                                     READY   STATUS    RESTARTS   AGE
alertmanager-prometheus-kube-prometheus-alertmanager-0   2/2     Running   0          6m3s
prometheus-grafana-5d95cbc57f-v2bw8                      3/3     Running   0          61s
prometheus-kube-prometheus-operator-74fcfc7ff6-2bzfj     1/1     Running   0          6m19s
prometheus-prometheus-kube-prometheus-prometheus-0       2/2     Running   0          6m3s
$ kubectl get ingress -n kube-otel
NAME                 CLASS   HOSTS               ADDRESS       PORTS   AGE
prometheus-grafana   nginx   grafana.k8s.local   10.98.12.94   80      114s

现在我们需要将指标数据发送到 Prometheus,所以我们需要在 Otel 采集器里面去配置导出器,可以使用到 ​​prometheus​​​ 或者 ​​prometheusremotewrite​​​ 导出器。我们这里将使用如下的 ​​otel-collector-ds-values.yaml​​ 文件来配置 OpenTelemetry Collector Helm Chart:

# otel-collector-ds-values.yaml
mode: daemonset

tolerations:
  - key: node-role.kubernetes.io/control-plane
    effect: NoSchedule

clusterRole:
  create: true
  rules:
    - apiGroups:
        - ""
      resources:
        - nodes/proxy
      verbs:
        - get
        - watch
    - apiGroups:
        - ""
      resources:
        - nodes
      verbs:
        - list
        - watch
        - get

presets:
  hostMetrics:
    enabled: true
  kubernetesAttributes:
    enabled: true
  kubeletMetrics:
    enabled: true

ports:
  prom: # 添加一个 9090 端口,用于 Prometheus 抓取
    enabled: true
    containerPort: 9090
    servicePort: 9090
    protocol: TCP

service: # 创建一个 Service,后面 ServiceMonitor 会用到
  enabled: true

config:
  receivers:
    prometheus:
      config:
        scrape_configs:
          - job_name: opentelemetry-collector
            scrape_interval: 10s
            static_configs:
              - targets:
                  - ${env:MY_POD_IP}:8888
  exporters:
    logging:
      loglevel: debug
    prometheus:
      endpoint: "0.0.0.0:9090"
      metric_expiration: 180m
      resource_to_telemetry_conversion:
        enabled: true
    # prometheusremotewrite:
    #   endpoint: http://prometheus-kube-prometheus-prometheus:9090/api/v1/write
    #   tls:
    #     insecure: true
  processors:
    metricstransform:
      transforms:
        include: .+
        match_type: regexp
        action: update
        operations:
          - action: add_label
            new_label: k8s.cluster.id
            new_value: abcd1234
          - action: add_label
            new_label: k8s.cluster.name
            new_value: youdian-k8s
  service:
    pipelines:
      metrics:
        exporters:
          - prometheus
        processors:
          - memory_limiter # 内存限制一般放在最前面
          - metricstransform
          - k8sattributes
          - batch # 批量处理器放在最后
        receivers:
          - otlp
          - hostmetrics
          - kubeletstats
          - prometheus

直接使用上面的配置文件来部署 OpenTelemetry Collector DaemonSet:

$ helm upgrade --install opentelemetry-collector open-telemetry/opentelemetry-collector -f otel-ds-values.yaml --namespace kube-otel --create-namespace
$ kubectl get pods -n kube-otel
NAME                                                     READY   STATUS      RESTARTS   AGE
opentelemetry-collector-agent-22rsm                      1/1     Running     0          18h
opentelemetry-collector-agent-v4nkh                      1/1     Running     0          18h
opentelemetry-collector-agent-xndlq                      1/1     Running     0          18h

安装后我们可以查看当前采集器的配置信息,使用命令 ​​kubectl get cm -n kube-otel opentelemetry-collector-agent -oyaml​​:

exporters:
  logging:
    loglevel: debug
  prometheus:
    endpoint: 0.0.0.0:9090
    metric_expiration: 180m
    resource_to_telemetry_conversion:
      enabled: true
extensions:
  health_check: {}
  memory_ballast:
    size_in_percentage: 40
processors:
  batch: {}
  k8sattributes:
    extract:
      metadata:
        - k8s.namespace.name
        - k8s.deployment.name
        - k8s.statefulset.name
        - k8s.daemonset.name
        - k8s.cronjob.name
        - k8s.job.name
        - k8s.node.name
        - k8s.pod.name
        - k8s.pod.uid
        - k8s.pod.start_time
    filter:
      node_from_env_var: K8S_NODE_NAME
    passthrough: false
    pod_association:
      - sources:
          - from: resource_attribute
            name: k8s.pod.ip
      - sources:
          - from: resource_attribute
            name: k8s.pod.uid
      - sources:
          - from: connection
  memory_limiter:
    check_interval: 5s
    limit_percentage: 80
    spike_limit_percentage: 25
  metricstransform:
    transforms:
      action: update
      include: .+
      match_type: regexp
      operations:
        - action: add_label
          new_label: k8s.cluster.id
          new_value: abcd1234
        - action: add_label
          new_label: k8s.cluster.name
          new_value: youdian-k8s
receivers:
  hostmetrics:
    collection_interval: 10s
    root_path: /hostfs
    scrapers:
      cpu: null
      disk: null
      filesystem:
        exclude_fs_types:
          fs_types:
            - autofs
            - binfmt_misc
            - bpf
            - cgroup2
            - configfs
            - debugfs
            - devpts
            - devtmpfs
            - fusectl
            - hugetlbfs
            - iso9660
            - mqueue
            - nsfs
            - overlay
            - proc
            - procfs
            - pstore
            - rpc_pipefs
            - securityfs
            - selinuxfs
            - squashfs
            - sysfs
            - tracefs
          match_type: strict
        exclude_mount_points:
          match_type: regexp
          mount_points:
            - /dev/*
            - /proc/*
            - /sys/*
            - /run/k3s/containerd/*
            - /var/lib/docker/*
            - /var/lib/kubelet/*
            - /snap/*
      load: null
      memory: null
      network: null
  kubeletstats:
    auth_type: serviceAccount
    collection_interval: 20s
    endpoint: ${K8S_NODE_NAME}:10250
  otlp:
    protocols:
      grpc:
        endpoint: ${env:MY_POD_IP}:4317
      http:
        endpoint: ${env:MY_POD_IP}:4318
  prometheus:
    config:
      scrape_configs:
        - job_name: opentelemetry-collector
          scrape_interval: 10s
          static_configs:
            - targets:
                - ${env:MY_POD_IP}:8888
service:
  extensions:
    - health_check
    - memory_ballast
  pipelines:
    metrics:
      exporters:
        - prometheus
      processors:
        - memory_limiter
        - metricstransform
        - k8sattributes
        - batch
      receivers:
        - otlp
        - hostmetrics
        - kubeletstats
        - prometheus
  telemetry:
    metrics:
      address: ${env:MY_POD_IP}:8888
# ...... 省略其他

上面的配置信息是 OpenTelemetry Collector 真正运行时的配置信息,我们这里只保留了和 metrics 相关的配置。从上面配置文件可以看出我们定义了 4 个接收器:

  • hostmetrics 接收器
  • kubeletstats 接收器
  • otlp 接收器
  • prometheus 接收器

4 个处理器:

  • batch 处理器
  • memory_limiter 处理器
  • k8sattributes 处理器
  • metricstransform 处理器

2 个导出器:

  • logging 导出器
  • prometheus 导出器

下面我们来详细介绍一下其他组件。

otlp 接收器

otlp 接收器是在 OTLP 格式中收集跟踪、指标和日志的最佳解决方案。如果您在以其他格式发出应用程序遥测数据,那么收集器很有可能也有一个相应的接收器。这个前面我们已经详细介绍过了,我们这里定义了 ​​http​​​ 和 ​​grpc​​​ 两种协议,分别监听 ​​4317​​​ 和 ​​4318​​ 端口。配置如下所示:

receivers:
  otlp:
    protocols:
      grpc:
        endpoint: ${env:MY_POD_IP}:4317
      http:
        endpoint: ${env:MY_POD_IP}:4318

hostmetrics 接收器

​hostmetrics​​ 接收器用于收集主机级别的指标,例如 CPU 使用率、磁盘使用率、内存使用率和网络流量。我们这里的配置如下所示:

receivers:
  hostmetrics:
    collection_interval: 10s
    root_path: /hostfs
    scrapers:
      cpu: null
      disk: null
      filesystem:
        exclude_fs_types:
          fs_types:
            - autofs
            - binfmt_misc
            - bpf
            - cgroup2
            - configfs
            - debugfs
            - devpts
            - devtmpfs
            - fusectl
            - hugetlbfs
            - iso9660
            - mqueue
            - nsfs
            - overlay
            - proc
            - procfs
            - pstore
            - rpc_pipefs
            - securityfs
            - selinuxfs
            - squashfs
            - sysfs
            - tracefs
          match_type: strict
        exclude_mount_points:
          match_type: regexp
          mount_points:
            - /dev/*
            - /proc/*
            - /sys/*
            - /run/k3s/containerd/*
            - /var/lib/docker/*
            - /var/lib/kubelet/*
            - /snap/*
      load: null
      memory: null
      network: null

配置红通过 ​​collection_interval​​​ 指定了每 10 秒收集一次指标,并使用根路径 ​​/hostfs​​ 来访问主机文件系统。

hostmetrics 接收器包括多个抓取器,用于收集不同类型的指标。例如,cpu 抓取器用于收集 CPU 使用率指标,disk 抓取器用于收集磁盘使用率指标,memory 抓取器用于收集内存使用率指标,load 抓取器用于收集 CPU 负载指标。在这个配置文件中,我们只启用了 filesystem 抓取器,用于收集文件系统使用率指标。

filesystem 抓取器的配置中,指定了要排除某些文件系统类型和挂载点的指标收集。具体来说,它排除了文件系统类型 ​​autofs​​​、​​binfmt_misc​​​、​​bpf​​​、​​cgroup2​​​......,它还排除了挂载点 ​​/dev/*​​​、​​/proc/*​​​、​​/sys/*​​​、​​/run/k3s/containerd/*​​​、​​/var/lib/docker/*​​​、​​/var/lib/kubelet/*​​​ 和 ​​/snap/*​​,这些排除操作确保只收集相关的文件系统使用率指标。

kubeletstats 接收器

Kubelet Stats Receiver 用于从 kubelet 上的 API 服务器中获取指标。通常用于收集与 Kubernetes 工作负载相关的指标,例如 CPU 使用率、内存使用率和网络流量。这些指标可用于监视 Kubernetes 集群和工作负载的健康状况和性能。

Kubelet Stats Receiver 默认支持在端口 10250 暴露的安全 Kubelet 端点和在端口 10255 暴露的只读 Kubelet 端点。如果 ​​auth_type​​​ 设置为 none,则将使用只读端点。如果 ​​auth_type​​ 设置为以下任何值,则将使用安全端点:

  • ​tls​​​ 告诉接收方使用 TLS 进行身份验证,并要求设置​​ca_file​​​、​​key_file​​​ 和​​cert_file​​ 字段。
  • ​serviceAccount​​ 告诉该接收者使用默认的 ServiceAccount 令牌来向 kubelet API 进行身份验证。
  • ​kubeConfig​​​ 告诉该接收器使用​​kubeconfig​​​ 文件(​​KUBECONFIG​​​ 环境变量或​​~/.kube/config​​)进行身份验证并使用 APIServer 代理来访问 kubelet API。
  • ​initial_delay​​(默认 = 1 秒),定义接收器在开始之前等待的时间。

此外还可以指定以下参数:

  • ​collection_interval​​(默认= 10s),收集数据的时间间隔。
  • ​insecure_skip_verify​​(默认= false),是否跳过证书验证。

默认情况下,所有生成的指标都基于 kubelet 的 ​​/stats/summary​​ 端点提供的资源标签。对于某些场景而言,这可能还不够。因此,可以利用其他端点来获取附加的元数据,并将它们设置为指标资源的额外标签。当前支持的元数据包括以下内容:

  • ​container.id​​​ - 使用从通过​​/pods​​ 暴露的容器状态获取的容器 ID 标签来增强指标。
  • ​k8s.volume.type​​​ - 从通过​​/pods​​​ 暴露的 Pod 规范收集卷类型,并将其作为卷指标的标签。如果端点提供的信息不仅仅是卷类型,这些信息也会根据可用字段和卷类型进行同步。例如,​​aws.volume.id​​​ 将从​​awsElasticBlockStore​​​ 同步,​​gcp.pd.name​​​ 将从​​gcePersistentDisk​​ 同步。

如果你希望将 ​​container.id​​​ 标签添加到你的指标中,请使用 ​​extra_metadata_labels​​ 字段来启用它,例如:

receivers:
  kubeletstats:
    collection_interval: 10s
    auth_type: "serviceAccount"
    endpoint: "${env:K8S_NODE_NAME}:10250"
    insecure_skip_verify: true
    extra_metadata_labels:
      - container.id

如果没有设置 ​​extra_metadata_labels​​,则不会进行额外的 API 调用来获取额外的元数据。

默认情况下,该收集器将收集来自容器、pod 和节点的指标。我们可以通过设置一个 ​​metric_groups​​​ 来指定要收集的数据来源,可以指定的值包括 ​​container​​​、​​pod​​​、​​node​​​ 和 ​​volume​​。比如希望仅从接收器收集节点和 Pod 指标,则可以使用以下配置:

receivers:
  kubeletstats:
    collection_interval: 10s
    auth_type: "serviceAccount"
    endpoint: "${env:K8S_NODE_NAME}:10250"
    insecure_skip_verify: true
    metric_groups:
      - node
      - pod

​K8S_NODE_NAME​​ 环境变量在 Kubernetes 集群里面我们可以通过 Downward API 来注入。

prometheus 接收器

Prometheus 接收器以 Prometheus 格式接收指标数据。该接收器旨在最大限度地成为 Prometheus 的替代品,但是目前不支持下面这些 Prometheus 的高级功能:

  • ​alert_config.alertmanagers​
  • ​alert_config.relabel_configs​
  • ​remote_read​
  • ​remote_write​
  • ​rule_files​

该接收器是让 Prometheus 抓取你的服务的直接替代品。它支持 ​​scrape_config​​ 中的全部 Prometheus 配置,包括服务发现。就像在启动 Prometheus 之前在 YAML 配置文件中写入一样,例如:

prometheus --config.file=prom.yaml

注意:由于收集器配置支持 env 变量替换,prometheus 配置中的 ​​$​​​ 字符将被解释为环境变量。如果要在 prometheus 配置中使用 ​​$​​​ 字符,则必须使用 ​​$$​​ 对其进行转义。

比如我们可以通过下面的配置来让收集器接收 Prometheus 的指标数据,使用方法和 Prometheus 一样,只需要在 ​​scrape_configs​​ 中添加一个任务即可:

receivers:
  prometheus:
    config:
      scrape_configs:
        - job_name: opentelemetry-collector
          scrape_interval: 10s
          static_configs:
            - targets:
                - ${env:MY_POD_IP}:8888
        - job_name: k8s
          kubernetes_sd_configs:
            - role: pod
          relabel_configs:
            - source_labels:
                [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
              regex: "true"
              action: keep
          metric_relabel_configs:
            - source_labels: [__name__]
              regex: "(request_duration_seconds.*|response_duration_seconds.*)"
              action: keep

我们这里添加的 ​​opentelemetry-collector​​​ 任务,是去抓取 ​​8888​​​ 端口的数据,而 ​​8888​​​ 端口就是 OpenTelemetry Collector 的端口,这个端口我们在 ​​service.telemetry​​ 中已经定义了,这样我们就可以通过该接收器来抓取 OpenTelemetry Collector 本身的指标数据了。



文章转载自公众号:k8s技术圈

分类
标签
已于2023-11-22 14:57:03修改
收藏
回复
举报
回复
    相关推荐