איך להגדיר שירות Cloud Run לגשת לשירות Cloud Run פנימי באמצעות תעבורת נתונים יוצאת (egress) ישירה של VPC

1. מבוא

סקירה כללית

ארגונים רבים משתמשים ברשת VPC ב-Google Cloud עם אמצעי בקרה היקפיים כדי למנוע זליגת נתונים, וכך לאבטח את תעבורת הנתונים ברשת של השירותים והאפליקציות שלהם. רשת VPC היא גרסה וירטואלית של רשת פיזית שמוטמעת בתוך רשת הייצור של Google. רשת VPC מספקת קישוריות למכונות וירטואליות (VM) ב-Compute Engine, מציעה מאזני עומסים פנימיים של רשת להעברת סיגנל ללא שינוי ומערכות proxy למאזני עומסים פנימיים של אפליקציות, מתחברת לרשתות מקומיות באמצעות מנהרות Cloud VPN וחיבורי VLAN ל-Cloud Interconnect, ומפיצה תנועה ממאזני עומסים חיצוניים של Google Cloud למערכות בק-אנד.

בניגוד למכונות וירטואליות, שירותי Cloud Run לא משויכים לרשת VPC מסוימת כברירת מחדל. ב-Codelab הזה נדגים איך משנים את הגדרות תעבורת הנתונים הנכנסת (ingress) (חיבורים נכנסים) כך שרק תעבורה שמגיעה מ-VPC תוכל לגשת לשירות Cloud Run (למשל, שירות לקצה העורפי). בנוסף, ב-Codelab הזה נראה איך שירות שני (למשל, שירות frontend) יכול לגשת לשירות backend ב-Cloud Run דרך VPC.

בדוגמה הזו, שירות הקצה העורפי של Cloud Run מחזיר את המחרוזת hello world. שירות ה-Cloud Run של הקצה הקדמי מספק שדה להזנת קלט בממשק המשתמש לאיסוף כתובת URL. לאחר מכן, שירות הקצה הקדמי מבצע בקשת GET לכתובת ה-URL הזו (למשל, שירות הקצה העורפי), ולכן זו בקשה משירות לשירות (במקום בקשה מדפדפן לשירות). כששירות הקצה הקדמי מצליח להגיע לקצה האחורי, ההודעה hello world מוצגת בדפדפן.

מה תלמדו

  • איך מאפשרים רק תעבורה מרשת VPC לשירות Cloud Run
  • איך מגדירים יציאה (egress) בשירות Cloud Run כדי לתקשר עם שירות Cloud Run עם כניסה (ingress) פנימית בלבד

2. הגדרה ודרישות

דרישות מוקדמות

הפעלת Cloud Shell

  1. ב-Cloud Console, לוחצים על Activate Cloud Shell d1264ca30785e435.png.

cb81e7c8e34bc8d.png

אם זו הפעם הראשונה שאתם מפעילים את Cloud Shell, יוצג לכם מסך ביניים עם תיאור של השירות. אם הוצג לכם מסך ביניים, לוחצים על המשך.

d95252b003979716.png

הקצאת המשאבים והחיבור ל-Cloud Shell נמשכים רק כמה רגעים.

7833d5e1c5d18f54.png

במכונה הווירטואלית הזו טעונים כל הכלים הדרושים למפתחים. יש בה ספריית בית בנפח מתמיד של 5GB והיא פועלת ב-Google Cloud, מה שמשפר מאוד את הביצועים והאימות של הרשת. אפשר לבצע את רוב העבודה ב-codelab הזה, אם לא את כולה, באמצעות דפדפן.

אחרי שמתחברים ל-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].

3. יצירת שירותי Cloud Run

הגדרה של משתני סביבה

אתם יכולים להגדיר משתני סביבה שישמשו אתכם לאורך כל ה-codelab הזה.

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

יצירת שירות הקצה העורפי ב-Cloud Run

קודם יוצרים ספרייה לקוד המקור ועוברים לספרייה הזו.

mkdir -p internal-codelab/frontend internal-codelab/backend && cd internal-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.

cd ../frontend

לאחר מכן, יוצרים קובץ 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"
  }
}

לאחר מכן, יוצרים קובץ מקור 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 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>

לבסוף, פורסים את שירות Cloud Run באמצעות הפקודה הבאה.

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

התקשרות לשירות לקצה העורפי

מוודאים שפרסתם בהצלחה שני שירותי Cloud Run.

