Help build the future of open source observability software Open positions

Check out the open source projects we support Downloads

We cannot remember your choice unless you click the consent notice at the bottom.

Lançamento do Grafana Beyla 1.2: autoinstrumentação eBPF com suporte completo ao Kubernetes

Lançamento do Grafana Beyla 1.2: autoinstrumentação eBPF com suporte completo ao Kubernetes

2024-01-24 9 min

Estamos entusiasmados em anunciar que, com o lançamento do Grafana Beyla 1.2, o suporte ao Kubernetes agora está totalmente integrado.

Com esta atualização, a configuração do Grafana Beyla agora “entende” a semântica do Kubernetes para fornecer uma seleção mais detalhada de serviços para instrumentar. Os usuários do Beyla podem decorar métricas e rastros com os metadados de entidades do Kubernetes, como pods e deployments, que executam os serviços instrumentados automaticamente. Antes do lançamento do Beyla 1.2, os usuários que queriam enriquecer suas métricas e rastros com metadados do Kubernetes tinham que configurar um coletor OpenTelemetry intermediário. No geral, esta atualização permite uma experiência mais rica ao visualizar e consultar suas métricas e rastros.

Ao mesmo tempo, DaemonSet se tornou o modo de implantação preferido para o Beyla. Graças à versatilidade dos novos seletores de serviço, um usuário pode definir precisamente quais serviços precisam ser instrumentados e quais não. Uma única instância do Beyla será capaz de instrumentar o grupo selecionado de serviços dentro de um único nó do Kubernetes.

Neste post, vamos dar uma olhada mais de perto nessas novas funcionalidades e como usá-las para selecionar quais serviços autoinstrumentar com base em seus atributos do Kubernetes. Também mostraremos como seus rastros são decorados com os metadados das entidades do Kubernetes.

Observação: Para saber mais sobre o Grafana Beyla 1.2, você pode conferir nossa documentação técnica do Beyla e notas de lançamento.

Seletores de serviço Beyla

Um seletor de serviço é um conjunto de propriedades que indica à Beyla quais processos devem ser instrumentados.

Quando a Beyla é implantada como um processo do sistema operacional regular que instrumenta outros processos, os seletores de serviço únicos são a porta de rede na qual o processo instrumentado está ouvindo (que pode ser especificada com a variável de ambiente BEYLA_OPEN_PORT), ou uma expressão regular para combinar com o nome do arquivo executável do processo a ser instrumentado (BEYLA_EXECUTABLE_NAME variável de ambiente).

Para selecionar múltiplos grupos de processos, o formato de arquivo de configuração YAML da Beyla fornece uma seção discovery.services, que aceita múltiplos grupos de seletores:

yaml
discovery:
  services:
    # Instrumentar qualquer processo usando as portas de 8080 a 8089
    - open_ports: 8080-8089
    # Instrumentar qualquer processo cujo executável contenha "http"
    - exe_path: "http"
    # Instrumentar qualquer processo com um executável contendo "nginx"
    # e usando a porta 443 (ambas as condições devem ser cumpridas)
    - open_ports: 443
      exe_path: "nginx"

Os critérios acima são insuficientes para pods do Kubernetes, onde frequentemente as portas de serviço são efêmeras e internas aos pods. Além disso, os pods do Kubernetes envolvem um nível de abstração que geralmente oculta detalhes, como o nome dos executáveis ​​do serviço. Beyla 1.2 está totalmente preparada para Kubernetes e introduz critérios de seleção de serviço específicos do Kubernetes. Todos os seguintes novos critérios de seleção aceitam uma expressão regular da sintaxe Go RE2 como valor:

  • k8s_namespace: somente instrumentar aplicativos no namespace que corresponda à expressão regular fornecida.
  • k8s_deployment_name: somente instrumentar pods que pertencem a um deployment com um nome que corresponda à expressão regular fornecida.
  • k8s_replicaset_name: somente instrumentar pods que pertencem a um ReplicaSet com um nome que corresponda à expressão regular fornecida.
  • k8s_pod_name: somente instrumentar pods com um nome que corresponda à expressão regular fornecida.

Cenário de exemplo

1. Implementar serviços instrumentáveis

Você pode instrumentar qualquer serviço HTTP ou HTTPS em seu cluster Kubernetes. Se preferir, você pode começar experimentando a instrumentação dos serviços fictícios fornecidos neste exemplo.

O seguinte arquivo de exemplo Kubernetes contém dois servidores Apache HTTP: um finge ser o site de uma empresa website e o outro finge ser um site de documentação (docs). Ambos os servidores apenas retornarão a string “It Works!” quando o diretório raiz for solicitado, e um erro 404 se qualquer outro caminho for solicitado.

