Pic-a-daily: Lab 2—สร้างภาพขนาดย่อของรูปภาพ

1. ภาพรวม

ในโค้ดแล็บนี้ คุณจะต่อยอดจากแล็บก่อนหน้าและเพิ่มบริการภาพขนาดย่อ บริการภาพขนาดย่อคือคอนเทนเนอร์บนเว็บที่รับรูปภาพขนาดใหญ่และสร้างภาพขนาดย่อจากรูปภาพเหล่านั้น

เมื่ออัปโหลดรูปภาพไปยัง Cloud Storage ระบบจะส่งการแจ้งเตือนผ่าน Cloud Pub/Sub ไปยังเว็บคอนเทนเนอร์ Cloud Run ซึ่งจะปรับขนาดรูปภาพและบันทึกกลับไปยัง Bucket อื่นใน Cloud Storage

31fa4f8a294d90df.png

สิ่งที่คุณจะได้เรียนรู้

  • Cloud Run
  • Cloud Storage
  • Cloud Pub/Sub

2. การตั้งค่าและข้อกำหนด

การตั้งค่าสภาพแวดล้อมแบบเรียนรู้ด้วยตนเอง

  1. ลงชื่อเข้าใช้ Google Cloud Console แล้วสร้างโปรเจ็กต์ใหม่หรือใช้โปรเจ็กต์ที่มีอยู่ซ้ำ หากยังไม่มีบัญชี Gmail หรือ Google Workspace คุณต้องสร้างบัญชี

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

  • ชื่อโปรเจ็กต์คือชื่อที่แสดงสำหรับผู้เข้าร่วมโปรเจ็กต์นี้ โดยเป็นสตริงอักขระที่ Google APIs ไม่ได้ใช้ และคุณสามารถอัปเดตได้ทุกเมื่อ
  • รหัสโปรเจ็กต์ต้องไม่ซ้ำกันในโปรเจ็กต์ Google Cloud ทั้งหมดและเปลี่ยนแปลงไม่ได้ (เปลี่ยนไม่ได้หลังจากตั้งค่าแล้ว) Cloud Console จะสร้างสตริงที่ไม่ซ้ำกันโดยอัตโนมัติ ซึ่งโดยปกติแล้วคุณไม่จำเป็นต้องสนใจว่าสตริงนั้นคืออะไร ใน Codelab ส่วนใหญ่ คุณจะต้องอ้างอิงรหัสโปรเจ็กต์ (และโดยทั่วไปจะระบุเป็น PROJECT_ID) ดังนั้นหากไม่ชอบรหัสที่สร้างขึ้น ให้สร้างรหัสแบบสุ่มอีกรหัส หรือจะลองใช้รหัสของคุณเองและดูว่ามีรหัสนั้นหรือไม่ก็ได้ จากนั้นจะ "หยุด" หลังจากสร้างโปรเจ็กต์แล้ว
  • นอกจากนี้ยังมีค่าที่ 3 คือหมายเลขโปรเจ็กต์ ซึ่ง API บางตัวใช้ ดูข้อมูลเพิ่มเติมเกี่ยวกับค่าทั้ง 3 นี้ได้ในเอกสารประกอบ
  1. จากนั้นคุณจะต้องเปิดใช้การเรียกเก็บเงินใน Cloud Console เพื่อใช้ทรัพยากร/API ของ Cloud การทำตาม Codelab นี้ไม่ควรมีค่าใช้จ่ายมากนัก หรืออาจไม่มีเลย หากต้องการปิดแหล่งข้อมูลเพื่อไม่ให้มีการเรียกเก็บเงินนอกเหนือจากบทแนะนำนี้ ให้ทำตามวิธีการ "ล้างข้อมูล" ที่ตอนท้ายของ Codelab ผู้ใช้ Google Cloud รายใหม่มีสิทธิ์เข้าร่วมโปรแกรมช่วงทดลองใช้ฟรีมูลค่า$300 USD

เริ่มต้น Cloud Shell

แม้ว่าคุณจะใช้งาน Google Cloud จากระยะไกลจากแล็ปท็อปได้ แต่ใน Codelab นี้คุณจะใช้ Google Cloud Shell ซึ่งเป็นสภาพแวดล้อมบรรทัดคำสั่งที่ทำงานในระบบคลาวด์

