Observabilidade com aplicações gRPC sem proxy

As ferramentas de observabilidade de microsserviços permitem-lhe instrumentar as suas aplicações para recolher e apresentar dados de telemetria no Cloud Monitoring, Cloud Logging> e Cloud Trace a partir de cargas de trabalho gRPC implementadas no Google Cloud, incluindo cargas de trabalho gRPC no Cloud Service Mesh.

Os clientes e os servidores gRPC estão integrados com o OpenCensus para exportar métricas e rastreios para vários back-ends, incluindo o Trace e a Monitorização. Pode fazê-lo com os seguintes idiomas gRPC:

  • C++
  • Ir
  • Java

Leia a vista geral da observabilidade dos microsserviços e, em seguida, use as instruções em Configure a observabilidade dos microsserviços para instrumentar as suas cargas de trabalho gRPC para o seguinte:

Siga as instruções neste documento para as seguintes tarefas:

Veja rastreios no Trace

Depois de concluir o processo de configuração, os clientes e os servidores gRPC instrumentados enviam rastreios para o Trace. A página Vista geral do rastreio na consola mostra uma lista de rastreios recentes. Google Cloud Pode selecionar um rastreio individual para ver uma análise detalhada do seu tráfego, semelhante ao que é descrito na secção seguinte.

Compatibilidade de rastreio com o proxy Envoy

A exportação de rastreios para o Trace com o Cloud Service Mesh e o proxy Envoy, conforme descrito em Observabilidade com o Envoy, usa a configuração do rastreador OpenCensus do Envoy, que permite que os rastreios exportados de aplicações gRPC sem proxy e proxies Envoy sejam totalmente compatíveis numa malha de serviços. Para compatibilidade com gRPC sem proxy, o bootstrap do Envoy tem de configurar o contexto de rastreio para incluir o formato de rastreio GRPC_TRACE_BIN no respetivo OpenCensusConfig. Por exemplo:

tracing:
  http:
      name: envoy.tracers.opencensus
      typed_config:
        "@type": type.googleapis.com/envoy.config.trace.v2.OpenCensusConfig
        stackdriver_exporter_enabled: "true"
        stackdriver_project_id: "PROJECT_ID"
        incoming_trace_context: ["CLOUD_TRACE_CONTEXT", "GRPC_TRACE_BIN"]
        outgoing_trace_context: ["CLOUD_TRACE_CONTEXT", "GRPC_TRACE_BIN"]

Exponha a interface de administração

Por vezes, as métricas e os dados de rastreio não são suficientes para resolver um problema. Pode ter de analisar a configuração ou o estado de tempo de execução da biblioteca gRPC na sua aplicação. Estas informações incluem informações do resolvedor, o estado da conetividade com os pares, estatísticas de RPC num canal e a configuração recebida do Cloud Service Mesh.

Para obter essas informações, as aplicações gRPC podem expor a interface de administração numa porta específica. Em seguida, pode consultar a aplicação para compreender como os serviços estão configurados e como estão a ser executados. Nesta secção, pode encontrar instruções sobre como configurar a interface de administração para aplicações escritas em cada idioma suportado.

Recomendamos que crie um servidor gRPC separado na sua aplicação que ouça numa porta reservada para este fim. Isto permite-lhe aceder às suas aplicações gRPC, mesmo quando as portas de dados estão inacessíveis devido a uma configuração incorreta ou a problemas de rede. Recomendamos que exponha a interface de administração apenas em localhost ou num soquete de domínio Unix.

Os fragmentos de código seguintes mostram como criar uma interface de administração.

C++

Em C++, use este código para criar uma interface de administração:

#include <grpcpp/ext/admin_services.h>

grpc::ServerBuilder builder;
grpc::AddAdminServices(&builder);
builder.AddListeningPort(":50051", grpc::ServerCredentials(...));
std::unique_ptr<grpc::Server> server(builder.BuildAndStart());

Ir

Em Go, use este código para criar uma interface de administrador:

import "google.golang.org/grpc/admin"

lis, err := net.Listen("tcp", ":50051")
if err != nil {
        log.Fatalf("failed to listen: %v", err)
}
defer lis.Close()
grpcServer := grpc.NewServer(...opts)
cleanup, err := admin.Register(grpcServer)
if err != nil {
        log.Fatalf("failed to register admin services: %v", err)
}
defer cleanup()