Copie o conteúdo a seguir em um arquivo (por exemplo, sampleapps.yml) e implante-o com o comando kubectl apply -f sampleapps.yml.

yaml
kind: Deployment
apiVersion: apps/v1
metadata:
  name: docs
spec:
  replicas: 2
  selector:
    matchLabels:
      app: docs
  template:
    metadata:
      labels:
        app: docs
    spec:
      containers:
        - name: docs-server
          image: httpd:latest
          ports:
            - containerPort: 80
              protocol: TCP
              name: http
---
apiVersion: v1
kind: Service
metadata:
  name: docs
spec:
  selector:
    app: docs
  ports:
    - protocol: TCP
      port: 80
---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: website
spec:
  replicas: 2
  selector:
    matchLabels:
      app: website
  template:
    metadata:
      labels:
        app: website
    spec:
      containers:
        - name: website-server
          image: httpd:latest
          ports:
            - containerPort: 80
              protocol: TCP
              name: http
---
apiVersion: v1
kind: Service
metadata:
  name: website
spec:
  selector:
    app: website
  ports:
    - protocol: TCP
      port: 80

Para testar se os serviços estão ativos e funcionando, abra duas sessões de terminal e execute um de cada comando abaixo em uma sessão diferente:

# Redirecione o site para a porta local 8080
kubectl port-forward services/website 8080:80
# Redirecione o site de documentação para a porta local 8081
kubectl port-forward services/docs 8081:80

Do seu computador, cada solicitação para http://localhost:8080 será uma solicitação hipotética ao site da empresa e cada solicitação para http://localhost:8081 será uma solicitação hipotética ao site de documentação. Você pode usar um simples comando curl para as URLs acima para verificar que seus serviços estão ativos e funcionando.

2. Crie um namespace beyla

Antes de configurar e implantar a Beyla, vamos criar um namespace beyla. Usaremos ele para agrupar todas as permissões necessárias, configurações e opções de implantação:

kubectl create namespace beyla

3. Obtenha as credenciais do Grafana Cloud

A Beyla pode exportar métricas e rastros para qualquer endpoint OpenTelemetry, bem como expor métricas como um endpoint Prometheus. Confira nossa documentação para mais informações sobre como selecionar os diferentes protocolos de exposição.

Neste post do blog, usaremos o endpoint OpenTelemetry no Grafana Cloud para começar o mais rápido possível. (Se você ainda não tem o Grafana Cloud, pode inscrever-se para uma conta gratuita hoje.)

No portal do Grafana Cloud, procure pela caixa OpenTelemetry e clique em Configurar.

A caixa OpenTelemetry no Grafana Cloud.

Em Senha/Token da API, clique em Gerar agora e siga as instruções para criar um token da API padrão.

As Variáveis de Ambiente serão preenchidas com um conjunto de variáveis de ambiente OpenTelemetry padrão, que fornecerão as informações de endpoint de conexão e credenciais para a Beyla.

Token da API Grafana Cloud e Variáveis de Ambiente.

Na seção Variáveis de Ambiente, copie os valores OTEL_EXPORTER_OTLP_ENDPOINT e OTEL_EXPORTER_OTLP_HEADERS e crie um novo segredo com eles. Por exemplo, crie o seguinte arquivo secret e aplique-o:

yaml
apiVersion: v1
kind: Secret
metadata:
  namespace: beyla
  name: grafana-credentials
type: Opaque
stringData:
  otlp-endpoint: "https://otlp-gateway-prod-eu-west-0.grafana.net/otlp"
  otlp-headers: "Authorization=Basic ...restante do valor do cabeçalho secreto..."

4. Configure e execute Beyla

A seguir, você precisa fornecer ao Beyla permissões para observar e inspecionar os metadados dos diversos recursos do Kubernetes, requisitos do mecanismo de descoberta do Beyla. Para isso, crie e aplique o seguinte arquivo YAML:

yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  namespace: beyla
  name: beyla
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: beyla
rules:
  - apiGroups: ["apps"]
    resources: ["replicasets"]
    verbs: ["list", "watch"]
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: beyla
subjects:
  - kind: ServiceAccount
    name: beyla
    namespace: beyla
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: beyla

E agora, implante Beyla criando as seguintes entidades Kubernetes:

  • Um ConfigMap armazenado no arquivo de configuração beyla-config.yml, que define os critérios de descoberta de serviço. Para garantir que o Beyla seja capaz de discriminar por instância de serviço, mesmo que as instâncias executem a mesma imagem e executável, o Beyla é configurado para selecionar APENAS o servidor web Apache docs.

  • Um DaemonSet do Beyla, que fornece o pod do Beyla e sua configuração:

    • Carrega o arquivo beyla-config.yml a partir do ConfigMap, conforme especificado em BEYLA_CONFIG_PATH.
    • Referencia os valores de grafana-secrets para o endpoint e credenciais.
    • Utiliza a ServiceAccount do Beyla para obter todas as permissões.

