Takip et

Nginx & Docker ile Kendi Kendini Onaran Blue/Green Dağıtım

Modern uygulamaların sürekli erişilebilir ve hatasız olması beklenir. Peki, yeni bir sürümü yayınlarken kesinti yaşanmadan, hatta olası bir hatada otomatik geri alarak bu beklentiyi nasıl karşılayabiliriz? İşte bu makale, Nginx ve Docker’ı kullanarak kendi kendini onarabilen, sıfır kesintili Blue/Green dağıtım stratejilerini adım adım nasıl uygulayacağınızı açıklıyor.

Günümüzün rekabetçi dijital dünyasında, kullanıcı deneyimi her şeyden önemlidir. Bir uygulamanın kısa süreli bir kesintisi bile, müşteri kaybına, marka imajının zedelenmesine ve finansal zararlara yol açabilir. Geleneksel dağıtım yöntemleri, genellikle uygulama duruş süreleri gerektirir veya güncellemeler sırasında hatalarla karşılaşma riskini artırır. Bu durum, özellikle yüksek erişilebilirlik gerektiren e-ticaret siteleri, finansal uygulamalar veya kritik altyapı hizmetleri gibi senaryolarda kabul edilemezdir. Blue/Green dağıtım stratejisi, bu sorunlara güçlü ve zarif bir çözüm sunar. Bu strateji sayesinde, yeni bir uygulama sürümünü yayınlarken sıfır kesintiyle bir geçiş yapabilir, hatta olası hatalarda hızlıca eski sürüme geri dönebiliriz. Böylece, hem geliştiricilerin hem de operasyon ekiplerinin omuzlarındaki yük hafiflerken, kullanıcılar kesintisiz bir deneyim yaşamaya devam eder.

Blue/Green dağıtım, adından da anlaşılacağı üzere, “mavi” ve “yeşil” olmak üzere iki özdeş üretim ortamının paralel olarak çalıştırılması prensibine dayanır. Bir ortam mevcut çalışan sürümü (örneğin, mavi ortam) barındırırken, diğer ortam (yeşil ortam) yeni sürümün dağıtımı için kullanılır. Bu iki ortam, bir yük dengeleyici veya ters proxy (bizim durumumuzda Nginx) tarafından yönetilen trafik akışıyla birbirine bağlanır. Yeni sürüm yeşil ortama dağıtıldıktan ve tüm testleri başarıyla geçtikten sonra, yük dengeleyici trafiği yavaşça veya aniden mavi ortamdan yeşil ortama yönlendirir. Bu geçiş anında ve sorunsuz olduğu için kullanıcılar yeni sürüme geçtiğini bile fark etmezler. Bu yöntem, bir hata durumunda tek bir yapılandırma değişikliğiyle trafiği anında eski, kararlı mavi ortama geri yönlendirme (rollback) olanağı sunar. Bu, özellikle kritik uygulamalar için hayati öneme sahip bir güvenlik ağı sağlar.

Bu makale boyunca, Blue/Green dağıtımının temel prensiplerini Nginx ve Docker gibi popüler ve güçlü araçlarla nasıl birleştireceğimizi detaylı bir şekilde inceleyeceğiz. Ayrıca, dağıtım sürecini daha da güvenilir hale getirmek için kendi kendini onarma yeteneklerini nasıl ekleyeceğimizi, sağlık kontrollerini ve otomatik geri alma mekanizmalarını nasıl kuracağımızı adım adım göstereceğiz. Amacımız, uygulamanızın dağıtımını sadece kesintisiz değil, aynı zamanda olası hatalara karşı da dayanıklı hale getirmektir. Gerçek dünya senaryolarından örneklerle, bu güçlü kombinasyonun işinize nasıl değer katacağını göreceksiniz. Örneğin, bir e-ticaret platformunun yoğun Black Friday döneminde yeni bir kampanya özelliğini yayınladığını ve bu özelliğin kritik bir hataya yol açtığını düşünelim. Blue/Green dağıtım sayesinde, saniyeler içinde eski sürüme geri dönerek on binlerce dolarlık potansiyel kaybın önüne geçilebilir. İşte bu tür senaryolar, bu dağıtım stratejisinin ne kadar kritik olduğunu açıkça ortaya koymaktadır.

Uzman İpucu: Blue/Green dağıtım, sadece kesintisiz dağıtım sağlamakla kalmaz, aynı zamanda A/B testi ve kanarya dağıtımı gibi diğer gelişmiş dağıtım stratejileri için de güçlü bir temel oluşturur.

Temel Taşlar: Blue/Green Dağıtım, Docker ve Nginx Nedir?

Herhangi bir karmaşık sistemi anlamanın yolu, onu oluşturan temel bileşenleri kavramaktan geçer. Kendi kendini onaran Blue/Green dağıtım mimarisini inşa ederken de durum farklı değildir. Bu bölümde, sistemimizin üç ana bileşeni olan Blue/Green dağıtım stratejisi, Docker konteynerleri ve Nginx ters proxy’nin ne olduğunu, ne işe yaradığını ve birbirleriyle nasıl etkileşim kurduğunu detaylıca ele alacağız. Bu temel bilgiler, uygulamanın mimarisine ve dağıtım sürecine dair sağlam bir anlayış geliştirmeniz için kritik öneme sahiptir.

Blue/Green Dağıtım Stratejisi Nasıl Çalışır?