if err := grpcServer.Serve(lis); err != nil {
        log.Fatalf("failed to serve: %v", err)
}

Java

Em Java, use este código para criar uma interface de administração:

import io.grpc.services.AdminInterface;

server = ServerBuilder.forPort(50051)
        .useTransportSecurity(certChainFile, privateKeyFile)
        .addServices(AdminInterface.getStandardServices())
        .build()
        .start();
server.awaitTermination();

Python

Em Python, use este código para criar uma interface de administração:

import grpc_admin

server = grpc.server(futures.ThreadPoolExecutor())
grpc_admin.add_admin_servicers(server)
server.add_insecure_port('[::]:50051')
server.start()
server.wait_for_termination()

Use o SSH para estabelecer ligação a uma VM

O exemplo gRPC Wallet já ativa a interface de administração. Pode alterar a porta da interface de administração fornecendo a seguinte flag:

 --admin-port=PORT

A porta de administrador predefinida é localhost:28881.

Para depurar a sua aplicação gRPC, pode usar o SSH para estabelecer ligação a uma das VMs que servem o wallet-service. Isto dá-lhe acesso ao localhost.

# List the Wallet VMs
$ gcloud compute instances list --filter="zone:(us-central1-a)" --filter="name~'grpcwallet-wallet-v2'"
NAME                                       ZONE            MACHINE_TYPE   PREEMPTIBLE  INTERNAL_IP    EXTERNAL_IP     STATUS
grpcwallet-wallet-v2-mig-us-central1-ccl1  us-central1-a   n1-standard-1               10.240.0.38    35.223.42.98    RUNNING
grpcwallet-wallet-v2-mig-us-central1-k623  us-central1-a   n1-standard-1               10.240.0.112   35.188.133.75   RUNNING
# Pick one of the Wallet VMs to debug
$ gcloud compute ssh grpcwallet-wallet-v2-mig-us-central1-ccl1 --zone=us-central1-a

Instale a ferramenta grpcdebug

Para aceder à interface de administração, precisa de um cliente gRPC que possa comunicar com os serviços de administração na sua aplicação gRPC. Nos exemplos seguintes, usa uma ferramenta denominada grpcdebug que pode transferir e instalar na VM ou no Pod onde a sua aplicação gRPC está a ser executada. O repositório para grpcdebug está localizado em grpc-ecosystem/grpcdebug.

A versão mínima do Golang suportada é a 1.12. O guia de instalação oficial do Golang encontra-se no site do Golang. Se estiver a seguir o guia para criar uma VM do Linux para o wallet-service, pode instalar o Golang 1.16 através destes comandos:

sudo apt update && sudo apt install -y wget
wget https://golang.org/dl/go1.16.3.linux-amd64.tar.gz
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf go1.16.3.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin
sudo ln -sf /usr/local/go/bin/go /usr/bin/go
go version
# go version go1.16.3 linux/amd64

Instale a ferramenta grpcdebug com os seguintes comandos:

go install -v github.com/grpc-ecosystem/grpcdebug@latest
export PATH=$PATH:$(go env GOPATH)/bin

Já tem acesso à interface de linhas de comando grpcdebug. A saída de ajuda contém informações sobre os comandos suportados:

$ grpcdebug -h
grpcdebug is a gRPC service admin command-line interface

Usage:
  grpcdebug <target address> [flags]  <command>

Available Commands:
  channelz    Display gRPC states in human readable way.
  health      Check health status of the target service (default "").
  help        Help about any command
  xds         Fetch xDS related information.

Flags:
      --credential_file string        Sets the path of the credential file; used in [tls] mode
  -h, --help                          Help for grpcdebug
      --security string               Defines the type of credentials to use [tls, google-default, insecure] (default "insecure")
      --server_name_override string   Overrides the peer server name if non empty; used in [tls] mode
  -t, --timestamp                     Print timestamp as RFC 3339 instead of human readable strings
  -v, --verbose                       Print verbose information for debugging

Para obter mais informações sobre um comando específico, use o seguinte:

 grpcdebug <target address> [command] --help

Use a grpcdebug ferramenta para depurar as suas aplicações

