Esegui il deployment del tracciamento distribuito per osservare la latenza dei microservizi

Last reviewed 2023-08-11 UTC

Questo documento mostra come eseguire il deployment dell'architettura di riferimento descritta in Utilizzare il tracciamento distribuito per osservare la latenza dei microservizi. Il deployment illustrato in questo documento acquisisce informazioni sulle tracce nelle applicazioni di microservizi utilizzando OpenTelemetry e Cloud Trace.

L'applicazione di esempio in questo deployment è composta da due microservizi scritti in Go.

Questo documento presuppone la conoscenza di quanto segue:

Obiettivi

  • Crea un cluster GKE ed esegui il deployment di un'applicazione di esempio.
  • Esamina il codice di strumentazione OpenTelemetry.
  • Esamina le tracce e i log generati dalla strumentazione.

Architettura

Il seguente diagramma mostra l'architettura di cui esegui il deployment.

Architettura del deployment con due cluster GKE.

Puoi utilizzare Cloud Build, una piattaforma di integrazione continua, distribuzione e deployment completamente gestita, per creare immagini container dal codice campione e archiviarle in Artifact Registry. I cluster GKE eseguono il pull delle immagini da Artifact Registry al momento del deployment.

Il servizio frontend accetta le richieste HTTP sull'URL / e chiama il servizio di backend. L'indirizzo del servizio di backend è definito da una variabile di ambiente.

Il servizio di backend accetta le richieste HTTP sull'URL / ed effettua una chiamata in uscita a un URL esterno come definito in una variabile di ambiente. Al termine della chiamata esterna, il servizio di backend restituisce la chiamata dello stato HTTP (ad esempio, 200) al chiamante.

Costi

In questo documento vengono utilizzati i seguenti componenti fatturabili di Google Cloud:

Per generare una stima dei costi in base all'utilizzo previsto, utilizza il Calcolatore prezzi. I nuovi utenti di Google Cloud possono essere idonei a una prova senza costi aggiuntivi.

Una volta completate le attività descritte in questo documento, puoi evitare la fatturazione continua eliminando le risorse che hai creato. Per ulteriori informazioni, consulta la pagina Pulizia.

Prima di iniziare

  1. Accedi al tuo account Google Cloud. Se non conosci Google Cloud, crea un account per valutare le prestazioni dei nostri prodotti in scenari reali. I nuovi clienti ricevono anche 300 $di crediti gratuiti per l'esecuzione, il test e il deployment dei carichi di lavoro.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Assicurati che la fatturazione sia attivata per il tuo progetto Google Cloud.

  4. Abilita le API GKE, Cloud Trace, Cloud Build, Cloud Storage, and Artifact Registry.

    Abilita le API

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

    Go to project selector

  6. Assicurati che la fatturazione sia attivata per il tuo progetto Google Cloud.

  7. Abilita le API GKE, Cloud Trace, Cloud Build, Cloud Storage, and Artifact Registry.

    Abilita le API

configura l'ambiente

In questa sezione configurerai l'ambiente con gli strumenti da utilizzare durante il deployment. Esegui tutti i comandi del terminale in questo deployment da Cloud Shell.

  1. Nella console Google Cloud, attiva Cloud Shell.

    Attiva Cloud Shell

    Nella parte inferiore della console Google Cloud viene avviata una sessione di Cloud Shell che mostra un prompt della riga di comando. Cloud Shell è un ambiente shell con Google Cloud CLI già installato e con valori già impostati per il progetto attuale. L'inizializzazione della sessione può richiedere alcuni secondi.

  2. Imposta una variabile di ambiente sull'ID del tuo progetto Google Cloud:
    export PROJECT_ID=$(gcloud config list --format 'value(core.project)' 2>/dev/null)
    
  3. Scarica i file richiesti per questo deployment clonando il repository Git associato:
    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples.git
    cd kubernetes-engine-samples/observability/distributed-tracing
    WORKDIR=$(pwd)
    

    Imposta la cartella del repository come directory di lavoro ($WORKDIR) da cui esegui tutte le attività correlate a questo deployment. In questo modo, se non vuoi conservare le risorse, puoi eliminare la cartella al termine del deployment.

Installazione di strumenti

  1. In Cloud Shell, installa kubectx e kubens:

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

    Questi strumenti consentono di lavorare con più cluster, contesti e spazi dei nomi Kubernetes.

  2. In Cloud Shell, installa Apache Bench, uno strumento open source di generazione del carico:

    sudo apt-get install apache2-utils
    

Crea un repository Docker

Crea un repository Docker per archiviare l'immagine di esempio per questo deployment.

