Implementa y usa el recopilador

En este documento, se describe cómo implementar el recopilador de OpenTelemetry, configurarlo para que use el exportador de otlphttp y la API de Telemetry (OTLP), y ejecutar un generador de telemetría para escribir métricas en Cloud Monitoring. Luego, puedes ver estas métricas en Cloud Monitoring.

Si usas Google Kubernetes Engine, puedes seguir OpenTelemetry administrado para GKE en lugar de implementar y configurar manualmente un recopilador de OpenTelemetry que use la API de Telemetry.

Si usas un SDK para enviar métricas de una aplicación directamente a la API de Telemetry, consulta Usa SDKs para enviar métricas de aplicaciones para obtener más información y ejemplos.

También puedes usar un recopilador de OpenTelemetry y la API de Telemetry junto con la instrumentación sin código de OpenTelemetry. Para obtener más información, consulta Cómo usar la instrumentación sin código de OpenTelemetry para Java.

Antes de comenzar

En esta sección, se describe cómo configurar tu entorno para implementar y usar el recopilador.

Selecciona o crea un proyecto de Google Cloud

Elige un Google Cloud proyecto para este recorrido. Si aún no tienes un proyecto Google Cloud , crea uno:

  1. Accede a tu cuenta de Google Cloud . Si eres nuevo en Google Cloud, crea una cuenta para evaluar el rendimiento de nuestros productos en situaciones reales. Los clientes nuevos también obtienen $300 en créditos gratuitos para ejecutar, probar y, además, implementar cargas de trabajo.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. Verify that billing is enabled for your Google Cloud project.

  4. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  5. Verify that billing is enabled for your Google Cloud project.

Instala herramientas de línea de comandos

En este documento, se usan las siguientes herramientas de línea de comandos:

  • gcloud
  • kubectl

Las herramientas gcloud y kubectl forman parte de la CLI de Google Cloud. Para obtener información sobre cómo instalarlos, consulta Administra los componentes de Google Cloud CLI. Para ver los componentes de gcloud CLI que instalaste, ejecuta el siguiente comando:

gcloud components list

Para configurar gcloud CLI para su uso, ejecuta los siguientes comandos:

gcloud auth login
gcloud config set project PROJECT_ID

Habilita las APIs

Habilita la API de Cloud Monitoring y la API de Telemetry en tuGoogle Cloud proyecto. Presta especial atención a la API de Telemetry, telemetry.googleapis.com, ya que es posible que esta sea la primera vez que te encuentras con ella.

Para habilitar las APIs, ejecuta los siguientes comandos:

gcloud services enable monitoring.googleapis.com
gcloud services enable telemetry.googleapis.com

Crea un clúster

Crear un clúster de GKE

  1. Ejecuta el siguiente comando para crear un clúster de Google Kubernetes Engine llamado otlp-test:

    gcloud container clusters create-auto --location CLUSTER_LOCATION otlp-test --project PROJECT_ID
    
  2. Después de crear el clúster, conéctate a él ejecutando el siguiente comando:

    gcloud container clusters get-credentials otlp-test --region CLUSTER_LOCATION --project PROJECT_ID
    

Autoriza la cuenta de servicio de Kubernetes

Los siguientes comandos otorgan los roles de Identity and Access Management (IAM) necesarios a la cuenta de servicio de Kubernetes. En estos comandos, se supone que usas la federación de identidades para cargas de trabajo para GKE:

export PROJECT_NUMBER=$(gcloud projects describe PROJECT_ID --format="value(projectNumber)")

gcloud projects add-iam-policy-binding projects/PROJECT_ID \
  --role=roles/logging.logWriter \
  --member=principal://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/opentelemetry/sa/opentelemetry-collector \
  --condition=None

gcloud projects add-iam-policy-binding projects/PROJECT_ID \
  --role=roles/monitoring.metricWriter \
  --member=principal://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/opentelemetry/sa/opentelemetry-collector \
  --condition=None

gcloud projects add-iam-policy-binding projects/PROJECT_ID \
  --role=roles/telemetry.tracesWriter \
  --member=principal://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/opentelemetry/sa/opentelemetry-collector \
  --condition=None

Si tu cuenta de servicio tiene un formato diferente, puedes usar el comando de la documentación de Google Cloud Managed Service para Prometheus para autorizar la cuenta de servicio con los siguientes cambios:

  • Reemplaza el nombre de la cuenta de servicio gmp-test-sa por tu cuenta de servicio.
  • Otorga los roles que se muestran en el conjunto anterior de comandos, no solo el rol roles/monitoring.metricWriter.

