İçeriğe Atla
Mustafa Erbay
Kariyer · 10 dk okuma · görüntülenme

GitOps vs Push Tabanlı CI/CD: Danışmanlıkta Hangisi?

Saha tecrübelerime dayanarak GitOps ve Push tabanlı CI/CD yaklaşımlarını karşılaştırıyorum. Hangi senaryoda hangisini seçmeliyiz?

100%

GitOps vs Push tabanlı CI/CD karşılaştırması yaparken teorik makalelerin anlattığı pembe dünyalardan uzak durmayı seviyorum. Sahada, gece saat 03:00’te bir deploy patladığında ne “Zero Trust” kalıyor ne de “Single Source of Truth”. Yıllar içinde irili ufaklı onlarca altyapı kurmuş, acı tatlı pek çok deploy krizine girmiş biri olarak bu iki yaklaşımın danışmanlık projelerindeki gerçek karşılığını masaya yatırmak istedim.

Müşteri projelerinde veya kendi geliştirdiğim büyük ölçekli sistemlerde her iki modeli de defalarca uyguladım. Hangisinin daha “modern” olduğu beni hiç ilgilendirmiyor; benim baktığım tek şey operasyonel yükü ne kadar azalttığı, ekipleri ne kadar az uykusuz bıraktığı ve faturayı ne kadar optimize ettiğidir. Gelin, teoriyi bir kenara bırakıp doğrudan production ortamlarının gerçeklerine odaklanalım.

Push Tabanlı CI/CD Yaklaşımının Sahadaki Gerçekleri

Geleneksel push tabanlı CI/CD modellerinde (örneğin GitLab CI veya GitHub Actions kullanarak hedef sunucuya doğrudan bağlanıp deploy yaptığımız senaryolarda) tetikleyici her zaman dışarıdaki bir pipeline aracıdır. Kod push edilir, testler koşar ve ardından runner gidip hedef sunucudaki API’ye veya SSH portuna vurarak yeni imajı ya da kod paketini deploy eder.

Bu yaklaşım, özellikle Kubernetes dışı bare-metal veya hibrit dağıtımlarda hayat kurtarır. Ancak bu modelin en büyük zayıflığı, hedef sunucuların erişim anahtarlarını (SSH key’ler, API token’lar, Kubernetes Kubeconfig dosyaları) CI/CD runner’ları üzerinde barındırmak zorunda olmamızdır. Bir müşteri projesinde, harici bir CI/CD servisinin hacklenmesi sonucu, runner üzerinde saklanan Kubernetes admin yetkili kubeconfig dosyasının sızdırılmasına ramak kalmıştı. Şans eseri IP kısıtlaması (egress filtering) sayesinde saldırganlar içeri sızamadı ama o günden sonra push tabanlı modelin güvenlik sınırlarını çok daha sıkı sorgulamaya başladım.

Aşağıdaki gibi tipik bir GitLab CI push deploy adımını ele alalım. Bu kod parçasında runner, hedef sunucuya SSH üzerinden bağlanarak Docker Compose komutlarını tetikliyor:

# .gitlab-ci.yml - Klasik Push Tabanlı Deploy
deploy_to_production:
  stage: deploy
  image: alpine:3.19
  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
    - echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
    - chmod 644 ~/.ssh/known_hosts
  script:
    - ssh deploy_user@$PRODUCTION_IP "cd /opt/app && docker compose pull && docker compose up -d"
  only:
    - main

Bu kod çalışıyor mu? Evet, yıllarca bu şekilde yüzlerce projeyi ayağa kaldırdım. Ancak buradaki en büyük risk, $SSH_PRIVATE_KEY değişkeninin güvenliğidir. Ayrıca hedef sunucunun SSH portunu (genellikle 22 veya değiştirdiyseniz başka bir portu) dış dünyaya ya da en azından CI runner IP’lerine açmak zorundasınız. Statik IP vermeyen bulut tabanlı runner servisleri kullanıyorsanız, firewall kurallarını yönetmek tam bir kabusa dönüşüyor.

GitOps ile Tanışma ve Pull Tabanlı Modelin Anatomisi