Console

  1. Nella console Google Cloud, apri la pagina Repositories.

    Apri la pagina Repository

  2. Fai clic su Crea repository.

  3. Specifica distributed-tracing-docker-repo come nome del repository.

  4. Scegli Docker come formato e Standard come modalità.

  5. In Tipo di località, seleziona Regione e poi scegli la località us-west1.

  6. Fai clic su Crea.

Il repository viene aggiunto all'elenco.

gcloud

  1. In Cloud Shell, crea un nuovo repository Docker denominato distributed-tracing-docker-repo nella località us-west1 con la descrizione docker repository:

    gcloud artifacts repositories create distributed-tracing-docker-repo --repository-format=docker \
    --location=us-west1 --description="Docker repository for distributed tracing deployment"
    
  2. Verifica che il repository sia stato creato:

    gcloud artifacts repositories list
    

crea cluster GKE

In questa sezione creerai due cluster GKE in cui eseguire il deployment dell'applicazione di esempio. Per impostazione predefinita, i cluster GKE vengono creati con accesso in sola scrittura all'Cloud Trace API, quindi non è necessario definire l'accesso quando crei i cluster.

  1. In Cloud Shell, crea i cluster:

    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
    

    In questo esempio, i cluster si trovano nella zona us-west1-a. Per ulteriori informazioni, consulta Area geografica e regioni.

  2. Recupera le credenziali del cluster e archiviale localmente:

    gcloud container clusters get-credentials backend-cluster --zone=us-west1-a
    gcloud container clusters get-credentials frontend-cluster --zone=us-west1-a
    
  3. Rinomina i contesti dei cluster per accedervi più facilmente in una fase successiva del deployment:

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

Esamina la strumentazione OpenTelemetry

Nelle sezioni seguenti, esaminerai il codice del file main.go nell'applicazione di esempio. Questo ti aiuta a imparare a utilizzare la propagazione del contesto per consentire l'aggiunta di intervalli di più richieste a una singola traccia padre.

Esamina le importazioni nel codice dell'applicazione

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"
)

Tieni presente quanto segue sulle importazioni:

  • Il pacchetto go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp contiene il plug-in otelhttp, che può supportare un server HTTP o un client HTTP. La strumentazione server recupera il contesto di intervallo dalla richiesta HTTP e registra un intervallo per la gestione della richiesta da parte del server. La strumentazione client inserisce il contesto di intervallo nella richiesta HTTP in uscita e registra un intervallo per il tempo trascorso in attesa di una risposta.
  • Il pacchetto go.opentelemetry.io/contrib/propagators/autoprop fornisce un'implementazione dell'interfaccia TextMapPropagator OpenTelemetry, che viene utilizzata da otelhttp per gestire la propagazione. I propagatori determinano il formato e le chiavi utilizzate per archiviare il contesto della traccia nei trasporti come HTTP. In particolare, otelhttp passa le intestazioni HTTP al propagatore. Il propagatore estrae un contesto di intervallo in un contesto Go dalle intestazioni oppure codifica e inserisce un contesto di intervallo nel contesto Go nelle intestazioni (a seconda che si tratti di client o server). Per impostazione predefinita, il pacchetto autoprop inserisce ed estrae il contesto di intervallo utilizzando il formato di propagazione del contesto della traccia W3C.
  • L'importazione github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace esporta le tracce in Cloud Trace.
  • L'importazione github.com/gorilla/mux è la libreria utilizzata dall'applicazione di esempio per la gestione delle richieste.
  • L'importazione go.opentelemetry.io/contrib/detectors/gcp aggiunge attributi agli intervalli, come cloud.availability_zone, che identificano dove viene eseguita l'applicazione all'interno di Google Cloud.
  • Le importazioni go.opentelemetry.io/otel, go.opentelemetry.io/otel/sdk/trace e go.opentelemetry.io/otel/sdk/resource utilizzate per configurare OpenTelemetry.

Esamina la funzione main

La funzione main configura l'esportazione delle tracce in Cloud Trace e utilizza un router Mux per gestire le richieste inviate all'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))
}

Tieni presente quanto segue in merito a questo codice:

  • Puoi configurare un TracerProvider OpenTelemetry, che rileva gli attributi quando viene eseguito su Google Cloud e esporta le tracce in Cloud Trace.
  • Puoi utilizzare le funzioni otel.SetTracerProvider e otel.SetTextMapPropagators per definire le impostazioni globali TracerProvider e Propagator. Per impostazione predefinita, le librerie di strumentazione come otelhttp utilizzano il valore TracerProvider registrato a livello globale per creare intervalli e Propagator per propagare il contesto.
  • Esegui il wrapping del server HTTP con otelhttp.NewHandler per eseguire il wrapping del server HTTP.

Esamina la funzione 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))
}

