CI/CD overview - Phần 2/2 - Từ pipeline MQTT broker đến release process hoàn chỉnh
Bài 2/6 trong series CI/CD và Kubernetes. Tiếp nối CI/CD overview - Phần 1/2 - nếu chưa đọc phần khái niệm nền tảng (CI/CD/CD, pipeline, stage, job, runner, artifact), nên đọc trước nhé!
Mục tiêu
Phần này tập trung tìm hiểu các nội dung sau:
- đọc được luồng release cơ bản trong GitLab CI qua pipeline MQTT broker thật;
- hiểu vì sao image bất biến, quyền tối thiểu và rollback là các phần của release process chứ không phải việc làm thêm sau cùng;
- nhận biết các chiến lược rolling, blue-green, canary và feature flag;
- đo lường hiệu quả CI/CD bằng deployment frequency, lead time, change failure rate và time to restore service;
- áp dụng các thực hành tốt: fail fast, least privilege, tách build khỏi deploy, truy vết hai chiều.
Vòng đời của một thay đổi
Hãy theo dõi một thay đổi trong MQTT broker:
flowchart LR
A[Developer commit] --> B[Git push]
B --> C[GitLab pipeline]
C --> D[Test]
D -->|Pass| E[Build image]
D -->|Fail| X[Dừng pipeline]
E --> F[Push GitLab Registry]
F --> G[Update Kubernetes Deployment]
G --> H[Rollout và kiểm tra Ready]
H --> I[Prometheus và Grafana]
- Developer tạo commit. Commit SHA là điểm nối giữa source và pipeline.
- GitLab nhận push và đánh giá rules của từng job.
- Job test cài dependency và chạy test.
- Với một release tag hợp lệ, job package build image và push hai tag: semantic version cùng commit SHA rút gọn.
- Job deploy đổi image của Kubernetes Deployment sang semantic tag vừa tạo.
- Pipeline đợi kubectl rollout status; deploy chỉ thành công khi rollout hoàn tất trong thời gian quy định.
- Metric runtime được quan sát sau deploy để xác nhận phiên bản hoạt động đúng trong thực tế. Pipeline cho biết thao tác kỹ thuật đã hoàn tất. Observability cho biết người dùng và hệ thống đang nhận kết quả gì. Hai tín hiệu bổ sung cho nhau.
Đọc pipeline MQTT broker
Pipeline được Ansible seed vào project MQTT broker có bốn stage:
stages: [test, package, deploy, demo]
Ba stage đầu tạo release. Stage demo phục vụ thao tác seminar như đổi static capacity, bật HPA hoặc mô phỏng lỗi Pod; nó không tạo image mới.
Job test
Job test dùng image Node.js, chạy npm install và npm test. Job này chạy cho thay đổi source thông thường nhưng được bỏ qua với pipeline thao tác Web UI. Lý do là pipeline Web UI chỉ thay đổi cấu hình runtime của release hiện tại, không đóng gói source.
Job package
Job package chỉ chạy khi tag khớp biểu thức semantic version vX.Y.Z. Job thực hiện bốn việc quan trọng:
- đăng nhập registry bằng biến CI do GitLab cung cấp;
- từ chối chạy nếu release tag đã tồn tại;
- build một image;
- push image với cả release tag và commit SHA rút gọn. Việc kiểm tra tag đã tồn tại bảo vệ tính bất biến. Nếu v1.1.0 hôm nay trỏ tới nội dung A nhưng ngày mai bị thay bằng nội dung B, việc điều tra sự cố và rollback sẽ không còn đáng tin cậy.
Job deploy
Job deploy cần kết quả từ package, sau đó:
- dùng kubectl set image để cập nhật riêng container broker trong Deployment mqtt-broker;
- gắn annotation về release, commit và pipeline để truy vết;
- đợi rollout hoàn tất với timeout năm phút.
Identity của CI được giới hạn trong namespace mqtt và chỉ có các quyền cần cho workload seminar. Nó không dùng quyền cluster-admin.
Release, tính bất biến và rollback
Release bằng semantic tag
Lab dùng tag có dạng vMAJOR.MINOR.PATCH, ví dụ:
git tag v1.1.0
git push origin v1.1.0
Tag là release event, không chỉ là nhãn trang trí. Một tag hợp lệ kích hoạt package và deploy; push lên branch chỉ chạy kiểm tra source.
Không build lại khi deploy
Build một lần và deploy chính image đó giúp bảo đảm thứ đã test là thứ đang chạy. Nếu mỗi môi trường tự build, khác biệt dependency, thời điểm tải package hoặc cấu hình build có thể tạo ra nhiều image dù cùng một commit. Mô hình đúng là build once, promote many:
flowchart LR
A[Commit SHA] --> B[Build một lần]
B --> C[(Image digest bất biến)]
C --> D[Development]
C --> E[Staging]
C --> F[Production]
D -->|Đạt kiểm tra| E
E -->|Đạt release gate| F
Các environment cùng tham chiếu một digest; chỉ deployment configuration và thời điểm promotion khác nhau. Semantic tag giúp con người đọc phiên bản, còn digest giúp máy xác nhận chính xác nội dung. Một chuỗi cung ứng phần mềm trưởng thành có thể bổ sung checksum, Software Bill of Materials (SBOM), chữ ký artifact và provenance của build. Đây là các lớp chứng minh artifact gồm gì, được tạo ở đâu và có bị thay đổi sau build hay không; chúng không thay thế test chức năng.
Rollback có hai lớp
Kubernetes có thể quay Deployment về ReplicaSet trước đó:
kubectl -n mqtt rollout undo deployment/mqtt-broker
kubectl -n mqtt rollout status deployment/mqtt-broker
Cách này hữu ích để phục hồi nhanh. Với lịch sử release dài hạn, nên tạo một semantic tag mới từ commit tốt đã biết. Tag mới giữ lịch sử tuyến tính và giúp pipeline, registry cùng Git history kể một câu chuyện thống nhất. Rollback không thay thế việc tìm nguyên nhân. Sau khi dịch vụ ổn định, đội ngũ vẫn cần xác định lỗi đã lọt qua quality gate nào và bổ sung test hoặc guardrail tương ứng.
Rollback và roll forward
Rollback đưa hệ thống về revision trước và thường là đường phục hồi nhanh nhất khi thay đổi độc lập với dữ liệu. Roll forward release một revision mới đã sửa lỗi, phù hợp khi migration hoặc thay đổi dữ liệu khiến phiên bản cũ không còn tương thích. Đội ngũ cần quyết định trước điều kiện dùng mỗi cách. Một nút rollback tồn tại trong giao diện không bảo đảm rollback an toàn; schema database, message format và external API cũng phải tương thích ngược trong deployment window.
Các deployment strategy
CI/CD quyết định artifact nào được release, còn deployment strategy quyết định traffic chuyển sang revision mới như thế nào.
flowchart TB
R[Release mới]
R --> Rolling[Rolling update<br/>thay instance từng phần]
R --> BG[Blue-green<br/>hai môi trường hoàn chỉnh]
R --> Canary[Canary<br/>một phần traffic trước]
R --> Flag[Feature flag<br/>deploy code, bật tính năng riêng]
Rolling --> M[Quan sát health và metric]
BG --> M
Canary --> M
Flag --> M
M -->|Tốt| Continue[Tiếp tục rollout]
M -->|Xấu| Recover[Dừng, rollback hoặc tắt flag]

Lab MQTT dùng rolling update của Kubernetes. kubectl rollout status xác nhận Pod mới sẵn sàng, còn Grafana cung cấp metric runtime. Lab chưa áp dụng blue-green hay canary, nhưng cùng nguyên tắc vẫn đúng: thay đổi nhỏ, quan sát tín hiệu và có điều kiện phục hồi rõ ràng.
Deploy không đồng nghĩa release
Deploy là đưa code hoặc artifact vào môi trường. Release là cho người dùng thực sự sử dụng hành vi mới. Với rolling update đơn giản, hai thời điểm gần như trùng nhau. Với feature flag, code có thể đã deploy nhiều ngày nhưng tính năng chưa release. Phân biệt này hữu ích khi cần giảm rủi ro: pipeline kỹ thuật có thể deploy thường xuyên, trong khi product owner kiểm soát thời điểm bật tính năng mà không cần build lại.
Đo lường hiệu quả CI/CD
Pipeline xanh chưa đủ để kết luận quy trình tốt. Cần đo cả tốc độ dòng chảy lẫn độ ổn định của hệ thống:
flowchart LR
subgraph SPEED[Tốc độ dòng chảy]
DF[Deployment frequency<br/>tần suất deploy]
LT[Lead time for changes<br/>từ commit đến production]
end
subgraph STABILITY[Độ ổn định]
CFR[Change failure rate<br/>tỷ lệ thay đổi gây sự cố]
MTTR[Time to restore service<br/>thời gian phục hồi]
end
SPEED --> Outcome[Khả năng giao thay đổi an toàn]
STABILITY --> Outcome
- Deployment frequency cho biết đội ngũ có thể đưa các lô thay đổi nhỏ ra thường xuyên đến đâu.
- Lead time for changes đo thời gian một thay đổi đi từ commit đến môi trường chạy.
- Change failure rate đo tỷ lệ deploy cần rollback, hotfix hoặc gây suy giảm dịch vụ.
- Time to restore service đo tốc độ phục hồi sau sự cố. Bốn chỉ số cần được đọc cùng nhau. Tăng deployment frequency bằng cách bỏ test có thể làm change failure rate xấu đi. Giữ production “ổn định” bằng cách không deploy làm lead time tăng và tạo release batch lớn hơn. Mục tiêu là cải thiện dòng chảy mà không đánh đổi khả năng phục hồi. Ở cấp pipeline, có thể theo dõi thêm thời gian chờ runner, thời gian chạy từng job, tỷ lệ flaky test và tỷ lệ pipeline phải retry. Các metric này giúp tìm bottleneck, nhưng không nên biến thành mục tiêu để các nhóm tối ưu con số mà bỏ qua kết quả người dùng.
Các thực hành tốt
Fail fast
Đặt kiểm tra nhanh và có xác suất bắt lỗi cao ở đầu pipeline. Lint và unit test nên chạy trước build image nặng. Mục tiêu là dừng sớm, đưa phản hồi nhanh và không tiêu tốn tài nguyên cho một revision đã biết là sai.
Không hard-code secret
Password, token, kubeconfig và private key không thuộc source code hoặc log job. Dùng biến CI được bảo vệ, secret store hoặc identity gắn với runner. Khi truyền password cho CLI, ưu tiên stdin để tránh lộ trong process argument hoặc log.
Áp dụng least privilege
Job build cần quyền push đúng image repository. Job deploy chỉ cần quyền đọc/patch workload liên quan. Tách quyền theo nhiệm vụ làm giảm phạm vi ảnh hưởng nếu một job hoặc credential bị lạm dụng.
Tách build khỏi deploy
Build tạo artifact; deploy chọn artifact đã có và đưa nó đến môi trường đích. Sự phân tách này giúp phê duyệt, retry deploy và rollback mà không vô tình build ra nội dung mới.
Truy vết hai chiều
Từ Deployment đang chạy phải tìm được image tag, commit và pipeline. Từ một pipeline phải biết nó tạo artifact nào và deploy ở đâu. Tag, commit SHA, annotation và log cung cấp chuỗi truy vết đó.
Serialize các thay đổi cùng một workload
Hai pipeline cùng patch một Deployment có thể ghi đè lẫn nhau. Lab đặt các job thay đổi broker vào cùng resource_group, nhờ đó GitLab chỉ cho một thay đổi chạy tại một thời điểm.
Thiết kế cho retry và idempotency
Job có thể bị gián đoạn vì runner hoặc mạng, nên chạy lại phải có kết quả dự đoán được. Lệnh khai báo trạng thái như kubectl apply thường an toàn hơn một chuỗi thao tác phụ thuộc trạng thái ẩn. Với thao tác không thể lặp như tạo release tag, pipeline cần kiểm tra trước và thất bại rõ ràng thay vì âm thầm ghi đè. Retry không nên được dùng để che flaky test. Nếu cùng source lúc pass lúc fail, tín hiệu của quality gate đã mất độ tin cậy và cần được sửa tận gốc.
Xác minh sau deploy
rollout status xác nhận Kubernetes hoàn thành rollout, nhưng chưa đủ để kết luận tính năng hoạt động. Cần kiểm tra readiness, error rate, latency và metric nghiệp vụ. Trong lab, Prometheus và Grafana cho biết active connections, rejected connections, số Pod và connection limit.
Tổng kết
CI/CD là hệ thống phản hồi có thể lặp lại, không chỉ là file YAML chạy vài lệnh. CI phát hiện vấn đề khi tích hợp; Continuous Delivery giữ phần mềm ở trạng thái sẵn sàng release; Continuous Deployment tự động deploy thay đổi đã đạt yêu cầu đến environment chạy. Một quy trình tốt kết hợp quality gate nhiều lớp, artifact bất biến, deployment strategy phù hợp, telemetry và đường phục hồi. Tốc độ phải được đọc cùng độ ổn định qua deployment frequency, lead time, change failure rate và time to restore service. Pipeline MQTT broker thể hiện các nguyên tắc chính: test trước, release bằng semantic tag, build image một lần, không ghi đè release tag, deploy với quyền giới hạn và đợi rollout. Ở bài tiếp theo, chúng ta sẽ xem Kubernetes tiếp nhận image đó và duy trì desired state như thế nào.
All Rights Reserved