L
Git • Literally Web ID

Optimasi Performa Gitlab CI/CD Pipeline untuk Skala Enterprise

⏱️ 15 menit baca • 📅 14 Oct 2026 • 👁️ 1 views
Optimasi Performa Gitlab CI/CD Pipeline untuk Skala Enterprise

1. Konteks Industri & Analisis Akar Masalah

Dalam lanskap pengembangan perangkat lunak skala enterprise modern, kecepatan iterasi dan keandalan rilis (release reliability) adalah penentu utama daya saing bisnis. Tim teknik sering kali berhadapan dengan ekosistem aplikasi yang kompleks, mulai dari frontend berbasis HTML/CSS/JS modern, backend berperforma tinggi menggunakan Go, Node.js, atau PHP-FPM, hingga infrastruktur pendukung seperti Nginx, Caddy, database MySQL/MariaDB, sistem caching Redis, dan penyimpanan objek S3/MinIO. Namun, seiring bertambahnya ukuran kode sumber dan kompleksitas pengujian, GitLab CI/CD pipeline sering kali berubah menjadi titik kemacetan (bottleneck) utama yang menghambat produktivitas.

Di dunia nyata, bottleneck performa pipeline biasanya disebabkan oleh beberapa faktor krusial:

  • Unduhan Dependensi yang Berulang: Setiap job melakukan npm install, composer install, atau go mod download dari internet tanpa mekanisme caching lokal yang efisien, menghabiskan waktu bandwidth dan latensi jaringan.
  • Eksekusi Sekuensial yang Tidak Perlu: Job pengujian, analisis statis (linting), dan pembangunan aset (build) dijalankan secara linier (sequential) alih-alih paralel, padahal sumber daya runner tersedia.
  • Konfigurasi Executor yang Sub-optimal: Penggunaan shell executor yang meninggalkan sampah di server host atau docker executor yang berulang kali menarik (pull) image dasar (base image) yang sama tanpa strategi image caching yang tepat.

Sebelum vs Sesudah Penerapan Optimasi

Metrik Performa Sebelum Optimasi Sesudah Optimasi Enterprise Dampak Bisnis
Total Durasi Pipeline 25 - 45 Menit 3 - 6 Menit Peningkatan kecepatan feedback loop developer hingga 85%.
Penggunaan Bandwidth Tinggi (Download ulang node_modules/vendor tiap job) Minimal (Caching cerdas berbasis lock file) Menghemat kuota jaringan dan menghindari rate limit registry eksternal.
Ketersediaan Runner Sering deadlock / kehabisan disk space Stabil dengan clean up policy dan auto-scaling Mengurangi waktu henti infrastruktur dan kegagalan build acak.

[!WARNING] Mengabaikan pengelolaan cache dan paralelisme job di lingkungan enterprise tidak hanya membuang waktu developer, tetapi juga membengkakkan biaya infrastruktur cloud (AWS/GCP/Azure) untuk runner nodes.


2. Konsep Inti & Deep Dive Arsitektur

Untuk merancang pipeline yang efisien, kita harus memahami arsitektur internal GitLab Runner dan interaksinya dengan GitLab Instance. GitLab Runner adalah aplikasi mandiri yang memproses job CI/CD. Dalam lingkungan enterprise, konfigurasi Docker Executor dengan Docker Machine atau Kubernetes Executor adalah standar industri karena menawarkan isolasi lingkungan yang sempurna.

Alur Eksekusi Data (Under the Hood)

+------------------+         1. Poll Job          +------------------------+
|  GitLab Instance | <----------------------------+     GitLab Runner      |
+--------+---------+                              +-----------+------------+
         |                                                    | 2. Create Container
         | 3. Clone / Fetch Repo                              v
         +---------------------------------------> +------------------------+
                                                   |   Docker Executor      |
         +-----------------------------------+     +-----------+------------+
         | 4. Restore Cache (S3 / MinIO)     |                 |
         +-----------------------------------+                 | 5. Run Script / Build
         | 6. Save Cache                     | <---------------+----------------+
         +-----------------------------------+                                  |
                                                   +----------------------------+
                                                   | Artifacts Upload to GitLab |
                                                   +----------------------------+
  1. Polling: Runner secara berkala melakukan polling ke GitLab Instance untuk mencari job yang antre.
  2. Inisialisasi Container: Saat job diterima, Docker executor membuat kontainer terisolasi berdasarkan image yang didefinisikan dalam .gitlab-ci.yml.
  3. Kloning Repositori: Runner mengunduh kode sumber menggunakan mekanisme fetch atau clone yang dioptimalkan (GIT_STRATEGY).
  4. Restorasi Cache: Cache yang dikompresi ditarik dari Cache Server (biasanya MinIO S3-compatible storage) ke dalam direktori kerja kontainer.
  5. Eksekusi Script: Perintah build, test, dan lint dijalankan secara sekuensial atau paralel sesuai tahapan stage.
  6. Penyimpanan Cache & Artefak: Perubahan pada direktori cache diunggah kembali ke storage, sementara artefak hasil build disimpan di GitLab untuk digunakan stage berikutnya.

