菜单
文档breadcrumb arrow Grafana Tempobreadcrumb arrow 设置breadcrumb arrow 使用 Tanka 在 Kubernetes 上部署
开源

使用 Tanka 在 Kubernetes 上部署

通过本部署指南,您可以使用 Jsonnet 库和 Grafana Tanka 将 Tempo 部署到 Kubernetes,创建开发集群或沙盒环境。此过程使用 MinIO 提供对象存储,无论您使用何种云平台或本地存储。在生产环境中,您可以使用您的云提供商的对象存储服务,以避免在生产环境中运行对象存储带来的运维开销。

要使用 Tanka 在 Kubernetes 上设置 Tempo,您需要

  1. 配置 Kubernetes 并安装 Tanka
  2. 设置 Tanka 环境
  3. 安装库
  4. 部署 MinIO 对象存储
  5. 可选:启用 metrics-generator
  6. 使用 Tanka 命令部署 Tempo

注意

此配置不适合生产环境,但可作为学习 Tempo 的有用方法。

开始之前

使用 Tanka 将 Tempo 部署到 Kubernetes,您需要

  • 一个 Kubernetes 集群,默认配置至少需要 40 个 CPU 和 46GB 内存。较小的摄入或查询量可以使用远小于此的配置。
  • kubectl (版本取决于您集群中 Kubernetes 的 API 版本)

配置 Kubernetes 并安装 Tanka

按照以下步骤配置 Kubernetes 并安装 Tanka。

  1. 为安装创建一个新目录,并将其设置为当前工作目录

    bash
    mkdir tempo
    cd tempo
  2. 创建一个 Kubernetes 命名空间。您可以将本例中的命名空间tempo替换为您选择的名称。

    bash
    kubectl create namespace tempo
  3. 安装 Grafana Tanka;请参阅 安装 Tanka

  4. 安装 jsonnet-bundler;请参阅 jsonnet-bundler README

设置 Tanka 环境

Tanka 需要您 Kubernetes 环境的当前上下文。

  1. 检查您的 Kubernetes 集群的当前上下文并确保其正确

    bash
    kubectl config current-context
  2. 初始化 Tanka。这将使用当前的 Kubernetes 上下文

    bash
    tk init --k8s=false
    tk env add environments/tempo
    tk env set environments/tempo \
     --namespace=tempo \
     --server-from-context=$(kubectl config current-context)

安装库

安装 k.libsonnet、Jsonnet 和 Memcached 库。

  1. 为您版本的 Kubernetes 安装 k.libsonnet

    bash
    mkdir -p lib
    export K8S_VERSION=1.25
    jb install github.com/jsonnet-libs/k8s-libsonnet/${K8S_VERSION}@main
    cat <<EOF > lib/k.libsonnet
    import 'github.com/jsonnet-libs/k8s-libsonnet/${K8S_VERSION}/main.libsonnet'
    EOF
  2. 安装 Tempo Jsonnet 库及其依赖项。

    bash
    jb install github.com/grafana/tempo/operations/jsonnet/microservices@main
  3. 安装 Memcached 库及其依赖项。

    bash
    jb install github.com/grafana/jsonnet-libs/memcached@master

部署 MinIO 对象存储

