Linha de comando gcloud em um tutorial de serviço do Cloud Run


Neste tutorial, você vai criar um inventário de serviços do Cloud Run usando a CLI do Google Cloud dentro de um serviço do Cloud Run. Você pode aplicar o que aprendeu neste tutorial nos scripts de operações do Cloud ou criar uma prova de conceito antes de usar bibliotecas de cliente para criar um serviço mais robusto.

Use a gcloud CLI como qualquer script de shell dentro de um serviço da Web. Por exemplo, como mostrado no guia de início rápido do Shell. No Cloud Run, as duas ferramentas trabalham com os serviços do Google Cloud fazendo a autenticação automática com a identidade do serviço do Cloud Run. Todas as permissões concedidas à identidade do serviço estão disponíveis para a CLI gcloud.

A CLI gcloud tem capacidades muito abrangentes de coleta de informações e gerenciamento de recursos no Google Cloud. Portanto, usá-la em um serviço da Web minimiza o risco de um autor de chamada fazer mau uso dessas capacidades. Sem controles de segurança, é possível haver riscos para outros serviços ou recursos em execução no mesmo projeto, possibilitando atividades prejudiciais acidentais ou intencionais. Veja alguns exemplos desses riscos:

  • Ativar a descoberta de endereços IP de máquinas virtuais particulares
  • Ativar acesso a dados particulares de um banco de dados no mesmo projeto
  • Ativar a exclusão de outros serviços em execução

Várias etapas neste tutorial mostram como impor controles para minimizar riscos, como, por exemplo, especificar o comando gcloud a ser executado no código, em vez de deixá-lo aberto como uma entrada do usuário.

O processo de script com a ferramenta de linha de comando em um serviço do Cloud Run é semelhante ao uso local. A principal diferença são as restrições extras que precisam ser adicionadas em torno da lógica principal do script.

Objetivos

  • Gravar e criar um contêiner personalizado com um Dockerfile (links em inglês)
  • Gravar, criar e implantar um serviço do Cloud Run
  • Usar a CLI gcloud com segurança em um serviço da Web
  • Gerar um relatório dos serviços do Cloud Run e salvá-lo no Cloud Storage

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.

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. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

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

  6. Enable the Artifact Registry, Cloud Build, Cloud Run, and Cloud Storage APIs.

    Enable the APIs

  7. Instale e inicialize a CLI gcloud.

Funções exigidas

Para conseguir as permissões necessárias para concluir o tutorial, peça ao administrador para conceder a você os seguintes papéis do IAM no seu projeto:

Para mais informações sobre a concessão de papéis, consulte Gerenciar o acesso a projetos, pastas e organizações.

Também é possível conseguir as permissões necessárias por meio de papéis personalizados ou de outros papéis predefinidos.

Configurar os padrões da gcloud

Para configurar a gcloud com os padrões do serviço do Cloud Run, realize as etapas a seguir:

  1. Defina seu projeto padrão:

    gcloud config set project PROJECT_ID

    Substitua PROJECT_ID pelo nome do projeto que você criou para este tutorial.

  2. Configure a gcloud para a região escolhida:

    gcloud config set run/region REGION

    Substitua REGION pela região compatível do Cloud Run.

Locais do Cloud Run

O Cloud Run é regional, o que significa que a infraestrutura que executa seus serviços do Cloud Run está localizada em uma região específica e é gerenciada pelo Google para estar disponível de maneira redundante em todas as zonas da região.

Atender aos seus requisitos de latência, disponibilidade ou durabilidade são os principais fatores para selecionar a região em que seus serviços do Cloud Run são executados. Geralmente, é possível selecionar a região mais próxima de seus usuários, mas considere a localização dos outros produtos do Google Cloud usados pelo serviço do Cloud Run. O uso de produtos do Google Cloud em vários locais pode afetar a latência e o custo do serviço.

O Cloud Run está disponível nas regiões a seguir:

Sujeitas aos preços do nível 1

  • asia-east1 (Taiwan)
  • asia-northeast1 (Tóquio)
  • asia-northeast2 (Osaka)
  • europe-north1 (Finlândia) Ícone de folha Baixo CO2
  • europe-southwest1 (Madri) Ícone de folha Baixo CO2
  • europe-west1 (Bélgica) Ícone de folha Baixo CO2
  • europe-west4 (Países Baixos) Ícone de folha Baixo CO2
  • europe-west8 (Milão)
  • europe-west9 (Paris) Ícone de folha Baixo CO2
  • me-west1 (Tel Aviv)
  • us-central1 (Iowa) Ícone de folha Baixo CO2
  • us-east1 (Carolina do Sul)
  • us-east4 (Norte da Virgínia)
  • us-east5 (Columbus)
  • us-south1 (Dallas) Ícone de folha Baixo CO2
  • us-west1 (Oregon) Ícone de folha Baixo CO2