Copie e faça o deploy do seguinte arquivo YAML:

yaml
apiVersion: v1
kind: ConfigMap
metadata:
  namespace: beyla
  name: beyla-config
data:
  beyla-config.yml: |
    # isso é necessário para habilitar a descoberta e metadados do Kubernetes
    attributes:
      kubernetes:
        enable: true
    # isso irá fornecer relatório automático de rotas minimizando a cardinalidade
    routes:
      unmatched: heuristic
    # vamos instrumentar apenas o servidor de documentação
    discovery:
      services:
        - k8s_deployment_name: "^docs$"
        # descomente a linha seguinte para também instrumentar o servidor do site
        # - k8s_deployment_name: "^website$"
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  namespace: beyla
  name: beyla
spec:
  selector:
    matchLabels:
      instrumentation: beyla
  template:
    metadata:
      labels:
        instrumentation: beyla
    spec:
      serviceAccountName: beyla
      hostPID: true # obrigatório!
      volumes:
        - name: beyla-config
          configMap:
            name: beyla-config
      containers:
        - name: beyla
          image: grafana/beyla:1.2
          securityContext:
            privileged: true # obrigatório!
          volumeMounts:
            - mountPath: /config
              name: beyla-config
          env:
            - name: BEYLA_CONFIG_PATH
              value: /config/beyla-config.yml
            - name: OTEL_EXPORTER_OTLP_ENDPOINT
              valueFrom:
                secretKeyRef:
                  name: grafana-credentials
                  key: otlp-endpoint
            - name: OTEL_EXPORTER_OTLP_HEADERS
              valueFrom:
                secretKeyRef:
                  name: grafana-credentials
                  key: otlp-headers

Algumas notas importantes:

  • Para funcionar no modo DaemonSet, o Beyla precisa acessar todos os processos no nó. É por isso que o pod do Beyla precisa ser executado com hostPID: true.
  • O container do Beyla precisa ser executado como privileged: true para que possa executar ações privilegiadas, como carregar programas eBPF e criar mapas eBPF.

5. Teste seus serviços instrumentados e veja os resultados no Grafana

Com os comandos kubectl port-forward do primeiro passo ainda em execução, teste ambas as instâncias do servidor web. Por exemplo:

curl http://localhost:8080
curl http://localhost:8080/foo
curl http://localhost:8081
curl http://localhost:8081/foo

Alguns pedidos retornarão um erro 404, mas tudo bem porque esses pedidos também estão instrumentados.

Agora, vá para a instância na Grafana Cloud e, na seção Explore no painel esquerdo, selecione a fonte de dados para os rastros (geralmente nomeada grafanacloud-<seu nome de usuário>-traces).

Selecione a fonte de dados para os rastros na seção Explore.

Para procurar todos os rastros, selecione a caixa Search na barra de Query, deixe o formulário vazio e clique Run query:

Selecione Run query para procurar todos os rastros.

Isso mostrará os rastros para a instância docs (porta 8081). Você pode ver rastros dos seus próprios serviços, mas não deve ver rastros do serviço website, pois ele não foi instrumentado pelo Beyla.

Rastros para a instância docs.

Se você expandir os detalhes do rastro, também verá que os atributos de recurso nos rastros são decorados com os metadados do pod do Kubernetes executando o serviço instrumentado. Os atributos de rastro do Kubernetes são todos prefixados com k8s, como visto no exemplo abaixo:

Atributos de rastro do Kubernetes.

Grafana Beyla 1.2: considerações finais

Enquanto Beyla 1.0 era funcional com Kubernetes, os primeiros usuários pediram por melhores mecanismos de integração para suavizar as operações — e foi isso que objetivamos entregar com o Beyla 1.2.

Com os seletores de atributos do Kubernetes integrados, os usuários do Beyla agora podem selecionar precisamente quais pods instrumentar sem precisar especificar detalhes de baixo nível, como nomes de processos ou faixas de portas.

Além disso, a decoração de métricas e rastros com metadados do Kubernetes permite uma melhor identificação das aplicações instrumentadas, já que agora você pode agrupá-las por pod e implantação. No geral, o Grafana Beyla 1.2 representa um grande avanço na simplificação de sua implantação.

Para saber mais sobre o suporte ao Kubernetes no Grafana Beyla 1.2, você pode consultar nossa documentação sobre opções de configuração do Beyla e executando o Beyla como Kubernetes DaemonSet.