Ders 12 / 12
Altyapı Sağlama Modelleri
Aynı ortam elle, betikle ve bildirimsel olarak kurulur; iki kurulum arasındaki fark, betiğin ikinci koşumda ve yarıda kaldığında bıraktığı durum ve altı dönem boyunca biriken yapılandırma sapması sayılır. Çalışan bir uzlaştırıcı istenen durumu dosyadan, gerçek durumu diskten okur, farkı kapatır ve ikinci koşumda sıfır iş yapar.
İçindekiler
Bir önceki ders on iki ilkeyi denetime çevirdi ve dördünün karar için ikinci bir gözlem — çoğu zaman ikinci bir ortam — istediğini yazdı. Uygulamanın kendisi artık denetlenebilir durumda: bağımlılığı bildirilmiş, yapılandırması dışarıda, kapanışı sınanabilir. Altında durduğu makine ise hâlâ elle kuruluyor ve o makinenin nasıl kurulduğu hiçbir denetimin kapsamında değil.
Sağlama, bir ortamı istenen duruma getirme işidir: paketlerin kurulması, ayarların yazılması, dizinlerin açılması. Üç biçimi vardır — elle, betikle, bildirimsel — ve aralarındaki ayrım hız değil, aynı tariften kaç ayrı sonuç doğduğudur. Bu ders aynı ortamı üçünde de kurar ve üç sayıyı ölçer: kurulum adımı, iki kurulum arasındaki fark, ve yapılandırma sapmasının dönemler boyunca ne kadar büyüdüğü.
Ölçüm yine bölgesel ölçüm ağı üzerindedir: su sayacı okumalarını toplayan, doğrulayan ve saha iş emri açan kurgu yazılım. Dosyalar gerçekten diske yazılır, betikler ve uzlaştırıcı gerçekten koşar.
DK27. Ortam yedi kalemle temsil edilir — iki paket sürümü, üç ayar, iki dizin. DK28. Elle kurulumun yönergesi düzyazıdır ve yedi adımın üçü sayı vermez; iki elin yorumu bu üç adımda ayrılır. El bir modeldir, yorumu önceden yazılıdır. DK29. Betik yedi adımı sırayla koşar, hiçbir adım önce durumu okumaz; yarıda kalma noktası bir ortam değişkeniyle tetiklenir. DK30. Bildirimsel modelde istenen durum bir dosyadır; uzlaştırıcı gerçek durumu diskten okur ve yalnız farklı kaleme dokunur. DK31. Sapma taramasında altı dönem koşulur ve her dönemde bir elle müdahale yapılır; müdahaleler önceden yazılıdır, rastgelelik yoktur.
Üç Model, Aynı Yedi Kalem
#!/usr/bin/env bash # Ayni ortamin uc ayri tarifi: bildirim, duzyazi yonerge ve saglama betigi. set -e cat > istenen.json <<'SON' { "paket/cozumleyici": "3.4.0", "paket/kural-paketi": "9.1.0", "ayar/kutuk-duzeyi": "ozet", "ayar/es-zamanli-isci": "8", "ayar/toplu-is-baslangic": "02:30", "dizin/veri": null, "dizin/kutuk": null } SON cat > tarif-elle.txt <<'SON' 1. paket dizinini ac, cozumleyicinin 3.4.0 surumunu kur 2. kural paketini 9.1.0 surumune sabitle 3. kutuk duzeyini uretime uygun bir degere cek 4. es zamanli isci sayisini makinenin gucune gore ayarla 5. gecelik toplu isi trafigin dusuk oldugu bir saate al 6. veri dizinini ac 7. kutuk dizinini ac SON cat > kur.sh <<'SON' #!/usr/bin/env bash # Betikle saglama: yedi adim sirayla kosar; hicbir adim once durumu okumaz. set -e mkdir -p ortam/paket ortam/ayar ortam/dizin echo "3.4.0" >> ortam/paket/cozumleyici echo "9.1.0" >> ortam/paket/kural-paketi echo "ozet" >> ortam/ayar/kutuk-duzeyi [ -z "$KES" ] || exit 3 # yarida kalma noktasi echo "8" >> ortam/ayar/es-zamanli-isci echo "02:30" >> ortam/ayar/toplu-is-baslangic mkdir ortam/dizin/veri ortam/dizin/kutuk SON
Üç tarif de aynı yedi kalemi hedefler. Bildirim kalemleri değerleriyle sayar; yönerge üç adımda sayı vermez (“uygun bir değer”, “makinenin gücüne göre”, “trafiğin düşük olduğu bir saat”); betik yedi adımı sırayla koşar. Denetleyici hiçbir şey düzeltmez, yalnız diski istenen durumla karşılaştırıp sayar.
// denetle.mjs — diskteki ortami istenen durumla karsilastirir ve sayar; hicbir sey duzeltmez. import { readFileSync, existsSync, statSync } from "node:fs"; const kok = process.argv[2] ?? "ortam"; const istenen = JSON.parse(readFileSync("istenen.json", "utf8")); const durum = (yol) => { const t = `${kok}/${yol}`; if (!existsSync(t)) return "eksik"; const g = statSync(t).isDirectory() ? "" : readFileSync(t, "utf8").trim(); return g === (istenen[yol] ?? "") ? "uygun" : "sapmis"; }; const s = Object.keys(istenen).map(durum); const say = (t) => s.filter((x) => x === t).length; const sapma = say("sapmis") + say("eksik"); console.log(process.argv[3] === "-k" ? sapma // -k: yalniz sapma sayisi : ` kalem ${s.length} uygun ${say("uygun")} sapmis ${say("sapmis")}` + ` eksik ${say("eksik")} sapma ${sapma}`);
Aynı Tarif, Kaç Ayrı Sonuç
#!/usr/bin/env bash # Betik modelinin uc senaryosu ve elle kurulumun iki eli. kos() { printf '%s\n' "$1"; shift; "$@" >/dev/null 2>&1; printf ' betigin cikis kodu %s\n' "$?"; } rm -rf ortam kos "1. kosum (bos ortam)" bash kur.sh node denetle.mjs kos "2. kosum (ayni betik yeniden)" bash kur.sh node denetle.mjs rm -rf ortam kos "3. kosum (yarida kesilen)" env KES=1 bash kur.sh node denetle.mjs printf ' nerede kaldigini yazan kayit: %s dosya\n' "$(ls ortam/*.durum 2>/dev/null | wc -l | tr -d ' ')" el() { # $1 dizin, $2..$4 elin yorumladigi uc deger rm -rf "$1"; mkdir -p "$1/paket" "$1/ayar" "$1/dizin/veri" "$1/dizin/kutuk" printf '3.4.0\n' > "$1/paket/cozumleyici"; printf '9.1.0\n' > "$1/paket/kural-paketi" printf '%s\n' "$2" > "$1/ayar/kutuk-duzeyi"; printf '%s\n' "$3" > "$1/ayar/es-zamanli-isci" printf '%s\n' "$4" > "$1/ayar/toplu-is-baslangic" } el el-1 ozet 8 02:30 el el-2 ayrinti 4 03:00 printf 'elle kurulum: ayni yonergeden iki el\n iki kurulum arasindaki fark %s kalem\n' \ "$(diff -rq el-1 el-2 | wc -l | tr -d ' ')" node denetle.mjs el-1 node denetle.mjs el-2
1. kosum (bos ortam) betigin cikis kodu 0 kalem 7 uygun 7 sapmis 0 eksik 0 sapma 0 2. kosum (ayni betik yeniden) betigin cikis kodu 1 kalem 7 uygun 2 sapmis 5 eksik 0 sapma 5 3. kosum (yarida kesilen) betigin cikis kodu 3 kalem 7 uygun 3 sapmis 0 eksik 4 sapma 4 nerede kaldigini yazan kayit: 0 dosya elle kurulum: ayni yonergeden iki el iki kurulum arasindaki fark 3 kalem kalem 7 uygun 7 sapmis 0 eksik 0 sapma 0 kalem 7 uygun 4 sapmis 3 eksik 0 sapma 3
Betiğin ilk koşumu yedi kalemin yedisini yerine koyar. Aynı betiğin ikinci koşumu ortamı
bozar: beş kalem sapar ve betik yedinci adımda düşer. Nedeni iki karakterdedir — ekleme yapan
>> ve -p almayan mkdir. Betik önce durumu okumadığı için işin daha önce yapılıp
yapılmadığını bilemez; bir işlemin bir kez ile çok kez uygulanmasının aynı sonucu vermesine
etkisizlik denir ve bu betik onu taşımaz.
Yarıda kesilen koşum daha pahalıdır: üç kalem yerinde, dört kalem eksik ve nerede kalındığını yazan kayıt sıfır. Ortam ne eski ne yeni durumdadır; betiğin bildirdiği tek şey bir çıkış kodudur ve o kod hangi adımda durulduğunu söylemez.
Elle kurulumda iki el aynı yönergeyi okudu ve üç kalemde ayrıldı — tam olarak yönergenin sayı vermediği üç adımda. Buradaki fark bir dikkatsizlik değil, tarifin yazılmamış kısmıdır: tarif ile ortam arasındaki boşluğu insan doldurur ve doldurduğu değer hiçbir yere yazılmaz. Ölçü tek satıra iner: elle kurulumda aynı tarif iki ayrı sonuç doğurdu, betikle sağlamada ikinci koşum üçüncü bir sonuç doğurdu — üstelik ilkinden de bozuk olanı.
Sapmanın Sayılabilir Olması
// uzlastir.mjs — istenen durumu dosyadan, gercek durumu diskten okur; farki yazar ve kapatir. import { readFileSync, writeFileSync, mkdirSync, existsSync, statSync } from "node:fs"; const istenen = JSON.parse(readFileSync("istenen.json", "utf8")); const gercek = (yol) => { const t = `ortam/${yol}`; if (!existsSync(t)) return null; return statSync(t).isDirectory() ? "" : readFileSync(t, "utf8").trim(); }; const fark = Object.entries(istenen).map(([yol, d]) => ({ yol, d: d ?? "", g: gercek(yol) })) .filter((f) => f.g !== f.d) .map((f) => ({ ...f, tur: f.g === null ? "eksik" : "sapmis" })); for (const f of fark) { // uzlastirma: yalniz farkli olan kaleme dokunulur const t = `ortam/${f.yol}`; if (istenen[f.yol] === null) mkdirSync(t, { recursive: true }); else { mkdirSync(t.slice(0, t.lastIndexOf("/")), { recursive: true }); writeFileSync(t, istenen[f.yol] + "\n"); } } console.log(` kalem ${Object.keys(istenen).length} fark ${fark.length}` + ` (eksik ${fark.filter((f) => f.tur === "eksik").length},` + ` sapmis ${fark.filter((f) => f.tur === "sapmis").length}) yapilan is ${fark.length}`); for (const f of fark) console.log(` ${f.tur.padEnd(6)} ${f.yol.padEnd(24)}` + (istenen[f.yol] === null ? " (dizin acilir)" : ` "${f.g ?? ""}" -> "${f.d}"`));
#!/usr/bin/env bash # Uzlastirici: bos ortam, ikinci kosum (etkisizlik), elle mudahale sonrasi. rm -rf ortam echo "1. kosum (bos ortam)"; node uzlastir.mjs echo "2. kosum (hemen ardindan)"; node uzlastir.mjs echo "elle mudahale: isci sayisi 16 yapildi, kutuk dizini silindi" echo 16 > ortam/ayar/es-zamanli-isci; rm -rf ortam/dizin/kutuk echo "3. kosum (mudahaleden sonra)"; node uzlastir.mjs mudahale() { case $1 in 1) echo 16 > ortam/ayar/es-zamanli-isci ;; 2) echo ayrinti > ortam/ayar/kutuk-duzeyi ;; 3) rm -rf ortam/dizin/kutuk ;; 4) echo 3.5.0 > ortam/paket/cozumleyici ;; 5) echo 03:15 > ortam/ayar/toplu-is-baslangic ;; 6) echo 9.2.0 > ortam/paket/kural-paketi ;; esac; } echo "" echo "alti donem, her donemde bir elle mudahale (sapma birikimi)" for uzlastirma in yok var; do rm -rf ortam; node uzlastir.mjs > /dev/null printf ' uzlastirma %s :' "$uzlastirma" for d in 1 2 3 4 5 6; do mudahale "$d" [ "$uzlastirma" = var ] && node uzlastir.mjs > /dev/null printf ' %s' "$(node denetle.mjs ortam -k)" done printf '\n' done echo "" printf 'tarif buyuklugu (satir): yonerge %s, betik %s, bildirim %s, uzlastirici %s\n' \ "$(wc -l < tarif-elle.txt)" "$(wc -l < kur.sh)" "$(wc -l < istenen.json)" \ "$(wc -l < uzlastir.mjs)" | tr -s ' '
1. kosum (bos ortam)
kalem 7 fark 7 (eksik 7, sapmis 0) yapilan is 7
eksik paket/cozumleyici "" -> "3.4.0"
eksik paket/kural-paketi "" -> "9.1.0"
eksik ayar/kutuk-duzeyi "" -> "ozet"
eksik ayar/es-zamanli-isci "" -> "8"
eksik ayar/toplu-is-baslangic "" -> "02:30"
eksik dizin/veri (dizin acilir)
eksik dizin/kutuk (dizin acilir)
2. kosum (hemen ardindan)
kalem 7 fark 0 (eksik 0, sapmis 0) yapilan is 0
elle mudahale: isci sayisi 16 yapildi, kutuk dizini silindi
3. kosum (mudahaleden sonra)
kalem 7 fark 2 (eksik 1, sapmis 1) yapilan is 2
sapmis ayar/es-zamanli-isci "16" -> "8"
eksik dizin/kutuk (dizin acilir)
alti donem, her donemde bir elle mudahale (sapma birikimi)
uzlastirma yok : 1 2 3 4 5 6
uzlastirma var : 0 0 0 0 0 0
tarif buyuklugu (satir): yonerge 7, betik 11, bildirim 3, uzlastirici 27
Uzlaştırıcı üç iş yapar: istenen durumu dosyadan okur, gerçek durumu diskten okur, yalnız farklı kaleme dokunur. İlk koşum yedi kalemi eksik bulup yedi iş yapar; ikinci koşum sıfır iş yapar. Betiğin taşımadığı etkisizlik burada ölçülmüş hâldedir ve nedeni tek bir sıra değişikliğidir — önce okumak, sonra yazmak.
Ayırt edici yan üçüncü koşumdadır. Elle müdahale iki kalemi bozdu; uzlaştırıcı ikisini de adıyla,
eski ve yeni değeriyle yazıp kapattı. Sapma burada bir sayıdır: fark 2. Öteki iki modelde
sapmayı sayacak yer yoktu, çünkü istenen durum okunabilir bir nesne değildi — biri insanın
yorumunda, öteki bir komut dizisinde duruyordu. Komut dizisi ne yapılacağını söyler, ne
olması gerektiğini söylemez; sapmanın sayılabilirliği bu iki cümle arasındaki farktır.
Altı dönemlik tarama bunu iki satıra indirir: uzlaştırma koşmadığında müdahaleler birikir (1, 2, 3, 4, 5, 6), koştuğunda dizi sıfırda kalır. Sapma yok olmuyor, her dönemde doğup kapanıyor. Birikmeyen şey sapmanın kendisi değil, bilinmeyen sapmadır.
Üç Modelin Bedeli
| Ölçü | Elle | Betikle | Bildirimsel |
|---|---|---|---|
| tarif büyüklüğü (satır) | 7 | 11 | 3 artı 27 (bir kez yazılır) |
| ilk kurulumda yerine gelen kalem | 7 ve 4 (iki el) | 7 | 7 |
| aynı tariften ayrı sonuç | 2 | 2 | 1 |
| tarif ikinci kez koşarsa | ölçülemez | 5 kalem sapar, çıkış 1 | 0 iş |
| yarıda kalırsa geriye kalan | kayıtsız | 3 kalem, 0 kayıt | fark yeniden hesaplanır |
| 6 dönemde biriken sapma | 1’den 6’ya | 1’den 6’ya | her dönem 0 |
| sapmayı yakalama | yok | yok | bildirimdeki 7 kalem |
Yazım maliyeti bildirimsel modelde en düşük görünür — üç satır — ama sayı yanıltıcıdır: uzlaştırıcı yirmi yedi satırdır ve farkı yapan şey onun bir kez yazılıp her ortam için yeniden kullanılmasıdır. Betik on bir satırdır ve her yeni kalemle büyür; yönerge yedi satırdır ve büyüdükçe belirsizliği de büyür, çünkü düzyazının her cümlesi bir yorum noktasıdır.
İlk kurulum süresi üç modelde de aynı mertebededir; ayrım orada değil, ikinci koşumda ve müdahaleden sonra çıkar. Sağlama tartışmasının en sık kaçırdığı yer budur: yalnız ilk kurulumla karşılaştırıldığında betik yeterli görünür, çünkü orada bildirimsel modelle aynı sonucu verir.
Bildirimsel modelin sınırı da sayılabilir. Uzlaştırıcı yalnız bildirimde yazan yedi kalemi görür; ortama sekizinci bir dosya elle eklendiğinde hiçbir koşumda fark olarak çıkmaz. Sapmayı sayılabilir kılan şey bildirimin kapsamıdır ve kapsam dışındaki fark hiçbir yerde yazılı olmayan bir yerde birikir: bir elin yorumunda, yarıda kalmış bir koşumun kısmi durumunda. Bu konunun ilk dersinde yalnız koşumda görünen altı farkın kaynağı burasıdır.
Özet
- Elle kurulumda iki el aynı yönergeden 3 kalemde ayrıldı; ayrıldıkları adımlar yönergenin sayı vermediği üç adımdı.
- Betiğin ilk koşumu 7 kalemi yerine koydu; ikincisi 5 kalemi bozup düştü, yarıda kesileni 3 kalem bırakıp 4’ünü eksik ve nerede kalındığını yazan 0 kayıt bıraktı.
- Uzlaştırıcı ilk koşumda 7, ikinci koşumda 0 iş yaptı; elle müdahaleden sonra 2 sapmayı adıyla yazıp kapattı.
- Altı dönemde uzlaştırma yokken sapma 1’den 6’ya birikti, varken 0’da kaldı; birikmeyen şey sapma değil, bilinmeyen sapmadır.
- Bildirimsel modelin sınırı bildirimin kapsamıdır: kapsam dışındaki her şey elle kurulumdaki durumuna geri düşer.
Kurs Kapanışı
| Ders | Ölçülen fark ya da ölçüt | Sayı | Farkın saklandığı yer |
|---|---|---|---|
| DevOps Nedir | sahibine ulaşmayan olgu, ulaşma adımı | 22 olgunun 4’ü; 7,0 → 1,6 adım | gözlem alanının bölünmesi |
| Duvar Üzerinden Atma | sınırda düşen bağlam kalemi | 29 kalemin 21’i yazısız, 14’ü düşüyor | yazılmamış bağlam |
| Değer Akışı | beklemenin tek adımda yığılması | 2237 adımın 1485’i; katma değer %38,5 | beklemenin dağılımı |
| Teslimat Ölçütleri | parti 8’den 2’ye inince oynayan ölçüt | dağıtım 3,2 → 13,5; hata 12’de sabit | ölçütün paydası |
| Site Güvenilirliği Mühendisliği | hata bütçesi ve tükenmesi | 43,2 dakika; ağır olay %208; 8/12 dönem | hedef ile kesinti dağılımı arası |
| Geri Bildirim Döngüleri | erken döngüye düşmeyen hata | 120 hatanın 32’si, gecikmenin %95’i | döngü kapsamı |
| Ortamlar | ortam denkliği, boyut başına fark | 18 fark; 12 künyede, 6 koşumda | künyede yazmayan boyut |
| Yapı Çıktısı ve Değişmezlik | yeniden üretilebilirliği bozan kaynak | 4 kaynak, 3’ü tek makinede görünmez | çıktıya gömülü değer |
| Yapı Çıktısı Depoları | etiketin taşıdığı ayrı çıktı | 11 adla dağıtım, 7’sinde başka çıktı | dağıtım anındaki ad çözümü |
| Yapılandırma ve Sır Ayrımı | değişen anahtar, sızma yolu | 14 anahtarın 6’sı; 7 sızıntıdan 5’i | kaynağa gömülü varsayılan |
| On İki Etmen Uygulama | denetime çevrilen ilke, yakalanan kusur | 12 ilkenin 8’i; 8 kusurdan 6’sı | kuralın kapsamı ile ilkenin konusu arası |
| Altyapı Sağlama Modelleri | aynı tariften doğan ayrı sonuç | elle 3, betik 5, bildirimsel 0; sapma 6 → 0 | tarifin yazılmamış kısmı |
On iki satırın hepsi tek bir kuralın örneğidir: aynı yazılım iki ortamda başka davranıyorsa fark bir yerdedir, ve adı konmadıkça ölçülmez. Tablodaki hiçbir sayı yazılımın kendisinden gelmiyor; hepsi farkın saklandığı yerden geliyor. Bir kalemin yazılı olup olmadığı, bir adın dağıtım anında neye çözüldüğü, bir yönergenin hangi adımda sayı vermediği — bunların hiçbiri kodun içinde değildir ve hiçbiri kendiliğinden görünmez.
Son sütun okunduğunda bir yığılma görünür: farkın saklandığı yerlerin çoğu ortamın kendisiydi — kurulu paketler, kütüphane sürümleri, dosya yolları, saat dilimi. Künyeyi genişletmek, yapılandırmayı dışarı almak ve sağlamayı bildirimsel yapmak bu farkı ölçülebilir kıldı, ama farkı ortamdan çıkarmadı; her seferinde yapılan, farkı sayılabilir bir yere taşımak oldu.
Buradan bir soru kalır ve M22/K02 Konteynerler onu üstlenir: bu farkı yapı çıktısının içine alıp ortamdan tümüyle çıkarmak mümkün mü? Kurulu paketler, sürümler ve dosya yolları çıktının parçası olursa ortamın yapabileceği tek şey o çıktıyı çalıştırmak olur ve sağlanacak bir şey kalmaz. Mümkünse bedeli nedir — çıktı ne kadar büyür, yeniden üretilebilirlik ne olur, ortamdan çıkarılamayan ne kalır?
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.