Implementa el recopilador de OpenTelemetry

Para crear la configuración del recopilador, haz una copia del siguiente archivo YAML y colócalo en un archivo llamado collector.yaml. También puedes encontrar la siguiente configuración en GitHub en el repositorio otlp-k8s-ingest.

En tu copia, asegúrate de reemplazar la ocurrencia de ${GOOGLE_CLOUD_PROJECT} por el ID de tu proyecto, PROJECT_ID.

OTLP para las métricas de Prometheus solo funciona cuando se usa la versión 0.140.0 o posterior del recopilador de OpenTelemetry.

# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

exporters:
  # The googlecloud exporter is used for logs
  googlecloud:
    log:
      default_log_name: opentelemetry-collector
    user_agent: Google-Cloud-OTLP manifests:0.4.0 OpenTelemetry Collector Built By Google/0.128.0 (linux/amd64)
  googlemanagedprometheus:
    user_agent: Google-Cloud-OTLP manifests:0.4.0 OpenTelemetry Collector Built By Google/0.128.0 (linux/amd64)
  # The otlphttp exporter is used to send traces to Google Cloud Trace and
  # metrics to Google Managed Prometheus using OTLP http/proto.
  # The otlp exporter could also be used to send them using OTLP grpc
  otlphttp:
    encoding: proto
    endpoint: https://telemetry.googleapis.com
    # Use the googleclientauth extension to authenticate with Google credentials
    auth:
      authenticator: googleclientauth


extensions:
  # Standard for the collector. Used for probes.
  health_check:
    endpoint: ${env:MY_POD_IP}:13133
  # This is an auth extension that adds Google Application Default Credentials to http and gRPC requests.
  googleclientauth:


