Jenkins Master-Agent Mimarisi: Dağıtık Build Ortamı Kurulumu ve Yönetimi

Büyük ölçekli projelerde tek bir Jenkins sunucusu üzerinde onlarca pipeline çalıştırmaya çalışmak, bir noktada kaçınılmaz olarak performans sorunlarına yol açar. Build kuyruğu uzar, sunucu kaynakları tükenir ve ekipler birbirini bekler hale gelir. İşte bu noktada Jenkins’in Master-Agent mimarisi devreye girer. Dağıtık build ortamı kurarak hem yükü dağıtabilir hem de farklı platformlarda (Linux, Windows, macOS) aynı anda build çalıştırabilirsin.

Master-Agent Mimarisi Nedir?

Jenkins’te Master (artık resmi dokümanlarda “Controller” olarak da geçer) merkezi yönetim noktasıdır. Build tanımlarını saklar, iş akışlarını koordine eder ve web arayüzünü sunar. Agent (eski adıyla Slave) ise asıl işi yapan, build komutlarını koşturan makinelerdir.

Bu mimarinin temel mantığı şudur: Master, ne yapılacağını bilir; Agent, nasıl yapıldığını uygular. Master kendisi mümkün olduğunca az iş yapar, asıl yükü Agent’lara devreder. Böylece 10, 20, hatta 100 Agent’ı aynı anda çalıştırarak paralel build kapasiteni uçsuz bucaksız artırabilirsin.

Gerçek dünya senaryosunda bir e-ticaret firmasını ele alalım: Frontend ekibi Node.js build için bir Agent, backend ekibi Java/Maven build için başka bir Agent, mobil ekip Android build için ayrı bir Agent kullanıyor olabilir. Tümünü tek bir Master üzerinden yönetirsin ama her biri kendi ortamında bağımsızca çalışır.

Kurulum Öncesi Gereksinimler

Master ve Agent makineler arasında ağ bağlantısı olması zorunludur. Bağlantı yöntemine göre SSH veya JNLP (Java Web Start) portlarının açık olması gerekir. Minimum gereksinimler şunlardır:

  • Master sunucu: En az 4 GB RAM, 2 CPU core, 50 GB disk (build artifact’ları için)
  • Agent sunucu: Çalıştıracağın build türüne göre değişir, en az 2 GB RAM, 2 CPU core
  • Java: Her iki tarafta da uyumlu JDK sürümü (Jenkins 2.361+ için Java 11 veya 17)
  • SSH erişimi: Master’dan Agent’a şifresiz SSH bağlantısı (SSH metodu için)

Master Sunucusunun Kurulumu

Önce Master sunucunu hazırla. Ubuntu 22.04 üzerinde kurulum yapıyoruz:

# Java kurulumu
sudo apt update
sudo apt install -y openjdk-17-jdk

# Jenkins repo ekleme
curl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key | sudo tee 
  /usr/share/keyrings/jenkins-keyring.asc > /dev/null

echo deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] 
  https://pkg.jenkins.io/debian-stable binary/ | sudo tee 
  /etc/apt/sources.list.d/jenkins.list > /dev/null

sudo apt update
sudo apt install -y jenkins

# Servisi başlat ve etkinleştir
sudo systemctl enable jenkins
sudo systemctl start jenkins

# İlk admin şifresini al
sudo cat /var/lib/jenkins/secrets/initialAdminPassword

Jenkins kurulduktan sonra http://master-ip:8080 adresine gidip kurulum sihirbazını tamamla. “Suggested plugins” seçeneğiyle devam edebilirsin, gerekli ek plugin’leri sonradan yükleyeceksin.

Agent Makinesinin Hazırlanması

Agent makinesinde Java kurulumu yapman yeterli, Jenkins’i kurman gerekmez. Agent, Master’ın göndereceği agent.jar dosyasıyla çalışır.

# Agent makinesinde Java kurulumu
sudo apt update
sudo apt install -y openjdk-17-jdk

# Jenkins için özel kullanıcı oluştur
sudo useradd -m -s /bin/bash jenkins
sudo mkdir -p /home/jenkins/workspace
sudo chown -R jenkins:jenkins /home/jenkins

# Build araçlarını kur (projeye göre değişir)
# Örnek: Maven kurulumu
sudo apt install -y maven

# Örnek: Node.js kurulumu
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt install -y nodejs

