יצירת שירות של Cloud Run באמצעות צדדית

1. סקירה כללית

מבוא

ב-Codelab הזה תלמדו איך לפרוס שירות Cloud Run שמשתמש בכמה קונטיינרים. תצרו אפליקציית Node.js שתשמש כקונטיינר Ingress של Cloud Run, ועוד אפליקציית Node.js שתשמש כקונטיינר sidecar.

סקירה כללית טכנית

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

יש שתי דרכים שבהן כמה קונטיינרים יכולים לתקשר ביניהם:

  1. הקונטיינרים חולקים את ממשק הרשת localhost, כך שכל הקונטיינרים יכולים להאזין ליציאה, לדוגמה localhost:port.
  2. אפשר גם להשתמש באמצעי אחסון בזיכרון ולהטמיע אותם במאגרי התוכן כדי לשתף קבצים.

תרחישים לדוגמה

מכיוון שכל הקונטיינרים במופע Cloud Run חולקים את ממשק הרשת של localhost, אפשר להשתמש ב-sidecar לפני הקונטיינר הראשי כדי להעביר בקשות דרך proxy. שרתי proxy כאלה יכולים לספק שכבת הפשטה נוספת לזרימת תנועה יעילה יותר לאפליקציה בין הלקוח לשרתים, על ידי יירוט בקשות והעברתן לנקודת הקצה המתאימה. לדוגמה, אפשר להשתמש באימג' הרשמי של Nginx מ-DockerHub (כפי שמוצג כאן).

מכיוון שכמה קונטיינרים יכולים לתקשר ביניהם באמצעות שיתוף קבצים דרך כרכים משותפים, אתם יכולים להוסיף לשירות שלכם אפליקציות שונות של sidecar. לדוגמה, אתם יכולים להגדיר את שירות Cloud Run כך שישתמש בסוכנים מותאמים אישית כמו OpenTelemetry כדי לייצא יומנים, מדדים ועקבות (דוגמה ל-OpenTelemetry). דוגמה נוספת היא שימוש ב-sidecar כדי להתחבר למסד נתונים של Cloud Spanner PostgreSQL (דוגמה ל-Cloud Spanner Postgress).

דוגמאות ב-Codelab הזה

ב-Codelab הזה, קודם תפרסו שירות Cloud Run שבו קונטיינר הכניסה מתקשר עם קונטיינר קובץ עזר דרך יציאת localhost. לאחר מכן, מעדכנים את קובץ ה-ingress ואת קובץ ה-sidecar כדי לשתף קובץ באמצעות טעינת נפח.

מה תלמדו

  • איך יוצרים קונטיינר שמשתמש ב-sidecar
  • איך קונטיינר של Ingress יכול לתקשר עם קונטיינר sidecar באמצעות localhost
  • איך קונטיינר של תעבורת נכנסת וקונטיינר sidecar יכולים לשתף קובץ באמצעות נפח מוטמע

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. יצירת אפליקציית הכניסה

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

ב-codelab הזה תיצרו כמה משתני סביבה כדי לשפר את הקריאות של הפקודות gcloud שמשמשות ב-codelab הזה.

REGION=<YOUR-REGION>
PROJECT_ID=<YOUR-PROJECT-ID>

SERVICE_NAME=sidecar-codelab
REPO_NAME=sidecar-codelab

יצירת מאגר ArtifactRegistry לאחסון תמונות קונטיינרים

אתם יכולים ליצור מאגר ב-Artifact Registry כדי לאחסן את תמונות הקונטיינר שלכם בשביל ה-codelab הזה.

gcloud artifacts repositories create $REPO_NAME --repository-format=docker \
--location=$REGION --description="sidecar codelab"

לאחר מכן, יוצרים קובץ package.json עם התוכן הבא:

{
  "name": "sidecar-codelab",
  "version": "1.0.0",
  "private": true,
  "description": "demonstrates how to use sidecars in cloud run",
  "main": "index.js",
  "author": "Google LLC",
  "license": "Apache-2.0",
  "scripts": {
    "start": "node ingress.js"
  },
  "dependencies": {
    "axios": "^1.6.2",
    "express": "^4.18.2"
  }
}

עכשיו יוצרים קובץ בשם ingress.js עם התוכן הבא:

const express = require('express');
const app = express();
const axios = require("axios");

