กำหนดค่าบริการ Cloud Run เพื่อเข้าถึงทั้งบริการ Cloud Run ภายในและอินเทอร์เน็ตสาธารณะ

1. บทนำ

ภาพรวม

องค์กรจำนวนมากใช้เครือข่าย Virtual Private Cloud (VCP) บน Google Cloud ที่มีการควบคุมขอบเขตเพื่อป้องกันการขโมยข้อมูลเพื่อรักษาความปลอดภัยการจราจรของข้อมูลในเครือข่ายสำหรับบริการและแอปพลิเคชัน เครือข่าย VPC คือเครือข่ายจริงเวอร์ชันเสมือนที่ใช้งานภายในเครือข่ายที่ใช้งานจริงของ Google เครือข่าย VPC มอบการเชื่อมต่อสำหรับอินสแตนซ์เครื่องเสมือน (VM) ของ Compute Engine, มอบตัวจัดสรรภาระงานของเครือข่ายแบบส่งผ่านภายในและระบบพร็อกซีสำหรับตัวจัดสรรภาระงานแอปพลิเคชันภายใน เชื่อมต่อกับเครือข่ายภายในองค์กรโดยใช้อุโมงค์ข้อมูล VPN ของ Cloud และไฟล์แนบ VLAN สำหรับ Cloud Interconnect รวมถึงกระจายการรับส่งข้อมูลจากตัวจัดสรรภาระงานภายนอกของ Google Cloud ไปยังแบ็กเอนด์

ซึ่งแตกต่างจาก VM ตรงที่บริการ Cloud Run จะไม่เชื่อมโยงกับเครือข่าย VPC ใดๆ โดยค่าเริ่มต้น Codelab นี้แสดงวิธีเปลี่ยนการตั้งค่าขาเข้า (การเชื่อมต่อขาเข้า) โดยจะมีเพียงการรับส่งข้อมูลที่มาจาก VPC เท่านั้นที่เข้าถึงบริการ Cloud Run ได้ (เช่น บริการแบ็กเอนด์) นอกจากนี้ Codelab นี้จะแสดงวิธีเข้าถึงบริการที่ 2 (เช่น บริการฟรอนท์เอนด์) เข้าถึงทั้งบริการ Cloud Run แบ็กเอนด์ผ่าน VPC และเพื่อให้มีสิทธิ์เข้าถึงอินเทอร์เน็ตสาธารณะต่อไป

ในตัวอย่างนี้ บริการ Cloud Run แบ็กเอนด์จะแสดง Hello World บริการ Cloud Run ฟรอนท์เอนด์มีช่องป้อนข้อมูลใน UI เพื่อรวบรวม URL จากนั้นบริการฟรอนท์เอนด์จะส่งคำขอ GET ไปยัง URL นั้น (เช่น บริการแบ็กเอนด์) จึงทําให้บริการนี้เป็นคำขอบริการ (แทนคำขอเบราว์เซอร์ไปยังบริการ) เมื่อบริการฟรอนท์เอนด์สามารถเข้าถึงแบ็กเอนด์ได้สำเร็จ ข้อความ Hello World จะปรากฏในเบราว์เซอร์ จากนั้น คุณจะโทรหา https://curlmyip.org เพื่อเรียกข้อมูลที่อยู่ IP ของบริการฟรอนท์เอนด์ได้

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

  • วิธีอนุญาตเฉพาะการรับส่งข้อมูลจาก VPC ไปยังบริการ Cloud Run ของคุณ
  • วิธีกำหนดค่าข้อมูลขาออกในบริการ Cloud Run (เช่น ฟรอนท์เอนด์) เพื่อสื่อสารกับบริการ Cloud Run ขาเข้าภายในเท่านั้น (เช่น แบ็กเอนด์) ขณะที่ยังคงรักษาการเข้าถึงอินเทอร์เน็ตสาธารณะสำหรับบริการฟรอนท์เอนด์

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

ข้อกำหนดเบื้องต้น

เปิดใช้งาน Cloud Shell

  1. คลิกเปิดใช้งาน Cloud Shell d1264ca30785e435.png จาก Cloud Console

cb81e7c8e34bc8d.png

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

d95252b003979716.png

การจัดสรรและเชื่อมต่อกับ Cloud Shell ใช้เวลาเพียงไม่กี่นาที

7833d5e1c5d18f54.png

เครื่องเสมือนนี้โหลดด้วยเครื่องมือการพัฒนาทั้งหมดที่จำเป็น โดยมีไดเรกทอรีหลักขนาด 5 GB ถาวรและทำงานใน 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 ได้

PROJECT_ID=<YOUR_PROJECT_ID>
REGION=<YOUR_REGION, e.g. us-central1>
FRONTEND=frontend-with-internet
BACKEND=backend
SUBNET_NAME=default

สร้างบริการ Cloud Run แบ็กเอนด์

ขั้นแรก ให้สร้างไดเรกทอรีสำหรับซอร์สโค้ดและ cd ลงในไดเรกทอรีนั้น

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 ฟรอนท์เอนด์

ไปที่ไดเรกทอรีฟรอนท์เอนด์

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

โทรหาบริการแบ็กเอนด์

