Systemd Unit Dosyaları ile Servis Yönetimi: Gelişmiş Uygulama Kontrolü
Modern Linux sistemlerde servis ve süreç yönetimi, systemd inisializasyon sisteminin temelini oluşturur. Geleneksel SysVinit veya Upstart sistemlerine kıyasla systemd, paralel servis başlatma, cgroup tabanlı kaynak yönetimi, anlık durum izleme ve güçlü bağımlılık mekanizmaları sunarak sistem performansını ve güvenilirliğini artırır. Bir uygulamanın veya servisin Linux açılışında otomatik olarak başlamasını, hatalı durumlarda yeniden başlatılmasını veya belirli koşullara göre davranış sergilemesini sağlamanın en etkili yolu, özel bir systemd unit dosyası yazmaktan geçer.
Temel Systemd Unit Yapısı ve Bölümleri
Bir systemd unit dosyası, genellikle /etc/systemd/system/ dizini altında bulunur ve .service, .target, .mount, .socket, .timer gibi uzantılara sahiptir. Uygulama veya arka plan süreçleri için en sık kullanılan tip .service uzantılı dosyalardır. Bu dosyalar, üç ana bölümden oluşur:
[Unit]Bölümü: Servisin genel tanımını, açıklamalarını ve bağımlılıklarını belirler.[Service]Bölümü: Servisin nasıl başlatılacağını, durdurulacağını, hangi kullanıcı ve grup altında çalışacağını ve kaynak sınırlarını tanımlar.[Install]Bölümü: Servisin sistem açılışında nasıl etkinleştirileceğini kontrol eder.
Örnek Bir Uygulama Servisi Oluşturma
Basit bir Python tabanlı Flask web uygulamasını bir systemd servisi olarak çalıştırma senaryosunu inceleyelim. Uygulamamız /opt/mywebapp/app.py yolunda bulunsun ve venv içinde çalışsın.
# /opt/mywebapp/app.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return 'Merhaba, systemd ile yönetilen Flask uygulaması!'
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)Önce gerekli sanal ortamı ve bağımlılıkları kuralım:
cd /opt/mywebapp
python3 -m venv venv
source venv/bin/activate
pip install Flask gunicorn
deactivateŞimdi mywebapp.service adında bir systemd unit dosyası oluşturalım:
sudo nano /etc/systemd/system/mywebapp.serviceİçeriği aşağıdaki gibi dolduralım:
[Unit]
Description=My Flask Web Application Service
After=network.target
[Service]
User=myuser
Group=myuser
WorkingDirectory=/opt/mywebapp
ExecStart=/opt/mywebapp/venv/bin/gunicorn -w 4 -b 0.0.0.0:5000 app:app
ExecStop=/bin/kill -TERM $MAINPID
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal
SyslogIdentifier=mywebapp
[Install]
WantedBy=multi-user.targetBu dosyadaki yönergeleri açıklayalım:
Description: Servisin kısa açıklaması.After=network.target: Ağ servisleri başladıktan sonra bu servisin başlamasını sağlar.User/Group: Servisin hangi kullanıcı ve grup izinleriyle çalışacağını belirtir. Üretim ortamında ayrıcalıksız bir kullanıcı kullanmak güvenlik açısından esastır.WorkingDirectory: Servis komutlarının hangi dizinde çalıştırılacağını belirler.ExecStart: Servisin başlatılması için çalıştırılacak komut. Burada Gunicorn ile Flask uygulamasını başlatıyoruz.gunicorn -w 4 -b 0.0.0.0:5000 app:appkomutu, 4 worker ile uygulamayı 5000 portunda çalıştırır.ExecStop: Servisin durdurulması için çalıştırılacak komut. Gunicorn'aTERMsinyali göndererek düzgün kapanmasını sağlarız.Restart=on-failure: Servis beklenmedik bir şekilde kapanırsa (hata veya çökme durumunda) otomatik olarak yeniden başlatılır. Diğer seçenekler:no,on-success,always.RestartSec=5: Yeniden başlatma denemeleri arasında 5 saniye bekle.StandardOutput=journal,StandardError=journal: Uygulamanın standart çıktı ve hata akışlarınısystemd-journald'ye yönlendirir. Bu sayedejournalctl -u mywebapp.servicekomutuyla logları kolayca görüntüleyebiliriz.SyslogIdentifier: Journal'da bu servise ait logları tanımlamak için kullanılır.WantedBy=multi-user.target: Servisin çok kullanıcılı sistem durumunda (normal çalışma modu) etkinleştirildiğinde başlatılmasını sağlar.
Servisi etkinleştirme ve başlatma:
sudo systemctl daemon-reload # systemd'ye yeni unit dosyasını tanıt
sudo systemctl enable mywebapp.service # Servisi açılışta başlaması için etkinleştir
sudo systemctl start mywebapp.service # Servisi şimdi başlat
sudo systemctl status mywebapp.service # Servisin durumunu kontrol etServis loglarını kontrol etmek için:
journalctl -u mywebapp.service -fGelişmiş Yapılandırma ve Üretim Senaryoları
Üretim ortamlarında servislerin kararlı, güvenli ve kaynak verimli çalışması kritik öneme sahiptir. systemd, bu ihtiyaçları karşılamak için bir dizi gelişmiş yapılandırma seçeneği sunar.
Kaynak Sınırlamaları ve İzolasyon
Uygulamaların sistem kaynaklarını aşırı tüketmesini engellemek için cgroup tabanlı sınırlar tanımlayabiliriz:
LimitNOFILE=65536: Açık dosya tanıtıcısı sayısını sınırlar. Yüksek trafikli web sunucuları veya veritabanları için önemlidir.MemoryLimit=2G: Servisin kullanabileceği maksimum belleği 2GB ile sınırlar.CPUShares=512: CPU kullanımındaki ağırlığını belirler (varsayılan 1024). Bu, yoğun işlemci kullanan bir servisin diğer kritik servislere engel olmasını önlemeye yardımcı olur.
[Service]
...
LimitNOFILE=65536
MemoryLimit=2G
CPUShares=512
...Güvenlik Bağlamı ve İzinler
En az ayrıcalık ilkesini uygulamak, güvenlik duruşunu güçlendirir:
User=myuser,Group=myuser: Servisi ayrıcalıksız bir kullanıcı altında çalıştırmak, güvenlik açığı durumunda sistemin geri kalanına verilen zararı sınırlar.ProtectSystem=full: Kök dosya sisteminin (/,/usr,/boot) servis tarafından yazılabilir olmasını engeller.ProtectHome=yes: Kullanıcıların ana dizinlerine (/home,/root) erişimi kısıtlar.NoNewPrivileges=yes: Servisin yeni ayrıcalıklar kazanmasını engeller (örneğinsetuid/setgidbitleri aracılığıyla).PrivateTmp=true: Servise özel bir geçici dizin (/tmpve/var/tmpiçin) sağlar, diğer servislerle çakışmayı önler ve güvenlik sağlar.
[Service]
...
ProtectSystem=full
ProtectHome=yes
NoNewPrivileges=yes
PrivateTmp=true
...Bağımlılık Yönetimi
Servislerin doğru sırada başlaması ve çalışması için bağımlılıklar hayati öneme sahiptir:
Requires=mysql.service: Eğermywebapp.service,mysql.service'in çalışmasını gerektiriyorsa, MySQL servisi durursa veya başlamazsa kendi servisimizi de durdurur veya başlatmaz.Wants=mysql.service: Benzer bir bağımlılık ancak daha az katıdır.mysql.servicebaşlamazsamywebapp.serviceyine de başlamayı dener.After=mysql.service:mysql.servicebaşarılı bir şekilde başladıktan sonramywebapp.service'in başlamasını sağlar.BindsTo=mysql.service:mysql.servicedurdurulduğunda veya çöktüğündemywebapp.service'i de durdurur.
Ortam Değişkenleri ve Yapılandırma
Uygulama yapılandırmasını ve hassas bilgileri yönetmek için:
Environment=