إنشاء خدمة Cloud Run باستخدام تطبيق جانبي

1. نظرة عامة

مقدمة

في هذا الدرس التطبيقي حول الترميز، ستتعرّف على كيفية نشر خدمة Cloud Run تستخدم حاويات متعددة. ستنشئ تطبيق node.js سيتم استخدامه كحاوية دخول Cloud Run وتطبيق node.js إضافي سيتم استخدامه كحاوية مشتركة.

نظرة عامة فنية

عند استخدام حاويات متعدّدة ضمن مثيل Cloud Run، يتم استخدام إحدى الحاويات كحاوية رئيسية لنقل البيانات إلى الويب. يُشار إلى الحاويات الإضافية الواحدة أو أكثر باسم "حاويات مصاحبة".

هناك طريقتان لتواصل حاويات متعدّدة مع بعضها البعض:

  1. تتشارك الحاويات واجهة شبكة المضيف المحلي، لذا يمكن لجميع الحاويات الاستماع إلى منفذ، مثل localhost:port.
  2. يمكنك أيضًا استخدام وحدات تخزين في الذاكرة وتثبيتها على الحاويات لمشاركة الملفات.

حالات الاستخدام

بما أنّ جميع الحاويات ضِمن مثيل Cloud Run تشترك في واجهة شبكة المضيف المحلي، يمكنك استخدام حاوية جانبية أمام الحاوية الرئيسية لتوجيه الطلبات. يمكن أن توفّر هذه الخوادم الوكيلة طبقة تجريد إضافية لتدفّق حركة المرور بشكل أكثر فعالية إلى التطبيق بين العميل والخوادم من خلال اعتراض الطلبات وإعادة توجيهها إلى نقطة النهاية المناسبة. على سبيل المثال، يمكنك استخدام صورة Nginx الرسمية من DockerHub (كما هو موضّح هنا).

بما أنّ حاويات متعدّدة يمكنها التواصل من خلال مشاركة الملفات عبر وحدات تخزين مشتركة، يمكنك إضافة تطبيقات مختلفة إلى خدمتك. على سبيل المثال، يمكنك إعداد خدمة Cloud Run لاستخدام برامج مخصّصة، مثل OpenTelemetry، لتصدير السجلّات والمقاييس وعمليات التتبُّع (مثال على OpenTelemetry). مثال آخر هو استخدام حاوية جانبية للاتصال بقاعدة بيانات Cloud Spanner PostgreSQL (مثال على Cloud Spanner Postgress).

أمثلة في هذا الدرس التطبيقي حول الترميز

في هذا الدرس التطبيقي حول الترميز، ستنشر أولاً خدمة Cloud Run يتواصل فيها حاوية الدخول مع حاوية جانبية عبر منفذ localhost. بعد ذلك، عليك تعديل حاوية الإدخال وحاوية Sidecar لمشاركة ملف من خلال ربط وحدة تخزين.

ما ستتعلمه

  • كيفية إنشاء حاوية تستخدم حاوية جانبية
  • كيف يمكن لحاوية الدخول التواصل مع حاوية جانبية باستخدام المضيف المحلي؟
  • كيف يمكن لحاوية إدخال وحاوية sidecar مشاركة ملف من خلال وحدة تخزين مثبَّتة

2. الإعداد والمتطلبات

المتطلبات الأساسية

تفعيل Cloud Shell

  1. من Cloud Console، انقر على تفعيل Cloud Shell d1264ca30785e435.png.

cb81e7c8e34bc8d.png

إذا كانت هذه هي المرة الأولى التي تبدأ فيها Cloud Shell، ستظهر لك شاشة وسيطة توضّح ماهية هذه الخدمة. إذا ظهرت لك شاشة وسيطة، انقر على متابعة.

d95252b003979716.png

يستغرق توفير Cloud Shell والاتصال به بضع لحظات فقط.

