Sıfırdan Docker Benzeri Konteyner Yaratma: Konteyner Mekanizmalarının İç Mekanizmaları
Sıfırdan Docker Benzeri Konteyner Yaratma: Konteyner Mekanizmalarının İç Mekanizmaları
Linux konteynerlerinin temelinde, sistem düzeyindeki izolasyon mekanizmalarına dayanan güçlü bir yapı yatıyor. Docker gibi bir ortamda bir konteyner çalıştırdığınızda, sanki kendi işletim sistemiyle birlikte çalışıyormuş gibi bir deneyim yaşarsınız. Ancak bu, sadece bir illüzyondur. Aslında, bu izolasyon, Linux’ın kendi içinde geliştirdiği birkaç teknik sayesinde sağlanır.
Bu makalede, Docker benzeri bir konteyneri sıfırdan, sadece standart Linux araçlarını kullanarak oluşturacağız. Amaç, geliştiricilerin konteynerlerin nasıl çalıştığını, hangi sistem düzeyi mekanizmalarının etkisinde olduğunu anlayarak, Docker veya Kubernetes gibi araçların arkasındaki mantığı kavramaktır.
Konteynerin Hedefi Nedir?
Bir konteynerin amacı, bir uygulamanın çalışmasını sağlamak için gerekli olan tüm dosyaları, kütüphaneleri ve yapılandırma dosyalarını izole bir ortamda barındırmaktır. Yani, bir uygulama çalışırken, bu ortamın ana sistemle (host) olan bağlantısını minimuma indirmek, aynı zamanda hem güvenliği hem de taşınabilirliği artırmaktır.
Örneğin, docker run nginx komutunu çalıştırdığınızda, Nginx bir Debian tabanlı bir ortamda çalışır, ancak bu, sunucunuzun işletim sistemi ne olursa olsun, aynı şekilde çalışır. Peki bu nasıl olur?
Konteynerin Temelleri: Namespace’lar ve Mount Mekanizması
Konteynerlerin çalışması için, Linux’un birkaç temel mekanizması kullanılır:
- Mount Namespace
- PID Namespace
- Cgroup Namespace
- UTS Namespace
- Network Namespace
Ancak bu makalede, Mount Namespace’ın ne kadar temel bir rol oynadığını göstereceğiz. Çünkü konteynerlerin izolasyonu, dosya sistemi görünümlerindeki değişiklikten başlar.
Mount Namespace Nedir?
Mount Namespace, bir process’in hangi dosya sistemlerini görebileceğini belirler. Yani, aynı dosya sistemini paylaşan birden fazla süreç, farklı mount tablolarına sahip olabilir.
Bir Deney: Mount Namespace Oluşturma
Terminal 1’de aşağıdaki komutla bir mount namespace’i oluşturun:
sudo unshare --mount bash
Bu komut, yeni bir shell açar ve bu shell, ana sistemdeki dosya sistemini paylaşmaz. Yani, bu yeni shell’deki mount komutu, ana sistemdeki dosya sistemiyle aynı şeyi görmeyecektir.
Şimdi Terminal 2’de bir dosya oluşturun:
echo "Hello from host's mount namespace" | sudo tee /opt/marker.txt
Terminal 1’de şimdi bu dosyayı arayın:
cat /opt/marker.txt
Sonuç: Dosya görünmüyor! Çünkü bu iki terminal farklı mount namespace’lere sahiptir.
Mount Namespace’ı Doğrulama
Her iki terminalde de şu komutu çalıştırın:
findmnt
Terminal 1’de ve Terminal 2’de farklı findmnt çıktıları görünecektir. Bu, her bir namespace’in kendi dosya sistemini görmesini sağlar.
Mount Propagation Nedir?
Mount Propagation, bir mount’un başka bir mount namespace’e nasıl yansıtılacağını belirler. Örneğin, bir mount noktasına bir dosya sistemi bağlandıysa, bu bağlanma diğer namespace’lere nasıl görünür?
Bu konu, konteynerlerin içindeki dosya sistemlerinin nasıl çalıştığını anlamak için çok önemlidir. Ancak bu makalede, sadece temel fikri anlatılacaktır.
Konteynerin Sıfırdan Yaratılması
Şimdi, bir konteyneri sıfırdan nasıl kuracağımızı adım adım görelim.
Adım 1: Root Filesystem Oluşturma
Konteynerler, bir root filesystem ile başlar. Bu, bir Linux dağıtımı gibi bir yapıdır. Örneğin, bir Ubuntu sistemini kullanabiliriz.
Daha önce bir chroot veya pivot_root gibi araçlarla bu işlem yapılır. Ancak günümüzde pivot_root daha güvenli ve doğru bir yoldur.
Adım 2: Mount Namespace ile İzolasyon
Aşağıdaki komutla bir mount namespace’i oluşturun:
sudo unshare --mount bash
Bu komut, yeni bir shell oluşturur ve bu shell, ana sistemdeki dosya sistemini paylaşmaz.
Adım 3: Root Filesystem’i Monte Etme
Şimdi, bir root filesystem’i monte etmek için bir dizin oluşturun ve üzerine bir dosya sistemi bağlayın:
mkdir /tmp/myroot
sudo mount --bind / /tmp/myroot
Bu, ana sistemdeki tüm dosyaları /tmp/myroot dizinine bağlar. Ancak bu, sadece bu namespace içinde geçerlidir.
Adım 4: Pivot Root ile Root Değiştirme
pivot_root komutu, yeni root dizinini sistemdeki root olarak belirler. Bu, konteynerin kendi dosya sistemini kullanmasını sağlar.
cd /tmp/myroot
sudo pivot_root . .
Bu komut, konteynerin root dizinini değiştirmeyi sağlar. Artık cd / komutu, konteynerin kendi root dizinini gösterir.
Diğer Namespace’lerin Rolü
Artık konteynerin dosya sistemi izole edilmiş. Ama bu sadece bir başlangıçtır. Konteynerin daha gerçekçi olması için aşağıdaki namespace’ler de eklenir:
- PID Namespace: Konteyner içindeki süreçlerin kendine ait process ID’lerine sahip olmalarını sağlar. Böylece, konteyner içindeki
initsüreci, sistemdeki1numaralı süreç olur. - Cgroup Namespace: Süreçlerin kaynak kullanımı (CPU, bellek) için izolasyon sağlar.
- UTS Namespace: Konteynerin kendi bilgisayar adı ve domain adı olmasına izin verir.
- Network Namespace: Konteynerin kendi ağ yapılandırmasına sahip olmasına izin verir.
Ancak bu namespace’ler, mount namespace’inin oluşturduğu temel izolasyonun üzerine kurulur.
Konteynerlerin Gerçekleşmesi
Docker gibi bir runtime (örneğin runc), bu tüm adımları otomatikleştirir:
unshareile namespace’ler oluşturur.mountile dosya sistemlerini monte eder.pivot_rootile root dizinini değiştirir.chrootveyaexecile komutu çalıştırır.
Bu süreç, sadece bir komutla tamamlanır: docker run nginx.
Sonuç
Konteynerler, sadece bir "iyi bir araç" değil, bir sistem düzeyi izolasyon mekanizmasıdır. Docker gibi bir araç, bu mekanizmaları kullanarak, bir uygulamanın farklı sistemlerde aynı şekilde çalışmasını sağlar.
Bu makalede, sadece birkaç komutla konteynerin nasıl çalıştığını anlattık. Ancak bu, geliştiricilerin Linux konteynerlerinin nasıl çalıştığını anlamasına yardımcı olur.
Ekstra Bilgi: Linux Konteynerlerinin Tarihi
Linux’ta ilk namespace mekanizması, 2002 yılında Linux 2.4 sürümünde tanıtılmıştır. Bu, konteyner teknolojisinin temelini oluşturmuştur. Daha sonra, cgroups, namespaces ve pivot_root gibi araçlar geliştirilerek, modern konteyner platformları oluşturulmuştur.
Özetle
- Konteynerler, dosya sistemi izolasyonu ile başlar.
mountnamespace, bu izolasyonun temelini oluşturur.unshare,mount,pivot_rootgibi araçlarla bu izolasyon sağlanır.- Diğer namespace’ler (PID, Cgroup, Network vb.) konteyneri daha gerçekçi hale getirir.
Konteyner teknolojisi, sadece bir araç değil, modern yazılım geliştirme dünyasının temel taşlarından biridir. Bu makale, bu yapıyı sadece kullanmak değil, aynı zamanda neden çalıştığını anlamanı sağlar.