Tutorial Como usar o Filestore com o Cloud Run


Este tutorial mostra como instalar o Filestore como um sistema de arquivos de rede em um serviço do Cloud Run para compartilhar dados entre vários contêineres e serviços. Neste tutorial, usamos o ambiente de execução de segunda geração do Cloud Run.

O ambiente de execução de segunda geração permite que sistemas de arquivos de rede sejam ativados em um diretório no contêiner. Montar um sistema de arquivos permite compartilhar recursos entre um sistema host e instâncias, bem como manter os recursos após a coleta de lixo.

O uso de um sistema de arquivos de rede com o Cloud Run exige conhecimento avançado sobre o Docker, já que seu contêiner precisa executar vários processos, incluindo o processo de montagem e o aplicativo de sistema de arquivos. Neste tutorial, explicamos os conceitos necessários com um exemplo prático. No entanto, ao adaptar este tutorial ao seu aplicativo, é preciso entender as implicações de quaisquer alterações que você possa fazer.

Visão geral do design

A instância do Filestore é hospedada em uma rede de nuvem privada virtual (VPC). Os recursos de uma rede VPC usam um intervalo de endereços IP privados para se comunicar com as APIs e os serviços do Google. portanto, os clientes precisam estar na mesma rede que a instância do Filestore para acessar os arquivos armazenados nessa instância. É necessário um conector de acesso VPC sem servidor para que o serviço do Cloud Run possa se conectar à rede VPC para se comunicar com o Filestore. Saiba mais sobre o acesso VPC sem servidor.

filesystem-architecture

O diagrama mostra o serviço do Cloud Run conectado à instância do Filestore por meio de um conector de acesso VPC sem servidor. A instância e o conector do Filestore estão localizados na mesma rede VPC, "padrão", e na mesma região/zona que o serviço do Cloud Run para melhor desempenho.

Limitações

  • Neste tutorial, não descrevemos como escolher um sistema de arquivos ou requisitos prontos para produção. Saiba mais sobre o Filestore e os níveis de serviço disponíveis.

  • Neste tutorial, não mostramos como trabalhar com um sistema de arquivos ou discutir padrões de acesso a arquivos.

Objetivos

  • Criar uma instância do Filestore na rede VPC padrão para servir como um compartilhamento de arquivos.

  • Crie um conector de acesso VPC sem servidor na mesma rede VPC padrão para se conectar ao serviço do Cloud Run.

  • Crie um Dockerfile com pacotes do sistema e init-process para gerenciar os processos de montagem e de aplicativo.

  • Implante no Cloud Run e verifique o acesso ao sistema de arquivos no serviço.

Custos

Neste tutorial, há componentes faturáveis do Google Cloud, entre eles:

Antes de começars

  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. As permissões do IAM controlam apenas o acesso às operações do Filestore, como a criação de uma instância do Filestore. Para controlar o acesso a operações no compartilhamento de arquivos, como leitura ou execução, use as permissões do arquivo POSIX. Saiba mais sobre o controle de acesso.
  7. Enable the Cloud Run, Filestore, Serverless VPC Access, Artifact Registry, and Cloud Build APIs.

    Enable the APIs

  8. Instale e inicialize a CLI gcloud.
  9. Atualize a Google Cloud CLI: gcloud components update

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 como conceder papéis, consulte Gerenciar acesso.

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

Como configurar padrões do 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.

  3. Configure a gcloud para o Filestore:

    gcloud config set filestore/zone ZONE

    Substitua ZONE pela zona do Filestore compatível.

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:

    Node.js

    git clone https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git

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

    Python

    git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git

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

    Java

    git clone https://github.com/GoogleCloudPlatform/java-docs-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:

    Node.js

    cd nodejs-docs-samples/run/filesystem/

    Python

    cd python-docs-samples/run/filesystem/

    Java

    cd java-docs-samples/run/filesystem/

Noções básicas sobre o código

Normalmente, você precisa executar um único processo ou aplicativo em um contêiner. Executar um único processo por contêiner reduz a complexidade do gerenciamento do ciclo de vida de vários processos: gerenciamento de reinicializações, encerramento do contêiner se algum deles falhar e responsabilidades do PID 1, como encaminhamento de sinal e filho zumbi colhendo. No entanto, o uso de sistemas de arquivos de rede no Cloud Run exige que você use contêineres de vários processos para executar o aplicativo e o processo de montagem do sistema de arquivos. Neste tutorial, mostramos como encerrar o contêiner em caso de falha no processo e gerenciar as responsabilidades do PID 1. O comando de ativação tem funcionalidade integrada para lidar com novas tentativas.