Pode usar a ferramenta grpcdebug para depurar as suas aplicações. A ferramenta grpcdebug oferece uma configuração semelhante à do ssh_config que suporta a criação de alias, a reescrita do nome de anfitrião e a definição de segurança da ligação (não segura/TLS). Para mais informações sobre esta funcionalidade avançada, consulte grpcdebug/Connect&Security.

As secções seguintes descrevem os serviços expostos pela interface de administração e como aceder aos mesmos.

Use o Channelz

O serviço Channelz fornece acesso a informações de tempo de execução sobre as ligações a diferentes níveis na biblioteca gRPC da sua aplicação. Pode usar esta opção para fazer uma análise em direto de aplicações que possam ter problemas relacionados com a configuração ou a rede. Os exemplos seguintes pressupõem que implementou o exemplo de carteira gRPC através das instruções em Configure a gestão de tráfego avançada com serviços gRPC sem proxy e que forneceu a seguinte flag:

 --admin-port=PORT

Depois de enviar alguns RPCs a partir de um cliente de teste, conforme mostrado em Validar a configuração, use os seguintes comandos para aceder aos dados do Channelz para serviços gRPC:

  1. Use o SSH para estabelecer ligação a uma VM que esteja a executar o wallet-service.
  2. Configure o grpcdebug para estabelecer ligação à aplicação gRPC em execução.

O resultado predefinido de grpcdebug está num formato de tabela compatível com a consola. Se fornecer a flag --json, a saída é codificada como JSON.

O comando grpcdebug channelz é usado para obter e apresentar informações de depuração do serviço Channelz. O comando funciona para clientes gRPC e servidores gRPC.

Para clientes gRPC, o comando grpcdebug channelz channels fornece uma lista de canais existentes e algumas informações básicas:

$ grpcdebug localhost:28881 channelz channels
Channel ID   Target                               State     Calls(Started/Succeeded/Failed)   Created Time
1            xds:///account.grpcwallet.io:10080   READY     0/0/0                             59 seconds ago
2            trafficdirector.googleapis.com:443   READY     2/0/0                             59 seconds ago
4            xds:///stats.grpcwallet.io:10080     READY     0/0/0                             59 seconds ago

Se precisar de informações adicionais sobre um canal específico, pode usar grpcdebug channelz channel [CHANNEL_ID] para inspecionar informações detalhadas desse canal. O identificador do canal pode ser o ID do canal ou o endereço de destino, se existir apenas um endereço de destino. Um canal gRPC pode conter vários subcanais, que é a abstração do gRPC sobre uma ligação TCP.

$ grpcdebug localhost:28881 channelz channel 2
Channel ID:        2
Target:            trafficdirector.googleapis.com:443
State:             READY
Calls Started:     2
Calls Succeeded:   0
Calls Failed:      0
Created Time:      10 minutes ago
---
Subchannel ID   Target                               State     Calls(Started/Succeeded/Failed)   CreatedTime
3               trafficdirector.googleapis.com:443   READY     2/0/0                             10 minutes ago
---
Severity   Time             Child Ref                      Description
CT_INFO    10 minutes ago                                  Channel Created
CT_INFO    10 minutes ago                                  parsed scheme: ""
CT_INFO    10 minutes ago                                  scheme "" not registered, fallback to default scheme
CT_INFO    10 minutes ago                                  ccResolverWrapper: sending update to cc: {[{trafficdirector.googleapis.com:443  <nil> 0 <nil>}] <nil> <nil>}
CT_INFO    10 minutes ago                                  Resolver state updated: {Addresses:[{Addr:trafficdirector.googleapis.com:443 ServerName: Attributes:<nil> Type:0 Metadata:<nil>}] ServiceConfig:<nil> Attributes:<nil>} (resolver returned new addresses)
CT_INFO    10 minutes ago                                  ClientConn switching balancer to "pick_first"
CT_INFO    10 minutes ago                                  Channel switches to new LB policy "pick_first"
CT_INFO    10 minutes ago   subchannel(subchannel_id:3 )   Subchannel(id:3) created
CT_INFO    10 minutes ago                                  Channel Connectivity change to CONNECTING
CT_INFO    10 minutes ago                                  Channel Connectivity change to READY

Também pode inspecionar informações detalhadas de um subcanal:

$ grpcdebug localhost:28881 channelz subchannel 3
Subchannel ID:     3
Target:            trafficdirector.googleapis.com:443
State:             READY
Calls Started:     2
Calls Succeeded:   0
Calls Failed:      0
Created Time:      12 minutes ago
---
Socket ID   Local->Remote                           Streams(Started/Succeeded/Failed)   Messages(Sent/Received)
9           10.240.0.38:60338->142.250.125.95:443   2/0/0                               214/132

Pode aceder a informações sobre entradas TCP:

$ grpcdebug localhost:28881 channelz socket 9
Socket ID:                       9
Address:                         10.240.0.38:60338->142.250.125.95:443
Streams Started:                 2
Streams Succeeded:               0
Streams Failed:                  0
Messages Sent:                   226
Messages Received:               141
Keep Alives Sent:                0
Last Local Stream Created:       12 minutes ago
Last Remote Stream Created:      a long while ago
Last Message Sent Created:       8 seconds ago
Last Message Received Created:   8 seconds ago
Local Flow Control Window:       65535
Remote Flow Control Window:      966515
---
Socket Options Name   Value
SO_LINGER             [type.googleapis.com/grpc.channelz.v1.SocketOptionLinger]:{duration:{}}
SO_RCVTIMEO           [type.googleapis.com/grpc.channelz.v1.SocketOptionTimeout]:{duration:{}}
SO_SNDTIMEO           [type.googleapis.com/grpc.channelz.v1.SocketOptionTimeout]:{duration:{}}
TCP_INFO              [type.googleapis.com/grpc.channelz.v1.SocketOptionTcpInfo]:{tcpi_state:1  tcpi_options:7  tcpi_rto:204000  tcpi_ato:40000  tcpi_snd_mss:1408  tcpi_rcv_mss:1408  tcpi_last_data_sent:8212  tcpi_last_data_recv:8212  tcpi_last_ack_recv:8212  tcpi_pmtu:1460  tcpi_rcv_ssthresh:88288  tcpi_rtt:2400  tcpi_rttvar:3012  tcpi_snd_ssthresh:2147483647  tcpi_snd_cwnd:10  tcpi_advmss:1408  tcpi_reordering:3}
---
Security Model:   TLS
Standard Name:    TLS_AES_128_GCM_SHA256

No lado do servidor, pode usar o Channelz para inspecionar o estado da aplicação do servidor. Por exemplo, pode obter a lista de servidores através do comando grpcdebug channelz servers:

$ grpcdebug localhost:28881 channelz servers
Server ID   Listen Addresses    Calls(Started/Succeeded/Failed)   Last Call Started
5           [127.0.0.1:28881]   9/8/0                             now
6           [[::]:50051]        159/159/0                         4 seconds ago

Para obter mais informações sobre um servidor específico, use o comando grpcdebug channelz server. Pode inspecionar as portas de servidor da mesma forma que inspeciona as portas de cliente.

$ grpcdebug localhost:28881 channelz server 6
Server Id:           6
Listen Addresses:    [[::]:50051]
Calls Started:       174
Calls Succeeded:     174
Calls Failed:        0
Last Call Started:   now
---
Socket ID   Local->Remote                            Streams(Started/Succeeded/Failed)   Messages(Sent/Received)
25          10.240.0.38:50051->130.211.1.39:44904    68/68/0                             68/68
26          10.240.0.38:50051->130.211.0.167:32768   54/54/0                             54/54
27          10.240.0.38:50051->130.211.0.22:32768    52/52/0                             52/52

Use o serviço de descoberta do estado do cliente

A API Client Status Discovery Service (CSDS) faz parte das APIs xDS. Numa aplicação gRPC, o serviço CSDS fornece acesso à configuração (também denominada configuração xDS) que recebe do Cloud Service Mesh. Isto permite-lhe identificar e resolver problemas relacionados com a configuração na sua malha.

Os exemplos seguintes pressupõem que implementou o exemplo da Carteira gRPC através das instruções em Configure a gestão de tráfego avançada com serviços gRPC sem proxy.

Para usar o CSDS para examinar a configuração:

  1. Use o SSH para estabelecer ligação a uma VM que esteja a executar o wallet-service. Use as instruções em Use o SSH para estabelecer ligação a uma VM.
  2. Execute o cliente grpcdebug.

Para obter uma vista geral do estado da configuração, execute o seguinte comando:

grpcdebug localhost:28881 xds status

