SaltStack Altyapısı: HAProxy Yük Dengeleyiciler İçin Salt State’leri Oluşturma
SaltStack, modern IT altyapılarında yapılandırma yönetimi, otomasyon ve orkestrasyon için güçlü, açık kaynaklı bir araçtır. Sunucuları ve ağ cihazlarını merkezi bir noktadan yönetme yeteneği sayesinde, altyapı operasyonlarını basitleştirir ve hata oranını düşürür. Diğer yandan, HAProxy (High Availability Proxy), yüksek performanslı ve güvenilir bir yük dengeleyici ve TCP/HTTP proxy çözümüdür. Web uygulamalarının ölçeklenebilirliğini ve yüksek erişilebilirliğini sağlamak için kritik bir bileşendir. Bu makale, SaltStack’in gücünü kullanarak HAProxy yük dengeleyicilerin kurulumunu, yapılandırmasını ve yönetimini otomatikleştirmek için Salt State’leri (durum dosyaları) nasıl oluşturulacağını detaylı bir şekilde inceleyecektir. SaltStack ve HAProxy’nin birleşimi, tutarlı, tekrarlanabilir ve ölçeklenebilir bir yük dengeleme altyapısı kurmanın anahtarını sunar.
SaltStack Temelleri
SaltStack, master-minion mimarisi üzerinde çalışır. Bir Salt Master, yapılandırma komutlarını ve durum dosyalarını (states) yönetirken, Salt Minion’lar bu komutları ve durumları hedef sunucularda uygular.
Salt Master ve Minion
Salt Master, tüm SaltStack operasyonlarının merkezi kontrol noktasıdır. Minion’lar ise, Master’dan gelen talimatları dinleyen ve uygulayan istemci makinelerdir. İletişim, genellikle ZeroMQ üzerinden şifreli bir kanalda gerçekleşir. Minion’lar, Master’a bağlanmak için kimlik doğrulaması yapar ve Master tarafından yetkilendirildikten sonra komutları almaya başlar.
Salt States (SLS Dosyaları)
Salt States veya SLS dosyaları, SaltStack’in yapılandırma yönetimi için temel bileşenleridir. Bu dosyalar, bir sistemin belirli bir durumda olmasını sağlamak için gerekli adımları tanımlayan YAML tabanlı bildirimsel yapılardır. Her state, bir Salt modülünü (örneğin, pkg modülü paket yönetimi için, service modülü servis yönetimi için) ve bu modülün bir fonksiyonunu (örneğin, pkg.installed, service.running) çağırır. Salt States, idempotenttir; yani, bir state’i birden fazla kez çalıştırmak, sistem üzerinde yalnızca gerekli değişiklikleri yapar ve zaten istenen durumda olan bileşenleri etkilemez. Bu, tutarlı ve öngörülebilir sonuçlar sağlar.
Pillar
Pillar, SaltStack’te hassas verileri (şifreler, API anahtarları vb.) veya minion’a özel yapılandırma verilerini güvenli bir şekilde depolamak ve minion’lara iletmek için kullanılan bir sistemdir. Pillar verileri, minion’lar tarafından doğrudan erişilemez; yalnızca Master, bir minion’ın yalnızca kendisine ait olan Pillar verilerine erişebileceğini garanti eder. Bu, yapılandırma dosyalarında doğrudan sabit kodlanmış değerler yerine dinamik ve güvenli yapılandırma sağlamak için idealdir.
Grains
Grains, bir minion hakkında statik bilgileri (işletim sistemi, IP adresi, CPU sayısı, bellek miktarı gibi) temsil eden verilerdir. Bu veriler, minion başladığında veya salt-call grains.ls gibi komutlarla toplanır. Grains, Salt Master’ın belirli özelliklere sahip minion’ları hedeflemesini sağlar. Örneğin, sadece Ubuntu sunucularına veya belirli bir rolü olan sunuculara state uygulamak için Grains kullanılabilir.
Top File
top.sls dosyası, SaltStack’in hangi minion’lara hangi state’leri uygulayacağını belirleyen ana haritalama dosyasıdır. Grains, minion ID’leri veya diğer hedefleme kriterleri kullanılarak, belirli gruplardaki minion’lara belirli state’ler atanır. Bu, büyük altyapılarda yapılandırma yönetimini organize etmenin ve ölçeklendirmenin temel yoludur.
Salt Dosya Sunucusu
Salt Master, state dosyaları, Pillar verileri, Jinja şablonları ve diğer statik dosyalar için bir dosya sunucusu görevi görür. Minion’lar, bu dosyaları Master’dan çekerek yerel sistemlerinde kullanır. Bu merkezi depolama, yapılandırma dosyalarının versiyon kontrolünü ve dağıtımını kolaylaştırır.
HAProxy Temelleri
HAProxy, TCP ve HTTP tabanlı uygulamalar için yüksek performanslı ve güvenilir bir yük dengeleyici çözümdür. Genellikle web sunucuları, veritabanı sunucuları ve uygulama sunucuları gibi birden fazla sunucu arasında trafiği dağıtmak için kullanılır.
HAProxy Mimarisi
HAProxy’nin temel mimarisi üç ana bileşenden oluşur:
* Frontend: Gelen bağlantıları dinleyen ve hangi backend‘e yönlendirileceğini belirleyen kısımdır. IP adresi, port ve protokol gibi bilgileri içerir.
* Backend: Gerçek sunucuların (örneğin web sunucuları) gruplarını tanımlar. Yük dengeleme algoritması, sağlık kontrolleri ve sunucu listesi bu bölümde belirlenir.
* Server: Backend grubunun içindeki her bir fiziksel sunucuyu temsil eder. IP adresi, port ve diğer sunucuya özel seçenekler burada belirtilir.
Temel Yapılandırma Bileşenleri
HAProxy yapılandırma dosyası (haproxy.cfg) çeşitli bölümlerden oluşur:
* global: HAProxy sürecine genel ayarlar (loglama, kullanıcı/grup, performans ayarları).
* defaults: frontend, backend ve listen bölümleri için varsayılan ayarlar.
* listen: Hem frontend hem de backend işlevselliğini tek bir blokta birleştiren eski bir yöntemdir, ancak hala kullanılmaktadır.
* bind: frontend veya listen bloklarında gelen bağlantıları dinlenecek IP adresi ve portu belirtir.
* mode: Bağlantı modunu belirler (tcp veya http).
* balance: Yük dengeleme algoritmasını belirler (örneğin, roundrobin, leastconn, source).
* option: Çeşitli seçenekleri etkinleştirir veya devre dışı bırakır (örneğin, http-check, forwardfor).
Yüksek Erişilebilirlik (HA) ve Yük Dengeleme Stratejileri
HAProxy, farklı yük dengeleme algoritmaları sunar:
* Round-robin: Sunuculara sırayla bağlantı dağıtır.
* Least-conn: En az aktif bağlantıya sahip sunucuya yeni bağlantıyı yönlendirir.
* Source: İstemcinin kaynak IP adresine göre bağlantıyı aynı sunucuya yönlendirir (sticky session için kullanışlıdır).
* Health Checks: HAProxy, check seçeneği ile backend sunucularının sağlık durumunu düzenli olarak kontrol eder. Sağlıksız sunucular havuzdan çıkarılır ve tekrar sağlıklı hale geldiğinde geri eklenir. Bu, yüksek erişilebilirliğin temelini oluşturur.
SaltStack ile HAProxy Entegrasyonu
Şimdi, SaltStack’i kullanarak bir HAProxy yük dengeleyicinin nasıl kurulacağını ve yapılandırılacağını adım adım inceleyelim. Senaryomuzda, iki adet web sunucusuna (örneğin Nginx veya Apache) gelen trafiği dengeleyecek tek bir HAProxy sunucusu kuracağız.
Hedef Belirleme ve Senaryo
* Bir HAProxy sunucusu üzerinde HAProxy paketinin kurulumu.
* HAProxy yapılandırma dosyasının (haproxy.cfg) SaltStack Pillar verileri kullanılarak dinamik olarak oluşturulması.
* HAProxy servisinin başlatılması ve sistem açılışında otomatik başlaması.
* HAProxy loglarının yönetimi (isteğe bağlı ama iyi bir uygulama).
* HAProxy istatistik sayfasının etkinleştirilmesi.
Dizin Yapısı Oluşturma
Salt Master üzerinde aşağıdaki gibi bir dizin yapısı oluşturacağız:
/srv/salt/
├── top.sls
└── haproxy/
├── init.sls
├── config.sls
└── files/
└── haproxy.cfg.j2
/srv/pillar/
├── top.sls
└── haproxy.sls
* /srv/salt/top.sls: Hangi minion’a hangi Salt state’lerinin uygulanacağını belirler.
* /srv/salt/haproxy/init.sls: HAProxy paketini kurar ve servisi yönetir.
* /srv/salt/haproxy/config.sls: HAProxy yapılandırma dosyasını oluşturur.
* /srv/salt/haproxy/files/haproxy.cfg.j2: HAProxy yapılandırma dosyasının Jinja2 şablonu.
* /srv/pillar/top.sls: Hangi minion’a hangi Pillar verilerinin gönderileceğini belirler.
* /srv/pillar/haproxy.sls: HAProxy yapılandırması için Pillar verilerini içerir.
HAProxy Paketi Kurulumu ve Servis Yönetimi
İlk olarak, HAProxy paketini kuracak ve servisin çalışır durumda olmasını sağlayacak bir state oluşturalım:
/srv/salt/haproxy/init.sls
{% if grains['os_family'] == 'Debian' %}
haproxy_pkg:
pkg.installed:
- name: haproxy
haproxy_service:
service.running:
- name: haproxy
- enable: True
- watch:
- file: /etc/haproxy/haproxy.cfg
{% elif grains['os_family'] == 'RedHat' %}
haproxy_pkg:
pkg.installed:
- name: haproxy
haproxy_service:
service.running:
- name: haproxy
- enable: True
- watch:
- file: /etc/haproxy/haproxy.cfg
{% endif %}
Bu state, işletim sistemi ailesine göre haproxy paketini kurar ve haproxy servisinin çalışır durumda olmasını ve sistem başlangıcında etkinleştirilmesini sağlar. watch ifadesi, /etc/haproxy/haproxy.cfg dosyasında bir değişiklik olduğunda servisin yeniden başlatılmasını tetikler.
HAProxy Yapılandırma Dosyası Oluşturma
Şimdi, HAProxy’nin ana yapılandırma dosyasını Pillar verilerini kullanarak dinamik olarak oluşturacak state’i ve Jinja2 şablonunu tanımlayalım.
/srv/salt/haproxy/config.sls
/etc/haproxy/haproxy.cfg:
file.managed:
- source: salt://haproxy/files/haproxy.cfg.j2
- template: jinja
- user: root
- group: root
- mode: 644
- require:
- pkg: haproxy_pkg # 'haproxy_pkg' from init.sls
- watch_in:
- service: haproxy_service # 'haproxy_service' from init.sls
Bu state, /etc/haproxy/haproxy.cfg dosyasının içeriğini haproxy.cfg.j2 şablonundan almasını sağlar. template: jinja ile Pillar verilerini kullanabileceğimizi belirtiyoruz. require ile HAProxy paketinin kurulu olmasını, watch_in ile de yapılandırma değiştiğinde servisin yeniden başlatılmasını sağlıyoruz.
/srv/salt/haproxy/files/haproxy.cfg.j2
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
stats timeout 30s
user haproxy
group haproxy
daemon
# maxconn 20000 # Max connections per process
# pidfile /var/run/haproxy.pid
defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000
Frontend for web application
frontend {{ pillar['haproxy']['frontend_name'] }}
bind *:{{ pillar['haproxy']['frontend_port'] }}
mode http
default_backend {{ pillar['haproxy']['backend_name'] }}
Backend for web servers
backend {{ pillar['haproxy']['backend_name'] }}
balance {{ pillar['haproxy']['balance_algorithm'] }}
{% for server in pillar['haproxy']['backend_servers'] %}
server {{ server.name }} {{ server.ip }}:{{ server.port }} check inter 2s fall 3 rise 2
{% endfor %}
HAProxy Statistics Page
listen stats
bind *:{{ pillar['haproxy']['stats_port'] }}
mode http
stats enable
stats uri /haproxy_stats
stats realm Haproxy\ Statistics
stats auth {{ pillar['haproxy']['stats_user'] }}:{{ pillar['haproxy']['stats_password'] }}
stats hide-version
stats refresh 5s
Bu Jinja2 şablonu, HAProxy yapılandırmasını Pillar’dan gelen verilerle dinamik olarak oluşturur. Örneğin, {{ pillar['haproxy']['frontend_port'] }} ifadesi, Pillar’daki haproxy:frontend_port değerini çeker. {% for server in pillar['haproxy']['backend_servers'] %} döngüsü ile backend sunucuları listesi dinamik olarak oluşturulur.
Pillar Verilerini Tanımlama
Şimdi HAProxy yapılandırmamız için gerekli Pillar verilerini oluşturalım:
/srv/pillar/haproxy.sls
haproxy:
frontend_name: my_webapp_frontend
frontend_port: 80
backend_name: web_servers_backend
balance_algorithm: roundrobin
backend_servers:
- name: webserver1
ip: 192.168.1.101
port: 80
- name: webserver2
ip: 192.168.1.102
port: 80
stats_port: 8080
stats_user: admin
stats_password: securepassword123
Bu Pillar dosyası, HAProxy’nin dinleyeceği port, backend sunucularının IP adresleri, yük dengeleme algoritması ve istatistik sayfası kimlik bilgileri gibi tüm dinamik değerleri içerir.
Son olarak, bu Pillar verilerini HAProxy minion’una atamak için top.sls dosyasını düzenlememiz gerekiyor:
/srv/pillar/top.sls
base:
'haproxy_minion_id': # Hedef minion ID'si veya Grains ile hedefleme
- haproxy
Burada haproxy_minion_id yerine gerçek minion ID’nizi veya G@os:Debian and G@roles:haproxy gibi bir Grains hedeflemesi kullanabilirsiniz.
Top File Yapılandırması
Salt Master’ın hangi minion’lara hangi state’leri uygulayacağını bildiren top.sls dosyasını yapılandıralım:
/srv/salt/top.sls
base:
'haproxy_minion_id': # Hedef minion ID'si veya Grains ile hedefleme
- haproxy # Bu, /srv/salt/haproxy/init.sls ve /srv/salt/haproxy/config.sls'i içerir
SaltStack, bir dizin adı verildiğinde (örneğin haproxy), o dizindeki init.sls dosyasını otomatik olarak arar ve çalıştırır. init.sls içinde, include veya extend kullanarak diğer state’leri de dahil edebiliriz. Bizim örneğimizde, haproxy/init.sls ve haproxy/config.sls dosyalarını aynı dizine koyarak ve init.sls içinde config.sls‘i dahil ederek daha modüler bir yapı oluşturabiliriz. Ancak basitlik adına, top.sls‘in sadece haproxy state’ini çağırması ve haproxy/init.sls‘in config.sls‘i çağırması daha iyi bir yaklaşımdır.
/srv/salt/haproxy/init.sls (Güncellenmiş hali)
include:
- haproxy.config # haproxy/config.sls'i dahil eder
{% if grains['os_family'] == 'Debian' %}
haproxy_pkg:
pkg.installed:
- name: haproxy
haproxy_service:
service.running:
- name: haproxy
- enable: True
- watch:
- file: /etc/haproxy/haproxy.cfg
{% elif grains['os_family'] == 'RedHat' %}
haproxy_pkg:
pkg.installed:
- name: haproxy
haproxy_service:
service.running:
- name: haproxy
- enable: True
- watch:
- file: /etc/haproxy/haproxy.cfg
{% endif %}
Bu şekilde, top.sls sadece haproxy state’ini çağırır ve haproxy/init.sls hem paketi kurar hem de yapılandırma dosyasını oluşturan haproxy/config.sls‘i dahil eder.
Gelişmiş Yapılandırmalar ve En İyi Uygulamalar
SaltStack ile HAProxy yönetimi, sadece temel kurulumdan ibaret değildir. Daha karmaşık senaryolar ve en iyi uygulamalarla altyapınızı daha da güçlendirebilirsiniz.
Yüksek Erişilebilirlik (HA) için Keepalived Entegrasyonu
Tek bir HAProxy sunucusu, tek hata noktası (Single Point of Failure – SPoF) oluşturur. Yüksek erişilebilirlik için iki veya daha fazla HAProxy sunucusunu aktif/pasif veya aktif/aktif modda çalıştırmak ve sanal bir IP adresi (VIP) kullanmak gerekir. Keepalived, VRRP (Virtual Router Redundancy Protocol) kullanarak bu sanal IP adresini yönetir ve birincil HAProxy sunucusu çöktüğünde VIP’yi yedek sunucuya otomatik olarak taşır. SaltStack ile Keepalived state’leri yazarak bu süreci tamamen otomatikleştirebilirsiniz:
* Keepalived paketi kurulumu: pkg.installed
* Keepalived yapılandırma dosyası (keepalived.conf) oluşturma: Pillar verileriyle Jinja2 şablonları kullanarak VIP, öncelikler ve sağlık kontrolleri tanımlanabilir.
* Keepalived servis yönetimi: service.running
Bu sayede, tüm yük dengeleme katmanınızın yüksek erişilebilirliğini SaltStack üzerinden yönetebilirsiniz.
HAProxy Monitoring ve Loglama
HAProxy’nin performansını ve sağlığını izlemek, üretim ortamları için kritik öneme sahiptir.
* HAProxy İstatistik Sayfası: Yukarıdaki örnekte gösterildiği gibi, bir istatistik sayfası etkinleştirerek HAProxy’nin çalışma zamanı istatistiklerini (bağlantılar, sunucu durumları, trafik vb.) web arayüzü üzerinden izleyebilirsiniz.
* Syslog Entegrasyonu: HAProxy, loglarını syslog’a gönderecek şekilde yapılandırılabilir. SaltStack ile rsyslog yapılandırmasını (/etc/rsyslog.d/haproxy.conf) yöneterek HAProxy loglarını merkezi bir log sunucusuna yönlendirebilirsiniz. Bu, log analizini ve hata ayıklamayı kolaylaştırır.
* Logrotate: HAProxy log dosyalarının boyutunu yönetmek için logrotate yapılandırmasını Salt ile otomatikleştirebilirsiniz.
Modüler Yaklaşım
Büyük ve karmaşık altyapılarda, Salt state’lerini daha küçük, yönetilebilir parçalara ayırmak en iyi uygulamadır.
* State Bölme: HAProxy kurulumu için init.sls, yapılandırma için config.sls, loglama için logging.sls gibi farklı dosyalar oluşturabilirsiniz.
* include ve extend: Bu SaltStack ifadeleri, farklı state dosyalarını bir araya getirmenizi veya mevcut state’leri genişletmenizi sağlar. Bu, kod tekrarını azaltır ve okunabilirliği artırır.
Güvenlik
SaltStack ile HAProxy yönetirken güvenlik her zaman öncelikli olmalıdır.
* Pillar’da Hassas Veri Yönetimi: HAProxy istatistik sayfası için kullanılan şifreler gibi hassas verileri doğrudan haproxy.sls dosyasına koymak yerine, SaltStack’in şifrelenmiş Pillar (Encrypted Pillar) özelliğini kullanabilirsiniz. Bu, verileri GPG ile şifreleyerek yalnızca yetkili Master ve Minion’ların bu verilere erişmesini sağlar.
* HAProxy Yönetim Arayüzü Güvenliği: İstatistik sayfası gibi yönetim arayüzlerine erişimi kısıtlamak için IP tabanlı kısıtlamalar veya daha güçlü kimlik doğrulama yöntemleri kullanın.
Test Etme ve Doğrulama
Salt state’lerini üretim ortamına uygulamadan önce test etmek çok önemlidir.
* salt-call state.highstate test=True: Bu komut, bir minion üzerinde state’lerin çalıştırıldığında hangi değişikliklerin yapılacağını gösterir ancak gerçekte hiçbir değişiklik yapmaz. Bu, potansiyel hataları önceden tespit etmek için harika bir yoldur.
* HAProxy Yapılandırma Doğrulaması: HAProxy, yapılandırma dosyasının sözdizimini kontrol etmek için yerleşik bir araca sahiptir: haproxy -c -f /etc/haproxy/haproxy.cfg. Salt state’lerinizde bu kontrolü tetikleyen bir cmd.run veya test.succeed_if kullanabilirsiniz.
* Servis Durum Kontrolü: HAProxy servisi başlatıldıktan sonra, service haproxy status veya systemctl status haproxy gibi komutlarla durumunu kontrol edin.
Uygulama ve Çalıştırma
SaltStack ile HAProxy state’lerinizi oluşturduktan sonra, bunları minion’larınıza uygulamak oldukça basittir.
1. Pillar Verilerini Senkronize Etme: Master üzerinde Pillar verilerinde bir değişiklik yaptığınızda, minion’ların bu değişiklikleri almasını sağlamak için Pillar verilerini yenilemeniz gerekebilir:
sudo salt 'haproxy_minion_id' saltutil.refresh_pillar
veya tüm minion’lar için:
sudo salt '*' saltutil.refresh_pillar
2. State’leri Uygulama: HAProxy minion’unuz üzerinde state’leri uygulamak için Salt Master’dan aşağıdaki komutu çalıştırın:
sudo salt 'haproxy_minion_id' state.highstate
Bu komut, haproxy_minion_id adlı minion’a top.sls dosyasında tanımlanan tüm state’leri uygulamasını söyler. Çıktı, her bir state’in başarılı olup olmadığını ve hangi değişikliklerin yapıldığını gösterecektir.
3. Doğrulama: State’ler uygulandıktan sonra, HAProxy sunucunuza SSH ile bağlanarak veya web tarayıcınızdan erişerek yapılandırmanın doğru çalıştığını doğrulayın.
* sudo systemctl status haproxy (servisin çalıştığından emin olun)
* sudo haproxy -c -f /etc/haproxy/haproxy.cfg (yapılandırma dosyasının geçerliliğini kontrol edin)
* Web tarayıcınızdan http:///haproxy_stats adresine giderek istatistik sayfasını kontrol edin (kullanıcı adı ve şifre ile giriş yapın).
* Web uygulamanızın ana URL’sine (http://) erişerek yük dengelemenin çalıştığını test edin.
Sonuç
SaltStack, HAProxy yük dengeleyicilerin kurulumu, yapılandırması ve yönetimi için güçlü ve esnek bir platform sunar. Bu makalede ele aldığımız Salt State’leri ve Pillar yapıları sayesinde, HAProxy altyapınızı tamamen otomatikleştirebilir, manuel hataları en aza indirebilir ve dağıtımlarınızı hızlandırabilirsiniz. Jinja2 şablonları ve Pillar’ın dinamik yapısı, farklı ortamlar (geliştirme, test, üretim) veya farklı uygulama gereksinimleri için kolayca uyarlanabilir yapılandırmalar oluşturmanıza olanak tanır.
SaltStack ve HAProxy’nin entegrasyonu, modern DevOps pratiklerinin temelini oluşturan altyapı kod (Infrastructure as Code – IaC) prensiplerini benimsemenize yardımcı olur. Bu sayede, tutarlı, ölçeklenebilir ve yüksek erişilebilir yük dengeleme çözümlerini etkin bir şekilde dağıtabilir ve yönetebilirsiniz. Gelecekte, bu yapılandırmaları sürekli entegrasyon/sürekli teslimat (CI/CD) işlem hatlarınıza entegre ederek altyapı dağıtım süreçlerinizi daha da optimize edebilirsiniz. SaltStack’in sunduğu esneklik ve güç ile, HAProxy altyapınızın yönetimini basitleştirirken, aynı zamanda karmaşıklığı azaltabilir ve güvenilirliği artırabilirsiniz.