ในส่วนนี้ คุณจะต้องยืนยันว่าคุณได้ทำให้บริการ Cloud Run ใช้งานได้ 2 บริการเรียบร้อยแล้ว

เปิด URL ของบริการฟรอนท์เอนด์ในเว็บเบราว์เซอร์ เช่น https://frontend-your-hash-uc.a.run.app/

ในกล่องข้อความ ให้ป้อน URL สำหรับบริการแบ็กเอนด์ โปรดทราบว่าระบบกำหนดเส้นทางคำขอนี้จากอินสแตนซ์ Cloud Run ฟรอนท์เอนด์ไปยังบริการ Cloud Run แบ็กเอนด์ ไม่ใช่จากเบราว์เซอร์ของคุณ

คุณจะเห็นคำว่า "สวัสดีโลก"

4. ตั้งค่าบริการแบ็กเอนด์สำหรับการรับส่งข้อมูลขาเข้าภายในเท่านั้น

คุณเรียกใช้คำสั่ง gcloud ต่อไปนี้เพื่อรวมบริการ Cloud Run เข้ากับเครือข่ายส่วนตัวได้

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

หากคุณลองเรียกใช้บริการแบ็กเอนด์จากบริการฟรอนท์เอนด์ คุณจะได้รับข้อผิดพลาด 404 การเชื่อมต่อขาออกของบริการ Cloud Run ฟรอนท์เอนด์ (หรือขาออก) จะออกไปยังอินเทอร์เน็ตก่อน ดังนั้น Google Cloud จึงจะไม่ทราบต้นทางของคำขอ

5. กำหนดค่าบริการฟรอนท์เอนด์เพื่อเข้าถึง VPC

ในส่วนนี้ คุณจะได้กำหนดค่าบริการ Cloud Run ฟรอนท์เอนด์เพื่อสื่อสารกับบริการแบ็กเอนด์ผ่าน VPC

ในการดำเนินการนี้ คุณจะต้องเพิ่มข้อมูลขาออก VPC โดยตรงไปยังบริการ Cloud Run ฟรอนท์เอนด์เพื่อให้แน่ใจว่าจะเข้าถึงที่อยู่ IP ภายในบนเครือข่าย VPC ได้ จากนั้นจึงกำหนดค่าข้อมูลขาออกให้กำหนดเส้นทางเฉพาะคำขอไปยัง IP ส่วนตัวไปยัง VPC การกำหนดค่านี้จะทำให้ฟรอนท์เอนด์ยังคงเข้าถึงอินเทอร์เน็ตสาธารณะได้ ดูข้อมูลเพิ่มเติมในเอกสารประกอบเกี่ยวกับการได้รับคำขอจากบริการ Cloud Run อื่นๆ

กำหนดค่าข้อมูลขาออก VPC โดยตรง

ก่อนอื่น ให้เรียกใช้คำสั่งนี้เพื่อใช้ข้อมูลขาออก VPC โดยตรงในบริการฟรอนท์เอนด์

gcloud beta run services update $FRONTEND \
--network=$SUBNET_NAME \
--subnet=$SUBNET_NAME  \
--vpc-egress=private-ranges-only \
--region=$REGION

ตอนนี้คุณจะยืนยันว่าบริการฟรอนท์เอนด์มีสิทธิ์เข้าถึง 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 โดยตรงเป็นช่วงส่วนตัวเท่านั้น ซึ่งหมายความว่าการเชื่อมต่อขาออกจากบริการฟรอนท์เอนด์จะส่งไปยังเครือข่าย 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. ยินดีด้วย

ขอแสดงความยินดีที่เรียน Codelab จนจบ

เราขอแนะนำให้อ่านเอกสารเกี่ยวกับ Private Networking on Cloud Run

หัวข้อที่ครอบคลุม

  • วิธีอนุญาตเฉพาะการรับส่งข้อมูลจาก VPC ไปยังบริการ Cloud Run ของคุณ
  • วิธีกำหนดค่าข้อมูลขาออกในบริการ Cloud Run (เช่น ฟรอนท์เอนด์) เพื่อสื่อสารกับบริการ Cloud Run ขาเข้าภายในเท่านั้น (เช่น แบ็กเอนด์) ขณะที่ยังคงรักษาการเข้าถึงอินเทอร์เน็ตสาธารณะสำหรับบริการฟรอนท์เอนด์

8. ล้างข้อมูล

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

หากต้องการลบบริการ Cloud Run ให้ไปที่ Cloud Console ของ Cloud Run ที่ https://console.cloud.google.com/functions/ และลบบริการ $FRONTEND และ $BACKEND ที่คุณสร้างไว้ใน Codelab นี้

หากเลือกลบทั้งโปรเจ็กต์ ให้ไปที่ https://console.cloud.google.com/cloud-resource-manager เลือกโปรเจ็กต์ที่คุณสร้างในขั้นตอนที่ 2 แล้วเลือกลบ หากลบโปรเจ็กต์ คุณจะต้องเปลี่ยนโปรเจ็กต์ใน Cloud SDK คุณสามารถดูรายการโปรเจ็กต์ที่ใช้ได้ทั้งหมดโดยเรียกใช้ gcloud projects list