Yeşil DevOps: CI/CD Pipeline’larınızın Karbon Ayak İzini Nasıl Takip Edersiniz?
Modern mühendislik ekipleri olarak FinOps dashboard’larına bakıp AWS faturasından yüzde üç kırpınca kendimizi zafer kazanmış sayıyoruz. Oysa altyapı maliyetini optimize ederken gözden kaçırdığımız daha somut bir parametre var: Watt tüketimi. CI/CD süreçlerimizin tükettiği enerji ve açığa çıkardığı karbon ayak izi, artık doğrudan ölçülebilir bir mühendislik metriği. Carbon-Aware DevOps yaklaşımı bu süreci “ağaç diktik” sertifikalarından çıkarıp doğrudan pipeline konfigürasyonlarına, Prometheus metriklerine ve eBPF seviyesine indiriyor.
Her PR açıldığında tetiklenen büyük entegrasyon testleri, gereksiz katman inşa eden Docker build’leri ve 32 vCPU’luk runner’larda 2 dakika koşan linter’lar yalnızca fatura değil, şebekeden doğrudan kirli elektrik de tüketiyor. Bu tüketimi hissi yaklaşımlarla değil, production-grade araçlarla nasıl ölçer ve optimize ederiz?
SCI (Software Carbon Intensity) ve ölçüm mantığı
Green Software Foundation’ın standartlaştırdığı SCI spesifikasyonu karmaşık bir fizik denklemi değil. Bir CI/CD pipeline’ı için denklemi şöyle özetleyebiliriz:
SCI = ((E * I) + M) / R
- E (Energy): Pipeline çalışırken harcanan toplam enerji (kWh).
- I (Location-Based Carbon Intensity): İşlemin yapıldığı veri merkezinin bağlı olduğu elektrik şebekesindeki emisyon oranı (gCO2eq/kWh).
- M (Embodied Carbon): Sunucu donanımının üretimi ve bertarafından düşen amortisman payı.
- R (Functional Unit): Bizim durumumuzda tek bir “Pipeline Run”, “Build Başına PR” veya “Deployment”.
Geliştirici ortamında M parametresini çoğunlukla sabit kabul ederiz. Doğrudan müdahale edebileceğimiz iki değişken var: Harcanan enerji (E) ve bu enerjinin tüketildiği andaki grid karbon yoğunluğu (I).
Runner seviyesinde enerji tüketimini ölçmek: Kepler ve eBPF
Self-hosted runner kullanıyorsanız (Kubernetes üzerinde Actions Runner Controller, yani ARC, ya da GitLab Runner), bare-metal veya sanal makine seviyesindeki enerji tüketimini RAPL (Running Average Power Limit) sayaçları ve eBPF ile pod bazında ayrıştırabilirsiniz. Sektör standardı araç Kepler (Kubernetes-based Efficient Power Level Exporter).
Kepler, eBPF tracing ile CPU döngülerini ve bellek erişimlerini pod ve container seviyesinde dinler, ardından RAPL arayüzünden okunan watt değerini bu metriklerle ilişkilendirir. Kubernetes tabanlı runner kümenize Kepler’i Helm ile deploy etmek oldukça kolay:
helm repo add kepler https://sustainable-computing-io.github.io/kepler-helm-chart
helm repo update
helm install kepler kepler/kepler \
--namespace kepler-system \
--create-namespace \
--set serviceMonitor.enabled=true \
--set canMount.usrSrc=true
Kepler ayağa kalktıktan sonra CI runner’larınızın namespace’i için anlık tüketimi Prometheus üzerinden Joule cinsinden sorgulayabilirsiniz. Tek bir pipeline pod’unun toplam enerji tüketimini (kWh cinsinden) çıkarmak için şu PromQL sorgusu işinizi görür:
# Belirli bir CI pod'unun tükettiği toplam enerji (kWh)
sum(
increase(kepler_container_joules_total{container_namespace="ci-runners", pod_name=~"runner-build-.*"}[1h])
) / 3600000
3.600.000’e bölmemizin nedeni Joule’ü kWh’a çevirmek. Artık elinizde soyut bir “build 8 dakika sürdü” verisi değil, “bu build 0.042 kWh tüketti” metriği var.
Carbon-aware scheduling: Testleri ne zaman koşmalı?
CI pipeline’larını yalnızca “hızlı bitsin” diye tasarlamak yerine işin doğasına göre sınıflandırmak gerekir. Kritik bir hotfix PR’ı hemen koşmalıdır. Nightly build’ler, periyodik regression testleri veya end-to-end sentetik yük testleri ise zamana duyarlı değildir. Carbon-Aware Execution burada devreye girer.
Elektrik şebekesindeki karbon yoğunluğu rüzgar ve güneş üretimine göre gün içinde radikal biçimde değişir. Örneğin Almanya (eu-central-1) şebekesi öğlen saatlerinde güneş panelleri devredeyken 150 gCO2eq/kWh seviyesindeyken, akşam rüzgar kesildiğinde ve kömür devreye girdiğinde 600 gCO2eq/kWh seviyesine fırlayabilir.
Aşağıdaki GitHub Actions workflow örneğinde Electricity Maps API’sini kullanarak o anki grid karbon yoğunluğunu sorguluyoruz. Emisyon eşik değerin üzerindeyse ve acil olmayan bir batch job koşuyorsak build’i postpone ediyoruz veya düşük karbonlu bir bölgedeki runner’a route ediyoruz:
name: Carbon-Aware Integration Suite
on:
schedule:
- cron: '0 * * * *' # Saatlik tetikleme
workflow_dispatch:
jobs:
check-carbon-intensity:
runs-on: ubuntu-latest
outputs:
should_run: ${{ steps.carbon_check.outputs.should_run }}
steps:
- name: Fetch Carbon Intensity
id: carbon_check
env:
EMAPS_API_TOKEN: ${{ secrets.ELECTRICITY_MAPS_TOKEN }}
ZONE: "DE" # Almanya şebekesi
THRESHOLD: 250 # gCO2eq/kWh sınırı
run: |
RESPONSE=$(curl -s -H "auth-token: $EMAPS_API_TOKEN" \
"https://api.electricitymap.org/v3/carbon-intensity/latest?zone=$ZONE")
INTENSITY=$(echo $RESPONSE | jq '.carbonIntensity')
echo "Güncel Karbon Yoğunluğu: $INTENSITY gCO2eq/kWh"
if [ "$INTENSITY" -lt "$THRESHOLD" ]; then
echo "Şebeke temiz. Pipeline çalıştırılıyor."
echo "should_run=true" >> $GITHUB_OUTPUT
else
echo "Şebeke kirli. Ağır testler erteleniyor."
echo "should_run=false" >> $GITHUB_OUTPUT
fi
heavy-tests:
needs: check-carbon-intensity
if: needs.check-carbon-intensity.outputs.should_run == 'true'
runs-on: arc-runner-set
steps:
- uses: actions/checkout@v4
- name: Run E2E Tests
run: make test-e2e
Neden böyle yapıyoruz?
Saatte 200 kWh tüketen büyük bir staging test kümeniz varsa, yalnızca çalıştırma saatini kaydırarak (carbon-shifting) pipeline altyapısına tek satır kod optimizasyonu yapmadan emisyonu yüzde 40 ila 60 oranında azaltabilirsiniz. Bu, production iş yüklerini taşımaktan çok daha risksiz ve anında etki eden bir yöntemdir.
Pipeline seviyesinde optimizasyon: Boşa yanan CPU döngülerini kesmek
Yalnızca zamanlama yetmez. Tüketilen ham enerjiyi (E) kısmak için pipeline anatomisini elden geçirmek gerekir. Tipik kurumsal CI/CD süreçlerinde en çok enerji israfına yol açan pratikler ve çözümleri şunlardır:
1. Docker katman önbelleği (BuildKit cache thrashing)
CI ortamında her build’de sıfırdan pip install veya npm ci yapmak yalnızca pipeline süresini uzatmaz, runner üzerinde disk I/O ve network adaptörü aracılığıyla gereksiz CPU watt tüketimi de üretir. GitHub Actions Cache veya harici S3/Registry cache backend kullanmak doğrudan enerji tasarrufudur.
# Kaniko veya Buildx ile GitHub Actions Cache backend kullanımı
docker buildx build \
--cache-to type=gha,mode=max \
--cache-from type=gha \
--tag my-service:${{ github.sha }} \
--file Dockerfile .
mode=max kullanımı yalnızca son imajı değil, ara katmanları da saklar. Böylece multi-stage build’lerde dependency stage’i değişmediği sürece CPU neredeyse rölanti modunda kalır.
2. Mimari değişimi: x86_64 yerine ARM64 runner’lar
AWS Graviton veya Ampere Altra tabanlı ARM64 instance’lar, modern Intel/AMD eşdeğerlerine kıyasla Watt başına kayda değer oranda daha yüksek işlem kapasitesi sunar (Performance-per-Watt). CI/CD runner filolarınızı ARM mimarisine taşımak, build sürelerini dramatik olarak değiştirmese bile tüketilen toplam enerjiyi yüzde 20-30 oranında aşağı çeker.
Aşağıdaki gibi basit bir Docker buildx multi-arch matrix konfigürasyonu yerine derlemeyi doğrudan hedef donanımda (native) yapmak CPU emülasyon maliyetini (QEMU overhead) ortadan kaldırır:
# QEMU üzerinden emüle edilmiş ARM build (YÜKSEK ENERJİ TÜKETİMİ - KAÇININ)
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
docker buildx build --platform linux/arm64 -t app:latest .
# DOĞRU YAKLAŞIM: Native ARM64 Runner ayağa kaldırıp doğrudan derlemek
# GitHub Actions: runs-on: [self-hosted, linux, arm64]
Emülasyonla derleme yapmak CPU döngülerini 4 ila 10 kat artırarak ciddi bir enerji israfı yaratır. Build’i native runner’a devretmek doğrudan watt tasarrufudur.
Emisyon verisini PR seviyesine indirmek
Mühendise geri bildirim vermediğiniz hiçbir metrik iyileşmez. Code-coverage raporu veya lint hatası gibi, her pull request’in ne kadar karbon emisyonuna yol açtığını PR yorumu olarak basmak ekip kültürünü değiştirir. Açık kaynak araçlardan Eco-CI bu iş için doğrudan GitHub Actions içine entegre olabilen hazır step’ler sağlar:
steps:
- name: Eco-CI Init
uses: green-coding-solutions/eco-ci-energy-estimation@v4
with:
task: start-measurement
- name: Build and Test Project
run: |
mvn clean verify
- name: Eco-CI Measurement
uses: green-coding-solutions/eco-ci-energy-estimation@v4
with:
task: get-measurement
label: 'Maven Test Suite'
- name: Eco-CI PR Comment
uses: green-coding-solutions/eco-ci-energy-estimation@v4
with:
task: display-results
send-pr-comment: true
Bu konfigürasyon, GitHub API üzerinden PR altına çalıştırılan donanımın ortalama enerji katsayılarına göre tüketilen kWh ve üretilen CO2eq gramajını yazar. Bir geliştirici, yazdığı verimsiz bir integration testinin pipeline süresini 10 dakika uzatmasının yalnızca kendisini değil, ölçülebilir bir emisyonu da tetiklediğini gördüğünde optimizasyon soyut bir hedef olmaktan çıkar.
Sonuç: FinOps ve GreenOps ayrımı ortadan kalkıyor
Yeşil DevOps, marjinal bir çevreci PR çalışması değil, modern sistem mimarisinin kaçınılmaz bir optimizasyon evresidir. Pipeline’larınızdaki CPU kullanımını optimize etmek, katmanları doğru önbelleğe almak, runner’ları doğru mimariye geçirmek ve zamana duyarsız işleri şebekenin temiz olduğu anlara kaydırmak teknik borcu azaltır. Daha az CPU döngüsü, daha az fatura ve nihayetinde daha düşük bir karbon ayak izi demektir.