Salt Cloud Harita Dosyalarını Kullanarak Uygulama Sunucuları ve Nginx Ters Proxy Dağıtma
Giriş: Salt Cloud ve Altyapı Otomasyonu
Modern bulut tabanlı uygulamaların dağıtımı ve yönetimi, giderek karmaşıklaşan bir süreç haline gelmiştir. Geleneksel manuel yöntemler, hızlı ölçeklenme ve tutarlılık gereksinimlerini karşılamakta yetersiz kalmaktadır. İşte bu noktada SaltStack gibi güçlü konfigürasyon yönetimi ve otomasyon araçları devreye girer. SaltStack, sunucu konfigürasyonunu, uygulama dağıtımını ve altyapı yönetimini merkezileştirilmiş ve deklaratif bir yaklaşımla otomatikleştirmeyi sağlar.
Salt Cloud, SaltStack ekosisteminin önemli bir parçasıdır ve bulut sağlayıcılar (AWS, Azure, GCP, VMware, OpenStack vb.) üzerinde sanal makinelerin (VM) veya konteynerlerin programatik olarak oluşturulmasını, yönetilmesini ve yok edilmesini sağlar. Salt Cloud ile, altyapınızı kod olarak tanımlayabilir (Infrastructure as Code – IaC) ve bu sayede dağıtımları tekrarlanabilir, tutarlı ve hatasız hale getirebilirsiniz.
Bu makalede, Salt Cloud’un “harita dosyaları” (map files) özelliğini kullanarak birden fazla uygulama sunucusu ve bu sunuculara gelen trafiği yönetecek bir Nginx ters proxy’nin nasıl dağıtılacağını ayrıntılı olarak inceleyeceğiz. Amacımız, hem sunucuların bulutta otomatik olarak provision edilmesini hem de bu sunucuların SaltStack state’leri (durum dosyaları) aracılığıyla otomatik olarak yapılandırılmasını sağlamaktır.
Salt Cloud Harita Dosyaları Nedir ve Neden Kullanılır?
Salt Cloud harita dosyaları, dağıtmak istediğiniz tüm bulut kaynaklarını (sanal makineler) ve bunların özelliklerini (profil, minion ID, Salt Grains, Pillar verileri vb.) tek bir YAML dosyasında tanımlamanıza olanak tanır. Bu dosyalar, Salt Cloud’a hangi sunucuların hangi bulut sağlayıcıda, hangi özelliklerle ve hangi Salt minion ID’leriyle oluşturulacağını bildirir.
Harita dosyalarını kullanmanın başlıca faydaları şunlardır:
* Deklaratif Tanımlama: Dağıtmak istediğiniz altyapıyı “ne” istediğinizi belirterek tanımlarsınız, “nasıl” yapılacağını değil. Salt Cloud gerisini halleder.
* Tekrarlanabilirlik ve Tutarlılık: Bir kez tanımladığınız bir harita dosyası, aynı altyapıyı defalarca ve her seferinde aynı şekilde oluşturmanızı sağlar. Bu, geliştirme, test ve üretim ortamları arasında tutarlılığı garanti eder.
* Sürüm Kontrolü: Harita dosyaları metin tabanlı olduğu için Git gibi sürüm kontrol sistemleriyle kolayca yönetilebilir. Bu, altyapı değişikliklerini izlemeyi, geri almayı ve işbirliği yapmayı mümkün kılar.
* Karmaşık Dağıtımları Basitleştirme: Birden fazla sunucu türünü, farklı konfigürasyonlarla ve farklı bulut sağlayıcılarda tek bir komutla dağıtmak için kullanılabilir.
* Altyapı Kod Olarak (IaC): Altyapınızı kod olarak yöneterek otomasyonu, verimliliği ve hata oranını artırırsınız.
Ön Koşullar ve Kurulum
Bu makaledeki örnekleri takip edebilmek için bazı ön koşulların yerine getirilmiş olması gerekmektedir:
1. Salt Master Kurulumu: Bir Salt Master sunucusunun kurulu ve çalışır durumda olması gerekir. Bu sunucu, Salt minion’ları yönetecek ve Salt Cloud komutlarını çalıştıracaktır.
2. Salt Cloud Kurulumu ve Yapılandırması: Salt Master üzerinde Salt Cloud bileşeninin kurulu olması ve kullanılacak bulut sağlayıcısı (örneğin AWS EC2) için gerekli kimlik bilgilerinin ve yapılandırmaların yapılmış olması gerekmektedir.
* cloud.providers.d/ dizini altında bulut sağlayıcısı yapılandırma dosyaları (örneğin aws.conf).
* cloud.profiles.d/ dizini altında sunucu profili tanımlama dosyaları (örneğin app_server.conf, nginx_proxy.conf).
3. Bulut Sağlayıcı Kimlik Bilgileri: Seçtiğiniz bulut sağlayıcısı için API erişim anahtarları ve ilgili yetkilendirmeler Salt Cloud tarafından erişilebilir olmalıdır.
4. Temel Salt State (SLS) Dosyaları: Uygulama sunucularını ve Nginx ters proxy’yi yapılandırmak için Salt State dosyalarına ihtiyacımız olacak.
Bu makalede örnek olarak AWS EC2 kullanılacaktır, ancak kavramlar diğer bulut sağlayıcıları için de benzerdir.
Dağıtım Mimarisi Tasarımı
Hedefimiz, aşağıdaki bileşenlere sahip bir altyapı oluşturmaktır:
* Uygulama Sunucuları (App Servers): Birden fazla örnekten oluşacak, uygulamanın çalıştığı sunucular. Bu sunucular genellikle aynı konfigürasyona sahiptir ve bir ters proxy tarafından erişilir.
* Nginx Ters Proxy (Nginx Reverse Proxy): Tek bir örnekten oluşacak (basitlik adına), gelen HTTP/HTTPS isteklerini uygulama sunucularına yönlendiren sunucu. Nginx, uygulama sunucularının IP adreslerini bilmeli ve trafiği dengelemelidir.
Bu mimaride, uygulama sunucuları doğrudan internete açık olmayacak, sadece Nginx ters proxy’den gelen isteklere yanıt verecektir. Nginx ise belirli portlardan (örn. 80, 443) gelen istekleri dinleyecektir.
Salt Cloud Sağlayıcıları ve Profilleri Yapılandırma
İlk adım, Salt Cloud’un bulut sağlayıcınızla iletişim kurabilmesi için gerekli yapılandırmayı yapmaktır. Ardından, dağıtacağımız sunucu tipleri için profiller tanımlayacağız.
Sağlayıcı Yapılandırması (Örnek: AWS EC2)
/etc/salt/cloud.providers.d/aws.conf dosyası şöyle görünebilir:
aws_ec2_provider:
driver: ec2
id:
key:
region: eu-central-1 # Frankfurt
securitygroup: my-security-group # Önceden oluşturulmuş bir güvenlik grubu
ssh_username: ec2-user # SSH kullanıcı adı
location: eu-central-1
sudo: True
minion:
master:
, ve kendi değerlerinizle değiştirilmelidir. my-security-group ise EC2 instance’larının hangi portlardan erişilebilir olacağını belirleyen bir AWS güvenlik grubudur.
Profil Tanımlamaları
Profiller, belirli bir sanal makine türünün özelliklerini (AMI, boyut, disk, güvenlik grubu vb.) tanımlar.
Uygulama Sunucusu Profili (/etc/salt/cloud.profiles.d/app_server_profile.conf):
app_server_profile:
provider: aws_ec2_provider
image: ami-0abcdef1234567890 # Ubuntu 20.04 LTS veya benzeri bir AMI ID
size: t2.micro
del_blob_on_destroy: False
minion:
grains:
role: app_server
Burada ami-0abcdef1234567890 yerine kullandığınız AWS bölgesindeki uygun bir AMI kimliğini girmelisiniz. t2.micro örnek boyutunu belirtir. minion altındaki grains tanımı, Salt minion’ına role: app_server adında bir grain atar. Bu grain, daha sonra Salt State’lerini hedeflemek için kullanılacaktır.
Nginx Ters Proxy Profili (/etc/salt/cloud.profiles.d/nginx_proxy_profile.conf):
nginx_proxy_profile:
provider: aws_ec2_provider
image: ami-0abcdef1234567890 # Aynı veya farklı bir AMI ID
size: t2.micro
del_blob_on_destroy: False
minion:
grains:
role: nginx_proxy
Nginx proxy için de benzer bir profil tanımlıyoruz, ancak role grain’i nginx_proxy olarak ayarlanmıştır.
Salt State (SLS) Dosyalarını Oluşturma
Şimdi, Salt Cloud tarafından oluşturulan sunucuların nasıl yapılandırılacağını tanımlayan Salt State dosyalarını hazırlayalım. Bu dosyalar, /srv/salt/ dizini altında bulunmalıdır.
Uygulama Sunucusu State’leri (/srv/salt/app/init.sls)
Bu örnekte basit bir Python uygulamasını dağıttığımızı varsayalım.
# /srv/salt/app/init.sls
install_python_deps:
pkg.installed:
- pkgs:
- python3
- python3-pip
- git
clone_app_repo:
git.latest:
- name: https://github.com/myuser/my-python-app.git
- target: /opt/my-python-app
- rev: master
- require:
- pkg: install_python_deps
install_app_deps:
pip.installed:
- requirements: /opt/my-python-app/requirements.txt
- bin_env: /usr/bin/pip3
- require:
- git: clone_app_repo
app_service:
file.managed:
- name: /etc/systemd/system/my-app.service
- source: salt://app/my-app.service
- template: jinja
- defaults:
app_port: 5000 # Uygulamanın dinleyeceği port
- require:
- pip: install_app_deps
service.running:
- name: my-app
- enable: True
- watch:
- file: app_service
Uygulamanın özel IP adresini Salt Mine'a yayınla
publish_private_ip:
mine.present:
- func: network.ip_addrs
- listen_addrs: True # Sadece dinlenen adresleri yayınla
- key: app_private_ip
/srv/salt/app/my-app.service (systemd service dosyası):
[Unit]
Description=My Python Application
After=network.target
[Service]
User=root
WorkingDirectory=/opt/my-python-app
ExecStart=/usr/bin/python3 /opt/my-python-app/app.py --port {{ app_port }}
Restart=always
[Install]
WantedBy=multi-user.target
Bu state dosyası şunları yapar: Python ve Git’i kurar, uygulama kodunu bir Git deposundan çeker, Python bağımlılıklarını kurar, uygulamanın systemd servisini yapılandırır ve başlatır. En önemlisi, minion’ın özel IP adresini Salt Mine’a app_private_ip anahtarıyla yayınlar. Bu, Nginx’in uygulama sunucularının IP’lerini dinamik olarak öğrenmesini sağlayacaktır.
Nginx Ters Proxy State’leri (/srv/salt/nginx/init.sls)
# /srv/salt/nginx/init.sls
install_nginx:
pkg.installed:
- name: nginx
nginx_config:
file.managed:
- name: /etc/nginx/sites-available/my-app.conf
- source: salt://nginx/my-app.conf.jinja
- template: jinja
- defaults:
app_servers: {{ salt['mine.get']('role:app_server', 'app_private_ip', tgt_type='grain') | unique | join(',') }}
- require:
- pkg: install_nginx
file.symlink:
- name: /etc/nginx/sites-enabled/my-app.conf
- target: /etc/nginx/sites-available/my-app.conf
- force: True
- require:
- file: nginx_config
nginx_service:
service.running:
- name: nginx
- enable: True
- watch:
- file: nginx_config
/srv/salt/nginx/my-app.conf.jinja (Nginx yapılandırma şablonu):
upstream backend_app {
{% for server_ip in app_servers.split(',') %}
server {{ server_ip }}:5000;
{% endfor %}
}
server {
listen 80;
server_name myapp.example.com;
location / {
proxy_pass http://backend_app;
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 state dosyası şunları yapar: Nginx paketini kurar, Nginx yapılandırma dosyasını (Jinja şablonu kullanarak) oluşturur ve sembolik bağını kurar, ardından Nginx servisini başlatır.
Buradaki kritik nokta, nginx_config state’indeki defaults bölümüdür:
app_servers: {{ salt['mine.get']('role:app_server', 'app_private_ip', tgt_type='grain') | unique | join(',') }}
Bu ifade, Salt Mine’dan role:app_server grain’ine sahip tüm minion’ların app_private_ip anahtarı altında yayınladığı değerleri (yani özel IP adreslerini) çeker. unique filtresi tekrarlayan IP’leri kaldırır ve join(',') bunları virgülle ayrılmış bir dizeye dönüştürür. Bu dize daha sonra Nginx yapılandırma şablonunda backend_app upstream bloğunda kullanılır, böylece Nginx dinamik olarak uygulama sunucularının IP adreslerini bilir.
Önemli Not: Salt Mine verilerinin güncel olması için, uygulama sunucularına mine.present state’i uygulandıktan sonra Nginx minion’ında saltutil.refresh_mine veya saltutil.sync_all gibi komutlar çalıştırılması gerekebilir, ya da Nginx state’i uygulanmadan önce yeterli zaman tanınmalıdır. Daha robust bir yaklaşım için bir Salt Orchestration runner kullanılabilir.
Salt Cloud Harita Dosyasını Hazırlama
Şimdi, tüm bu parçaları bir araya getiren Salt Cloud harita dosyasını oluşturalım. Bu dosya, map_file.map adıyla kaydedilebilir.
# map_file.map
app_servers:
- app-server-01:
profile: app_server_profile
- app-server-02:
profile: app_server_profile
- app-server-03:
profile: app_server_profile
nginx_proxy:
- nginx-proxy-01:
profile: nginx_proxy_profile
Bu harita dosyası şunları tanımlar:
* app_servers grubu altında üç adet app-server-XX isminde minion oluşturulacak ve hepsi app_server_profile profilini kullanacak.
* nginx_proxy grubu altında bir adet nginx-proxy-01 isminde minion oluşturulacak ve nginx_proxy_profile profilini kullanacak.
Salt Cloud, bu tanımlamaları kullanarak her bir minion’ı bulut sağlayıcınızda başlatacak, Salt minion yazılımını kuracak ve Salt Master’a bağlayacaktır. Minion’lar Salt Master’a bağlandığında, profillerinde tanımlanan grains değerleri otomatik olarak atanacaktır.
Harita Dosyası ile Dağıtım Yapma
Harita dosyasını kullanarak sunucuları dağıtmak için Salt Master üzerinde aşağıdaki komutu çalıştırın:
salt-cloud -m map_file.map
Bu komut, harita dosyasındaki tanımlamalara göre tüm sanal makineleri bulutta oluşturmaya başlayacaktır. İşlem tamamlandığında, Salt Master’ınızın salt-key -L çıktısında yeni minion’ları göreceksiniz (eğer otomatik kabul ayarlanmışsa).
Dağıtım Sonrası Konfigürasyon (Orchestration ile)
Sunucular provision edildikten ve Salt Master’a bağlandıktan sonra, Salt State’lerini uygulayarak onları yapılandırmamız gerekir. Bu adımlar genellikle bir orkestrasyon (orchestration) state’i ile otomatikleştirilir. Ancak basitlik adına, ayrı ayrı komutlarla gösterebiliriz.
1. Uygulama Sunucularını Yapılandırma:
Tüm app_server rolüne sahip minion’lara app state’ini uygulayın:
salt -G 'role:app_server' state.apply app
Bu komut, uygulama sunucularına Python, Git ve uygulamanızı kuracak, systemd servisini ayarlayacak ve en önemlisi minion’ların özel IP adreslerini Salt Mine’a yayınlayacaktır.
2. Salt Mine’ı Güncelleme (Nginx için):
Nginx minion’ının, uygulama sunucularının yeni IP adreslerini Salt Mine’dan çekebilmesi için Mine verilerinin güncel olması gerekir. Nginx minion’ında Mine’ı yenilemek için:
salt 'nginx-proxy-01' saltutil.refresh_mine
Veya tüm minion’larda Mine’ı yenilemek için:
salt '*' saltutil.refresh_mine
Bu adım, Nginx minion’ının Salt Mine’dan en güncel uygulama sunucusu IP’lerini almasını sağlar.
3. Nginx Ters Proxy’yi Yapılandırma:
nginx_proxy rolüne sahip minion’a nginx state’ini uygulayın:
salt -G 'role:nginx_proxy' state.apply nginx
Bu komut Nginx’i kuracak ve Salt Mine’dan aldığı uygulama sunucusu IP’lerini kullanarak my-app.conf dosyasını oluşturup Nginx’i başlatacaktır.
Bu adımlar tamamlandığında, Nginx ters proxy’niz uygulama sunucularınıza gelen istekleri yönlendirmeye hazır olacaktır.
Gelişmiş Orkestrasyon (Salt Orchestration)
Yukarıdaki adımları tek bir komutla çalıştırmak için Salt Orchestration kullanmak daha iyi bir yaklaşımdır. /srv/salt/orchestrate/deploy_app.sls gibi bir dosya oluşturabilirsiniz:
# /srv/salt/orchestrate/deploy_app.sls
deploy_app_servers:
salt.runner:
- name: cloud.map
- map: /etc/salt/cloud.maps.d/map_file.map # Harita dosyanızın yolu
configure_app_servers:
salt.state:
- tgt: 'role:app_server'
- fun: state.apply
- arg:
- app
- require:
- salt: deploy_app_servers
refresh_all_mines:
salt.function:
- name: saltutil.refresh_mine
- tgt: '*' # Tüm minion'larda mine'ı yenile
- require:
- salt: configure_app_servers
configure_nginx_proxy:
salt.state:
- tgt: 'role:nginx_proxy'
- fun: state.apply
- arg:
- nginx
- require:
- salt: refresh_all_mines
Bu orkestrasyon state’ini çalıştırmak için:
salt-run state.orchestrate orchestrate.deploy_app
Bu tek komut, tüm dağıtım ve yapılandırma sürecini sırayla ve otomatik olarak gerçekleştirecektir.
Salt Cloud Harita Dosyalarını Kullanmanın Faydaları
Bu süreç, Salt Cloud harita dosyalarının ve SaltStack’in genel yeteneklerinin sunduğu birçok avantajı ortaya koymaktadır:
* Hızlı ve Otomatik Dağıtım: Altyapı ve uygulama dağıtımı saatler yerine dakikalar içinde tamamlanabilir.