MinIO 是一种开源的 Amazon S3 兼容对象存储服务,可免费获取且易于在 Kubernetes 上运行。

  1. 创建一个名为 minio.yaml 的文件,并将以下 YAML 配置复制到其中。您可能需要根据您的 Kubernetes 平台删除/修改 storageClassName。例如,GKE 可能不支持 local-path 名称,但可能支持 standard 等其他选项。

    yaml
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      # This name uniquely identifies the PVC. Will be used in deployment below.
      name: minio-pv-claim
      labels:
        app: minio-storage-claim
    spec:
      # Read more about access modes here: https://kubernetes.ac.cn/docs/user-guide/persistent-volumes/#access-modes
      accessModes:
        - ReadWriteOnce
      storageClassName: local-path
      resources:
        # This is the request for storage. Should be available in the cluster.
        requests:
          storage: 50Gi
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: minio
    spec:
      selector:
        matchLabels:
          app: minio
      strategy:
        type: Recreate
      template:
        metadata:
          labels:
            # Label is used as selector in the service.
            app: minio
        spec:
          # Refer to the PVC created earlier
          volumes:
            - name: storage
              persistentVolumeClaim:
                # Name of the PVC created earlier
                claimName: minio-pv-claim
          initContainers:
            - name: create-buckets
              image: busybox:1.28
              command:
                - "sh"
                - "-c"
                - "mkdir -p /storage/tempo-data"
              volumeMounts:
                - name: storage # must match the volume name, above
                  mountPath: "/storage"
          containers:
            - name: minio
              # Pulls the default Minio image from Docker Hub
              image: minio/minio:latest
              args:
                - server
                - /storage
                - --console-address
                - ":9001"
              env:
                # Minio access key and secret key
                - name: MINIO_ACCESS_KEY
                  value: "minio"
                - name: MINIO_SECRET_KEY
                  value: "minio123"
              ports:
                - containerPort: 9000
                - containerPort: 9001
              volumeMounts:
                - name: storage # must match the volume name, above
                  mountPath: "/storage"
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: minio
    spec:
      type: ClusterIP
      ports:
        - port: 9000
          targetPort: 9000
          protocol: TCP
          name: api
        - port: 9001
          targetPort: 9001
          protocol: TCP
          name: console
      selector:
        app: minio
  2. 运行以下命令应用 minio.yaml 文件

    bash
    kubectl apply --namespace tempo -f minio.yaml
  3. 要检查 MinIO 是否已正确配置,请登录 MinIO 并验证是否已创建一个 bucket。如果没有这些 bucket,将不会存储数据。

    1. 将 MinIO 端口转发到 9001

      bash
       kubectl port-forward --namespace tempo service/minio 9001:9001
    2. 使用浏览器导航到 MinIO 管理界面:https://:9001。登录凭据是用户名 minio,密码 minio123

    3. 验证 Buckets 页面是否列出 tempo-data

  4. 通过运行以下命令更新 environments/tempo/main.jsonnet 文件的内容,使用 MinIO 对象存储配置 Tempo 集群

    jsonnet
    cat <<EOF > environments/tempo/main.jsonnet
    // The jsonnet file used to generate the Kubernetes manifests.
    local tempo = import 'microservices/tempo.libsonnet';
    local k = import 'ksonnet-util/kausal.libsonnet';
    local container = k.core.v1.container;
    local containerPort = k.core.v1.containerPort;
    
    tempo {
        _images+:: {
            tempo: 'grafana/tempo:latest',
            tempo_query: 'grafana/tempo-query:latest',
        },
    
        tempo_distributor_container+:: container.withPorts([
                containerPort.new('jaeger-grpc', 14250),
                containerPort.new('otlp-grpc', 4317),
            ]),
    
        _config+:: {
            namespace: 'tempo',
    
            compactor+: {
                replicas: 1,
            },
            query_frontend+: {
                replicas: 2,
            },
            querier+: {
                replicas: 3,
            },
            ingester+: {
                replicas: 3,
                pvc_size: '10Gi',
                pvc_storage_class: 'standard',
            },
            distributor+: {
                replicas: 3,
                receivers: {
                    jaeger: {
                        protocols: {
                            grpc: {
                                endpoint: '0.0.0.0:14250',
                            },
                        },
                    },
                    otlp: {
                        protocols: {
                            grpc: {
                                endpoint: '0.0.0.0:4317',
                            },
                        },
                    },
                },
            },
    
            metrics_generator+: {
                replicas: 1,
                ephemeral_storage_request_size: '10Gi',
                ephemeral_storage_limit_size: '11Gi',
                pvc_size: '10Gi',
                pvc_storage_class: 'standard',
            },
            memcached+: {
                replicas: 3,
            },
    
            bucket: 'tempo-data',
            backend: 's3',
        },
    
        tempo_config+:: {
            storage+: {
                trace+: {
                    s3: {
                        bucket: $._config.bucket,
                        access_key: 'minio',
                        secret_key: 'minio123',
                        endpoint: 'minio:9000',
                        insecure: true,
                    },
                },
            },
            metrics_generator+: {
                processor: {
                    span_metrics: {},
                    service_graphs: {},
                },
    
                registry+: {
                    external_labels: {
                        source: 'tempo',
                    },
                },
            },
            overrides+: {
                metrics_generator_processors: ['service-graphs', 'span-metrics'],
            },
        },
    
        tempo_ingester_container+:: {
          securityContext+: {
            runAsUser: 0,
          },
        },
    
        local statefulSet = $.apps.v1.statefulSet,
        tempo_ingester_statefulset+:
            statefulSet.mixin.spec.withPodManagementPolicy('Parallel'),
    }
    EOF