processors:
  # This filter is a standard part of handling the collector's self-observability metrics. Not related to OTLP ingestion.
  filter/self-metrics:
    metrics:
      include:
        match_type: strict
        metric_names:
        - otelcol_process_uptime
        - otelcol_process_memory_rss
        - otelcol_grpc_io_client_completed_rpcs
        - otelcol_googlecloudmonitoring_point_count

  # The recommended batch size for the OTLP endpoint is 200 metric data points.
  batch:
    send_batch_max_size: 200
    send_batch_size: 200
    timeout: 5s

  # The k8sattributes processor adds k8s resource attributes to metrics based on the source IP that sent the metrics to the collector.
  # k8s attributes are important for avoiding errors from timeseries "collisions".
  # These attributes help distinguish workloads from each other, and provide useful metadata (e.g. namespace) when querying.
  k8sattributes:
    extract:
      metadata:
      - k8s.namespace.name
      - k8s.deployment.name
      - k8s.statefulset.name
      - k8s.daemonset.name
      - k8s.cronjob.name
      - k8s.job.name
      - k8s.replicaset.name
      - k8s.node.name
      - k8s.pod.name
      - k8s.pod.uid
      - k8s.pod.start_time
    passthrough: false
    pod_association:
    - sources:
      - from: resource_attribute
        name: k8s.pod.ip
    - sources:
      - from: resource_attribute
        name: k8s.pod.uid
    - sources:
      - from: connection

  # Standard processor for gracefully degrading when overloaded to prevent OOM.
  memory_limiter:
    check_interval: 1s
    limit_percentage: 65
    spike_limit_percentage: 20

  # Standard processor for enriching self-observability metrics. Unrelated to OTLP ingestion.
  metricstransform/self-metrics:
    transforms:
    - action: update
      include: otelcol_process_uptime
      operations:
      - action: add_label
        new_label: version
        new_value: Google-Cloud-OTLP manifests:0.4.0 OpenTelemetry Collector Built By Google/0.128.0 (linux/amd64)

  # The resourcedetection processor, similar to the k8sattributes processor, enriches metrics with important metadata.
  # The gcp detector provides the cluster name and cluster location.
  resourcedetection:
    detectors: [gcp]
    timeout: 10s

  # This transform processor avoids ingestion errors if metrics contain attributes with names that are reserved for the prometheus_target resource.
  transform/collision:
    metric_statements:
    - context: datapoint
      statements:
      - set(attributes["exported_location"], attributes["location"])
      - delete_key(attributes, "location")
      - set(attributes["exported_cluster"], attributes["cluster"])
      - delete_key(attributes, "cluster")
      - set(attributes["exported_namespace"], attributes["namespace"])
      - delete_key(attributes, "namespace")
      - set(attributes["exported_job"], attributes["job"])
      - delete_key(attributes, "job")
      - set(attributes["exported_instance"], attributes["instance"])
      - delete_key(attributes, "instance")
      - set(attributes["exported_project_id"], attributes["project_id"])
      - delete_key(attributes, "project_id")

  # The relative ordering of statements between ReplicaSet & Deployment and Job & CronJob are important.
  # The ordering of these controllers is decided based on the k8s controller documentation available at
  # https://kubernetes.io/docs/concepts/workloads/controllers.
  # The relative ordering of the other controllers in this list is inconsequential since they directly
  # create pods.
  transform/aco-gke:
    metric_statements:
    - context: datapoint
      statements:
      - set(attributes["top_level_controller_type"], "ReplicaSet") where resource.attributes["k8s.replicaset.name"] != nil
      - set(attributes["top_level_controller_name"], resource.attributes["k8s.replicaset.name"]) where resource.attributes["k8s.replicaset.name"] != nil
      - set(attributes["top_level_controller_type"], "Deployment") where resource.attributes["k8s.deployment.name"] != nil
      - set(attributes["top_level_controller_name"], resource.attributes["k8s.deployment.name"]) where resource.attributes["k8s.deployment.name"] != nil
      - set(attributes["top_level_controller_type"], "DaemonSet") where resource.attributes["k8s.daemonset.name"] != nil
      - set(attributes["top_level_controller_name"], resource.attributes["k8s.daemonset.name"]) where resource.attributes["k8s.daemonset.name"] != nil
      - set(attributes["top_level_controller_type"], "StatefulSet") where resource.attributes["k8s.statefulset.name"] != nil
      - set(attributes["top_level_controller_name"], resource.attributes["k8s.statefulset.name"]) where resource.attributes["k8s.statefulset.name"] != nil
      - set(attributes["top_level_controller_type"], "Job") where resource.attributes["k8s.job.name"] != nil
      - set(attributes["top_level_controller_name"], resource.attributes["k8s.job.name"]) where resource.attributes["k8s.job.name"] != nil
      - set(attributes["top_level_controller_type"], "CronJob") where resource.attributes["k8s.cronjob.name"] != nil
      - set(attributes["top_level_controller_name"], resource.attributes["k8s.cronjob.name"]) where resource.attributes["k8s.cronjob.name"] != nil
  # For each Prometheus unknown-typed metric, which is a gauge, create a counter that is an exact copy of this metric.
  # The GCP OTLP endpoint will add appropriate the appropriate suffixes for the counter and gauge.
  transform/unknown-counter:
    metric_statements:
    - context: metric
      statements:
      # Copy the unknown metric, but add a suffix so we can distinguish the copy from the original.
      - copy_metric(Concat([metric.name, "unknowncounter"], ":")) where metric.metadata["prometheus.type"] == "unknown" and not HasSuffix(metric.name, ":unknowncounter")
      # Change the copy to a monotonic, cumulative sum.
      - convert_gauge_to_sum("cumulative", true) where HasSuffix(metric.name, ":unknowncounter")
      # Delete the extra suffix once we are done.
      - set(metric.name, Substring(metric.name, 0, Len(metric.name)-Len(":unknowncounter"))) where HasSuffix(metric.name, ":unknowncounter")

  # When sending telemetry to the GCP OTLP endpoint, the gcp.project_id resource attribute is required to be set to your project ID.
  resource/gcp_project_id:
    attributes:
    - key: gcp.project_id
      # MAKE SURE YOU REPLACE THIS WITH YOUR PROJECT ID
      value: ${GOOGLE_CLOUD_PROJECT}
      action: insert
  # The metricstarttime processor is important to include if you are using the prometheus receiver to ensure the start time is set properly.
  # It is a no-op otherwise.
  metricstarttime:
    strategy: subtract_initial_point

receivers:
  # This collector is configured to accept OTLP metrics, logs, and traces, and is designed to receive OTLP from workloads running in the cluster.
  otlp:
    protocols:
      grpc:
        endpoint: ${env:MY_POD_IP}:4317
      http:
        cors:
          allowed_origins:
          - http://*
          - https://*
        endpoint: ${env:MY_POD_IP}:4318

  # Push the collector's own self-observability metrics to the otlp receiver.
  otlp/self-metrics:
    protocols:
      grpc:
        endpoint: ${env:MY_POD_IP}:14317

