Configurar um serviço do Cloud Run para acessar um serviço interno do Cloud Run e a Internet pública

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 (VCP, na sigla em inglês) 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 por uma VPC e também para continuar a ter acesso à Internet pública.

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. Em seguida, você aprenderá a chamar https://curlmyip.org (em inglês) para recuperar o endereço IP do serviço front-end.

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 (por exemplo, front-end) para se comunicar com um serviço do Cloud Run somente de entrada interna (por exemplo, back-end), mantendo o acesso à Internet pública para o serviço front-end.

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.

PROJECT_ID=<YOUR_PROJECT_ID>
REGION=<YOUR_REGION, e.g. us-central1>
FRONTEND=frontend-with-internet
BACKEND=backend
SUBNET_NAME=default

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 egress-private-codelab/frontend-w-internet egress-private-codelab/backend && cd egress-private-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-w-internet

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",
    "htmx.org": "^1.9.10"
  }
}

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 conter 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 Request Tester service on the Internet</h1>
      <form hx-trigger="submit" hx-post="/callService" hx-target="#zen">
        <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="zen" 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

Nesta seção, você vai verificar se implantou dois serviços do Cloud Run.

Abra o URL do serviço de front-end no navegador da Web, por exemplo, https://frontend-your-hash-uc.a.run.app/

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

A mensagem "Hello World" vai aparecer.

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

Execute o comando gcloud a seguir para incorporar um serviço do Cloud Run à sua rede privada.

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

Se você tentasse chamar o serviço de back-end a partir do serviço de front-end, receberia um erro 404. A conexão de saída (ou saída) do serviço de front-end do Cloud Run vai para a Internet primeiro, então o Google Cloud não sabe a origem da solicitação.

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 ao serviço de front-end do Cloud Run para garantir que ele possa alcançar endereços IP internos na rede VPC. Depois você vai configurar a saída de modo que apenas as solicitações de IPs particulares sejam roteadas para a VPC. Com essa configuração, o front-end ainda poderá acessar a Internet pública. Saiba mais na documentação sobre como receber solicitações de outros serviços do Cloud Run.

Configurar a saída de VPC direta

Primeiro, execute este comando para usar a saída de VPC direta no seu serviço front-end:

gcloud beta run services update $FRONTEND \
--network=$SUBNET_NAME \
--subnet=$SUBNET_NAME  \
--vpc-egress=private-ranges-only \
--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:          private-ranges-only

ativar o Acesso privado do Google

Em seguida, ative o Acesso privado do Google na sub-rede executando o seguinte comando:

gcloud compute networks subnets update $SUBNET_NAME \
--region=$REGION \
--enable-private-ip-google-access

Para verificar se o Acesso privado do Google foi ativado, execute este comando:

gcloud compute networks subnets describe $SUBNET_NAME \
--region=$REGION \
--format="get(privateIpGoogleAccess)"

Criar uma zona do Cloud DNS para URLs run.app

Por fim, crie uma zona do Cloud DNS para URLs run.app, para que o Google Cloud possa tratá-los como endereços IP internos.

Em uma etapa anterior, quando você configurou a saída de VPC direta para "private-ranges-only". Isso significa que as conexões de saída do serviço de front-end só vão para a rede VPC se o destino for um IP interno. No entanto, o serviço de back-end usa um URL run.app que corresponde a um IP público.

Nesta etapa, você vai criar uma zona do Cloud DNS para os URLs run.app com o objetivo de resolver os intervalos de endereços IP private.googleapis.com, que são reconhecidos como endereços IP internos. Agora todas as solicitações para esses intervalos serão roteadas pela sua rede VPC.

Para fazer isso, acesse: https://cloud.google.com/run/docs/securing/private-networking#from-other-services

# do not include the https:// in your DNS Name
# for example: backend-<hash>-uc.a.run.app
DNS_NAME=<your backend service URL without the https://>

gcloud dns --project=$PROJECT_ID managed-zones create codelab-backend-service \
 --description="" \
 --dns-name="a.run.app." \
 --visibility="private" \
 --networks=$SUBNET_NAME

gcloud dns --project=$PROJECT_ID record-sets create $DNS_NAME. \
--zone="codelab-backend-service" \
 --type="A" \
 --ttl="60" \
--rrdatas="199.36.153.8,199.36.153.9,199.36.153.10,199.36.153.11"

Agora, quando você tentar acessar o serviço de back-end do seu site, a mensagem "Hello World" vai aparecer. retornados.

E quando você tentar acessar a Internet usando https://curlmyip.org/, verá seu endereço IP.

6. Solução de problemas

Aqui estão algumas mensagens de erro que você pode encontrar se as configurações não forem definidas corretamente.

  • Se você receber uma mensagem de erro getaddrinfo ENOTFOUND backend-your-hash-uc.a.run.app, verifique se você não adicionou o "https://" para o registro A do DNS
  • Se você receber um erro 404 ao tentar acessar o back-end após configurar a zona, aguarde até que o cache no registro global run.app expire (por exemplo, seis horas) ou crie uma nova revisão (limpe o cache) executando o seguinte comando: gcloud beta run services update $FRONTEND --network=$SUBNET_NAME --subnet=$SUBNET_NAME --vpc-egress=private-ranges-only --region=$REGION

7. Parabéns!

Parabéns por concluir o codelab.

Recomendamos a leitura da documentação sobre Rede privada no 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 (por exemplo, front-end) para se comunicar com um serviço do Cloud Run somente de entrada interna (por exemplo, back-end), mantendo o acesso à Internet pública para o serviço front-end.

8. Limpar

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

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

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.