Vê resultados semelhantes aos seguintes:

Name                                                                    Status    Version               Type                                                                 LastUpdated
account.grpcwallet.io:10080                                             ACKED     1618529574783547920   type.googleapis.com/envoy.config.listener.v3.Listener                3 seconds ago
stats.grpcwallet.io:10080                                               ACKED     1618529574783547920   type.googleapis.com/envoy.config.listener.v3.Listener                3 seconds ago
URL_MAP/830293263384_grpcwallet-url-map_0_account.grpcwallet.io:10080   ACKED     1618529574783547920   type.googleapis.com/envoy.config.route.v3.RouteConfiguration         3 seconds ago
URL_MAP/830293263384_grpcwallet-url-map_1_stats.grpcwallet.io:10080     ACKED     1618529574783547920   type.googleapis.com/envoy.config.route.v3.RouteConfiguration         3 seconds ago
cloud-internal-istio:cloud_mp_830293263384_3566964729007423588          ACKED     1618529574783547920   type.googleapis.com/envoy.config.cluster.v3.Cluster                  3 seconds ago
cloud-internal-istio:cloud_mp_830293263384_7383783194368524341          ACKED     1618529574783547920   type.googleapis.com/envoy.config.cluster.v3.Cluster                  3 seconds ago
cloud-internal-istio:cloud_mp_830293263384_3363366193797120473          ACKED     1618529574783547920   type.googleapis.com/envoy.config.cluster.v3.Cluster                  3 seconds ago
cloud-internal-istio:cloud_mp_830293263384_3566964729007423588          ACKED     86                    type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment   2 seconds ago
cloud-internal-istio:cloud_mp_830293263384_3363366193797120473          ACKED     86                    type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment   2 seconds ago
cloud-internal-istio:cloud_mp_830293263384_7383783194368524341          ACKED     86                    type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment   2 seconds ago

Pode encontrar a definição do estado de configuração na documentação do proxy Envoy. Resumidamente, o estado de um recurso xDS é um dos seguintes: REQUESTED, DOES_NOT_EXIST, ACKED ou NACKED.

Para obter uma descarga da configuração xDS não processada, execute o seguinte comando:

grpcdebug localhost:28881 xds config

É apresentada uma lista de JSON do objeto PerXdsConfig:

{
  "config":  [
    {
      "node":  {
        "id":  "projects/830293263384/networks/default/nodes/6e98b038-6d75-4a4c-8d35-b0c7a8c9cdde",
        "cluster":  "cluster",
        "metadata":  {
          "INSTANCE_IP":  "10.240.0.38",
          "TRAFFICDIRECTOR_GCP_PROJECT_NUMBER":  "830293263384",
          "TRAFFICDIRECTOR_NETWORK_NAME":  "default"
        },
        "locality":  {
          "zone":  "us-central1-a"
        },
        "userAgentName":  "gRPC Go",
        "userAgentVersion":  "1.37.0",
        "clientFeatures":  [
          "envoy.lb.does_not_support_overprovisioning"
        ]
      },
      "xdsConfig":  [
        {
          "listenerConfig":  {
            "versionInfo":  "1618529930989701137",
            "dynamicListeners":  [
              {
...

Se o resultado da configuração não processada for demasiado detalhado, grpcdebug permite filtrar com base em tipos de xDS específicos. Por exemplo:

$ grpcdebug localhost:28881 xds config --type=cds
{
  "versionInfo":  "1618530076226619310",
  "dynamicActiveClusters":  [
    {
      "versionInfo":  "1618530076226619310",
      "cluster":  {
        "@type":  "type.googleapis.com/envoy.config.cluster.v3.Cluster",
        "name":  "cloud-internal-istio:cloud_mp_830293263384_7383783194368524341",
        "altStatName":  "/projects/830293263384/global/backendServices/grpcwallet-stats-service",
        "type":  "EDS",
        "edsClusterConfig":  {
          "edsConfig":  {
            "ads":  {},
            "initialFetchTimeout":  "15s",
...

Também pode despejar a configuração de vários tipos de xDS ao mesmo tempo:

$ grpcdebug localhost:28881 xds config --type=lds,eds
{
  "versionInfo":  "1618530076226619310",
  "dynamicListeners":  [...]
}
{
  "dynamicEndpointConfigs":  [...]
}

O que se segue?