Ders 16 / 21
Birimler ve Bağlama Takmaları
Kalıcı verinin yazılabilir katmanın dışına çıkarılması: yönetilen birim ile doğrudan dizin takmasının gerçek dizinlerle kurulması, konteyner silindiğinde kalan bayt, konteyner içindeki kullanıcı kimliği ana makinedeki dosya sahibiyle uyuşmadığında yazılamayan düğüm sayısı ve mutlak yola bağlı takmanın makine değiştiğinde kırılması.
İçindekiler
Önceki ders kaybın iki sınıfta kabul edilemez olduğunu ölçtü: iş durumu ve kullanıcı verisi, toplam 7.945 bayt. İkisi de yazılabilir katmanın içinde durduğu için konteyner silindiğinde gitti. Çözüm tek cümleyle söylenir — o iki dosyayı katmanın dışına koymak. Ama katmanın dışı ana makinenin dosya sistemidir ve oraya açılan her yol yalıtım bütçesinden bir kalem harcar.
Bu ders iki bağlama biçimini gerçek dizinlerle kurup üç şeyi ayrı ayrı sayar: konteyner silindiğinde kaç bayt kalıyor, konteyner içindeki kullanıcı kimliği dizinin sahibiyle uyuşmadığında kaç düğüm yazılamıyor ve makine değiştiğinde hangi biçim kırılıyor. Üçüncü ölçüm, yalıtımın bu kursta en açık delindiği yeri de adıyla verir.
İki Bağlama Biçimi
Konteynerin gördüğü dosya sistemi bir takma tablosudur: konteyner içindeki her yol, ana makinede bir yere karşılık gelir. Yazılabilir katman da bu tablodaki bir satırdır, tek farkı konteynerle birlikte silinmesidir. Katmanın dışına çıkmanın iki yolu vardır ve ikisi tabloda nasıl anıldıklarıyla ayrılır.
Yönetilen birim bir adla anılır. Çalışma zamanı adı kendi kök dizini altında bir yere çözer; ayarda yalnız ad durur, yol durmaz. Bağlama takması doğrudan bir mutlak yolla anılır; ayarda ana makinenin dizin yolu yazılıdır ve çözüm diye bir şey yoktur, yol neyse odur.
İkisinin ortak bir yan etkisi vardır: takma noktası imajda dolu bir dizine denk geliyorsa, oradaki içerik takma sürdüğü sürece görünmez olur. Alt katmandaki baytlar durur, silinmez, yalnız konteynerin gördüğü yolun ucunda artık başka bir dizin vardır. Bu, imajın içine alınmış bir varsayılan ayarın koşumda sessizce ortadan kalkması demektir; hata verilmez, dosya “yok” görünür.
Hangi verinin dışarı çıkarılacağı da bir bütçe kararıdır. 02. dersteki beş sınıftan yalnız ikisi takıldı; günlük yazılabilir katmanda bırakıldı ve 673.560 baytı yine gitti. Takılsaydı kaybolmazdı ama otuz gecede 673.560 bayt kalıcı diskte birikirdi ve onu kim silecek sorusu da eklenirdi. Dışarı çıkarılan her sınıf kalıcılık kazandırır, karşılığında bir yaşam döngüsü sorumluluğu yükler.
- CZ13 — Takma tablosu modeldir: üç konteyner içi yol üç ayrı ana makine hedefine karşılık geliyor. Dizinler ve baytlar gerçektir.
- CZ14 — 02. dersteki koşum aynen tekrarlanıyor: 30 gece, gecede 480 okuma, aynı tohum. Değişen tek şey iş durumu ile düzeltmelerin nereye yazıldığıdır; günlük yazılabilir katmanda kalıyor.
- CZ15 — Yönetilen birim çalışma zamanının kök dizini altında
olcum-durumadıyla, bağlama takması ana makinede mutlak bir yolla anılıyor. - CZ16 — Konteyner içindeki kullanıcı kimliği ana makinedeki dosya sahibiyle uyuşmuyor; bu yüzden uygulanan izin sınıfı “diğer”dir. Mod bitleri gerçek dosyalardan okunuyor.
- CZ17 — Sekiz düğümün mod dağılımı kurgudur; saha ekibinin bıraktığı düzeni temsil ediyor.
- CZ18 — Makine değişimi, kök dizinin adının değişmesiyle modelleniyor.
// calisma/baglama.mjs — iki baglama bicimi: kalicilik, sahiplik catismasi, tasinabilirlik. // MODEL: takma tablosu ve konteyner kullanici kimligi modeldir; dizinler, bayt ve mod bitleri gercektir. import { mkdirSync, writeFileSync, appendFileSync, chmodSync, statSync, existsSync, readdirSync, renameSync, rmSync } from "node:fs"; import { join, dirname, resolve } from "node:path"; const KOK = "kok", CZ = `${KOK}/cz`, UST = `${KOK}/konteyner/ust`, SAHA = `${KOK}/saha`; const OKUMA = 480, GECE = 30, TOHUM = 20260801; // 02. dersle ayni kosum rmSync(KOK, { recursive: true, force: true }); rmSync("kok-b", { recursive: true, force: true }); const TAKMA = { // CZ13: konteyner ici yol -> ana makine "/gunluk": { tur: "yazilabilir katman", hedef: `${UST}/gunluk` }, "/veri/durum": { tur: "yonetilen birim", ad: "olcum-durum", hedef: `${CZ}/birimler/olcum-durum` }, "/veri/duzeltmeler": { tur: "dogrudan takma", yol: resolve(`${SAHA}/duzeltmeler`), hedef: `${SAHA}/duzeltmeler` }, }; const yaz = (ic, dosya, icerik, ek) => { const p = join(TAKMA[ic].hedef, dosya); mkdirSync(dirname(p), { recursive: true }); (ek ? appendFileSync : writeFileSync)(p, icerik); }; let s = TOHUM % 2147483647; const rast = () => (s = (s * 48271) % 2147483647) / 2147483647; for (let g = 1; g <= GECE; g += 1) for (let i = 1; i <= OKUMA; i += 1) { const deger = (100 + rast() * 900).toFixed(3); yaz("/gunluk", "dogrulama.log", `okuma ${i} sayac ${1000 + i} deger ${deger} durum tamam\n`, true); if (i % 60 === 0) yaz("/veri/durum", "ilerleme.json", `{"islenen":${i},"kalan":${OKUMA - i}}`, false); if (i % 40 === 0) yaz("/veri/duzeltmeler", "duzeltmeler.csv", `${1000 + i},operator,${deger}\n`, true); } const olc = (k) => { let b = 0, n = 0; const gez = (d) => { for (const e of readdirSync(d, { withFileTypes: true })) { const p = join(d, e.name); if (e.isDirectory()) gez(p); else { b += statSync(p).size; n += 1; } } }; if (existsSync(k)) gez(k); return { bayt: b, dosya: n }; }; const once = Object.fromEntries(Object.entries(TAKMA).map(([ic, t]) => [ic, olc(t.hedef)])); rmSync(`${KOK}/konteyner`, { recursive: true, force: true }); // konteyner siliniyor console.log(`${"takma".padEnd(22)}${"bicim".padEnd(21)}${"silmeden once".padStart(14)}${"silmeden sonra".padStart(16)}`); let kalan = 0, giden = 0; for (const [ic, t] of Object.entries(TAKMA)) { const sonra = olc(t.hedef).bayt; kalan += sonra; giden += once[ic].bayt - sonra; console.log(`${ic.padEnd(22)}${t.tur.padEnd(21)}${String(once[ic].bayt).padStart(14)}${String(sonra).padStart(16)}`); } console.log(`konteyner silindi: giden ${giden} bayt, kalan ${kalan} bayt (02. derste kalan 0 bayt idi)`); // CZ16: konteyner icindeki kimlik ana makinenin sahibiyle uyusmuyor; uygulanan izin sinifi "diger". const DUGUM = [[`${CZ}/birimler/olcum-durum`, 0o755, "d"], [`${CZ}/birimler/olcum-durum/ilerleme.json`, 0o644, "f"], [`${CZ}/birimler/olcum-durum/kilit`, 0o644, "f"], [`${SAHA}/duzeltmeler`, 0o775, "d"], [`${SAHA}/duzeltmeler/duzeltmeler.csv`, 0o664, "f"], [`${SAHA}/arsiv/2026-07.csv`, 0o600, "f"], [`${SAHA}/paylasim`, 0o777, "d"], [`${SAHA}/paylasim/aktarim.csv`, 0o666, "f"]]; for (const [p, m, tur] of DUGUM) { if (tur === "d") mkdirSync(p, { recursive: true }); else if (!existsSync(p)) { mkdirSync(dirname(p), { recursive: true }); writeFileSync(p, "x"); } chmodSync(p, m); } console.log(`\n${"dugum".padEnd(38)}${"mod".padStart(6)}${"sahip yazabilir".padStart(17)}${"diger yazabilir".padStart(17)}`); let sahipY = 0, digerY = 0; for (const [p] of DUGUM) { const m = statSync(p).mode & 0o777; const s1 = (m & 0o200) !== 0, s2 = (m & 0o002) !== 0; sahipY += s1 ? 1 : 0; digerY += s2 ? 1 : 0; console.log(`${p.replace(`${KOK}/`, "").padEnd(38)}${m.toString(8).padStart(6)}` + `${(s1 ? "evet" : "hayir").padStart(17)}${(s2 ? "evet" : "hayir").padStart(17)}`); } console.log(`kimlik uyusmadiginda ${DUGUM.length} dugumun ${DUGUM.length - digerY} tanesi yazilamiyor; ` + `kimlik esitlendiginde ${DUGUM.length - sahipY} tanesi yazilamiyor`); renameSync(KOK, "kok-b"); // makine degisti: duzen baska console.log(`\n${"takma".padEnd(22)}${"ayardaki referans".padEnd(30)}${"yeni makinede".padStart(14)}`); let kirik = 0, mutlak = 0; for (const [ic, t] of Object.entries(TAKMA)) { if (t.tur === "yazilabilir katman") continue; const yeni = t.ad ? join("kok-b/cz/birimler", t.ad) : t.yol; const cozuldu = existsSync(yeni); if (!cozuldu) kirik += 1; if (!t.ad) mutlak += 1; console.log(`${ic.padEnd(22)}${(t.ad ? `ad: ${t.ad}` : "mutlak yol").padEnd(30)}${(cozuldu ? "cozuldu" : "kirik").padStart(14)}`); } console.log(`iki takmanin ${mutlak} tanesi mutlak yola bagli, makine degisince ${kirik} tanesi kirildi`); rmSync("kok-b", { recursive: true, force: true });
takma bicim silmeden once silmeden sonra /gunluk yazilabilir katman 673560 0 /veri/durum yonetilen birim 25 25 /veri/duzeltmeler dogrudan takma 7920 7920 konteyner silindi: giden 673560 bayt, kalan 7945 bayt (02. derste kalan 0 bayt idi) dugum mod sahip yazabilir diger yazabilir cz/birimler/olcum-durum 755 evet hayir cz/birimler/olcum-durum/ilerleme.json 644 evet hayir cz/birimler/olcum-durum/kilit 644 evet hayir saha/duzeltmeler 775 evet hayir saha/duzeltmeler/duzeltmeler.csv 664 evet hayir saha/arsiv/2026-07.csv 600 evet hayir saha/paylasim 777 evet evet saha/paylasim/aktarim.csv 666 evet evet kimlik uyusmadiginda 8 dugumun 6 tanesi yazilamiyor; kimlik esitlendiginde 0 tanesi yazilamiyor takma ayardaki referans yeni makinede /veri/durum ad: olcum-durum cozuldu /veri/duzeltmeler mutlak yol kirik iki takmanin 1 tanesi mutlak yola bagli, makine degisince 1 tanesi kirildi
Bu sayılar ölçüm sınıfındadır.
Kalıcılık: Silinen Konteyner, Kalan Bayt
İlk tablo sorunun çözüldüğünü gösteriyor ve çözümün sınırını da veriyor. Konteyner silindikten sonra yazılabilir katmandaki 673.560 baytlık günlük gitti; yönetilen birimdeki 25 bayt ve bağlama takmasındaki 7.920 bayt yerinde. Toplam 7.945 bayt kaldı — önceki dersin kurtarılamaz sayısının tam olarak kendisi, ve o derste bu sayı sıfırdı.
Kalıcılık açısından iki biçim arasında hiçbir fark yoktur. İkisi de yazılabilir katmanın dışında durur, ikisi de konteynerin ömrüne bağlı değildir. Bu ölçü ikisini ayırmaz; ayıran ölçüler sonrakilerdir.
Yalıtımın bedeli burada koşum cinsinden değil, yüzey cinsindendir. Önceki derste konteynerin ana makineye açılan yazma yüzeyi tek bir dizindi ve o dizin konteynerle birlikte gidiyordu. Şimdi iki dizin daha eklendi ve ikisi de konteynerden uzun yaşıyor. Konteyner artık başladığı yerden başlamaz; başlangıç durumu diskte duran 7.945 bayta bağlıdır. Durumsuzluk 02. derste ölçülen anlamıyla bozuldu — bilerek ve bir karşılık alarak.
Bedelin ikinci kalemi hemen görünmüyor. Kalan 7.945 baytı silen bir yaşam döngüsü artık yoktur. Konteyner silindi, katman gitti, birim ve takma durdu; onları kaldıracak olan şey konteynerin ölümü değil, ayrı bir karardır. Yalıtımın dışına çıkarılan her dizin kendi saklama kuralını da ister — kim, ne zaman, hangi ölçüte göre silecek. Karar verilmezse ölçü şu olur: konteyner sayısı sabit kalırken diskte duran dizin sayısı artmayı sürdürür, çünkü her yeni ad yeni bir birim yaratır ve eskisini kimse aramaz.
Sahiplik: Yalıtımın Delindiği Yer
İkinci tablo, konteynerlerde yalıtımın en somut şekilde delindiği yeri veriyor.
Konteynerin içinde çalışan kullanıcının bir kimlik numarası vardır. Bağlama takmasıyla açılan dizin ise ana makinenin dosya sistemindedir ve oradaki dosyaların sahibi ana makinenin bir kullanıcısıdır. Yazma izni bu iki kimliğin karşılaştırılmasıyla belirlenir. Ad alanı süreçleri, ağı ve dosya sistemi görünümünü ayırır; kullanıcı kimliğinin sayı uzayını ayırmaz. Konteyner içindeki kimlik ile ana makinedeki sahip aynı sayı uzayında yaşar ve dosya izni yalnız o sayıya bakar.
Sonucu sayıyla: sekiz düğümün altısı yazılamıyor. Yazılabilen ikisi, mod bitlerinde “diğer” sınıfına yazma hakkı tanınmış olanlardır — 777 dizini ve 666 dosyası. Kalan altı düğüm, sahibi yazabildiği hâlde konteyner için kapalıdır: 755, 644, 644, 775, 664 ve 600. Kimlikler eşitlendiğinde sayı sıfıra iniyor; sekiz düğümün hepsi yazılabilir hâle geliyor, çünkü uygulanan sınıf “diğer” değil “sahip” oluyor.
İki satır ayrıca okunmalıdır. saha/duzeltmeler/duzeltmeler.csv 664 modundadır; sahibi ve grubu
yazabilir. Bu genellikle çözüm sanılır — konteyner kullanıcısı doğru gruba alınırsa yazabilir.
Ancak grup da bir sayıdır ve konteyner içindeki grup kimliği ana makinedekiyle uyuşmuyorsa
uygulanan sınıf yine “diğer”dir; tabloda o satırın yanıtı hayir. saha/arsiv/2026-07.csv ise
600 modundadır ve yalnız sahibine açıktır: geçmiş dönemin arşivi, takılan dizinin içinde durduğu
hâlde konteyner için hem yazılamaz hem okunamaz. Takma, dizinin görünmesini sağlar; içindekilere
erişimi sağlamaz.
Bu tablo iki yanlış çözümü de gösteriyor. Birincisi izinleri gevşetmektir: 777 ve 666 satırları gerçekten yazılabilir, ama o iki düğüm ana makinedeki her kullanıcıya da açıktır; konteynerin yazabilmesi için ödenen bedel, konteynerle ilgisi olmayan herkesin de yazabilmesidir. İkincisi kimlikleri eşitlemektir: sayı sıfıra iner, ama o zaman konteyner ana makinedeki bir kullanıcı gibi davranır ve takılan dizinde o kullanıcının yapabildiği her şeyi yapabilir. Yalıtım bütçesi açısından ikisi de aynı kalemi harcar — ana makinenin dosya sistemine açılan yetki yüzeyini.
Üçüncü bir yol daha vardır ve ölçüsü tabloda dolaylı okunur: takılan dizini konteynerin yazamayacağı, yalnız okuyacağı bir kaynak saymak. O zaman altı kapalı düğüm sorun olmaktan çıkar, çünkü zaten yazma istenmiyordur. Ölçüm ağında bu ayrım nettir — tarife tablosu ve sayaç listesi okunur, iş durumu ve düzeltmeler yazılır. Sekiz düğümün kaçının gerçekten yazılması gerektiği sorulduğunda sayı ikiye iner ve çakışma da o ikiye daralır.
Yönetilen birim bu çakışmayı ortadan kaldırmaz, yalnız başlangıç durumunu kontrol eder: birim çalışma zamanı tarafından yaratıldığı için sahipliği baştan konteynerin beklediği kimliğe ayarlanabilir. Bağlama takmasında böyle bir an yoktur; dizin zaten vardır, sahibi zaten bellidir ve konteyner ona uymak zorundadır.
Taşınabilirlik: Mutlak Yolun Bedeli
Üçüncü tablo iki biçimi ayıran ölçüdür. Makine değiştiğinde — koşum burada kök dizinin adını değiştirerek modelliyor — yönetilen birim çözüldü, bağlama takması kırıldı.
Nedeni ayardaki referansın türüdür. Birim bir adla anılır ve ad her makinede çalışma zamanının kendi
kökü altında çözülür; kök nerede olursa olsun olcum-durum bulunur. Takma bir mutlak yolla anılır ve
o yol bir makinenin dizin düzenine aittir. İki takmanın biri mutlak yola bağlıdır, makine değişince
biri kırılmıştır — yani taşınabilirlik oranı bire iki.
Ortamdan çıkarılan farkın burada bir sayısı vardır ve tabloda iki yönü birden okunur. Konteynerin
içinden bakıldığında fark tümüyle çıkarılmıştır: uygulama her makinede /veri/durum ve
/veri/duzeltmeler yollarına yazar, iki yol da her yerde aynıdır, ikisi de koda gömülüdür ve
makine değiştiğinde değişmez. Fark ana makine tarafına, takma tablosunun sağ sütununa itilmiştir ve
orada iki referanstan biri makineye bağlıdır. Yani çıkarılan fark yok olmadı, tek bir satıra
toplandı — ve o satır artık ayarın kendisidir, uygulamanın değil.
Bu, bağlama takmasının kusuru değil tanımıdır: amacı zaten ana makinedeki belirli bir dizini konteynere açmaktır. Kaynak kodun bulunduğu dizini konteynere takan bir geliştirme kurulumu bunu bilerek yapar; makineye bağlı olması istenen davranıştır. Sorun, aynı takmanın koşum ortamına taşınmasıdır. Sayı şunu söyler: makineye bağlı olmayan bir ayar isteniyorsa iki biçimden yalnız biri o sözü verir.
Özet
- İki bağlama biçimi de yazılabilir katmanın dışındadır: konteyner silindikten sonra yönetilen birimde 25, bağlama takmasında 7.920 bayt kalıyor; toplam 7.945 bayt, önceki derste sıfırdı. Yazılabilir katmandaki 673.560 baytlık günlük yine gitti.
- Kalıcılık ölçüsü iki biçimi ayırmıyor; ayıran ölçüler sahiplik ve taşınabilirliktir.
- Yalıtımın delindiği yer: ad alanı kullanıcı kimliğinin sayı uzayını ayırmaz. Konteyner içindeki kimlik ana makinedeki dosya sahibiyle uyuşmadığında sekiz düğümün altısı yazılamıyor; kimlikler eşitlendiğinde sayı sıfıra iniyor.
- İki yanlış çözümün de bedeli aynı kalemdedir: izinleri gevşetmek (777, 666) düğümü ana makinedeki herkese açar, kimlikleri eşitlemek konteynere ana makine kullanıcısının yetkisini verir.
- Yönetilen birim çakışmayı kaldırmaz, başlangıç durumunu kontrol eder: birim yaratıldığı anda sahipliği ayarlanabilir, bağlama takmasında böyle bir an yoktur.
- Taşınabilirlikte iki biçim ayrışıyor: iki takmanın biri mutlak yola bağlı ve makine değişince o biri kırıldı; adla anılan birim çözüldü.
Sonraki Adım
Kalıcı veri yerine oturdu: iş durumu ve düzeltmeler artık konteynerden uzun yaşıyor ve bunun bedeli ana makinenin dosya sistemine açılan iki dizinle ödendi. Ölçülen her şey burada tek bir konteynerin kendi sınırları içindeydi — kaynağı, dosya sistemi, kimliği. Oysa ölçüm ağı tek bir program değil: okuma toplayıcı doğrulayıcıya, doğrulayıcı faturalamaya, faturalama iş emri servisine veri veriyor ve dördü ayrı konteynerde koşuyor. Dosya sistemi yalıtıldığında bu dördü birbirini nasıl buluyor, hangi adla çağırıyor ve biri ötekine ulaşamasın istendiğinde ne yapılıyor? Sonraki ders bir ad çözümleme ve erişilebilirlik matrisi kurar ve şunu sayar: dört servis iki ağa bölündüğünde kaç yol kapanıyor ve dışarıya açılan yüzey kaç uçtan kaç uca iniyor.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.