Daha önce de bahsettiğimiz gibi, Blue/Green dağıtım, üretim ortamının iki özdeş kopyasını kullanır: “mavi” (mevcut canlı sürüm) ve “yeşil” (yeni sürümün konuşlandırılacağı ortam). Bu ayrım, yeni sürümün canlı trafiğe maruz kalmadan tamamen test edilmesini sağlar. Süreç genellikle şu adımları takip eder:

  1. Mevcut sürüm “mavi” ortamda çalışır ve tüm canlı trafiği alır.
  2. Yeni sürüm “yeşil” ortama dağıtılır. Bu aşamada, yeşil ortam henüz canlı trafik almaz, bu da geliştiricilere ve test ekiplerine yeni sürümü kapsamlı bir şekilde test etme olanağı tanır.
  3. Yeşil ortamdaki yeni sürüm tüm testleri başarıyla geçtiğinde, yük dengeleyici veya ters proxy (Nginx) yapılandırması güncellenerek gelen trafiğin mavi ortamdan yeşil ortama yönlendirilmesi sağlanır. Bu geçiş genellikle saniyeler içinde gerçekleşir.
  4. Tüm trafik yeşil ortama geçtikten sonra, mavi ortam bekleme moduna alınır. Eğer yeşil ortamda beklenmedik bir sorun ortaya çıkarsa, trafik anında ve kolayca mavi ortama geri yönlendirilebilir. Bu, hızlı bir geri alma (rollback) mekanizması sunar.
  5. Yeni sürüm yeşil ortamda istikrarlı çalıştığında, mavi ortam bir sonraki dağıtım için “yeşil” rolünü üstlenmek üzere güncellenebilir veya tamamen kapatılabilir.

Bu strateji, dağıtım riskini minimize ederken, aynı zamanda geri alma işlemlerini son derece kolay ve hızlı hale getirir. Önemli bir nokta, her iki ortamın da mümkün olduğunca aynı yapılandırmaya sahip olması gerektiğidir; bu, “altyapı olarak kod” (Infrastructure as Code) prensiplerinin burada devreye girmesi anlamına gelir.

Docker Konteynerlerinin Rolü Nelerdir?

Docker, uygulamaları bağımlılıklarıyla birlikte hafif, taşınabilir ve izole konteynerler içinde paketlemeyi sağlayan devrim niteliğinde bir teknolojidir. Blue/Green dağıtım stratejisiyle birleştiğinde, Docker’ın faydaları daha da belirginleşir:

  • Tutarlılık: Docker konteynerleri, uygulamanın geliştirme, test ve üretim ortamları arasında tutarlı bir şekilde çalışmasını garanti eder. Bu, “benim makinemde çalışıyor” sorununu ortadan kaldırır.
  • İzolasyon: Her uygulama veya mikroservis kendi konteynerinde izole bir şekilde çalıştığı için, bağımlılık çakışmaları riski azalır ve güvenlik artar.
  • Hızlı Dağıtım ve Ölçeklenebilirlik: Konteynerler hızlı bir şekilde başlatılabilir ve durdurulabilir. Bu da Blue/Green geçişlerini hızlandırır ve gerektiğinde uygulama örneklerinin kolayca ölçeklendirilmesine olanak tanır.
  • Kaynak Verimliliği: Sanal makinelerin aksine, konteynerler işletim sistemi çekirdeğini paylaşır, bu da daha az kaynak tüketimi anlamına gelir.

Blue/Green senaryosunda, “mavi” ve “yeşil” ortamlar, Docker konteynerleri aracılığıyla aynı uygulamaların farklı sürümlerini barındıran tamamen izole edilmiş yığınlar olarak düşünülebilir. Docker Compose veya Docker Swarm gibi araçlar, birden fazla konteyneri tek bir hizmet olarak tanımlamayı ve yönetmeyi kolaylaştırır, bu da dağıtım sürecini basitleştirir.

Nginx Yük Dengeleme ve Ters Proxy Yetenekleri Neler Sunar?

Nginx, yüksek performanslı bir ters proxy, yük dengeleyici, HTTP sunucusu ve önbellek sunucusudur. Blue/Green dağıtım mimarimizde, Nginx’in rolü merkezi ve kritik öneme sahiptir:

  • Ters Proxy: Kullanıcı isteklerini arka uçtaki Docker konteynerlerine yönlendirir. Bu, uygulama sunucularını doğrudan internete maruz bırakmadan güvenlik sağlar.
  • Yük Dengeleme: Gelen trafiği birden fazla uygulama örneği arasında dağıtarak performansı artırır ve hizmetin yüksek erişilebilirliğini sağlar. Blue/Green senaryosunda, Nginx trafiği dinamik olarak “mavi” veya “yeşil” uygulama yığınına yönlendirecektir.
  • Sıfır Kesinti Geçişi: Nginx, yapılandırma dosyası güncellemelerini duruş süresi olmadan yeniden yükleme yeteneğine sahiptir. Bu özellik, trafiği anında mavi ortamdan yeşil ortama veya tam tersine yönlendirmemizi sağlar.
  • Sağlık Kontrolleri: Nginx, arka uç sunucularının (bizim durumumuzda Docker konteynerleri) sağlık durumunu periyodik olarak kontrol edebilir. Sağlıksız bir örneği trafik havuzundan çıkararak kesintisiz hizmeti destekler.

Nginx’in dinamik yapılandırma yeteneği, Blue/Green dağıtımının kalbinde yer alır. Dağıtım betiklerimiz aracılığıyla Nginx yapılandırmasını kolayca güncelleyebilir ve hangi ortamın canlı trafik alacağını belirleyebiliriz. Bu, operasyonel yükü önemli ölçüde azaltırken, güvenilir ve hızlı dağıtımların önünü açar. Dolayısıyla, Nginx, Blue/Green dağıtımımızın orkestrasyonunda kritik bir rol oynayan, trafiği akıllıca yöneten ve sistemin genel istikrarını sağlayan kilit bir bileşendir.

Dikkat: Blue/Green ortamlarınızı yapılandırırken, veritabanı gibi paylaşılan kaynakların yönetimini dikkatlice planlamanız gerekmektedir. Veritabanı şema değişiklikleri veya veri geçişleri, Blue/Green dağıtımında genellikle ayrı zorluklar yaratır ve dikkatli bir strateji gerektirir.

Kendi Kendini Onaran Yapının Temelleri Nasıl Atılır?

