İçeriğe geç
academia.sh

Ders 01 / 12

DevOps Nedir

Sorumluluk paylaşımının teknik ve örgütsel yanı: aynı 22 olgunun ayrık gözlem alanlarında 9'unun yalnız işletenin, 1'inin yalnız yazanın alanında ve 1'inin hiçbir alanda görünmesi, 4 olgunun sahibine hiç ulaşmaması ve sahibe ulaşmanın ortalama 7,0 adım sürmesi, üç yüzeyin paylaşılmasıyla ulaşmayanın 1'e ve ulaşmanın 5,0 adıma inmesi, alanların tümüyle birleştirilmesiyle ulaşmanın 1,6 adıma inerken yazan ekibin yükünün 95'ten 107 adıma, öncü sürenin 25,8'den 34,8 adıma çıkması ve dağıtım sıklığının 5'ten 4 yayına düşmesi.

İçindekiler

Önceki ders devri bir sözleşme olarak ölçtü: yirmi sekiz sorumluluk kaleminin yirmisi devredildi, sekizi bilgi, araç ya da yordam yokluğunda geliştirmede kaldı. Sözleşme kimin neyi yapacağını yazıyordu. Yazmadığı şey, kimin neyi göreceğiydi. İki taraf aynı servisten sorumlu olabilir ve yine de aynı olguyu farklı adımda, farklı yüzeyde, kimi zaman hiç görmez.

Sorumluluk paylaşımı, yazan ve işleten rollerin bir servisin sonucundan birlikte sorumlu tutulmasıdır. Devir sözleşmesi kalemleri böler, sorumluluk paylaşımı sonucu böler; ikincisinin ön koşulu, iki tarafın aynı olguyu görebilmesidir. Bu ders o ön koşulu ölçer: aynı olgu kümesi iki rolün gözlem alanına düşürülür, kaç olgunun yalnız bir tarafta kaldığı sayılır ve alanları birleştirmenin faturası çıkarılır.

Gözlem Alanı Bir Veri Yapısıdır

Örnek, bu müfredatın kurgu bölgesel ölçüm ağıdır: bir belediyenin su sayaçlarından okuma toplayan, okumaları doğrulayan, faturaya çeviren ve saha ekiplerine iş emri açan bir yazılım. Ağ da ekipler de kurgudur. KA1: üç ortam (geliştirme, sınama, üretim), iki ekip (yazan ve işleten) ve bir gecelik toplu iş vardır. KA2: sekiz gözlem yüzeyi vardır; üçü yazan ekibin, dördü işleten ekibin alanındadır, fatura-dokumu hiç kimsenin alanında değildir. KA3: bir pencerede yirmi iki olgu doğar; her olgunun bir sınıfı (hata, gecikme, sapma), bir doğuş adımı ve göründüğü yüzeylerle o yüzeydeki gecikmesi vardır. KA4: her olgunun onu kapatabilen bir sahibi vardır — yazan, işleten ya da ortak; ortak olgu iki alanda da görünmedikçe kapatılamaz, kapatma sırasıyla 4, 2 ve 5 adım tutar. KA5: alanında görünen olgu role 2 adım inceleme yazar; sahibine 30 adımda ulaşmamış olgu üstten duyulur ve bağlam ikinci elden kurulduğu için 2 adım fazladan tutar. KA6: yazan ekip boş adımlarında yayına çalışır, bir yayın 8 adım iş ister; her olgu kendinden önceki son yayına bağlanır ve bağlı olgusu sahibine hiç ulaşmayan yayın başarısız sayılır. Pencere 140 adımdır.

Olgular, yüzeyler ve iki rolün nöbeti süreç içi bir modeldir; gerçek bir uyarı akışı ya da olay kaydı yoktur.

// gozlem/alan.mjs — kurgu bolgesel olcum aginin olgu ve gozlem alani modeli (model): gercek bir
// uyari akisi ya da olay kaydi yok, adimlar veri yapisidir. Rastgelelik yok.

