یک سرویس Cloud Run را برای دسترسی به یک سرویس داخلی Cloud Run و هم به اینترنت عمومی پیکربندی کنید

۱. مقدمه

نمای کلی

برای ایمن‌سازی ترافیک شبکه برای سرویس‌ها و برنامه‌های کاربردی خود، بسیاری از سازمان‌ها از یک شبکه ابر خصوصی مجازی (VCP) در Google Cloud با کنترل‌های محیطی برای جلوگیری از خروج داده‌ها استفاده می‌کنند. یک شبکه VPC یک نسخه مجازی از یک شبکه فیزیکی است که در داخل شبکه تولید گوگل پیاده‌سازی شده است. یک شبکه VPC اتصال را برای نمونه‌های ماشین مجازی (VM) Compute Engine شما فراهم می‌کند، متعادل‌کننده‌های بار شبکه داخلی بومی و سیستم‌های پروکسی را برای متعادل‌کننده‌های بار برنامه داخلی ارائه می‌دهد، با استفاده از تونل‌های Cloud VPN و پیوست‌های VLAN برای Cloud Interconnect به شبکه‌های داخلی متصل می‌شود و ترافیک را از متعادل‌کننده‌های بار خارجی Google Cloud به backendها توزیع می‌کند.

برخلاف ماشین‌های مجازی، سرویس‌های Cloud Run به طور پیش‌فرض با هیچ شبکه VPC خاصی مرتبط نیستند. این آزمایشگاه کد نشان می‌دهد که چگونه تنظیمات ورودی (اتصالات ورودی) را تغییر دهید تا فقط ترافیکی که از یک VPC می‌آید بتواند به یک سرویس Cloud Run (مثلاً یک سرویس backend) دسترسی داشته باشد. علاوه بر این، این آزمایشگاه کد به شما نشان می‌دهد که چگونه یک سرویس دوم (مثلاً یک سرویس frontend) داشته باشید که هم به سرویس Cloud Run backend از طریق VPC دسترسی داشته باشد و هم به اینترنت عمومی دسترسی داشته باشد.

در این مثال، سرویس Cloud Run در سمت سرور backend عبارت hello world را برمی‌گرداند. سرویس Cloud Run در سمت سرور frontend یک فیلد ورودی در رابط کاربری برای جمع‌آوری یک URL فراهم می‌کند. سپس سرویس frontend یک درخواست GET به آن URL (مثلاً سرویس backend) ارسال می‌کند، از این رو این درخواست به یک درخواست سرویس به سرویس تبدیل می‌شود (به جای درخواست مرورگر به سرویس). هنگامی که سرویس frontend بتواند با موفقیت به backend برسد، پیام hello world در مرورگر نمایش داده می‌شود. سپس، خواهید دید که چگونه می‌توانید برای بازیابی آدرس IP سرویس frontend خود، به https://curlmyip.org فراخوانی کنید.

آنچه یاد خواهید گرفت

  • چگونه فقط ترافیک را از یک VPC به سرویس Cloud Run خود مجاز کنیم؟
  • نحوه پیکربندی خروجی در یک سرویس Cloud Run (مثلاً frontend) برای برقراری ارتباط با یک سرویس Cloud Run که فقط از ورودی داخلی استفاده می‌کند (مثلاً backend)، در حالی که دسترسی عمومی به اینترنت را برای سرویس frontend حفظ می‌کند.

۲. تنظیمات و الزامات

پیش‌نیازها

فعال کردن پوسته ابری

  1. از کنسول ابری، روی فعال کردن پوسته ابری کلیک کنید d1264ca30785e435.png .

cb81e7c8e34bc8d.png

اگر این اولین باری است که Cloud Shell را اجرا می‌کنید، یک صفحه میانی برای توضیح آن به شما نمایش داده می‌شود. اگر با یک صفحه میانی مواجه شدید، روی ادامه کلیک کنید.

d95252b003979716.png

آماده‌سازی و اتصال به Cloud Shell فقط چند لحظه طول می‌کشد.

7833d5e1c5d18f54.png

این ماشین مجازی مجهز به تمام ابزارهای توسعه مورد نیاز است. این ماشین یک دایرکتوری خانگی پایدار ۵ گیگابایتی ارائه می‌دهد و در فضای ابری گوگل اجرا می‌شود که عملکرد شبکه و احراز هویت را تا حد زیادی افزایش می‌دهد. بخش عمده‌ای از کار شما در این آزمایشگاه کد، اگر نگوییم همه، را می‌توان با یک مرورگر انجام داد.

پس از اتصال به Cloud Shell، باید ببینید که احراز هویت شده‌اید و پروژه روی شناسه پروژه شما تنظیم شده است.

  1. برای تأیید احراز هویت، دستور زیر را در Cloud Shell اجرا کنید:
gcloud auth list