Modern uygulamalar sadece hızlı ve kesintisiz dağıtılmakla kalmamalı, aynı zamanda dağıtım sonrası oluşabilecek hatalara karşı da dirençli olmalıdır. İşte bu noktada “kendi kendini onaran” (self-healing) yapı devreye girer. Kendi kendini onaran bir sistem, problemleri otomatik olarak tespit edebilir ve insan müdahalesine gerek kalmadan düzeltici önlemler alabilir. Blue/Green dağıtım stratejimizle birleştiğinde, bu, dağıtımlarımızı daha da sağlam hale getirir. Bu bölümde, sistemimizin kendi kendini onarma yeteneklerini nasıl inşa edeceğimizi, sağlık kontrollerinin neden hayati olduğunu ve Nginx’in bu süreçteki rolünü inceleyeceğiz. Ayrıca, olası bir problemde otomatik geri alma mekanizmalarını nasıl tetikleyeceğimizi de ele alacağız.

Sağlık Kontrolleri (Health Checks) Neden Hayati Önem Taşır?

Bir uygulamanın “canlı” olması, onun tamamen işlevsel olduğu anlamına gelmeyebilir. Bir sunucu çalışıyor olabilir, ancak üzerindeki uygulama bir veritabanı bağlantı hatası veya bellek sızıntısı nedeniyle hizmet veremiyor olabilir. Sağlık kontrolleri, uygulamanızın sadece ayakta olup olmadığını değil, aynı zamanda beklenen şekilde çalışıp çalışmadığını doğrulamak için tasarlanmış otomatik kontrollerdir. Blue/Green dağıtımımızda sağlık kontrolleri iki ana amaç için kullanılır:

  1. Yeni Sürümün Doğrulanması: “Yeşil” ortama yeni bir sürüm dağıtıldığında, trafiği bu ortama yönlendirmeden önce uygulamanın tamamen sağlıklı ve kullanıma hazır olduğunu doğrulamak.
  2. Canlı Ortamın İzlenmesi: Trafiğin yönlendirildiği “mavi” veya “yeşil” ortamdaki uygulamanın sürekli olarak sağlıklı kalmasını sağlamak. Bir sorun tespit edildiğinde, Nginx trafiği otomatik olarak sağlıklı olan diğer ortama yönlendirebilir veya uyarı tetikleyebilir.

Sağlık kontrolleri genellikle HTTP uç noktalarına (örneğin, /health) yapılan basit GET istekleri şeklinde uygulanır. Bu uç nokta, uygulamanın temel bağımlılıklarını (veritabanı bağlantısı, önbellek erişimi vb.) kontrol eder ve başarılı olursa bir HTTP 200 OK yanıtı döner. Başarısız olursa, bir hata kodu veya boş yanıt dönerek uygulamanın sağlıksız olduğunu belirtir.

Docker’da sağlık kontrolü tanımlamak oldukça kolaydır. Docker Compose dosyanızda healthcheck yönergesini kullanarak bir hizmetin nasıl kontrol edileceğini belirleyebilirsiniz. Örneğin:


version: '3.8'
services:
  app:
    image: myapp:latest
    ports:
      - "8080:8080"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 30s
      timeout: 10s
      retries: 3
    

Bu yapılandırma, Docker'ın 30 saniyede bir uygulamanızın /health endpoint'ine bir curl isteği göndermesini ve 10 saniye içinde yanıt alamazsa veya hata alırsa sağlıksız olduğunu kabul etmesini sağlar. 3 denemeden sonra hala sağlıksız ise, Docker bu hizmeti yeniden başlatmayı veya durumu "unhealthy" olarak işaretlemeyi düşünecektir.

Nginx ile Dinamik Yönlendirme Nasıl Yapılır?

Nginx, kendi kendini onaran Blue/Green dağıtımımızın kalbinde yer alan dinamik yönlendirme yeteneğini sunar. Bu, Nginx yapılandırmasını duruş süresi olmadan güncelleyerek trafiği bir ortamdan diğerine anında yönlendirebilmemiz anlamına gelir. Bunu genellikle bir Nginx upstream bloğu ve bir map direktifi kullanarak başarırız.

İlk olarak, hem mavi hem de yeşil ortamlar için ayrı upstream grupları tanımlarız:


# /etc/nginx/conf.d/app_upstreams.conf
upstream blue_app {
    server 172.18.0.2:8080; # Blue ortamdaki uygulamanızın IP'si/Portu
    # server blue_app_server_2:8080;
}

upstream green_app {
    server 172.18.0.3:8080; # Green ortamdaki uygulamanızın IP'si/Portu
    # server green_app_server_2:8080;
}
    

Daha sonra, hangi ortamın canlı olacağını belirlemek için basit bir metin dosyası (örneğin, /etc/nginx/conf.d/current_env.conf) kullanırız. Bu dosya sadece aktif ortamın adını (blue veya green) içerecektir. Nginx'in bu değeri dinamik olarak okuması için bir map direktifi kullanabiliriz:


# /etc/nginx/nginx.conf içinde veya dahil edilen bir dosyada
map $active_env $backend_servers {
    default blue_app; # Varsayılan olarak blue
    blue blue_app;
    green green_app;
}

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://$backend_servers;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
    

Buradaki kritik nokta, $active_env değişkeninin değerini harici bir kaynaktan alabilmemizdir. Nginx'in dinamik yapılandırma yeteneği sayesinde, bu değişkeni bir betik aracılığıyla güncelleyebilir ve Nginx'i yeniden yüklemeden (nginx -s reload) aktif ortamı değiştirebiliriz. Dağıtım betiğimiz, bu current_env.conf dosyasını güncelleyerek trafiği istediğimiz ortama yönlendirecektir. Bu sayede, trafik geçişi sıfır kesintiyle gerçekleşir.

Dağıtım Sürecinde Hata Tespiti ve Geri Alma (Rollback) Mekanizmaları

Kendi kendini onaran bir sistemin en önemli özelliklerinden biri de, sorun anında otomatik olarak eski ve kararlı duruma dönebilmesidir. Blue/Green dağıtım, bu geri alma sürecini doğal olarak destekler. Dağıtım betiklerimiz, yeni sürüme geçiş yaparken belirli sağlık kontrol adımlarını içermelidir. Eğer bu sağlık kontrolleri başarısız olursa, betik otomatik olarak geri alma sürecini tetiklemelidir.