Sujeitas aos preços do nível 2

  • africa-south1 (Johannesburgo)
  • asia-east2 (Hong Kong)
  • asia-northeast3 (Seul, Coreia do Sul)
  • asia-southeast1 (Singapura)
  • asia-southeast2 (Jacarta)
  • asia-south1 (Mumbai, Índia)
  • asia-south2 (Déli, Índia)
  • australia-southeast1 (Sydney)
  • australia-southeast2 (Melbourne)
  • europe-central2 (Varsóvia, Polônia)
  • europe-west10 (Berlim) Ícone de folha Baixo CO2
  • europe-west12 (Turim)
  • europe-west2 (Londres, Reino Unido) Ícone de folha Baixo CO2
  • europe-west3 (Frankfurt, Alemanha) Ícone de folha Baixo CO2
  • europe-west6 (Zurique, Suíça) Ícone de folha Baixo CO2
  • me-central1 (Doha)
  • me-central2 (Damã)
  • northamerica-northeast1 (Montreal) Ícone de folha Baixo CO2
  • northamerica-northeast2 (Toronto) Ícone de folha Baixo CO2
  • southamerica-east1 (São Paulo, Brasil) Ícone de folha Baixo CO2
  • southamerica-west1 (Santiago, Chile) Ícone de folha Baixo CO2
  • us-west2 (Los Angeles)
  • us-west3 (Salt Lake City)
  • us-west4 (Las Vegas)

Se você já criou um serviço do Cloud Run, é possível visualizar a região no painel do Cloud Run no console do Google Cloud.

Como recuperar o exemplo de código

Para recuperar o exemplo de código para uso, siga estas etapas:

  1. Clone o repositório do aplicativo de amostra na máquina local:

    git clone https://github.com/GoogleCloudPlatform/cloud-run-samples.git

    Outra alternativa é fazer o download da amostra como um arquivo ZIP e extraí-lo.

  2. Mude para o diretório que contém o código de amostra do Cloud Run:

    cd cloud-run-samples/gcloud-report/

Revisar o código

Esta seção inclui informações sobre o exemplo de código que você recuperou.

Gerar um relatório e fazer upload dele no Cloud Storage

Esse script de shell gera um relatório dos serviços do Cloud Run no projeto e na região atuais e faz upload do resultado para o Cloud Storage. Ele lista os serviços cujo nome contém o argumento search de string fornecido.

O script usa o comando gcloud run services list, opções de formato avançado da gcloud e o modo de cópia da transferência por streaming da gcloud.

set -eo pipefail

# Check for required environment variables.
requireEnv() {
  test "${!1}" || (echo "gcloud-report: '$1' not found" >&2 && exit 1)
}
requireEnv GCLOUD_REPORT_BUCKET

# Prepare formatting: Default search term to include all services.
search=${1:-'.'}
limits='spec.template.spec.containers.resources.limits.flatten("", "", " ")'
format='table[box, title="Cloud Run Services"](name,status.url,metadata.annotations.[serving.knative.dev/creator],'${limits}')'

# Create a specific object name that will not be overridden in the future.
obj="gs://${GCLOUD_REPORT_BUCKET}/report-${search}-$(date +%s).txt"

# Write a report containing the service name, service URL, service account or user that
# deployed it, and any explicitly configured service "limits" such as CPU or Memory.
gcloud run services list \
  --format "${format}" \
  --filter "metadata.name~${search}" | gsutil -q cp -J - "${obj}"

# /dev/stderr is sent to Cloud Logging.
echo "gcloud-report: wrote to ${obj}" >&2
echo "Wrote report to ${obj}"

Esse script é seguro para ser executado como um serviço, porque invocações repetidas dele atualizam o relatório sem que haja mais desligamentos de usuários. Outros scripts que usam a CLI gcloud podem ser mais caros quando invocados repetidamente, como criar novos recursos do Cloud ou realizar tarefas caras. Scripts idempotentes, que geram o mesmo resultado em invocações repetidas, são mais seguros para executar como um serviço.

Invocar o script na solicitação HTTP

Este código em Go configura um serviço da Web que executa um script de shell para gerar um relatório. Como a consulta de pesquisa é uma entrada do usuário, o código a valida para garantir que ela contenha apenas letras, números ou hífens para impedir comandos maliciosos como entrada. Esse conjunto de caracteres é restrito o suficiente para evitar ataques de injeção de comandos.

O serviço da Web passa o parâmetro de pesquisa como um argumento para o script de shell.


// Service gcloud-report is a Cloud Run shell-script-as-a-service.
package main

import (
	"log"
	"net/http"
	"os"
	"os/exec"
	"regexp"
)