# Docker kurulumu (eğer container build yapacaksan)
sudo apt install -y docker.io
sudo usermod -aG docker jenkins

SSH ile Agent Bağlantısı Kurma

SSH metodu, production ortamları için en güvenilir ve yaygın kullanılan yöntemdir. Master’dan Agent’a şifresiz SSH bağlantısı kurman gerekir.

# Master makinesinde Jenkins kullanıcısı olarak SSH key oluştur
sudo su - jenkins
ssh-keygen -t ed25519 -C "jenkins-master" -f ~/.ssh/id_ed25519 -N ""

# Public key'i görüntüle
cat ~/.ssh/id_ed25519.pub

# Bu çıktıyı Agent makinesine kopyala
# Agent makinesinde jenkins kullanıcısı olarak:
sudo su - jenkins
mkdir -p ~/.ssh
chmod 700 ~/.ssh
echo "BURAYA_PUBLIC_KEY_YAPISTIR" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

# Master'dan bağlantıyı test et
ssh -i ~/.ssh/id_ed25519 jenkins@agent-ip-adresi

Bağlantı test ettikten sonra Jenkins web arayüzüne geç. Manage Jenkins > Nodes > New Node yolunu izle.

Node konfigürasyon sayfasında şu ayarları yap:

  • Node name: linux-agent-01 (anlamlı bir isim ver)
  • Number of executors: 2 (Agent’ın aynı anda kaç build çalıştırabileceği)
  • Remote root directory: /home/jenkins
  • Labels: linux maven java (pipeline’larda bu etiketlerle Agent seçersin)
  • Usage: Only build jobs with label expressions matching this node
  • Launch method: Launch agents via SSH
  • Host: Agent’ın IP adresi
  • Credentials: SSH private key eklemen gerekecek

Credentials eklemek için Add > Jenkins seçip “SSH Username with private key” türünü seç. Username olarak jenkins, private key olarak Master’daki ~/.ssh/id_ed25519 içeriğini yapıştır.

JNLP ile Agent Bağlantısı (Inbound Agent)

Bazen Agent makinesi bir güvenlik duvarının arkasında olabilir ve Master’ın SSH ile Agent’a erişmesi mümkün olmayabilir. Bu durumda JNLP (inbound agent) yöntemi kullanılır: Agent, Master’a bağlanır.

# Jenkins web arayüzünden agent oluşturduktan sonra
# Agent makinesinde aşağıdaki komutu çalıştır:
# Manage Jenkins > Nodes > agent-adı > Launch agent'tan komutu kopyala

curl -sO http://master-ip:8080/jnlpJars/agent.jar

java -jar agent.jar 
  -url http://master-ip:8080/ 
  -secret BURAYA_SECRET_TOKEN 
  -name "windows-agent-01" 
  -workDir "/home/jenkins"

Bunu systemd servisi olarak çalıştırmak için:

# /etc/systemd/system/jenkins-agent.service
sudo tee /etc/systemd/system/jenkins-agent.service > /dev/null <<EOF
[Unit]
Description=Jenkins Agent
After=network.target

[Service]
User=jenkins
WorkingDirectory=/home/jenkins
ExecStart=/usr/bin/java -jar /home/jenkins/agent.jar 
  -url http://master-ip:8080/ 
  -secret BURAYA_SECRET_TOKEN 
  -name "linux-agent-02" 
  -workDir "/home/jenkins"
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable jenkins-agent
sudo systemctl start jenkins-agent

Docker Agent ile Dinamik Ortamlar

Modern CI/CD pipeline’larında her build için temiz bir Docker container kullanmak en iyi pratiklerden biridir. Docker Plugin ile bunu kolayca sağlayabilirsin.

Önce Master’a Docker Plugin ve Docker Pipeline Plugin kurmalısın. Ardından Manage Jenkins > Clouds > New Cloud > Docker seçeneğiyle Docker host’u tanımla.

Docker içinde çalışacak bir örnek Jenkinsfile:

pipeline {
    agent {
        docker {
            image 'maven:3.9-eclipse-temurin-17'
            label 'linux'
            args '-v /root/.m2:/root/.m2'
        }
    }
    stages {
        stage('Build') {
            steps {
                sh 'mvn clean package -DskipTests'
            }
        }
        stage('Test') {
            steps {
                sh 'mvn test'
            }
        }
        stage('Package') {
            steps {
                archiveArtifacts artifacts: 'target/*.jar', fingerprint: true
            }
        }
    }
    post {
        always {
            junit 'target/surefire-reports/*.xml'
            cleanWs()
        }
    }
}