Örneğin, yeni sürümü "yeşil" ortama dağıttıktan ve Nginx'i trafiği yeşil ortama yönlendirdikten sonra, yeşil ortamın sağlık kontrollerini belirli bir süre (örneğin 5 dakika) boyunca aktif olarak izleyebiliriz. Eğer bu süre zarfında sağlık kontrolleri sürekli olarak başarısız olursa veya uygulama beklenenden farklı davranırsa (CPU/bellek kullanımı anormalse), dağıtım betiğimiz Nginx'i tekrar "mavi" ortama yönlendirecek şekilde yapılandırmalıdır. Bu, hızlı ve otomatik bir geri alma mekanizması sağlar.

Bu otomatik geri alma, özellikle gece geç saatlerde yapılan dağıtımlar veya operasyon ekibinin anında müdahale edemeyeceği durumlar için paha biçilmezdir. Geri alma sürecini başlatmak için yapmamız gereken tek şey, current_env.conf dosyasını eski ortamı işaret edecek şekilde güncellemek ve Nginx'i yeniden yüklemektir. Bu, Blue/Green dağıtımının sağladığı en büyük güvenlik ağlarından biridir ve kendi kendini onaran bir yapının temel direğidir.

Uzman İpucu: Geri alma mekanizmanızı test etmek, dağıtım sürecinizin önemli bir parçası olmalıdır. Periyodik olarak geri alma senaryoları simüle ederek sisteminizin beklendiği gibi çalıştığından emin olun.

Uygulamalı Adımlar: Nginx ve Docker ile Blue/Green Nasıl Kurulur?

Teorik bilgileri pekiştirmenin en iyi yolu, bunları uygulamaya dökmektir. Bu bölümde, Nginx ve Docker kullanarak sıfır kesintili ve kendi kendini onaran bir Blue/Green dağıtım sistemini adım adım nasıl kuracağınızı göstereceğiz. Docker Compose kullanarak iki farklı uygulama ortamını nasıl yöneteceğimizi, Nginx'i bu ortamlar arasında dinamik geçiş yapacak şekilde nasıl yapılandıracağımızı ve nihayetinde dağıtım sürecini otomatikleştiren bir betik nasıl yazacağımızı detaylandıracağız. Bu pratik uygulama, konuyu derinlemesine kavramanıza yardımcı olacaktır.

Geliştirme Ortamı Kurulumu ve Docker Compose Yapılandırması

Başlamak için, Docker ve Docker Compose kurulu bir Linux sunucusuna ihtiyacımız var. Eğer yoksa, bunları işletim sisteminize uygun şekilde kurun. Ardından, Blue/Green ortamlarımızı yönetecek bir Docker Compose dosyası oluşturalım. Bu dosya, uygulamamızın "mavi" ve "yeşil" sürümlerini ve Nginx ters proxy'yi içerecektir.

Örnek bir Node.js uygulamamız olduğunu ve bu uygulamanın /health endpoint'inde sağlık kontrolü yaptığını varsayalım.


# docker-compose.yml
version: '3.8'

services:
  nginx:
    image: nginx:latest
    ports:
      - "80:80"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./nginx/conf.d:/etc/nginx/conf.d:ro # Dinamik dosyaları barındıracak
    depends_on:
      - app_blue
      - app_green
    networks:
      - app_network

  app_blue:
    image: myapp:blue # Uygulamanızın mavi versiyonu
    environment:
      APP_COLOR: blue
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 10s
      timeout: 5s
      retries: 3
      start_period: 20s
    networks:
      - app_network

  app_green:
    image: myapp:green # Uygulamanızın yeşil versiyonu
    environment:
      APP_COLOR: green
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 10s
      timeout: 5s
      retries: 3
      start_period: 20s
    networks:
      - app_network

networks:
  app_network:
    driver: bridge
    

Bu docker-compose.yml dosyası şunları yapar:

  • nginx servisi, gelen trafiği yönetecek Nginx sunucusunu çalıştırır. Nginx yapılandırma dosyalarını dışarıdan monte ederiz.
  • app_blue ve app_green servisleri, uygulamamızın farklı sürümlerini (veya başlangıçta aynı sürümünü) temsil eder. Her birinin kendi Docker imajı ve sağlık kontrolü vardır. APP_COLOR çevresel değişkeni, uygulamanın hangi ortamda çalıştığını loglarda veya UI'da göstermek için kullanılabilir.
  • Tüm servisler app_network adlı özel bir Docker ağında iletişim kurar. Bu, servisler arası DNS çözümlemesini kolaylaştırır.

Başlangıç olarak myapp:blue ve myapp:green imajları aynı olabilir. Örneğin, basit bir Node.js Express uygulaması:


// app.js
const express = require('express');
const app = express();
const port = 8080;
const appColor = process.env.APP_COLOR || 'default';

app.get('/', (req, res) => {
  res.send(Hello from ${appColor} environment!);
});

app.get('/health', (req, res) => {
  // Veritabanı bağlantısı, dosya sistemi erişimi vb. kontrol edilebilir.
  // Bu örnekte sadece 200 OK dönüyoruz.
  res.status(200).send('OK');
});

app.listen(port, () => {
  console.log(App (${appColor}) listening at http://localhost:${port});
});
    

Bu kodu içeren bir Dockerfile:


# Dockerfile
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 8080
CMD ["node", "app.js"]
    

Bu imajı docker build -t myapp:blue . ve docker build -t myapp:green . komutlarıyla oluşturabilirsiniz.

Nginx Konfigürasyonu: Dinamik Yönlendirmeyi Nasıl Sağlarız?

Nginx yapılandırması, trafiği doğru ortama yönlendirmek için kritik öneme sahiptir. nginx klasörünüzde aşağıdaki dosyaları oluşturun:


# nginx/nginx.conf
user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}
    


# nginx/conf.d/upstreams.conf
upstream app_blue {
    server app_blue:8080;
    # sağlık kontrolü ekle
    zone app_blue 64k; # Durum bilgisi için
}

upstream app_green {
    server app_green:8080;
    # sağlık kontrolü ekle
    zone app_green 64k; # Durum bilgisi için
}
    


