Implantar o rastreamento distribuído para observar a latência do microsserviço

Last reviewed 2023-08-11 UTC

Neste documento, mostramos como implantar a arquitetura de referência descrita em Usar rastreamento distribuído para observar a latência do microsserviço. A implantação ilustrada neste documento captura informações de trace em aplicativos de microsserviço usando o OpenTelemetry e o Cloud Trace.

O aplicativo de amostra nesta implantação é composto por dois microsserviços escritos em Go.

Ele pressupõe que você esteja familiarizado com os seguintes produtos:

Objetivos

  • Criar um cluster do GKE e implante um aplicativo de amostra.
  • Revise o código de instrumentação do OpenTelemetry.
  • Revisar os traces e registros gerados pela instrumentação.

Arquitetura

O diagrama a seguir mostra a arquitetura implantada.

Arquitetura do tutorial com dois clusters do GKE.

Use o Cloud Build, uma plataforma de integração contínua, entrega e implantação totalmente gerenciada, para criar imagens de contêiner a partir do código de amostra e armazená-las no Artifact Registry. Os clusters do GKE extraem as imagens do Container Registry no momento da implantação.

O serviço de front-end aceita solicitações HTTP no URL / e chama o serviço de back-end. O endereço do serviço de back-end é definido pela variável de ambiente .

O serviço de back-end aceita solicitações HTTP no URL / e faz uma chamada de saída para um URL externo, conforme definido na variável de ambiente . Após a conclusão da chamada externa, o serviço de back-end retorna a chamada de status HTTP (por exemplo, 200) ao autor da chamada.

Custos

Neste documento, você usará os seguintes componentes faturáveis do Google Cloud:

Para gerar uma estimativa de custo baseada na projeção de uso deste tutorial, use a calculadora de preços. Novos usuários do Google Cloud podem estar qualificados para uma avaliação gratuita.

Ao concluir as tarefas descritas neste documento, é possível evitar o faturamento contínuo excluindo os recursos criados. Saiba mais em Limpeza.

Antes de começar

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Google Cloud project.

  4. Enable the GKE, Cloud Trace, Cloud Build, Cloud Storage, and Artifact Registry APIs.

    Enable the APIs

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

    Go to project selector

  6. Make sure that billing is enabled for your Google Cloud project.

  7. Enable the GKE, Cloud Trace, Cloud Build, Cloud Storage, and Artifact Registry APIs.

    Enable the APIs

Configure seu ambiente

Nesta seção, você configurará seu ambiente com as ferramentas usadas em toda a implantação. Todos os comandos de terminal neste tutorial são executados pelo Cloud Shell.

  1. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

    At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

  2. Defina uma variável de ambiente como o ID do seu projeto do Google Cloud:
    export PROJECT_ID=$(gcloud config list --format 'value(core.project)' 2>/dev/null)
    
  3. Faça o download dos arquivos necessários para esta implantação clonando o repositório Git associado:
    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples.git
    cd kubernetes-engine-samples/observability/distributed-tracing
    WORKDIR=$(pwd)
    

    Você torna a pasta do repositório no diretório de trabalho ($WORKDIR) em que estão todas as tarefas relacionadas a essa implantação. Dessa forma, se não quiser manter os recursos, exclua a pasta quando terminar a implantação.

Instalar ferramentas

  1. No Cloud Shell, instale kubectx e kubens.

    git clone https://github.com/ahmetb/kubectx $WORKDIR/kubectx
    export PATH=$PATH:$WORKDIR/kubectx
    

    Use essas ferramentas para trabalhar com vários clusters, contextos e namespaces do Kubernetes.

  2. No Cloud Shell, instale o Apache Database, uma ferramenta de geração de carga de código aberto:

    sudo apt-get install apache2-utils
    

Crie um repositório do Docker

Crie um repositório do Docker para armazenar a imagem de amostra deste guia de início rápido.

Console

  1. No Console do Google Cloud, abra a página Repositórios.

    Abrir a página Repositórios

  2. Clique em Criar repositório.

  3. Especifique distributed-tracing-docker-repo como o nome do repositório.

  4. Escolha Docker como o formato e Standard como o modo.

  5. Em Tipo de local, selecione Região e escolha o local us-west1.

  6. Clique em Criar.