export const PENCERE = 140;                 // olculen adim penceresi
export const INCELEME = 2;                  // bir olgunun bir role inceleme maliyeti (adim)
export const YAYIN_ISI = 8;                 // bir yayin icin gereken calisma adimi
export const KAPATMA = { yazan: 4, isleten: 2, ortak: 5 };
export const TAVAN = 30;                    // sahibine ulasmayan olgu bu gecikmeyle ustten duyulur
export const IKINCI_EL = 2;                 // ustten duyulan olgunun ek baglam maliyeti

export const YUZEY = {                      // yuzey -> ayrik duzende kimin alaninda
  "uygulama-kaydi": "yazan", "hata-izleme": "yazan", "surum-gunlugu": "yazan",
  "is-cizelgesi": "isleten", "makine-olcumu": "isleten", "uyari-akisi": "isleten",
  "destek-kaydi": "isleten", "fatura-dokumu": "-",
};
export const ROL = ["yazan", "isleten"];

const cizelge = (s, f) => s.trim().split("\n").map((r) => f(r.trim().split(/\s+/)));

// olgu: dogus adimi, sinif, kapatabilen rol, ad, gorundugu yuzeyler (yuzey:gecikme)
export const OLGU = cizelge(`
    2  hata     yazan    okuma-ayristirici       uygulama-kaydi:0 destek-kaydi:12
    6  gecikme  isleten  toplu-is-tasmasi        is-cizelgesi:1 makine-olcumu:2
   11  sapma    yazan    sinamada-olmayan-ayar   surum-gunlugu:0 uyari-akisi:9
   17  hata     isleten  kuyruk-tikanmasi        makine-olcumu:0 uyari-akisi:1
   21  gecikme  yazan    sorgu-yavaslamasi       uygulama-kaydi:3 makine-olcumu:1
   26  hata     yazan    yinelenen-fatura        destek-kaydi:16
   31  sapma    isleten  disk-doluluk            makine-olcumu:0
   36  hata     yazan    bos-adresli-is-emri     hata-izleme:2 destek-kaydi:9
   42  gecikme  isleten  ag-gecikmesi            makine-olcumu:1 uyari-akisi:2
   46  sapma    yazan    kutuphane-sapmasi       surum-gunlugu:1
   51  hata     ortak    gecelik-is-yarim        is-cizelgesi:1 uygulama-kaydi:4
   57  hata     yazan    negatif-tuketim         fatura-dokumu:0 destek-kaydi:14
   61  gecikme  isleten  yedekleme-cakismasi     is-cizelgesi:2 makine-olcumu:3
   66  sapma    ortak    zaman-dilimi-farki      uygulama-kaydi:6 is-cizelgesi:3
   71  hata     yazan    yuvarlama-farki         fatura-dokumu:0
   77  gecikme  yazan    onbellek-isinmasi       hata-izleme:2 makine-olcumu:1
   81  hata     isleten  baglanti-havuzu         uyari-akisi:1 uygulama-kaydi:0
   86  sapma    yazan    eksik-ortam-degiskeni   uygulama-kaydi:0 uyari-akisi:5
   91  hata     yazan    sayac-kimligi-catismasi hata-izleme:2 destek-kaydi:10
   96  gecikme  isleten  is-yeniden-kosumu       is-cizelgesi:1
  102  sapma    yazan    bicim-kirilmasi         fatura-dokumu:0 destek-kaydi:15
  107  hata     ortak    yinelenen-is-emri       uygulama-kaydi:3 destek-kaydi:8`,
([dogus, sinif, sahip, ad, ...y]) => ({ dogus: +dogus, sinif, sahip, ad,
  yuzey: y.map((p) => ({ ad: p.split(":")[0], gec: +p.split(":")[1] })) }));

// Duzen: ayrik duzenin uzerine hangi rol hangi yuzeyi ek olarak goruyor (karsit kosum).
export const DUZEN = {
  ayrik: { yazan: [], isleten: [] },
  secili: { yazan: ["destek-kaydi"], isleten: ["surum-gunlugu", "fatura-dokumu"] },
  birlesik: { yazan: Object.keys(YUZEY), isleten: Object.keys(YUZEY) },
};

export const alan = (d) => Object.fromEntries(ROL.map((r) =>
  [r, new Set([...Object.keys(YUZEY).filter((y) => YUZEY[y] === r), ...DUZEN[d][r]])]));