# nginx/conf.d/blue_green_router.conf
# Bu dosya dağıtım betiği tarafından güncellenecek
# Başlangıçta blue ortamına yönlendiriyoruz
map $request_uri $backend_servers {
    default app_blue;
}
    


# nginx/conf.d/default.conf
server {
    listen 80;
    server_name localhost;

    location / {
        proxy_pass http://$backend_servers;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
    

Nginx, blue_green_router.conf dosyasındaki map direktifi aracılığıyla hangi upstream grubunu kullanacağını belirleyecektir. Bu dosyayı dağıtım betiğimizle değiştireceğiz.

Dağıtım Betiği (Deployment Script) Nasıl Yazılır?

Şimdi, tüm bu parçaları bir araya getiren bir dağıtım betiği oluşturalım. Bu betik, yeni bir sürümü dağıtacak, sağlık kontrollerini yapacak ve trafiği güvenli bir şekilde yönlendirecektir. Olası bir hatada geri alma yeteneği de bu betiğe dahil edilecektir.



#!/bin/bash

# Renk kodları
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[0;33m'
NC='\033[0m' # No Color

echo -e "${YELLOW}Blue/Green Dağıtım Betiği Başlatılıyor...${NC}"

# Mevcut aktif ortamı bul
CURRENT_ACTIVE_COLOR=$(docker inspect --format='{{index .Config.Env "APP_COLOR"}}' $(docker-compose ps -q app_blue) 2>/dev/null | cut -d'=' -f2)

if [ "$CURRENT_ACTIVE_COLOR" == "blue" ]; then
    NEW_COLOR="green"
    OLD_COLOR="blue"
else
    NEW_COLOR="blue"
    OLD_COLOR="green"
fi

echo -e "${YELLOW}Mevcut aktif ortam: $OLD_COLOR${NC}"
echo -e "${YELLOW}Yeni dağıtılacak ortam: $NEW_COLOR${NC}"

# 1. Yeni sürüm imajını çek/oluştur
echo -e "${GREEN}1. Yeni uygulama imajı oluşturuluyor/çekiliyor...${NC}"
# Bu kısımda Dockerfile'ınızdan yeni imajı build edebilir veya uzaktan çekebilirsiniz.
# Örnek: docker build -t myapp:$NEW_COLOR .
# Mevcut durumda Docker Compose zaten imaj etiketlerini kullanıyor.
# Buraya gerçek bir build adımı eklenebilir.
docker build -t myapp:$NEW_COLOR . || { echo -e "${RED}İmaj oluşturma/çekme başarısız!${NC}"; exit 1; }
echo -e "${GREEN}İmaj myapp:$NEW_COLOR başarıyla hazırlandı.${NC}"

# 2. Yeni ortamı başlat (eski ortamı durdurmadan)
echo -e "${GREEN}2. $NEW_COLOR ortamı başlatılıyor...${NC}"
# Sadece yeni ortama ait servisi çalıştır
docker-compose up -d --no-deps app_$NEW_COLOR || { echo -e "${RED}$NEW_COLOR ortamı başlatılamadı!${NC}"; exit 1; }
echo -e "${GREEN}$NEW_COLOR ortamı arka planda başlatıldı.${NC}"

# 3. Yeni ortamın sağlık kontrollerini yap
echo -e "${GREEN}3. $NEW_COLOR ortamının sağlık kontrolleri bekleniyor...${NC}"
MAX_RETRIES=10
RETRY_COUNT=0
HEALTHY=false

while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
    HEALTH_STATUS=$(docker inspect --format='{{.State.Health.Status}}' $(docker-compose ps -q app_$NEW_COLOR) 2>/dev/null)
    if [ "$HEALTH_STATUS" == "healthy" ]; then
        HEALTHY=true
        echo -e "${GREEN}$NEW_COLOR ortamı sağlıklı!${NC}"
        break
    else
        echo -e "${YELLOW}Sağlık durumu '$HEALTH_STATUS'. Bekleniyor... ($((RETRY_COUNT+1))/$MAX_RETRIES)${NC}"
        sleep 10
        RETRY_COUNT=$((RETRY_COUNT+1))
    fi
done

if [ "$HEALTHY" == "false" ]; then
    echo -e "${RED}$NEW_COLOR ortamı yeterli sürede sağlıklı hale gelemedi. Geri alınıyor...${NC}"
    docker-compose stop app_$NEW_COLOR
    echo -e "${YELLOW}Dağıtım başarısız. Geri alma işlemi tamamlandı.${NC}"
    exit 1
fi

# 4. Nginx yapılandırmasını yeni ortama yönlendir
echo -e "${GREEN}4. Nginx yapılandırması $NEW_COLOR ortamına yönlendiriliyor...${NC}"
echo "map \$request_uri \$backend_servers { default app_${NEW_COLOR}; }" > ./nginx/conf.d/blue_green_router.conf
docker-compose exec nginx nginx -s reload || { echo -e "${RED}Nginx yeniden yüklenemedi! Geri alınıyor...${NC}";
    echo "map \$request_uri \$backend_servers { default app_${OLD_COLOR}; }" > ./nginx/conf.d/blue_green_router.conf;
    docker-compose exec nginx nginx -s reload;
    docker-compose stop app_$NEW_COLOR;
    exit 1;
}
echo -e "${GREEN}Trafik başarıyla $NEW_COLOR ortamına yönlendirildi.${NC}"

# 5. Yeni ortamın stabil kalmasını bekle ve eski ortamı kapat
echo -e "${GREEN}5. $NEW_COLOR ortamının stabilitesi kontrol ediliyor (30 saniye)...${NC}"
sleep 30 # Yeterince trafik akışını sağlamak için kısa bir süre
# Bu noktada daha gelişmiş izleme ve uyarı sistemleri entegre edilebilir.
# Örneğin, Prometheus/Grafana metrikleri kontrol edilebilir.

echo -e "${GREEN}$OLD_COLOR ortamı durduruluyor...${NC}"
docker-compose stop app_$OLD_COLOR
docker-compose rm -f app_$OLD_COLOR # Eski konteyneri ve verilerini sil
echo -e "${GREEN}Dağıtım tamamlandı! Yeni sürüm $NEW_COLOR ortamında çalışıyor.${NC}"


Bu betik, adımları açıkça gösterir: yeni sürümü oluştur, başlat, sağlık kontrolü yap, Nginx'i güncelle ve eski sürümü kapat. Eğer sağlık kontrolleri başarısız olursa veya Nginx yeniden yüklenemezse, betik otomatik olarak geri alma işlemi başlatır.

Sıfır Kesintiyle Geçiş Nasıl Gerçekleştirilir?

Yukarıdaki dağıtım betiği, sıfır kesintiyle geçişi mümkün kılar. İşte kilit noktalar:

  • Paralel Çalışma: Yeni sürüm (yeşil) eski sürüm (mavi) çalışırken başlatılır. Bu, her iki ortamın da bir süre paralel çalıştığı anlamına gelir ve hizmet kesintisi yaşanmaz.
  • Sağlık Kontrolleri: Yeni sürümün trafiği almadan önce tamamen sağlıklı olduğundan emin olunur. Bu, olası sorunların erken aşamada tespit edilmesini sağlar.
  • Nginx Reload: Nginx, yapılandırma değişikliklerini servis duruşu olmadan, anında yükleyebilir. Bu, trafik yönlendirmesinin anlık olmasını sağlar. Tek bir komutla (nginx -s reload) tüm trafik yeni ortama yönlendirilirken, aktif bağlantılar kesintiye uğramaz.
  • Geri Alma Mekanizması: Eğer yeni sürümde bir sorun oluşursa, Nginx yapılandırması eski ortama geri döndürülerek hizmet anında eski, kararlı duruma getirilir. Bu süreç de yine sıfır kesintiyle gerçekleşir.

Bu adımlarla, geliştiriciler yeni özellikleri güvenle dağıtabilir, operasyon ekipleri daha az stresle çalışır ve kullanıcılar her zaman kesintisiz bir hizmet deneyimi yaşarlar. Özellikle büyük ve karmaşık sistemlerde, bu tür bir dağıtım stratejisi, hata oranlarını dramatik bir şekilde düşürür ve dağıtım süreçlerinin hızlanmasına yardımcı olur.

Uzman İpucu: Dağıtım betiğinizi bir CI/CD boru hattına entegre ederek (Jenkins, GitLab CI, GitHub Actions vb.) dağıtım sürecini tamamen otomatik hale getirebilirsiniz. Bu, insan hatasını minimize eder ve dağıtım hızını artırır.

Gelişmiş Stratejiler ve Otomasyon: Dağıtımınızı Nasıl Optimize Edersiniz?

Temel bir kendi kendini onaran Blue/Green dağıtım yapısını kurduk, ancak modern DevOps uygulamaları, bu temeli daha da güçlendirerek dağıtım süreçlerini optimize etmeyi gerektirir. Bu bölümde, dağıtımınızı daha da otomatik, izlenebilir ve dirençli hale getirmek için kullanabileceğiniz gelişmiş stratejilere ve otomasyon tekniklerine odaklanacağız. CI/CD entegrasyonundan detaylı gözetime, performans optimizasyonlarından ölçeklenebilirlik ipuçlarına kadar birçok konuyu ele alarak, sisteminizi bir sonraki seviyeye taşımanıza yardımcı olacağız.

CI/CD Entegrasyonu ile Otomatik Dağıtım Nasıl Sağlanır?

Dağıtım betiğimizi yazdıktan sonraki doğal adım, onu bir Sürekli Entegrasyon/Sürekli Dağıtım (CI/CD) boru hattına entegre etmektir. CI/CD, yazılım teslim sürecini hızlandıran ve otomatikleştiren bir metodolojidir. Bir CI/CD boru hattı, kod değişikliklerinin otomatik olarak test edilmesini, derlenmesini, Docker imajına dönüştürülmesini ve ardından Blue/Green dağıtım betiğimiz aracılığıyla üretim ortamına dağıtılmasını sağlar.

Popüler CI/CD araçları arasında Jenkins, GitLab CI, GitHub Actions, CircleCI ve Azure DevOps bulunmaktadır. Bir CI/CD boru hattı genellikle şu adımları içerir:

  1. Kod Değişikliği: Geliştiriciler kodu Git deposuna (örneğin GitHub, GitLab) iter.
  2. Tetikleme: Kod değişikliği, CI/CD boru hattını tetikler.
  3. Derleme ve Test: Uygulama kodu derlenir, birim ve entegrasyon testleri çalıştırılır.
  4. Docker İmajı Oluşturma: Başarılı testlerden sonra, uygulamanın Docker imajı oluşturulur ve bir konteyner kayıt defterine (Docker Hub, GitLab Container Registry vb.) gönderilir.
  5. Blue/Green Dağıtımı: Dağıtım betiğimiz (önceki bölümde yazdığımız gibi) çalıştırılır. Bu betik, yeni Docker imajını çeker, yeni ortamı başlatır, sağlık kontrollerini yapar, trafiği yönlendirir ve eski ortamı kaldırır.

Örnek bir .gitlab-ci.yml dosyası (GitLab CI için):



# .gitlab-ci.yml
stages:
  - build
  - deploy

variables:
  DOCKER_IMAGE_NAME: myapp
  DOCKER_REGISTRY: myregistry.example.com

build_image:
  stage: build
  image: docker:latest
  services:
    - docker:dind
  script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
    - docker build -t $DOCKER_REGISTRY/$DOCKER_IMAGE_NAME:$CI_COMMIT_SHORT_SHA .
    - docker push $DOCKER_REGISTRY/$DOCKER_IMAGE_NAME:$CI_COMMIT_SHORT_SHA

deploy_blue_green:
  stage: deploy
  image: alpine/git # Dağıtım betiğini çalıştırmak için hafif bir imaj
  before_script:
    - apk add --no-cache docker-compose curl # Gerekli araçları yükle
    - eval $(ssh-agent -s)
    - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null # SSH anahtarı
    - mkdir -p ~/.ssh && chmod 700 ~/.ssh
    - ssh-keyscan $DEPLOYMENT_SERVER_IP >> ~/.ssh/known_hosts
    - chmod 644 ~/.ssh/known_hosts
  script:
    - ssh $DEPLOYMENT_SERVER_USER@$DEPLOYMENT_SERVER_IP "
        cd /path/to/your/app_directory &&
        # Yeni imajı Docker Compose dosyasında referans almak için
        sed -i 's|myapp:blue|'$DOCKER_REGISTRY'/'$DOCKER_IMAGE_NAME':'$CI_COMMIT_SHORT_SHA'|g' docker-compose.yml &&
        ./deploy.sh
      "
  environment:
    name: production
    url: http://example.com
  only:
    - main


Bu örnek, GitLab CI'ın nasıl bir Docker imajı oluşturup bir kayıt defterine göndereceğini ve ardından SSH üzerinden dağıtım sunucusuna bağlanarak deploy.sh betiğini çalıştıracağını gösterir. Bu tam otomasyon, insan hatasını en aza indirir ve dağıtım süreçlerinin hızını ve güvenilirliğini artırır.

Gözetim ve Uyarı Sistemleri: Sorunları Erken Nasıl Tespit Ederiz?

Kendi kendini onaran bir sistemin etkinliği, iyi bir gözlem ve uyarı sistemine bağlıdır. Sistemdeki anormallikleri erken tespit etmek, otomatik geri alma mekanizmalarını tetiklemek veya manuel müdahaleyi hızlandırmak için kritik öneme sahiptir. İzleme araçları, uygulamanızın performansını, sistem kaynaklarının kullanımını ve Nginx gibi altyapı bileşenlerinin durumunu sürekli olarak denetlemelidir.

Kullanabileceğiniz bazı popüler izleme araçları:

  • Prometheus: Uygulama ve altyapı metriklerini toplamak için güçlü bir araç. Docker konteynerlerinden ve Nginx'ten metrikler toplayabilir.
  • Grafana: Prometheus'tan toplanan metrikleri görselleştirmek için kullanılır. Durum panoları oluşturarak sistemin genel sağlığını kolayca takip edebilirsiniz.
  • ELK Stack (Elasticsearch, Logstash, Kibana): Uygulama ve sistem günlüklerini merkezi olarak toplamak, depolamak ve analiz etmek için idealdir. Hata loglarını izleyerek anormallikleri hızla tespit edebilirsiniz.
  • PagerDuty/Opsgenie: Önemli uyarıları ilgili ekiplere yönlendirmek ve olay yönetimi sağlamak için kullanılır.

Özellikle Nginx, kendi durum metriklerini sağlayabilir (ngx_http_stub_status_module veya Nginx Plus ile daha gelişmiş metrikler). Uygulamalarınızda özel izleme endpoint'leri (örneğin /metrics) tanımlayarak Prometheus'un bu verileri toplamasını sağlayabilirsiniz. Bu metrikler, CPU kullanımı, bellek tüketimi, istek gecikmeleri, hata oranları gibi verileri içerir. Bir dağıtım sonrasında bu metriklerde ani bir artış veya düşüş olması durumunda, sistem otomatik olarak bir uyarı tetikleyebilir veya dağıtım betiğimizdeki geri alma adımlarını başlatabilir.

Uzman İpucu: İzleme sisteminizi, her iki Blue ve Green ortamı da ayrı ayrı izleyecek şekilde yapılandırın. Bu, bir dağıtım sırasında yeni ortamın (yeşil) performansını eski ortamla (mavi) karşılaştırmanıza olanak tanır ve potansiyel sorunları daha hızlı tespit etmenizi sağlar.

Performans Optimizasyonları ve Ölçeklenebilirlik İçin İpuçları

Kendi kendini onaran bir Blue/Green dağıtım, uygulamanızın kararlılığını artırırken, performans ve ölçeklenebilirlik de aynı derecede önemlidir. Nginx ve Docker kullanarak bu alanlarda da iyileştirmeler yapabiliriz:

  • Nginx Önbellekleme: Statik içerikleri (CSS, JS, resimler) veya sık erişilen dinamik içerikleri Nginx'te önbelleğe alarak arka uçtaki uygulama sunucularının yükünü azaltabilirsiniz. Bu, özellikle yüksek trafikli uygulamalar için performansı önemli ölçüde artırır.
  • Nginx Bağlantı Yönetimi: Nginx'in keepalive_timeout ve worker_connections gibi direktiflerini optimize ederek daha fazla eşzamanlı bağlantıyı daha verimli bir şekilde yönetebilirsiniz.
  • Docker Kaynak Sınırları: Docker Compose veya Docker Swarm'da, her bir hizmet için CPU ve bellek sınırları tanımlayarak (resources: limits: cpu: "0.5", memory: "256M" gibi) kaynakların eşit dağıtılmasını ve bir uygulamanın diğerlerini etkilemesini önleyebilirsiniz.
  • Veritabanı ve Harici Servisler: Ölçeklenebilirliğin darboğazı genellikle veritabanı veya harici API'lerdir. Veritabanı optimizasyonlarına yatırım yapın, okuma replikaları kullanın ve önbellekleme katmanları (Redis, Memcached) ekleyin. Harici servis bağımlılıklarını izleyin ve gecikmeleri minimumda tutmaya çalışın.
  • Hizmet Keşfi ve Otomatik Ölçekleme: Daha büyük ve dinamik ortamlar için Docker Swarm veya Kubernetes gibi konteyner orkestrasyon araçları, otomatik hizmet keşfi ve otomatik ölçekleme yetenekleri sunar. Uygulamanızın yüküne göre otomatik olarak yeni örnekler başlatabilir veya mevcutları durdurabilirler. Bu, özellikle dalgalı trafik desenlerine sahip uygulamalar için maliyet verimliliği ve performans artışı sağlar.

Unutmayın, performans ve ölçeklenebilirlik bir kerelik bir iş değildir; uygulamanız geliştikçe sürekli izleme, test etme ve ayarlama gerektiren devam eden bir süreçtir. Bu gelişmiş stratejiler ve otomasyon teknikleri, dağıtım ve operasyon süreçlerinizi daha verimli ve hataya dayanıklı hale getirerek rekabet avantajı sağlamanıza yardımcı olacaktır.

Sonuç ve Sıkça Sorulan Sorular

Bu makale boyunca, Nginx ve Docker kullanarak kendi kendini onaran, sıfır kesintili bir Blue/Green dağıtım stratejisinin nasıl inşa edileceğini detaylı bir şekilde inceledik. Modern yazılım geliştirme pratiklerinin vazgeçilmezi haline gelen bu dağıtım modeli, hem operasyonel riskleri minimize etmek hem de kullanıcıya kesintisiz bir deneyim sunmak için kritik bir rol oynamaktadır. Temel kavramlardan başlayarak, pratik uygulama adımlarına ve gelişmiş otomasyon tekniklerine kadar birçok konuya değindik. Gördüğümüz gibi, Blue/Green dağıtım, sadece yeni bir sürümü canlıya almakla kalmaz, aynı zamanda potansiyel hatalara karşı güçlü bir geri alma mekanizması sunar. Docker'ın konteynerizasyon gücüyle uygulamalarımızı izole edip taşınabilir hale getirdik, Nginx'in dinamik yönlendirme ve yük dengeleme yetenekleriyle trafiği akıllıca yönettik ve CI/CD ile bu süreci tamamen otomatikleştirdik.

Kendi kendini onarma yetenekleri, sağlık kontrolleri ve otomatik geri alma betikleri sayesinde, sistemimiz olası sorunlara karşı daha dirençli hale geldi. Bu tür bir mimariyi benimsemek, ekiplerin daha hızlı, daha güvenli ve daha güvenle dağıtım yapmasına olanak tanır. Sonuç olarak, geliştirme döngüleri hızlanır, hata oranları düşer ve en önemlisi, kullanıcı memnuniyeti artar. Bu stratejiyi uygulayarak, sürekli değişen ve gelişen dijital dünyada rekabetçi kalmaya devam edebilirsiniz. Unutmayın ki teknoloji sürekli evriliyor ve en iyi pratikler de bununla birlikte değişiyor. Bu nedenle, öğrendiklerimizi uygulamak ve sistemlerimizi sürekli olarak iyileştirmek esastır.

Sıkça Sorulan Sorular (SSS)

S1: Blue/Green dağıtımının diğer dağıtım stratejilerine göre avantajları nelerdir?
C1: En büyük avantajı, sıfır kesintiyle dağıtım ve anında geri alma (rollback) yeteneğidir. Canary dağıtımı gibi diğer stratejilerle karşılaştırıldığında, Blue/Green genellikle daha basit bir geçişe sahiptir, çünkü trafiği iki tamamen ayrı ortam arasında değiştirir. Bu, risk toleransının düşük olduğu ve kesintisiz hizmetin mutlak olduğu durumlar için idealdir.
S2: Blue/Green dağıtımı maliyetli midir?
C2: Evet, Blue/Green dağıtımı iki özdeş üretim ortamının paralel çalışmasını gerektirdiği için altyapı maliyetleri açısından genellikle daha fazladır. Ancak, bu ek maliyet, dağıtım kesintilerinin neden olabileceği potansiyel gelir kaybı, marka zedelenmesi ve operasyonel maliyetlerle karşılaştırıldığında çoğu zaman kabul edilebilir, hatta avantajlıdır. Özellikle bulut sağlayıcılarda (AWS, Azure, GCP) talep üzerine kaynakları kolayca sağlayıp sonradan kapatabildiğiniz için bu maliyet optimize edilebilir.
S3: Veritabanı güncellemeleri Blue/Green dağıtımında nasıl yönetilir?
C3: Veritabanı şema değişiklikleri, Blue/Green dağıtımında genellikle en zorlu kısımdır. Genellikle "ileri-uyumlu" (forward-compatible) ve "geri-uyumlu" (backward-compatible) değişiklikler yapılması önerilir. Yani, yeni sürümün eski veritabanı şemasıyla çalışabilmesi ve eski sürümün de yeni şemayla çalışabilmesi gerekir. Bu genellikle aşamalı şema güncellemeleri ve geçici çift yazma stratejileri ile sağlanır. Veritabanı geçiş araçları (örneğin Flyway, Liquibase) bu süreçte yardımcı olabilir.
S4: Nginx yerine başka bir yük dengeleyici veya API Gateway kullanabilir miyim?
C4: Kesinlikle! Nginx bu makalede örnek olarak kullanılmıştır, ancak HaProxy, Apache HTTP Server (mod_proxy ile), Envoy Proxy veya bulut sağlayıcılarının yük dengeleyicileri (AWS ELB/ALB, Azure Application Gateway, GCP Load Balancer) gibi alternatifleri de kullanabilirsiniz. Önemli olan, seçtiğiniz aracın dinamik yapılandırma ve sağlık kontrolü yeteneklerine sahip olmasıdır.
S5: Kendi kendini onarma yeteneği olmayan bir Blue/Green dağıtım kurmak yine de mantıklı mı?
C5: Evet, kesinlikle! Kendi kendini onarma, Blue/Green dağıtımına ek bir güvenlik ve otomasyon katmanı ekler. Ancak, temel Blue/Green dağıtımının kendisi bile sıfır kesinti ve hızlı geri alma yetenekleri ile dağıtım süreçlerinizde büyük bir iyileşme sağlar. Otomatik geri alma adımları olmadan da, bir hata durumunda manuel olarak eski ortama dönme seçeneğiniz her zaman bulunur. Kendi kendini onarma özelliklerini zamanla sisteminize entegre edebilirsiniz.

Yorumlar
İçeriği beğendiniz mi? Bir tartışma başlatın veya görüşlerinizi paylaşın.
Yorum Yaz

Bir yanıt yazın

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

E-posta Bülteni
Yazılım Topluluğuna Katılın
En son güncellemeleri, yaratıcı ipuçlarını ve özel kaynakları doğrudan e-posta kutunuza alın. Tasarım ve inovasyonun geleceğini birlikte keşfedelim.