O repositório é adicionado à lista de repositórios.

gcloud

  1. No Cloud Shell, crie um novo repositório do Docker chamado distributed-tracing-docker-repo no local us-west1 com a descrição docker repository:

    gcloud artifacts repositories create distributed-tracing-docker-repo --repository-format=docker \
    --location=us-west1 --description="Docker repository for distributed tracing deployment"
    
  2. Verifique se o repositório foi criado:

    gcloud artifacts repositories list
    

Criar clusters do GKE

Nesta seção, você criará dois clusters do GKE em que implantará o aplicativo de amostra. Por padrão, os clusters do GKE são criados com acesso somente gravação à API Cloud Trace. Portanto, não é necessário definir o acesso ao criar os clusters.

  1. No Cloud Shell, crie os clusters:

    gcloud container clusters create backend-cluster \
        --zone=us-west1-a \
        --verbosity=none --async
    
    gcloud container clusters create frontend-cluster \
        --zone=us-west1-a \
        --verbosity=none
    

    Neste tutorial, os clusters estão na zona us-west1-a. Para mais informações, consulte Geografia e regiões.

  2. Consiga as credenciais do cluster e armazene-as localmente:

    gcloud container clusters get-credentials backend-cluster --zone=us-west1-a
    gcloud container clusters get-credentials frontend-cluster --zone=us-west1-a
    
  3. Renomeie os contextos dos clusters para facilitar o acesso a eles posteriormente na implantação:

    kubectx backend=gke_${PROJECT_ID}_us-west1-a_backend-cluster
    kubectx frontend=gke_${PROJECT_ID}_us-west1-a_frontend-cluster
    

Revisar a instrumentação do OpenTelemetry

Nas seções a seguir, analise o código do arquivo main.go no aplicativo de amostra. Isso ajuda você a aprender como usar a propagação de contexto para permitir que períodos de várias solicitações sejam anexados a um único trace pai.

Analisar as importações no código do aplicativo

import (
	"context"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"strconv"

	cloudtrace "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace"
	"github.com/gorilla/mux"
	"go.opentelemetry.io/contrib/detectors/gcp"
	"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
	"go.opentelemetry.io/contrib/propagators/autoprop"
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/sdk/resource"
	"go.opentelemetry.io/otel/sdk/trace"
)

Observe o seguinte sobre as importações:

  • O pacote go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp contém o plug-in otelhttp, que pode instrumentar um servidor HTTP ou cliente HTTP. A instrumentação do servidor recupera o contexto de período da solicitação HTTP e registra um span para o processamento da solicitação pelo servidor. A instrumentação do cliente injeta o contexto do período na solicitação HTTP de saída e registra um período pelo tempo gasto na espera por uma resposta.
  • O pacote go.opentelemetry.io/contrib/propagators/autoprop fornece uma implementação da interface TextMapPropagator do OpenTelemetry, que é usada pelo otelhttp para processar a propagação. Os propagadores determinam o formato e as chaves usados para armazenar o contexto de rastreamento em transportes como HTTP. Especificamente, otelhttp transmite cabeçalhos HTTP para o propagador. O propagador extrai um contexto de período em um contexto do Go dos cabeçalhos ou codifica e injeta um contexto de período no contexto do Go em cabeçalhos (dependendo se é cliente ou servidor). Por padrão, o pacote autoprop injeta e extrai o contexto do período usando o formato de propagação contexto de rastreamento W3C.
  • A importação github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace exporta traces para o Trace.
  • A importação github.com/gorilla/mux é a biblioteca que o app de amostra usa para processar solicitações.
  • A importação go.opentelemetry.io/contrib/detectors/gcp adiciona atributos a períodos, como cloud.availability_zone, que identificam onde o aplicativo está sendo executado no Google Cloud.
  • As importações go.opentelemetry.io/otel, go.opentelemetry.io/otel/sdk/trace e go.opentelemetry.io/otel/sdk/resource usadas para configurar o OpenTelemetry.

Revise a função main

A função main configura a exportação de trace para o Cloud Trace e usa um roteador mux para processar solicitações feitas ao URL /.