Per acquisire la latenza delle richieste in uscita effettuate verso la destinazione, utilizza il plug-in otelhttp per effettuare una richiesta HTTP. Puoi utilizzare la funzione r.Context anche per collegare la richiesta in arrivo con la richiesta in uscita, come mostrato nell'elenco seguente:

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

Esegui il deployment dell'applicazione

In questa sezione utilizzerai Cloud Build per creare immagini container per i servizi di backend e frontend. Poi eseguine il deployment nei cluster GKE.

Crea il container Docker

  1. In Cloud Shell, invia la build dalla directory di lavoro:

    cd $WORKDIR
    gcloud builds submit . --tag us-west1-docker.pkg.dev/$PROJECT_ID/distributed-tracing-docker-repo/backend:latest
    
  2. Verifica che l'immagine container sia stata creata e che sia disponibile in Artifact Registry:

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

    L'immagine container è stata creata quando l'output è simile al seguente, dove PROJECT_ID è l'ID del tuo progetto Google Cloud:

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

Esegui il deployment del servizio di backend

  1. In Cloud Shell, imposta il contesto kubectx sul cluster backend:

    kubectx backend
    
  2. Crea il file YAML per il deployment backend:

    export PROJECT_ID=$(gcloud info --format='value(config.project)')
    envsubst < backend-deployment.yaml | kubectl apply -f -
    
  3. Verifica che i pod siano in esecuzione:

    kubectl get pods
    

    L'output mostra un valore Status pari a 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. Esponi il deployment backend utilizzando un bilanciatore del carico:

    kubectl expose deployment backend --type=LoadBalancer
    
  5. Recupera l'indirizzo IP del servizio backend:

    kubectl get services backend
    

    L'output è simile al seguente:

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

    Se il valore del campo EXTERNAL-IP è <pending>, ripeti il comando fino a quando il valore non è un indirizzo IP.

  6. Acquisisci l'indirizzo IP del passaggio precedente in una variabile:

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

esegui il deployment del servizio frontend

  1. In Cloud Shell, imposta il contesto kubectx sul cluster di backend:

    kubectx frontend
    
  2. Crea il file YAML per il deployment frontend:

    export PROJECT_ID=$(gcloud info --format='value(config.project)')
    envsubst < frontend-deployment.yaml | kubectl apply -f -
    
  3. Verifica che i pod siano in esecuzione:

    kubectl get pods
    

    L'output mostra un valore Status pari a 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. Esponi il deployment frontend utilizzando un bilanciatore del carico:

    kubectl expose deployment frontend --type=LoadBalancer
    
  5. Recupera l'indirizzo IP del servizio frontend:

    kubectl get services frontend
    

    L'output è simile al seguente:

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

    Se il valore del campo EXTERNAL-IP è <pending>, ripeti il comando fino a quando il valore non è un indirizzo IP.

  6. Acquisisci l'indirizzo IP del passaggio precedente in una variabile:

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

Carica l'applicazione ed esamina le tracce

In questa sezione utilizzerai l'utilità Apache Bench per creare richieste per la tua applicazione. Quindi, esaminerai le tracce risultanti in Cloud Trace.

  1. In Cloud Shell, utilizza Apache Bench per generare 1000 richieste utilizzando 3 thread simultanei:

    ab -c 3 -n 1000 http://${FRONTEND_IP}:8081/
    
  2. Nella console Google Cloud, vai alla pagina Elenco di tracce.

    Vai a Elenco di tracce

  3. Per esaminare la cronologia, fai clic su uno degli URI con l'etichetta server.

    Grafico a dispersione delle tracce.

    Questa traccia contiene quattro intervalli con i seguenti nomi:

    • Il primo intervallo server acquisisce la latenza end-to-end della gestione della richiesta HTTP nel server frontend.
    • Il primo intervallo HTTP GET acquisisce la latenza della chiamata GET effettuata dal client del frontend al backend.
    • Il secondo intervallo server acquisisce la latenza end-to-end relativa alla gestione della richiesta HTTP nel server di backend.
    • Il secondo intervallo HTTP GET acquisisce la latenza della chiamata GET effettuata dal client del backend a google.com.

    Grafico a barre degli intervalli.

Esegui la pulizia

Il modo più semplice per eliminare la fatturazione è eliminare il progetto Google Cloud che hai creato per il deployment. In alternativa, puoi eliminare le singole risorse.

Elimina il progetto

  1. Nella console Google Cloud, vai alla pagina Gestisci risorse.

    Vai a Gestisci risorse

  2. Nell'elenco dei progetti, seleziona il progetto che vuoi eliminare, quindi fai clic su Elimina.
  3. Nella finestra di dialogo, digita l'ID del progetto e fai clic su Chiudi per eliminare il progetto.

Elimina singole risorse

Per eliminare singole risorse invece di eliminare l'intero progetto, esegui questi comandi in 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

Passaggi successivi