خروجی دستور

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

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. دستور زیر را در Cloud Shell اجرا کنید تا تأیید کنید که دستور gcloud از پروژه شما اطلاع دارد:
gcloud config list project

خروجی دستور

[core]
project = <PROJECT_ID>

اگر اینطور نیست، می‌توانید با این دستور آن را تنظیم کنید:

gcloud config set project <PROJECT_ID>

خروجی دستور

Updated property [core/project].

۳. سرویس‌های Cloud Run را ایجاد کنید

متغیرهای محیطی را تنظیم کنید

شما می‌توانید متغیرهای محیطی که در سراسر این آزمایشگاه کد استفاده خواهند شد را تنظیم کنید.

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

سرویس Cloud Run بک‌اند را ایجاد کنید

ابتدا، یک دایرکتوری برای کد منبع ایجاد کنید و با دستور cd به آن دایرکتوری بروید.

mkdir -p egress-private-codelab/frontend-w-internet egress-private-codelab/backend && cd egress-private-codelab/backend

سپس، یک فایل `package.json`` با محتوای زیر ایجاد کنید:

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

در مرحله بعد، یک فایل منبع index.js با محتوای زیر ایجاد کنید. این فایل شامل نقطه ورود سرویس و منطق اصلی برنامه است.

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}`);
});

در نهایت، سرویس Cloud Run را با اجرای دستور زیر مستقر کنید.

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

سرویس Cloud Run را به صورت frontend ایجاد کنید

به دایرکتوری frontend بروید

cd ../frontend-w-internet

سپس، یک فایل package.json با محتوای زیر ایجاد کنید:

{
  "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"
  }
}

