1. Visão geral
Este laboratório mostra as funcionalidades projetadas para simplificar o fluxo de trabalho de engenheiros de software responsáveis pelo desenvolvimento de aplicativos NodeJS em um ambiente conteinerizado. O desenvolvimento de contêineres típico exige que o usuário entenda os detalhes dos contêineres e do processo de criação do contêiner. Além disso, os desenvolvedores geralmente precisam interromper o fluxo, saindo do ambiente de desenvolvimento integrado para testar e depurar os aplicativos em ambientes remotos. Com as ferramentas e tecnologias mencionadas neste tutorial, os desenvolvedores podem trabalhar efetivamente com aplicativos conteinerizados sem sair do ambiente de desenvolvimento integrado.
O que você vai aprender
Neste laboratório, você vai aprender métodos para desenvolver com contêineres no Google Cloud, incluindo:
- Como criar um aplicativo Nodejs inicial
- Como configurar um aplicativo Nodejs para o desenvolvimento de contêineres
- Codificação de um serviço de descanso CRUD simples
- Como implantar no GKE
- Como depurar um estado de erro
- Como usar registros / pontos de interrupção
- Mudanças na implantação a quente no GKE
- Opcional: integrar o CloudSQL para persistência de back-end
2. Configuração e requisitos
Configuração de ambiente personalizada
- Faça login no Console do Google Cloud e crie um novo projeto ou reutilize um existente. Crie uma conta do Gmail ou do Google Workspace, se ainda não tiver uma.
- O Nome do projeto é o nome de exibição para os participantes do projeto. É uma string de caracteres não usada pelas APIs do Google Você pode atualizar a qualquer momento.
- O ID do projeto precisa ser exclusivo em todos os projetos do Google Cloud e não pode ser mudado após a definição. O console do Cloud gera automaticamente uma string exclusiva. normalmente você não se importa com o que seja. Na maioria dos codelabs, é necessário fazer referência ao ID do projeto, que normalmente é identificado como
PROJECT_ID
. Se você não gostar do ID gerado, poderá gerar outro ID aleatório. Como alternativa, você pode tentar o seu próprio e ver se ele está disponível. Ela não pode ser alterada após essa etapa e permanecerá durante a duração do projeto. - Para sua informação, há um terceiro valor, um Número de projeto, que algumas APIs usam. Saiba mais sobre esses três valores na documentação.
- Em seguida, ative o faturamento no console do Cloud para usar os recursos/APIs do Cloud. A execução deste codelab não será muito cara, se tiver algum custo. Para encerrar os recursos e não gerar faturamento além deste tutorial, exclua os recursos criados ou exclua o projeto inteiro. Novos usuários do Google Cloud estão qualificados para o programa de US$ 300 de avaliação sem custos.
Inicie o editor do Cloud Shell
Este laboratório foi elaborado e testado para uso com o Editor do Google Cloud Shell. Para acessar o editor,
- acesse seu projeto do Google em https://console.cloud.google.com.
- No canto superior direito, clique no ícone do editor do Cloud Shell
- Um novo painel será aberto na parte inferior da janela.
- Clique no botão "Abrir editor"
- O editor será aberto com um explorador à direita e o editor na área central.
- Um painel do terminal também deve estar disponível na parte inferior da tela
- Se o terminal NÃO estiver aberto, use a combinação de teclas "ctrl+" para abrir uma nova janela de terminal
Configurar a gcloud
No Cloud Shell, defina o ID do projeto e a região em que você quer implantar o aplicativo. Salve-as como variáveis PROJECT_ID
e REGION
.
export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')
Provisionar a infraestrutura usada neste laboratório
Neste laboratório, você vai implantar um código no GKE e acessar os dados armazenados em um banco de dados do CloudSQL. O script de configuração abaixo prepara essa infraestrutura para você.
- Baixe o script de configuração e torne-o executável.
wget https://raw.githubusercontent.com/GoogleCloudPlatform/container-developer-workshop/main/labs/nodejs/setup_with_cw.sh
chmod +x setup_with_cw.sh
- Abra o arquivo
setup_with_cw.sh
e edite os valores das senhas que estão definidos como CHANGEME no momento - Execute o script de configuração para criar um cluster do GKE e um banco de dados CloudSQL que você vai usar neste laboratório
./setup_with_cw.sh &
Cluster do Cloud Workstations
- Abra o Cloud Workstations no Console do Cloud. Aguarde o cluster estar no status
READY
.
Criar configuração de estações de trabalho
- Se a sessão do Cloud Shell tiver sido desconectada, clique em "Reconectar". e execute o comando gcloud cli para definir o ID do projeto. Substitua o ID do projeto de exemplo abaixo pelo ID do projeto do Qwiklabs antes de executar o comando.
gcloud config set project qwiklabs-gcp-project-id
- Faça o download e execute o script abaixo no terminal para criar a configuração do Cloud Workstations.
wget https://raw.githubusercontent.com/GoogleCloudPlatform/container-developer-workshop/main/labs/nodejs/workstation_config_setup.sh
chmod +x workstation_config_setup.sh
./workstation_config_setup.sh
- Verifique os resultados na seção "Configurações". A transição para o status READY levará dois minutos.
- Abra Cloud Workstations no console e crie uma nova instância.
- Mude o nome para
my-workstation
e selecione a configuração atual:codeoss-js
.
- Verifique os resultados na seção "Estações de trabalho".
Iniciar estação de trabalho
- Inicie e inicie a estação de trabalho. A estação de trabalho pode levar alguns minutos para ser iniciada.
- Clique no ícone na barra de endereço para permitir cookies de terceiros.
- Clique em "O site não está funcionando?".
- Clique em "Permitir cookies".
- Depois que a estação de trabalho for iniciada, o ambiente de desenvolvimento integrado Code OSS vai aparecer. Clique em "Marcar como concluído" na página "Primeiros passos" um, o ambiente de desenvolvimento integrado da estação de trabalho
3. Como criar um novo aplicativo inicial do Nodejs
Nesta seção, você criará um novo aplicativo Nodejs.
- Abra um novo Terminal.
- No Cloud Shell, crie um novo diretório com o nome
mynodejsapp
mkdir mynodejsapp
Se essa mensagem aparecer para você, clique no botão "Permitir" para copiar e colar na estação de trabalho.
- Mude para este diretório e abra como um espaço de trabalho. Isso recarregará o editor ao criar uma configuração de espaço de trabalho na pasta recém-criada.
cd mynodejsapp && code-oss-cloud-workstations -r --folder-uri="$PWD"
- Abra um novo terminal. Instalar o Node e o NPM usando o NVM.
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.2/install.sh | bash
# This loads nvm bash_completion
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"
nvm install stable
nvm alias default stable
4. Criar um novo aplicativo inicial
- Inicializar o aplicativo
Crie um arquivo package.json
executando o seguinte comando:
npm init
Choose the `entry point: (index.js) src/index.js` and leave default values for the rest of the parameters. This will create the `package.json` file with following contents
{ "name": "mynodejsapp", "version": "1.0.0", "description": "", "main": "src/index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC" }
- Adicionar um ponto de entrada
Abra e edite o arquivo package.json
no ambiente de desenvolvimento integrado para incluir o comando "start" no script "start": "node src/index.js",
. Após a mudança, os scripts vão ficar parecidos com o snippet de código abaixo:
"scripts": {
"start": "node src/index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
- Adicionar a dependência Express
O código que vamos adicionar também usa express
. Portanto, vamos adicionar essa dependência ao arquivo package.json
. Após todas as mudanças, o arquivo package.json
ficará como mostrado abaixo.
{
"name": "mynodejsapp",
"version": "1.0.0",
"description": "",
"main": "src/index.js",
"scripts": {
"start": "node src/index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.17.3"
}
}
- Criar o arquivo index.js
Crie um diretório de origem chamado src selecionando Nova pasta na visualização do explorador.
Criar um arquivo src/index.js
pelo seguinte código:
const express = require('express');
const app = express();
const PORT = 8080;
app.get('/', (req, res) => {
var message="Greetings from Node";
res.send({ message: message });
});
app.listen(PORT, () => {
console.log(`Server running at: http://localhost:${PORT}/`);
});
A PORTA está definida com o valor 8080
Gerar manifestos
O Skaffold fornece ferramentas integradas para simplificar o desenvolvimento de contêineres. Nesta etapa, você inicializará o Skaffold, que criará automaticamente arquivos YAML de base do Kubernetes. Execute o comando abaixo para iniciar o processo.
Execute o seguinte comando no terminal
skaffold init --generate-manifests
Quando solicitado:
- Digite 8080 na porta
- Digite y para salvar a configuração
Dois arquivos foram adicionados à visualização do espaço de trabalho, skaffold.yaml
e deployment.yaml
.
Atualizar o nome do app
Os valores padrão incluídos na configuração atualmente não correspondem ao nome do seu aplicativo. Atualize os arquivos para fazer referência ao nome do aplicativo em vez dos valores padrão.
- Alterar entradas na configuração do Skaffold
- Abrir
skaffold.yaml
- Selecione o nome da imagem definido atualmente como
package-json-image
- Clique com o botão direito do mouse e escolha "Alterar todas as ocorrências"
- Digite o novo nome como
mynodejsapp
- Alterar entradas na configuração do Kubernetes
- Abrir arquivo
deployment.yaml
- Selecione o nome da imagem definido atualmente como
package-json-image
- Clique com o botão direito do mouse e escolha "Alterar todas as ocorrências"
- Digite o novo nome como
mynodejsapp
No arquivo skaffold.yaml
, a seção build
usa buildpacks
para conteinerizar o aplicativo. Esse código não tem o Dockerfile, e o desenvolvedor não precisa de conhecimento sobre o Docker para conteinerizar o aplicativo.
Além disso, a sincronização quente é ativada automaticamente entre o editor e o contêiner em execução por essa configuração do skaffold. Nenhuma configuração adicional é necessária para ativar a sincronização a quente.
5. Orientações sobre o processo de desenvolvimento
Nesta seção, você verá algumas etapas usando o plug-in do Cloud Code para aprender os processos básicos e validar a configuração do seu aplicativo inicial.
O Cloud Code se integra ao skaffold para otimizar o processo de desenvolvimento. Quando você implantar no GKE nas etapas a seguir, o Cloud Code e o Skaffold vão criar automaticamente a imagem do contêiner, enviá-la para um Container Registry e implantar o aplicativo no GKE. Isso acontece nos bastidores abstraindo os detalhes do fluxo do desenvolvedor. O Cloud Code também melhora seu processo de desenvolvimento fornecendo recursos tradicionais de depuração e hotsync para o desenvolvimento baseado em contêiner.
Faça login no Google Cloud
- Clique no ícone do Cloud Code e selecione "Fazer login no Google Cloud":
- Clique em "Continuar para fazer login".
- Confira a resposta no terminal e abra o link:
- Faça login com suas credenciais de estudante do Qwiklabs.
- Selecione "Permitir":
- Copie o código de verificação e volte à guia Estação de trabalho.
- Cole o código de verificação e pressione Enter.
Adicionar cluster do Kubernetes
- Adicionar um cluster
- Selecione o Google Kubernetes Engine:
- Selecione o projeto.
- Selecione "mycluster" que foi criado na configuração inicial.
- O cluster agora aparece na lista de clusters do Kubernetes, em Cloud Code. Navegue e analise o cluster daqui.
Definir o ID do projeto atual usando a gcloud cli
- Copie o ID do projeto deste laboratório na página do qwiklabs.
- No terminal, execute o comando gcloud cli para definir o ID do projeto. Substitua o ID do projeto de exemplo antes de executar o comando. SUBSTITUIR o ID do projeto antes de executar o comando abaixo.
gcloud config set project qwiklabs-gcp-project-id
Implantar no Kubernetes
- No painel da parte de baixo do Editor do Cloud Shell, selecione Cloud Code Envio
- No painel que aparece na parte de cima, em SESSÕES DE DESENVOLVIMENTO, selecione Executar no Kubernetes. Se solicitado, selecione Sim para usar o contexto atual do Kubernetes.
- Na primeira vez que você executar o comando, um prompt vai aparecer na parte de cima da tela perguntando se você quer o contexto atual do Kubernetes. Selecione "Yes" para aceitar e usar o contexto atual.
- Em seguida, será exibido um prompt perguntando qual registro de contêiner usar. Pressione "Enter" para aceitar o valor padrão fornecido
- Selecione a guia "Output" no painel inferior e Kubernetes: Run/Debug no menu suspenso para conferir o progresso e as notificações.
- Selecione "Kubernetes: Run/Debug - Detalhado". no menu suspenso do canal à direita, é possível ver mais detalhes e os registros das transmissões ao vivo dos contêineres.
- Retorne à visualização simplificada selecionando "Kubernetes: Run/Debug". no menu suspenso
- Quando o build e os testes forem concluídos, a guia "Output" vai mostrar:
Resource deployment/mynodejsapp status completed successfully
e um URL vai estar listado: "Forwarded URL from service demo-app: http://localhost:8080" - No terminal do Cloud Code, passe o cursor sobre o URL na saída (http://localhost:8080) e, na dica de ferramenta exibida, selecione "Seguir link".
A resposta será:
{"message":"Greetings from Node"}
Fazer recarga automática
- Navegue para
src/index.js
. Edite o código da mensagem de saudação para'Hello from Node'
Na janela Output
, na visualização Kubernetes: Run/Debug
, o inspetor sincroniza os arquivos atualizados com o contêiner no Kubernetes.
Update initiated File sync started for 1 files for gcr.io/myproject/mynodejsapp:latest@sha256:f554756b3b4d6c301c4b26ef96102227cfa2833270db56241248ae42baa1971a File sync succeeded for 1 files for gcr.io/myproject/mynodejsapp:latest@sha256:f554756b3b4d6c301c4b26ef96102227cfa2833270db56241248ae42baa1971a Update succeeded
- Se você mudar para a visualização
Kubernetes: Run/Debug - Detailed
, vai perceber que ela reconhece mudanças no arquivo e reinicia o nó.
files modified: [src/index.js] Copying files:map[src/index.js:[/workspace/src/index.js]]togcr.io/myproject/mynodejsapp:latest@sha256:f554756b3b4d6c301c4b26ef96102227cfa2833270db56241248ae42baa1971a Syncing 1 files for gcr.io/myproject/mynodejsapp:latest@sha256:f554756b3b4d6c301c4b26ef96102227cfa2833270db56241248ae42baa1971a Watching for changes... [mynodejsapp] [mynodejsapp]> mynodejsapp@1.0.0 start /workspace [mynodejsapp]> node src/index.js [mynodejsapp] [mynodejsapp]Server running at: http://localhost:8080/
- Atualize seu navegador para conferir os resultados atualizados.
Depuração
- Acesse a Visualização de depuração e interrompa a linha de execução atual .
- Clique em
Cloud Code
no menu da parte de baixo e selecioneDebug on Kubernetes
para executar o aplicativo no mododebug
.
- Na visualização
Kubernetes Run/Debug - Detailed
da janelaOutput
, observe que o skaffold vai implantar esse aplicativo no modo de depuração. - Poderá levar alguns minutos para o aplicativo ser criado e implantado. Você vai notar um depurador anexado neste momento.
Port forwarding pod/mynodejsapp-6bbcf847cd-vqr6v in namespace default, remote port 9229 -> http://127.0.0.1:9229 [mynodejsapp]Debugger attached.
- A barra de status inferior muda de azul para laranja, indicando que está no modo de depuração.
- Na visualização
Kubernetes Run/Debug
, observe que um contêiner depurável foi iniciado.
**************URLs***************** Forwarded URL from service mynodejsapp-service: http://localhost:8080 Debuggable container started pod/mynodejsapp-deployment-6bc7598798-xl9kj:mynodejsapp (default) Update succeeded ***********************************
Usar pontos de interrupção
- Abra o
src/index.js
- Localize a instrução que diz
var message="Hello from Node";
- Adicione um ponto de interrupção a essa linha clicando no espaço em branco à esquerda do número da linha. Um indicador vermelho vai indicar que o ponto de interrupção está definido
- Atualize o navegador e observe que o depurador interrompe o processo no ponto de interrupção e permite investigar as variáveis e o estado do aplicativo que está sendo executado remotamente no GKE
- Clique na seção de variáveis até encontrar a variável
"message"
. - Execute a linha pressionando "Step over "
- Observe a mudança do valor atual da variável
"message"
para"Hello from Node"
. - Clique duas vezes no nome da variável "target". No pop-up, mude o valor para algo diferente, como
"Hi from Node"
. - Clique no botão "Continuar" no painel de controle de depuração.
- Revise a resposta no navegador, que agora mostra o valor atualizado que você inseriu.
- Parar a "Depuração" pressionando o botão de parada e remova o ponto de interrupção clicando nele novamente.
6. Como desenvolver um serviço CRUD simples
Neste ponto, o aplicativo está totalmente configurado para o desenvolvimento conteinerizado, e você já conheceu o fluxo de trabalho básico de desenvolvimento com o Cloud Code. Nas seções a seguir, você vai praticar o que aprendeu adicionando endpoints do serviço REST que se conectam a um banco de dados gerenciado no Google Cloud.
Configurar dependências
O código do aplicativo usa um banco de dados para manter os dados do serviço REST. Verifique se as dependências estão disponíveis adicionando o seguinte ao arquivo package.json
- Adicione mais duas dependências,
pg
esequelize
, ao arquivopackage.json
para criar um Postgres de aplicativo CRUD. Publicar as mudanças, a seção de dependências ficaria assim.
"dependencies": {
"express": "^4.17.3",
"pg": "^8.8.0",
"sequelize": "^6.25.7"
}
Programar o serviço REST
- Adicione o código CRUD do aplicativo a este aplicativo
wget -O app.zip https://github.com/GoogleCloudPlatform/container-developer-workshop/raw/main/labs/nodejs/app.zip
unzip app.zip
Esse código tem
- Pasta models com o modelo de entidade para
item
- pasta controllers com o código que realiza as operações CRUD
- Pasta routes que encaminha padrões de URL específicos para chamadas diferentes
- Pasta config com detalhes de conectividade do banco de dados
- Observe que a configuração do banco de dados no arquivo
db.config.js
se refere às variáveis de ambiente que precisam ser fornecidas para se conectar ao banco de dados. Além disso, você precisa analisar a solicitação recebida para codificação de URL. - Adicione o snippet de código a seguir em
src/index.js
para se conectar ao código CRUD do seu arquivo JavaScript principal logo antes da última seção que começa comapp.listen(PORT, () => {
.
const bodyParser = require('body-parser')
app.use(bodyParser.json())
app.use(
bodyParser.urlencoded({
extended: true,
})
)
const db = require("../app/models");
db.sequelize.sync();
require("../app/routes/item.routes")(app);
- Edite a implantação no arquivo
deployment.yaml
para adicionar as variáveis de ambiente e fornecer as informações de conectividade do banco de dados.
Atualize a entrada de especificação no final do arquivo para corresponder à definição a seguir
spec:
containers:
- name: mynodejsapp
image: mynodejsapp
env:
- name: DB_HOST
value: ${DB_INSTANCE_IP}
- name: DB_PORT
value: "5432"
- name: DB_USER
valueFrom:
secretKeyRef:
name: gke-cloud-sql-secrets
key: username
- name: DB_PASS
valueFrom:
secretKeyRef:
name: gke-cloud-sql-secrets
key: password
- name: DB_NAME
valueFrom:
secretKeyRef:
name: gke-cloud-sql-secrets
key: database
- Substitua o valor DB_HOST pelo endereço do seu banco de dados.
export DB_INSTANCE_IP=$(gcloud sql instances describe mytest-instance \
--format=json | jq \
--raw-output ".ipAddresses[].ipAddress")
envsubst < deployment.yaml > deployment.new && mv deployment.new deployment.yaml
Implante e valide o aplicativo
- No painel da parte de baixo do Editor do Cloud Shell, selecione
Cloud Code
e depoisDebug on Kubernetes
na parte de cima da tela. - Quando o build e os testes forem concluídos, a guia "Output" vai mostrar:
Resource deployment/mynodejsapp status completed successfully
e um URL vai estar listado: "Forwarded URL from service mynodejsapp: http://localhost:8080" - Adicione alguns itens.
No terminal cloudshell, execute os comandos abaixo
URL=localhost:8080
curl -X POST $URL/items -d '{"itemName":"Body Spray", "itemPrice":3.2}' -H "Content-Type: application/json"
curl -X POST $URL/items -d '{"itemName":"Nail Cutter", "itemPrice":2.5}' -H "Content-Type: application/json"
- Teste o GET executando $URL/items no navegador. Também é possível executar "curl" na linha de comando
curl -X GET $URL/items
- Teste a exclusão: agora tente excluir um item executando o comando abaixo. Mude o valor do item-id, se necessário.
curl -X DELETE $URL/items/1
This throws an error message
{"message":"Could not delete Item with id=[object Object]"}
Identificar e corrigir o problema
- O aplicativo está sendo executado no modo de depuração. Portanto, use pontos de interrupção para encontrar o problema. Veja algumas dicas:
- Sabemos que há algo errado com a função DELETE, pois ela não está retornando o resultado desejado. Portanto, defina o ponto de interrupção no método
itemcontroller.js
->exports.delete
. - Execute passo a passo e observe as variáveis em cada etapa para observar os valores das variáveis locais na janela esquerda.
- Para observar valores específicos, como
request.params
, adicione essa variável à janela de observação.
- Observe que o valor atribuído a
id
éundefined
. Mude o código para corrigir o problema.
O snippet de código fixo ficaria assim:
// Delete a Item with the specified id in the request exports.delete = (req, res) => { const id = req.params.id;
- Depois que o aplicativo for reiniciado, teste novamente tentando excluir.
- Pare a sessão de depuração clicando no quadrado vermelho na barra de ferramentas de depuração .
7. Limpeza
Parabéns! Neste laboratório, você criou um novo aplicativo Nodejs do zero e o configurou para funcionar no modo de implantação dinâmica com contêineres. Em seguida, você implantou e depurou seu aplicativo em um cluster remoto do GKE seguindo o mesmo fluxo de desenvolvedor encontrado nas pilhas de aplicativos tradicionais.
Para fazer a limpeza após a conclusão do laboratório:
- Exclua os arquivos usados no laboratório
cd ~ && rm -rf mynodejsapp && rm -f setup.sh
- Exclua o projeto para remover toda a infraestrutura e os recursos relacionados