GitOps, push tabanlı modelin tam tersi bir felsefeyle çalışır. Altyapının ve uygulamaların istenen durumu (desired state) bir Git reposunda deklaratif olarak tutulur. Hedef sistemin içinde çalışan bir agent (örneğin ArgoCD veya Flux v2), sürekli olarak bu Git reposunu dinler. Git reposundaki durum ile mevcut durum (actual state) arasında bir fark (drift) oluştuğunda, agent bu farkı kapatmak için hedef sistemi günceller.

Bu yaklaşım, dışarıdan içeriye doğru bir erişim ihtiyacını tamamen ortadan kaldırır. Yani Kubernetes cluster’ınızın API portunu dış dünyaya kapatabilirsiniz. Cluster içindeki ArgoCD agent’ı, dışarıdaki Git reposuna outbound (egress) bağlantı kurarak değişiklikleri çeker (pull eder). Güvenlik açısından bu muazzam bir kazanımdır.

Ancak GitOps’un da kendine has karmaşaları vardır. Örneğin, ArgoCD 2.10+ üzerinde bir uygulamanın durumunu yönetirken karşılaştığım en büyük sorunlardan biri, helm chart’lardaki dinamik değerlerin senkronizasyon döngüsünü bozmasıydı. Aşağıdaki Kubernetes manifest dosyasında, GitOps agent’ının sürekli olarak Git reposunu izleyerek durumu nasıl eşitlediğini görebilirsiniz:

# argocd-application.yaml - GitOps Pull Tabanlı Model
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: production-erp-api
  namespace: argocd
spec:
  project: default
  source:
    repoURL: 'https://github.com/mustafaerbay/production-manifests.git'
    targetRevision: HEAD
    path: apps/erp-api
  destination:
    server: 'https://kubernetes.default.svc'
    namespace: production
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true

Bu modelde, uygulama geliştiricisi sadece kodu yazar ve imajı build edip registry’ye push eder. Ardından manifest reposundaki imaj tag’ini günceller. ArgoCD bu değişikliği algılar ve cluster içine yeni imajı dağıtır. Geliştiricinin veya CI pipeline’ının cluster’a erişim yetkisine ihtiyacı yoktur. Ancak bu durum, CI pipeline’ı ile CD sürecinin tamamen birbirinden kopmasına yol açar. CI pipeline’ının başarıyla bitmesi, uygulamanın gerçekten deploy edildiği anlamına gelmez. Sadece “manifest reposuna commit atıldı” anlamına gelir.

Danışmanlık Pratiğinde GitOps vs Push Tabanlı CI/CD Seçim Kriterleri

Danışmanlık yaptığım şirketlerde “en iyi teknoloji” diye bir şey olmadığını, sadece “uygun bütçe ve insan kaynağı ile yönetilebilir teknoloji” olduğunu defalarca gördüm. Bir startup’a gidip “Hadi hemen GitOps kuruyoruz, ArgoCD ile declarative cluster yönetimi yapacağız” derseniz, o ekibe iyilik değil kötülük yapmış olursunuz. Çünkü o startup’ın önceliği hızlıca pazar doğrulaması yapmaktır; Git reposundaki drift’leri çözmekle vakit kaybetmek değil.

Daha önce yazdığım VPS migration deneyimim yazısında da bahsettiğim gibi, operasyonel sadelik her zaman karmaşık mühendislik fantezilerinden daha değerlidir. Karar verirken kullandığım temel metrikleri ve trade-off’ları aşağıdaki tabloda özetledim:

Kriter Push Tabanlı CI/CD (GitLab/GitHub Actions) GitOps (ArgoCD/Flux)
İlk Kurulum Maliyeti Çok Düşük (Saatler içinde hazır olur) Yüksek (Cluster içi agent ve repo yapısı gerekir)
Güvenlik Sınırı Zayıf (CI aracına geniş yetkili key’ler verilir) Çok Güçlü (İçeriden dışarıya güvenli çekim)
Kubernetes Bağımlılığı Yok (VM, Bare-metal, Serverless destekler) Çok Yüksek (Genellikle K8s dünyasına özeldir)
Geri Alım (Rollback) Hızı Yavaş (Pipeline’ı tekrar tetiklemek gerekir) Çok Hızlı (Git revert veya UI üzerinden anlık rollback)
Hata Tespit Kolaylığı Kolay (Tüm loglar tek bir pipeline ekranındadır) Zor (Hatanın Git’te mi, agent’ta mı olduğunu bulmak gerekir)
Ekip Öğrenme Eğrisi Çok Düşük (Her yazılımcı push etmeyi bilir) Yüksek (K8s manifestleri ve GitOps akışı bilinmeli)