func main() {
	http.HandleFunc("/", scriptHandler)

	// Determine port for HTTP service.
	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
		log.Printf("defaulting to port %s", port)
	}

	// Start HTTP server.
	log.Printf("listening on port %s", port)
	if err := http.ListenAndServe(":"+port, nil); err != nil {
		log.Fatal(err)
	}
}

func scriptHandler(w http.ResponseWriter, r *http.Request) {
	search := r.URL.Query().Get("search")
	re := regexp.MustCompile(`^[a-z]+[a-z0-9\-]*$`)
	if !re.MatchString(search) {
		log.Printf("invalid search criteria %q, using default", search)
		search = "."
	}

	cmd := exec.CommandContext(r.Context(), "/bin/bash", "script.sh", search)
	cmd.Stderr = os.Stderr
	out, err := cmd.Output()
	if err != nil {
		log.Printf("Command.Output: %v", err)
		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	}
	w.Write(out)
}

Um arquivo go.mod declara as dependências do aplicativo em um módulo go:

module github.com/GoogleCloudPlatform/cloud-run-samples/gcloud-report

go 1.19

Definir o ambiente do contêiner

O Dockerfile define como o ambiente é agrupado para o serviço. Ele é semelhante ao Dockerfile do guia de início rápido "helloworld-shell", exceto que a imagem do contêiner final é baseada na imagem da CLI do Google Cloud gcloud. Isso permite que seu serviço use o gcloud sem precisar de instalação personalizada e e as etapas de configuração da CLI do Google Cloud.


# Use the official golang image to create a binary.
# This is based on Debian and sets the GOPATH to /go.
# https://hub.docker.com/_/golang
FROM golang:1.20-buster as builder

# Create and change to the app directory.
WORKDIR /app

# Retrieve application dependencies.
# This allows the container build to reuse cached dependencies.
# Expecting to copy go.mod and if present go.sum.
COPY go.* ./
RUN go mod download

# Copy local code to the container image.
COPY invoke.go ./

# Build the binary.
RUN go build -mod=readonly -v -o server

# Use a gcloud image based on debian:buster-slim for a lean production container.
# https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds
FROM gcr.io/google.com/cloudsdktool/cloud-sdk:slim

WORKDIR /app