จาก GCP Console ให้คลิกไอคอน Cloud Shell ในแถบเครื่องมือด้านขวาบน

bce75f34b2c53987.png

การจัดสรรและเชื่อมต่อกับสภาพแวดล้อมจะใช้เวลาเพียงไม่กี่นาที เมื่อเสร็จแล้ว คุณควรเห็นข้อความคล้ายกับตัวอย่างต่อไปนี้

f6ef2b5f13479f3a.png

เครื่องเสมือนนี้มาพร้อมเครื่องมือพัฒนาซอฟต์แวร์ทั้งหมดที่คุณต้องการ โดยมีไดเรกทอรีหลักแบบถาวรขนาด 5 GB และทำงานบน Google Cloud ซึ่งช่วยเพิ่มประสิทธิภาพเครือข่ายและการตรวจสอบสิทธิ์ได้อย่างมาก คุณสามารถทำงานทั้งหมดในห้องทดลองนี้ได้โดยใช้เพียงเบราว์เซอร์

3. เปิดใช้ API

ในแล็บนี้ คุณจะต้องใช้ Cloud Build เพื่อสร้างอิมเมจคอนเทนเนอร์ และ Cloud Run เพื่อทำให้คอนเทนเนอร์ใช้งานได้

เปิดใช้ทั้ง 2 API จาก Cloud Shell โดยทำดังนี้

gcloud services enable cloudbuild.googleapis.com \
  run.googleapis.com

คุณควรเห็นการดำเนินการเสร็จสมบูรณ์ดังนี้

Operation "operations/acf.5c5ef4f6-f734-455d-b2f0-ee70b5a17322" finished successfully.

4. สร้างที่เก็บข้อมูลอื่น

คุณจะจัดเก็บภาพปกของรูปภาพที่อัปโหลดไว้ในอีก Bucket หนึ่ง มาใช้ gsutil เพื่อสร้าง Bucket ที่ 2 กัน

ใน Cloud Shell ให้ตั้งค่าตัวแปรสำหรับชื่อที่เก็บข้อมูลที่ไม่ซ้ำกัน Cloud Shell มี GOOGLE_CLOUD_PROJECT ตั้งค่าเป็นรหัสโปรเจ็กต์ที่ไม่ซ้ำกันของคุณอยู่แล้ว คุณสามารถต่อท้ายชื่อ Bucket ได้ จากนั้นสร้าง Bucket แบบหลายภูมิภาคสาธารณะในยุโรปที่มีสิทธิ์เข้าถึงระดับเดียวกัน

BUCKET_THUMBNAILS=thumbnails-$GOOGLE_CLOUD_PROJECT
gsutil mb -l EU gs://$BUCKET_THUMBNAILS
gsutil uniformbucketlevelaccess set on gs://$BUCKET_THUMBNAILS
gsutil iam ch allUsers:objectViewer gs://$BUCKET_THUMBNAILS

ในท้ายที่สุด คุณควรมีที่เก็บข้อมูลสาธารณะใหม่ดังนี้

8e75c8099938e972.png

5. โคลนโค้ด

โคลนโค้ดแล้วไปที่ไดเรกทอรีที่มีบริการโดยใช้คำสั่งต่อไปนี้

git clone https://github.com/GoogleCloudPlatform/serverless-photosharing-workshop
cd serverless-photosharing-workshop/services/thumbnails/nodejs

คุณจะมีเลย์เอาต์ไฟล์ต่อไปนี้สำหรับบริการ

services
 |
 ├── thumbnails
      |
      ├── nodejs
           |
           ├── Dockerfile
           ├── index.js
           ├── package.json

ภายในโฟลเดอร์ thumbnails/nodejs คุณจะมีไฟล์ 3 ไฟล์ดังนี้

  • index.js มีโค้ด Node.js
  • package.json กำหนดทรัพยากร Dependency ของไลบรารี
  • Dockerfile กำหนดอิมเมจคอนเทนเนอร์

6. สำรวจโค้ด

หากต้องการสำรวจโค้ด คุณสามารถใช้โปรแกรมแก้ไขข้อความในตัวได้โดยคลิกปุ่ม Open Editor ที่ด้านบนของหน้าต่าง Cloud Shell

3d145fe299dd8b3e.png

