1. Giới thiệu
Tổng quan
Để bảo mật lưu lượng truy cập mạng cho các dịch vụ và ứng dụng của mình, nhiều tổ chức sử dụng mạng Đám mây riêng ảo (VCP) trên Google Cloud với các biện pháp kiểm soát ranh giới để ngăn chặn việc đánh cắp dữ liệu. Mạng VPC là phiên bản ảo của một mạng vật lý được triển khai bên trong mạng sản xuất của Google. Mạng VPC cung cấp khả năng kết nối cho các phiên bản máy ảo (VM) Compute Engine, cung cấp Bộ cân bằng tải mạng truyền qua nội bộ gốc và hệ thống proxy cho Bộ cân bằng tải ứng dụng nội bộ, kết nối với các mạng tại chỗ bằng cách sử dụng đường hầm Cloud VPN và tệp đính kèm VLAN cho Cloud Interconnect, đồng thời phân phối lưu lượng truy cập từ bộ cân bằng tải bên ngoài của Google Cloud đến các phần phụ trợ.
Không giống như máy ảo, các dịch vụ Cloud Run không được liên kết với bất kỳ mạng VPC cụ thể nào theo mặc định. Lớp học lập trình này minh hoạ cách thay đổi chế độ cài đặt lưu lượng truy cập đến (kết nối đến) để chỉ lưu lượng truy cập đến từ một VPC mới có thể truy cập vào một dịch vụ Cloud Run (ví dụ: dịch vụ phụ trợ). Ngoài ra, lớp học lập trình này còn hướng dẫn bạn cách để một dịch vụ thứ hai (ví dụ: dịch vụ giao diện người dùng) truy cập vào cả dịch vụ Cloud Run phụ trợ thông qua một VPC và tiếp tục có quyền truy cập vào Internet công cộng.
Trong ví dụ này, dịch vụ Cloud Run phụ trợ trả về thông báo "hello world". Dịch vụ Cloud Run giao diện người dùng cung cấp một trường nhập dữ liệu trong giao diện người dùng để thu thập URL. Sau đó, dịch vụ giao diện người dùng sẽ đưa ra yêu cầu GET đến URL đó (ví dụ: dịch vụ phụ trợ), do đó, đây là yêu cầu từ dịch vụ đến dịch vụ (thay vì yêu cầu từ trình duyệt đến dịch vụ). Khi dịch vụ giao diện người dùng có thể tiếp cận thành công phần phụ trợ, thông báo "hello world" sẽ xuất hiện trong trình duyệt. Sau đó, bạn sẽ thấy cách thực hiện lệnh gọi đến https://curlmyip.org để truy xuất địa chỉ IP của dịch vụ giao diện người dùng.
Kiến thức bạn sẽ học được
- Cách chỉ cho phép lưu lượng truy cập từ một VPC đến dịch vụ Cloud Run
- Cách định cấu hình lưu lượng truy cập ra trên một dịch vụ Cloud Run (ví dụ: giao diện người dùng) để giao tiếp với một dịch vụ Cloud Run chỉ có lưu lượng truy cập đến nội bộ (ví dụ: phần phụ trợ), đồng thời duy trì quyền truy cập Internet công cộng cho dịch vụ giao diện người dùng.
2. Thiết lập và yêu cầu
Điều kiện tiên quyết
- Bạn đã đăng nhập vào Cloud Console.
- Bạn đã triển khai một hàm thế hệ thứ 2 trước đó. Ví dụ: bạn có thể làm theo hướng dẫn bắt đầu nhanh về cách triển khai Cloud Function thế hệ thứ 2 để bắt đầu.
Kích hoạt Cloud Shell
- Trong Cloud Console, hãy nhấp vào Kích hoạt Cloud Shell
.

Nếu đây là lần đầu tiên bạn khởi động Cloud Shell, bạn sẽ thấy một màn hình trung gian mô tả về Cloud Shell. Nếu bạn thấy màn hình trung gian, hãy nhấp vào Tiếp tục.

Quá trình cung cấp và kết nối với Cloud Shell chỉ mất vài phút.