3. Perbandingan Komparatif / Analisis Pendekatan

Berikut adalah analisis mendalam mengenai berbagai pendekatan arsitektur executor dan strategi caching dalam GitLab CI/CD:

Pendekatan / Fitur Docker Executor (Standard) Docker Executor + S3 Cache Kubernetes Executor (K8s)
Isolasi Keamanan Tinggi (Kontainer terisolasi) Tinggi (Kontainer terisolasi) Sangat Tinggi (Pod & Namespace level)
Kecepatan Cache Lambat (Lokal disk runner) Cepat (Dedicated S3/MinIO) Sangat Cepat (Distributed PVC / S3)
Skalabilitas Terbatas pada kapasitas host Tinggi (Multi-runner node) Skala tak terbatas (Auto-scaling node)
Kompleksitas Setup Rendah Menengah Tinggi
Penggunaan RAM/CPU Efisien Efisien Memerlukan overhead Kubernetes
Trade-off Utama Risiko disk penuh di host runner Membutuhkan infrastruktur S3 terpisah Manajemen cluster Kubernetes yang rumit

[!TIP] Untuk perusahaan skala menengah ke atas, kombinasi Docker Executor dengan Distributed S3/MinIO Cache memberikan rasio biaya dan performa paling optimal tanpa kompleksitas manajemen Kubernetes yang tinggi.


4. Prasyarat Sistem & Persiapan Lingkungan

Sebelum mengimplementasikan optimasi pipeline, pastikan infrastruktur pendukung telah memenuhi spesifikasi berikut:

  • Sistem Operasi Host Runner: Ubuntu Server 22.04 LTS / Debian 12 (Minimum 4 vCPU, 8 GB RAM, 100 GB SSD NVMe).
  • Software Dependencies:
    • Docker Engine v24.0+
    • GitLab Runner v16.0+
    • MinIO Server atau akses ke AWS S3 Bucket untuk Distributed Cache.
  • Hak Akses & Port:
    • User gitlab-runner memiliki izin akses ke socket Docker (/var/run/docker.sock).
    • Port keluar (Outbound) 443 terbuka ke GitLab Instance dan S3 Storage.

Verifikasi Awal di Server Runner

# Verifikasi versi Docker dan GitLab Runner
docker --version
gitlab-runner --version

# Pastikan user gitlab-runner dapat menjalankan perintah docker tanpa sudo
sudo -u gitlab-runner docker run hello-world

5. Panduan Implementasi Langkah demi Langkah

Berikut adalah konfigurasi lengkap config.toml untuk GitLab Runner dan file .gitlab-ci.yml tingkat enterprise yang menerapkan caching tingkat lanjut dan paralelisme multi-stage.

Langkah 1: Konfigurasi config.toml GitLab Runner

Letakkan konfigurasi ini pada /etc/gitlab-runner/config.toml untuk mengaktifkan S3 distributed cache dan mengoptimalkan penggunaan volume Docker.

concurrent = 8
check_interval = 0

[session_server]
  session_timeout = 1800

[[runners]]
  name = "enterprise-docker-runner-01"
  url = "https://gitlab.domain.internal"
  id = 1
  token = "GLRT-REDACTED_RUNNER_TOKEN"
  token_obtained_at = 2023-10-01T00:00:00Z
  token_expires_at = 0001-01-01T00:00:00Z
  executor = "docker"
  
  [runners.custom_build_dir]
  [runners.cache]
    Type = "s3"
    Shared = true
    [runners.cache.s3]
      ServerAddress = "s3.dualstack.us-east-1.amazonaws.com"
      BucketName = "enterprise-gitlab-runner-cache"
      BucketLocation = "us-east-1"
      Insecure = false
      AuthenticationType = "iam"
    [runners.cache.gcs]
    [runners.cache.azure]
    
  [runners.docker]
    tls_verify = false
    image = "ubuntu:22.04"
    privileged = false
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    volumes = ["/cache", "/var/run/docker.sock:/var/run/docker.sock"]
    shm_size = 2147483648
    pull_policy = ["if-not-present", "always"]

Langkah 2: Implementasi .gitlab-ci.yml Multi-stage Komprehensif

