菜单
文档breadcrumb arrow Beylabreadcrumb arrow 设置breadcrumb arrow Kubernetes
Grafana Cloud

在 Kubernetes 中部署 Beyla

注意

本文档介绍了如何在 Kubernetes 中手动部署 Beyla,并自行设置所有必需的实体。

您可能更倾向于遵循使用 Helm 在 Kubernetes 中部署 Beyla 文档。

目录

配置 Kubernetes 元数据装饰

Beyla 可以使用以下 Kubernetes 标签装饰您的链路追踪

  • k8s.namespace.name
  • k8s.deployment.name
  • k8s.statefulset.name
  • k8s.replicaset.name
  • k8s.daemonset.name
  • k8s.node.name
  • k8s.pod.name
  • k8s.container.name
  • k8s.pod.uid
  • k8s.pod.start_time
  • k8s.cluster.name

要启用元数据装饰,您需要

  • 创建一个 ServiceAccount 并绑定一个 ClusterRole,授予对 Pods 和 ReplicaSets 的列表和监视权限。您可以通过部署以下示例文件来实现
yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: beyla
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: beyla
rules:
  - apiGroups: [ "apps" ]
    resources: [ "replicasets" ]
    verbs: [ "list", "watch" ]
  - apiGroups: [ "" ]
    resources: [ "pods", "services", "nodes" ]
    verbs: [ "list", "watch" ]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: beyla
subjects:
  - kind: ServiceAccount
    name: beyla
    namespace: default
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: beyla

(如果您在其他命名空间中部署 Beyla,则需要更改 namespace: default 的值)。

  1. 使用 BEYLA_KUBE_METADATA_ENABLE=true 环境变量配置 Beyla,或在 YAML 配置中使用 attributes.kubernetes.enable: true

  2. 请不要忘记在您的 Beyla Pod 中指定 serviceAccountName: beyla 属性(如后面的部署示例所示)。

(可选)在 YAML 配置文件的 discovery -> services 部分选择要插桩哪些 Kubernetes 服务。更多信息请参阅配置文档中的 *Service discovery*(服务发现)部分,以及本页的提供外部配置文件部分。

部署 Beyla

您可以通过两种不同的方式在 Kubernetes 中部署 Beyla

  • 作为边车容器
  • 作为 DaemonSet

将 Beyla 作为边车容器部署

如果您想监控某个可能未部署在所有主机上的特定服务,则可以按此方式部署 Beyla,这样您只需为每个服务实例部署一个 Beyla 实例。

将 Beyla 作为边车容器部署有以下配置要求

  • Pod 中的所有容器必须共享进程命名空间(shareProcessNamespace: true pod 变量)
  • 自动插桩容器必须在特权模式下运行(容器配置的 securityContext.privileged: true 属性)。
    • 某些 Kubernetes 安装允许以下 securityContext 配置,但它可能无法与所有容器运行时配置一起使用,因为其中一些配置会限制容器并移除部分权限
      yaml
      securityContext:
        runAsUser: 0
        capabilities:
          add:
            - SYS_ADMIN
            - SYS_RESOURCE # not required for kernels 5.11+

以下示例通过将 Beyla 作为容器附加(镜像位于 grafana/beyla:latest)来对 goblog Pod 进行插桩。自动插桩工具配置为将指标和链路追踪转发到 Grafana Alloy,该服务在同一命名空间中可通过 grafana-alloy 服务访问

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: goblog
  labels:
    app: goblog
spec:
  replicas: 2
  selector:
    matchLabels:
      app: goblog
  template:
    metadata:
      labels:
        app: goblog
    spec:
      # Required so the sidecar instrument tool can access the service process
      shareProcessNamespace: true
      serviceAccountName: beyla # required if you want kubernetes metadata decoration
      containers:
        # Container for the instrumented service
        - name: goblog
          image: mariomac/goblog:dev
          imagePullPolicy: IfNotPresent
          command: ["/goblog"]
          ports:
            - containerPort: 8443
              name: https
        # Sidecar container with Beyla - the eBPF auto-instrumentation tool
        - name: beyla
          image: grafana/beyla:latest
          securityContext: # Privileges are required to install the eBPF probes
            privileged: true
          env:
            # The internal port of the goblog application container
            - name: BEYLA_OPEN_PORT
              value: "8443"
            - name: OTEL_EXPORTER_OTLP_ENDPOINT
              value: "http://grafana-alloy:4318"
              # required if you want kubernetes metadata decoration
            - name: BEYLA_KUBE_METADATA_ENABLE
              value: "true"