Label Tabanlı Agent Seçimi

Gerçek dünya senaryosunda farklı projeler farklı Agent’lar üzerinde çalışmalıdır. Label sistemi bu konuda kritik öneme sahiptir.

Diyelim ki üç tür Agent’ın var:

  • linux-agent-01: linux, java, maven etiketleri
  • linux-agent-02: linux, nodejs, frontend etiketleri
  • windows-agent-01: windows, dotnet, msbuild etiketleri

Pipeline’larında bu etiketleri şöyle kullanırsın:

pipeline {
    agent none
    stages {
        stage('Backend Build') {
            agent {
                label 'linux && maven'
            }
            steps {
                sh 'mvn clean install'
            }
        }
        stage('Frontend Build') {
            agent {
                label 'linux && nodejs'
            }
            steps {
                sh 'npm ci && npm run build'
            }
        }
        stage('Windows Tests') {
            agent {
                label 'windows && dotnet'
            }
            steps {
                bat 'dotnet test'
            }
        }
    }
}

agent none direktifi ile pipeline başlar, her stage kendi ihtiyacına göre uygun Agent’ı seçer. Bu sayede paralel çalışma imkanı da doğar.

Güvenlik ve İzin Yönetimi

Master-Agent mimarisinde güvenlik ciddi bir konudur. Agent’ların ne kadar yetkiye sahip olduğunu sınırlamak önemlidir.

Manage Jenkins > Security > Agent Protocols altında sadece ihtiyaç duyduğun protokolleri etkin bırak. Güncel Jenkins sürümlerinde Remoting tabanlı eski protokoller devre dışı bırakılmalıdır.

# Master'da Jenkins yapılandırma dosyasını düzenle
sudo nano /etc/default/jenkins

# Aşağıdaki JVM argümanını ekle
JAVA_ARGS="-Djava.awt.headless=true 
  -Djenkins.security.SystemReadPermission=true 
  -Dhudson.model.DownloadService.noSignatureCheck=false"

Agent makinelerinde filesystem izinlerini doğru ayarla:

# Agent üzerinde workspace dizini için doğru izinler
sudo chown -R jenkins:jenkins /home/jenkins/workspace
sudo chmod 755 /home/jenkins
sudo chmod 750 /home/jenkins/workspace

# Hassas dosyalara erişimi kısıtla
sudo chmod 700 /home/jenkins/.ssh
sudo chmod 600 /home/jenkins/.ssh/authorized_keys

Agent’ların İzlenmesi ve Bakımı

Onlarca Agent’ı yönetirken otomasyon şart. Aşağıdaki script, Agent durumlarını kontrol ederek çevrimdışı olanları raporlar:

#!/bin/bash
# check-jenkins-agents.sh
# Jenkins API ile agent durumlarını kontrol eder

JENKINS_URL="http://master-ip:8080"
JENKINS_USER="admin"
JENKINS_TOKEN="your-api-token"

echo "=== Jenkins Agent Durum Raporu ==="
echo "Tarih: $(date)"
echo ""

curl -s -u "${JENKINS_USER}:${JENKINS_TOKEN}" 
  "${JENKINS_URL}/computer/api/json?pretty=true" | 
  python3 -c "
import json, sys

data = json.load(sys.stdin)
computers = data['computer']

print(f'Toplam Agent: {len(computers)}')
print('---')

for c in computers:
    name = c['displayName']
    offline = c['offline']
    executors = c['numExecutors']
    reason = c.get('offlineCauseReason', '')
    
    status = 'CEVRIMDISI' if offline else 'CEVRIMICI'
    print(f'{name}: {status} | Executor: {executors}')
    if offline and reason:
        print(f'  Sebep: {reason}')
"

# Disk kullanımını da kontrol et
echo ""
echo "=== Disk Kullanimi ==="
ssh jenkins@agent-01-ip "df -h /home/jenkins"
ssh jenkins@agent-02-ip "df -h /home/jenkins"

Bu scripti cron ile düzenli çalıştırabilirsin:

# Her 15 dakikada bir çalıştır
*/15 * * * * /opt/scripts/check-jenkins-agents.sh >> /var/log/jenkins-agent-check.log 2>&1

