1. Kiến Trúc Triển Khai Production#
1.1. Nguyên Tắc Thiết Kế#
Môi trường Production áp dụng kiến trúc tách biệt hoàn toàn giữa giai đoạn Build và giai đoạn Deploy:Giai đoạn Build diễn ra trên Bastion Build Server — máy chủ trung gian chuyên dụng. Máy này có Node.js, Docker và quyền truy cập AWS ECR.
Giai đoạn Deploy diễn ra trên Production Server (AWS EC2). Máy này không có Node.js, không có mã nguồn, chỉ kéo Docker image từ ECR và chạy.
Lợi ích của kiến trúc này:Production Server không bao giờ chứa mã nguồn hay Node.js, giảm thiểu bề mặt tấn công.
Docker image được build một lần và deploy nhiều lần, đảm bảo tính nhất quán.
Có thể rollback về bất kỳ phiên bản nào bằng cách chỉ định tag commit cụ thể.
1.2. Luồng Triển Khai Tổng Quan#
Khi developer merge code vào nhánh master:GitLab CI kích hoạt pipeline với hai stage tuần tự: build-master và deploy-master.
Stage build-master kết nối SSH đến Bastion Build Server, pull code mới nhất, build Docker image đa kiến trúc (arm64 + amd64) và push lên AWS ECR.
Stage deploy-master kết nối SSH đến Production Server, kéo image mới từ ECR và khởi động lại container.
2. Giai Đoạn Build (build-master)#
2.1. Cấu Hình Pipeline#
2.2. Xác Thực SSH Đến Bastion Build Server#
BASTION_BUILD_KEY là SSH private key (base64 encoded) được lưu trong GitLab CI/CD Variables Protected. Key này chỉ có quyền truy cập Bastion Build Server.2.3. Đăng Nhập AWS ECR#
AWS ECR token có hiệu lực 12 giờ. Lệnh này lấy token mới và đăng nhập Docker vào ECR registry.2.4. Cập Nhật Mã Nguồn#
2.5. Build Docker Image Đa Kiến Trúc#
Giải thích các tham số quan trọng:--cache-from $TAG_LATEST — Tận dụng layer cache từ image cũ. Các layer không thay đổi (Node.js base, npm install) được tái sử dụng, giảm thời gian build từ 10 phút xuống còn 2-3 phút.
--platform linux/arm64,linux/amd64 — Build cho cả chip ARM (AWS Graviton) và x86_64. Đảm bảo image chạy được trên mọi loại EC2 instance.
-t $TAG_LATEST — Tag latest để deploy nhanh.
-t $TAG_COMMIT — Tag theo commit hash ($CI_COMMIT_SHORT_SHA) để rollback về phiên bản cụ thể.
--target web_server — Chỉ lấy stage web_server từ multi-stage Dockerfile, loại bỏ toàn bộ Node.js build environment. Image cuối chỉ chứa Nginx và file tĩnh, kích thước giảm từ hơn 800MB xuống dưới 20MB.
--push — Push image lên ECR ngay sau khi build xong.
2.6. Dockerfile Production#
3. Giai Đoạn Deploy (deploy-master)#
3.1. Cấu Hình Pipeline#
3.2. Lấy IP Production Server Động#
Kỹ thuật lấy IP qua AWS tag thay vì hardcode IP giúp pipeline hoạt động đúng ngay cả khi EC2 instance bị thay thế hoặc IP thay đổi.3.3. Quy Trình Deploy Trên Production Server#
Giải thích tham số docker-compose up:--force-recreate — Buộc tạo lại container ngay cả khi cấu hình không thay đổi. Đảm bảo container mới luôn sử dụng image mới nhất.
--remove-orphans — Xóa các container không còn được định nghĩa trong docker-compose.yml.
4. Quản Lý Image Trên AWS ECR#
4.1. Cấu Trúc Tag#
| Tag | Ví Dụ | Mô Tả |
|---|
latest | ...amazonaws.com/traffic/admin-prod:latest | Image mới nhất, luôn được cập nhật sau mỗi lần build. |
| Commit hash | ...amazonaws.com/traffic/admin-prod:b5f8r7w2 | Image của một commit cụ thể, dùng để rollback. |
4.2. Xem Danh Sách Image Trên ECR#
5. Quy Trình Rollback Khẩn Cấp#
5.1. Khi Nào Cần Rollback#
Sau khi deploy, người dùng báo cáo lỗi nghiêm trọng: trang trắng, không đăng nhập được, mất dữ liệu hiển thị.
Tính năng mới gây ra hành vi không mong muốn ảnh hưởng đến vận hành.
5.2. Quy Trình Rollback Nhanh#
Bước 1 — Xác định commit hash của phiên bản ổn định:Bước 2 — Đăng nhập SSH vào Production Server:Bước 3 — Cập nhật docker-compose.yml để dùng image cũ:Mở file docker-compose.yml và thay đổi tag image từ latest sang commit hash cụ thể:Bước 4 — Kéo image cũ và khởi động l ại:Bước 5 — Xác nhận rollback thành công:Toàn bộ quy trình rollback có thể hoàn thành trong vòng 2 phút nếu image cũ đã có trong local cache của Production Server.5.3. Rollback Qua GitLab Pipeline#
Cách rollback an toàn hơn là revert commit trên GitLab:Pipeline sẽ tự động build và deploy phiên bản đã revert. Cách này mất nhiều thời gian hơn (5-10 phút) nhưng đảm bảo lịch sử Git sạch và có thể audit.
6. Giám Sát Sau Khi Deploy#
6.1. Kiểm Tra Ngay Sau Deploy#
Truy cập URL Production và đăng nhập thành công.
Kiểm tra trang reportDaily hiển thị dữ liệu đúng.
Kiểm tra trang server-performance hiển thị biểu đồ.
Kiểm tra trang proxy-management tải danh sách proxy.
DevTools → Console → Đảm bảo không có lỗi JavaScript.
DevTools → Network → Đảm bảo không có request nào trả về 4xx hoặc 5xx.
6.2. Theo Dõi Log Container#
6.3. Kiểm Tra Tài Nguyên Server#
7. Bảo Mật Trong Môi Trường Production#
7.1. Quản Lý Secret#
Tất cả thông tin nhạy cảm được lưu trong GitLab CI/CD Variables với chế độ Protected và Masked:SSH private keys được lưu dạng base64 encoded.
AWS credentials được lưu dưới dạng biến riêng biệt.
Không có secret nào được hardcode trong .gitlab-ci.yml hay Dockerfile.
7.2. Nguyên Tắc Least Privilege#
SSH key của Bastion Build Server chỉ có quyền truy cập Bastion, không có quyền truy cập Production Server.
SSH key của Production Deploy chỉ có quyền truy cập Production Server.
AWS IAM role của Bastion Build Server chỉ có quyền push lên ECR repository traffic/admin-prod.
AWS IAM role của Production Server chỉ có quyền pull từ ECR repository traffic/admin-prod.
7.3. Không Lưu Mã Nguồn Trên Production Server#
Production Server chỉ chứa file docker-compose.yml và Docker image từ ECR. Không có Node.js, không có node_modules, không có mã nguồn TypeScript/Vue. Ngay cả khi Production Server bị xâm phạm, kẻ tấn công cũng không thể đọc mã nguồn hay sửa đổi logic ứng dụng.
8. Biến CI/CD Cần Thiết#
8.1. Danh Sách Biến Bắt Buộc#
| Biến | Phạm Vi | Mô Tả |
|---|
BASTION_BUILD_KEY | Protected | SSH private key (base64) để kết nối Bastion Build Server. |
BASTION_BUILD_USER | Protected | Username SSH của Bastion Build Server. |
BASTION_BUILD_IP | Protected | Địa chỉ IP của Bastion Build Server. |
BASTION_BUILD_PORT | Protected | Port SSH của Bastion Build Server. |
AWS_TRAFFIC_PROD_KEY | Protected | SSH private key (base64) để kết nối Production Server. |
AWS_TRAFFIC_PROD_USER | Protected | Username SSH của Production Server. |
AWS_TRAFFIC_PROD_PORT | Protected | Port SSH của Production Server. |
AWS_ACCESS_KEY_ID | Protected, Masked | AWS Access Key ID để đăng nhập ECR. |
AWS_SECRET_ACCESS_KEY | Protected, Masked | AWS Secret Access Key để đăng nh ập ECR. |
AWS_DEFAULT_REGION | Protected | AWS Region: ap-southeast-1. |
8.2. Cách Thêm Biến Mới#
Vào GitLab project → Settings → CI/CD → Variables.
Nhấn "Add variable", đặt Key và Value.
Chọn "Protected" để biến chỉ khả dụng trên nhánh protected.
Chọn "Masked" để giá trị không hiển thị trong log pipeline.
9. Xử Lý Sự Cố Triển Khai Production#
9.1. Pipeline Build Thất Bại#
Lỗi: Permission denied (publickey) khi kết nối Bastion:Kiểm tra biến BASTION_BUILD_KEY có được cấu hình đúng không.
Kiểm tra public key tương ứng có trong ~/.ssh/authorized_keys trên Bastion không.
Lỗi: no space left on device khi build Docker:Lỗi: npm install thất bại trong Docker build:9.2. Pipeline Deploy Thất Bại#
Lỗi: Không lấy được IP Production Server:Kiểm tra AWS credentials (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY) có đúng không.
Kiểm tra EC2 instance có đang chạy và có tag đúng không.
Kiểm tra IAM role có quyền ec2:DescribeInstances không.
Lỗi: docker pull thất bại:Kiểm tra Production Server có quyền pull từ ECR không.
Kiểm tra image tag có tồn tại trên ECR không.
9.3. Ứng Dụng Không Phản Hồi Sau Deploy#
10. Quy Trình Phát Hành Phiên Bản Mới#
10.1. Checklist Trước Khi Merge Vào Master#
Trước khi merge code vào nhánh master để deploy Production, đảm bảo:Tất cả test case trên Staging đã pass.
UAT (User Acceptance Testing) đã được thực hiện và approved.
Không có lỗi TypeScript: npm run typecheck pass.
Không có lỗi lint: npm run lint pass.
CHANGELOG.md đã được cập nhật với các thay đổi mới.
Tech Lead đã review và approve Merge Request.
Thời điểm deploy không trùng với giờ cao điểm sử dụng hệ thống.
10.2. Quy Trình Deploy Có Kiểm Soát#
Để giảm thiểu rủi ro khi deploy Production:Thông báo cho team trước khi deploy ít nhất 30 phút.
Deploy vào thời điểm ít người dùng nhất (thường là buổi tối hoặc cuối tuần).
Chuẩn bị sẵn quy trình rollback trước khi bắt đầu deploy.
Theo dõi log và metrics trong 30 phút sau khi deploy.
Xác nhận với người dùng rằng hệ thống hoạt động bình thường.
10.3. Versioning#
Sau mỗi lần deploy Production thành công, cập nhật phiên bản trong package.json:Lệnh npm version tự động cập nhật package.json, tạo git tag và commit.
11. Tối Ưu Hóa Hiệu Suất Production#
11.1. Phân Tích Bundle Size#
Sau mỗi lần thêm dependency mới, kiểm tra kích thước bundle:Nếu bundle quá lớn, sử dụng rollup-plugin-visualizer để phân tích:11.2. Lazy Loading Routes#
Tất cả route components đã được cấu hình lazy loading bằng dynamic import:Điều này đảm bảo chỉ tải code của màn hình khi người dùng thực sự truy cập, giảm thời gian tải trang ban đầu.11.3. Tối Ưu Hình Ảnh#
Hình ảnh trong thư mục public/ không qua build pipeline. Để tối ưu:Sử dụng định dạng WebP thay vì PNG/JPEG khi có thể.
Nén hình ảnh trước khi commit vào repository.
Sử dụng SVG cho icon và logo thay vì PNG.
12. Disaster Recovery#
12.1. Kịch Bản Sự Cố Và Phương Án Xử Lý#
Kịch bản 1: Production Server bị down hoàn toàn.Phương án: Khởi động EC2 instance mới từ AMI snapshot.
Thời gian phục hồi ước tính: 15-30 phút.
Bước thực hiện: Tạo EC2 instance mới, cài Docker, kéo image từ ECR, chạy docker-compose.
Kịch bản 2: AWS ECR không khả dụng.Phương án: Sử dụng image đã có trong local cache của Production Server.
Thời gian phục hồi: Ngay lập tức nếu image cũ vẫn còn trong cache.
Bước thực hiện: docker-compose up -d với image đã có trong local.
Kịch bản 3: Deploy mới gây lỗi nghiêm trọng.Phương án: Rollback về phiên bản trước theo quy trình ở mục 5.
Thời gian phục hồi: 2-5 phút.
Kịch bản 4: Database Backend bị lỗi (không liên quan đến Frontend).Phương án: Admin Dashboard vẫn load được nhưng hiển thị lỗi API.
Hành động: Hiển thị thông báo bảo trì cho người dùng, liên hệ team Backend.
12.2. Backup Và Restore#
Admin Dashboard là ứng dụng stateless — không lưu trữ dữ liệu nghiệp vụ. Dữ liệu duy nhất cần backup là:Docker image trên AWS ECR (tự động được giữ lại theo lifecycle policy).
File docker-compose.yml trên Production Server (được lưu trong Git repository).
Biến CI/CD trong GitLab (cần export thủ công định kỳ).
12.3. Kế Hoạch Dự Phòng#
Nếu GitLab CI/CD không khả dụng, có thể deploy thủ công theo quy trình:Kết nối SSH đến Bastion Build Server.
Pull code mới nhất từ repository.
Build Docker image thủ công.
Kết nối SSH đến Production Server.
Pull image và restart container.
13. Tài Liệu Tham Khảo Kỹ Thuật#
13.1. AWS Services Được Sử Dụng#
| Service | Mục Đích | Region |
|---|
| AWS ECR | Lưu trữ Docker image | ap-southeast-1 (Singapore) |
| AWS EC2 | Chạy Production Server | ap-southeast-1 (Singapore) |
| AWS IAM | Quản lý quyền truy cập | Global |
13.2. Thông Tin ECR Repository#
Repository name: traffic/admin-prod
Full URI: 211125536219.dkr.ecr.ap-southeast-1.amazonaws.com/traffic/admin-prod
13.3. Tag EC2 Instance Production#
EC2 instance Production được xác định bằng các tag:Name: traffic-social-search-api-tool-prod
Service_Traffic: traffic-api
Các tag này được sử dụng trong pipeline để tự động lấy IP của server mà không cần hardcode.13.4. Liên Hệ Khẩn Cấp#
Khi xảy ra sự cố Production nghiêm trọng ngoài giờ làm việc:Liên hệ Tech Lead qua số điện thoại khẩn cấp.
Gửi thông báo vào kênh Slack #incident-production.
Tạo incident report trên GitLab với label severity::critical.
Thực hiện rollback ngay lập tức nếu có thể, không chờ phân tích nguyên nhân.
Modified at 2026-03-26 10:10:22