export function kos(d) {
  const A = alan(d);
  const G = OLGU.map((o) => {                 // her olgu her rolde kacinci adimda goruluyor
    const g = Object.fromEntries(ROL.map((r) => {
      const v = o.yuzey.filter((y) => A[r].has(y.ad)).map((y) => y.gec);
      return [r, v.length ? Math.min(...v) : null];
    }));
    const kapi = o.sahip === "ortak"          // ortak olgu iki alanda da gorunmus olmali
      ? (g.yazan === null || g.isleten === null ? null : Math.max(g.yazan, g.isleten))
      : g[o.sahip];
    return { o, g, kapi, sahipRol: o.sahip === "ortak" ? "yazan" : o.sahip };
  });

  const kuyruk = Object.fromEntries(ROL.map((r) => [r, []]));
  const kalan = Object.fromEntries(ROL.map((r) => [r, 0]));
  const yuk = Object.fromEntries(ROL.map((r) => [r, 0]));
  const kapanis = new Map(), yayin = [];
  let birikim = 0, basla = 0;

  for (let t = 0; t <= PENCERE; t++) {
    for (const x of G) {
      for (const r of ROL)                    // alaninda gorunen olgu inceleme isi acar
        if (x.g[r] !== null && t === x.o.dogus + x.g[r]) kuyruk[r].push([INCELEME, null]);
      if (x.kapi !== null && t === x.o.dogus + x.kapi)
        kuyruk[x.sahipRol].push([KAPATMA[x.o.sahip], x]);
      else if (x.kapi === null && t === x.o.dogus + TAVAN)      // ustten duyulma
        kuyruk[x.sahipRol].push([KAPATMA[x.o.sahip] + IKINCI_EL, x]);
    }
    for (const r of ROL) {
      if (kalan[r] === 0 && kuyruk[r].length) [kalan[r]] = kuyruk[r][0];
      if (kalan[r] > 0) {                     // rol bu adimda olguyla ugrasiyor
        kalan[r]--; yuk[r]++;
        if (kalan[r] === 0) { const [, x] = kuyruk[r].shift(); if (x) kapanis.set(x.o.ad, t + 1); }
        continue;
      }
      if (r !== "yazan") continue;            // bos adim: yazan ekip yayina calisir
      if (birikim === 0) basla = t;
      if (++birikim === YAYIN_ISI) { yayin.push({ t: t + 1, basla, olgu: [] }); birikim = 0; }
    }
  }
  for (const x of G) {                        // olgu kendinden onceki son yayina baglanir
    const y = [...yayin].reverse().find((v) => v.t <= x.o.dogus);
    if (y) y.olgu.push(x);
  }
  return { G, yuk, kapanis, yayin };
}

export const ort = (a) => (a.length ? (a.reduce((s, v) => s + v, 0) / a.length).toFixed(1) : "-");

export function olc(d) {
  const R = kos(d), say = (f) => R.G.filter(f).length;
  const ulasma = R.G.map((x) => (x.kapi === null ? TAVAN : x.kapi));   // ulasmayana tavan yazilir
  const sure = R.G.map((x) => (R.kapanis.get(x.o.ad) ?? PENCERE) - x.o.dogus);
  const bozuk = R.yayin.filter((y) => y.olgu.some((x) => x.kapi === null)).length;
  return { R,
    yalnizYazan: say((x) => x.g.yazan !== null && x.g.isleten === null),
    yalnizIsleten: say((x) => x.g.isleten !== null && x.g.yazan === null),
    ikisi: say((x) => x.g.yazan !== null && x.g.isleten !== null),
    hicbiri: say((x) => x.g.yazan === null && x.g.isleten === null),
    ulasmayan: say((x) => x.kapi === null), ulasmaAdimi: ort(ulasma),
    gurultuYazan: say((x) => x.g.yazan !== null && x.o.sahip === "isleten"),
    gurultuIsleten: say((x) => x.g.isleten !== null && x.o.sahip === "yazan"),
    yukYazan: R.yuk.yazan, yukIsleten: R.yuk.isleten, kurtarma: ort(sure),
    yayinSayisi: R.yayin.length, onculSure: ort(R.yayin.map((y) => y.t - y.basla)),
    geriDonus: R.yayin.length ? (100 * bozuk / R.yayin.length).toFixed(0) + "%" : "-" };
}

