1. Tổng quan
Phòng thí nghiệm này minh hoạ các tính năng và chức năng được thiết kế để đơn giản hoá quy trình làm việc cho các kỹ sư phần mềm có nhiệm vụ phát triển các ứng dụng NodeJS trong một môi trường được chứa trong vùng chứa. Việc phát triển vùng chứa thông thường đòi hỏi người dùng phải hiểu rõ thông tin chi tiết về vùng chứa và quy trình xây dựng vùng chứa. Ngoài ra, nhà phát triển thường phải ngắt quy trình của mình, chuyển ra khỏi IDE để kiểm thử và gỡ lỗi ứng dụng trong môi trường từ xa. Với các công cụ và công nghệ được đề cập trong hướng dẫn này, nhà phát triển có thể làm việc hiệu quả với các ứng dụng được chứa trong vùng chứa mà không cần rời khỏi IDE.
Kiến thức bạn sẽ học được
Trong phòng thí nghiệm này, bạn sẽ tìm hiểu các phương pháp phát triển bằng vùng chứa trong GCP, bao gồm:
- Tạo một ứng dụng Node.js ban đầu
- Định cấu hình ứng dụng Nodejs để phát triển vùng chứa
- Mã hoá một Dịch vụ REST CRUD đơn giản
- Triển khai vào GKE
- Gỡ lỗi trạng thái lỗi
- Sử dụng điểm ngắt / nhật ký
- Triển khai nóng các thay đổi trở lại GKE
- Không bắt buộc: Tích hợp CloudSQL để duy trì phần phụ trợ
2. Thiết lập và yêu cầu
Thiết lập môi trường theo tốc độ của riêng bạn
- Đăng nhập vào Google Cloud Console rồi tạo một dự án mới hoặc sử dụng lại một dự án hiện có. Nếu chưa có tài khoản Gmail hoặc Google Workspace, bạn phải tạo một tài khoản.



- Tên dự án là tên hiển thị của những người tham gia dự án này. Đây là một chuỗi ký tự mà các API của Google không dùng và bạn có thể cập nhật chuỗi này bất cứ lúc nào.
- Mã dự án phải là duy nhất trên tất cả các dự án trên Google Cloud và không thể thay đổi (bạn không thể thay đổi sau khi đã đặt). Cloud Console sẽ tự động tạo một chuỗi duy nhất; thường thì bạn không cần quan tâm đến chuỗi này. Trong hầu hết các lớp học lập trình, bạn sẽ cần tham chiếu đến Mã dự án (thường được xác định là
PROJECT_ID). Vì vậy, nếu không thích mã này, bạn có thể tạo một mã ngẫu nhiên khác hoặc thử mã của riêng mình để xem mã đó có dùng được hay không. Sau đó, mã này sẽ "đóng băng" sau khi dự án được tạo. - Có một giá trị thứ ba là Số dự án mà một số API sử dụng. Tìm hiểu thêm về cả 3 giá trị này trong tài liệu.
- Tiếp theo, bạn cần bật tính năng thanh toán trong Cloud Console để sử dụng các tài nguyên/API trên Cloud. Việc thực hiện lớp học lập trình này sẽ không tốn nhiều chi phí, nếu có. Để tắt các tài nguyên nhằm tránh bị tính phí ngoài phạm vi hướng dẫn này, hãy làm theo mọi hướng dẫn "dọn dẹp" ở cuối lớp học lập trình. Người dùng mới của Google Cloud đủ điều kiện tham gia chương trình Dùng thử miễn phí trị giá 300 USD.
Khởi động Trình chỉnh sửa Cloud Shell
Bài tập thực hành này được thiết kế và thử nghiệm để sử dụng với Trình chỉnh sửa Google Cloud Shell. Để truy cập vào trình chỉnh sửa,
- truy cập vào dự án của bạn trên Google tại https://console.cloud.google.com.
- Ở góc trên cùng bên phải, hãy nhấp vào biểu tượng trình chỉnh sửa Cloud Shell

- Một ngăn mới sẽ mở ra ở cuối cửa sổ
- Nhấp vào nút Mở trình chỉnh sửa