นอกจากนี้ คุณยังเปิดเครื่องมือแก้ไขในหน้าต่างเบราว์เซอร์เฉพาะได้ด้วยเพื่อให้มีพื้นที่หน้าจอมากขึ้น

ทรัพยากร Dependency

ไฟล์ package.json จะกำหนดทรัพยากร Dependency ของไลบรารีที่จำเป็น

{
  "name": "thumbnail_service",
  "version": "0.0.1",
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  },
  "dependencies": {
    "bluebird": "^3.7.2",
    "express": "^4.17.1",
    "imagemagick": "^0.1.3",
    "@google-cloud/firestore": "^4.9.9",
    "@google-cloud/storage": "^5.8.3"
  }
}

ไลบรารี Cloud Storage ใช้เพื่ออ่านและบันทึกไฟล์รูปภาพภายใน Cloud Storage Firestore เพื่ออัปเดตข้อมูลเมตาของรูปภาพ Express เป็นเฟรมเวิร์กเว็บ JavaScript / Node โมดูล Body-parser ใช้เพื่อแยกวิเคราะห์คำขอขาเข้าได้อย่างง่ายดาย Bluebird ใช้สำหรับการจัดการ Promise และ Imagemagick เป็นไลบรารีสำหรับการจัดการรูปภาพ

Dockerfile

Dockerfile กำหนดอิมเมจคอนเทนเนอร์สำหรับแอปพลิเคชัน

FROM node:14-slim

