Linux Namespaces ile Süreç İzolasyonunun Temelleri ve Mekanizmaları

 · 

Linux Namespaces ile Süreç İzolasyonunun Temelleri ve Mekanizmaları

Linux Namespaces: Süreç İzolasyonunun Temelleri ve Mekanizmaları

Modern bulut altyapılarında ve kapsayıcılık (containerization) teknolojilerinde temel bir izolasyon mekanizması olarak Linux Namespaces öne çıkar. Bu mekanizma, bir sürecin işletim sisteminin global kaynaklarına olan bakış açısını izole etmeyi sağlar. Her namespace, belirli bir kaynak türü için sistemin ayrı bir örneğini sunarak süreçlerin birbirini etkilemeden güvenli bir şekilde çalışmasına olanak tanır.

Namespaces Nedir ve Neden Gereklidir?

Linux Namespaces, bir süreç grubunun işletim sisteminin küresel kaynaklarını kendilerine aitmiş gibi algılamasını sağlayan bir özelliktir. Temel amacı, süreçlerin birbirini görmesini, kaynaklara erişmesini veya sistem ayarlarını değiştirmesini engelleyerek daha güvenli ve tutarlı ortamlar yaratmaktır. Bu izolasyon, özellikle Docker, Kubernetes gibi kapsayıcı teknolojilerin omurgasını oluşturur. Bir kapsayıcı içinde çalışan bir uygulama, host sistemdeki diğer uygulamaların PID'lerini, ağ arayüzlerini veya dosya sistemlerini göremez; çünkü kendi izole edilmiş namespace'lerinde çalışır.

Başlıca Linux Namespace Türleri

Linux çekirdeği, farklı kaynak türleri için çeşitli namespace türleri sunar. Her biri belirli bir sistem kaynağının izolasyonunu sağlar:

  • PID (Process ID) Namespace: Süreçlerin PID'lerini izole eder. Her namespace'in kendi PID 1'i (init süreci) olabilir. Bir namespace içinde çalışan süreçler, dışarıdaki süreçleri göremez ve kendi içlerinde yeniden 1'den başlayan PID'lere sahip olur.
  • Mount (MNT) Namespace: Dosya sistemi mount noktalarını izole eder. Her namespace'in kendi mount tablosu bulunur, böylece bir namespace içindeki dosya sistemi değişiklikleri diğerlerini etkilemez.
  • UTS (UNIX Time-sharing System) Namespace: Hostname ve NIS (Network Information Service) alan adını izole eder. Bu sayede, farklı kapsayıcılar aynı host üzerinde farklı hostname'lere sahip olabilir.
  • IPC (Interprocess Communication) Namespace: Süreçler arası iletişim (IPC) kaynaklarını (semaphorlar, mesaj kuyrukları, paylaşımlı bellek) izole eder.
  • Network (NET) Namespace: Ağ aygıtlarını, IP adreslerini, routing tablolarını, portları ve firewall kurallarını izole eder. Her network namespace kendi bağımsız ağ yığınına sahiptir.
  • User Namespace: Kullanıcı ve grup ID'lerini izole eder. Bir namespace içindeki bir kullanıcı, host sistemdeki farklı bir UID'ye eşlenebilir. Bu, kapsayıcı içinde root olan bir kullanıcının host sistemde yetkisiz bir kullanıcı olarak çalışmasını sağlayarak güvenlik açısından büyük fayda sunar.
  • Cgroup Namespace: Süreçlerin cgroup hiyerarşisine olan bakış açısını izole eder, ancak kendisi kaynak sınırlaması yapmaz. Cgroups'lar kaynak yönetimi için kullanılırken, cgroup namespace'leri bu yönetimin görünürlüğünü izole eder.

unshare Komutu ile Namespaces Kullanımı

Namespaces'leri manuel olarak oluşturmak ve yönetmek için unshare komutu kullanılabilir. Bu komut, yeni bir veya daha fazla namespace içinde bir komut çalıştırmanıza olanak tanır.

Örnek: PID, Mount ve UTS Namespacelerini Ayırma

Aşağıdaki örnek, yeni bir PID, Mount ve UTS namespace'i içinde bir Bash kabuğu başlatır. Bu, hafif bir “mini-kapsayıcı” ortamı yaratmaya benzer.

sudo unshare --pid --mount --uts --fork bash

Bu komut çalıştırıldıktan sonra, yeni açılan kabukta aşağıdaki kontrolleri yapabiliriz:

# Yeni PID namespace'indeki süreçleri listele (sadece kendi sürecimiz ve 'ps' komutu görünmeli)ps aux# Yeni UTS namespace'indeki hostname'i ayarla ve kontrol ethostname my-isolated-hosthostname# Yeni mount namespace'ini göster (host'tan farklı olmalı)mount | grep -i proc# İsteğe bağlı olarak, yeni bir /proc dosya sistemi mount etsudo mount -t proc proc /proc# Şimdi ps aux tekrar çalıştırıldığında daha temiz bir çıktı görülebilirps aux

