Blue Ocean ile Modern Jenkins Pipeline Görselleştirme
Jenkins’i ilk kurduğumda pipeline’ları yönetmek gerçekten bir kabustu. Onlarca stage, paralel çalışan joblar, hata ayıklamak için log dosyalarını satır satır okumak… Sonra Blue Ocean ile tanıştım ve her şey değişti. Eğer hala klasik Jenkins arayüzünde boğuşuyorsanız, bu yazı tam size göre.
Blue Ocean Nedir ve Neden Önemlidir
Blue Ocean, Jenkins için geliştirilen modern bir kullanıcı arayüzü eklentisidir. Atlassian, CloudBees ve Jenkins topluluğunun birlikte yürüttüğü bu proje, klasik Jenkins’in karmaşık ve kullanıcı dostu olmayan arayüzünün yerine görsel, sezgisel bir deneyim sunmayı hedefler.
Klasik Jenkins arayüzünde bir pipeline hatası aldığınızda ne yaparsınız? Muhtemelen “Console Output” linkine tıklar, binlerce satır logu okumaya çalışırsınız. Blue Ocean’da ise hangi stage’in patladığını, tam olarak hangi adımda durduğunu ve hata mesajını saniyeler içinde görebilirsiniz.
Blue Ocean’ın getirdiği temel yenilikler:
- Pipeline’ları görsel akış diyagramı olarak göstermek
- Paralel stage’leri yan yana görselleştirmek
- Her step için ayrı log görünümü
- Git entegrasyonu ile branch ve PR yönetimi
- Modern ve responsive bir arayüz
Kurulum ve Ön Hazırlık
Blue Ocean’ı kurmadan önce Jenkins’inizin hazır olduğundan emin olun. Ben genellikle LTS sürümünü öneriyorum, çünkü eklenti uyumluluğu çok daha istikrarlı.
# Jenkins LTS kurulumu (Ubuntu/Debian)
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-get update
sudo apt-get install -y jenkins
# Java 17 kurulumu (Jenkins için gerekli)
sudo apt-get install -y openjdk-17-jdk
# Jenkins servisini başlat
sudo systemctl enable jenkins
sudo systemctl start jenkins
sudo systemctl status jenkins
Jenkins kurulumu tamamlandıktan sonra Blue Ocean eklentisini yüklemenin birkaç yolu var. En kolay yol Jenkins Plugin Manager üzerinden yapmak, ama production ortamlarında CLI üzerinden yapmayı tercih ediyorum.
# Jenkins CLI ile Blue Ocean kurulumu
# Önce jenkins-cli.jar dosyasını indir
wget http://localhost:8080/jnlpJars/jenkins-cli.jar
# Blue Ocean eklenti paketini kur
java -jar jenkins-cli.jar -s http://localhost:8080/
-auth admin:YOUR_API_TOKEN
install-plugin blueocean
# Jenkins'i yeniden başlat
java -jar jenkins-cli.jar -s http://localhost:8080/
-auth admin:YOUR_API_TOKEN
safe-restart
Eğer Docker ile Jenkins kullanıyorsanız, ki production dışı ortamlar için bu yöntemi şiddetle tavsiye ederim, aşağıdaki yaklaşım işinizi görecektir:
# Docker ile Blue Ocean dahil Jenkins
docker run -d
--name jenkins-blueocean
--restart=on-failure
-p 8080:8080
-p 50000:50000
-v jenkins_home:/var/jenkins_home
-v /var/run/docker.sock:/var/run/docker.sock
jenkinsci/blueocean:latest
# Container loglarını kontrol et
docker logs -f jenkins-blueocean
# Jenkins initial admin password'ü al
docker exec jenkins-blueocean
cat /var/jenkins_home/secrets/initialAdminPassword
İlk Pipeline’ı Oluşturmak
Blue Ocean’a erişmek için tarayıcınızda http://YOUR_JENKINS_URL/blue adresine gidin. Klasik arayüzden de “Open Blue Ocean” butonuna tıklayabilirsiniz.
Şimdi gerçek dünya senaryosuna geçelim. Diyelim ki bir Node.js uygulamanız var ve bunu Blue Ocean üzerinden görselleştirmek istiyorsunuz. Önce Jenkinsfile’ınızı hazırlayalım:
// Jenkinsfile - Node.js Uygulama Pipeline
pipeline {
agent {
docker {
image 'node:18-alpine'
args '-p 3000:3000'
}
}
environment {
NODE_ENV = 'production'
DOCKER_REGISTRY = 'your-registry.example.com'
APP_NAME = 'nodejs-app'
}
stages {
stage('Checkout') {
steps {
checkout scm
echo "Branch: ${env.GIT_BRANCH}"
echo "Commit: ${env.GIT_COMMIT}"
}
}
stage('Install Dependencies') {
steps {
sh 'npm ci --prefer-offline'
sh 'npm audit --audit-level=high'
}
}
stage('Lint ve Format Check') {
parallel {
stage('ESLint') {
steps {
sh 'npm run lint'
}
}
stage('Prettier') {
steps {
sh 'npm run format:check'
}
}
stage('TypeScript Check') {
steps {
sh 'npm run type-check'
}
}
}
}
stage('Test') {
parallel {
stage('Unit Tests') {
steps {
sh 'npm run test:unit -- --ci --coverage'
}
post {
always {
publishHTML([
allowMissing: false,
alwaysLinkToLastBuild: true,
keepAll: true,
reportDir: 'coverage',
reportFiles: 'index.html',
reportName: 'Coverage Report'
])
}
}
}
stage('Integration Tests') {
steps {
sh 'npm run test:integration'
}
}
}
}
stage('Build') {
steps {
sh 'npm run build'
archiveArtifacts artifacts: 'dist/**/*', fingerprint: true
}
}
stage('Docker Build ve Push') {
when {
branch 'main'
}
steps {
script {
def image = docker.build("${DOCKER_REGISTRY}/${APP_NAME}:${env.BUILD_NUMBER}")
docker.withRegistry("https://${DOCKER_REGISTRY}", 'docker-registry-credentials') {
image.push()
image.push('latest')
}
}
}
}
stage('Deploy to Staging') {
when {
branch 'main'
}
steps {
withCredentials([sshUserPrivateKey(
credentialsId: 'staging-server-key',
keyFileVariable: 'SSH_KEY'
)]) {
sh """
ssh -i ${SSH_KEY} -o StrictHostKeyChecking=no
[email protected]
'docker pull ${DOCKER_REGISTRY}/${APP_NAME}:${env.BUILD_NUMBER} &&
docker stop ${APP_NAME} || true &&
docker rm ${APP_NAME} || true &&
docker run -d --name ${APP_NAME} -p 3000:3000
${DOCKER_REGISTRY}/${APP_NAME}:${env.BUILD_NUMBER}'
"""
}
}
}
}
post {
always {
cleanWs()
}
success {
slackSend(
channel: '#deployments',
color: 'good',
message: "Pipeline başarılı: ${env.JOB_NAME} #${env.BUILD_NUMBER}"
)
}
failure {
slackSend(
channel: '#deployments',
color: 'danger',
message: "Pipeline başarısız: ${env.JOB_NAME} #${env.BUILD_NUMBER}nDetay: ${env.BUILD_URL}blue"
)
}
}
}
Bu pipeline’ı Blue Ocean’da çalıştırdığınızda, özellikle paralel stage’lerin görsel olarak yan yana gösterildiğini göreceksiniz. “Lint ve Format Check” aşamasında üç farklı kontrol aynı anda çalışırken Blue Ocean bunları paralel sütunlar halinde gösterir. Hangi column’ın ne kadar sürdüğünü, hangisinin hata verdiğini anlık olarak takip edebilirsiniz.
Blue Ocean Pipeline Editörü
Blue Ocean’ın en güçlü özelliklerinden biri görsel pipeline editörüdür. Jenkinsfile yazmadan, sürükle bırak mantığıyla pipeline oluşturabilirsiniz. Ancak şunu söylemeliyim: bu editör basit pipeline’lar için harika, karmaşık iş akışları için hala kod yazmak daha pratik.
Pipeline editörüne erişmek için Blue Ocean ana sayfasında “New Pipeline” butonuna tıklayın. Buradan Git repository’nizi bağlayabilir, branch’leri seçebilir ve görsel olarak stage’lerinizi tanımlayabilirsiniz.
Editörde yapabilecekleriniz:
- Stage ekleme ve silme
- Her stage’e step atama
- Environment variable tanımlama
- Agent seçimi yapma
- Post-build aksiyon tanımlama
Multibranch Pipeline ile Branch Yönetimi
Blue Ocean, Multibranch Pipeline ile gerçek gücünü gösterir. Her branch için ayrı pipeline çalıştırabilir, PR’ları otomatik olarak test edebilirsiniz.
// Multibranch Pipeline için geliştirilmiş Jenkinsfile
pipeline {
agent any
options {
buildDiscarder(logRotator(numToKeepStr: '10'))
timeout(time: 30, unit: 'MINUTES')
skipDefaultCheckout(true)
}
stages {
stage('Checkout') {
steps {
checkout scm
script {
// Branch tipine göre değişken ata
env.IS_PR = env.CHANGE_ID ? 'true' : 'false'
env.IS_MAIN = env.BRANCH_NAME == 'main' ? 'true' : 'false'
env.IS_RELEASE = env.BRANCH_NAME.startsWith('release/') ? 'true' : 'false'
echo "Branch: ${env.BRANCH_NAME}"
echo "PR: ${env.IS_PR}"
echo "Main: ${env.IS_MAIN}"
}
}
}
stage('Build ve Test') {
steps {
sh 'make build'
sh 'make test'
}
}
stage('Security Scan') {
when {
anyOf {
branch 'main'
changeRequest()
}
}
steps {
sh 'trivy fs --exit-code 1 --severity HIGH,CRITICAL .'
}
}
stage('Deploy Preview') {
when {
changeRequest()
}
steps {
script {
def previewUrl = deployPreview(env.CHANGE_ID)
// PR'a yorum olarak preview URL ekle
pullRequest.comment("Preview ortamı hazır: ${previewUrl}")
}
}
}
stage('Deploy Production') {
when {
branch 'main'
}
steps {
input message: 'Production deployment onaylıyor musunuz?', ok: 'Deploy Et'
sh 'make deploy-prod'
}
}
}
}
Gerçek Dünya Senaryosu: Microservice Mimarisinde Blue Ocean
Şirkette çalıştığım dönemde 12 microservice’ten oluşan bir sistemi yönetiyorduk. Her servisin kendi repository’si, kendi test suite’i vardı. Blue Ocean olmadan bu kaosta kaybolmak an meselesiydi.
Çözüm olarak her servis için standart bir Jenkinsfile şablonu oluşturduk ve bunu Shared Library olarak tanımladık:
// vars/microservicePipeline.groovy
// Jenkins Shared Library
def call(Map config = [:]) {
def serviceName = config.serviceName ?: error("serviceName zorunludur")
def dockerRegistry = config.dockerRegistry ?: 'registry.company.com'
def k8sNamespace = config.k8sNamespace ?: 'production'
pipeline {
agent {
kubernetes {
yaml """
apiVersion: v1
kind: Pod
spec:
containers:
- name: build
image: golang:1.21-alpine
command:
- sleep
args:
- infinity
- name: docker
image: docker:24-dind
securityContext:
privileged: true
"""
}
}
stages {
stage("${serviceName} Build") {
steps {
container('build') {
sh "go build -v -o ${serviceName} ./cmd/${serviceName}"
sh "go test ./... -v -coverprofile=coverage.out"
sh "go vet ./..."
}
}
}
stage("${serviceName} Docker Build") {
steps {
container('docker') {
sh """
docker build
--build-arg SERVICE_NAME=${serviceName}
--build-arg BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
--build-arg GIT_COMMIT=${env.GIT_COMMIT}
-t ${dockerRegistry}/${serviceName}:${env.BUILD_NUMBER}
-t ${dockerRegistry}/${serviceName}:latest
.
"""
}
}
}
stage("${serviceName} Deploy") {
when { branch 'main' }
steps {
container('build') {
withKubeConfig([credentialsId: 'k8s-config']) {
sh """
kubectl set image deployment/${serviceName}
${serviceName}=${dockerRegistry}/${serviceName}:${env.BUILD_NUMBER}
-n ${k8sNamespace}
kubectl rollout status deployment/${serviceName}
-n ${k8sNamespace}
--timeout=300s
"""
}
}
}
}
}
}
}
Her microservice’in Jenkinsfile’ı bu sayede sadece birkaç satıra indi:
// Her microservice'in Jenkinsfile'ı
@Library('company-shared-lib') _
microservicePipeline(
serviceName: 'user-service',
dockerRegistry: 'registry.company.com',
k8sNamespace: 'production'
)
Blue Ocean bu yapıyla çalışırken her servisin pipeline’ını ayrı ayrı görselleştirir, hangi servisin hangi aşamada olduğunu dashboard üzerinden anlık takip edebilirsiniz.
Blue Ocean API Kullanımı
Blue Ocean’ın REST API’si, pipeline durumlarını harici sistemlerle entegre etmek için kullanışlıdır. Monitoring dashboardlarına veri çekmek, Slack veya Teams entegrasyonu yapmak için bu API’yi aktif olarak kullanıyorum.
# Blue Ocean REST API ile pipeline bilgilerini çek
JENKINS_URL="http://jenkins.example.com"
JENKINS_USER="admin"
JENKINS_TOKEN="your-api-token"
JOB_NAME="my-multibranch-pipeline"
# Tüm branch pipeline'larını listele
curl -s -u "${JENKINS_USER}:${JENKINS_TOKEN}"
"${JENKINS_URL}/blue/rest/organizations/jenkins/pipelines/${JOB_NAME}/branches/"
| python3 -m json.tool
# Son build'in detaylarını al
curl -s -u "${JENKINS_USER}:${JENKINS_TOKEN}"
"${JENKINS_URL}/blue/rest/organizations/jenkins/pipelines/${JOB_NAME}/branches/main/runs/latest/"
| python3 -m json.tool
# Belirli bir build'in stage'lerini görüntüle
BUILD_NUMBER="42"
curl -s -u "${JENKINS_USER}:${JENKINS_TOKEN}"
"${JENKINS_URL}/blue/rest/organizations/jenkins/pipelines/${JOB_NAME}/branches/main/runs/${BUILD_NUMBER}/nodes/"
| python3 -m json.tool
# Pipeline loglarını çek (belirli bir node/stage için)
NODE_ID="15"
curl -s -u "${JENKINS_USER}:${JENKINS_TOKEN}"
"${JENKINS_URL}/blue/rest/organizations/jenkins/pipelines/${JOB_NAME}/branches/main/runs/${BUILD_NUMBER}/nodes/${NODE_ID}/log/?start=0"
Bu API’yi kullanarak yazdığım basit bir monitoring scripti şirketimizde günde düzinelerce pipeline’ı izlemek için hala aktif olarak çalışıyor.
Performans ve Optimizasyon İpuçları
Blue Ocean’ın arayüzü zengin olduğu için tarayıcıda biraz ağır açılabiliyor. Özellikle onlarca pipeline’ı olan büyük ortamlarda bu can sıkıcı hale gelebilir. Bir kaç pratik ipucu:
Jenkins JVM ayarları için:
# /etc/default/jenkins dosyasını düzenle
# veya systemd service dosyasına ekle
JAVA_OPTS="-Xms2g -Xmx4g
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
-XX:+UnlockExperimentalVMOptions
-XX:+UseCGroupMemoryLimitForHeap
-Djava.awt.headless=true
-Djenkins.install.runSetupWizard=false
-Dblueocean.features.CACHE_RESPONSES=true"
Blue Ocean cache ayarları için Jenkins system groovy:
// init.groovy.d/blueocean-config.groovy
import jenkins.model.Jenkins
def instance = Jenkins.getInstance()
// Blue Ocean için executor thread sayısını artır
instance.setNumExecutors(4)
// Build history'yi sınırla (Blue Ocean daha hızlı yüklensin)
def strategy = new jenkins.model.BuildDiscarder()
instance.save()
println "Blue Ocean konfigürasyonu tamamlandı"
Pipeline optimizasyonu:
- Paralel stage’leri mümkün olduğunca kullanın, Blue Ocean bunları zaten güzel görselleştirir
skipDefaultCheckout(true)ile gereksiz checkout işlemlerinden kaçınınbuildDiscarderile eski build’leri temizleyin, Blue Ocean’ın yüklenme hızı buna çok bağlı- Docker agent kullanıyorsanız image’ları önceden pull etmiş olduğunuzdan emin olun
Yaygın Sorunlar ve Çözümleri
“Blue Ocean yüklenmiyor” sorunu:
Genellikle eklenti bağımlılık çakışmasından kaynaklanır. Şu şekilde tanımlayabilirsiniz:
# Jenkins eklenti sorunlarını kontrol et
java -jar jenkins-cli.jar -s http://localhost:8080/
-auth admin:TOKEN
list-plugins | grep -E "(blueocean|pipeline)"
# Tüm eklentileri güncelle
java -jar jenkins-cli.jar -s http://localhost:8080/
-auth admin:TOKEN
install-plugin
blueocean
workflow-aggregator
git
credentials-binding
--restart
Pipeline görselleştirilmiyor: Declarative Pipeline syntax kullanmanız gerekiyor. Scripted Pipeline’lar Blue Ocean’da tam görselleştirilemiyor. Eğer eski scripted pipeline’larınız varsa, declarative’e geçişi planlayın.
GitHub/GitLab bağlantı sorunları: Blue Ocean’ın Git entegrasyonu için personal access token kullanıyor. Bu token’ın repo, webhook ve pull request yetkilerine sahip olduğundan emin olun.
Sonuç
Blue Ocean, Jenkins’i sadece bir CI aracı olmaktan çıkarıp gerçek anlamda bir DevOps platformuna dönüştürüyor. Özellikle takım olarak çalışırken, herkesin pipeline durumunu kolayca görebilmesi, PR’ların test sonuçlarını anlık takip edebilmesi inanılmaz bir verimlilik artışı sağlıyor.
Kendi deneyimimden söyleyebilirim ki Blue Ocean’a geçtikten sonra “pipeline neden patladı” sorusuna cevap bulmak için harcanan zaman ciddi ölçüde azaldı. Geliştiriciler artık bana “Jenkins’te bir şeyler oldu, bakabilir misin?” diye gelmek yerine kendileri hangi adımın neden başarısız olduğunu görebiliyorlar.
Eğer hala klasik Jenkins arayüzünde çalışıyorsanız, Blue Ocean’a geçiş için bir hafta sonu yeterli. Kurulum basit, öğrenme eğrisi düşük. En kötü ihtimalle iki arayüzü paralel kullanabilirsiniz, zira Blue Ocean klasik arayüzü devre dışı bırakmıyor. Deneyin, bence memnun kalacaksınız.
