Este tutorial descreve como migrar apps Web Node.js que estão a ser executadas no Heroku para o Cloud Run no Google Cloud. Este tutorial destina-se a arquitetos e proprietários de produtos que querem migrar as respetivas apps do Heroku para serviços geridos no Google Cloud.
O Cloud Run é uma plataforma de computação gerida que lhe permite executar contentores sem estado invocáveis através de pedidos HTTP. É criada com base no código aberto Knative, o que permite a portabilidade entre plataformas e suporta fluxos de trabalho de contentores e normas para a entrega contínua. A plataforma Cloud Run está bem integrada com o conjunto de produtos e facilita a conceção e o desenvolvimento de apps portáteis, escaláveis e resilientes. Google Cloud
Neste tutorial, vai aprender a migrar uma app Google Cloud escrita em Node.js e que usa o Heroku Postgres como um serviço de apoio no Heroku. A app Web está contentorizada e alojada no Cloud Run e usa o Cloud SQL para PostgreSQL como camada de persistência.
No tutorial, usa uma app simples denominada Tasks que lhe permite ver e criar tarefas. Estas tarefas são armazenadas no Heroku Postgres na implementação atual da app no Heroku.
Este tutorial pressupõe que conhece a funcionalidade básica do Heroku e que tem uma conta do Heroku (ou acesso a uma). Também pressupõe que tem conhecimentos sobre o Cloud Run, o Cloud SQL, o Docker e o Node.js.
Objetivos
- Crie uma imagem Docker para implementar a app no Cloud Run.
- Crie uma instância do Cloud SQL para PostgreSQL para servir como back-end após a migração para o Google Cloud.
- Reveja o código Node.js para compreender como o Cloud Run se liga ao Cloud SQL e para ver as alterações ao código (se existirem) necessárias para migrar do Heroku para o Cloud Run.
- Migre dados do Heroku Postgres para o Cloud SQL para PostgreSQL.
- Implemente a app no Cloud Run.
- Teste a app implementada.
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.
Também lhe pode ser cobrado o uso de recursos no Heroku.
Antes de começar
- 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.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Verify that billing is enabled for your Google Cloud project.
-
Enable the Cloud SQL, Cloud Build, Cloud Run, Container Registry, Service Networking, Serverless VPC Access APIs.
-
Make sure that you have the following role or roles on the project: Cloud Run > Cloud Run Admin, Cloud Storage > Storage Admin, Cloud SQL > Cloud SQL Admin, Compute Engine > Compute Network Admin, Resource Manager > Project IAM Admin, Cloud Build > Cloud Build Editor, Serverless VPC Access > Serverless VPC Access Admin, Logging > Logs Viewer, Service Accounts > Service Account Admin, Service Accounts > Service Account User, and Service Usage > Service Usage Consumer
Check for the roles
-
In the Google Cloud console, go to the IAM page.
Go to IAM - Select the project.
-
In the Principal column, find all rows that identify you or a group that you're included in. To learn which groups you're included in, contact your administrator.
- For all rows that specify or include you, check the Role column to see whether the list of roles includes the required roles.
Grant the roles
-
In the Google Cloud console, go to the IAM page.
Aceder ao IAM - Selecione o projeto.
- Clique em Conceder acesso.
-
No campo Novos responsáveis, introduza o identificador do utilizador. Normalmente, este é o endereço de email de uma Conta Google.
- Na lista Selecionar uma função, selecione uma função.
- Para conceder funções adicionais, clique em Adicionar outra função e adicione cada função adicional.
- Clique em Guardar.
-
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Verify that billing is enabled for your Google Cloud project.
-
Enable the Cloud SQL, Cloud Build, Cloud Run, Container Registry, Service Networking, Serverless VPC Access APIs.
-
Make sure that you have the following role or roles on the project: Cloud Run > Cloud Run Admin, Cloud Storage > Storage Admin, Cloud SQL > Cloud SQL Admin, Compute Engine > Compute Network Admin, Resource Manager > Project IAM Admin, Cloud Build > Cloud Build Editor, Serverless VPC Access > Serverless VPC Access Admin, Logging > Logs Viewer, Service Accounts > Service Account Admin, Service Accounts > Service Account User, and Service Usage > Service Usage Consumer
Check for the roles
-
In the Google Cloud console, go to the IAM page.
Go to IAM - Select the project.
-
In the Principal column, find all rows that identify you or a group that you're included in. To learn which groups you're included in, contact your administrator.
- For all rows that specify or include you, check the Role column to see whether the list of roles includes the required roles.
Grant the roles
-
In the Google Cloud console, go to the IAM page.
Aceder ao IAM - Selecione o projeto.
- Clique em Conceder acesso.
-
No campo Novos responsáveis, introduza o identificador do utilizador. Normalmente, este é o endereço de email de uma Conta Google.
- Na lista Selecionar uma função, selecione uma função.
- Para conceder funções adicionais, clique em Adicionar outra função e adicione cada função adicional.
- Clique em Guardar.
-
Abra o Cloud Shell.
No Cloud Shell, defina as variáveis de ambiente e os valores predefinidos para a CLI do Google Cloud usada neste tutorial.
gcloud config set project PROJECT_ID gcloud config set run/region us-central1
Substitua
PROJECT_ID
pelo ID do seu projeto.Inicie sessão na consola Web do Heroku e, de seguida, na página de definições da conta, copie o valor da chave da API.
No Cloud Shell, instale a CLI Heroku
No Cloud Shell, autentique a CLI do Heroku. Quando lhe for pedida a palavra-passe, introduza o valor da chave da API que copiou da consola do Heroku e não a palavra-passe que usa para iniciar sessão na consola.
heroku login --interactive
No Cloud Shell, clone o repositório do GitHub da app Tasks de exemplo:
git clone https://github.com/GoogleCloudPlatform/migrate-webapp-heroku-to-cloudrun-node.git
Altere os diretórios para o diretório criado através da clonagem do repositório:
cd migrate-webapp-heroku-to-cloudrun-node
O diretório contém os seguintes ficheiros:
- Um script Node.js denominado
index.js
com o código para as rotas publicadas pela app Web. package.json
epackage-lock.json
que descrevem as dependências da app Web. Tem de instalar estas dependências para que a app seja executada.- Um ficheiro
Procfile
que especifica o comando que a app executa no arranque. Crie um ficheiroProcfile
para implementar a sua app no Heroku. - Um diretório
views
com o conteúdo HTML publicado pela app Web na rota "/". - Um ficheiro
.gitignore
.
- Um script Node.js denominado
No Cloud Shell, crie uma app Heroku:
heroku create
Tome nota do nome criado para a app. Precisa deste valor no passo seguinte.
Crie uma variável de ambiente para o nome da app Heroku:
export APP_NAME=APP_NAME
Substitua
APP_NAME
pelo nome da app devolvido pelo comandoheroku create
.Adicione o suplemento Heroku Postgres para aprovisionar uma base de dados PostgreSQL:
heroku addons:create heroku-postgresql:mini
Certifique-se de que o suplemento foi adicionado com êxito:
heroku addons
Se o suplemento Postgres tiver sido adicionado com êxito, é apresentada uma mensagem semelhante à seguinte:
Add-on Plan Price State ----------------- ----- -------- ----- heroku-postgresql mini 5$/month created
Implemente a app no Heroku:
git push heroku master
Execute o seguinte comando para confirmar o valor de DATABASE_URL.
heroku config
Anote o valor obtido para DATABASE_URL. Precisa deste valor no passo seguinte.
Execute um contentor Docker.
docker run -it --rm postgres psql "DATABASE_URL"
Substitua
DATABASE_URL
pelo URL do Heroku Postgres que anotou no passo anterior.No contentor do Docker, crie a tabela
TASKS
com o seguinte comando:CREATE TABLE TASKS (DESCRIPTION TEXT NOT NULL);
Saia do contentor:
exit
No Cloud Shell, execute o seguinte comando para obter o URL da Web da sua app Heroku:
heroku info
Abra o URL da Web numa janela do navegador. A app tem o seguinte aspeto: captura de ecrã (embora a sua versão não tenha as tarefas apresentadas):
Crie tarefas de exemplo na sua app a partir do navegador. Certifique-se de que as tarefas são obtidas a partir da base de dados e estão visíveis na IU.
No Cloud Shell, crie um Dockerfile no diretório criado pela clonagem do repositório para este tutorial:
cat <<"EOF" > Dockerfile # Use the official Node image. # https://hub.docker.com/_/node FROM node:10-alpine # Create and change to the app directory. WORKDIR /app # Copying this separately prevents re-running npm install on every code change. COPY package*.json ./ RUN npm install # Copy local code to the container image. COPY . /app # Configure and document the service HTTP port. ENV PORT 8080 EXPOSE $PORT # Run the web service on container startup. CMD ["npm", "start"] EOF
Crie o contentor com o Cloud Build e publique a imagem no Container Registry:
gcloud builds submit --tag gcr.io/PROJECT_ID/APP_NAME:1 \ --gcs-log-dir=gs://PROJECT_ID_cloudbuild
Crie uma variável de ambiente para guardar o nome da imagem do Docker que criou:
export IMAGE_NAME="gcr.io/PROJECT_ID/APP_NAME:1"
No Cloud Shell, instale a CLI pack.
Defina a CLI pack para usar o criador do Heroku por predefinição:
pack config default-builder heroku/buildpacks:22
Crie uma variável de ambiente para guardar o nome da imagem do Docker:
export IMAGE_NAME=gcr.io/PROJECT_ID/APP_NAME:1
Crie a imagem com o comando
pack
e envie ou publique a imagem para o Container Registry:pack build --publish $IMAGE_NAME
Prepare a sua rede para o Cloud SQL com um endereço IP privado.
gcloud compute addresses create google-managed-services-default \ --global \ --purpose=VPC_PEERING \ --prefix-length=16 \ --description="peering range for CloudSQL Private Service Access" \ --network=default gcloud services vpc-peerings connect \ --service=servicenetworking.googleapis.com \ --ranges=google-managed-services-default \ --network=default \ --project=PROJECT_ID
Crie uma variável de ambiente denominada
CLOUDSQL_DB_NAME
para armazenar o nome da instância da base de dados que criar no passo seguinte:export CLOUDSQL_DB_NAME=tasks-db
Crie a base de dados:
gcloud sql instances create $CLOUDSQL_DB_NAME \ --cpu=1 \ --memory=4352Mib \ --database-version=POSTGRES_15 \ --region=us-central1 \ --network default \ --no-assign-ip
A instância pode demorar alguns minutos a ser inicializada.
Defina uma palavra-passe para o utilizador do Postgres:
gcloud sql users set-password postgres \ --instance=$CLOUDSQL_DB_NAME \ --password=POSTGRES_PASSWORD
Substitua
POSTGRES_PASSWORD
pela palavra-passe que quer usar para a base de dados do Postgres.No Cloud Shell, obtenha as credenciais da base de dados para a sua base de dados Heroku Postgres associada à app de exemplo. Precisa destas credenciais no passo seguinte.
heroku pg:credentials:url
Este comando devolve a string de informações de ligação e o URL de ligação para a sua aplicação. A string de informações de ligação tem o seguinte formato:
"dbname=DATABASE_NAME host=FQDN port=5432 user=USER_NAME password=PASSWORD_STRING sslmode=require"
Precisa dos valores apresentados na string de ligação no passo seguinte.
Para ver um exemplo de um valor FQDN (nome de domínio totalmente qualificado) numa string de informações de ligação, consulte a documentação do Heroku.
Defina variáveis de ambiente para conter valores do Heroku que usa nos passos subsequentes:
export HEROKU_PG_DBNAME=DATABASE_NAME export HEROKU_PG_HOST=FQDN export HEROKU_PG_USER=USER_NAME export HEROKU_PG_PASSWORD=PASSWORD_STRING
Substitua o seguinte:
DATABASE_NAME
: o nome da base de dados apresentado na string de informações.FQDN
: o FQDN apresentado na string de informações.USER_NAME
: o nome do utilizador apresentado na string de informações.PASSWORD_STRING
: a string da palavra-passe apresentada na string de informações.
Crie uma cópia de segurança em formato SQL da sua base de dados Heroku Postgres:
docker run \ -it --rm \ -e PGPASSWORD=$HEROKU_PG_PASSWORD \ -v $(pwd):/tmp \ --entrypoint "pg_dump" \ postgres \ -Fp \ --no-acl \ --no-owner \ -h $HEROKU_PG_HOST \ -U $HEROKU_PG_USER \ $HEROKU_PG_DBNAME > herokudump.sql
Crie uma variável de ambiente para armazenar o nome do seu contentor do Cloud Storage:
export PG_BACKUP_BUCKET=gs://PROJECT_ID-pg-backup-bucket
Crie um contentor do Cloud Storage:
gcloud storage buckets create $PG_BACKUP_BUCKET \ --location=us-central1 \ --public-access-prevention \ --uniform-bucket-level-access
Carregue o ficheiro SQL para este contentor:
gcloud storage cp herokudump.sql $PG_BACKUP_BUCKET/herokudump.sql
Autorize a sua instância do Cloud SQL com as funções necessárias para importar o ficheiro SQL do contentor do Cloud Storage:
gcloud projects add-iam-policy-binding PROJECT_ID \ --member=serviceAccount:$(gcloud sql instances describe $CLOUDSQL_DB_NAME --format='get("serviceAccountEmailAddress")') \ --role=roles/storage.objectAdmin gcloud projects add-iam-policy-binding PROJECT_ID \ --member=serviceAccount:$(gcloud sql instances describe $CLOUDSQL_DB_NAME --format='get("serviceAccountEmailAddress")') \ --role=roles/cloudsql.editor
Importe o ficheiro SQL para a instância do Cloud SQL:
gcloud sql import sql $CLOUDSQL_DB_NAME $PG_BACKUP_BUCKET/herokudump.sql \ --database=postgres \ --user=postgres
Quando lhe for pedido
do you want to continue (y/n)
, introduza "y".No Cloud Shell, configure o acesso VPC sem servidor para permitir tráfego privado do Cloud Run para o Cloud SQL:
gcloud compute networks subnets create serverless-connector-subnet \ --network=default \ --range=10.0.0.0/28 \ --region=us-central1 gcloud compute networks vpc-access connectors create serverless-connector \ --region=us-central1 \ --subnet=serverless-connector-subnet
No Cloud Shell, crie uma variável de ambiente que contenha o nome de ligação da instância do Cloud SQL que criou:
export DB_CONN_NAME=$(gcloud sql instances describe $CLOUDSQL_DB_NAME --format='value(connectionName)')
Crie uma variável de ambiente denominada
DATABASE_URL
para conter a string de ligação para ligar ao proxy do Cloud SQL através de uma porta UNIX.export DATABASE_URL="socket:/cloudsql/${DB_CONN_NAME}?db=postgres&user=postgres&password=POSTGRES_PASSWORD"
Crie uma conta de serviço para o Cloud Run com uma função do IAM para ligar à base de dados:
gcloud iam service-accounts create sa-run-db-client gcloud projects add-iam-policy-binding PROJECT_ID \ --member=serviceAccount:sa-run-db-client@PROJECT_ID.iam.gserviceaccount.com \ --role=roles/cloudsql.client
Implemente a app Web no Cloud Run:
gcloud run deploy tasksapp-PROJECT_ID \ --image=$IMAGE_NAME \ --service-account=sa-run-db-client@PROJECT_ID.iam.gserviceaccount.com \ --set-env-vars=DATABASE_URL=$DATABASE_URL \ --add-cloudsql-instances $DB_CONN_NAME \ --vpc-connector serverless-connector \ --allow-unauthenticated
O comando anterior também associa o seu contentor do Cloud Run à instância da base de dados do Cloud SQL que criou. O comando define uma variável de ambiente para o Cloud Run apontar para a string
DATABASE_URL
que criou no passo anterior.No Cloud Shell, obtenha o URL no qual o Cloud Run serve tráfego:
gcloud run services list
Também pode rever o serviço do Cloud Run na Google Cloud consola.
Certifique-se de que a sua app Web está a aceitar pedidos HTTP navegando para o URL do serviço do Cloud Run.
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
- Saiba como importar dados para o Cloud SQL.
- Explore a documentação do Cloud Run.
Configurar o seu ambiente
Arquitetura
As figuras seguintes descrevem a arquitetura da app Web no Heroku (tal como está) e o esquema arquitetónico no Google Cloud (que vai criar).
A app Tasks implementada atualmente no Heroku consiste em um ou mais web dynos. Os dynos Web podem receber e responder ao tráfego HTTP, ao contrário dos dynos de trabalho, que são mais adequados para tarefas em segundo plano e tarefas programadas. A app apresenta uma página de índice que apresenta tarefas armazenadas numa base de dados Postgres, usando a biblioteca de modelos Mustache para Node.js.
Pode aceder à app através de um URL HTTPS. Uma rota /tasks
nesse URL permite-lhe
criar novas tarefas.
No Google Cloud, o Cloud Run é usado como a plataforma sem servidor para implementar a app Tasks. O Cloud Run foi concebido para executar contentores sem estado e baseados em pedidos. É adequado quando precisa que o seu serviço gerido suporte apps contentorizadas com escala automática e também escala para zero quando não estão a publicar tráfego.
Mapeamento de componentes usados no Heroku para o Google Cloud
A tabela seguinte mapeia os componentes na plataforma Heroku para Google Cloud. Este mapeamento ajuda a traduzir a arquitetura descrita neste tutorial do Heroku para o Google Cloud.
Componente | Plataforma Heroku | Google Cloud |
---|---|---|
Contentores | Dynos: O Heroku usa o modelo de contentor para criar e dimensionar apps Heroku. Estes contentores Linux são denominados dynos e podem ser dimensionados para um número que especificar para suportar as exigências de recursos da sua app Heroku. Pode selecionar entre uma variedade de tipos de dynos com base nos requisitos de memória e CPU da sua app. | Contentores do Cloud Run: Google Cloud suporta a execução de cargas de trabalho em contentores sem estado que podem ser executados num ambiente totalmente gerido ou em clusters do Google Kubernetes Engine (GKE). |
App Web | App Heroku: os dynos são os elementos básicos das apps Heroku. Normalmente, as apps consistem num ou mais tipos de dynos, geralmente uma combinação de dynos web e worker. | Serviço do Cloud Run: uma app Web pode ser modelada como um serviço do Cloud Run. Cada serviço tem o seu próprio ponto final HTTPS e pode ser automaticamente dimensionado para cima ou para baixo de 0 a N com base no tráfego para o ponto final do seu serviço. |
Bases de dados | O Heroku Postgres é a base de dados da Heroku como serviço (DaaS) baseada no PostgreSQL. | O Cloud SQL é um serviço de base de dados gerido para bases de dados relacionais no Google Cloud. |
Implementar a app Web Tasks de exemplo no Heroku
As secções seguintes mostram como configurar a interface de linhas de comando (CLI) para o Heroku, clonar o repositório de origem do GitHub e implementar a app no Heroku.
Configure a interface de linhas de comando para o Heroku
Este tutorial executa a CLI do Heroku no Cloud Shell e tem de ser autenticado através de uma chave da API do Heroku. Quando executada no Cloud Shell, a CLI do Heroku não pode autenticar-se através de uma palavra-passe ou da autenticação baseada na Web.
Em alternativa, se executar o exemplo num terminal local, pode usar qualquer método de autenticação da CLI do Heroku. Quando executar o tutorial num terminal local, também tem de instalar a CLI do Google Cloud, o git e o Docker.
Clone o repositório de origem
Implemente uma app no Heroku
Preparar o código da app Web para a migração para o Cloud Run
Esta secção detalha os passos que tem de concluir para preparar a sua app Web para a implementação no Cloud Run.
Crie e publique o seu contentor Docker no Container Registry
Precisa de uma imagem Docker para criar o contentor da app para que possa ser executado no Cloud Run. Pode criar o contentor manualmente ou através de Buildpacks.
Crie o contentor manualmente
Crie um contentor com Buildpacks
Crie uma instância do Cloud SQL para PostgreSQL
Cria uma instância do Cloud SQL para PostgreSQL para servir como back-end para a app Web. Neste tutorial, o PostgreSQL é mais adequado como a app de exemplo implementada no Heroku, que usa uma base de dados Postgres como back-end. Para efeitos desta app, a migração para o Cloud SQL para PostgreSQL a partir de um serviço Postgres gerido não requer alterações ao esquema.
Importe dados para o Cloud SQL a partir do Heroku Postgres
Existem vários padrões de migração que pode usar para migrar dados para o Cloud SQL. Geralmente, a melhor abordagem que requer pouco ou nenhum tempo de inatividade é configurar o Cloud SQL como uma réplica da base de dados que está a ser migrada e tornar o Cloud SQL a instância principal após a migração. O Heroku Postgres não suporta réplicas externas (seguidores). Por isso, neste tutorial, vai usar ferramentas de código aberto para migrar o esquema da app.
Para a app Tasks neste tutorial, usa o utilitário pg_dump para exportar dados do Heroku Postgres para um contentor do Cloud Storage e, em seguida, importá-los para o Cloud SQL. Esta utilidade pode transferir dados entre versões homogéneas ou quando a versão da base de dados de destino é mais recente do que a da base de dados de origem.
Como o Cloud Run acede à base de dados do Cloud SQL
Tal como a app Web implementada no Heroku tem de se ligar à instância gerida do Heroku Postgres, o Cloud Run requer acesso ao Cloud SQL para poder ler e escrever dados.
O Cloud Run comunica com o Cloud SQL através do proxy do Cloud SQL que é ativado e configurado automaticamente quando implementa o contentor no Cloud Run. A base de dados não precisa de ter endereços IP externos aprovados porque toda a comunicação que recebe é do proxy através de TCP seguro.
O seu código tem de invocar operações de base de dados (como obter dados da base de dados ou escrever nela) invocando o proxy através de um socket UNIX.
Uma vez que esta app Web está escrita em Node.js, usa a biblioteca pg-connection-string
para analisar um URL da base de dados e criar um objeto config
. A vantagem desta abordagem é que torna a ligação à base de dados de back-end integrada no Heroku e no Cloud Run.
No passo seguinte, transmite o URL da base de dados como uma variável de ambiente quando implementa a app Web.
Implemente a app de exemplo no Cloud Run
Testar a aplicação
O Cloud Run cria ou inicia um novo contentor quando um pedido HTTP é enviado para o ponto final de publicação e se ainda não estiver a ser executado um contentor. Isto significa que o pedido que faz com que um novo contentor seja iniciado pode demorar um pouco mais a ser processado. Tendo em conta esse tempo adicional, considere o número de pedidos simultâneos que a sua app pode suportar e quaisquer requisitos de memória específicos que possa ter.
Para esta app, usa as predefinições de simultaneidade, que permitem que um serviço do Cloud Run processe 80 pedidos em simultâneo a partir de um único contentor.
Limpar
Para evitar incorrer em custos na sua conta do Google Cloud pelos recursos usados neste tutorial. Também pode eliminar os recursos criados no Heroku para este tutorial.
Elimine o Google Cloud projeto
Elimine a app Heroku
Para eliminar a app de exemplo implementada no Heroku e o suplemento PostgreSQL associado, execute o seguinte comando:
heroku apps:destroy -a APP_NAME