פותחים את כתובת ה-URL של שירות ה-frontend בדפדפן האינטרנט.

בתיבת הטקסט, מזינים את כתובת ה-URL של שירות הבק-אנד. שימו לב שהבקשה הזו מנותבת ממופע הקצה הקדמי של Cloud Run לשירות הקצה העורפי של Cloud Run, במקום להיות מנותבת מהדפדפן שלכם.

יוצג 'hello world'.

4. הגדרת שירות לקצה העורפי רק לתעבורה פנימית

מריצים את פקודת gcloud הבאה כדי לאפשר גישה לשירות לקצה העורפי רק לתעבורת נתונים מתוך רשת VPC.

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

כדי לוודא ששירות לקצה העורפי יכול לקבל תעבורת נתונים רק מה-VPC, נסו שוב להתקשר לשירות לקצה העורפי משירות הקצה הקדמי.

הפעם תופיע ההודעה "הבקשה נכשלה עם קוד סטטוס 404"

השגיאה הזו מתרחשת כי הבקשה היוצאת (כלומר, תעבורת נתונים יוצאת (egress)) של שירות הקצה הקדמי של Cloud Run יוצאת קודם לאינטרנט, ולכן Google Cloud לא יודעת מה המקור של הבקשה.

בקטע הבא תגדירו את שירות ה-frontend כך שתהיה לו גישה ל-VPC, כדי שמערכת Google Cloud תדע שהבקשה הגיעה מה-VPC, שמזוהה כמקור פנימי.

5. הגדרת שירות הקצה הקדמי לגישה ל-VPC

בקטע הזה תגדירו את שירות הקצה הקדמי של Cloud Run כדי שיוכל לתקשר עם שירות הקצה האחורי דרך VPC.

כדי לעשות את זה, תצטרכו להוסיף תעבורת נתונים יוצאת (egress) ישירה מ-VPC למופעי Cloud Run של הקצה הקדמי, כדי לתת לשירות כתובת IP פנימית לשימוש ב-VPC. לאחר מכן, תגדירו יציאה כך שכל החיבורים היוצאים משירות הקצה הקדמי יעברו אל ה-VPC.

קודם מריצים את הפקודה הבאה כדי להפעיל יציאה ישירה מרשת ה-VPC:

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

עכשיו אפשר לוודא שלשירות הקצה הקדמי יש גישה ל-VPC:

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

הפלט אמור להיראות כך:

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

עכשיו מנסים שוב להתקשר לשירות לקצה העורפי משירות ה-Frontend.

הפעם תופיע ההודעה 'hello world'.

הערה: לשירות הקצה הקדמי לא תהיה גישה לאינטרנט, כי כל התעבורה היוצאת מנותבת ל-VPC. לדוגמה, שירות הקצה הקדמי יגיע לזמן קצוב לתפוגה אם הוא ינסה לגשת לכתובת https://curlmyip.org/.

6. מעולה!

כל הכבוד, סיימתם את ה-Codelab!

מומלץ לעיין במסמכי התיעוד בנושא Cloud Run ובמאמר בנושא הגדרת רשת פרטית לשירותי Cloud Run.

מה נכלל

  • איך מאפשרים רק תעבורה מרשת VPC לשירות Cloud Run
  • איך מגדירים יציאה (egress) בשירות Cloud Run כדי לתקשר עם שירות Cloud Run עם כניסה (ingress) פנימית בלבד

7. הסרת המשאבים

כדי להימנע מחיובים לא מכוונים (לדוגמה, אם שירותי Cloud Run מופעלים בטעות יותר פעמים מההקצאה החודשית של הפעלות Cloud Run בתוכנית בחינם), אפשר למחוק את Cloud Run או את הפרויקט שיצרתם בשלב 2.

כדי למחוק את שירות Cloud Run, נכנסים למסוף Cloud Run בכתובת https://console.cloud.google.com/run ומוחקים את השירותים ‎ $FRONTEND ו-‎ $BACKEND.

אם אתם רוצים למחוק את הפרויקט כולו, אתם יכולים להיכנס לכתובת https://console.cloud.google.com/cloud-resource-manager, לבחור את הפרויקט שיצרתם בשלב 2 וללחוץ על 'מחיקה'. אם תמחקו את הפרויקט, תצטרכו לשנות את הפרויקטים ב-Cloud SDK. כדי לראות את רשימת כל הפרויקטים הזמינים, מריצים את הפקודה gcloud projects list.