Eğer danışmanlık verdiğim firmanın altyapısı tamamen Kubernetes üzerinde koşmuyorsa, GitOps’u doğrudan eliyorum. Bare-metal sunucularda veya basit Docker Compose yapılarında GitOps uygulamaya çalışmak, tabiri caizse sinek öldürmek için balyoz kullanmaya benzer. Git üzerinde çalışan bazı “bare-metal GitOps” araçları olsa da, bunların bakım maliyeti (maintenance overhead) getirdiği faydadan çok daha fazladır.

Güvenlik ve Ağ Topolojisi Açısından Karşılaştırma

Güvenlik mimarisi tasarlarken her zaman en kötü senaryoyu düşünürüm. Push tabanlı modelde, CI runner’ınızın ele geçirilmesi durumunda tüm production ortamınız tehlikeye girer. Örneğin, GitLab Runner’ın çalıştığı sunucuya sızan bir saldırgan, environment variable’lar arasında duran AWS IAM key’lerini veya Kubernetes konfigürasyonlarını alıp tüm altyapınızı silebilir.

GitOps modelinde ise durum farklıdır. Saldırgan manifest reposunu ele geçirse bile, yapabileceği şeyler o manifest sınırları ile kısıtlıdır. Kubernetes içindeki ArgoCD, sadece kendi service account yetkileri dahilinde işlem yapabilir. Ayrıca ağ topolojisi açısından zero-trust mimarisine çok daha uygundur.

Aşağıdaki şemada, iki modelin ağ trafiği yönünü karşılaştırabilirsiniz:

PUSH TABANLI MODEL:
[CI/CD Runner] ---------- (Inbound: Port 22/6443) ----------> [Production Server]
(Dışarıdan içeriye doğru tehlikeli bir erişim yolu açılması gerekir)

GİTOPS (PULL) TABANLI MODEL:
[Production Server (ArgoCD Agent)] ---------- (Outbound: Port 443) ----------> [Git Repo]
(Dışarıdan içeriye erişim tamamen kapalıdır, sadece güvenli dışa doğru istekler yapılır)

Güvenliği bir adım öteye taşımak için Linux kernel hardening adımlarını da uygulamak gerekir. Örneğin, production ortamındaki GitOps agent’larının çalıştığı pod’ların veya container’ların yetkilerini kısıtlamak için AppArmor veya SELinux profilleri kullanıyorum. Ayrıca kernel düzeyinde gereksiz modülleri kara listeye (blacklist) alarak olası bir container breakout saldırısının önüne geçmeye çalışıyorum.

Bir Üretim ERP’sinde Yaşadığım Göç Hikayesi ve Çıkartılan Dersler

Bir dönem, yoğun olarak kullandığımız bir üretim ERP’sinin altyapısını modernize ediyorduk. Sistem, PostgreSQL veritabanı, FastAPI backend ve Vue frontend bileşenlerinden oluşuyordu. İlk başta her şey klasik push tabanlı CI/CD ile yönetiliyordu. GitLab runner’ları her commit’te Ansible playbook’larını tetikliyor ve sunucuları güncelliyordu.

Ancak üretim bandındaki operatör ekranlarının 7/24 kesintisiz çalışması gerekiyordu. Mesai saatlerinin tam ortasında yapılan bir deploy sırasında, Ansible playbook’unun SSH bağlantısı ağdaki anlık bir dalgalanma yüzünden koptu. Deploy yarıda kaldı. Sistem “half-deployed” durumuna düştü; veritabanı migrasyonu yapılmıştı ama backend kodunun sadece bir kısmı güncellenmişti. Operatör ekranları dondu ve üretim planlama modülü çöktü. Hatayı toparlayıp düzeltene kadar fabrikada sevkiyatlar epeyce bir süre durdu.