# Copy the binary to the production image from the builder stage.
COPY --from=builder /app/server /app/server
COPY *.sh /app/
RUN chmod +x /app/*.sh

# Run the web service on container startup.
CMD ["/app/server"]

Criar um repositório padrão do Artifact Registry

Crie um repositório padrão do Artifact Registry para armazenar a imagem do contêiner:

gcloud artifacts repositories create REPOSITORY \
    --repository-format=docker \
    --location=REGION

Substitua:

  • REPOSITORY por um nome exclusivo para o repositório.
  • REGION pela região do Google Cloud do Artifact Registry.

Configurar o bucket do Cloud Storage

Crie um bucket do Cloud Storage para fazer upload de relatórios:

gcloud storage buckets create gs://REPORT_ARCHIVE_BUCKET

Substitua REPORT_ARCHIVE_BUCKET por um nome de bucket globalmente exclusivo.

Configurar a identidade do serviço

Para limitar os privilégios que o serviço tem a outra infraestrutura, crie uma identidade de serviço e personalize as permissões específicas do IAM necessárias para fazer o trabalho.

Nesse caso, os privilégios necessários são permissão para ler serviços do Cloud Run e permissão para ler e gravar no bucket do Cloud Storage.

  1. Crie uma conta de serviço:

    gcloud iam service-accounts create gcloud-report-identity

  2. Conceder permissão à conta de serviço para ler os serviços do Cloud Run:

    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member=serviceAccount:gcloud-report-identity@PROJECT_ID.iam.gserviceaccount.com \
      --role roles/run.viewer
  3. Conceder permissão à conta de serviço para ler e gravar no bucket do Cloud Storage:

    gcloud storage buckets add-iam-policy-binding gs://REPORT_ARCHIVE_BUCKET \
      --member=serviceAccount:gcloud-report-identity@PROJECT_ID.iam.gserviceaccount.com \
      --role=roles/storage.objectUser

O acesso limitado dessa identidade de serviço personalizada impede que o serviço acesse outros recursos do Google Cloud.

Enviar o serviço

O código de envio é composto de três etapas:

  • Criar uma imagem de contêiner com o Cloud Build
  • Enviar a imagem do contêiner para o Artifact Registry
  • Implantar a imagem de contêiner no Cloud Run.

Para enviar o código, siga estas etapas:

  1. Compile seu contêiner e publique no Artifact Registry:

    gcloud builds submit --tag REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/gcloud-report

    Substitua:

    • PROJECT_ID pelo ID do projeto do Google Cloud
    • REPOSITORY pelo nome do repositório do Artifact Registry.
    • REGION pela região do Google Cloud do Artifact Registry.

    gcloud-report é o nome do serviço.

    Após a conclusão, uma mensagem de sucesso exibe o ID, a hora da criação e o nome da imagem. A imagem é armazenada no Artifact Registry e poderá ser reutilizada se necessário.

  2. Execute o comando a seguir para implantar o serviço:

    gcloud run deploy gcloud-report \
       --image REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/gcloud-report \
       --update-env-vars GCLOUD_REPORT_BUCKET=REPORT_ARCHIVE_BUCKET \
       --service-account gcloud-report-identity \
       --no-allow-unauthenticated

    Substitua:

    • PROJECT_ID pelo ID de projeto do Google Cloud;
    • REPOSITORY pelo nome do repositório do Artifact Registry.
    • REGION pela região do Google Cloud do serviço.

    gcloud-report faz parte do nome do contêiner e do serviço. A imagem de contêiner é implantada no serviço e na região (Cloud Run) que você configurou anteriormente em Como configurar a gcloud.

    A sinalização --no-allow-unauthenticated restringe o acesso não autenticado ao serviço. Mantendo o serviço particular, a autenticação integrada do Cloud Run bloqueia solicitações não autorizadas. Para mais detalhes sobre autenticação baseada no Identity and Access Management (IAM), consulte Como gerenciar o acesso usando o IAM.

    Aguarde a conclusão da implantação. Isso pode levar cerca de meio minuto. Em caso de sucesso, a linha de comando exibe o URL de serviço.

  3. Se você quer implantar uma atualização de código no serviço, repita as etapas anteriores. Cada implantação em um serviço cria uma nova revisão e inicia automaticamente o tráfego de serviço quando estiver pronto.

Consulte Como gerenciar o acesso usando o IAM para saber como conceder acesso aos usuários do Google Cloud para invocar esse serviço. Os editores e proprietários do projeto têm esse acesso automaticamente.

Gerar um relatório

Para gerar um relatório dos serviços do Cloud Run:

  1. Use curl para enviar uma solicitação autenticada:

    curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" SERVICE_URL

    Substitua SERVICE_URL pelo URL fornecido pelo Cloud Run após concluir a implantação.

    Se você criou um novo projeto e seguiu este tutorial, a saída será semelhante a:

    Wrote report to gs://REPORT_ARCHIVE_BUCKET/report-.-DATE.txt

    O . no nome do arquivo é o argumento de pesquisa padrão, conforme mencionado no código-fonte.

    Para usar o recurso de pesquisa, adicione um argumento search à solicitação:

    curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" SERVICE_URL?search=gcloud

    Esta consulta retornará uma resposta como esta:

    Wrote report to gs://REPORT_ARCHIVE_BUCKET/report-gcloud-DATE.txt
  2. Extraia o arquivo usando a CLI gcloud localmente:

    gcloud storage cp gs://REPORT_FILE_NAME .

    O . no comando significa o diretório de trabalho atual.

    Substitua REPORT_FILE_NAME pela saída do nome do objeto do Cloud Storage na etapa anterior.

Abra o arquivo para ver o relatório. Você verá o seguinte:

Captura de tela da lista de serviços do Cloud Run no projeto com colunas para quatro atributos de serviço.
As quatro colunas são extraídas da descrição do serviço. Elas incluem o Nome do serviço, o URL atribuído na primeira implantação, o Criador inicial do serviço e os Limites de CPU e memória máximas do serviço.

Melhorar a robustez para o futuro

Se você pretende desenvolver mais esse serviço, considere reescrever em uma linguagem de programação mais robusta, usando a API Cloud Run e a biblioteca de cliente do Cloud Storage.

É possível examinar as chamadas de API que estão sendo feitas (e conferir alguns detalhes da autenticação) adicionando --log-http aos comandos da CLI da gcloud.

Automatizar esta operação

Agora que o relatório de serviços do Cloud Run pode ser acionado por uma solicitação HTTP, use automação para gerar relatórios quando você precisar deles:

Liberar memória

Se você criou um novo projeto para este tutorial, exclua o projeto. Se você usou um projeto atual e quer mantê-lo sem as alterações incluídas neste tutorial, exclua os recursos criados para o tutorial.

Como excluir o projeto

O jeito mais fácil de evitar cobranças é excluindo o projeto que você criou para o tutorial.

Para 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.

Como excluir recursos do tutorial

  1. Exclua o serviço do Cloud Run que você implantou neste tutorial:

    gcloud run services delete SERVICE-NAME

    SERVICE-NAME é o nome escolhido do serviço.

    Também é possível excluir os serviços do Cloud Run no Console do Google Cloud.

  2. Remova a configuração da região padrão da gcloud que você adicionou durante a configuração do tutorial:

     gcloud config unset run/region
    
  3. Remova a configuração do projeto:

     gcloud config unset project
    
  4. Exclua outros recursos do Google Cloud criados neste tutorial:

A seguir