Buat file .gitlab-ci.yml di akar repositori proyek Anda.

stages:
  - prepare
  - lint
  - test
  - build
  - deploy

variables:
  DOCKER_DRIVER: overlay2
  FF_USE_FAST_ZIP: "true"
  CACHE_COMPRESSION_LEVEL: "fastest"
  NODE_ENV: "production"

default:
  interruptible: true
  retry:
    max: 2
    when:
      - runner_system_failure
      - api_failure

# Global Caching Strategy
cache:
  key: "${CI_COMMIT_REF_SLUG}"
  paths:
    - node_modules/
    - vendor/
    - .go/pkg/mod/
    - .npm/

# 1. Prepare Stage: Dependencies Installation
install_dependencies:
  stage: prepare
  image: node:20-alpine
  script:
    - echo "Installing Node.js dependencies..."
    - npm ci --cache .npm --prefer-offline
  cache:
    key:
      files:
        - package-lock.json
    paths:
      - .npm/
      - node_modules/
    policy: pull-push
  rules:
    - if: '$CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "merge_request_event"'

# 2. Lint Stage: Parallelized Code Quality Checks
lint:frontend:
  stage: lint
  image: node:20-alpine
  dependencies: [install_dependencies]
  script:
    - echo "Running ESLint and Prettier..."
    - npm run lint

lint:backend:
  stage: lint
  image: golang:1.21-alpine
  script:
    - echo "Running Golangci-lint..."
    - golangci-lint run --timeout=5m

# 3. Test Stage: Unit & Integration Testing
test:unit:
  stage: test
  image: php:8.2-fpm
  script:
    - echo "Running PHPUnit tests..."
    - vendor/bin/phpunit --colors=always
  cache:
    key:
      files:
        - composer.lock
    paths:
      - vendor/
    policy: pull

# 4. Build Stage: Multi-Service Asset & Binary Compilation
build:frontend:
  stage: build
  image: node:20-alpine
  dependencies: [install_dependencies]
  script:
    - echo "Compiling frontend assets..."
    - npm run build
  artifacts:
    name: "frontend-dist-$CI_COMMIT_SHA"
    expire_in: 7 days
    paths:
      - public/

build:backend:
  stage: build
  image: golang:1.21-alpine
  script:
    - echo "Compiling Go binary..."
    - export GOMODCACHE=$CI_PROJECT_DIR/.go/pkg/mod
    - go build -ldflags="-s -w" -o bin/app main.go
  artifacts:
    name: "backend-binary-$CI_COMMIT_SHA"
    expire_in: 7 days
    paths:
      - bin/app
  cache:
    key: 
      files:
        - go.sum
    paths:
      - .go/pkg/mod/
    policy: pull-push

# 5. Deploy Stage: Production Deployment
deploy:production:
  stage: deploy
  image: alpine:3.18
  dependencies:
    - build:frontend
    - build:backend
  before_script:
    - apk add --no-cache openssh-client
    - eval $(ssh-agent -s)
    - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
    - mkdir -p ~/.ssh
    - chmod 700 ~/.ssh
    - ssh-keyscan -H "$PRODUCTION_SERVER_IP" >> ~/.ssh/known_hosts
  script:
    - echo "Deploying artifacts to Production Server..."
    - scp bin/app user@$PRODUCTION_SERVER_IP:/var/www/app/bin/
    - scp -r public/* user@$PRODUCTION_SERVER_IP:/var/www/app/public/
    - ssh user@$PRODUCTION_SERVER_IP "sudo systemctl restart php8.2-fpm nginx app-supervisor"
  environment:
    name: production
    url: https://example.com
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'
      when: manual

6. Bedah Kode & Penjelasan Detail Baris Kunci

Mari kita bedah parameter krusial dalam konfigurasi di atas untuk memahami bagaimana optimasi bekerja:

  • FF_USE_FAST_ZIP: "true": Fitur eksperimental GitLab CI yang menggunakan pustaka pengarsipan Go yang dioptimalkan. Mengurangi waktu kompresi dan dekompresi cache hingga 60% dibandingkan utilitas zip standar sistem.
  • CACHE_COMPRESSION_LEVEL: "fastest": Mengatur tingkat kompresi arsip cache. Opsi fastest memprioritaskan kecepatan CPU runner dibandingkan ukuran file cache, yang sangat ideal karena bandwidth jaringan S3 enterprise biasanya jauh lebih cepat daripada kapasitas CPU untuk kompresi tingkat tinggi (best).
  • **`pull_policy = ["if-not-present
🏷️ Tags: #Nginx #High Concurrency #Performance #Sysadmin #Web Server