可选:启用 metrics-generator

在前面的配置中,已启用指标生成。但是,您仍然需要指定将生成的指标数据发送到何处。如果您想将这些指标远程写入到 Prometheus 兼容实例(例如 Grafana Cloud metrics 或 Mimir 实例),您需要在上面的 tempo_config 块的 metrics_generator 部分包含以下配置块(这假定需要基本身份验证,如果不需要,则移除 basic_auth 部分)。您可以通过云门户找到您的 Grafana Cloud 账户的 Grafana Cloud metrics 实例的详细信息。

jsonnet
storage+: {
    remote_write: [
        {
            url: 'https://<urlForPrometheusCompatibleStore>/api/v1/write',
            send_exemplars: true,
            basic_auth: {
                username: '<username>',
                password: '<password>',
            },
        }
    ],
},

注意:启用指标生成并将其远程写入 Grafana Cloud Metrics 将产生额外的活跃序列,这可能会影响您的账单。有关账单的更多信息,请参阅账单和使用情况。有关指标生成的更多信息,请参阅 Tempo 文档中的Metrics-generator

可选:降低组件系统要求

较小的摄入和查询量允许使用较少的资源。如果您希望降低分配给组件的资源,可以通过容器配置来完成。例如,更改 ingester 的 CPU 和内存资源分配。

要更改资源要求,请按照以下步骤操作

  1. 打开 environments/tempo/main.jsonnet 文件。
  2. 为相应的组件(在本例中是 ingester)添加一个新的配置块
    jsonnet
    tempo_ingester_container+:: {
        resources+: {
            limits+: {
                cpu: '3',
                memory: '5Gi',
            },
            requests+: {
                cpu: '200m',
                memory: '2Gi',
            },
        },
    },
  3. 保存对文件的更改。

注意

降低这些要求可能会影响整体性能。

使用 Tanka 部署 Tempo

  1. 使用 Tanka 命令部署 Tempo
    bash
    tk apply environments/tempo/main.jsonnet

注意

如果在部署 Tempo 后 ingester 未启动,这可能与为预写日志 (Write Ahead Logs) 选择的存储类有关。如果是这种情况,请在 ingester 配置中添加一个适当的存储类。例如,要添加 standard 而不是 fast 存储类,请在上一步的 config(不是 tempo_config)部分中添加以下内容

bash
  ingester+: {
    pvc_storage_class: 'standard',
  },

后续步骤

Tempo 实例现在将通过 distributor 服务在相关端口 distributor.tempo.svc.cluster.local 接受两个已配置的追踪协议(OTLP gRPC 和 Jaeger gRPC)

  • OTLP gRPC: 4317
  • Jaeger gRPC: 14250

您可以使用 query-frontend.tempo.svc.cluster.local 服务在端口 3200 上查询 Tempo,或者在端口 1668616687 上进行 Jaeger 类型查询。

现在您已经配置了一个 Tempo 集群,您需要将数据发送到其中。阅读设置测试应用程序获取说明。