Como configurar um serviço do Cloud Run para acessar um serviço interno do Cloud Run usando saída de VPC direta

1. Introdução

Visão geral

Para proteger o tráfego de rede para serviços e aplicativos, muitas organizações usam uma rede de nuvem privada virtual (VPC) no Google Cloud com controles de perímetro para evitar a exfiltração de dados. Uma rede VPC é uma versão virtual de uma rede física implementada dentro da rede de produção do Google. Uma rede VPC fornece conectividade para suas instâncias de máquina virtual (VM) do Compute Engine, oferece balanceadores de carga de rede de passagem interna nativos e sistemas de proxy para balanceadores de carga de aplicativo internos, conecta-se a redes no local usando túneis do Cloud VPN e anexos da VLAN para o Cloud Interconnect e distribui o tráfego dos balanceadores de carga externos do Google Cloud para back-ends.

Ao contrário das VMs, os serviços do Cloud Run não estão associados a nenhuma rede VPC específica por padrão. Este codelab demonstra como alterar as configurações de entrada (conexões de entrada) para que apenas o tráfego proveniente de uma VPC possa acessar um serviço do Cloud Run (por exemplo, um serviço de back-end). Além disso, este codelab mostra como fazer com que um segundo serviço (por exemplo, um front-end) acesse o serviço de back-end do Cloud Run usando uma VPC.

Neste exemplo, o serviço de back-end do Cloud Run retorna "Hello World". O serviço de front-end do Cloud Run fornece um campo de entrada na IU para coletar um URL. Em seguida, o serviço de front-end faz uma solicitação GET para esse URL (por exemplo, o serviço de back-end), tornando-a uma solicitação de serviço a serviço (em vez de uma solicitação de navegador para serviço). Quando o serviço de front-end consegue acessar o back-end, a mensagem "hello world" é exibida no navegador.

O que você vai aprender

  • Como permitir apenas o tráfego de uma VPC para o serviço do Cloud Run
  • Como configurar a saída em um serviço do Cloud Run para se comunicar com um serviço do Cloud Run somente para entrada interna

2. Configuração e requisitos

Pré-requisitos

Ativar o Cloud Shell

  1. No Console do Cloud, clique em Ativar o Cloud Shelld1264ca30785e435.png.

cb81e7c8e34bc8d.png

Se você estiver iniciando o Cloud Shell pela primeira vez, verá uma tela intermediária com a descrição dele. Se aparecer uma tela intermediária, clique em Continuar.

d95252b003979716.png

Leva apenas alguns instantes para provisionar e se conectar ao Cloud Shell.

7833d5e1c5d18f54.png

Essa máquina virtual tem todas as ferramentas de desenvolvimento necessárias. Ela oferece um diretório principal persistente de 5 GB, além de ser executada no Google Cloud. Isso aprimora o desempenho e a autenticação da rede. Grande parte do trabalho neste codelab, se não todo, pode ser feito em um navegador.

Depois de se conectar ao Cloud Shell, você verá sua autenticação e o projeto estará configurado com o ID do seu projeto.

  1. Execute o seguinte comando no Cloud Shell para confirmar se a conta está autenticada:
gcloud auth list

Resposta ao comando

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Execute o seguinte comando no Cloud Shell para confirmar que o comando gcloud sabe sobre seu projeto:
gcloud config list project

Resposta ao comando

[core]
project = <PROJECT_ID>

Se o projeto não estiver configurado, configure-o usando este comando:

gcloud config set project <PROJECT_ID>

Resposta ao comando

Updated property [core/project].

3. Criar os serviços do Cloud Run

Configurar as variáveis de ambiente.

Você pode definir variáveis de ambiente que serão usadas neste codelab.

REGION=<YOUR_REGION, e.g. us-central1>
FRONTEND=frontend
BACKEND=backend

Criar o serviço de back-end do Cloud Run

Primeiro, crie um diretório para o código-fonte e use cd nele.

mkdir -p internal-codelab/frontend internal-codelab/backend && cd internal-codelab/backend

Em seguida, crie um arquivo package.json com o seguinte conteúdo:

{
    "name": "backend-service",
    "version": "1.0.0",
    "description": "",
    "scripts": {
        "start": "node index.js"
    },
    "dependencies": {
        "express": "^4.18.1"
    }
}

Em seguida, crie um arquivo de origem index.js com o conteúdo abaixo. Esse arquivo contém o ponto de entrada para o serviço e a lógica principal do app.

const express = require('express');

const app = express();

app.use(express.urlencoded({ extended: true }));

app.get('/', function (req, res) {
    res.send("hello world");
});

const port = parseInt(process.env.PORT) || 8080;
app.listen(port, () => {
    console.log(`helloworld: listening on port ${port}`);
});

Por fim, implante o serviço do Cloud Run executando o comando a seguir.

gcloud run deploy $BACKEND --source . --allow-unauthenticated --region $REGION

Criar o serviço de front-end do Cloud Run

Navegue até o diretório de front-end.

cd ../frontend

Em seguida, crie um arquivo package.json com o seguinte conteúdo:

{
  "name": "frontend",
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "start": "node index.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "axios": "^1.6.6",
    "express": "^4.18.2"
  }
}

Em seguida, crie um arquivo de origem index.js com o conteúdo abaixo. Esse arquivo contém o ponto de entrada para o serviço e a lógica principal do app.

const express = require("express");
const app = express();
const port = 8080;
const path = require('path');
const axios = require('axios');