Dört teslimat ölçütü aynı koşumdan okunur: dağıtım sıklığı penceredeki yayın sayısı, öncü süre bir yayının işine başlanmasından yayına girmesine kadar geçen adım, geri dönüş oranı başarısız yayınların payı, kurtarma süresi olgunun doğuşundan kapanışına kadar geçen adımdır.

// gozlem/olc.mjs — olgu iki rolun gozlem alanina nasil dusuyor, birlestirmenin bedeli ne.
import { OLGU, YUZEY, ROL, olc, alan, TAVAN } from "./alan.mjs";

const yaz = (g, ...s) => console.log(s.map((v, i) =>
  (g[i] < 0 ? String(v).padEnd(-g[i]) : String(v).padStart(g[i]))).join(""));
const D = ["ayrik", "secili", "birlesik"];
const R = Object.fromEntries(D.map((d) => [d, olc(d)]));

console.log(`${OLGU.length} olgu, ${Object.keys(YUZEY).length} gozlem yuzeyi; ` +
  ["hata", "gecikme", "sapma"].map((s) =>
    `${s} ${OLGU.filter((o) => o.sinif === s).length}`).join(", "));
for (const r of ROL) console.log(`  ${r}: ${[...alan("ayrik")[r]].join(", ")}`);
console.log(`  kimsenin alaninda degil: ` +
  Object.keys(YUZEY).filter((y) => YUZEY[y] === "-").join(", "));

const A = [-27, 9, 9, 11];
console.log("\n1. ayni 22 olgu, uc gozlem duzeni");
yaz(A, "olcu", "ayrik", "secili", "birlesik");
for (const [ad, k] of [["yalniz yazanin alaninda", "yalnizYazan"],
  ["yalniz isletenin alaninda", "yalnizIsleten"], ["iki alanda birden", "ikisi"],
  ["hicbir alanda", "hicbiri"], ["sahibine hic ulasmayan", "ulasmayan"],
  [`sahibe ulasma (ort. adim)`, "ulasmaAdimi"], ["yazana gurultu (olgu)", "gurultuYazan"],
  ["isletene gurultu (olgu)", "gurultuIsleten"], ["yazanin yuku (adim)", "yukYazan"],
  ["isletenin yuku (adim)", "yukIsleten"]]) yaz(A, ad, ...D.map((d) => R[d][k]));

console.log("\n2. dort teslimat olcutu, ayni pencerede");
yaz(A, "olcut", "ayrik", "secili", "birlesik");
for (const [ad, k] of [["dagitim sikligi (yayin)", "yayinSayisi"],
  ["oncu sure (ort. adim)", "onculSure"], ["geri donus orani", "geriDonus"],
  ["kurtarma suresi (ort. adim)", "kurtarma"]]) yaz(A, ad, ...D.map((d) => R[d][k]));

const B = [-9, 7, 16, 18, 18];
console.log("\n3. ayrik duzende olgu sinifi kimin alanina dusuyor");
yaz(B, "sinif", "olgu", "yalniz yazanda", "yalniz isletende", "sahibe ulasmayan");
for (const s of ["hata", "gecikme", "sapma"]) {
  const g = R.ayrik.R.G.filter((x) => x.o.sinif === s);
  yaz(B, s, g.length, g.filter((x) => x.g.yazan !== null && x.g.isleten === null).length,
    g.filter((x) => x.g.isleten !== null && x.g.yazan === null).length,
    g.filter((x) => x.kapi === null).length);
}

console.log("\n4. ayrik duzende sahibine ulasmayan olgular (tavan " + TAVAN + " adim)");
const C = [-24, -9, 10, 16];
yaz(C, "olgu", "sahip", "kapanis", "gorundugu alan");
for (const x of R.ayrik.R.G.filter((x) => x.kapi === null))
  yaz(C, x.o.ad, x.o.sahip, R.ayrik.R.kapanis.get(x.o.ad) - x.o.dogus,
    ROL.filter((r) => x.g[r] !== null).join("+") || "hicbiri");
