İçeriğe geç
academia.sh

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.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat