> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-mintlify-8c05c8a2.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> 用于 ClickStack 的 Kubernetes 集成 - ClickHouse 可观测性技术栈

# Kubernetes

ClickStack 使用 OpenTelemetry (OTel) collector 从 Kubernetes 集群中收集日志、指标和 Kubernetes 事件，并将其转发到 ClickStack。我们支持原生 OTel 日志格式，无需任何额外的厂商专用配置。

本指南集成以下内容：

* **日志**
* **基础设施指标**

<Note>
  如需发送应用层指标或 APM/链路追踪，你还需要为应用添加相应的语言集成。
</Note>

以下指南假设你已部署了[作为网关的 ClickStack OTel collector](/zh/clickstack/ingesting-data/collector)，并使用摄取 API key 对其进行了保护。

<div id="creating-the-otel-helm-chart-config-files">
  ## 创建 OTel Helm 图表配置文件
</div>

为了同时从各个节点和集群本身收集日志与指标，我们需要部署两个独立的 OpenTelemetry Collector。一个将作为 DaemonSet 守护进程集部署，用于从各个节点收集日志与指标；另一个将作为部署来运行，用于从集群本身收集日志与指标。

<div id="create-api-key-secret">
  ### 创建 API key Secret
</div>

使用 HyperDX 中的[摄取 API key](/zh/clickstack/ingesting-data/opentelemetry#sending-otel-data)创建一个新的 Kubernetes Secret。下方安装的组件将使用它安全地将数据摄取到你的 ClickStack OTel collector 中：

```shell theme={null}
kubectl create secret generic hyperdx-secret \
--from-literal=HYPERDX_API_KEY=<ingestion_api_key> \
```

此外，创建一个包含 ClickStack OTel collector 位置的 ConfigMap：

```shell theme={null}
kubectl create configmap -n=otel-demo otel-config-vars --from-literal=YOUR_OTEL_COLLECTOR_ENDPOINT=<OTEL_COLLECTOR_ENDPOINT>
# 例如：kubectl create configmap -n=otel-demo otel-config-vars --from-literal=YOUR_OTEL_COLLECTOR_ENDPOINT=http://my-hyperdx-hdx-oss-v2-otel-collector:4318
```

<div id="creating-the-daemonset-configuration">
  ### 创建 DaemonSet 守护进程集配置
</div>

DaemonSet 守护进程集会从集群中的每个节点采集日志和指标，但不会采集 Kubernetes 事件或集群级指标。

下载 DaemonSet 守护进程集清单：

```shell theme={null}
curl -O https://raw.githubusercontent.com/ClickHouse/clickhouse-docs/refs/heads/main/docs/use-cases/observability/clickstack/example-datasets/_snippets/k8s_daemonset.yaml
```

<Tabs>
  <Tab title="托管 ClickStack">
    <Accordion title="k8s_daemonset.yaml">
      ```yaml theme={null}
      # daemonset.yaml
      mode: daemonset

      # 使用 kubeletstats 的 CPU/内存利用率指标所必需
      clusterRole:
        create: true
        rules:
          - apiGroups:
              - ''
            resources:
              - nodes/proxy
            verbs:
              - get

      presets:
        logsCollection:
          enabled: true
        hostMetrics:
          enabled: true
        # 配置 Kubernetes 处理器以添加 Kubernetes 元数据。
        # 将 k8sattributes 处理器添加到所有管道，并向集群角色添加必要的规则。
        # 更多信息：https://opentelemetry.io/docs/kubernetes/collector/components/#kubernetes-attributes-processor
        kubernetesAttributes:
          enabled: true
          # 启用后，该处理器会提取关联 pod（容器组）的所有标签，并将其作为资源属性添加。
          # 标签的精确名称将作为键。
          extractAllPodLabels: true
          # 启用后，该处理器会提取关联 pod（容器组）的所有注解，并将其作为资源属性添加。
          # 注解的精确名称将作为键。
          extractAllPodAnnotations: true
        # 配置收集器通过 kubelet 上的 API server 收集节点、pod（容器组）和容器指标。
        # 将 kubeletstats receiver 添加到指标管道，并向集群角色添加必要的规则。
        # 更多信息：https://opentelemetry.io/docs/kubernetes/collector/components/#kubeletstats-receiver
        kubeletMetrics:
          enabled: true

      extraEnvs:
        - name: YOUR_OTEL_COLLECTOR_ENDPOINT
          valueFrom:
            configMapKeyRef:
              name: otel-config-vars
              key: YOUR_OTEL_COLLECTOR_ENDPOINT

      config:
        receivers:
          # 配置额外的 kubelet 指标
          kubeletstats:
            collection_interval: 20s
            auth_type: 'serviceAccount'
            endpoint: '${env:K8S_NODE_NAME}:10250'
            insecure_skip_verify: true
            metrics:
              k8s.pod.cpu_limit_utilization:
                enabled: true
              k8s.pod.cpu_request_utilization:
                enabled: true
              k8s.pod.memory_limit_utilization:
                enabled: true
              k8s.pod.memory_request_utilization:
                enabled: true
              k8s.pod.uptime:
                enabled: true
              k8s.node.uptime:
                enabled: true
              k8s.container.cpu_limit_utilization:
                enabled: true
              k8s.container.cpu_request_utilization:
                enabled: true
              k8s.container.memory_limit_utilization:
                enabled: true
              k8s.container.memory_request_utilization:
                enabled: true
              container.uptime:
                enabled: true

        exporters:
          otlphttp:
            endpoint: "${env:YOUR_OTEL_COLLECTOR_ENDPOINT}"
            compression: gzip

        service:
          pipelines:
            logs:
              exporters:
                - otlphttp
            metrics:
              exporters:
                - otlphttp
      ```
    </Accordion>
  </Tab>

  <Tab title="ClickStack 开源版">
    <Accordion title="k8s_daemonset.yaml">
      ```yaml theme={null}
      # daemonset.yaml
      mode: daemonset

      # 使用 kubeletstats 的 CPU/内存利用率指标所必需
      clusterRole:
        create: true
        rules:
          - apiGroups:
              - ''
            resources:
              - nodes/proxy
            verbs:
              - get

      presets:
        logsCollection:
          enabled: true
        hostMetrics:
          enabled: true
        # 配置 Kubernetes 处理器以添加 Kubernetes 元数据。
        # 将 k8sattributes 处理器添加到所有管道中，并向集群角色添加所需规则。
        # 更多信息：https://opentelemetry.io/docs/kubernetes/collector/components/#kubernetes-attributes-processor
        kubernetesAttributes:
          enabled: true
          # 启用后，该处理器会提取关联 pod（容器组）的所有标签，并将其添加为资源属性。
          # 标签的原始名称将作为键。
          extractAllPodLabels: true
          # 启用后，该处理器会提取关联 pod（容器组）的所有注解，并将其添加为资源属性。
          # 注解的原始名称将作为键。
          extractAllPodAnnotations: true
        # 配置 collector 通过 kubelet 节点代理上的 API server 收集节点、pod（容器组）和容器指标。
        # 将 kubeletstats receiver 添加到指标管道中，并向集群角色添加所需规则。
        # 更多信息：https://opentelemetry.io/docs/kubernetes/collector/components/#kubeletstats-receiver
        kubeletMetrics:
          enabled: true

      extraEnvs:
        - name: HYPERDX_API_KEY
          valueFrom:
            secretKeyRef:
              name: hyperdx-secret
              key: HYPERDX_API_KEY
              optional: true
        - name: YOUR_OTEL_COLLECTOR_ENDPOINT
          valueFrom:
            configMapKeyRef:
              name: otel-config-vars
              key: YOUR_OTEL_COLLECTOR_ENDPOINT

      config:
        receivers:
          # 配置额外的 kubelet 指标
          kubeletstats:
            collection_interval: 20s
            auth_type: 'serviceAccount'
            endpoint: '${env:K8S_NODE_NAME}:10250'
            insecure_skip_verify: true
            metrics:
              k8s.pod.cpu_limit_utilization:
                enabled: true
              k8s.pod.cpu_request_utilization:
                enabled: true
              k8s.pod.memory_limit_utilization:
                enabled: true
              k8s.pod.memory_request_utilization:
                enabled: true
              k8s.pod.uptime:
                enabled: true
              k8s.node.uptime:
                enabled: true
              k8s.container.cpu_limit_utilization:
                enabled: true
              k8s.container.cpu_request_utilization:
                enabled: true
              k8s.container.memory_limit_utilization:
                enabled: true
              k8s.container.memory_request_utilization:
                enabled: true
              container.uptime:
                enabled: true

        exporters:
          otlphttp:
            endpoint: "${env:YOUR_OTEL_COLLECTOR_ENDPOINT}"
            headers:
              authorization: "${env:HYPERDX_API_KEY}"
            compression: gzip

        service:
          pipelines:
            logs:
              exporters:
                - otlphttp
            metrics:
              exporters:
                - otlphttp
      ```
    </Accordion>
  </Tab>
</Tabs>

<div id="creating-the-deployment-configuration">
  ### 创建部署配置
</div>

要收集 Kubernetes 事件和集群级指标，我们需要单独部署一个以部署形式运行的 OpenTelemetry Collector。

下载安装清单：

```shell theme={null}
curl -O https://raw.githubusercontent.com/ClickHouse/clickhouse-docs/refs/heads/main/docs/use-cases/observability/clickstack/example-datasets/_snippets/k8s_deployment.yaml
```

<Tabs>
  <Tab title="托管 ClickStack">
    <Accordion title="k8s_deployment.yaml">
      ```yaml theme={null}
      # deployment.yaml
      mode: deployment

      image:
        repository: otel/opentelemetry-collector-contrib
        tag: 0.123.0
       
      # 这里只需要一个 collector，更多的话会产生重复数据
      replicaCount: 1
       
      presets:
        kubernetesAttributes:
          enabled: true
          # 启用后，处理器会提取关联 pod（容器组）的所有 labels，并将其添加为资源属性。
          # label 的准确名称将作为键。
          extractAllPodLabels: true
          # 启用后，处理器会提取关联 pod（容器组）的所有 annotations，并将其添加为资源属性。
          # annotation 的准确名称将作为键。
          extractAllPodAnnotations: true
        # 配置 collector 以收集 Kubernetes 事件。
        # 将 k8sobject receiver 添加到日志管道中，并默认收集 Kubernetes 事件。
        # 更多信息：https://opentelemetry.io/docs/kubernetes/collector/components/#kubernetes-objects-receiver
        kubernetesEvents:
          enabled: true
        # 配置 Kubernetes Cluster Receiver 以收集集群级指标。
        # 将 k8s_cluster receiver 添加到指标管道中，并向 ClusteRole 添加必要的规则。
        # 更多信息：https://opentelemetry.io/docs/kubernetes/collector/components/#kubernetes-cluster-receiver
        clusterMetrics:
          enabled: true

      extraEnvs:
        - name: YOUR_OTEL_COLLECTOR_ENDPOINT
          valueFrom:
            configMapKeyRef:
              name: otel-config-vars
              key: YOUR_OTEL_COLLECTOR_ENDPOINT

      config:
        exporters:
          otlphttp:
            endpoint: "${env:YOUR_OTEL_COLLECTOR_ENDPOINT}"
            compression: gzip
        service:
          pipelines:
            logs:
              exporters:
                - otlphttp
            metrics:
              exporters:
                - otlphttp
      ```
    </Accordion>
  </Tab>

  <Tab title="ClickStack 开源版">
    <Accordion title="k8s_deployment.yaml">
      ```yaml theme={null}
      # deployment.yaml
      mode: deployment

      image:
        repository: otel/opentelemetry-collector-contrib
        tag: 0.123.0
       
      # 这里只需要一个 collector，更多的话会产生重复数据
      replicaCount: 1
       
      presets:
        kubernetesAttributes:
          enabled: true
          # 启用后，处理器会提取关联 pod（容器组）的所有 labels，并将其添加为资源属性。
          # label 的准确名称将作为键。
          extractAllPodLabels: true
          # 启用后，处理器会提取关联 pod（容器组）的所有 annotations，并将其添加为资源属性。
          # annotation 的准确名称将作为键。
          extractAllPodAnnotations: true
        # 配置 collector 以收集 Kubernetes 事件。
        # 将 k8sobject receiver 添加到日志管道中，并默认收集 Kubernetes 事件。
        # 更多信息：https://opentelemetry.io/docs/kubernetes/collector/components/#kubernetes-objects-receiver
        kubernetesEvents:
          enabled: true
        # 配置 Kubernetes Cluster Receiver 以收集集群级指标。
        # 将 k8s_cluster receiver 添加到指标管道中，并向 ClusteRole 添加必要的规则。
        # 更多信息：https://opentelemetry.io/docs/kubernetes/collector/components/#kubernetes-cluster-receiver
        clusterMetrics:
          enabled: true

      extraEnvs:
        - name: HYPERDX_API_KEY
          valueFrom:
            secretKeyRef:
              name: hyperdx-secret
              key: HYPERDX_API_KEY
              optional: true
        - name: YOUR_OTEL_COLLECTOR_ENDPOINT
          valueFrom:
            configMapKeyRef:
              name: otel-config-vars
              key: YOUR_OTEL_COLLECTOR_ENDPOINT

      config:
        exporters:
          otlphttp:
            endpoint: "${env:YOUR_OTEL_COLLECTOR_ENDPOINT}"
            compression: gzip
            headers:
              authorization: "${env:HYPERDX_API_KEY}"
        service:
          pipelines:
            logs:
              exporters:
                - otlphttp
            metrics:
              exporters:
                - otlphttp
      ```
    </Accordion>
  </Tab>
</Tabs>

<div id="deploying-the-otel-collector">
  ## 部署 OpenTelemetry Collector
</div>

现在，您可以使用 [OpenTelemetry Helm 图表](https://github.com/open-telemetry/opentelemetry-helm-charts/tree/main/charts/opentelemetry-collector) 在 Kubernetes 集群中部署 OpenTelemetry Collector。

添加 OpenTelemetry Helm 仓库：

```shell theme={null}
helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts # 添加 OTel Helm 仓库
```

按上述配置安装 chart：

```shell copy theme={null}
helm install my-opentelemetry-collector-deployment open-telemetry/opentelemetry-collector -f k8s_deployment.yaml
helm install my-opentelemetry-collector-daemonset open-telemetry/opentelemetry-collector -f k8s_daemonset.yaml
```

现在，来自 Kubernetes 集群的指标、日志和 Kubernetes 事件应该已经显示在 HyperDX 中了。

<div id="forwarding-resouce-tags-to-pods">
  ## 将资源标签传递到 pod (容器组)  (推荐)
</div>

为了将应用层的日志、指标和链路追踪与 Kubernetes 元数据
(例如 pod 名称、命名空间等) 关联起来，您需要使用 `OTEL_RESOURCE_ATTRIBUTES` 环境变量
将 Kubernetes 元数据传递给应用程序。

以下是一个示例部署，演示如何使用环境变量将 Kubernetes 元数据传递给
应用程序：

```yaml theme={null}
# my_app_deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: app
  template:
    metadata:
      labels:
        app: app
        # 结合 Kubernetes Attribute Processor，可确保
        # pod（容器组）的日志和指标与服务名称相关联。
        service.name: <MY_APP_NAME>
    spec:
      containers:
        - name: app-container
          image: my-image
          env:
            # ... 其他环境变量
            # 通过 downward API 收集 K8s 元数据并转发给应用
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: POD_UID
              valueFrom:
                fieldRef:
                  fieldPath: metadata.uid
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
            - name: NODE_NAME
              valueFrom:
                fieldRef:
                  fieldPath: spec.nodeName
            - name: DEPLOYMENT_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.labels['deployment']
            # 通过 OTEL_RESOURCE_ATTRIBUTES 将 K8s 元数据转发给应用
            - name: OTEL_RESOURCE_ATTRIBUTES
              value: k8s.pod.name=$(POD_NAME),k8s.pod.uid=$(POD_UID),k8s.namespace.name=$(POD_NAMESPACE),k8s.node.name=$(NODE_NAME),k8s.deployment.name=$(DEPLOYMENT_NAME)
```