func main() {
	ctx := context.Background()
	// Set up the Cloud Trace exporter.
	exporter, err := cloudtrace.New()
	if err != nil {
		log.Fatalf("cloudtrace.New: %v", err)
	}
	// Identify your application using resource detection.
	res, err := resource.New(ctx,
		// Use the GCP resource detector to detect information about the GKE Cluster.
		resource.WithDetectors(gcp.NewDetector()),
		resource.WithTelemetrySDK(),
	)
	if err != nil {
		log.Fatalf("resource.New: %v", err)
	}
	tp := trace.NewTracerProvider(
		trace.WithBatcher(exporter),
		trace.WithResource(res),
	)
	// Set the global TracerProvider which is used by otelhttp to record spans.
	otel.SetTracerProvider(tp)
	// Flush any pending spans on shutdown.
	defer tp.ForceFlush(ctx)

	// Set the global Propagators which is used by otelhttp to propagate
	// context using the w3c traceparent and baggage formats.
	otel.SetTextMapPropagator(autoprop.NewTextMapPropagator())

	// Handle incoming request.
	r := mux.NewRouter()
	r.HandleFunc("/", mainHandler)
	var handler http.Handler = r

	// Use otelhttp to create spans and extract context for incoming http
	// requests.
	handler = otelhttp.NewHandler(handler, "server")
	log.Fatal(http.ListenAndServe(fmt.Sprintf(":%v", os.Getenv("PORT")), handler))
}

Observe o seguinte sobre esse código:

  • Você configura um TracerProvider do OpenTelemetry, que detecta atributos quando é executado no Google Cloud e exporta traces para o Cloud Trace.
  • Use as funções otel.SetTracerProvider e otel.SetTextMapPropagators para definir as configurações globais de TracerProvider e Propagator. Por padrão, bibliotecas de instrumentação como otelhttp usam o TracerProvider registrado globalmente para criar períodos e Propagator para propagar o contexto.
  • Una o servidor HTTP com otelhttp.NewHandler para instrumentar o servidor HTTP.

Revise a função mainHandler

func mainHandler(w http.ResponseWriter, r *http.Request) {
	// Use otelhttp to record a span for the outgoing call, and propagate
	// context to the destination.
	destination := os.Getenv("DESTINATION_URL")
	resp, err := otelhttp.Get(r.Context(), destination)
	if err != nil {
		log.Fatal("could not fetch remote endpoint")
	}
	defer resp.Body.Close()
	_, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatalf("could not read response from %v", destination)
	}

	fmt.Fprint(w, strconv.Itoa(resp.StatusCode))
}

Para capturar a latência das solicitações de saída feitas para o destino, use o plug-in otelhttp para fazer uma solicitação HTTP. Use também a função r.Context para vincular a solicitação recebida à solicitação de saída, conforme mostrado na listagem a seguir:

// Use otelhttp to record a span for the outgoing call, and propagate
// context to the destination.
resp, err := otelhttp.Get(r.Context(), destination)

Implantar o aplicativo

Nesta seção, você usará o Cloud Build para criar imagens de contêiner para os serviços de back-end e front-end e implantá-los nos clusters do GKE.

Criar o contêiner do Docker

  1. No Cloud Shell, envie a versão pelo diretório de trabalho:

    cd $WORKDIR
    gcloud builds submit . --tag us-west1-docker.pkg.dev/$PROJECT_ID/distributed-tracing-docker-repo/backend:latest
    
  2. Confirme se a imagem do contêiner foi criada e está disponível no Container Registry:

    gcloud artifacts docker images list us-west1-docker.pkg.dev/$PROJECT_ID/distributed-tracing-docker-repo
    

    A imagem do contêiner foi criada com sucesso quando a saída é semelhante à seguinte, em que PROJECT_ID é o ID do projeto do Google Cloud:

    NAME
    us-west1-docker.pkg.dev/PROJECT_ID/distributed-tracing-docker-repo/backend
    

