DevSecOps (Phần 9): Build – Release – Run: Vì sao không bao giờ được sửa trực tiếp ứng dụng đang chạy?
Đã bao giờ bạn nghe câu nói này chưa?
Cách xử lý này có thể giải quyết sự cố trước mắt, nhưng trong DevSecOps và 12-Factor App, đây là một điều không bao giờ nên làm.
Lý do rất đơn giản:
Mọi thay đổi đều phải đi qua quy trình Build → Release → Run, chứ không được chỉnh sửa trực tiếp trên môi trường Production.
Ba giai đoạn của vòng đời ứng dụng
Yếu tố thứ 5 trong 12-Factor App yêu cầu tách biệt hoàn toàn ba giai đoạn:
Mỗi giai đoạn có nhiệm vụ riêng và không được chồng chéo lên nhau.
Điều này giúp hệ thống dễ kiểm soát, dễ kiểm toán và có thể triển khai tự động thông qua CI/CD Pipeline.
Giai đoạn 1: Build
Build là nơi source code được chuyển thành một sản phẩm có thể thực thi.
Trong giai đoạn này, hệ thống sẽ:
Điểm quan trọng là sau khi Build hoàn thành, artifact không còn phụ thuộc vào máy của developer. Cùng một artifact có thể được sử dụng để triển khai ở nhiều môi trường khác nhau, miễn là cấu hình phù hợp.
Giai đoạn 2: Release
Sau khi Build thành công, hệ thống bước sang Release.
Release không tạo lại ứng dụng.
Thay vào đó, Release sẽ:
Release ID có thể là:
Ví dụ:
v1.0.0
v1.0.1
v1.1.0
v2.0.0
Mỗi Release phải có một định danh riêng để có thể theo dõi lịch sử triển khai và phục vụ việc kiểm toán.
Release phải bất biến
Đây là nguyên tắc rất quan trọng.
Sau khi Release được tạo:
Không được sửa.
Nếu phát hiện lỗi:
❌ Không SSH vào Production sửa code.
❌ Không copy đè file.
❌ Không sửa trực tiếp Docker Container.
Thay vào đó phải:
Sửa Source Code
│
▼
Build mới
│
▼
Release mới
│
▼
Deploy mới
Nếu cần thay đổi, quy trình Build → Release → Run phải được thực hiện lại từ đầu để tạo ra một phiên bản Release mới, thay vì chỉnh sửa phiên bản cũ.
Rollback trở nên cực kỳ đơn giản
Giả sử Release mới gặp lỗi.
Nếu mỗi Release đều có Version riêng:
v1.0.0
v1.0.1
v1.1.0
v1.2.0 ❌
Doanh nghiệp chỉ cần:
Rollback
│
▼
v1.1.0
Không cần Build lại.
Không cần sửa mã nguồn.
Không cần cấu hình lại.
Đó là lý do Release luôn phải được đánh phiên bản (Versioning) và không thay đổi sau khi phát hành.
Giai đoạn 3: Run
Đây là lúc ứng dụng chính thức phục vụ người dùng.
Điểm thú vị là:
Developer gần như không còn tham gia.
Môi trường vận hành sẽ chịu trách nhiệm:
Trong môi trường Cloud Native, các nền tảng như Kubernetes sẽ tự động thực hiện phần lớn các công việc này, giúp ứng dụng vận hành ổn định mà không cần can thiệp thủ công.
Vì sao phải tách Build – Release – Run?
Nếu ba giai đoạn bị trộn lẫn, doanh nghiệp sẽ gặp nhiều vấn đề:
Ngược lại, khi tách biệt rõ ràng:
Mỗi bước có trách nhiệm riêng và có thể tự động hóa hoàn toàn.
Build Once, Release Many
Một trong những lợi ích lớn nhất của mô hình này là:
Bạn chỉ Build một lần.
Sau đó sử dụng chính artifact đó để triển khai lên:
Điều thay đổi duy nhất là Configuration, không phải mã nguồn hay artifact.
Đây là nguyên tắc Build Once, Release Many, giúp bảo đảm mọi môi trường đều chạy cùng một phiên bản ứng dụng, giảm sai lệch giữa Development và Production, đồng thời đơn giản hóa việc triển khai và rollback.
Build – Release – Run không chỉ là một khuyến nghị trong 12-Factor App, mà còn là nền tảng của mọi quy trình DevSecOps hiện đại. Khi mỗi thay đổi đều phải đi qua Build, tạo Release mới và triển khai lại, doanh nghiệp sẽ có được một hệ thống dễ kiểm soát, dễ kiểm toán, dễ rollback và đủ tin cậy để tự động hóa toàn bộ CI/CD Pipeline.
Đã bao giờ bạn nghe câu nói này chưa?
"Server Production bị lỗi, SSH vào sửa nhanh một dòng code là xong!"
Cách xử lý này có thể giải quyết sự cố trước mắt, nhưng trong DevSecOps và 12-Factor App, đây là một điều không bao giờ nên làm.
Lý do rất đơn giản:
Ứng dụng đang chạy phải là bất biến (Immutable).
Mọi thay đổi đều phải đi qua quy trình Build → Release → Run, chứ không được chỉnh sửa trực tiếp trên môi trường Production.
Ba giai đoạn của vòng đời ứng dụng
Yếu tố thứ 5 trong 12-Factor App yêu cầu tách biệt hoàn toàn ba giai đoạn:
- Build
- Release
- Run
Mỗi giai đoạn có nhiệm vụ riêng và không được chồng chéo lên nhau.
Điều này giúp hệ thống dễ kiểm soát, dễ kiểm toán và có thể triển khai tự động thông qua CI/CD Pipeline.
Giai đoạn 1: Build
Build là nơi source code được chuyển thành một sản phẩm có thể thực thi.
Trong giai đoạn này, hệ thống sẽ:
- Lấy source code từ repository.
- Cài đặt các dependency cần thiết.
- Build ứng dụng hoặc Docker Image.
- Chạy các kiểm tra tự động trong CI Pipeline.
- Tạo ra một Build Artifact bất biến.
Điểm quan trọng là sau khi Build hoàn thành, artifact không còn phụ thuộc vào máy của developer. Cùng một artifact có thể được sử dụng để triển khai ở nhiều môi trường khác nhau, miễn là cấu hình phù hợp.
Giai đoạn 2: Release
Sau khi Build thành công, hệ thống bước sang Release.
Release không tạo lại ứng dụng.
Thay vào đó, Release sẽ:
- Kết hợp Build Artifact với Configuration của từng môi trường.
- Gán một Release ID duy nhất.
Release ID có thể là:
- Số phiên bản (v1.2.0)
- Build Number
- Timestamp
- Semantic Versioning (Major.Minor.Patch)
Ví dụ:
v1.0.0
v1.0.1
v1.1.0
v2.0.0
Mỗi Release phải có một định danh riêng để có thể theo dõi lịch sử triển khai và phục vụ việc kiểm toán.
Release phải bất biến
Đây là nguyên tắc rất quan trọng.
Sau khi Release được tạo:
Không được sửa.
Nếu phát hiện lỗi:
❌ Không SSH vào Production sửa code.
❌ Không copy đè file.
❌ Không sửa trực tiếp Docker Container.
Thay vào đó phải:
Sửa Source Code
│
▼
Build mới
│
▼
Release mới
│
▼
Deploy mới
Nếu cần thay đổi, quy trình Build → Release → Run phải được thực hiện lại từ đầu để tạo ra một phiên bản Release mới, thay vì chỉnh sửa phiên bản cũ.
Rollback trở nên cực kỳ đơn giản
Giả sử Release mới gặp lỗi.
Nếu mỗi Release đều có Version riêng:
v1.0.0
v1.0.1
v1.1.0
v1.2.0 ❌
Doanh nghiệp chỉ cần:
Rollback
│
▼
v1.1.0
Không cần Build lại.
Không cần sửa mã nguồn.
Không cần cấu hình lại.
Đó là lý do Release luôn phải được đánh phiên bản (Versioning) và không thay đổi sau khi phát hành.
Giai đoạn 3: Run
Đây là lúc ứng dụng chính thức phục vụ người dùng.
Điểm thú vị là:
Developer gần như không còn tham gia.
Môi trường vận hành sẽ chịu trách nhiệm:
- Khởi động ứng dụng.
- Giám sát trạng thái hoạt động.
- Thu thập log.
- Tự động mở rộng hoặc thu hẹp tài nguyên theo tải.
- Đảm bảo tính sẵn sàng của dịch vụ.
Trong môi trường Cloud Native, các nền tảng như Kubernetes sẽ tự động thực hiện phần lớn các công việc này, giúp ứng dụng vận hành ổn định mà không cần can thiệp thủ công.
Vì sao phải tách Build – Release – Run?
Nếu ba giai đoạn bị trộn lẫn, doanh nghiệp sẽ gặp nhiều vấn đề:
- Không biết phiên bản nào đang chạy.
- Khó truy vết nguyên nhân khi xảy ra sự cố.
- Không thể rollback nhanh.
- Mỗi môi trường có thể chạy một phiên bản khác nhau.
- Khó tự động hóa quy trình triển khai.
Ngược lại, khi tách biệt rõ ràng:
- Build chỉ tạo artifact.
- Release chỉ kết hợp artifact với configuration.
- Run chỉ tập trung vận hành ứng dụng.
Mỗi bước có trách nhiệm riêng và có thể tự động hóa hoàn toàn.
Build Once, Release Many
Một trong những lợi ích lớn nhất của mô hình này là:
Bạn chỉ Build một lần.
Sau đó sử dụng chính artifact đó để triển khai lên:
- Development
- Testing
- Staging
- Production
Điều thay đổi duy nhất là Configuration, không phải mã nguồn hay artifact.
Đây là nguyên tắc Build Once, Release Many, giúp bảo đảm mọi môi trường đều chạy cùng một phiên bản ứng dụng, giảm sai lệch giữa Development và Production, đồng thời đơn giản hóa việc triển khai và rollback.
Build – Release – Run không chỉ là một khuyến nghị trong 12-Factor App, mà còn là nền tảng của mọi quy trình DevSecOps hiện đại. Khi mỗi thay đổi đều phải đi qua Build, tạo Release mới và triển khai lại, doanh nghiệp sẽ có được một hệ thống dễ kiểm soát, dễ kiểm toán, dễ rollback và đủ tin cậy để tự động hóa toàn bộ CI/CD Pipeline.