Linha de comandos gcloud num tutorial de serviço do Cloud Run


Neste tutorial, cria um inventário de serviços do Cloud Run usando a CLI do Google Cloud num serviço do Cloud Run. Pode aplicar o que aprende neste tutorial aos seus scripts de operações na nuvem existentes ou criar uma prova de conceito antes de usar bibliotecas de cliente para criar um serviço mais robusto.

Usa a CLI gcloud como qualquer script de shell num serviço Web, por exemplo, conforme mostrado no guia de início rápido da shell. No Cloud Run, ambas as ferramentas funcionam com serviços ao fazerem a autenticação automaticamente com a identidade do serviço do Cloud Run. Google CloudTodas as autorizações concedidas à identidade de serviço estão disponíveis para a CLI gcloud.

A CLI gcloud é tão amplamente capaz de recolher informações e gerir recursos em Google Cloud que o desafio de a usar num serviço Web é minimizar o risco de um autor da chamada usar indevidamente estas capacidades. Sem controlos de segurança, pode criar riscos para outros serviços ou recursos em execução no mesmo projeto, permitindo atividade maliciosa acidental ou intencional. Alguns exemplos destes riscos:

  • Ativar a deteção de endereços IP de máquinas virtuais privadas
  • Ativar o acesso a dados privados a partir de uma base de dados no mesmo projeto
  • Ativar a eliminação de outros serviços em execução

Vários passos neste tutorial mostram como impor controlos para minimizar os riscos, como especificar o comando gcloud a ser executado no código, em vez de o deixar aberto como uma entrada do utilizador.

A criação de scripts com a ferramenta de linha de comandos num serviço do Cloud Run é semelhante à utilização da linha de comandos localmente. A principal diferença são as restrições adicionais que deve adicionar em torno da lógica do script principal.

Objetivos

  • Escreva e crie um contentor personalizado com um Dockerfile
  • Escreva, crie e implemente um serviço do Cloud Run
  • Use a CLI gcloud de forma segura num serviço Web
  • Gere um relatório dos serviços do Cloud Run e guarde-o no Cloud Storage

Custos

Neste documento, usa os seguintes componentes faturáveis do Google Cloud:

Para gerar uma estimativa de custos com base na sua utilização projetada, use a calculadora de preços.

Os novos Google Cloud utilizadores podem ser elegíveis 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. Verify 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. Verify 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.
  8. Funções necessárias

    Para receber as autorizações de que precisa para concluir o tutorial, peça ao seu administrador para lhe conceder as seguintes funções da IAM no seu projeto:

    Para mais informações sobre a atribuição de funções, consulte o artigo Faça a gestão do acesso a projetos, pastas e organizações.

    Também pode conseguir as autorizações necessárias através de funções personalizadas ou outras funções predefinidas.

Configure as predefinições do gcloud

Para configurar o gcloud com as predefinições do seu serviço do Cloud Run:

  1. Defina o projeto predefinido:

    gcloud config set project PROJECT_ID

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

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

    gcloud config set run/region REGION

    Substitua REGION pela região do Cloud Run suportada à sua escolha.

Localizações do Cloud Run

O Cloud Run é regional, o que significa que a infraestrutura que executa os seus serviços do Cloud Run está localizada numa região específica e é gerida pela Google para estar disponível de forma redundante em todas as zonas dessa região.

O cumprimento dos requisitos de latência, disponibilidade ou durabilidade são fatores principais para selecionar a região onde os seus serviços do Cloud Run são executados. Geralmente, pode selecionar a região mais próxima dos seus utilizadores, mas deve considerar a localização dos outros Google Cloudprodutos usados pelo seu serviço do Cloud Run. A utilização Google Cloud de produtos em conjunto em várias localizações pode afetar a latência do seu serviço, bem como o custo.

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