22 olgu, 8 gozlem yuzeyi; hata 10, gecikme 6, sapma 6
  yazan: uygulama-kaydi, hata-izleme, surum-gunlugu
  isleten: is-cizelgesi, makine-olcumu, uyari-akisi, destek-kaydi
  kimsenin alaninda degil: fatura-dokumu

1. ayni 22 olgu, uc gozlem duzeni
olcu                           ayrik   secili   birlesik
yalniz yazanin alaninda            1        0          0
yalniz isletenin alaninda          9        7          0
iki alanda birden                 11       15         22
hicbir alanda                      1        0          0
sahibine hic ulasmayan             4        1          0
sahibe ulasma (ort. adim)        7.0      5.0        1.6
yazana gurultu (olgu)              1        1          7
isletene gurultu (olgu)           10       12         12
yazanin yuku (adim)               95       95        107
isletenin yuku (adim)             54       58         58

2. dort teslimat olcutu, ayni pencerede
olcut                          ayrik   secili   birlesik
dagitim sikligi (yayin)            5        5          4
oncu sure (ort. adim)           25.8     27.0       34.8
geri donus orani                 40%      20%         0%
kurtarma suresi (ort. adim)     13.5     11.9       10.2

3. ayrik duzende olgu sinifi kimin alanina dusuyor
sinif       olgu  yalniz yazanda  yalniz isletende  sahibe ulasmayan
hata          10               0                 3                 3
gecikme        6               0                 4                 0
sapma          6               1                 2                 1

4. ayrik duzende sahibine ulasmayan olgular (tavan 30 adim)
olgu                    sahip       kapanis  gorundugu alan
yinelenen-fatura        yazan            42         isleten
negatif-tuketim         yazan            42         isleten
yuvarlama-farki         yazan            40         hicbiri
bicim-kirilmasi         yazan            36         isleten

Sayılar ölçüm sınıfındadır; girdileri yukarıdaki varsayımlardır.

Aynı Olgu, İki Ayrı Alan

Birinci tablonun ayrik sütunu bugünkü bölüşmedir. Yirmi iki olgunun on biri iki alanda birden görünür, dokuzu yalnız işletenin, biri yalnız yazanın alanındadır, biri de hiçbir alanda görünmez — fatura-dokumu yüzeyine düşen yuvarlama-farki kimsenin nöbet listesinde yoktur. Üçüncü tablo bunu sınıfa göre böler: altı gecikmenin dördü yalnız işletenin alanındadır, çünkü gecikme makine ölçümüne ve iş çizelgesine düşer; altı sapmanın biri yalnız yazanın alanındadır, çünkü sürüm günlüğünü yalnız yazan ekip okur.

Asıl sayı alt satırdadır: dört olgu sahibine hiç ulaşmaz. Dördüncü tablo bunları adıyla verir ve dördünün de sahibi yazan ekiptir. Üçü işletenin alanında görünür — destek kaydına düşerler, işleten ekip onları görür ama kapatamaz; biri hiçbir yerde görünmez. Üstten duyulmaları 30 adım sürer, kapanışları 36 ile 42 adım arasındadır. Aynı pencerede sahibine ulaşan olguların ortalama ulaşma adımı ile birlikte hesaplandığında sinyalin sahibine ortalama ulaşma süresi 7,0 adımdır.

İşletenin alanındaki on olgu, işletenin kapatamayacağı olgudur; yani ayrık düzende işleten ekip zaten kapatamadığı bir olgu yığınına bakmaktadır. Bölünmüş gözlem alanı sinyali yok etmez, yanlış tarafa koyar.

Alanı Birleştirmenin Faturası

birlesik sütunu iki role sekiz yüzeyin tamamını verir. Görünürlük tamamlanır: yirmi iki olgunun yirmi ikisi iki alanda birden, sahibine ulaşmayan sıfır, ortalama ulaşma 7,0 adımdan 1,6 adıma iner. Bedel de aynı sütundadır: yazan ekibe düşen gürültü — kapatamayacağı olgu — 1’den 7’ye, inceleme yükü 95 adımdan 107 adıma çıkar.

