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

1. مقدمه

نمای کلی

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

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

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

چیزی که یاد خواهید گرفت

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

2. راه اندازی و الزامات

پیش نیازها

  • شما به کنسول Cloud وارد شده اید.
  • شما قبلاً یک تابع نسل دوم را مستقر کرده اید. برای مثال، می‌توانید برای شروع، استقرار یک راه‌اندازی سریع نسل دوم Cloud Function را دنبال کنید.

Cloud Shell را فعال کنید

  1. از Cloud Console، روی Activate Cloud Shell کلیک کنید d1264ca30785e435.png .

cb81e7c8e34bc8d.png

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

d95252b003979716.png

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

7833d5e1c5d18f54.png

این ماشین مجازی با تمام ابزارهای توسعه مورد نیاز بارگذاری شده است. این یک فهرست اصلی 5 گیگابایتی دائمی ارائه می‌کند و در Google Cloud اجرا می‌شود، که عملکرد و احراز هویت شبکه را بسیار افزایش می‌دهد. بسیاری از کارهای شما، اگر نه همه، در این کد لبه با مرورگر قابل انجام است.

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

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

3. خدمات 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 را ایجاد کنید

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

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 را با موفقیت اجرا کرده‌اید.

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

در جعبه متن، URL مربوط به سرویس Backend را وارد کنید. توجه داشته باشید که این درخواست از نمونه Cloud Run جلویی به سرویس Cloud Run باطن ارسال می شود و نه از مرورگر شما.

"سلام دنیا" را خواهید دید

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

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

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

اگر بخواهید از سرویس frontend با سرویس پشتیبان تماس بگیرید، خطای 404 دریافت خواهید کرد. اتصال خروجی سرویس Cloud Run (یا خروج) ابتدا به اینترنت می رود، بنابراین Google Cloud منشأ درخواست را نمی داند.

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

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

برای انجام این کار، باید خروج مستقیم VPC را به سرویس Cloud Run frontend خود اضافه کنید تا مطمئن شوید که می تواند به آدرس های 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

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

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

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

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

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 را فقط در محدوده خصوصی پیکربندی کردید. این بدان معنی است که اتصالات خروجی از سرویس frontend شما تنها در صورتی به شبکه VPC می رود که مقصد یک IP داخلی باشد. با این حال، سرویس پشتیبان شما از 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"

اکنون هنگامی که سعی می کنید به سرویس پشتیبان وب سایت خود دسترسی پیدا کنید، "سلام جهان" را مشاهده خواهید کرد.

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

6. عیب یابی

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

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

7. تبریک می گویم!

برای تکمیل کد لبه تبریک می گویم!

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

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

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

8. پاکسازی کنید

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

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

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