7833d5e1c5d18f54.png

يتم تحميل هذا الجهاز الافتراضي بجميع أدوات التطوير اللازمة. توفّر هذه الخدمة دليلًا رئيسيًا دائمًا بسعة 5 غيغابايت وتعمل في Google Cloud، ما يؤدي إلى تحسين أداء الشبكة والمصادقة بشكل كبير. يمكن إنجاز معظم عملك في هذا الدرس التطبيقي حول الترميز، إن لم يكن كله، باستخدام متصفح.

بعد الاتصال بـ 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- إنشاء تطبيق Ingress

ضبط متغيرات البيئة

في هذا الدرس التطبيقي حول الترميز، ستنشئ بعض متغيرات البيئة لتحسين إمكانية قراءة أوامر gcloud المستخدَمة في هذا الدرس.

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

SERVICE_NAME=sidecar-codelab
REPO_NAME=sidecar-codelab

إنشاء مستودع ArtifactRegistry لتخزين صور الحاويات

يمكنك إنشاء مستودع في Artifact Registry لتخزين صور الحاويات الخاصة بهذا الدرس العملي.

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

إنشاء ملف dockerfile لحاوية الدخول

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

يمكنك الآن إنشاء صورة لحاوية الدخول عن طريق تنفيذ الأمر التالي:

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

4. إنشاء تطبيق Sidecar

في هذا القسم، ستنشئ تطبيق node.js ثانيًا سيتم استخدامه كحاوية مشتركة في خدمة 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

يمكنك الآن إنشاء صورة لحاوية الدخول عن طريق تنفيذ الأمر التالي:

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 لأنّ ميزة "ربط وحدات التخزين" متاحة في الإصدار التجريبي العلني.

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. مشاركة ملف من خلال ربط وحدة تخزين

في هذا القسم، ستعدّل الحاويات لمشاركة ملف من خلال ربط وحدة تخزين. في هذا المثال، سيكتب حاوية الدخول إلى ملف على وحدة تخزين مشترَكة. سيقرأ التطبيق المساعد الملف ويعيد محتواه إلى حاوية الإدخال.

عليك أولاً تعديل رمز حاوية الدخول. انتقِل إلى دليل الإدخال.

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. تهانينا!

تهانينا على إكمال هذا الدرس العملي.

ننصحك بمراجعة المستندات حول Cloud Run، وتحديدًا نشر حاويات متعدّدة واستخدام عمليات ربط وحدات التخزين في الذاكرة.

المواضيع التي تناولناها

  • كيفية إنشاء حاوية تستخدم حاوية جانبية
  • كيف يمكن لحاوية الدخول التواصل مع حاوية جانبية باستخدام المضيف المحلي؟
  • كيف يمكن لحاوية واردة وحاوية جانبية مشاركة وحدة تخزين مثبَّتة؟

8. تَنظيم

لتجنُّب فرض رسوم غير مقصودة (على سبيل المثال، إذا تم استدعاء Cloud Function هذا عن غير قصد مرات أكثر من عدد مرات الاستدعاء المخصّصة لك في Cloud Run في المستوى المجاني)، يمكنك إما حذف خدمة Cloud Run أو حذف المشروع الذي أنشأته في الخطوة 2.

لحذف Cloud Function، انتقِل إلى Cloud Console في Cloud Function على https://console.cloud.google.com/run/ واحذف خدمة sidecar-codelab (أو $SERVICE_NAME في حال استخدام اسم مختلف).

إذا اخترت حذف المشروع بأكمله، يمكنك الانتقال إلى https://console.cloud.google.com/cloud-resource-manager، واختيار المشروع الذي أنشأته في الخطوة 2، ثم النقر على "حذف". إذا حذفت المشروع، عليك تغيير المشاريع في Cloud SDK. يمكنك الاطّلاع على قائمة بجميع المشاريع المتاحة من خلال تنفيذ gcloud projects list.