É possível usar um gerenciador de processos para executar e gerenciar vários processos como o ponto de entrada do contêiner. Este tutorial usa tini, uma substituição de init que limpa processos zumbi e executa o encaminhamento de sinais. Especificamente, esse processo init permite que o sinal SIGTERM no encerramento seja propagado para o aplicativo. O sinal SIGTERM pode ser capturado para encerramento correto do aplicativo. Saiba mais sobre o ciclo de vida de um contêiner no Cloud Run.

Como definir sua configuração de ambiente com o Dockerfile

Esse serviço do Cloud Run requer um ou mais pacotes de sistema adicionais não disponíveis por padrão. A instrução RUN instalará tini como nosso processo init e nfs-common, que fornece o mínimo de funcionalidade de cliente NFS. Leia mais sobre como trabalhar com pacotes do sistema no serviço do Cloud Run no tutorial Como usar pacotes do sistema.

O próximo conjunto de instruções cria um diretório de trabalho, copia o código-fonte e instala as dependências do app.

O ENTRYPOINT especifica o binário init-process que é anexado às instruções do CMD. Neste caso, é o script de inicialização. Isso inicia um único processo tini e faz o proxy de todos os sinais recebidos para uma sessão com acesso root nesse processo filho.

A instrução CMD define o comando a ser executado ao executar a imagem, o script de inicialização. Ele também fornece argumentos padrão para o ENTRYPOINT. Entenda como CMD e ENTRYPOINT interagem.

Node.js


# Use the official Node.js image.
# https://hub.docker.com/_/node
FROM node:20-slim

# Install system dependencies
RUN apt-get update -y && apt-get install -y \
    tini \
    nfs-common \
	libtool \
    && apt-get clean

# Set fallback mount directory
ENV MNT_DIR /mnt/nfs/filestore

# Copy local code to the container image.
ENV APP_HOME /app
WORKDIR $APP_HOME
COPY package*.json ./

# Install production dependencies.
RUN npm install --only=production

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

# Ensure the script is executable
RUN chmod +x /app/run.sh

# Use tini to manage zombie processes and signal forwarding
# https://github.com/krallin/tini
ENTRYPOINT ["/usr/bin/tini", "--"]

# Pass the wrapper script as arguments to tini
CMD ["/app/run.sh"]

Python

# Use the official lightweight Python image.
# https://hub.docker.com/_/python
FROM python:3.11-slim

# Install system dependencies
RUN apt-get update -y && apt-get install -y \
    tini \
    nfs-common \
    && apt-get clean

# Set fallback mount directory
ENV MNT_DIR /mnt/nfs/filestore

# Copy local code to the container image.
ENV APP_HOME /app
WORKDIR $APP_HOME
COPY . ./

# Install production dependencies.
RUN pip install -r requirements.txt

# Ensure the script is executable
RUN chmod +x /app/run.sh

# Use tini to manage zombie processes and signal forwarding
# https://github.com/krallin/tini
ENTRYPOINT ["/usr/bin/tini", "--"]

# Pass the startup script as arguments to tini
CMD ["/app/run.sh"]

Java


# Use the official maven image to create a build artifact.
# https://hub.docker.com/_/maven
FROM maven:3-eclipse-temurin-17-alpine as builder

# Copy local code to the container image.
WORKDIR /app
COPY pom.xml .
COPY src ./src

# Build a release artifact.
RUN mvn package -DskipTests

# Use Eclipse Temurin for base image.
# https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds
FROM eclipse-temurin:18-jdk-focal

# Install filesystem dependencies
RUN apt-get update -y && apt-get install -y \
    tini \
    nfs-kernel-server \
    nfs-common \
    && apt-get clean

# Set fallback mount directory
ENV MNT_DIR /mnt/nfs/filestore

# Copy the jar to the production image from the builder stage.
COPY --from=builder /app/target/filesystem-*.jar /filesystem.jar

# Copy the statup script
COPY run.sh ./run.sh
RUN chmod +x ./run.sh

# Use tini to manage zombie processes and signal forwarding
# https://github.com/krallin/tini
ENTRYPOINT ["/usr/bin/tini", "--"]

# Run the web service on container startup.
CMD ["/run.sh"]

Como definir seus processos no script de inicialização

O script de inicialização cria um diretório para ser o ponto de montagem, em que a instância do Filestore ficará acessível. Em seguida, o script usa o comando mount para anexar a instância do Filestore, especificando o endereço IP da instância e o nome do compartilhamento de arquivos, até o ponto de montagem do serviço e inicia o servidor do aplicativo. O comando mount tem a funcionalidade de repetição integrada. Portanto, não é necessário mais scripts bash. Por fim, o comando wait é usado para detectar todos os processos em segundo plano para sair e sair do script.