Bu krizden sonra tüm sistemi Kubernetes’e taşıma ve CD sürecini ArgoCD ile GitOps modeline geçirme kararı aldım. Bu göç süreci bize şu somut faydaları sağladı:

  1. Rollback Süresi: Eskiden hatalı bir deploy’u geri almak için GitLab pipeline’ının baştan tekrar çalışmasını beklemek zorundaydık. GitOps’a geçtikten sonra, ArgoCD arayüzünden tek bir tıkla (veya Git üzerinden bir önceki commit’e revert atarak) rollback’i neredeyse anlık hale getirdik.
  2. Sistem Kararlılığı: Network kopması veya runner çökmesi gibi durumlar artık deploy’u etkilemiyordu. ArgoCD, cluster içinde çalıştığı için ağ dalgalanmalarından bağımsız olarak durumu sürekli senkronize ediyordu.
  3. Log İzleme: Sorun çıktığında journald limitlerine takılmadan, doğrudan Kubernetes event’leri üzerinden hatayı yakalayabilir hale geldik.

Göç sonrası aldığımız hata loglarındaki azalmayı ve sistem kararlılığını izlemek için kullandığımız basit bir journalctl izleme çıktısı şu şekildeydi:

# GitOps sonrası senkronizasyon loglarının kontrolü
$ journalctl -u k3s -n 100 --no-pager | grep -i "argocd"
# çıktı ortama göre değişir; tipik olarak şuna benzer satırlar görürsünüz:
# argocd-application-controller: Comparing app 'production-erp-api' status
# argocd-application-controller: Resource 'apps/Deployment/production/erp-api' is Synced

Bu log satırları, sistemin kendi kendini iyileştirme (self-healing) mekanizmasının tıkır tıkır çalıştığının en büyük kanıtıydı. Manuel müdahaleye gerek kalmadan, dışarıdan yapılan hatalı bir değişiklik saniyeler içinde ezilerek doğru duruma getiriliyordu.

Hangisini Ne Zaman Seçmeli?

Eğer bir danışman olarak bana “Mustafa abi, projemizde hangisini kullanalım?” diye sorarsanız, size doğrudan şu soruları sorarım:

  1. Altyapınız Kubernetes mi? Cevap hayır ise, GitOps fantezisinden uzak durun. Push tabanlı modelle (GitLab CI, GitHub Actions, Jenkins) devam edin. Basit bir SSH tabanlı deploy veya Docker Compose tetiklemesi işinizi fazlasıyla görür. “Olur o kadar” deyip geçin, sistemi aşırı mühendislikle boğmayın.
  2. Ekibinizde özel bir platform/DevOps mühendisi var mı? GitOps araçlarının bakımı, drift analizleri ve secret yönetimi ciddi bir uzmanlık gerektirir. Eğer ekibiniz sadece yazılımcılardan oluşuyorsa, GitOps’un getireceği karmaşa ekibi yavaşlatacaktır. Push tabanlı modelde hata ayıklamak yazılımcılar için çok daha doğaldır.
  3. Güvenlik ve regülasyon gereksinimleriniz ne seviyede? Finansal teknolojiler, sağlık sistemleri veya sıkı denetlenen kurumsal yapılarda çalışıyorsanız, dışarıdan içeriye SSH/API erişimi açmak yasaktır. Bu durumda Kubernetes + GitOps (ArgoCD) tek mantıklı seçenektir.

Daha fazla teknik detay ve sistem mimarisi analizi için sistem güvenliği ve hardening konusunu inceleyebilirsiniz. Günün sonunda, en iyi araç en çok bildiğiniz ve production ortamında sorun çıktığında en hızlı debug edebildiğiniz araçtır. Altyapınızı modaya göre değil, ekibinizin kas hafızasına ve projenin gerçek ihtiyaçlarına göre şekillendirin.

Sonraki adım: Altyapınızdaki gizli güvenlik açıklarını bulmak için log analiz altyapınızı güçlendirin.