در مرحله بعد، یک فایل منبع index.js با محتوای زیر ایجاد کنید. این فایل شامل نقطه ورود سرویس و منطق اصلی برنامه است.

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}`);
});

یک پوشه عمومی برای فایل index.html ایجاد کنید.

mkdir public
touch public/index.html

و فایل index.html را به‌روزرسانی کنید تا شامل موارد زیر باشد:

<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>

در نهایت، سرویس Cloud Run را با اجرای دستور زیر مستقر کنید.

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

با سرویس Backend تماس بگیرید

در این بخش، تأیید خواهید کرد که دو سرویس Cloud Run را با موفقیت مستقر کرده‌اید.

آدرس اینترنتی سرویس frontend را در مرورگر وب خود باز کنید، مثلاً https://frontend-your-hash-uc.a.run.app/

در کادر متن، آدرس اینترنتی (URL) سرویس بک‌اند را وارد کنید. توجه داشته باشید که این درخواست از نمونه‌ی کلود ران (Cloud Run) در فرانت‌اند به سرویس کلود ران در بک‌اند هدایت می‌شود و نه از مرورگر شما.

شما عبارت "سلام دنیا" را خواهید دید.

۴. سرویس Backend را فقط برای ورودی داخلی تنظیم کنید

شما می‌توانید دستور gcloud زیر را برای ادغام سرویس Cloud Run در شبکه خصوصی خود اجرا کنید.

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

اگر بخواهید سرویس بک‌اند را از سرویس فرانت‌اند فراخوانی کنید، با خطای ۴۰۴ مواجه خواهید شد. اتصال خروجی (یا خروجی) سرویس کلود ران فرانت‌اند ابتدا به اینترنت متصل می‌شود، بنابراین گوگل کلود مبدا درخواست را نمی‌داند.

۵. سرویس Frontend را برای دسترسی به VPC پیکربندی کنید

در این بخش، سرویس Cloud Run فرانت‌اند خود را برای ارتباط با سرویس بک‌اند از طریق یک VPC پیکربندی خواهید کرد.

برای انجام این کار، باید خروجی مستقیم VPC را به سرویس Cloud Run فرانت‌اند خود اضافه کنید تا مطمئن شوید که می‌تواند به آدرس‌های IP داخلی در شبکه VPC دسترسی پیدا کند. سپس، خروجی را طوری پیکربندی می‌کنید که فقط درخواست‌های مربوط به IPهای خصوصی به VPC هدایت شوند. این پیکربندی به فرانت‌اند شما اجازه می‌دهد تا همچنان به اینترنت عمومی دسترسی داشته باشد. می‌توانید در مستندات مربوط به دریافت درخواست‌ها از سایر سرویس‌های Cloud Run اطلاعات بیشتری کسب کنید.

پیکربندی خروجی مستقیم VPC

ابتدا، این دستور را اجرا کنید تا از خروجی مستقیم VPC در سرویس frontend خود استفاده کنید:

gcloud beta run services update $FRONTEND \
--network=$SUBNET_NAME \
--subnet=$SUBNET_NAME  \
--vpc-egress=private-ranges-only \
--region=$REGION

اکنون می‌توانید تأیید کنید که سرویس frontend شما به VPC دسترسی دارد:

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

شما باید خروجی مشابه زیر را ببینید

VPC access:
    Network:        default
    Subnet:          default
    Egress:          private-ranges-only

فعال کردن دسترسی خصوصی گوگل

در مرحله بعد، با اجرای دستور زیر، دسترسی خصوصی گوگل را در زیرشبکه فعال خواهید کرد:

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

با اجرای این دستور می‌توانید تأیید کنید که دسترسی خصوصی به گوگل فعال شده است:

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

ایجاد منطقه Cloud DNS برای URL های run.app

در نهایت، یک منطقه Cloud DNS برای URL های run.app ایجاد کنید تا Google Cloud بتواند آنها را به عنوان آدرس های IP داخلی در نظر بگیرد.

در مرحله قبلی، وقتی خروجی مستقیم VPC را روی private-ranges-only پیکربندی کردید، این بدان معناست که اتصالات خروجی از سرویس frontend شما فقط در صورتی به شبکه VPC می‌روند که مقصد یک IP داخلی باشد. با این حال، سرویس backend شما از یک URL run.app استفاده می‌کند که به یک IP عمومی تبدیل می‌شود.

در این مرحله، یک منطقه Cloud DNS برای URL های run.app ایجاد خواهید کرد تا به محدوده آدرس های IP private.googleapis.com که به عنوان آدرس های IP داخلی شناخته می شوند، متصل شوند. اکنون، هر درخواستی به این محدوده ها از طریق شبکه VPC شما هدایت می شود.

می‌توانید این کار را از طریق آدرس زیر انجام دهید: 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"

حالا وقتی سعی می‌کنید به سرویس بک‌اند وب‌سایت خود دسترسی پیدا کنید، عبارت "hello world" را مشاهده خواهید کرد.

و وقتی سعی می‌کنید با استفاده از https://curlmyip.org/ به اینترنت دسترسی پیدا کنید، آدرس IP خود را مشاهده خواهید کرد.

۶. عیب‌یابی

در اینجا برخی از پیام‌های خطای احتمالی که ممکن است در صورت پیکربندی نادرست تنظیمات با آنها مواجه شوید، آورده شده است.

  • اگر با خطای getaddrinfo ENOTFOUND backend-your-hash-uc.a.run.app مواجه شدید، مطمئن شوید که "https://" را به رکورد DNS A اضافه نکرده‌اید.
  • اگر هنگام تلاش برای دسترسی به backend پس از پیکربندی zone با خطای ۴۰۴ مواجه شدید، می‌توانید منتظر بمانید تا حافظه پنهان (cache) رکورد سراسری run.app منقضی شود (مثلاً ۶ ساعت) یا می‌توانید با اجرای دستور زیر یک نسخه جدید ایجاد کنید (و در نتیجه حافظه پنهان را پاک کنید): gcloud beta run services update $FRONTEND --network=$SUBNET_NAME --subnet=$SUBNET_NAME --vpc-egress=private-ranges-only --region=$REGION

۷. تبریک می‌گویم!

تبریک می‌گویم که آزمایشگاه کد را تمام کردید!

توصیه می‌کنیم مستندات مربوط به شبکه خصوصی در Cloud Run را بررسی کنید.

آنچه ما پوشش داده‌ایم

  • چگونه فقط ترافیک را از یک VPC به سرویس Cloud Run خود مجاز کنیم؟
  • نحوه پیکربندی خروجی در یک سرویس Cloud Run (مثلاً frontend) برای برقراری ارتباط با یک سرویس Cloud Run که فقط از ورودی داخلی استفاده می‌کند (مثلاً backend)، در حالی که دسترسی عمومی به اینترنت را برای سرویس frontend حفظ می‌کند.

۸. تمیز کردن

برای جلوگیری از هزینه‌های ناخواسته، (برای مثال، اگر این سرویس Cloud Run سهواً بیشتر از تخصیص فراخوانی ماهانه Cloud Run شما در سطح رایگان فراخوانی شود)، می‌توانید سرویس Cloud Run یا پروژه‌ای را که در مرحله 2 ایجاد کرده‌اید، حذف کنید.

برای حذف سرویس‌های Cloud Run، به کنسول ابری Cloud Run در آدرس https://console.cloud.google.com/functions/ بروید و سرویس‌های $FRONTEND و $BACKEND که در این آزمایشگاه کد ایجاد کرده‌اید را حذف کنید.

اگر تصمیم به حذف کل پروژه دارید، می‌توانید به آدرس https://console.cloud.google.com/cloud-resource-manager بروید، پروژه‌ای را که در مرحله ۲ ایجاد کرده‌اید انتخاب کنید و گزینه Delete را انتخاب کنید. اگر پروژه را حذف کنید، باید پروژه‌ها را در Cloud SDK خود تغییر دهید. می‌توانید با اجرای gcloud projects list لیست تمام پروژه‌های موجود را مشاهده کنید.