Node.js

#!/usr/bin/env bash
set -eo pipefail

# Create mount directory for service.
mkdir -p $MNT_DIR

echo "Mounting Cloud Filestore."
mount -o nolock $FILESTORE_IP_ADDRESS:/$FILE_SHARE_NAME $MNT_DIR
echo "Mounting completed."

# Start the application
node index.js &

# Exit immediately when one of the background processes terminate.
wait -n

Python

#!/usr/bin/env bash
set -eo pipefail

# Create mount directory for service.
mkdir -p $MNT_DIR

echo "Mounting Cloud Filestore."
mount -o nolock $FILESTORE_IP_ADDRESS:/$FILE_SHARE_NAME $MNT_DIR
echo "Mounting completed."

# Run the web service on container startup. Here we use the gunicorn
# webserver, with one worker process and 8 threads.
# For environments with multiple CPU cores, increase the number of workers
# to be equal to the cores available.
# Timeout is set to 0 to disable the timeouts of the workers to allow Cloud Run to handle instance scaling.
exec gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 main:app

Java

#!/usr/bin/env bash
set -eo pipefail

# Create mount directory for service
mkdir -p $MNT_DIR

echo "Mounting Cloud Filestore."
mount -o nolock $FILESTORE_IP_ADDRESS:/$FILE_SHARE_NAME $MNT_DIR
echo "Mounting completed."

# Start the application
java -jar filesystem.jar

# Exit immediately when one of the background processes terminate.
wait -n

Como trabalhar com arquivos

Node.js

Consulte index.js para interagir com o sistema de arquivos.

Python

Consulte main.py para interagir com o sistema de arquivos.

Java

Consulte FilesystemApplication.java para interagir com o sistema de arquivos.

Como enviar o serviço

  1. Criar uma instância do Filestore:

    gcloud filestore instances create INSTANCE_ID \
        --tier=basic-hdd \
        --file-share=name=FILE_SHARE_NAME,capacity=1TiB \
        --network=name="default"

    Substitua INSTANCE_ID pelo nome da instância do Filestore, por exemplo, my-filestore-instance, e FILE_SHARE_NAME pelo nome do diretório exibido pela instância do Filestore, por exemplo, vol1. Veja mais informações em Como nomear sua instância e Como nomear o compartilhamento de arquivos.

    Os clientes (serviço do Cloud Run) precisam estar na mesma rede que a instância do Filestore para acessar os arquivos armazenados nessa instância. Esse comando cria a instância na rede VPC padrão e atribui um intervalo de endereços IP livre. Novos projetos começam com uma rede padrão e, provavelmente, não é necessário criar uma rede separada.

    Saiba mais sobre a configuração em Como criar instâncias.

  2. Configure um conector de acesso VPC sem servidor:

    Para se conectar à instância do Filestore , o serviço do Cloud Run (totalmente gerenciado) precisa acessar a rede VPC autorizada da instância do Filestore.

    Cada conector VPC requer a própria sub-rede /28 para colocar instâncias de conector. Ele não pode sobrepor nenhuma reserva de endereço IP atual na rede VPC. Por exemplo, 10.8.0.0 (/28) funcionará na maioria dos novos projetos ou é possível especificar outro intervalo de IP personalizado não utilizado, como 10.9.0.0 (/28). É possível ver quais intervalos de IP estão reservados no Console do Google Cloud.

    gcloud compute networks vpc-access connectors create CONNECTOR_NAME \
      --region REGION \
      --range "10.8.0.0/28"

    Substitua CONNECTOR_NAME pelo nome do conector.

    Esse comando cria um conector na rede VPC padrão, igual à instância do Filestore, com tamanho de máquina e2-micro. Aumentar o tamanho da máquina do conector melhora a capacidade do conector, mas também aumenta o custo. O conector também precisa estar na mesma região que o serviço do Cloud Run. Saiba mais sobre Como configurar o acesso VPC sem servidor.

  3. Defina uma variável de ambiente com o endereço IP da instância do Filestore:

    export FILESTORE_IP_ADDRESS=$(gcloud filestore instances describe INSTANCE_ID --format "value(networks.ipAddresses[0])")
  4. Crie uma conta de serviço para servir como a identidade de serviço. Por padrão, isso não tem privilégios além da associação ao projeto.

    gcloud iam service-accounts create fs-identity

    Esse serviço não precisa interagir com mais nada no Google Cloud. Portanto, nenhuma outra permissão precisa ser atribuída a essa conta de serviço.

  5. Crie e implante a imagem do contêiner no Cloud Run:

    gcloud run deploy filesystem-app --source . \
        --vpc-connector CONNECTOR_NAME \
        --execution-environment gen2 \
        --allow-unauthenticated \
        --service-account fs-identity \
        --update-env-vars FILESTORE_IP_ADDRESS=$FILESTORE_IP_ADDRESS,FILE_SHARE_NAME=FILE_SHARE_NAME

    Esse comando cria e implanta o serviço Cloud Run e especifica o conector de VPC e o ambiente de execução da segunda geração. A implantação da origem criará a imagem com base no Dockerfile e enviará a imagem ao repositório do Artifact Registry: cloud-run-source-deploy.

    Saiba mais sobre como implantar a partir do código-fonte.