Paylaş:

Bu yazı faydalı oldu mu?

Yükleniyor...

Bu yazı nasıldı?

Sıkça Sorulanlar

Bu makale ile ilgili okurların sorduğu yaygın sorular.

GitOps ve Push tabanlı CI/CD arasında seçim yaparken nelere dikkat etmeliyim?
Benim deneyimime göre, seçim yaparken projenin ölçeği, kompleksitesi ve güvenlik gereksinimleri gibi faktörleri dikkate almalısınız. Ayrıca, ekiplerin uzmanlık düzeyini ve operasyonel yükü de göz önünde bulundurmalısınız. Örneğin, büyük ölçekli sistemlerde GitOps daha uygun olabilirken, küçük projelerde Push tabanlı CI/CD daha pratik olabilir.
Push tabanlı CI/CD yaklaşımının güvenlik açısından avantajları veya dezavantajları nelerdir?
Push tabanlı CI/CD'nin en büyük dezavantajı, hedef sunucuların erişim anahtarlarını CI/CD runner'ları üzerinde barındırmak zorunda olmamızdır. Bu, güvenlik riskleri yaratır. Ben bir müşteri projesinde, harici bir CI/CD servisinin hacklenmesi sonucu, runner üzerinde saklanan Kubernetes admin yetkili kubeconfig dosyasının sızdırılmasına ramak kalmıştı. Bu nedenle, güvenlik açısından GitOps gibi daha güvenli alternatifler düşünülmelidir.
GitOps yaklaşımını uygulamaya başlarken hangi araçları kullanmalıyım?
Ben GitOps uygulamalarımızda genellikle Kubernetes ve Git gibi araçları kullanıyorum. Ayrıca, Flux, Argo CD gibi özel GitOps araçlarını da kullanabilirsiniz. Bu araçlar, kaynak kodunuza dayalı olarak ortamınızı yönetmenize ve değişiklikleri takip etmenize yardımcı olur. Ancak, araç seçimi projenizin özel gereksinimlerine göre yapılmalıdır.
GitOps ve Push tabanlı CI/CD arasında performans açısından bir fark var mıdır?
Benim deneyimime göre, GitOps genellikle daha yüksek performans sağlar. Çünkü, GitOps'de ortam değişiklikleri kaynak kodunda yönetilir ve自动 olarak uygulanır. Bu, daha hızlı ve daha reliable bir deployment süreci sağlar. Push tabanlı CI/CD'de ise, her değişiklikten sonra>manual olarak deployment işlemleri yapılmaktadır. Bu nedenle, büyük ölçekli sistemlerde GitOps daha uygun olabilir.
ME

Mustafa Erbay

Sistem Mimarisi · Network Uzmanı · Altyapı, Güvenlik ve Yazılım

2006'dan bu yana sistem mimarisi, network, sunucu altyapıları, büyük yapıların kurulumu, yazılım ve sistem güvenliği ekseninde çalışıyorum. Bu blogda sahada karşılığı olan teknik deneyimlerimi paylaşıyorum.

Kişisel Notlar

Bu notlar sadece sizde saklanır. Tarayıcınızda yerel olarak tutulur.

Hazır 0 karakter

Yorumlar

Sunucu Taraflı AI Moderasyon

Yorumlar sunucuda yapay zeka ile denetlenir ve kalıcı olarak saklanır.

?
0/2000

Sunucu taraflı AI denetim

✉️ Ücretsiz · Spam yok · İstediğin an çık

Yeni yazılardan haberdar olun

Yeni içerikler ve teknik notlar e-postanıza gelsin.

  • 📌
    Haftanın en iyisi Sadece okumaya değer tek yazı
  • 🔧
    Alet çantası Bu hafta kullandığım araçlar
  • 🧠
    Perde arkası Blog'a girmeyen notlar

Spam yapmıyoruz. İstediğiniz zaman ayrılabilirsiniz. · Sadece Umami (self-hosted, Google yok) ile takip.

Okuma İstatistikleriniz

0

Yazı Okundu

0dk

Okuma Süresi

0

Gün Serisi

-

Favori Kategori

İlgili Yazılar