Sujeito aos preços de Nível 1

  • asia-east1 (Taiwan)
  • asia-northeast1 (Tóquio)
  • asia-northeast2 (Osaca)
  • asia-south1 (Mumbai, Índia)
  • europe-north1 (Finlândia) ícone de folha Baixo CO2
  • europe-north2 (Estocolmo) ícone de folha Baixo CO2
  • europe-southwest1 (Madrid) í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 (Telavive)
  • northamerica-south1 (México)
  • us-central1 (Iowa) ícone de folha Baixo CO2
  • us-east1 (Carolina do Sul)
  • us-east4 (Virgínia do Norte)
  • us-east5 (Columbus)
  • us-south1 (Dallas) ícone de folha Baixo CO2
  • us-west1 (Oregão) ícone de folha Baixo CO2

Sujeito aos preços de Nível 2

  • africa-south1 (Joanesburgo)
  • asia-east2 (Hong Kong)
  • asia-northeast3 (Seul, Coreia do Sul)
  • asia-southeast1 (Singapura)
  • asia-southeast2 (Jacarta)
  • asia-south2 (Deli, Í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)
  • europe-west6 (Zurique, Suíça) ícone de folha Baixo CO2
  • me-central1 (Doha)
  • me-central2 (Dammam)
  • 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 já criou um serviço do Cloud Run, pode ver a região no painel de controlo do Cloud Run na Google Cloud consola.

Obter o exemplo de código

Para obter o exemplo de código para utilização:

  1. Clone o repositório da app de exemplo para a sua máquina local:

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

    Em alternativa, pode transferir o exemplo como um ficheiro ZIP e extraí-lo.

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

    cd cloud-run-samples/gcloud-report/

Reveja o código

Esta secção inclui informações acerca do exemplo de código que recuperou.

Gere um relatório e carregue-o para o Cloud Storage

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

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

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

Este script é seguro para ser executado como um serviço porque as invocações repetidas do mesmo atualizam o relatório sem mais rotatividade dispendiosa. Outros scripts que usam a CLI gcloud podem ser mais dispendiosos quando invocados repetidamente, como criar novos recursos da nuvem ou realizar tarefas dispendiosas. Os scripts idempotentes, que produzem o mesmo resultado em invocações repetidas, são mais seguros de executar como um serviço.

Invocar o script no pedido HTTP

Este código Go configura um serviço Web que executa um script de shell para gerar um relatório. Uma vez que a consulta de pesquisa é uma entrada do utilizador, o código valida-a para garantir que contém apenas letras, números ou hífenes para evitar comandos maliciosos como entrada. Este conjunto de carateres é suficientemente estreito para evitar ataques de injeção de comandos.

O serviço Web transmite o parâmetro de pesquisa como um argumento ao 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 ficheiro go.mod declara as dependências da aplicação num módulo Go:

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

go 1.19

Defina o ambiente do contentor

O Dockerfile define como o ambiente é organizado para o serviço. É semelhante ao Dockerfile do início rápido helloworld-shell, exceto que a imagem do contentor final se baseia na imagem da CLI Google Cloud gcloud. Isto permite que o seu serviço use o gcloud sem passos de instalação e configuração personalizados para a CLI 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"]

Crie um repositório padrão do Artifact Registry

Crie um repositório padrão do Artifact Registry para armazenar a imagem de contentor:

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

Substituir:

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

Configure o contentor do Cloud Storage

Crie um contentor do Cloud Storage para carregar relatórios:

gcloud storage buckets create gs://REPORT_ARCHIVE_BUCKET

Substitua REPORT_ARCHIVE_BUCKET por um nome de contentor exclusivo a nível global.

Configure a identidade do serviço

Para limitar os privilégios que o serviço tem para outra infraestrutura, cria uma identidade de serviço e personaliza as autorizações específicas da IAM necessárias para fazer o trabalho.

Neste caso, os privilégios necessários são a autorização para ler serviços do Cloud Run e a autorização para ler e escrever no contentor do Cloud Storage.

  1. Crie uma conta de serviço:

    gcloud iam service-accounts create gcloud-report-identity

  2. Conceda à conta de serviço autorização para ler 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. Conceda à conta de serviço autorização para ler e escrever no contentor 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 desta identidade de serviço personalizada impede que o serviço aceda a outros Google Cloud recursos.

Envie o serviço

O código de envio consiste em três passos:

  • Criar uma imagem de contentor com o Cloud Build
  • Carregar a imagem do contentor para o Artifact Registry
  • Implementar a imagem do contentor no Cloud Run.

