Thực chiến GitLab CI/CD: Từ cơ bản đến nâng cao

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)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/except vẫn được hỗ trợ nhưng là từ khóa cũ, dự án mới nên dùng rules (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.

needs vs dependencies: needs kiểm soát cả "thứ tự thực thi + tải artifact"; dependencies chỉ kiểm soát tải artifact (thứ tự vẫn do Stage quyết định). Dự án mới nên dùng needs.

③ 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ụ sub khớp duong_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: tags củ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: concurrent khô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 lint hoặc gitlab-ci-local chạy dry-run.

Q3 | Triển khai SSH thất bại

  • Private key inject qua biến, và cấu hình known_hosts rõ 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.key có ổ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 needs DAG, phá vỡ tuần tự Stage.
  • Sử dụng parallel:matrix chia 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: true tự động hủy pipeline lỗi thời chạy song song.

Q6 | Pipeline Merge Request không hoạt động

  • Đảm bảo rules chứ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_limit của Runner hoặc chia nhỏ task.
  • Tình huống điển hình: build webpack frontend, mvn package dự á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.

Thẻ: gitlab CICD DevOps automation continuous-integration

Đăng vào ngày 1 tháng 7 lúc 02:41