app.get('/', async (req, res) => {

    let response = await axios.get("http://localhost:5000");

    res.send("The sidecar says: " + response.data);
});

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

יצירת קובץ Docker למאגר הכניסה

FROM node:20.10.0-slim
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install --production

# Copy local code to the container image.
COPY . .

# Run the web service on container startup.
ENV PORT=8080
CMD [ "npm", "start" ]

יוצרים קובץ ‎.dockerignore למאגר התגים של הכניסה.

# Exclude locally installed dependencies
node_modules/

# Exclude "build-time" ignore files.
.dockerignore
.gcloudignore

# Exclude git history and configuration.
.gitignore

עכשיו אפשר ליצור את קובץ האימג' של קונטיינר ה-ingress על ידי הרצת הפקודה הבאה:

gcloud builds submit --tag $REGION-docker.pkg.dev/$PROJECT_ID/$REPO_NAME/ingress:latest

4. יצירת אפליקציית ה-sidecar

בקטע הזה תיצרו אפליקציית Node.js שנייה שתשמש כ-sidecar בשירות Cloud Run.

עוברים לספרייה sidecar.

cd ../sidecar

יוצרים קובץ package.json עם התוכן הבא:

{
  "name": "sidecar-codelab",
  "version": "1.0.0",
  "private": true,
  "description": "demonstrates how to use sidecars in cloud run",
  "main": "index.js",
  "author": "Google LLC",
  "license": "Apache-2.0",
  "scripts": {
    "start": "node sidecar.js"
  },
  "dependencies": {
    "axios": "^1.6.2",
    "express": "^4.18.2"
  }
}

עכשיו יוצרים קובץ בשם sidecar.js עם התוכן הבא:

const express = require('express');
const app = express();

app.get('/', async (req, res) => {
    res.send("Hello ingress container! I'm the sidecar.");
});

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

יצירת קובץ Dockerfile לקונטיינר sidecar

FROM node:20.10.0-slim
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install --production

# Copy local code to the container image.
COPY . .

# Run the web service on container startup.
ENV PORT=5000
CMD [ "npm", "start" ]

יוצרים קובץ ‎.dockerignore עבור קונטיינר ה-sidecar.

# Exclude locally installed dependencies
node_modules/

# Exclude "build-time" ignore files.
.dockerignore
.gcloudignore

# Exclude git history and configuration.
.gitignore

עכשיו אפשר ליצור את קובץ האימג' של קונטיינר ה-ingress על ידי הרצת הפקודה הבאה:

gcloud builds submit --tag $REGION-docker.pkg.dev/$PROJECT_ID/$REPO_NAME/sidecar:latest

פריסת שירות Cloud Run

תפרסו את שירות Cloud Run באמצעות קובץ YAML.

עוברים לספריית ההורה.

cd ..

יוצרים קובץ בשם sidecar-codelab.yaml עם התוכן הבא:

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  annotations:
  name: sidecar-codelab
  labels:
    cloud.googleapis.com/location: "<YOUR_REGION>"
spec:
  template:
    spec:
      containers:
        - image: "<YOUR_REGION>-docker.pkg.dev/<YOUR_PROJECT_ID>/sidecar-codelab/ingress:latest"
          ports:
            - containerPort: 8080
        - image: "<YOUR_REGION>-docker.pkg.dev/<YOUR_PROJECT_ID>/sidecar-codelab/sidecar:latest"
          env:
            - name: PORT
              value: "5000"

לאחר מכן פורסים את השירות באמצעות הפקודה הבאה. צריך להשתמש ב-gcloud beta כי האפשרות 'טעינת אמצעי אחסון' נמצאת בגרסת Public Preview.

gcloud beta run services replace sidecar-codelab.yaml

אחרי הפריסה, שומרים את כתובת ה-URL של השירות במשתנה סביבה.

SERVICE_URL=$(gcloud run services describe $SERVICE_NAME --platform managed --region $REGION --format 'value(status.url)') 

5. קריאה לשירות Cloud Run

עכשיו אפשר להתקשר לשירות על ידי צירוף אסימון הזהות.

curl -X GET -H "Authorization: Bearer $(gcloud auth print-identity-token)" ${SERVICE_URL}

התוצאות שלכם אמורות להיות דומות לפלט לדוגמה שבהמשך:

