Menghubungkan GitOps dengan pipeline CI/CD: memisahkan tanggung jawab CI dan CD, membangun pipeline dari checkout hingga security scanning, memperbarui manifest di Git sebagai jembatan CD, dan integrasi dengan GitHub Actions, GitLab CI/CD, serta Jenkins secara praktis.

Di episode 26 kalian sudah menyiapkan disaster recovery — klaster bisa dibangun ulang kapan saja dengan prosedur yang teruji dan target RTO/RPO yang terukur. Namun ada satu hal yang masih manual dalam siklus kalian: bagaimana kode aplikasi yang baru di-commit akhirnya berjalan di klaster. Jika setiap update image masih dilakukan lewat flux reconcile manual atau kubectl set image, ada pekerjaan yang seharusnya bisa diotomasi.
Mari kita tarik kembali ke prinsip inti GitOps: satu-satunya cara mengubah klaster adalah melalui Git. Pipeline yang bagus menghormati prinsip ini — ia tidak mengakses klaster secara langsung, melainkan memperbarui repository Git dan membiarkan Flux menarik perubahan tersebut. Ini mengubah CI/CD dari "deploy langsung ke klaster" menjadi "menjaga Git tetap sinkron dengan kode terbaru".
Pada episode ini kita akan membangun pipeline CI/CD yang utuh di atas Flux: pemisahan tanggung jawab CI dan CD, pipeline CI dari checkout hingga security scanning, CD melalui Git sebagai jembatan menuju Flux, dan integrasi praktis dengan GitHub Actions, GitLab CI/CD, serta Jenkins.
CI (Continuous Integration) bertanggung jawab atas kualitas kode: mengambil sumber, membangun, menguji, dan menerbitkan artifact. Pertanyaan yang dijawab CI adalah "apakah kode ini layak dikirim?" Cakupan kerjanya:
CI berhenti di pintu registry. Ia tidak menyentuh klaster dan tidak mengecek deployment.
CD (Continuous Delivery/Deployment) bertanggung jawab atas pengiriman ke lingkungan. Pertanyaan yang dijawab CD adalah "kapan dan ke mana artifact ini dikirim?" Cakupan kerjanya:
Dalam GitOps, CD tidak mendorong ke klaster; CD mendorong perubahan ke Git, dan Flux yang menariknya. Ini memindahkan risiko deployment keluar dari pipeline dan ke dalam mekanisme reconciliation.
Jembatan antara CI dan CD adalah repository GitOps: CI menulis artifact (image tag), CD menulis perubahan manifest, dan Flux membaca keduanya. Pemisahan ini penting karena:
Pipeline CI dimulai dengan checkout sumber dan menjalankan verifikasi kualitas. Contoh urutan langkah yang umum:
Tag yang unik adalah kuncinya. Menggunakan latest atau tag yang bisa ditimpa membuat audit deployment menjadi tidak mungkin — kita tidak akan tahu persis kode mana yang berjalan.
Pembangunan dan push image adalah inti CI. Contoh langkah sederhana:
docker build -t ghcr.io/devvnull/checkout-app:sha-abc123 .
docker push ghcr.io/devvnull/checkout-app:sha-abc123Atau gunakan Buildx untuk image multi-arsitektur yang siap production:
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t ghcr.io/devvnull/checkout-app:sha-abc123 \
--push .Dengan tag berbasis commit SHA, setiap image terhubung langsung ke revisi kode — fondasi untuk CD yang dapat diaudit.
Mengirim kode tanpa memindai keamanannya seperti membuka pintu tanpa mengecek siapa yang masuk. Dua lapis scan yang umum:
govulncheck, npm audit, atau pip-audit.Jadikan scan sebagai gerbang: jika ditemukan kerentanan dengan severity tinggi, pipeline gagal dan image tidak didorong. Perhatikan juga pemindaian dalam registry pada jadwal berkala, karena kerentanan baru bisa ditemukan setelah image dibuat.
Setelah image ada di registry, langkah CD adalah memperbarui repository GitOps agar merujuk image baru. Untuk Kustomize, update tag image di file image:
kustomize edit set image \
ghcr.io/devvnull/checkout-app=ghcr.io/devvnull/checkout-app:sha-abc123Untuk Helm, update nilai tag di values.yaml:
yq eval -i '.image.tag = "sha-abc123"' values.yamlPerubahan ini di-commit dan di-push. Di sinilah CD berakhir dari sisi pipeline — sisanya adalah pekerjaan Flux.
Karena GitRepository dan Kustomization sudah dikonfigurasi, Flux mendeteksi commit baru pada interval atau melalui webhook, lalu mereconcile. Pantau deployment berjalan dengan perintah Flux:
flux get kustomization apps
flux get helmrelease checkout
flux events --for Kustomization/appsflux events menampilkan event terbaru untuk resource tertentu. Jika deployment gagal, Flux menandai Kustomization tidak Ready dan menghentikan perubahan lebih lanjut.
Important
Jangan menambahkan langkah "deploy ke klaster" di pipeline. Jika pipeline butuh mengakses klaster, berarti arsitekturnya melanggar prinsip GitOps — kredensial klaster seharusnya hanya ada di sisi Flux, bukan di CI/CD.
GitHub Actions adalah pilihan paling populer untuk repositori di GitHub. Workflow build yang menggabungkan checkout, test, dan push image bisa dibuat dengan langkah-langkah berikut:
name: build
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: "1.22"
- run: go test ./...
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/build-push-action@v6
with:
push: true
tags: ghcr.io/devvnull/checkout-app:sha-${{ github.sha }}Perhatikan bahwa ekspresi GitHub Actions seperti github.sha hanya muncul di dalam blok YAML — di luar itu, pipeline tidak membawa rahasia klaster.
Setelah image terbit, workflow CD memperbarui repository GitOps. Untuk Kustomize, jalankan kustomize edit set image lalu commit:
git clone https://github.com/devvnull/gitops-production
cd gitops-production
cd apps/checkout/overlays/production
kustomize edit set image \
ghcr.io/devvnull/checkout-app=ghcr.io/devvnull/checkout-app:sha-abc123
git commit -am "chore: update checkout image"
git pushUntuk Helm, update values.yaml dengan yq dan commit dengan cara yang sama.
Untuk lingkungan yang membutuhkan persetujuan, jangan push langsung ke main. Buat pull request dari branch baru dan biarkan review menjadi gerbang terakhir:
git checkout -b update/checkout-sha-abc123
git commit -am "chore: update checkout image"
git push origin update/checkout-sha-abc123
gh pr create --title "chore: update checkout image" \
--body "Update image checkout ke sha-abc123"Setelah PR disetujui dan di-merge, Flux mendeteksi commit dan melakukan deployment. Alternatif yang lebih otomatis adalah flux image automation (ImagePolicy dan ImageUpdateAutomation) yang bahkan bisa menggantikan langkah ini sepenuhnya — dibahas pada seri sebelumnya.
GitLab memiliki konsep stage yang selaras dengan pemisahan CI/CD. Pipeline khas memiliki stage build, test, scan, dan gitops. Contoh konfigurasi untuk menjalankan image Flux CLI di pipeline:
gitops:
stage: gitops
image: ghcr.io/fluxcd/flux-cli:latest
script:
- git clone https://oauth2:$GITLAB_TOKEN@$GITOPS_REPO
- cd $GITOPS_REPO
- ./update-image.sh checkout sha-abc123
- git commit -am "chore: update checkout image"
- git push
only:
- mainPerhatikan bahwa pipeline GitLab tidak mengakses klaster sama sekali — ia hanya memperbarui repository GitOps.
Untuk workflow yang memerlukan review, GitLab dapat membuat Merge Request (MR) melalui API setelah memperbarui manifest:
curl -X POST "$CI_SERVER_URL/api/v4/projects/$GITOPS_PROJECT_ID/merge_requests" \
--header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
--data "source_branch=update/checkout-sha-abc123" \
--data "target_branch=main" \
--data "title=chore: update checkout image"MR menjaga perubahan manifest melewati review sebelum di-merge, lalu Flux mengeksekusi deployment otomatis setelah merge.
Tip
Gunakan token khusus untuk akses Git yang dibatasi hanya pada repository GitOps, bukan token developer penuh. GitLab memungkinkan membuat token dengan scope terbatas, sehingga pipeline tidak bisa mengubah repository lain.
Jenkins mengotomasi build dan deploy melalui Jenkinsfile. Untuk CD berbasis GitOps, Jenkins cukup melakukan hal yang sama seperti pipeline lain: memperbarui manifest GitOps dan push. Contoh pipeline:
pipeline {
agent any
stages {
stage('Update manifest') {
steps {
sh '''
git clone https://github.com/devvnull/gitops-production
cd gitops-production
kustomize edit set image \
ghcr.io/devvnull/checkout-app=ghcr.io/devvnull/checkout-app:sha-abc123
git commit -am "chore: update checkout image"
git push
'''
}
}
}
}kustomize edit set image dijalankan dari dalam direktori overlay aplikasi, dan push dilakukan dengan kredensial Git yang disimpan di Jenkins.
Jenkins menutup siklus dengan notifikasi — tim harus tahu status pipeline tanpa membuka Jenkins:
post {
success {
slackSend channel: '#ci-cd',
message: 'Deployment checkout berhasil: sha-abc123'
}
failure {
slackSend channel: '#ci-cd',
message: 'Deployment checkout GAGAL: ${BUILD_URL}'
}
}Notifikasi bisa diperluas ke email, Teams, atau webhook lain. Kombinasikan dengan alerting Flux di episode 25 untuk cakupan penuh: pipeline memberi tahu bahwa perubahan dikirim, Flux memberi tahu bahwa reconciliation berhasil atau gagal.
Warning
Jangan menyimpan kredensial Git di dalam Jenkinsfile. Simpan di credential store Jenkins (misalnya credentials('git-ops-token')) dan ambil di dalam script. Jenkinsfile yang masuk ke repository harus bebas rahasia.
Pada episode 27 ini kalian telah menghubungkan GitOps dengan pipeline CI/CD: pemisahan tanggung jawab CI (build, test, publish) dan CD (deploy, promote, monitor) dengan Git sebagai jembatan, pipeline CI dari checkout hingga security scanning dengan tag image unik, CD melalui Git tempat Flux mendeteksi dan men-deploy otomatis, serta integrasi praktis dengan GitHub Actions, GitLab CI/CD, dan Jenkins.
Inti yang harus dibawa pulang:
latest.Sekarang perubahan mengalir otomatis dari commit ke klaster. Namun seberapa yakin kalian bahwa manifest yang dikirim benar-benar aman untuk diterapkan? Di episode 28 selanjutnya kita akan membahas Testing Strategies — validasi manifest dengan linting dan policy, dry-run testing dengan flux diff, preview environments berbasis PR, integration testing pasca-deploy, hingga chaos engineering untuk menguji ketahanan klaster. Pastikan tetap semangat!