Tek bir Docker host’unuzda her şey yolunda gidiyorken, bir gün trafik patlaması yaşanıyor ve o tek makine artık yük altında ezilmeye başlıyor. Ya da daha kötüsü, o makine çöküyor ve tüm servisleriniz birden erişilemez hale geliyor. İşte bu noktada Docker Swarm devreye giriyor. Swarm, birden fazla Docker host’unu bir araya getirip tek bir mantıksal küme olarak yönetmenizi sağlıyor. Kubernetes kadar karmaşık değil, ama production ortamları için gayet yeterli. Bu yazıda sıfırdan Swarm kurulumu yapacak, servis yönetimini öğrenecek ve gerçek dünya senaryolarıyla konuyu pekiştireceğiz.
Docker Swarm Nedir, Ne Değildir?
Docker Swarm, Docker’ın kendi bünyesinde gelen orkestrasyon çözümüdür. Ek bir araç kurmanıza gerek yok, Docker kuruluysa Swarm da kullanıma hazırdır. Kubernetes ile karşılaştırıldığında öğrenme eğrisi çok daha düzdür, küçük ve orta ölçekli altyapılar için mükemmel bir seçimdir.
Swarm dünyasında iki tür node vardır:
- Manager node: Kümenin beynidur. Servis tanımlarını saklar, görevleri dağıtır, küme durumunu izler.
- Worker node: Asıl işi yapan makinelerdir. Konteynerları çalıştırır, manager’dan gelen görevleri yerine getirir.
Manager node’lar aynı zamanda worker olarak da çalışabilir, ama production’da manager’ları sadece orkestrasyon için ayırmak daha sağlıklıdır.
Swarm’ın temel kavramlarına bakalım:
- Service: Swarm üzerinde çalıştırmak istediğiniz uygulamanın tanımıdur. “Nginx’in 3 kopyasını çalıştır” gibi bir direktif.
- Task: Bir servisin her bir konteyner örneğidir. 3 replika demek 3 task demektir.
- Stack: Birden fazla servisin bir arada tanımlandığı compose dosyasının Swarm üzerindeki karşılığıdır.
- Overlay Network: Farklı node’lardaki konteynerların birbiriyle iletişim kurmasını sağlayan sanal ağdur.
Lab Ortamının Hazırlanması
Ben bu yazıda 3 node’luk bir küme kuracağım. Gerçek sunucularınız olabilir, cloud VM’ler olabilir, hatta aynı makinede birden fazla VM çalıştırabilirsiniz. Önemli olan şu:
- Her node’da Docker kurulu olmalı
- Node’lar birbirinin IP adreslerine ulaşabilmeli
- Gerekli portlar açık olmalı
Açılması gereken portlar:
- 2377/tcp: Swarm yönetim trafiği için
- 7946/tcp ve 7946/udp: Node’lar arası iletişim için
- 4789/udp: Overlay network trafiği için
Node IP adreslerim şu şekilde:
- manager1: 192.168.1.10
- worker1: 192.168.1.11
- worker2: 192.168.1.12
Firewall kurallarını ayarlayalım (UFW kullanıyorsanız):
# Manager ve worker node'ların hepsinde çalıştırın
ufw allow 2377/tcp
ufw allow 7946/tcp
ufw allow 7946/udp
ufw allow 4789/udp
ufw reload
Swarm Kümesini Oluşturmak
Manager node üzerinde başlatma işlemini yapalım:
# manager1 üzerinde çalıştırın
docker swarm init --advertise-addr 192.168.1.10
Bu komutun çıktısı şuna benzer bir şey olacak:
Swarm initialized: current node (abc123xyz) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-abc123...xyz789 192.168.1.10:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
Çıktıdaki join token’ı saklayın. Worker node’ları eklemek için kullanacaksınız.
Eğer token’ı kaybettiyseniz panik yapmayın, her zaman tekrar alabilirsiniz:
# Worker token'ı görüntüle
docker swarm join-token worker
# Manager token'ı görüntüle
docker swarm join-token manager
Şimdi worker node’ları kümeye ekleyelim. worker1 ve worker2 üzerinde çalıştırın:
docker swarm join
--token SWMTKN-1-abc123...xyz789
192.168.1.10:2377
Manager node üzerinde küme durumunu kontrol edelim:
docker node ls
Çıktı şuna benzer görünmeli:
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
abc123 * manager1 Ready Active Leader
def456 worker1 Ready Active
ghi789 worker2 Ready Active
Artık 3 node’luk bir Swarm kümemiz var. Şimdi asıl işe girelim.
İlk Servisinizi Oluşturmak
Swarm’da servis oluşturmak, docker run komutuna benzer ama çok daha güçlüdür. Bir Nginx servisi oluşturalım:
docker service create
--name web-server
--replicas 3
--publish published=80,target=80
nginx:alpine
Bu komutla ne yaptık:
- –name web-server: Servise bir isim verdik
- –replicas 3: 3 kopya çalıştırmasını istedik
- –publish published=80,target=80: Port mapping yaptık
- nginx:alpine: Kullanacağımız image
Servis durumunu kontrol edelim:
# Genel servis listesi
docker service ls
# Belirli bir servisin detayları
docker service ps web-server
docker service ps komutu size her task’ın hangi node üzerinde çalıştığını gösterir. 3 task’ın 3 farklı node’a dağıtıldığını göreceksiniz.
Servis Ölçeklendirme ve Güncelleme
Gerçek dünyada en sık yapacağınız işlemlerden biri servisi ölçeklendirmektir. Trafik arttı, daha fazla replica lazım:
# Replica sayısını 5'e çıkar
docker service scale web-server=5
# Birden fazla servisi aynı anda ölçeklendir
docker service scale web-server=5 api-server=3
Peki uygulama güncellemesi nasıl yapılır? Zero-downtime deployment Swarm’ın en güçlü özelliklerinden biridir:
docker service update
--image nginx:1.25-alpine
--update-parallelism 2
--update-delay 10s
web-server
Buradaki parametreler kritiktir:
- –update-parallelism 2: Aynı anda kaç task’ın güncelleneceği
- –update-delay 10s: Her batch güncellemesi arasında kaç saniye bekleyeceği
Bu sayede tüm replica’lar aynı anda kapanmaz, servis kesintisiz çalışmaya devam eder.
Güncelleme sırasında bir sorun çıkarsa geri almak çok kolay:
docker service rollback web-server
Overlay Network ve Servisler Arası İletişim
Gerçek uygulamalarda servisler birbiriyle konuşmak zorundadır. Bir web uygulaması veritabanıyla, API gateway mikroservislerle iletişim kurar. Swarm’da bu overlay network ile sağlanır.
Önce özel bir overlay network oluşturalım:
docker network create
--driver overlay
--attachable
app-network
Şimdi bu network üzerinde birbirleriyle konuşabilen servisler oluşturalım:
# Veritabanı servisi
docker service create
--name postgres-db
--network app-network
--env POSTGRES_PASSWORD=gizli123
--env POSTGRES_DB=myapp
--replicas 1
postgres:15-alpine
# API servisi
docker service create
--name api-server
--network app-network
--publish published=8080,target=8080
--replicas 3
--env DATABASE_URL=postgresql://postgres:gizli123@postgres-db:5432/myapp
myapp/api:latest
Dikkat edin, API servisi veritabanına postgres-db ismiyle bağlanıyor. Swarm’ın dahili DNS’i bu ismi otomatik olarak çözümler. Node değişse bile, task yeniden başlasa bile servis ismi her zaman erişilebilir olur. Bu çok büyük bir kolaylık.
Stack ile Çoklu Servis Yönetimi
Tek tek servis oluşturmak küçük testler için işe yarar ama production’da onlarca servisiniz olacak. İşte bu noktada Stack devreye girer. Bir docker-compose.yml benzeri dosyayla tüm uygulamanızı tek komutla yönetirsiniz.
Bir e-ticaret uygulaması için stack dosyası yazalım:
# docker-stack.yml
version: '3.8'
services:
web:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
networks:
- frontend
- backend
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 10s
failure_action: rollback
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
api:
image: myapp/api:2.1.0
networks:
- backend
environment:
- NODE_ENV=production
- DB_HOST=db
deploy:
replicas: 4
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M
db:
image: postgres:15-alpine
networks:
- backend
environment:
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
POSTGRES_DB: ecommerce
volumes:
- db-data:/var/lib/postgresql/data
deploy:
replicas: 1
placement:
constraints:
- node.role == worker
- node.labels.disk == ssd
volumes:
db-data:
networks:
frontend:
driver: overlay
backend:
driver: overlay
internal: true
secrets:
db_password:
external: true
Stack’i deploy edelim:
docker stack deploy -c docker-stack.yml ecommerce
Stack durumunu kontrol etmek:
# Stack listesi
docker stack ls
# Stack içindeki servisler
docker stack services ecommerce
# Tüm task'ların durumu
docker stack ps ecommerce
Swarm Secret Yönetimi
Production ortamında şifreleri environment variable olarak geçmek güvenlik açığıdır. Swarm’ın secret yönetimi bu sorunu çözer. Secret’lar şifreli olarak saklanır ve sadece ihtiyacı olan servislere açılır.
# Komut satırından secret oluştur
echo "super_gizli_sifre_123" | docker secret create db_password -
# Dosyadan secret oluştur
docker secret create ssl_certificate ./cert.pem
# Secret listesi
docker secret ls
Secret kullanan bir servis oluşturalım:
docker service create
--name secure-db
--secret db_password
--env POSTGRES_PASSWORD_FILE=/run/secrets/db_password
postgres:15-alpine
Secret, konteyner içinde /run/secrets/secret_ismi yolunda dosya olarak belirir. Uygulama bu dosyayı okur, şifre asla environment variable’da görünmez.
Node Yönetimi ve Placement Constraints
Production’da tüm servisler tüm node’larda çalışmamalıdır. Veritabanını SSD diskli node’larda, ağır hesaplama işlerini yüksek CPU’lu node’larda çalıştırmak istersiniz. Bunun için node label’ları kullanırsınız.
# Node'a label ekle
docker node update --label-add disk=ssd worker1
docker node update --label-add disk=hdd worker2
docker node update --label-add role=compute worker2
# Node detaylarını görüntüle
docker node inspect worker1 --pretty
Placement constraint ile servislerinizi belirli node’lara yönlendirin:
docker service create
--name high-perf-db
--constraint 'node.labels.disk == ssd'
--constraint 'node.role == worker'
postgres:15-alpine
Bir node’u bakıma almak istediğinizde availability’yi değiştirin. Bu sayede o node üzerindeki task’lar diğer node’lara taşınır:
# Node'u bakım moduna al
docker node update --availability drain worker1
# Bakım tamamlandı, node'u aktif et
docker node update --availability active worker1
Global Servisler
Bazı servisler her node’da tam olarak bir kez çalışmalıdır. Log toplayıcılar, monitoring agent’lar bunun en iyi örneğidir. Bunun için global mod kullanılır:
docker service create
--name node-exporter
--mode global
--publish published=9100,target=9100
--mount type=bind,source=/proc,target=/host/proc,readonly
--mount type=bind,source=/sys,target=/host/sys,readonly
prom/node-exporter:latest
Global modda kaç node varsa o kadar task oluşturulur. Yeni bir node eklendiğinde otomatik olarak o node’a da deploy edilir. Kümeye 5. node eklediğinizde node-exporter oraya da otomatik gelir.
Health Check ve Otomatik Yeniden Başlatma
Swarm, başarısız task’ları otomatik olarak yeniden başlatır. Ama bunu doğru yapabilmesi için uygulamanızın sağlık durumunu bilmesi gerekir.
Health check tanımlı bir servis oluşturalım:
docker service create
--name api-with-health
--replicas 3
--health-cmd "curl -f http://localhost:8080/health || exit 1"
--health-interval 30s
--health-timeout 10s
--health-retries 3
--health-start-period 60s
myapp/api:latest
Bu parametreler ne anlama gelir:
- –health-cmd: Sağlık kontrolü için çalıştırılacak komut
- –health-interval 30s: Her 30 saniyede bir kontrol et
- –health-timeout 10s: 10 saniye içinde cevap gelmezse başarısız say
- –health-retries 3: 3 başarısız denemeden sonra unhealthy işaretle
- –health-start-period 60s: Konteyner başladıktan sonra 60 saniye bekle, bu sürede başarısızlıkları sayma
Bir task sürekli başarısız olursa Swarm onu yeniden başlatır. Restart policy stack dosyasında şöyle tanımlanır:
- condition: on-failure: Sadece başarısız olduğunda yeniden başlat
- delay: 5s: Yeniden başlatmadan önce 5 saniye bekle
- max_attempts: 3: En fazla 3 kez dene
- window: 120s: 120 saniyelik pencerede dene
Gerçek Dünya Senaryosu: Rolling Update Stratejisi
Bir e-ticaret sitesi yönettiğinizi düşünün. Cuma akşamı 23:00’da yeni bir sürüm deploy etmeniz gerekiyor. Aşağıdaki strateji ile sıfır kesinti sağlarsınız:
# Önce mevcut durumu not edin
docker service ps ecommerce_api --no-trunc
# Yeni image'ı deploy et, dikkatli bir stratejiyle
docker service update
--image myapp/api:2.2.0
--update-parallelism 1
--update-delay 30s
--update-failure-action rollback
--update-monitor 60s
--update-max-failure-ratio 0.3
ecommerce_api
Kritik parametreler:
- –update-failure-action rollback: Güncelleme başarısız olursa otomatik geri al
- –update-monitor 60s: Her task güncellendikten sonra 60 saniye izle
- –update-max-failure-ratio 0.3: Task’ların yüzde 30’u başarısız olursa güncellemeyi durdur
Bu parametrelerle güncelleme sırasında bir sorun çıkarsa Swarm müdahale beklemeden geri alır. Pazar sabahı işe geldiğinizde sistemi sağlam bulursunuz.
Monitoring ve Loglar
Swarm kümesini izlemek için birkaç temel komut:
# Küme genelinde çalışan tüm servisleri listele
docker service ls
# Belirli bir servisin loglarını takip et
docker service logs -f web-server
# Son 100 satır log
docker service logs --tail 100 api-server
# Tüm stack logları
docker stack ps ecommerce --no-trunc
# Node kaynak kullanımı
docker node ls
docker system df
Uyarı: docker service logs komutu tüm node’lardan logları toplar. Büyük bir kümede bu çok fazla çıktı üretebilir. Gerçek production’da Elasticsearch, Loki veya benzeri bir merkezi log sistemi kullanmanızı kesinlikle tavsiye ederim.
Görsel bir dashboard istiyorsanız Portainer kullanabilirsiniz:
docker service create
--name portainer
--publish 9000:9000
--constraint 'node.role == manager'
--mount type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock
--mount type=volume,source=portainer_data,target=/data
portainer/portainer-ce:latest
Portainer, Swarm kümesini tarayıcıdan yönetmenizi sağlar. Servis oluşturma, ölçeklendirme, log görüntüleme gibi işlemleri GUI üzerinden yapabilirsiniz.
Yaygın Sorunlar ve Çözümleri
Sorun: Task pending durumunda kalıyor
Bir task başlamıyorsa önce şunu kontrol edin:
docker service ps --no-trunc web-server
Çıktıdaki hata mesajına bakın. Genellikle image bulunamadı, yetersiz kaynak veya placement constraint uyumsuzluğu gibi nedenleri vardır.
Sorun: Node ulaşılamıyor
# Node durumunu kontrol et
docker node inspect worker1 --pretty
# Node'u kümeden güvenli çıkar
docker node update --availability drain worker1
docker node rm worker1
Sorun: Overlay network sorunları
# Network listesi
docker network ls
# Network detayları
docker network inspect app-network
Overlay network sorunlarının büyük çoğunluğu firewall kurallarından kaynaklanır. 4789/udp portunu her node’da kontrol edin.
Sonuç
Docker Swarm, özellikle Kubernetes’e geçmeye henüz hazır olmayan ya da geçmeyi düşünmeyen ekipler için mükemmel bir çözümdür. Kurulumu basit, yönetimi anlaşılır ve Docker ekosistemiyle mükemmel entegre olur.
Bu yazıda ele aldıklarımızın özeti:
- Swarm kümesini sıfırdan nasıl kuracağınızı ve node’ları nasıl ekleyeceğinizi gördünüz
- Temel servis oluşturma, ölçeklendirme ve güncelleme işlemlerini öğrendiniz
- Overlay network ile servisler arası iletişimi kurguladınız
- Stack dosyalarıyla çoklu servis yönetimini öğrendiniz
- Secret yönetimiyle güvenli konfigürasyon saklamayı gördünüz
- Node label’ları ve placement constraint’ler ile akıllı dağıtım yaptınız
- Sıfır kesintili rolling update stratejisi uyguladınız
Bir sonraki adım olarak Swarm üzerinde Traefik gibi bir reverse proxy kurarak SSL termination ve otomatik servis keşfini eklemenizi öneririm. Ayrıca Prometheus ve Grafana ile metrik toplamanızı da planınıza ekleyin. Sağlam bir Swarm kurulumu, takımınıza deployment güveni ve altyapınıza esneklik kazandırır.