The sidecar says: Hello ingress container! I'm the sidecar.

6. שיתוף קובץ באמצעות טעינת אמצעי אחסון

בקטע הזה תעדכנו את הקונטיינרים כדי לשתף קובץ באמצעות טעינת נפח אחסון. בדוגמה הזו, קונטיינר הכניסה יכתוב לקובץ בכרך משותף. קובץ ה-sidecar יקרא את הקובץ ויחזיר את התוכן שלו למאגר הכניסה.

קודם מעדכנים את קוד מאגר התגים של הכניסה. עוברים לספריית הכניסה.

cd ../ingress

ואז מחליפים את התוכן של הקובץ ingress.js בתוכן הבא:

const express = require('express');
const app = express();
const fs = require('fs');
const axios = require("axios");

const filename = "test.txt"

let path = "/my-volume-mount";
app.use(path, express.static(path));

try {
    fs.writeFileSync(`${path}/${filename}`, "The ingress container created this file.");
} catch (err) {
    console.error(err);
}

app.get('/', async (req, res) => {

    let response = await axios.get("http://localhost:5000");

    res.send("The sidecar says: " + response.data);
});

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

מריצים את הפקודה הבאה כדי ליצור את קובץ האימג' החדש של קונטיינר הכניסה:

gcloud builds submit --tag $REGION-docker.pkg.dev/$PROJECT_ID/$REPO_NAME/ingress:latest

עכשיו עוברים לספריית ה-sidecar:

cd ../sidecar

מעדכנים את sidecar.js עם התוכן הבא:

const express = require('express');
const app = express();
const fs = require('fs');

const filename = "test.txt"

let path = "/my-volume-mount";
app.use(path, express.static(path));

async function readFile() {
    try {
        return await fs.readFileSync(`${path}/${filename}`, { encoding: 'utf8' });
    } catch (err) {
        console.log(err);
    }
}

app.get('/', async (req, res) => {
    let contents = await readFile();
    res.send(contents);
});

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

מריצים את הפקודה הבאה כדי ליצור את קובץ האימג' החדש של קונטיינר ה-sidecar:

gcloud builds submit --tag $REGION-docker.pkg.dev/$PROJECT_ID/$REPO_NAME/sidecar:latest

כדי לשתף נפח אחסון, מעדכנים את sidecar-codelab.yaml באופן הבא:

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  annotations:
  name: sidecar-codelab
  labels:
    cloud.googleapis.com/location: "<YOUR_REGION>"
spec:
  template:
    spec:
      containers:
        - image: "<YOUR_REGION>-docker.pkg.dev/<YOUR_PROJECT_ID>/sidecar-codelab/ingress:latest"
          ports:
            - containerPort: 8080
          volumeMounts:
            - mountPath: /my-volume-mount
              name: in-memory-1
        - image: "<YOUR_REGION>-docker.pkg.dev/<YOUR_PROJECT_ID>/sidecar-codelab/sidecar:latest"
          env:
            - name: PORT
              value: "5000"
          volumeMounts:
            - mountPath: /my-volume-mount
              name: in-memory-1
      volumes:
        - emptyDir:
            medium: Memory
          name: in-memory-1

פריסה של הקובץ המעודכן sidecar-codelab.yaml

gcloud beta run services replace sidecar-codelab.yaml

עכשיו אפשר להתקשר לשירות על ידי צירוף אסימון הזהות.

curl -X GET -H "Authorization: Bearer $(gcloud auth print-identity-token)" ${SERVICE_URL}

התוצאות שלכם אמורות להיות דומות לפלט לדוגמה שבהמשך:

The sidecar says: the ingress container created this file.

7. מעולה!

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

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

מה נכלל

  • איך יוצרים קונטיינר שמשתמש ב-sidecar
  • איך קונטיינר של Ingress יכול לתקשר עם קונטיינר sidecar באמצעות localhost
  • איך קונטיינר של Ingress וקונטיינר sidecar יכולים לחלוק נפח אחסון מוטמע

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

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

כדי למחוק את Cloud Function, עוברים אל Cloud Console בכתובת https://console.cloud.google.com/run/ ומוחקים את שירות sidecar-codelab (או את ‎ $SERVICE_NAME אם השתמשתם בשם אחר).

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