Implantar o serviço de back-end

  1. No Cloud Shell, defina o contexto kubectx para o cluster backend:

    kubectx backend
    
  2. Crie o arquivo YAML para a implantação backend:

    export PROJECT_ID=$(gcloud info --format='value(config.project)')
    envsubst < backend-deployment.yaml | kubectl apply -f -
    
  3. Confirme se os pods estão em execução:

    kubectl get pods
    

    A saída exibe um valor Status de Running:

    NAME                       READY   STATUS    RESTARTS   AGE
    backend-645859d95b-7mx95   1/1     Running   0          52s
    backend-645859d95b-qfdnc   1/1     Running   0          52s
    backend-645859d95b-zsj5m   1/1     Running   0          52s
    
  4. Exponha a implantação backend usando um balanceador de carga:

    kubectl expose deployment backend --type=LoadBalancer
    
  5. Consiga o endereço IP do serviço backend:

    kubectl get services backend
    

    O resultado será assim:

    NAME      TYPE           CLUSTER-IP     EXTERNAL-IP    PORT(S)          AGE
    backend   LoadBalancer   10.11.247.58   34.83.88.143   8080:30714/TCP   70s
    

    Se o valor do campo EXTERNAL-IP for <pending>, repita o comando até que o valor seja um endereço IP.

  6. Capture o endereço IP da etapa anterior como uma variável:

    export BACKEND_IP=$(kubectl get svc backend -ojson | jq -r '.status.loadBalancer.ingress[].ip')
    

Implantar o serviço de front-end

  1. No Cloud Shell, defina o contexto kubectx como o cluster de back-end:

    kubectx frontend
    
  2. Crie o arquivo YAML para a implantação frontend:

    export PROJECT_ID=$(gcloud info --format='value(config.project)')
    envsubst < frontend-deployment.yaml | kubectl apply -f -
    
  3. Confirme se os pods estão em execução:

    kubectl get pods
    

    A saída exibe um valor Status de Running:

    NAME                        READY   STATUS    RESTARTS   AGE
    frontend-747b445499-v7x2w   1/1     Running   0          57s
    frontend-747b445499-vwtmg   1/1     Running   0          57s
    frontend-747b445499-w47pf   1/1     Running   0          57s
    
  4. Exponha a implantação frontend usando um balanceador de carga:

    kubectl expose deployment frontend --type=LoadBalancer
    
  5. Consiga o endereço IP do serviço frontend:

    kubectl get services frontend
    

    O resultado será assim:

    NAME       TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)         AGE
    frontend   LoadBalancer   10.27.241.93   34.83.111.232   8081:31382/TCP  70s
    

    Se o valor do campo EXTERNAL-IP for <pending>, repita o comando até que o valor seja um endereço IP.

  6. Capture o endereço IP da etapa anterior como uma variável:

    export FRONTEND_IP=$(kubectl get svc frontend -ojson | jq -r '.status.loadBalancer.ingress[].ip')
    

Carregar o aplicativo e analisar traces

Nesta seção, você usa o utilitário Apache Bench para criar solicitações para o aplicativo. Em seguida, analise os traces resultantes no Cloud Trace.

  1. No Cloud Shell, use o Apache Bench para gerar 1.000 solicitações usando três linhas de execução simultâneas:

    ab -c 3 -n 1000 http://${FRONTEND_IP}:8081/
    
  2. No console do Google Cloud, acesse a página Lista de traces.

    Acessar a lista de traces

  3. Para revisar a linha do tempo, clique em um dos URIs rotulados como server.

    Gráfico de dispersão de traces.

    Esse trace contém quatro períodos com os seguintes nomes:

    • O primeiro período server captura a latência de ponta a ponta ao processar a solicitação HTTP no servidor de front-end.
    • O primeiro período HTTP GET captura a latência da chamada GET feita pelo cliente do front-end para o back-end.
    • O segundo período server captura a latência de ponta a ponta do processamento da solicitação HTTP no servidor de back-end.
    • O segundo período HTTP GET captura a latência da chamada GET feita pelo cliente do back-end para google.com.

    Gráfico de barras de períodos.

Limpar

A maneira mais fácil de eliminar o faturamento é excluir o projeto do Google Cloud que você criou para a implantação. A outra opção é excluir os recursos individuais.

Excluir o projeto

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

Excluir recursos individuais

Para excluir recursos individuais em vez de excluir o projeto inteiro, execute os seguintes comandos no Cloud Shell:

gcloud container clusters delete frontend-cluster --zone=us-west1-a
gcloud container clusters delete backend-cluster --zone=us-west1-a
gcloud artifacts repositories delete distributed-tracing-docker-repo --location us-west1

A seguir