Como depurar

Se a implantação não for bem-sucedida, verifique os detalhes do Cloud Logging.

  • Se a conexão expirar, verifique se você está fornecendo o endereço IP correto da instância do Filestore.

  • Se o acesso tiver sido negado pelo servidor, verifique se o nome do compartilhamento de arquivos está correto.

  • Se você quiser que todos os registros do processo de ativação usem a sinalização --verbose em combinação com o comando de ativação: mount --verbose -o nolock $FILESTORE_IP_ADDRESS:/$FILE_SHARE_NAME $MNT_DIR

Testar

Para testar o serviço completo:

  1. Navegue até o URL fornecido pela etapa de implantação acima.
  2. Você verá um arquivo recém-criado na instância do Filestore.
  3. Clique no arquivo para ver o conteúdo.

Se você optar por continuar desenvolvendo esses serviços, lembre-se de que eles têm acesso restrito do gerenciamento de identidade e acesso (IAM, na sigla em inglês) ao restante do Google Cloud e precisarão receber mais papéis do IAM para acessar muitos outros serviços.

Discussão sobre custos

Exemplo de detalhamento de custos para um serviço, hospedado em Iowa (us-central1) com uma instância do Filestore de 1 TiB e um conector de acesso VPC sem servidor. Acesse as páginas de preços individuais para ver os preços mais atualizados.

Produto Custo por mês
Filestore (não depende do montante usado) Custo = capacidade provisionada (1.024 GiB ou 1 TiB) * Preço do nível regional (us-central1)

Nível HDD básico: 1.024 GiB * US$ 0,16/mês = US $163,84
Zonal (SSD): 1.024 GiB * US$ 0,25/mês = US $256,00
Enterprise (SSD, disponibilidade regional): 1.024 GiB * US$ 0,45/mês = US $460,80
Acesso VPC sem servidor Custo = preço da máquina * número de instâncias (o mínimo de instâncias é 2)

f1-micro: US$ 3,88 * 2 instâncias = US$ 7,76
e2- micro: US$ 6,11 * 2 instâncias = US$ 12,22
e2-standard-4: US$ 97,83 * 2 instâncias = US$ 195,66
Cloud Run Custo = CPU + memória + solicitações + rede
Total US$ 163,84 + US$12,22 = US$ 176,06/mês + custo do Cloud Run

Este tutorial usa uma instância do Filestore no nível HDD básico. O nível de serviço de uma instância do Filestore é uma combinação do tipo de instância e do tipo de armazenamento. É possível fazer upgrade do tipo de instância para ter mais capacidade e escalonabilidade. É possível fazer upgrade do tipo de armazenamento para melhorar o desempenho. Saiba mais sobre as recomendações de tipo de armazenamento. A região e a capacidade também afetam os preços do Filestore. Por exemplo, uma instância de nível 1 TiB de HDD básico em Iowa (us-central1) custa US $0,16 por GiB ao mês, ou aproximadamente US $163,84 por mês.

O conector de acesso VPC sem servidor tem o preço por tamanho de instância e número, além da saída de rede. Aumentar o tamanho e o número pode melhorar a capacidade ou reduzir a latência nas mensagens. Há três tamanhos de máquinas: f1-micro, e2-micro e e2-standard-4. O número mínimo de instâncias é 2. Portanto, o custo mínimo é o dobro do tamanho da máquina.

O Cloud Run tem o preço calculado por uso de recursos, arredondado para os 100 ms mais próximos, para memória, CPU, número de solicitações e rede. Portanto, o custo varia de acordo com as configurações do serviço, o número de solicitações e o tempo de execução. Esse serviço custa no mínimo US$ 176,06 por mês. Veja e explore uma estimativa na calculadora de preços do Google Cloud.

Limpar

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