有关不同配置选项的更多信息,请查阅本文档站点的配置部分。

将 Beyla 作为 DaemonSet 部署

您还可以将 Beyla 作为 Daemonset 部署。如果出现以下情况,这是首选方式

  • 您想对 Daemonset 进行插桩
  • 您想从单个 Beyla 实例插桩多个进程,甚至插桩集群中的所有进程。

以上面的示例 (goblog Pod) 为例,我们无法通过其开放端口选择要插桩的进程,因为该端口对 Pod 内部开放。同时,该服务的多个实例将具有不同的开放端口。在这种情况下,我们需要使用应用程序服务可执行文件的名称进行插桩(参见后面的示例)。

除了边车方案的特权要求外,您还需要在自动插桩 Pod 模板中启用 hostPID: true 选项,以便它可以访问在同一主机上运行的所有进程。

yaml
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: beyla
  labels:
    app: beyla
spec:
  selector:
    matchLabels:
      app: beyla
  template:
    metadata:
      labels:
        app: beyla
    spec:
      hostPID: true # Required to access the processes on the host
      serviceAccountName: beyla # required if you want kubernetes metadata decoration
      containers:
        - name: autoinstrument
          image: grafana/beyla:latest
          securityContext:
            privileged: true
          env:
            # Select the executable by its name instead of BEYLA_OPEN_PORT
            - name: BEYLA_EXECUTABLE_NAME
              value: "goblog"
            - name: OTEL_EXPORTER_OTLP_ENDPOINT
              value: "http://grafana-alloy:4318"
              # required if you want kubernetes metadata decoration
            - name: BEYLA_KUBE_METADATA_ENABLE
              value: "true"

在非特权模式下部署 Beyla

到目前为止的所有示例中,Beyla 部署的 securityContext 部分都使用了 privileged:trueSYS_ADMIN Linux 能力。虽然这在所有情况下都适用,但如果您的安全配置要求如此,也有办法在降低特权的情况下在 Kubernetes 中部署 Beyla。这是否可能取决于您使用的 Kubernetes 版本以及底层的容器运行时(例如 ContainerdCRI-ODocker)。

以下指南主要基于使用 containerd 运行 GKEkubeadmk3smicrok8skind 执行的测试。

要在非特权模式下运行 Beyla,您需要将 privileged:true 设置替换为一组 Linux 能力。Beyla 所需能力的完整列表可在安全性、权限和能力中找到。

注意 加载 BPF 程序需要 Beyla 能够读取 Linux 性能事件,或者至少能够执行 Linux 内核 API perf_event_open()

此权限由 CAP_PERFMON 授予,或通过 CAP_SYS_ADMIN 更宽松地授予。由于 CAP_PERFMONCAP_SYS_ADMIN 都授予 Beyla 读取性能事件的权限,您应该使用 CAP_PERFMON,因为它授予的权限较少。但是,在系统级别,对性能事件的访问是通过设置 kernel.perf_event_paranoid 控制的,您可以使用 sysctl 或修改文件 /proc/sys/kernel/perf_event_paranoid 来读取或写入此设置。kernel.perf_event_paranoid 的默认设置通常为 2,这在内核文档perf_event_paranoid 部分中有记录。一些 Linux 发行版为 kernel.perf_event_paranoid 定义了更高的级别,例如基于 Debian 的发行版也使用 kernel.perf_event_paranoid=3,这在没有 CAP_SYS_ADMIN 的情况下禁止访问 perf_event_open()。如果您正在运行 kernel.perf_event_paranoid 设置高于 2 的发行版,您可以修改配置将其降低到 2,或使用 CAP_SYS_ADMIN 代替 CAP_PERFMON

下面是 Beyla 非特权容器配置示例,您也可以下载完整的示例部署文件

yaml
...
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: beyla
  namespace: beyla-demo
  labels:
    k8s-app: beyla