Máy ảo này được tải tất cả các công cụ phát triển cần thiết. Máy ảo này cung cấp một thư mục chính liên tục có dung lượng 5 GB và chạy trong Google Cloud, giúp tăng cường đáng kể hiệu suất mạng và khả năng xác thực. Bạn có thể thực hiện hầu hết, nếu không phải là tất cả, công việc trong lớp học lập trình này bằng trình duyệt.
Sau khi kết nối với Cloud Shell, bạn sẽ thấy rằng mình đã được xác thực và dự án được đặt thành mã dự án.
- Chạy lệnh sau trong Cloud Shell để xác nhận rằng bạn đã được xác thực:
gcloud auth list
Kết quả đầu ra của lệnh
Credentialed Accounts
ACTIVE ACCOUNT
* <my_account>@<my_domain.com>
To set the active account, run:
$ gcloud config set account `ACCOUNT`
- Chạy lệnh sau trong Cloud Shell để xác nhận rằng lệnh gcloud biết về dự án của bạn:
gcloud config list project
Kết quả đầu ra của lệnh
[core] project = <PROJECT_ID>
Nếu không, bạn có thể đặt dự án bằng lệnh sau:
gcloud config set project <PROJECT_ID>
Kết quả đầu ra của lệnh
Updated property [core/project].
3. Tạo các dịch vụ Cloud Run
Thiết lập các biến môi trường
Bạn có thể thiết lập các biến môi trường sẽ được sử dụng trong suốt lớp học lập trình này.
PROJECT_ID=<YOUR_PROJECT_ID> REGION=<YOUR_REGION, e.g. us-central1> FRONTEND=frontend-with-internet BACKEND=backend SUBNET_NAME=default
Tạo dịch vụ Cloud Run phụ trợ
Trước tiên, hãy tạo một thư mục cho mã nguồn và chuyển đến thư mục đó.
mkdir -p egress-private-codelab/frontend-w-internet egress-private-codelab/backend && cd egress-private-codelab/backend
Sau đó, hãy tạo tệp `package.json`` có nội dung sau:
{
"name": "backend-service",
"version": "1.0.0",
"description": "",
"scripts": {
"start": "node index.js"
},
"dependencies": {
"express": "^4.18.1"
}
}
Tiếp theo, hãy tạo tệp nguồn index.js có nội dung bên dưới. Tệp này chứa điểm truy cập cho dịch vụ và chứa logic chính cho ứng dụng.
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}`);
});
Cuối cùng, hãy triển khai dịch vụ Cloud Run bằng cách chạy lệnh sau.
gcloud run deploy $BACKEND --source . --allow-unauthenticated --region $REGION
Tạo dịch vụ Cloud Run giao diện người dùng
Chuyển đến thư mục giao diện người dùng
cd ../frontend-w-internet
Sau đó, hãy tạo tệp package.json có nội dung sau:
{
"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"
}
}
Tiếp theo, hãy tạo tệp nguồn index.js có nội dung bên dưới. Tệp này chứa điểm truy cập cho dịch vụ và chứa logic chính cho ứng dụng.
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}`);
});
Tạo một thư mục công khai cho tệp index.html
mkdir public touch public/index.html
Và cập nhật index.html để chứa nội dung sau:
<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>
Cuối cùng, hãy triển khai dịch vụ Cloud Run bằng cách chạy lệnh sau.
gcloud run deploy $FRONTEND --source . --allow-unauthenticated --region $REGION
Gọi dịch vụ phụ trợ
Trong phần này, bạn sẽ xác minh rằng bạn đã triển khai thành công hai dịch vụ Cloud Run.
Mở URL của dịch vụ giao diện người dùng trong trình duyệt web, ví dụ: https://frontend-your-hash-uc.a.run.app/
Trong hộp văn bản, hãy nhập URL cho dịch vụ phụ trợ. Xin lưu ý rằng yêu cầu này được định tuyến từ thực thể Cloud Run giao diện người dùng đến dịch vụ Cloud Run phụ trợ, chứ không phải từ trình duyệt của bạn.
Bạn sẽ thấy thông báo "hello world"
4. Đặt dịch vụ phụ trợ chỉ cho lưu lượng truy cập đến nội bộ
Bạn có thể chạy lệnh gcloud sau để kết hợp một dịch vụ Cloud Run vào mạng riêng của mình.
gcloud run services update $BACKEND --ingress internal --region $REGION
Nếu cố gắng gọi dịch vụ phụ trợ từ dịch vụ giao diện người dùng, bạn sẽ nhận được lỗi 404. Kết nối đi (hoặc lưu lượng truy cập ra) của dịch vụ Cloud Run giao diện người dùng sẽ đi ra Internet trước, vì vậy, Google Cloud không biết nguồn gốc của yêu cầu.
5. Định cấu hình dịch vụ giao diện người dùng để truy cập vào VPC
Trong phần này, bạn sẽ định cấu hình dịch vụ Cloud Run giao diện người dùng để giao tiếp với dịch vụ phụ trợ thông qua một VPC.
Để thực hiện việc này, bạn cần thêm lưu lượng truy cập ra trực tiếp của VPC vào dịch vụ Cloud Run giao diện người dùng để đảm bảo dịch vụ này có thể tiếp cận các địa chỉ IP nội bộ trên mạng VPC. Sau đó, bạn sẽ định cấu hình lưu lượng truy cập ra để chỉ các yêu cầu đến IP riêng tư mới được định tuyến đến VPC. Cấu hình này sẽ cho phép giao diện người dùng vẫn tiếp cận được Internet công cộng. Bạn có thể tìm hiểu thêm trong tài liệu về cách nhận yêu cầu từ các dịch vụ Cloud Run khác.
Định cấu hình lưu lượng truy cập ra trực tiếp của VPC
Trước tiên, hãy chạy lệnh này để sử dụng lưu lượng truy cập ra trực tiếp của VPC trên dịch vụ giao diện người dùng:
gcloud beta run services update $FRONTEND \ --network=$SUBNET_NAME \ --subnet=$SUBNET_NAME \ --vpc-egress=private-ranges-only \ --region=$REGION
Giờ đây, bạn có thể xác nhận rằng dịch vụ giao diện người dùng có quyền truy cập vào VPC:
gcloud beta run services describe $FRONTEND \ --region=$REGION
Bạn sẽ thấy kết quả đầu ra tương tự như
VPC access:
Network: default
Subnet: default
Egress: private-ranges-only
Bật tính năng Truy cập riêng tư vào Google
Tiếp theo, bạn sẽ bật tính năng Truy cập riêng tư vào Google trên mạng con bằng cách chạy lệnh sau:
gcloud compute networks subnets update $SUBNET_NAME \ --region=$REGION \ --enable-private-ip-google-access
Bạn có thể xác minh rằng tính năng Truy cập riêng tư vào Google đã được bật bằng cách chạy lệnh sau:
gcloud compute networks subnets describe $SUBNET_NAME \ --region=$REGION \ --format="get(privateIpGoogleAccess)"
Tạo vùng DNS Cloud cho URL run.app
Cuối cùng, hãy tạo một vùng Cloud DNS cho các URL run.app để Google Cloud có thể coi các URL này là địa chỉ IP nội bộ.
Trong bước trước, khi bạn định cấu hình lưu lượng truy cập ra trực tiếp của VPC chỉ cho các dải IP riêng tư. Điều này có nghĩa là các kết nối đi từ dịch vụ giao diện người dùng sẽ chỉ đi đến mạng VPC nếu đích đến là một IP nội bộ. Tuy nhiên, dịch vụ phụ trợ của bạn sử dụng một URL run.app phân giải thành một IP công khai.
Trong bước này, bạn sẽ tạo một vùng Cloud DNS cho các URL run.app để phân giải thành các dải địa chỉ IP private.googleapis.com, được nhận dạng là địa chỉ IP nội bộ. Giờ đây, mọi yêu cầu đến các dải IP này sẽ được định tuyến thông qua mạng VPC của bạn.
Bạn có thể thực hiện việc này bằng cách: 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"
Giờ đây, khi cố gắng tiếp cận dịch vụ phụ trợ cho trang web của mình, bạn sẽ thấy thông báo "hello world" được trả về.
Và khi cố gắng tiếp cận Internet bằng https://curlmyip.org/, bạn sẽ thấy địa chỉ IP của mình.
6. Khắc phục sự cố
Dưới đây là một số thông báo lỗi có thể gặp phải nếu bạn không định cấu hình chế độ cài đặt đúng cách.
- Nếu bạn gặp lỗi
getaddrinfo ENOTFOUND backend-your-hash-uc.a.run.app, hãy đảm bảo rằng bạn không thêm "https://" vào bản ghi DNS A - Nếu nhận được lỗi 404 khi cố gắng truy cập vào phần phụ trợ sau khi định cấu hình vùng, bạn có thể đợi bộ nhớ đệm trên bản ghi run.app toàn cầu hết hạn (ví dụ: 6 giờ) hoặc tạo một bản sửa đổi mới (do đó, xoá bộ nhớ đệm) bằng cách chạy lệnh sau:
gcloud beta run services update $FRONTEND --network=$SUBNET_NAME --subnet=$SUBNET_NAME --vpc-egress=private-ranges-only --region=$REGION
7. Xin chúc mừng!
Xin chúc mừng bạn đã hoàn tất lớp học lập trình này!
Bạn nên xem lại tài liệu về Mạng riêng tư trên Cloud Run.
Nội dung chúng tôi đã đề cập
- Cách chỉ cho phép lưu lượng truy cập từ một VPC đến dịch vụ Cloud Run
- Cách định cấu hình lưu lượng truy cập ra trên một dịch vụ Cloud Run (ví dụ: giao diện người dùng) để giao tiếp với một dịch vụ Cloud Run chỉ có lưu lượng truy cập đến nội bộ (ví dụ: phần phụ trợ), đồng thời duy trì quyền truy cập Internet công cộng cho dịch vụ giao diện người dùng.
8. Dọn dẹp
Để tránh bị tính phí ngoài ý muốn (ví dụ: nếu dịch vụ Cloud Run này vô tình được gọi nhiều lần hơn hạn mức gọi Cloud Run hằng tháng trong gói miễn phí), bạn có thể xoá dịch vụ Cloud Run hoặc xoá dự án mà bạn đã tạo ở Bước 2.
Để xoá các dịch vụ Cloud Run, hãy chuyển đến Cloud Run Cloud Console tại https://console.cloud.google.com/functions/ rồi xoá các dịch vụ $FRONTEND và $BACKEND mà bạn đã tạo trong lớp học lập trình này.
Nếu chọn xoá toàn bộ dự án, bạn có thể chuyển đến https://console.cloud.google.com/cloud-resource-manager, chọn dự án mà bạn đã tạo ở Bước 2 rồi chọn Xoá. Nếu xoá dự án, bạn cần thay đổi dự án trong Cloud SDK. Bạn có thể xem danh sách tất cả các dự án hiện có bằng cách chạy gcloud projects list.