Systemd Unit Dosyaları ile Servis Yönetimi: Gelişmiş Uygulama Kontrolü

 · 

Systemd Unit Dosyaları ile Servis Yönetimi: Gelişmiş Uygulama Kontrolü

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.target

Bu 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:app komutu, 4 worker ile uygulamayı 5000 portunda çalıştırır.
  • ExecStop: Servisin durdurulması için çalıştırılacak komut. Gunicorn'a TERM sinyali 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 sayede journalctl -u mywebapp.service komutuyla 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 et

Servis loglarını kontrol etmek için:

journalctl -u mywebapp.service -f

Geliş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ğin setuid/setgid bitleri aracılığıyla).
  • PrivateTmp=true: Servise özel bir geçici dizin (/tmp ve /var/tmp iç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ğer mywebapp.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.service başlamazsa mywebapp.service yine de başlamayı dener.
  • After=mysql.service: mysql.service başarılı bir şekilde başladıktan sonra mywebapp.service'in başlamasını sağlar.
  • BindsTo=mysql.service: mysql.service durdurulduğunda veya çöktüğünde mywebapp.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=
← Blog Listesine Dön