// serve static content (index.html) using
// built-in middleware function in Express 
app.use(express.static('public'));
app.use(express.urlencoded({ extended: true }));

// this endpoint receives a URL in the post body
// and then makes a get request to that URL
// results are sent back to the caller
app.post('/callService', async (req, res) => {

    const url = req.body.url;
    let message = "";

    try {
        console.log("url: ", url);
        const response = await axios.get(url);
        message = response.data;

    } catch (error) {
        message = error.message;
        console.error(error.message);
    }

    res.send(`
        ${message}
        <p>
        </p>
    `);
});

app.listen(port, () => {
    console.log(`Example app listening on port ${port}`);
});

Crie um diretório público para o arquivo index.html.

mkdir public
touch public/index.html

E atualize o index.html para que contenha o seguinte:

<html>
  <script
    src="https://unpkg.com/htmx.org@1.9.10"
    integrity="sha384-D1Kt99CQMDuVetoL1lrYwg5t+9QdHe7NLX/SoJYkXDFfX37iInKRy5xLSi8nO7UC"
    crossorigin="anonymous"
  ></script>
  <body>
    <div style="margin-top: 100px; margin-left: 100px">
      <h1>I'm the Frontend service on the Internet</h1>
      <form hx-trigger="submit" hx-post="/callService" hx-target="#message">
        <label for="url"> URL:</label>
        <input
          style="width: 308px"
          type="text"
          id="url"
          name="url"
          placeholder="The backend service URL"
          required
        />
        <button hx-indicator="#loading" type="submit">Submit</button>
        <p></p>
        <span class="htmx-indicator" id="loading"> Loading... </span>
        <div id="message" style="white-space: pre-wrap"></div>
        <p></p>
      </form>
    </div>
  </body>
</html>

Por fim, implante o serviço do Cloud Run executando o comando a seguir.

gcloud run deploy $FRONTEND --source . --allow-unauthenticated --region $REGION

Chamar o serviço de back-end

Verifique se você implantou dois serviços do Cloud Run.

Abra o URL do serviço de front-end no navegador da Web.

Na caixa de texto, digite o URL do serviço de back-end. Observe que essa solicitação é roteada da instância de front-end do Cloud Run para o serviço de back-end do Cloud Run, em vez de ser roteada do seu navegador.

Você verá "hello world".

4. Defina o serviço de back-end apenas para entrada interna

Execute o comando gcloud a seguir para permitir que apenas o tráfego da sua rede VPC acesse seu serviço de back-end.

gcloud run services update $BACKEND --ingress internal --region $REGION

Para confirmar que o serviço de back-end só pode receber tráfego da VPC, tente chamar o serviço de back-end do serviço de front-end novamente.

Desta vez, você verá "Falha na solicitação com o código de status 404".

Você recebeu esse erro porque a solicitação de saída do serviço de front-end do Cloud Run vai primeiro para a Internet, então o Google Cloud não sabe a origem da solicitação.

Na próxima seção, você vai configurar o serviço de front-end para acessar a VPC. Assim, o Google Cloud vai saber que a solicitação veio da VPC, que é reconhecida como uma origem interna.

5. Configurar o serviço de front-end para acessar a VPC

Nesta seção, você vai configurar seu serviço de front-end do Cloud Run para se comunicar com o serviço de back-end por uma VPC.

Para isso, adicione a saída de VPC direta às instâncias de front-end do Cloud Run para dar ao serviço um IP interno para uso na VPC. Depois você vai configurar a saída para que todas as conexões do serviço de front-end sejam direcionadas para a VPC.

Primeiro, execute este comando para ativar a saída de VPC direta:

gcloud beta run services update $FRONTEND \
--network=default \
--subnet=default \
--vpc-egress=all-traffic \
--region=$REGION

Confirme se o serviço de front-end tem acesso à VPC:

gcloud beta run services describe $FRONTEND \
--region=$REGION

Você verá uma saída semelhante a

VPC access:
    Network:         default
    Subnet:          default
    Egress:          all-traffic

Agora tente chamar o serviço de back-end no serviço de front-end novamente.

Desta vez, você verá "hello world".

Observação: seu serviço de front-end não terá acesso à Internet porque toda a saída foi roteada para a VPC. Por exemplo, o serviço de front-end atingirá o tempo limite se tentar acessar https://curlmyip.org/.

6. Parabéns!

Parabéns por concluir o codelab.

Recomendamos a leitura da documentação do Cloud Run e de como configurar a rede particular para os serviços do Cloud Run.

O que vimos

  • Como permitir apenas o tráfego de uma VPC para o serviço do Cloud Run
  • Como configurar a saída em um serviço do Cloud Run para se comunicar com um serviço do Cloud Run somente para entrada interna

7. Limpar

Para evitar cobranças acidentais (por exemplo, se os serviços do Cloud Run forem invocados por engano mais vezes do que sua alocação mensal de invocação do Cloud Run no nível sem custo financeiro), exclua o Cloud Run ou o projeto criado na etapa 2.

Para excluir o serviço do Cloud Run, acesse o console do Cloud Run do Cloud em https://console.cloud.google.com/run e exclua os serviços $FRONTEND e $BACKEND.

Se você optar por excluir o projeto inteiro, acesse https://console.cloud.google.com/cloud-resource-manager, selecione o projeto criado na etapa 2 e escolha "Excluir". Se você excluir o projeto, precisará alterar os projetos no SDK Cloud. Para conferir a lista de todos os projetos disponíveis, execute gcloud projects list.