service:
  extensions:
  - health_check
  - googleclientauth
  pipelines:
    # Recieve OTLP logs, and export logs using the googlecloud exporter.
    logs:
      exporters:
      - googlecloud
      processors:
      - k8sattributes
      - resourcedetection
      - memory_limiter
      - batch
      receivers:
      - otlp
    # Recieve OTLP metrics, and export metrics to GMP using the otlphttp exporter.
    metrics/otlp:
      exporters:
      - otlphttp
      processors:
      - k8sattributes
      - memory_limiter
      - resource/gcp_project_id
      - resourcedetection
      - transform/collision
      - transform/aco-gke
      - transform/unknown-counter
      - metricstarttime
      - batch
      receivers:
      - otlp
    # Scrape self-observability Prometheus metrics, and export metrics to GMP using the otlphttp exporter.
    metrics/self-metrics:
      exporters:
      - otlphttp
      processors:
      - filter/self-metrics
      - metricstransform/self-metrics
      - k8sattributes
      - memory_limiter
      - resource/gcp_project_id
      - resourcedetection
      - batch
      receivers:
      - otlp/self-metrics
    # Recieve OTLP traces, and export traces using the otlphttp exporter.
    traces:
      exporters:
      - otlphttp
      processors:
      - k8sattributes
      - memory_limiter
      - resource/gcp_project_id
      - resourcedetection
      - batch
      receivers:
      - otlp
  telemetry:
    logs:
      encoding: json
    metrics:
      readers:
      - periodic:
          exporter:
            otlp:
              protocol: grpc
              endpoint: ${env:MY_POD_IP}:14317

Configura el recopilador de OpenTelemetry implementado

Configura la implementación del recopilador creando recursos de Kubernetes.

  1. Ejecuta los siguientes comandos para crear el espacio de nombres opentelemetry y la configuración del recopilador en el espacio de nombres:

    kubectl create namespace opentelemetry
    
    kubectl create configmap collector-config -n opentelemetry --from-file=collector.yaml
    
  2. Configura el recopilador con recursos de Kubernetes ejecutando los siguientes comandos:

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/otlp-k8s-ingest/refs/heads/otlpmetric/k8s/base/2_rbac.yaml
    
    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/otlp-k8s-ingest/refs/heads/otlpmetric/k8s/base/3_service.yaml
    
    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/otlp-k8s-ingest/refs/heads/otlpmetric/k8s/base/4_deployment.yaml
    
    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/otlp-k8s-ingest/refs/heads/otlpmetric/k8s/base/5_hpa.yaml
    
  3. Espera a que los pods del recopilador alcancen el estado "Running" y tengan 1/1 contenedores listos. Esto tarda alrededor de tres minutos en Autopilot, si es la primera carga de trabajo implementada. Para verificar los pods, usa el siguiente comando:

    kubectl get po -n opentelemetry -w
    

    Para dejar de observar el estado del pod, presiona Ctrl+C para detener el comando.

  4. También puedes consultar los registros del recopilador para asegurarte de que no haya errores evidentes:

    kubectl logs -n opentelemetry deployment/opentelemetry-collector
    

Implementa el generador de telemetría

Puedes probar tu configuración con la herramienta telemetrygen de código abierto. Esta app genera datos de telemetría y los envía al recopilador.

  1. Para implementar la app de telemetrygen en el espacio de nombres opentelemetry-demo, ejecuta el siguiente comando:

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/otlp-k8s-ingest/refs/heads/main/sample/app.yaml
    
  2. Después de crear la implementación, es posible que los pods tarden un tiempo en crearse y comenzar a ejecutarse. Para verificar el estado de los pods, ejecuta el siguiente comando:

    kubectl get po -n opentelemetry-demo -w
    

    Para dejar de observar el estado del pod, presiona Ctrl+C para detener el comando.

Consulta una métrica con el Explorador de métricas

La herramienta telemetrygen escribe en una métrica llamada gen. Puedes consultar esta métrica desde la interfaz del compilador de consultas y el editor de consultas de PromQL en el Explorador de métricas.

En la consola de Google Cloud , accede a la página  Explorador de métricas:

Acceder al Explorador de métricas

Si usas la barra de búsqueda para encontrar esta página, selecciona el resultado cuyo subtítulo es Monitoring.

  • Si usas la interfaz del compilador de consultas del Explorador de métricas, el nombre completo de la métrica es prometheus.googleapis.com/gen/gauge.
  • Si usas el editor de consultas de PromQL, puedes consultar la métrica con el nombre gen.

En la siguiente imagen, se muestra un gráfico de la métrica gen en el Explorador de métricas:

Un gráfico muestra la métrica de generación, capturada por el exportador de otlphttp.

Borra el clúster

Después de verificar la implementación consultando la métrica, puedes borrar el clúster. Para borrar el clúster, ejecuta el siguiente comando:

gcloud container clusters delete --location CLUSTER_LOCATION otlp-test --project PROJECT_ID

¿Qué sigue?