Para enviar o código:

  1. Crie o contentor e publique-o no Artifact Registry:

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

    Substituir:

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

    gcloud-report é o nome do seu serviço.

    Em caso de êxito, é apresentada uma mensagem de ÊXITO com o ID, a hora de criação e o nome da imagem. A imagem é armazenada no Artifact Registry e pode ser reutilizada, se necessário.

  2. Execute o seguinte comando para implementar o seu 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

    Substituir:

    • PROJECT_ID com o seu Google Cloud ID do projeto.
    • REPOSITORY com o nome do repositório do Artifact Registry.
    • REGION com a Google Cloud região do serviço.

    gcloud-report faz parte do nome do contentor e do nome do serviço. A imagem do contentor é implementada no serviço e na região (Cloud Run) que configurou anteriormente em Configurar o gcloud.

    A flag --no-allow-unauthenticated restringe o acesso público ao serviço. Ao manter o serviço privado, pode confiar na autenticação integrada do Cloud Run para bloquear pedidos não autorizados. Para mais detalhes sobre a autenticação baseada na gestão de identidade e de acesso (IAM), consulte o artigo Gerir o acesso através da IAM.

    Aguarde até que a implementação esteja concluída. Esta operação pode demorar cerca de meio minuto. Se for bem-sucedido, a linha de comandos apresenta o URL do serviço.

  3. Se quiser implementar uma atualização de código no serviço, repita os passos anteriores. Cada implementação num serviço cria uma nova revisão e começa automaticamente a publicar tráfego quando estiver pronta.

Consulte o artigo Gerir o acesso através da IAM para saber como conceder Google Cloud acesso aos utilizadores para invocar este serviço. Os editores e os proprietários do projeto têm automaticamente este acesso.

Gere um relatório

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

  1. Use o curl para enviar um pedido autenticado:

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

    Substitua SERVICE_URL pelo URL fornecido pelo Cloud Run após a conclusão da implementação.

    Se criou um novo projeto e seguiu este tutorial, o resultado será semelhante ao seguinte:

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

    O . no nome do ficheiro é o argumento de pesquisa predefinido, conforme mencionado no código-fonte.

    Para usar a funcionalidade de pesquisa, adicione um argumento search ao pedido:

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

    Esta consulta devolve um resultado semelhante ao seguinte:

    Wrote report to gs://REPORT_ARCHIVE_BUCKET/report-gcloud-DATE.txt
  2. Recupere o ficheiro através da CLI gcloud localmente:

    gcloud storage cp gs://REPORT_FILE_NAME .

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

    Substitua REPORT_FILE_NAME pelo nome do objeto do Cloud Storage gerado no passo anterior.

Abra o ficheiro para ver o relatório. Deve ter esta forma:

Captura de ecrã 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. Incluem o Nome do serviço, o URL atribuído na primeira implementação, o Criador inicial do serviço e os Limites do serviço de CPU e memória máximos.

Melhore a robustez para o futuro

Se tencionar desenvolver ainda mais este serviço, considere reescrevê-lo numa linguagem de programação mais robusta e usar a API Cloud Run Admin e a biblioteca cliente do Cloud Storage.

Pode examinar as chamadas API que estão a ser feitas (e ver alguns detalhes de autenticação) adicionando --log-http aos comandos da CLI gcloud.

Automatize esta operação

Agora que o relatório dos serviços do Cloud Run pode ser acionado por um pedido HTTP, use a automatização para gerar relatórios quando precisar deles:

Limpar

Se criou um novo projeto para este tutorial, elimine o projeto. Se usou um projeto existente e quer mantê-lo sem as alterações adicionadas neste tutorial, elimine os recursos criados para o tutorial.

Eliminar o projeto

A forma mais fácil de eliminar a faturação é eliminar o projeto que criou para o tutorial.

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

Eliminar recursos do tutorial

  1. Elimine o serviço do Cloud Run que implementou neste tutorial:

    gcloud run services delete SERVICE-NAME

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

    Também pode eliminar serviços do Cloud Run a partir da Google Cloud consola.

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

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

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

O que se segue?