spec:
  selector:
    matchLabels:
      k8s-app: beyla
  template:
    metadata:
      labels:
        k8s-app: beyla
    spec:
      serviceAccount: beyla
      hostPID: true           # <-- Important. Required in Daemonset mode so Beyla can discover all monitored processes
      containers:
      - name: beyla
        terminationMessagePolicy: FallbackToLogsOnError
        image: grafana/beyla:latest
        env:
          - name: BEYLA_TRACE_PRINTER
            value: "text"
          - name: BEYLA_KUBE_METADATA_ENABLE
            value: "autodetect"
          - name: KUBE_NAMESPACE
            valueFrom:
              fieldRef:
                fieldPath: metadata.namespace
          ...
        securityContext:
          runAsUser: 0
          readOnlyRootFilesystem: true
          capabilities:
            add:
              - BPF                 # <-- Important. Required for most eBPF probes to function correctly.
              - SYS_PTRACE          # <-- Important. Allows Beyla to access the container namespaces and inspect executables.
              - NET_RAW             # <-- Important. Allows Beyla to use socket filters for http requests.
              - CHECKPOINT_RESTORE  # <-- Important. Allows Beyla to open ELF files.
              - DAC_READ_SEARCH     # <-- Important. Allows Beyla to open ELF files.
              - PERFMON             # <-- Important. Allows Beyla to load BPF programs.
              #- SYS_RESOURCE       # <-- pre 5.11 only. Allows Beyla to increase the amount of locked memory.
              #- SYS_ADMIN          # <-- Required for Go application trace context propagation, or if kernel.perf_event_paranoid >= 3 on Debian distributions.
            drop:
              - ALL
        volumeMounts:
        - name: var-run-beyla
          mountPath: /var/run/beyla
        - name: cgroup
          mountPath: /sys/fs/cgroup
      tolerations:
      - effect: NoSchedule
        operator: Exists
      - effect: NoExecute
        operator: Exists
      volumes:
      - name: var-run-beyla
        emptyDir: {}
      - name: cgroup
        hostPath:
          path: /sys/fs/cgroup
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: some-service
  namespace: beyla-demo
  ...
---

提供外部配置文件

在前面的示例中,Beyla 是通过环境变量配置的。但是,您也可以通过外部 YAML 文件进行配置(如本站点的配置部分所述)。

要将配置作为文件提供,推荐的方法是使用所需配置部署一个 ConfigMap,然后将其挂载到 Beyla Pod 中,并通过 BEYLA_CONFIG_PATH 环境变量引用它。

包含 Beyla YAML 文档的 ConfigMap 示例

yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: beyla-config
data:
  beyla-config.yml: |
    trace_printer: text
    grafana:
      otlp:
        submit: ["metrics","traces"]
    otel_traces_export:
      sampler:
        name: parentbased_traceidratio
        arg: "0.01"
    routes:
      patterns:
        - /factorial/{num}

Beyla DaemonSet 配置示例,挂载并访问之前的 ConfigMap

yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: beyla
spec:
  selector:
    matchLabels:
      instrumentation: beyla
  template:
    metadata:
      labels:
        instrumentation: beyla
    spec:
      serviceAccountName: beyla
      hostPID: true #important!
      containers:
        - name: beyla
          image: grafana/beyla:latest
          imagePullPolicy: IfNotPresent
          securityContext:
            privileged: true
            readOnlyRootFilesystem: true
          # mount the previous ConfigMap as a folder
          volumeMounts:
            - mountPath: /config
              name: beyla-config
            - mountPath: /var/run/beyla
              name: var-run-beyla
          env:
            # tell beyla where to find the configuration file
            - name: BEYLA_CONFIG_PATH
              value: "/config/beyla-config.yml"
      volumes:
        - name: beyla-config
          configMap:
            name: beyla-config
        - name: var-run-beyla
          emptyDir: {}

提供秘密配置

上面的示例适用于常规配置,但不应用于传递密码或 API 密钥等秘密信息。

要提供秘密信息,推荐的方法是部署一个 Kubernetes Secret。例如,这个 Secret 包含一些虚构的 Grafana Cloud 凭据

yaml
apiVersion: v1
kind: Secret
metadata:
  name: grafana-secret
type: Opaque
stringData:
  grafana-user: "123456"
  grafana-api-key: "xxxxxxxxxxxxxxx"

然后您可以将 Secret 值作为环境变量访问。按照前面的 DaemonSet 示例,这可以通过向 Beyla 容器添加以下 env 部分来实现。

yaml
env:
  - name: GRAFANA_CLOUD_ZONE
    value: prod-eu-west-0
  - name: GRAFANA_CLOUD_INSTANCE_ID
    valueFrom:
      secretKeyRef:
        key: grafana-user
        name: grafana-secret
  - name: GRAFANA_CLOUD_API_KEY
    valueFrom:
      secretKeyRef:
        key: grafana-api-key
        name: grafana-secret