DEV Community

Cover image for Como integrei testes de carga com K6, GitHub Actions e OpenTelemetry
Marcos Vilela
Marcos Vilela

Posted on

Como integrei testes de carga com K6, GitHub Actions e OpenTelemetry

Neste artigo, compartilho minha experiência construindo uma infraestrutura de testes de carga gerida de forma eficiente com GitHub Actions e observável via integração com OpenTelemetry (OTel). O objetivo era garantir que o desempenho da nossa API pudesse ser monitorado facilmente dentro dos pipelines de CI/CD.

O Problema

Precisávamos executar testes de desempenho regularmente contra nossos ambientes de staging e produção sem intervenção manual. Além disso, as métricas geradas por esses testes precisavam ficar visíveis nos nossos dashboards centralizados do Grafana, que usam o Amazon Managed Prometheus (AMP) alimentado por um OpenTelemetry Collector.

Por que o K6?

Escolhi o K6 porque permite escrever testes em JavaScript, tornando-os acessíveis para toda a equipe. É leve, compatível com containers e tem suporte nativo para exportar métricas para OpenTelemetry.

Estrutura do caso de uso

Estruturei o repositório para lidar com diferentes tipos de testes:

  • Smoke Tests: Verificações rápidas de saúde executadas em pull requests.
  • Load Tests: Baselines de desempenho padrão executadas em agendamentos.
  • Stress & Soak Tests: Testes mais agressivos para identificar pontos de ruptura.

Aqui está um exemplo simplificado de como estruturei um teste básico usando checks e thresholds:

import http from 'k6/http';
import { check } from 'k6';

export const options = {
    thresholds: {
        http_req_duration: ['p(95)<2000'], // 95% das requisições devem estar abaixo de 2s
        http_req_failed: ['rate<0.01'],     // Menos de 1% de falha
    },
};

export default function () {
    const res = http.get('https://api.staging.example.com/health');

    check(res, {
        'status é 200': (r) => r.status === 200,
    });
}
Enter fullscreen mode Exit fullscreen mode

Passo 1: Implementação no GitHub Actions

O núcleo da automação fica no GitHub Actions. Criei um workflow que permite execução agendada (cron) e acionamento manual (workflow_dispatch) para ambientes específicos.

Um desafio específico foi garantir que o binário do K6 estivesse corretamente instalado e disponível no PATH. Usar a action oficial grafana/setup-k6-action foi a solução mais confiável.

Aqui está a configuração essencial do arquivo de workflow .github/workflows/load-tests.yml:

name: K6 Load Tests

on:
    schedule:
        - cron: '0 0 * * 5' # Toda sexta-feira à meia-noite
    workflow_dispatch:
        inputs:
            environment:
                type: choice
                options: 
                    - staging
                    - production
            test_type:
                type: choice
                options: 
                    - smoke
                    - load

jobs:
    run-tests:
        runs-on: ubuntu-latest
        steps:
            - uses: actions/checkout@v4

            - name: Setup k6
                uses: grafana/setup-k6-action@v1

            - name: Run K6 Test
                run: k6 run --out opentelemetry tests/${{ inputs.test_type }}/test.js
                env:
                    K6_OTEL_EXPORTER_TYPE: http
                    K6_OTEL_HTTP_EXPORTER_ENDPOINT: ${{ vars.OTEL_COLLECTOR_ENDPOINT }}
Enter fullscreen mode Exit fullscreen mode

Passo 2: Integração com OpenTelemetry

Esta foi a parte mais crítica da configuração. Integrar o K6 com nosso OpenTelemetry Collector exigiu configurações específicas para garantir que as métricas viajassem do runner do GitHub Action para nosso collector e, finalmente, para o Prometheus.

O suporte nativo do K6 ao OTel é excelente, mas nuances de configuração importam.

Configuração do protocolo

Precisei definir explicitamente o tipo do exporter para http porque o collector escuta na porta 4318 para payloads HTTP/OTLP. Por padrão, algumas ferramentas assumem gRPC (porta 4317).

env:
    K6_OTEL_EXPORTER_TYPE: http
    K6_OTEL_HTTP_EXPORTER_ENDPOINT: ${{ vars.OTEL_COLLECTOR_ENDPOINT }}
    K6_OTEL_EXPORTER_INSECURE: true
Enter fullscreen mode Exit fullscreen mode

A variável de endpoint geralmente é algo como seu-domínio.com:4318. O K6 adiciona o protocolo/caminho correto se configurado apropriadamente, mas aprendi que K6_OTEL_HTTP_EXPORTER_ENDPOINT é a variável específica quando o tipo é http, enquanto K6_OTEL_EXPORTER_ENDPOINT costuma ser usada para gRPC ou defaults genéricos.

Atributos de recurso e filtragem

Em um ambiente de observabilidade compartilhado, taguear suas métricas é obrigatório. Nosso collector descarta qualquer métrica que não contenha um client_id específico. Resolvi isso injetando K6_OTEL_RESOURCE_ATTRIBUTES diretamente no pipeline:

K6_OTEL_RESOURCE_ATTRIBUTES: client_id=test3,environment=${{ matrix.environment }},service_name=k6-load-tests
Enter fullscreen mode Exit fullscreen mode

Isso garante que, ao consultar k6_http_req_duration no Grafana, eu possa filtrar exatamente pela execução do teste e ambiente.

Passo 3: Simulação local com Act

Testar workflows do GitHub Actions cometendo e dando push com mensagens "fix ci" é tedioso. Integrei o act para simular o ambiente do GitHub Actions localmente.

Criando um arquivo simples de payload de evento dispatch-event.json, pude verificar o comportamento exato da injeção de variáveis de ambiente e da execução do comando K6 sem sair do terminal:

act workflow_dispatch -e .github/dispatch-event.json -W .github/workflows/load-tests.yml
Enter fullscreen mode Exit fullscreen mode

Isso economizou horas de depuração, especialmente ao ajustar as variáveis de ambiente do OTel.

Conclusão

Ao combinar K6, GitHub Actions e OpenTelemetry, implementei um sistema onde o desempenho é monitorado como a saúde da aplicação.

  • Automação: Não há mais execução manual dos testes de carga.
  • Visibilidade: Métricas estão no mesmo dashboard que as métricas da aplicação.
  • Depuração: Testes locais com act garantem que o pipeline permaneça estável.

Se for montar testes de carga, recomendo priorizar o aspecto de observabilidade desde cedo. Ver gráficos em tempo real de Virtual Users (VUs) e Duração de Requisições ao lado do uso de CPU do servidor oferece insights que um relatório local isolado nunca proporciona.

Top comments (0)