# installing Imagemagick
RUN set -ex; \
  apt-get -y update; \
  apt-get -y install imagemagick; \
  rm -rf /var/lib/apt/lists/*; \
  mkdir /tmp/original; \
  mkdir /tmp/thumbnail;

WORKDIR /picadaily/services/thumbnails
COPY package*.json ./
RUN npm install --production
COPY . .
CMD [ "npm", "start" ]

อิมเมจพื้นฐานคือ Node 14 และใช้ไลบรารี ImageMagick ในการจัดการรูปภาพ ระบบจะสร้างไดเรกทอรีชั่วคราวบางรายการเพื่อจัดเก็บไฟล์รูปภาพต้นฉบับและภาพขนาดย่อ จากนั้นระบบจะติดตั้งโมดูล NPM ที่โค้ดของเราต้องการก่อนที่จะเริ่มโค้ดด้วย npm start

index.js

มาดูโค้ดทีละส่วนเพื่อให้เข้าใจการทำงานของโปรแกรมนี้ได้ดียิ่งขึ้น

const express = require('express');
const imageMagick = require('imagemagick');
const Promise = require("bluebird");
const path = require('path');
const {Storage} = require('@google-cloud/storage');
const Firestore = require('@google-cloud/firestore');

const app = express();
app.use(express.json());

ก่อนอื่นเราต้องระบุการอ้างอิงที่จำเป็นและสร้างเว็บแอปพลิเคชัน Express รวมถึงระบุว่าเราต้องการใช้ตัวแยกวิเคราะห์เนื้อหา JSON เนื่องจากคำขอขาเข้าเป็นเพียงเพย์โหลด JSON ที่ส่งผ่านคำขอ POST ไปยังแอปพลิเคชันของเรา

app.post('/', async (req, res) => {
    try {
        // ...
    } catch (err) {
        console.log(`Error: creating the thumbnail: ${err}`);
        console.error(err);
        res.status(500).send(err);
    }
});

เราได้รับเพย์โหลดขาเข้าเหล่านั้นใน URL ฐาน / และเรากำลังห่อหุ้มโค้ดของเราด้วยตรรกะการจัดการข้อผิดพลาดบางอย่าง เพื่อให้มีข้อมูลที่ดีขึ้นเกี่ยวกับสาเหตุที่อาจเกิดข้อผิดพลาดในโค้ดของเราโดยดูที่บันทึกที่จะมองเห็นได้จากอินเทอร์เฟซ Stackdriver Logging ในเว็บคอนโซลของ Google Cloud

const pubSubMessage = req.body;
console.log(`PubSub message: ${JSON.stringify(pubSubMessage)}`);

const fileEvent = JSON.parse(Buffer.from(pubSubMessage.message.data, 'base64').toString().trim());
console.log(`Received thumbnail request for file ${fileEvent.name} from bucket ${fileEvent.bucket}`);

ในแพลตฟอร์ม Cloud Run ระบบจะส่งข้อความ Pub/Sub ผ่านคำขอ HTTP POST เป็นเพย์โหลด JSON ในรูปแบบต่อไปนี้

{
  "message": {
    "attributes": {
      "bucketId": "uploaded-pictures",
      "eventTime": "2020-02-27T09:22:43.255225Z",
      "eventType": "OBJECT_FINALIZE",
      "notificationConfig": "projects/_/buckets/uploaded-pictures/notificationConfigs/28",
      "objectGeneration": "1582795363255481",
      "objectId": "IMG_20200213_181159.jpg",
      "payloadFormat": "JSON_API_V1"
    },
    "data": "ewogICJraW5kIjogInN0b3JhZ2Ujb2JqZWN...FQUU9Igp9Cg==",
    "messageId": "1014308302773399",
    "message_id": "1014308302773399",
    "publishTime": "2020-02-27T09:22:43.973Z",
    "publish_time": "2020-02-27T09:22:43.973Z"
  },
  "subscription": "projects/serverless-picadaily/subscriptions/gcs-events-subscription"
}

แต่สิ่งที่น่าสนใจจริงๆ ในเอกสาร JSON นี้คือสิ่งที่อยู่ในแอตทริบิวต์ message.data ซึ่งเป็นเพียงสตริงที่เข้ารหัสเพย์โหลดจริงเป็น Base 64 ด้วยเหตุนี้ โค้ดด้านบนจึงถอดรหัสเนื้อหา Base64 ของแอตทริบิวต์นี้ เมื่อถอดรหัสแล้ว แอตทริบิวต์ data จะมีเอกสาร JSON อีกรายการหนึ่งซึ่งแสดงรายละเอียดเหตุการณ์ของ Cloud Storage ซึ่งจะระบุชื่อไฟล์และชื่อ Bucket รวมถึงข้อมูลเมตาอื่นๆ

{
  "kind": "storage#object",
  "id": "uploaded-pictures/IMG_20200213_181159.jpg/1582795363255481",
  "selfLink": "https://www.googleapis.com/storage/v1/b/uploaded-pictures/o/IMG_20200213_181159.jpg",
  "name": "IMG_20200213_181159.jpg",
  "bucket": "uploaded-pictures",
  "generation": "1582795363255481",
  "metageneration": "1",
  "contentType": "image/jpeg",
  "timeCreated": "2020-02-27T09:22:43.255Z",
  "updated": "2020-02-27T09:22:43.255Z",
  "storageClass": "STANDARD",
  "timeStorageClassUpdated": "2020-02-27T09:22:43.255Z",
  "size": "4944335",
  "md5Hash": "QzBIoPJBV2EvqB1EVk1riw==",
  "mediaLink": "https://www.googleapis.com/download/storage/v1/b/uploaded-pictures/o/IMG_20200213_181159.jpg?generation=1582795363255481&alt=media",
  "crc32c": "hQ3uHg==",
  "etag": "CLmJhJu08ecCEAE="
}

เราสนใจชื่อรูปภาพและชื่อที่เก็บข้อมูล เนื่องจากโค้ดของเราจะดึงรูปภาพดังกล่าวจากที่เก็บข้อมูลเพื่อใช้เป็นภาพปก

const bucket = storage.bucket(fileEvent.bucket);
const thumbBucket = storage.bucket(process.env.BUCKET_THUMBNAILS);

const originalFile = path.resolve('/tmp/original', fileEvent.name);
const thumbFile = path.resolve('/tmp/thumbnail', fileEvent.name);

await bucket.file(fileEvent.name).download({
    destination: originalFile
});
console.log(`Downloaded picture into ${originalFile}`);

เรากำลังดึงชื่อของที่เก็บข้อมูลเอาต์พุตจากตัวแปรสภาพแวดล้อม

เรามี Bucket ต้นทางที่การสร้างไฟล์ทำให้บริการ Cloud Run ทํางาน และ Bucket ปลายทางที่เราจะจัดเก็บรูปภาพผลลัพธ์ เราใช้ pathAPI ในตัวเพื่อจัดการไฟล์ในเครื่อง เนื่องจากไลบรารี ImageMagick จะสร้างภาพขนาดย่อในเครื่องใน/tmpไดเรกทอรีชั่วคราว เราawaitสำหรับการเรียกแบบอะซิงโครนัสเพื่อดาวน์โหลดไฟล์รูปภาพที่อัปโหลด

const resizeCrop = Promise.promisify(im.crop);
await resizeCrop({
        srcPath: originalFile,
        dstPath: thumbFile,
        width: 400,
        height: 400         
});
console.log(`Created local thumbnail in ${thumbFile}`);

โมดูล ImageMagick ไม่ค่อยเป็นมิตรกับ async / await เราจึงห่อหุ้มไว้ใน Promise ของ JavaScript (จัดทำโดยโมดูล Bluebird) จากนั้นเราจะเรียกใช้ฟังก์ชันการปรับขนาด / ครอบตัดแบบอะซิงโครนัสที่เราสร้างขึ้นพร้อมกับพารามิเตอร์สำหรับไฟล์ต้นฉบับและไฟล์ปลายทาง รวมถึงขนาดของภาพขนาดย่อที่เราต้องการสร้าง

await thumbBucket.upload(thumbFile);
console.log(`Uploaded thumbnail to Cloud Storage bucket ${process.env.BUCKET_THUMBNAILS}`);

เมื่ออัปโหลดไฟล์ภาพปกไปยัง Cloud Storage แล้ว เราจะอัปเดตข้อมูลเมตาใน Cloud Firestore เพื่อเพิ่มค่าสถานะบูลีนที่ระบุว่าระบบได้สร้างภาพปกสำหรับรูปภาพนี้แล้ว

const pictureStore = new Firestore().collection('pictures');
const doc = pictureStore.doc(fileEvent.name);
await doc.set({
    thumbnail: true
}, {merge: true});
console.log(`Updated Firestore about thumbnail creation for ${fileEvent.name}`);

res.status(204).send(`${fileEvent.name} processed`);

เมื่อคำขอของเราสิ้นสุดลง เราจะตอบกลับคำขอ HTTP POST ว่าระบบประมวลผลไฟล์อย่างถูกต้องแล้ว

const PORT = process.env.PORT || 8080;

app.listen(PORT, () => {
    console.log(`Started thumbnail generator on port ${PORT}`);
});

ที่ส่วนท้ายของไฟล์ต้นฉบับ เรามีวิธีการเพื่อให้ Express เริ่มแอปพลิเคชันเว็บในพอร์ตเริ่มต้น 8080 จริงๆ

7. ทดสอบในเครื่อง

ทดสอบโค้ดในเครื่องเพื่อให้แน่ใจว่าใช้งานได้ก่อนที่จะนำไปใช้ในระบบคลาวด์

ในโฟลเดอร์ thumbnails/nodejs ให้ติดตั้งทรัพยากร Dependency ของ npm และเริ่มเซิร์ฟเวอร์โดยทำดังนี้

npm install; npm start

หากทุกอย่างเป็นไปด้วยดี เซิร์ฟเวอร์ควรเริ่มทำงานบนพอร์ต 8080

Started thumbnail generator on port 8080

ใช้ CTRL-C เพื่อออก

8. สร้างและเผยแพร่อิมเมจคอนเทนเนอร์

Cloud Run เรียกใช้คอนเทนเนอร์ แต่ก่อนอื่นคุณต้องสร้างอิมเมจคอนเทนเนอร์ (กำหนดไว้ใน Dockerfile) คุณสามารถใช้ Google Cloud Build เพื่อสร้างอิมเมจคอนเทนเนอร์ แล้วโฮสต์ไปยัง Google Container Registry ได้

ในโฟลเดอร์ thumbnails/nodejs ที่มี Dockerfile ให้เรียกใช้คำสั่งต่อไปนี้เพื่อสร้างอิมเมจคอนเทนเนอร์

gcloud builds submit --tag gcr.io/$GOOGLE_CLOUD_PROJECT/thumbnail-service

หลังจากผ่านไป 1-2 นาที การสร้างควรสำเร็จ

b354b3a9a3631097.png

ส่วน "ประวัติ" ของ Cloud Build ควรแสดงบิลด์ที่สำเร็จด้วย

df00f198dd2bf6bf.png

เมื่อคลิกรหัสบิลด์เพื่อดูมุมมองรายละเอียด คุณจะเห็นว่าระบบได้อัปโหลดอิมเมจคอนเทนเนอร์ไปยัง Cloud Registry (GCR) ในแท็บ "อาร์ติแฟกต์ของบิลด์"

a4577ce0744f73e2.png

หากต้องการ คุณสามารถตรวจสอบอีกครั้งว่าอิมเมจคอนเทนเนอร์ทำงานในเครื่องใน Cloud Shell ได้โดยทำดังนี้

docker run -p 8080:8080 gcr.io/$GOOGLE_CLOUD_PROJECT/thumbnail-service

โดยควรเริ่มเซิร์ฟเวอร์ในพอร์ต 8080 ในคอนเทนเนอร์

Started thumbnail generator on port 8080

ใช้ CTRL-C เพื่อออก

9. ทำให้ใช้งานได้กับ Cloud Run

ก่อนที่จะทำให้ใช้งานได้กับ Cloud Run ให้ตั้งค่าภูมิภาค Cloud Run เป็นภูมิภาคที่รองรับและแพลตฟอร์มเป็น managed

gcloud config set run/region europe-west1
gcloud config set run/platform managed

คุณตรวจสอบได้ว่าได้ตั้งค่าการกำหนดค่าแล้วหรือไม่โดยทำดังนี้

gcloud config list

...
[run]
platform = managed
region = europe-west1

เรียกใช้คำสั่งต่อไปนี้เพื่อทําให้อิมเมจคอนเทนเนอร์ใช้งานได้ใน Cloud Run

SERVICE_NAME=thumbnail-service
gcloud run deploy $SERVICE_NAME \
    --image gcr.io/$GOOGLE_CLOUD_PROJECT/thumbnail-service \
    --no-allow-unauthenticated \
    --update-env-vars BUCKET_THUMBNAILS=$BUCKET_THUMBNAILS

โปรดสังเกตธง --no-allow-unauthenticated ซึ่งจะทำให้บริการ Cloud Run เป็นบริการภายในที่จะทริกเกอร์ได้โดยบัญชีบริการที่เฉพาะเจาะจงเท่านั้น

หากการติดตั้งใช้งานสำเร็จ คุณควรเห็นเอาต์พุตต่อไปนี้

c0f28e7d6de0024.png

หากไปที่ UI ของคอนโซลระบบคลาวด์ คุณควรเห็นว่าระบบได้ติดตั้งใช้งานบริการเรียบร้อยแล้วด้วย

9bfe48e3c8b597e5.png

10. เหตุการณ์ Cloud Storage ไปยัง Cloud Run ผ่าน Pub/Sub

บริการพร้อมใช้งานแล้ว แต่คุณยังคงต้องสร้างเหตุการณ์ Cloud Storage ไปยังบริการ Cloud Run ที่สร้างขึ้นใหม่ Cloud Storage สามารถส่งเหตุการณ์การสร้างไฟล์ผ่าน Cloud Pub/Sub ได้ แต่ต้องทำตามขั้นตอน 2-3 ขั้นตอนเพื่อให้ทำงานได้

สร้างหัวข้อ Pub/Sub เป็นไปป์ไลน์การสื่อสาร

TOPIC_NAME=cloudstorage-cloudrun-topic
gcloud pubsub topics create $TOPIC_NAME

สร้างการแจ้งเตือน Pub/Sub เมื่อจัดเก็บไฟล์ในที่เก็บข้อมูลโดยทำดังนี้

BUCKET_PICTURES=uploaded-pictures-$GOOGLE_CLOUD_PROJECT
gsutil notification create -t $TOPIC_NAME -f json gs://$BUCKET_PICTURES

สร้างบัญชีบริการสำหรับการสมัครใช้บริการ Pub/Sub ที่เราจะสร้างในภายหลัง

SERVICE_ACCOUNT=$TOPIC_NAME-sa
gcloud iam service-accounts create $SERVICE_ACCOUNT \
     --display-name "Cloud Run Pub/Sub Invoker"

ให้สิทธิ์บัญชีบริการในการเรียกใช้บริการ Cloud Run โดยทำดังนี้

SERVICE_NAME=thumbnail-service
gcloud run services add-iam-policy-binding $SERVICE_NAME \
   --member=serviceAccount:$SERVICE_ACCOUNT@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com \
   --role=roles/run.invoker

หากเปิดใช้บัญชีบริการ Pub/Sub ในวันที่ 8 เมษายน 2021 หรือก่อนหน้านั้น ให้มอบบทบาท iam.serviceAccountTokenCreator ให้กับบัญชีบริการ Pub/Sub โดยทำดังนี้

PROJECT_NUMBER=$(gcloud projects describe $GOOGLE_CLOUD_PROJECT --format='value(projectNumber)')
gcloud projects add-iam-policy-binding $GOOGLE_CLOUD_PROJECT \
     --member=serviceAccount:service-$PROJECT_NUMBER@gcp-sa-pubsub.iam.gserviceaccount.com \
     --role=roles/iam.serviceAccountTokenCreator

การเปลี่ยนแปลง IAM อาจใช้เวลา 2-3 นาทีจึงจะมีผล

สุดท้าย ให้สร้างการสมัครใช้บริการ Pub/Sub ด้วยบัญชีบริการ

SERVICE_URL=$(gcloud run services describe $SERVICE_NAME --format 'value(status.url)')
gcloud pubsub subscriptions create $TOPIC_NAME-subscription --topic $TOPIC_NAME \
   --push-endpoint=$SERVICE_URL \
   --push-auth-service-account=$SERVICE_ACCOUNT@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com

คุณตรวจสอบได้ว่ามีการสร้างการสมัครใช้บริการแล้ว ไปที่ Pub/Sub ในคอนโซล เลือกgcs-events หัวข้อ แล้วคุณจะเห็นการสมัครใช้บริการที่ด้านล่าง

e8ab86dccb8d890.png

11. ทดสอบบริการ

หากต้องการทดสอบว่าการตั้งค่าใช้งานได้หรือไม่ ให้อัปโหลดรูปภาพใหม่ไปยัง Bucket uploaded-pictures แล้วตรวจสอบใน Bucket thumbnails ว่ารูปภาพใหม่ที่ปรับขนาดแล้วปรากฏตามที่คาดไว้หรือไม่

นอกจากนี้ คุณยังตรวจสอบบันทึกอีกครั้งเพื่อดูข้อความบันทึกที่ปรากฏขึ้นได้ เนื่องจากขั้นตอนต่างๆ ของบริการ Cloud Run กำลังดำเนินการอยู่

42c025e2d7d6ca3a.png

12. ล้างข้อมูล (ไม่บังคับ)

หากไม่ต้องการทำแล็บอื่นๆ ในชุดนี้ต่อ คุณสามารถล้างข้อมูลทรัพยากรเพื่อประหยัดค่าใช้จ่ายและเป็นพลเมืองคลาวด์ที่ดีโดยรวม คุณล้างข้อมูลทรัพยากรแต่ละรายการได้โดยทำดังนี้

ลบ Bucket

gsutil rb gs://$BUCKET_THUMBNAILS

ลบบริการ

gcloud run services delete $SERVICE_NAME -q

ลบหัวข้อ Pub/Sub โดยทำดังนี้

gcloud pubsub topics delete $TOPIC_NAME

หรือจะลบทั้งโปรเจ็กต์ก็ได้โดยทำดังนี้

gcloud projects delete $GOOGLE_CLOUD_PROJECT

13. ยินดีด้วย

ตอนนี้ทุกอย่างพร้อมแล้ว

  • สร้างการแจ้งเตือนใน Cloud Storage ที่ส่งข้อความ Pub/Sub ในหัวข้อเมื่อมีการอัปโหลดรูปภาพใหม่
  • กำหนดการเชื่อมโยงและบัญชี IAM ที่จำเป็น (ต่างจาก Cloud Functions ที่เป็นแบบอัตโนมัติทั้งหมด แต่ที่นี่จะกำหนดค่าด้วยตนเอง)
  • สร้างการสมัครใช้บริการเพื่อให้บริการ Cloud Run ของเราได้รับข้อความ Pub/Sub
  • ทุกครั้งที่มีการอัปโหลดรูปภาพใหม่ไปยังที่เก็บข้อมูล ระบบจะปรับขนาดรูปภาพด้วยบริการ Cloud Run ใหม่

สิ่งที่เราได้พูดถึง

  • Cloud Run
  • Cloud Storage
  • Cloud Pub/Sub

ขั้นตอนถัดไป