Yeni kabuktan çıkmak için exit yazmanız yeterlidir. Çıktığınızda, oluşturulan namespace'ler ve içlerindeki süreçler yok olur.

Örnek: Network Namespace Oluşturma

Yeni bir ağ namespace'i oluşturup içine bir süreç başlatmak, ağ izolasyonunu anlamak için kritiktir.

# Yeni bir ağ namespace'i oluşturursudo ip netns add mynetns# Bu namespace içinde bir bash kabuğu başlatıp ağ arayüzlerini kontrol etsudo ip netns exec mynetns baship link show# Görüldüğü gibi, sadece 'lo' (loopback) arayüzü olmalı.exit# Oluşturulan ağ namespace'ini silsudo ip netns del mynetns

Bu örnekte, mynetns içinde başlatılan kabuk, host sistemin ağ arayüzlerini veya IP yapılandırmasını göremez. Bu, Docker kapsayıcılarının her birinin kendi izole IP adreslerine ve ağ arayüzlerine sahip olmasını sağlayan temel prensiptir.

Üretim Senaryosu: Kapsayıcılık ve Kubernetes

Linux Namespaces, kapsayıcı teknolojilerinin temel taşıdır. Docker veya Podman gibi kapsayıcı çalışma zamanları (runtimes), her bir kapsayıcı için birden fazla namespace (PID, Mount, Network, IPC, UTS, User) oluşturur. Bu, aşağıdaki faydaları sağlar:

  • Güvenlik İzolasyonu: Bir kapsayıcıdaki bir zafiyet, host sisteme veya diğer kapsayıcılara doğrudan sıçramaz çünkü kendi izole ortamında çalışır. Özellikle User Namespaces, kapsayıcı içindeki root kullanıcısının host sistemde ayrıcalıksız bir kullanıcı olarak eşleşmesini sağlayarak ciddi bir güvenlik katmanı ekler.
  • Kaynak İzolasyonu: Cgroups ile birlikte Namespaces, kapsayıcıların CPU, bellek gibi kaynakları ne kadar kullanabileceğini belirlerken, Namespaces bu kaynakların görünürlüğünü ve erişilebilirliğini izole eder.
  • Taşınabilirlik ve Tutarlılık: Bir kapsayıcı, bağımsız bir işletim ortamı sağladığı için farklı Linux host'ları arasında tutarlı bir şekilde çalışabilir. Kapsayıcının kendi dosya sistemi, ağ yapılandırması ve süreç alanı vardır.

Kubernetes ortamlarında, bir Pod içindeki tüm kapsayıcılar genellikle aynı PID, IPC ve Network Namespacelerini paylaşır (shareProcessNamespace ayarına bağlı olarak PID namespace paylaşımı değişebilir). Bu sayede, Pod içindeki sidecar kapsayıcıları ana uygulama ile kolayca iletişim kurabilir. Ancak farklı Pod'lar, birbirlerinden tamamen izole edilmiş kendi ayrı Namespacelerine sahiptir.

Teknik Derinlik: clone() Sistem Çağrısı

Namespaces'lerin altında yatan mekanizma, Linux çekirdeğinin clone() sistem çağrısıdır. Bir süreç oluşturulurken (fork() veya vfork() gibi), clone() çağrısına özel bayraklar (örneğin, CLONE_NEWPID, CLONE_NEWNET) iletilerek yeni bir namespace içinde başlatılması sağlanır. Bu bayraklar, çocuğun ebeveynin namespace'lerini mi kullanacağını yoksa yenilerini mi oluşturacağını belirler.

Her sürecin hangi namespace'lere ait olduğunu /proc/[pid]/ns/ dizini altındaki sembolik bağlantılardan görebilirsiniz. Örneğin:

ls -l /proc/self/ns

Buradaki inode numaraları, farklı süreçlerin aynı namespace'i paylaşıp paylaşmadığını anlamak için kullanılabilir. Aynı inode numarasına sahip iki süreç, aynı namespace'i paylaşır.

Sonuç

Linux Namespaces, modern sistem mühendisliğinde ve DevOps pratiklerinde vazgeçilmez bir bileşendir. Süreç izolasyonunu temel düzeyde sağlayarak kapsayıcı teknolojileri için sağlam bir zemin oluşturur. Bu mekanizmanın derinlemesine anlaşılması, güvenli, ölçeklenebilir ve yönetilebilir Linux tabanlı altyapılar inşa etmek için kritik öneme sahiptir. Geliştiriciler ve sistem yöneticileri için Namespaces'in nasıl çalıştığını bilmek, sorun gidermeden sistem tasarımına kadar geniş bir yelpazede yetkinlik kazandırır.

← Blog Listesine Dön