Workspace Temizleme Stratejisi

Agent’larda disk dolması yaygın bir sorundur. Her projede workspace’i temizlemek için Jenkinsfile’a cleanWs() eklemek temel önlemdir. Fakat daha kapsamlı bir yaklaşım gerekir:

pipeline {
    agent { label 'linux' }
    options {
        // 10 günden eski build'leri sil
        buildDiscarder(logRotator(daysToKeepStr: '10', numToKeepStr: '20'))
        // Her build'de workspace temizle
        skipDefaultCheckout(false)
    }
    stages {
        stage('Build') {
            steps {
                checkout scm
                sh 'mvn clean package'
            }
        }
    }
    post {
        always {
            // Build bittikten sonra workspace'i temizle
            cleanWs(
                cleanWhenNotBuilt: false,
                cleanWhenAborted: true,
                cleanWhenFailure: true,
                cleanWhenSuccess: true,
                cleanWhenUnstable: true,
                deleteDirs: true
            )
        }
    }
}

Yaygın Sorunlar ve Çözümleri

Agent bağlanamıyor sorunu: En sık karşılaşılan problem SSH bağlantı hatasıdır. Master makinesinde Jenkins kullanıcısının known_hosts dosyasını kontrol et:

sudo su - jenkins
ssh-keyscan -H agent-ip >> ~/.ssh/known_hosts

Java sürüm uyumsuzluğu: Master ve Agent’ta farklı Java sürümleri olabilir. Her iki makinede de sürümü kontrol et:

# Her iki makinede
java -version
# Aynı major sürümde olmalarına dikkat et (her ikisi de 17 gibi)

Build executor sayısı optimizasyonu: Bir Agent’ta kaç executor çalıştıracağın CPU core sayısıyla ilgilidir. Genel kural olarak CPU core sayısı + 1 executor ayarlayabilirsin. Yoğun I/O işlemleri için daha fazla, CPU yoğun işlemler için daha az executor tercih et.

Agent offline kalıyor: Ağ kesintilerinde JNLP agent’ların yeniden bağlanması için systemd servisi Restart=always ile yapılandırılmış olmalı. SSH agent’lar için Master otomatik yeniden bağlantı dener, timeout sürelerini Manage Jenkins > Nodes > Advanced altından ayarlayabilirsin.

Kubernetes ile Dinamik Agent Scaling

İleri seviye bir senaryo olarak Kubernetes üzerinde dinamik agent’lar çalıştırmak mümkündür. Kubernetes Plugin ile her build için bir pod oluşturulur, build biter bitmez pod silinir. Bu yaklaşım kaynak kullanımını optimize eder.

pipeline {
    agent {
        kubernetes {
            yaml """
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: maven
    image: maven:3.9-eclipse-temurin-17
    command:
    - sleep
    args:
    - infinity
    resources:
      requests:
        memory: "512Mi"
        cpu: "500m"
      limits:
        memory: "1Gi"
        cpu: "1"
  - name: docker
    image: docker:24-dind
    securityContext:
      privileged: true
"""
        }
    }
    stages {
        stage('Build') {
            steps {
                container('maven') {
                    sh 'mvn clean package'
                }
            }
        }
        stage('Docker Build') {
            steps {
                container('docker') {
                    sh 'docker build -t myapp:${BUILD_NUMBER} .'
                }
            }
        }
    }
}

Sonuç

Jenkins Master-Agent mimarisi, büyüyen CI/CD ihtiyaçlarını karşılamak için vazgeçilmez bir yapıdır. Tek bir sunucunun sınırlamalarından kurtularak hem paralel build kapasitesi hem de platform çeşitliliği elde edersin. SSH tabanlı statik agent’larla başlayıp zamanla Docker veya Kubernetes tabanlı dinamik agent’lara geçmek, olgun bir CI/CD yolculuğunun doğal evrimi olarak görülebilir.

Kurulumda dikkat etmen gereken kritik noktalar şunlardır: label yönetimini baştan iyi planla, workspace temizleme stratejini erken uygula, agent durumlarını izlemeyi otomatize et ve güvenlik ayarlarını atlama. Bu temeller sağlam kurulduğunda, on kişilik bir ekibin CI/CD altyapısını da yüz kişilik bir mühendis organizasyonunun altyapısını da aynı prensipler üzerinde yönetebilirsin.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir