Bài viết này hướng dẫn các nhà phát triển và kỹ sư vận hành cách triển khai hiệu quả GitLab CI/CD, theo trình tự từ lý thuyết → thực hành → nâng cao → bảo mật → khắc phục sự cố → so sánh, giúp bạn xây dựng được một quy trình CI/CD hiệu quả, an toàn và dễ quan sát trong dự án thực tế.
I. Giới thiệu: Tại sao cần GitLab CI/CD?
Trong phát triển phần mềm hiện đại, Tích hợp liên tục (CI) và Giao hàng liên tục/Triển khai liên tục (CD) là những thực hành cốt lõi để tăng tốc độ giao hàng và nâng cao chất lượng code. GitLab CI/CD là tính năng tích hợp sẵn của GitLab, kết nối liền mạch mã nguồn, pipeline và giám sát, là một trong những giải pháp DevOps toàn diện phổ biến nhất hiện nay.
Bảng tổng hợp lợi ích chính
| Lợi ích | Mô tả |
|---|---|
| **Tích hợp sâu** | Kết nối tự nhiên với repository Git, MR, Issue, Registry, không cần công cụ bên ngoài. |
| **Cấu hình khai báo** | Chỉ cần một file .gitlab-ci.yml để định nghĩa toàn bộ pipeline, dễ đọc và bảo trì. |
| **Hỗ trợ đa môi trường** | tương thích với Shell, Docker, Kubernetes, từ máy vật lý đến cloud-native. |
| **Hệ sinh thái phong phú** | cung cấp sẵn các mẫu SAST, DAST, quét dependency, Auto DevOps. |
| **Kiểm soát chi phí** | hỗ trợ tự Runner, dự án nhạy cảm có thể triển khai hoàn toàn riêng tư. |
II. Khái niệm cốt lõi và kiến trúc
2.1 Thuật ngữ cơ bản
| Thuật ngữ | Định nghĩa |
|---|---|
| **Pipeline (Đường ống)** | Quy trình tự động gồm nhiều Stage và Job, được kích hoạt bởi các sự kiện như push, MR, tag, lịch trình. |
| **Stage (Giai đoạn)** | Nhóm các Job có logic liên quan (như xay\_dung, kiem\_thu, triển\_khai), Stage chạy tuần tự, Job trong cùng Stage chạy song song. |
| **Job (Nhiệm vụ)** | Đơn vị thực thi nhỏ nhất trong Pipeline, được định nghĩa bởi script. |
| **Runner (Trình chạy)** | Agent thực thi Job, có thể dùng Runner chung của GitLab hoặc tự tạo Runner riêng. |
| **Executor (Trình thực thi)** | Cách thức Runner thực thi: shell / docker / kubernetes / ssh / virtualbox. |
| **Artifact (Sản phẩm)** | File đầu ra của Job, có thể được Job tải xuống hoặc cung cấp cho người dùng tải về. |
| **Cache (Bộ nhớ đệm)** | Thư mục dependency có thể tái sử dụng giữa các pipeline (như .m2, node\_modules), để tăng tốc build. |
| **Environment (Môi trường)** | Trừu tượng hóa mục tiêu triển khai (dev/staging/prod), hỗ trợ rollback và theo dõi lịch sử. |
2.2 Loại pipeline
| Loại | Cách kích hoạt | Mục đích điển hình |
|---|---|---|
| **Pipeline nhánh** | push đến nhánh | Xây dựng và kiểm thử hàng ngày |
| **Pipeline Merge Request** | Tạo/cập nhật MR | Kiểm tra trước khi review code |
| **Pipeline Tag** | đánh tag | Phát hành chính thức |
| **Pipeline Lịch trình** | Công việc định kỳ | Quay lại vào ban đêm, quét bảo mật |
| **Pipeline Cha-Con** | từ khóa trigger |
Phân chia module lớn trong kho duy nhất |
| **Pipeline Đa dự án** | trigger chéo dự án | Phát triển đồng bộ microservice |
2.3 Tổng quan quy trình làm việc
Nhà phát triển push / tạo MR
│
▼
┌─────────────────┐ Quy tắc kích hoạt (rules)
│ .gitlab-ci.yml │ ───────────────────┐
└─────────────────┘ │
│ ▼
▼ ┌───────────────┐
Pipeline ──► Stage₁ ──► Stage₂ ──► ... ──► Stageₙ
│ │ │
Job×N Job×N Job×N
│
▼
Runner (Shell / Docker / K8s)
│
▼
Artifact / Cache / Triển khai môi trường
Điểm quan trọng: Stage chạy tuần tự, nhưng có thể xây dựng pipeline DAG bằng
needsđể loại bỏ việc chờ không cần thiết.
III. Bắt đầu nhanh: Ba bước để chạy pipeline đầu tiên
Bước 1: Viết .gitlab-ci.yml
Tạo file .gitlab-ci.yml trong thư mục gốc dự án:
stages:
- xay_dung
- kiem_thu
- trien_khai
xay_dung_nhiem_vu:
stage: xay_dung
script:
- mvn clean package -DskipTests
artifacts:
paths:
- target/*.jar
expire_in: 1 tuan
kiem_thu_nhiem_vu:
stage: kiem_thu
script:
- mvn test
trien_khai_nhiem_vu:
stage: trien_khai
script:
- scp target/*.jar nguoidung@maychu:/duong/dan/trien_khai
environment:
name: san_xuat
url: https://ung-dung-cua-ban.com
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
only/exceptvẫn được hỗ trợ nhưng là từ khóa cũ, dự án mới nên dùngrules(khả năng biểu đạt mạnh hơn, hỗ trợ điều kiện phức tạp, biến toán,changes,exists).
Bước 2: Cài đặt và đăng ký Runner
# 1. Cài đặt (ví dụ trên CentOS)
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.rpm.sh | sudo bash
sudo yum install -y gitlab-runner
# 2. Đăng ký (Token có tại Cài đặt dự án → CI/CD → Runners)
sudo gitlab-runner register
# 3. Khởi động
sudo gitlab-runner start
sudo gitlab-runner status
Bước 3: Đẩy code, kích hoạt pipeline
git add .gitlab-ci.yml
git commit -m "ci: them cau hinh pipeline"
git push origin main
Sau khi đẩy, truy cập CI/CD → Pipelines để theo dõi trạng thái thực thi.
IV. Case study: Triển khai tự động dự án Java
4.1 Mô tả tình huống
Với dự án Maven, thực hiện: Xây dựng → Kiểm thử đơn vị → Triển khai SSH đến máy chủ từ xa → Khởi động lại dịch vụ.
4.2 Cấu hình đầy đủ
stages:
- xay_dung
- kiem_thu
- trien_khai
variables:
MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository"
cache:
key: "$CI_COMMIT_REF_SLUG"
paths:
- .m2/repository/
xay_dung:
stage: xay_dung
image: maven:3.8.4-openjdk-17
script:
- mvn clean package -DskipTests
artifacts:
paths:
- target/*.jar
expire_in: 1 ngay
kiem_thu:
stage: kiem_thu
image: maven:3.8.4-openjdk-17
script:
- mvn test
artifacts:
when: always
reports:
junit: target/surefire-reports/TEST-*.xml
trien_khai:
stage: trien_khai
image: alpine:latest
before_script:
- apk add --no-cache openssh-client
- eval $(ssh-agent -s)
- echo "$BI_MAT_SSH" | tr -d '\r' | ssh-add -
- mkdir -p ~/.ssh && chmod 700 ~/.ssh
- ssh-keyscan -H $MAY_CHU_DICH >> ~/.ssh/known_hosts
script:
- scp target/*.jar $NGUOI_DUNG@$MAY_CHU_DICH:/opt/app/app.jar
- ssh $NGUOI_DUNG@$MAY_CHU_DICH "sudo systemctl restart app"
environment:
name: san_xuat
url: https://ung-dung-cua-ban.com
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
4.3 Điểm thiết kế chính
| Chiều | Cách làm | Lý do |
|---|---|---|
| **Thông tin nhạy cảm** | BI\_MAT\_SSH đặt vào **Cài đặt → CI/CD → Variables**, chọn Masked + Protected |
Tránh lộ ra log hoặc kho code |
| ️ **Bảo mật SSH** | Sử dụng pipe ghi private key, và ssh-keyscan để thiết lập known\_hosts |
Ngừa tấn công man-in-the-middle, tránh vấn đề tương thích process substitution |
| **Tối ưu build** | Cache .m2/repository theo nhánh |
Giảm đáng kể việc tải lại dependency |
| **Quản lý lưu trữ** | Artifact đặt expire\_in |
Ngăn chặn tích tụ lâu dài vượt hạn mức lưu trữ |
V. Ví dụ đa ngôn ngữ và đa tình huống
5.1 Dự án Node.js
image: node:20-alpine
cache:
key:
files:
- package-lock.json
paths:
- node_modules/
stages: [cai_dat, kiem_tra, kiem_thu, xay_dung]
cai_dat:
stage: cai_dat
script:
- npm ci
kiem_tra:
stage: kiem_tra
script:
- npm run lint
kiem_thu:
stage: kiem_thu
script:
- npm test -- --coverage
coverage: '/All files[^|]*\|[^|]*\s+([\d.]+)/'
xay_dung:
stage: xay_dung
script:
- npm run build
artifacts:
paths:
- dist/
5.2 Dự án Python
image: python:3.11-slim
cache:
paths:
- .cache/pip
- venv/
before_script:
- python -m venv venv
- source venv/bin/activate
- pip install -r requirements.txt
stages: [kiem_tra, kiem_thu]
kiem_tra:
stage: kiem_tra
script:
- pip install ruff
- ruff check .
kiem_thu:
stage: kiem_thu
script:
- pytest --junitxml=bao_cao.xml --cov=app
artifacts:
reports:
junit: bao_cao.xml
5.3 Dự án Go
image: golang:1.22
variables:
GOPATH: $CI_PROJECT_DIR/.go
GOCACHE: $CI_PROJECT_DIR/.gocache
cache:
paths:
- .go/pkg/mod/
- .gocache/
stages: [kiem_thu, xay_dung]
kiem_thu:
stage: kiem_thu
script:
- go vet ./...
- go test -race -coverprofile=coverage.out ./...
xay_dung:
stage: xay_dung
script:
- CGO_ENABLED=0 go build -ldflags="-s -w" -o ung_dung ./cmd/ung_dung
artifacts:
paths: [ung_dung]
5.4 Triển khai Kubernetes
trien_khai_k8s:
stage: trien_khai
image: bitnami/kubectl:latest
variables:
TEN_GIAN_KHOI: san_xuat
before_script:
- echo "$CAU_HINH_K8S" | base64 -d > $HOME/.kube/config
script:
- kubectl set image deployment/ung_dung
ung_dung=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
-n $TEN_GIAN_KHOI
- kubectl rollout status deployment/ung_dung -n $TEN_GIAN_KHOI --timeout=5m
environment:
name: san_xuat
kubernetes:
namespace: $TEN_GIAN_KHOI
rules:
- if: '$CI_COMMIT_TAG'
VI. Năng lực nâng cao và best practices
Theo bốn chiều: Điều khiển quy trình → Tối ưu build → Chất lượng tích hợp → Tái sử dụng kỹ thuật.
6.1 Điều khiển quy trình
① Thực thi có điều kiện (rules)
trien_khai_san_xuat:
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
when: on_success
- when: never
trien_khai_phat_trienv:
environment:
name: phat_trien
rules:
- if: '$CI_COMMIT_BRANCH =~ /^feature\/.*/'
phat_hanh:
rules:
- if: '$CI_COMMIT_TAG'
② Xác nhận thủ công (manual gate)
trien_khai_san_xuat:
stage: trien_khai
when: manual
allow_failure: false
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
③ Pipeline con (parent-child)
kích_hoach_be:
trigger:
include: du_an_be/.gitlab-ci.yml
strategy: depend
kích_hoach_front:
trigger:
include: du_an_front/.gitlab-ci.yml
strategy: depend
④ Kiểm soát độ ổn định (retry / timeout / resource_group)
kiem_thu_e2e_bat_dinh:
script: [./chay_kiem_thu_e2e.sh]
retry:
max: 2
when:
- runner_system_failure
- stuck_or_timeout_failure
timeout: 30 phut
trien_khai_san_xuat:
stage: trien_khai
resource_group: san_xuat # Job trong cùng group chạy tuần tự, tránh triển khai đồng thời
script: [./trien_khai.sh]
| Từ khóa | Tác dụng | Khuyến nghị |
|---|---|---|
| Tự động thử lại với các loại thất bại chỉ định | Chỉ bật cho sự cố cơ sở hạ tầng/hết giờ, tránh che giấu bug thực | |
| Timeout cấp Job (mặc định 1h) | Nới rộng cho test dài, tránh treo chiếm dụng Runner | |
| Đồng bộ hóa Job cùng tên | Các tình huống cần độc quyền môi trường như triển khai sản xuất, di chuyển CSDL |
⑤ Review App (Môi trường xem trước động)
xem_truoc:
stage: trien_khai
script: [./triền_khai_xem_truoc.sh $CI_COMMIT_REF_SLUG]
environment:
name: xem_truoc/$CI_COMMIT_REF_SLUG
url: https://$CI_COMMIT_REF_SLUG.xemtruoc.vi_du.com
on_stop: dung_xem_truoc
auto_stop_in: 1 tuan
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
dung_xem_truoc:
stage: trien_khai
script: [./xoa_xem_truoc.sh $CI_COMMIT_REF_SLUG]
when: manual
environment:
name: xem_truoc/$CI_COMMIT_REF_SLUG
action: stop
Mỗi MR tự động có link xem trước độc lập, auto_stop_in hết hạn hoặc MR được đóng/hợp nhất sẽ tự động thu hồi tài nguyên.
6.2 Tối ưu build
① Song song ma trận
kiem_thu:
parallel:
matrix:
- BỘ_KIEM_TRA: [don_vi, hop_dong, cuoi_cung]
JAVA_VERSION: ["11", "17"]
script:
- mvn test -Dbo_kiem_tra=$BỘ_KIEM_TRA
② Pipeline DAG (needs)
trien_khai:
stage: trien_khai
needs:
- job: xay_dung
artifacts: true
- job: kiem_thu
Phá vỡ tuần tự Stage nghiêm ngặt, cho phép trien_khai kích hoạt ngay sau xay_dung hoàn tất, không cần chờ Job khác cùng Stage.
needsvsdependencies:needskiểm soát cả "thứ tự thực thi + tải artifact";dependencieschỉ kiểm soát tải artifact (thứ tự vẫn do Stage quyết định). Dự án mới nên dùngneeds.
③ Hủy pipeline lỗi thời
default:
interruptible: true
workflow:
auto_cancel:
on_new_commit: interruptible
6.3 Chất lượng tích hợp
① Báo cáo kiểm thử + độ phủ
kiem_thu:
script:
- mvn test jacoco:report
coverage: '/Tong.*?([0-9]{1,3})%/'
artifacts:
when: always
reports:
junit: target/surefire-reports/TEST-*.xml
coverage_report:
coverage_format: cobertura
path: target/site/jacoco/jacoco.xml
② Xây dựng và đẩy container image
xay_dung_image:
stage: xay_dung
image: docker:24.0
services:
- docker:24.0-dind
variables:
DOCKER_TLS_CERTDIR: "/certs"
script:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY"
- docker build -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA" .
- docker push "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA"
``>
> **Lưu ý bảo mật**: DinD phụ thuộc `privileged: true`, có nguy cơ thoát container trên Runner chung. Môi trường sản xuất nên dùng:
>
> - **Kaniko** (`gcr.io/kaniko-project/executor`): không cần Docker daemon, không cần đặc quyền;
> - **Buildah / Podman**: build không root;
> - **Buildx + remote builder**: Runner chỉ là OCI client đẩy image.
**③ Quét chất lượng code**
include:
- template: Code-Quality.gitlab-ci.yml
- template: Security/SAST.gitlab-ci.yml
- template: Security/Dependency-Scanning.gitlab-ci.yml
- template: Security/Secret-Detection.gitlab-ci.yml
### 6.4 Tái sử dụng kỹ thuật
**① `include` tái sử dụng chéo dự án**
include:
- project: 'devops/ci-templates' ref: main file: '/templates/java.yml'
- template: 'Security/SAST.gitlab-ci.yml'
**② `extends` tái sử dụng khối cấu hình**
.nhiem_vu_co_ban: image: maven:3.8.4-openjdk-17 cache: paths:
- .m2/repository/
xay_dung: extends: .nhiem_vu_co_ban script:
- mvn clean package
**③ Sử dụng YAML anchor**
.mau_trien_khai: &mau_trien_khai image: alpine:latest before_script:
- apk add --no-cache openssh-client
trien_khai_thuc_nghiem: <<: *mau_trien_khai script: [./trien_khai.sh thuc_nghiem]
trien_khai_san_xuat: <<: *mau_trien_khai script: [./trien_khai.sh san_xuat]
VII. Bảo mật và tuân thủ best practices
------------
### 7.1 Quản lý thông tin xác thực
| Cách làm | Giải thích |
|---|---|
| \*\*Sử dụng CI/CD Variables\*\* | Thông tin nhạy cảm đặt vào biến cấp dự án/nhóm, chọn `Masked` để che log |
| \*\*Phân biệt Protected\*\* | Biến `Protected` chỉ dùng trên nhánh/tag được bảo vệ, cách biệt thông tin sản xuất |
| \*\*Sử dụng Vault bên ngoài\*\* | Kết nối HashiCorp Vault, AWS Secrets Manager, lấy thông tin khi chạy CI |
| \*\*Tránh echo in biến\*\* | Dù có Mask vẫn có thể lộ do xuống dòng/phân tách |
| \*\*Không đẩy `.env` vào kho\*\* | Ngay cả `.gitignore` cũng nên kết hợp pre-commit kiểm tra |
**Khuyến nghị: Sử dụng OIDC `id_tokens` để triển khai không mật khẩu (GitLab 15.7+)**
GitLab có thể cấp JWT ngắn hạn cho mỗi Job, thiết lập OIDC với AWS / GCP / Azure / HashiCorp Vault, loại bỏ hoàn toàn AccessKey dài hạn.
trien_khai_aws: image: amazon/aws-cli:latest id_tokens: AWS_ID_TOKEN: aud: https://gitlab.com # Giữ nhất quán với cấu hình IdP ở cloud script:
DANG_NHAP=$(aws sts assume-role-with-web-identity --role-arn "$VAI_TRO_AWS" --role-session-name "gitlab-$CI_JOB_ID" --web-identity-token "$AWS_ID_TOKEN" --duration-seconds 3600 --query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]' --output text)
- export AWS_ACCESS_KEY_ID=$(echo $DANG_NHAP | awk '{print $1}')
- export AWS_SECRET_ACCESS_KEY=$(echo $DANG_NHAP | awk '{print $2}')
- export AWS_SESSION_TOKEN=$(echo $DANG_NHAP | awk '{print $3}')
- aws s3 sync dist/ s3://$BUCKET
``>
Lợi ích:
- Không có mật khẩu dài hạn: Thông tin xác thực hết hạn khi Job kết thúc, không cần xoay vòng
- Ủy quyền chi tiết: Cloud có thể đặt chính sách theo đường dẫn dự án, nhánh, môi trường, nguồn MR (ví dụ
subkhớpduong_dan:du_an_a:loai_nhanh:nhanh:main) - Có thể kiểm toán: Mỗi lần đảm nhận vai trò đều có thể truy xuất về Pipeline/Job cụ thể
7.2 Cách Runner
- Tách biệt Runner sản xuất và phát triển: Sử dụng tag để giới hạn Job triển khai quan trọng.
- Sử dụng Docker / Kubernetes Executor: Tránh Shell Executor làm ô nhiễm môi trường host.
- Tắt chế độ
privileged: Trừ khi cần thiết (như DinD), hãy tắt chế độ container đặc quyền.
7.3 Bảo mật chuỗi cung ứng
include:
- template: Security/SAST.gitlab-ci.yml
- template: Security/Dependency-Scanning.gitlab-ci.yml
- template: Security/Container-Scanning.gitlab-ci.yml
- template: Security/Secret-Detection.gitlab-ci.yml
- template: Security/License-Scanning.gitlab-ci.yml
``>
Sau khi bật, mỗi MR sẽ tạo báo cáo bảo mật so sánh với nhánh chính, phát hiện lỗ hổng mới sẽ chặn việc hợp nhất.
### 7.4 Kiểm toán và tuân thủ
- Bật **Audit Events** theo dõi các thao tác nhạy cảm (thay đổi biến, đăng ký Runner, ủy quyền pipeline).
- Sử dụng **Compliance Frameworks** bắt buộc dự án quan trọng phải chứa stage quét bảo mật.
- Bật **Protected Environments** cho môi trường sản xuất, phải có phê duyệt mới triển khai.
VIII. Khả năng quan sát và giám sát pipeline
-------------
### 8.1 Chỉ số tích hợp
GitLab có sẵn bảng **CI/CD → Analytics**, tập trung vào ba chỉ số cốt lõi:
| Chỉ số | Ý nghĩa | Hướng tối ưu |
|---|---|---|
| \*\*Thời gian Pipeline\*\* | Tổng thời gian chạy pipeline | Giảm bằng `needs`, song song và cache |
| \*\*Tỷ lệ thành công\*\* | Tỷ lệ thành công | Định vị test không ổn định, dependency không ổn định |
| \*\*Tần suất triển khai\*\* | Tần suất triển khai (chỉ số DORA) | Thể hiện độ trưởng thành của giao hàng liên tục |
### 8.2 Tích hợp Prometheus + Grafana
gitlab-runner tự hiển thị metrics
gitlab-runner run --listen-address=":9252"
``>
Prometheus thu thập sau đó có thể quan sát trên Grafana:
- Số lượng Runner rảnh/bận
- Thời gian chờ hàng đợi Job
- Số lượng chạy song song và sử dụng tài nguyên
8.3 Log và cảnh báo
- Lưu trữ Job Trace: Với Runner quy mô lớn, nên kết hợp S3/OSS để lưu lâu dài.
- Cảnh báo thất bại: Tự động gửi thông báo thất bại qua Integrations → Slack / WeChat / Feishu.
- Bảng SLA: Đặt ngưỡng cảnh báo cho dự án quan trọng như "tỷ lệ thành công pipeline nhánh chính ≥ 99%".
IX. Hướng dẫn khắc phục sự cố: Câu hỏi thường gặp
Q1 | Runner không thực thi Job
- Kiểm tra trạng thái:
sudo gitlab-runner status, xác nhận tiến trình đang chạy. - Khớp tag:
tagscủa Job phải khớp chính xác với tag Runner đăng ký. - Quyền dự án: Runner riêng cần cho phép dự án sử dụng trong cài đặt Runner.
- Hạn chế song song:
concurrentkhông đủ sẽ khiến Job phải xếp hàng.
Q2 | Lỗi cú pháp file cấu hình
- CI Lint: GitLab cung cấp CI/CD → Editor → Lint, có thể kiểm tra YAML trực tiếp.
- Xác thực cục bộ: Sử dụng
glab ci linthoặcgitlab-ci-localchạy dry-run.
Q3 | Triển khai SSH thất bại
- Private key inject qua biến, và cấu hình
known_hostsrõ ràng. - Nếu dùng Shell executor, đảm bảo user Runner trên máy chủ có đủ quyền.
- Tuân thủ nguyên tắc quyền tối thiểu, tránh dùng root.
Q4 | Cache không hoạt động
cache.keycó ổn định (nên dùng theo nhánh$CI_COMMIT_REF_SLUG).- Đường dẫn cache phải nằm trong thư mục làm việc dự án (như
.m2/repository/), đường dẫn tuyệt đối~/.m2/...dưới Docker executor sẽ không được cache. - Môi trường nhiều Runner nên cấu hình cache phân tán (S3/MinIO).
Q5 | Pipeline chạy quá chậm
- Bật
needsDAG, phá vỡ tuần tự Stage. - Sử dụng
parallel:matrixchia nhỏ bộ test lớn. - Xây dựng sẵn image cơ bản, tránh cài lại dependency mỗi lần.
- Tận dụng
interruptible: truetự động hủy pipeline lỗi thời chạy song song.
Q6 | Pipeline Merge Request không hoạt động
- Đảm bảo
ruleschứa$CI_PIPELINE_SOURCE == "merge_request_event". - Bật Settings → Merge requests → Pipelines for merged results.
Q7 | "Job failed: exit code 137"
- Container bị kill do OOM: kiểm tra sử dụng bộ nhớ của Job, điều chỉnh
memory_limitcủa Runner hoặc chia nhỏ task. - Tình huống điển hình: build
webpackfrontend,mvn packagedự án Java lớn.
X. So sánh ngang: GitLab CI vs Jenkins vs GitHub Actions
| Chiều | **GitLab CI** | **Jenkins** | **GitHub Actions** |
|---|---|---|---|
| Định dạng cấu hình | YAML (tập trung) | Groovy DSL / UI | YAML (tập trung) |
| Tích hợp với nền tảng code | Tích hợp tự nhiên | Cần plugin | Tích hợp tự nhiên |
| Hệ sinh thái plugin | Trung bình (nhiều template) | Cực kỳ phong phú | Phong phú (Marketplace) |
| Triển khai riêng tư | Hỗ trợ đầy đủ | Hỗ trợ đầy đủ | ️ Cần GitHub Enterprise |
| Quyền/kiểm toán | Enterprise grade | Cần plugin bổ sung | Enterprise grade |
| Đường cong học | Thấp | Trung bình - cao | Thấp |
| Phù hợp | DevOps toàn diện | Legacy pipeline phức tạp | Môi trường GitHub ưu tiên |
Lời khuyên chọn: Nếu code trên GitLab, nên dùng GitLab CI; nếu có tài sản Jenkins lớn, có thể di chuyển dần; dự án GitHub nên chọn Actions.
XI. Bảng tra cứu biến định sẵn
| Biến | Giải thích |
|---|---|
$CI\_PROJECT\_DIR |
Thư mục làm việc sau khi clone repository |
$CI\_PROJECT\_PATH |
Đường dẫn namespace dự án (như nhom/ung\_dung) |
$CI\_COMMIT\_SHA |
SHA đầy đủ của lần commit |
$CI\_COMMIT\_SHORT\_SHA |
SHA ngắn 8 ký tự, thường dùng cho image tag |
$CI\_COMMIT\_BRANCH |
Tên nhánh hiện tại (ngoại trừ ngữ cảnh MR) |
$CI\_COMMIT\_TAG |
Tên Tag hiện tại (chỉ pipeline Tag) |
$CI\_COMMIT\_REF\_SLUG |
Tên nhánh/Tag đã an toàn hóa, dùng cho cache key |
$CI\_PIPELINE\_SOURCE |
Nguồn kích hoạt: push / merge\_request\_event / schedule / web |
$CI\_MERGE\_REQUEST\_IID |
Số MR |
$CI\_REGISTRY / $CI\_REGISTRY\_IMAGE |
Địa chỉ/ten image Container Registry tích hợp |
$CI\_JOB\_TOKEN |
Token tạm, dùng cho API call và trigger chéo dự án |
$GITLAB\_USER\_LOGIN |
Tên người kích hoạt pipeline |
Nếu có thắc mắc hoặc muốn thảo luận tình huống cụ thể, vui để lại bình luận bên dưới.