- Trình chỉnh sửa sẽ mở ra với một trình khám phá ở bên phải và trình chỉnh sửa ở khu vực trung tâm
- Một ngăn cửa sổ dòng lệnh cũng phải có ở cuối màn hình
- Nếu thiết bị đầu cuối CHƯA mở, hãy dùng tổ hợp phím "Ctrl+" để mở một cửa sổ dòng lệnh mới
Thiết lập gcloud
Trong Cloud Shell, hãy đặt mã dự án và khu vực mà bạn muốn triển khai ứng dụng. Lưu các giá trị này dưới dạng biến PROJECT_ID và REGION.
export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')
Thiết lập cụm và cơ sở dữ liệu GKE
- Tải tập lệnh thiết lập xuống và thực thi tập lệnh đó.
wget https://raw.githubusercontent.com/GoogleCloudPlatform/container-developer-workshop/main/labs/nodejs/setup.sh
chmod +x setup.sh
Cung cấp cơ sở hạ tầng được dùng trong phòng thí nghiệm này
Trong phòng thí nghiệm này, bạn sẽ triển khai mã đến GKE và truy cập vào dữ liệu được lưu trữ trong cơ sở dữ liệu Spanner. Tập lệnh thiết lập bên dưới sẽ chuẩn bị cơ sở hạ tầng này cho bạn.
- Mở tệp
setup.shvà chỉnh sửa giá trị của mật khẩu hiện được đặt thành CHANGEME - Chạy tập lệnh thiết lập để thiết lập một cụm GKE và cơ sở dữ liệu CloudSQL mà bạn sẽ sử dụng trong bài tập thực hành này
./setup.sh
- Trong Cloud Shell, hãy tạo một thư mục mới có tên là
mynodejsapp
mkdir mynodejsapp
- Thay đổi thành thư mục này và mở thư mục đó dưới dạng một không gian làm việc. Thao tác này sẽ tải lại trình chỉnh sửa bằng cách tạo một cấu hình không gian làm việc trong thư mục mới tạo.
cd mynodejsapp && cloudshell workspace .
- Cài đặt Node và NPM bằng NVM.
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
# This loads nvm bash_completion
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"
nvm install stable
nvm alias default stable
3. Tạo một ứng dụng khởi động mới
- Khởi chạy ứng dụng
Tạo tệp package.json bằng cách chạy lệnh sau
npm init
Choose the entry point: (index.js) src/index.js and default values for the rest of the parameters. This will create the file with following contents
{
"name": "mynodejsapp",
"version": "1.0.0",
"description": "",
"main": "src/index.js",,
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
- Thêm điểm truy cập
Chỉnh sửa tệp này để thêm lệnh bắt đầu vào tập lệnh "start": "node src/index.js",. Sau khi thay đổi, tập lệnh sẽ có dạng như đoạn mã dưới đây:
"scripts": {
"start": "node src/index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
- Thêm phần phụ thuộc Express
Đoạn mã mà chúng ta sẽ thêm cũng sử dụng express, vì vậy, hãy thêm phần phụ thuộc đó vào tệp package.json này. Sau khi thay đổi, tệp package.json sẽ có dạng như bên dưới.
{
"name": "mynodejsapp",
"version": "1.0.0",
"description": "",
"main": "src/index.js",
"scripts": {
"start": "node src/index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Your Name",
"license": "ISC",
"dependencies": {
"express": "^4.16.4"
}
}
- Tạo tệp index.js
Tạo một thư mục nguồn có tên là src
Tạo src/index.js bằng mã sau
const express = require('express');
const app = express();
const PORT = 8080;
app.get('/', (req, res) => {
var message="Greetings from Node";
res.send({ message: message });
});
app.listen(PORT, () => {
console.log(`Server running at: http://localhost:${PORT}/`);
});
Lưu ý rằng CỔNG được đặt thành giá trị 8080
Tạo tệp kê khai
Skaffold cung cấp các công cụ tích hợp để đơn giản hoá quá trình phát triển vùng chứa. Trong bước này, bạn sẽ khởi động skaffold. Skaffold sẽ tự động tạo các tệp YAML cơ sở của Kubernetes. Thực hiện lệnh bên dưới để bắt đầu quy trình.
Thực thi lệnh sau trong dòng lệnh
skaffold init --generate-manifests
Khi thấy lời nhắc:
- Nhập 8080 cho cổng
- Nhập y để lưu cấu hình
Hai tệp được thêm vào không gian làm việc, cụ thể là skaffold.yaml và deployment.yaml
Cập nhật tên ứng dụng
Các giá trị mặc định có trong cấu hình hiện không khớp với tên ứng dụng của bạn. Cập nhật các tệp để tham chiếu đến tên ứng dụng của bạn thay vì các giá trị mặc định.
- Thay đổi các mục trong cấu hình Skaffold
- Mở
skaffold.yaml - Chọn tên hình ảnh hiện được đặt làm
package-json-image - Nhấp chuột phải rồi chọn Thay đổi tất cả các lần xuất hiện
- Nhập tên mới bằng
mynodejsapp
- Thay đổi các mục trong cấu hình Kubernetes
- Mở tệp
deployment.yaml - Chọn tên hình ảnh hiện được đặt làm
package-json-image - Nhấp chuột phải rồi chọn Thay đổi tất cả các lần xuất hiện
- Nhập tên mới bằng
mynodejsapp
Xin lưu ý rằng trong tệp skaffold.yaml, phần build sử dụng buildpacks để chứa ứng dụng. Mã này không có Dockerfile và nhà phát triển không cần có kiến thức về docker để chứa ứng dụng này.
Ngoài ra, chế độ đồng bộ hoá nhanh sẽ tự động được bật giữa trình chỉnh sửa và vùng chứa đang chạy theo cấu hình skaffold này. Bạn không cần phải thiết lập gì thêm để bật tính năng đồng bộ hoá nhanh.
4. Tìm hiểu quy trình phát triển
Trong phần này, bạn sẽ thực hiện một số bước bằng cách sử dụng trình bổ trợ Cloud Code để tìm hiểu các quy trình cơ bản và xác thực cấu hình cũng như chế độ thiết lập của ứng dụng khởi đầu.
Cloud Code tích hợp với Skaffold để tinh giản quy trình phát triển của bạn. Khi bạn triển khai đến GKE trong các bước sau, Cloud Code và Skaffold sẽ tự động tạo hình ảnh vùng chứa, đẩy hình ảnh đó vào một Container Registry, rồi triển khai ứng dụng của bạn đến GKE. Quá trình này diễn ra ở chế độ nền, giúp loại bỏ các thông tin chi tiết khỏi quy trình của nhà phát triển. Cloud Code cũng giúp nâng cao quy trình phát triển của bạn bằng cách cung cấp các chức năng gỡ lỗi và đồng bộ hoá nóng truyền thống cho quá trình phát triển dựa trên vùng chứa.
Triển khai lên Kubernetes
- Trong ngăn ở cuối Cloud Shell Editor, hãy chọn Cloud Code 

- Trong bảng điều khiển xuất hiện ở trên cùng, hãy chọn Chạy trên Kubernetes. Nếu được nhắc, hãy chọn Có để sử dụng ngữ cảnh Kubernetes hiện tại.

- Lần đầu tiên bạn chạy lệnh, một lời nhắc sẽ xuất hiện ở đầu màn hình để hỏi xem bạn có muốn ngữ cảnh kubernetes hiện tại hay không, hãy chọn "Yes" (Có) để chấp nhận và sử dụng ngữ cảnh hiện tại.

- Tiếp theo, một lời nhắc sẽ xuất hiện để hỏi bạn muốn dùng sổ đăng ký vùng chứa nào. Nhấn Enter để chấp nhận giá trị mặc định được cung cấp

- Chọn thẻ Đầu ra trong ngăn dưới cùng để xem tiến trình và thông báo

- Chọn "Kubernetes: Run/Debug – Detailed" (Kubernetes: Chạy/Gỡ lỗi – Chi tiết) trong trình đơn thả xuống ở bên phải để xem thêm thông tin chi tiết và nhật ký phát trực tiếp từ các vùng chứa

- Quay lại chế độ xem đơn giản bằng cách chọn "Kubernetes: Run/Debug" (Kubernetes: Chạy/Gỡ lỗi) trong trình đơn thả xuống
- Khi quá trình tạo và kiểm thử hoàn tất, thẻ Output (Đầu ra) sẽ có nội dung:
Resource deployment/mynodejsapp status completed successfullyvà một URL được liệt kê: "Forwarded URL from service demo-app: http://localhost:8080" (URL được chuyển tiếp từ ứng dụng minh hoạ dịch vụ: http://localhost:8080) - Trong cửa sổ Cloud Code, hãy di chuột lên URL trong đầu ra (http://localhost:8080), sau đó chọn Open Web Preview (Mở bản xem trước trên web) trong chú thích xuất hiện.
Phản hồi sẽ là:
{"message":"Greetings from Node"}
Tải lại nóng
- Chuyển đến
src/index.js. Chỉnh sửa mã của tin nhắn chào mừng thành'Hello from Node'
Lưu ý rằng ngay lập tức trong cửa sổ Output, chế độ xem Kubernetes: Run/Debug, trình theo dõi sẽ đồng bộ hoá các tệp đã cập nhật với vùng chứa trong Kubernetes
Update initiated File sync started for 1 files for gcr.io/myproject/mynodejsapp:latest@sha256:f554756b3b4d6c301c4b26ef96102227cfa2833270db56241248ae42baa1971a File sync succeeded for 1 files for gcr.io/myproject/mynodejsapp:latest@sha256:f554756b3b4d6c301c4b26ef96102227cfa2833270db56241248ae42baa1971a Update succeeded
- Nếu chuyển sang chế độ xem
Kubernetes: Run/Debug - Detailed, bạn sẽ nhận thấy chế độ xem này nhận ra các thay đổi đối với tệp và khởi động lại nút
files modified: [src/index.js] Copying files:map[src/index.js:[/workspace/src/index.js]]togcr.io/myproject/mynodejsapp:latest@sha256:f554756b3b4d6c301c4b26ef96102227cfa2833270db56241248ae42baa1971a Syncing 1 files for gcr.io/myproject/mynodejsapp:latest@sha256:f554756b3b4d6c301c4b26ef96102227cfa2833270db56241248ae42baa1971a Watching for changes... [mynodejsapp] [mynodejsapp]> mynodejsapp@1.0.0 start /workspace [mynodejsapp]> node src/index.js [mynodejsapp] [mynodejsapp]Server running at: http://localhost:8080/
- Hãy làm mới trình duyệt để xem kết quả mới nhất.
Gỡ lỗi
- Chuyển đến chế độ xem Gỡ lỗi và dừng luồng hiện tại
. - Nhấp vào biểu tượng
Cloud Codetrong trình đơn dưới cùng rồi chọnDebug on Kubernetesđể chạy ứng dụng ở chế độdebug.
- Trong chế độ xem
Kubernetes Run/Debug - Detailedcủa cửa sổOutput, hãy lưu ý rằng skaffold sẽ triển khai ứng dụng này ở chế độ gỡ lỗi. - Ứng dụng sẽ mất vài phút để tạo và triển khai. Lần này, bạn sẽ thấy một trình gỡ lỗi được đính kèm.
Port forwarding pod/mynodejsapp-6bbcf847cd-vqr6v in namespace default, remote port 9229 -> http://127.0.0.1:9229 [mynodejsapp]Debugger attached.
- Thanh trạng thái dưới cùng sẽ thay đổi màu từ xanh dương sang cam, cho biết rằng thanh này đang ở chế độ Gỡ lỗi.
- Trong khung hiển thị
Kubernetes Run/Debug, hãy lưu ý rằng một vùng chứa có thể gỡ lỗi đã được khởi động
**************URLs***************** Forwarded URL from service mynodejsapp-service: http://localhost:8080 Debuggable container started pod/mynodejsapp-deployment-6bc7598798-xl9kj:mynodejsapp (default) Update succeeded ***********************************
Khai thác điểm ngắt
- Mở
src/index.js - Tìm câu lệnh có nội dung
var message="Greetings from Node"; - Thêm một điểm ngắt vào dòng đó bằng cách nhấp vào khoảng trống ở bên trái số dòng. Một chỉ báo màu đỏ sẽ xuất hiện để cho biết điểm ngắt đã được đặt
- Tải lại trình duyệt và lưu ý rằng trình gỡ lỗi sẽ dừng quy trình tại điểm ngắt, đồng thời cho phép bạn kiểm tra các biến và trạng thái của ứng dụng đang chạy từ xa trong GKE
- Nhấp vào phần biến cho đến khi bạn tìm thấy biến
"message". - Thực thi dòng bằng cách nhấn vào Bước qua

- Quan sát giá trị hiện tại của biến
"message"thay đổi thành"Greetings from Node" - Nhấp đúp vào tên biến "target" và trong cửa sổ bật lên, hãy thay đổi giá trị thành một giá trị khác, chẳng hạn như
"Hello from Node" - Nhấp vào nút Tiếp tục trong bảng điều khiển gỡ lỗi
- Xem lại phản hồi trong trình duyệt. Lúc này, trình duyệt sẽ cho thấy giá trị mới cập nhật mà bạn vừa nhập.
- Dừng chế độ "Gỡ lỗi" bằng cách nhấn nút dừng
và xoá điểm ngắt bằng cách nhấp lại vào điểm ngắt.
5. Phát triển một Dịch vụ REST CRUD đơn giản
Đến đây, ứng dụng của bạn đã được định cấu hình đầy đủ cho quá trình phát triển theo mô hình vùng chứa và bạn đã tìm hiểu quy trình phát triển cơ bản bằng Cloud Code. Trong các phần sau, bạn sẽ thực hành những gì đã học bằng cách thêm các điểm cuối dịch vụ còn lại kết nối với một cơ sở dữ liệu được quản lý trong Google Cloud.
Định cấu hình các phần phụ thuộc
Mã xử lý ứng dụng sử dụng cơ sở dữ liệu để duy trì dữ liệu dịch vụ còn lại. Đảm bảo các phần phụ thuộc có sẵn bằng cách thêm nội dung sau vào tệp package.json
- Thêm 2 phần phụ thuộc nữa là
pgvàsequelizevào tệppackage.jsonđể tạo ứng dụng CRUD Postgres. Sau khi đăng thay đổi, phần phụ thuộc sẽ có dạng như sau.
"dependencies": {
"express": "^4.16.4",
"pg": "^8.7.3",
"sequelize": "^6.17.0"
}
Mã hoá dịch vụ REST
- Thêm mã xử lý ứng dụng CRUD vào ứng dụng này
wget -O app.zip https://github.com/GoogleCloudPlatform/container-developer-workshop/raw/main/labs/nodejs/app.zip
unzip app.zip
Mã này có
- thư mục models có mô hình thực thể cho
item - thư mục controllers có mã thực hiện các thao tác CRUD
- thư mục routes định tuyến các mẫu URL cụ thể đến các lệnh gọi khác nhau
- Thư mục config có thông tin chi tiết về khả năng kết nối cơ sở dữ liệu
- Xin lưu ý rằng cấu hình cơ sở dữ liệu trong tệp
db.config.jsđề cập đến các biến môi trường cần được cung cấp để kết nối với cơ sở dữ liệu. Bạn cũng cần phân tích cú pháp yêu cầu đến để mã hoá URL. - Thêm đoạn mã sau vào
src/index.jsđể có thể kết nối với mã CRUD từ tệp javascript chính ngay trước phần cuối cùng bắt đầu bằngapp.listen(PORT, () => {
const bodyParser = require('body-parser')
app.use(bodyParser.json())
app.use(
bodyParser.urlencoded({
extended: true,
})
)
const db = require("../app/models");
db.sequelize.sync();
require("../app/routes/item.routes")(app);
- Chỉnh sửa việc triển khai trong tệp
deployment.yamlđể thêm các biến môi trường nhằm cung cấp thông tin về khả năng kết nối cơ sở dữ liệu.
Cập nhật mục thông số kỹ thuật ở cuối tệp sao cho khớp với định nghĩa sau
spec:
containers:
- name: mynodejsapp
image: mynodejsapp
env:
- name: DB_HOST
value: ${DB_INSTANCE_IP}
- name: DB_PORT
value: "5432"
- name: DB_USER
valueFrom:
secretKeyRef:
name: gke-cloud-sql-secrets
key: username
- name: DB_PASS
valueFrom:
secretKeyRef:
name: gke-cloud-sql-secrets
key: password
- name: DB_NAME
valueFrom:
secretKeyRef:
name: gke-cloud-sql-secrets
key: database
- Thay thế giá trị DB_HOST bằng địa chỉ của Cơ sở dữ liệu
export DB_INSTANCE_IP=$(gcloud sql instances describe mytest-instance \
--format=json | jq \
--raw-output ".ipAddresses[].ipAddress")
envsubst < deployment.yaml > deployment.new && mv deployment.new deployment.yaml
Triển khai và xác thực ứng dụng
- Trong ngăn ở cuối Cloud Shell Editor, hãy chọn
Cloud Coderồi chọnDebug on Kubernetesở đầu màn hình. - Khi quá trình tạo và kiểm thử hoàn tất, thẻ Đầu ra sẽ có nội dung:
Resource deployment/mynodejsapp status completed successfullyvà một URL được liệt kê: "URL được chuyển tiếp từ dịch vụ mynodejsapp: http://localhost:8080" - Thêm một vài mục.
Trong Terminal của Cloud Shell, hãy chạy các lệnh bên dưới
URL=localhost:8080
curl -X POST $URL/items -d '{"itemName":"Body Spray", "itemPrice":3.2}' -H "Content-Type: application/json"
curl -X POST $URL/items -d '{"itemName":"Nail Cutter", "itemPrice":2.5}' -H "Content-Type: application/json"
- Kiểm thử GET bằng cách chạy $URL/items trong trình duyệt. Bạn cũng có thể chạy curl qua dòng lệnh
curl -X GET $URL/items
- Kiểm thử thao tác xoá: Bây giờ, hãy thử xoá một mục bằng cách chạy. Thay đổi giá trị của item-id nếu cần.
curl -X DELETE $URL/items/1
This throws an error message
{"message":"Could not delete Item with id=[object Object]"}
Xác định và khắc phục vấn đề
- Khởi động lại ứng dụng ở chế độ Gỡ lỗi và tìm ra vấn đề. Dưới đây là một số mẹo:
- Chúng tôi biết có vấn đề với thao tác XOÁ vì thao tác này không trả về kết quả mong muốn. Vì vậy, bạn sẽ đặt điểm ngắt trong phương thức
itemcontroller.js->exports.delete. - Chạy quy trình thực thi từng bước và theo dõi các biến ở mỗi bước để quan sát các giá trị của biến cục bộ trong cửa sổ bên trái.
- Để quan sát các giá trị cụ thể như
request.params, hãy thêm biến này vào cửa sổ Watch.
- Xin lưu ý rằng giá trị được chỉ định cho
idlàundefined. Thay đổi mã để khắc phục vấn đề.
Đoạn mã cố định sẽ có dạng như sau.
// Delete a Item with the specified id in the request
exports.delete = (req, res) => {
const id = req.params.id;
- Sau khi ứng dụng khởi động lại, hãy thử xoá lại để kiểm tra.
- Dừng phiên gỡ lỗi bằng cách nhấp vào hình vuông màu đỏ trên thanh công cụ gỡ lỗi

6. Dọn dẹp
Xin chúc mừng! Trong phòng thí nghiệm này, bạn đã tạo một ứng dụng Nodejs mới từ đầu và định cấu hình ứng dụng đó để hoạt động ở chế độ triển khai nóng bằng các vùng chứa. Sau đó, bạn đã triển khai và gỡ lỗi ứng dụng của mình cho một cụm GKE từ xa theo quy trình phát triển tương tự trong các ngăn xếp ứng dụng truyền thống.
Cách dọn dẹp sau khi hoàn thành bài thực hành:
- Xoá các tệp được dùng trong phòng thí nghiệm
cd ~ && rm -rf mynodejsapp && rm -f setup.sh
- Xoá dự án để loại bỏ tất cả cơ sở hạ tầng và tài nguyên liên quan