Bu on iki adım ikinci tabloda teslimat ölçütü olarak görünür. Dağıtım sıklığı 5 yayından 4’e iner, öncü süre 25,8 adımdan 34,8 adıma çıkar. Karşılığında geri dönüş oranı %40’tan %0’a, kurtarma süresi 13,5 adımdan 10,2 adıma iner. Dört ölçütün ikisi iyileşir, ikisi bozulur; bir tek ölçüte bakan cümle bu kararı taşıyamaz.

secili sütunu üçüncü seçenektir: sekiz yüzeyden yalnız üçü paylaşılır — yazan ekip destek kaydını, işleten ekip sürüm günlüğü ile fatura dökümünü görür. Sahibine ulaşmayan olgu 4’ten 1’e, ortalama ulaşma 7,0’dan 5,0 adıma, geri dönüş oranı %40’tan %20’ye, kurtarma süresi 13,5’ten 11,9 adıma iner. Dağıtım sıklığı 5 yayında kalır ve öncü süre yalnız 1,2 adım artar. Yazan ekibin yükü hiç değişmez: 95 adımdan 95 adıma. Üç yüzeyin getirdiği inceleme işi, artık üstten duyulmayan üç olgunun ikinci elden bağlam kurma maliyetini tam olarak karşılar.

Farkın Saklandığı Yer

Bu derste fark gözlem alanının bölünmesinde saklıdır ve sayısı şudur: sekiz yüzeyin dördü tek bir rolde, biri hiçbir roldedir; yirmi iki olgunun onu tek alanda, biri hiçbir alanda görünür. Farkın bildirilmiş kısmı yüzey bölüşmesidir — hangi ekibin neye baktığı bellidir. Bildirilmemiş kısmı, o bölüşmenin hangi olguyu hangi tarafta bıraktığıdır; bu ancak koşumda görünür.

Sinyalin kime kaç adımda ulaştığı da buradan okunur: ayrık düzende sahibine ortalama 7,0 adımda, üç yüzey paylaşıldığında 5,0 adımda, alanlar birleştirildiğinde 1,6 adımda ulaşır. Sorumluluk paylaşımının teknik yanı budur — yüzeylerin kime açıldığı; örgütsel yanı ise açılan yüzeyin getirdiği inceleme yükünün kimin akışından düşüldüğüdür.

Özet

  • Yirmi iki olgu ayrık gözlem alanlarında bölünür: 11’i iki alanda, 9’u yalnız işletenin, 1’i yalnız yazanın alanında, 1’i hiçbir alanda görünür; 4 olgu sahibine hiç ulaşmaz ve dördünün de sahibi yazan ekiptir.
  • Sinyalin sahibine ulaşması ayrık düzende ortalama 7,0 adım, üç yüzey paylaşıldığında 5,0 adım, alanlar birleştirildiğinde 1,6 adım sürer.
  • Birleştirmenin bedeli yazan ekibin akışındadır: gürültü 1’den 7 olguya, yük 95’ten 107 adıma çıkar; dağıtım sıklığı 5’ten 4 yayına iner ve öncü süre 25,8’den 34,8 adıma uzar.
  • Karşılığında geri dönüş oranı %40’tan %0’a, kurtarma süresi 13,5’ten 10,2 adıma iner: dört ölçütün ikisi iyileşir, ikisi bozulur.
  • Üç yüzeyin seçilerek paylaşılması iyileşmenin çoğunu getirir (ulaşmayan 1, ulaşma 5,0 adım, geri dönüş %20) ve yazan ekibin yükünü 95 adımda sabit bırakır.

Sonraki Adım

Gözlem alanı bölünmüşse sinyal geç ulaşır ya da hiç ulaşmaz; bu ölçüldü. Ama bölünme yalnız gözlemde değildir: işin kendisi de bölünmüştür ve bir değişiklik ekipten ekibe atılır. Sonraki ders aynı değişiklik kümesini iki düzende koşturur — ayrık ekipler ve paylaşılan sorumluluk — ve sınır başına beklemeyi, aktarılamayan bağlam yüzünden geri dönen değişikliği ve üretimde ortaya çıkan hata sayısını sayar.

İ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