CD va qaytarish: orqaga yo'l qancha vaqt oladi
Yong'in chiqqanda eshik qidirilmaydi
Har binoda zaxira chiqish eshigi bor. U kamdan-kam ishlatiladi — ko'p odam uning qayerdaligini ham bilmaydi.
Lekin eshik yong'in paytida qurilmaydi. U oldindan quriladi, belgilanadi va sinaladi. Chunki yong'in paytida qurishga vaqt yo'q.
31-bobda darvoza qurdik — u yomon modelni chiqishdan oldin to'xtatadi. Yaxshi.
Endi noqulay savol: darvozadan o'tib ketgan muammo-chi?
Chunki o'tadi. Darvoza F1 ni tekshiradi, lekin tezlikni tekshirmaydi. Sxemani tekshiradi, lekin haqiqiy foydalanuvchi xulqini tekshirmaydi. Bir kuni ishlab chiqarishda nimadir buziladi va siz buni faqat o'sha yerda bilib olasiz.
O'shanda muhim savol bitta bo'ladi: orqaga qancha vaqtda qaytasiz?
Ikki xil jamoa
Bir xil muammo, ikki xil kun.
Birinchi jamoa. "Tuzataylik" deydi. Sabab qidiriladi, kod yoziladi, test qilinadi, CI kutiladi, chiqariladi. Eng yaxshi holatda bir soat. Odatda uch.
Bu vaqt davomida foydalanuvchilar buzilgan tizimdan foydalanadi.
Ikkinchi jamoa. "Qaytaraylik" deydi. Bitta buyruq. Ikki daqiqa. Tizim ishlayapti.
Keyin tinchgina o'tirib sababni qidiradi — endi shoshilmasdan, kimdir ustingizda turmagan holda.
Farq texnikada emas, tayyorgarlikda. Ikkinchi jamoa qaytish yo'lini oldindan qurgan.
Eng muhim ko'rsatkich — tuzatish emas, qaytish vaqti
Ishlab chiqarishda ikki raqam bor:
- MTTR (o'rtacha tiklanish vaqti) — tizim qancha vaqt buzuq turdi;
- MTBF (buzilishlar orasidagi vaqt) — qanchalik kam buziladi.
Ko'p jamoa ikkinchisini yaxshilashga urinadi: "boshqa hech qachon buzilmasin".
Bu imkonsiz. Har doim buziladi.
Yaxshi jamoalar birinchisiga qaraydi: buzilsa ham, tez tiklanamiz. Shuning uchun ular tez-tez, kichik qismlarda chiqaradi — chunki qaytish arzon.
Teg: latest — qaytishning dushmani
Qaytish uchun qayerga qaytishni bilish kerak. Demak har versiya nomlanishi shart.
python3 -c " import sys, pathlib; sys.path.insert(0, 'src') if not pathlib.Path('model.onnx').exists(): import pandas as pd from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import train_test_split from quvur.xususiyat import XUSUSIYATLAR, tayyorla from quvur.format import onnx_ga d = pd.read_csv('../datasets/ijara.csv') x, y = tayyorla(d), d['broker'] Xtr, _, ytr, _ = train_test_split(x, y, test_size=0.25, stratify=y, random_state=42) m = RandomForestClassifier(n_estimators=150, min_samples_leaf=3, random_state=42, n_jobs=1).fit(Xtr, ytr) onnx_ga(m, len(XUSUSIYATLAR), 'model.onnx') print('model tayyor') " docker images mlops-servis:v1 -q | grep -q . || docker build -q -f Dockerfile.servis -t mlops-servis:v1 . > /dev/null 2>&1 docker tag mlops-servis:v1 mlops-servis:v2 2>/dev/null docker images mlops-servis --format '{{.Repository}}:{{.Tag}} {{.ID}}'
model tayyor mlops-servis:v1 2b7d80f0ae48 mlops-servis:v2 2b7d80f0ae48
`:latest` bilan qaytib bo'lmaydi
Eng keng tarqalgan xato: rasmni mlops-servis:latest deb belgilash.
Muammo shundaki, latest — bu nom, versiya emas. U doim eng oxirgisini ko'rsatadi.
Ishlab chiqarishda nima ishlayotganini so'rasangiz, javob "latest" bo'ladi. Lekin bu hech narsa demaydi: kecha ham latest edi, bugun ham latest — ichi boshqa.
Va eng yomoni: qaytmoqchi bo'lsangiz, qayerga qaytasiz? Eski rasm nomi yo'q.
Qoida: har chiqarish o'zgarmas teg oladi — v1, v2, yoki git commit xeshi
(a3f9c2e). latest faqat qulaylik uchun, hech qachon ishlab chiqarishda emas.
Bu 23-bobdagi model_final_v2_YANGI.pkl muammosining aynan o'zi, faqat rasmlarda.
Chiqarish skripti
shu faylni yaratingchiqar.sh
#!/usr/bin/env bash
# Yangi versiyani chiqaradi. Soglik tekshiruvidan otmasa - AVTOMATIK qaytaradi.
set -u
TEG="${1:?teg kerak: ./chiqar.sh v2}"
PORT="${2:-18130}"
NOM="mlops-joriy"
KUTISH=25
# hozirgi versiyani eslab qolamiz - qaytish uchun
ESKI=$(docker inspect "$NOM" --format '{{index .Config.Labels "versiya"}}' 2>/dev/null || echo "")
ishga_tushir() {
local teg="$1"
docker rm -f "$NOM" > /dev/null 2>&1
docker run -d --name "$NOM" -p "${PORT}:8000" \
--label "versiya=$teg" "mlops-servis:$teg" > /dev/null 2>&1
}
sogmi() {
for _ in $(seq 1 "$KUTISH"); do
[ "$(curl -s -o /dev/null -w %{http_code} "http://127.0.0.1:${PORT}/ready" 2>/dev/null)" = "200" ] \
&& return 0
sleep 1
done
return 1
}
echo "chiqarilmoqda: $TEG (eski: ${ESKI:-yoq})"
ishga_tushir "$TEG"
if sogmi; then
echo "OK: $TEG soglom, chiqarildi"
exit 0
fi
echo "XATO: $TEG soglik tekshiruvidan otmadi"
if [ -n "$ESKI" ]; then
echo "QAYTARILMOQDA -> $ESKI"
ishga_tushir "$ESKI"
sogmi && echo "qaytarildi: $ESKI ishlayapti" || echo "OGOHLANTIRISH: qaytarish ham muvaffaqiyatsiz"
else
echo "qaytadigan versiya yoq (birinchi chiqarish)"
fi
exit 1
Skriptda uchta qaror bor:
Eski versiya eslab qolinadi — --label versiya=... orqali. Qaytish uchun manzil kerak,
va u avtomatik olinadi, qo'lda yozilmaydi.
Sog'liq tekshiruvi kutiladi — 27-bobdagi /ready. Konteyner ishga tushgani yetarli
emas (28-bob), u tayyor bo'lishi kerak.
Qaytish avtomatik — odam qaror qilmaydi. Tungi soat 3 da odam sekin qaror qiladi.
Birinchi chiqarish
chmod +x chiqar.sh ./chiqar.sh v1 18130 echo "chiqish kodi: $?" echo "" echo -n "javob: "; curl -s http://127.0.0.1:18130/ready echo "" docker inspect mlops-joriy --format 'ishlayotgan versiya: {{index .Config.Labels "versiya"}}'
chiqarilmoqda: v1 (eski: yoq)
OK: v1 soglom, chiqarildi
chiqish kodi: 0
javob: {"holat":"tayyor","sorovlar":0,"chegara":0.5}
ishlayotgan versiya: v1
Buzilgan versiya chiqaramiz
Endi v2 ni ataylab buzamiz — model faylini olib tashlaymiz. 27-bobdan bilamizki, bunda
servis ishga tushadi, lekin /ready 503 qaytaradi.
shu faylni yaratingDockerfile.buzuq
FROM mlops-servis:v1 USER root RUN rm -f /app/model.onnx USER servis
docker build -q -f Dockerfile.buzuq -t mlops-servis:v2 . > /dev/null 2>&1 echo "v2 qurildi (model faylisiz)" echo "" t0=$SECONDS ./chiqar.sh v2 18130 KOD=$? echo "" echo "chiqish kodi: $KOD" echo "jami vaqt: $((SECONDS - t0)) s"
v2 qurildi (model faylisiz) chiqarilmoqda: v2 (eski: v1) XATO: v2 soglik tekshiruvidan otmadi QAYTARILMOQDA -> v1 qaytarildi: v1 ishlayapti chiqish kodi: 1 jami vaqt: 31 s
Qaytish ishladimi
echo -n "servis javob beryaptimi: " curl -s http://127.0.0.1:18130/ready echo "" docker inspect mlops-joriy --format 'hozirgi versiya: {{index .Config.Labels "versiya"}}' echo "" echo -n "bashorat ishlayaptimi: " curl -s -X POST http://127.0.0.1:18130/bashorat -H "Content-Type: application/json" -d '{ "xonalar": 2, "maydon": 55, "qavat": 3, "jami_qavat": 9, "narx_mln": 4.2, "tavsif_uzunligi": 60, "rasmlar_soni": 2, "telefon_takrorlanishi": 18, "kunlik_elonlar": 9, "egasi_tasdiqlangan": 0}'
servis javob beryaptimi: {"holat":"tayyor","sorovlar":0,"chegara":0.5}
hozirgi versiya: v1
bashorat ishlayaptimi: {"broker_ehtimoli":0.9179,"broker":true,"chegara":0.5,"ms":3.88}
Natijani o'qing: chiqarish muvaffaqiyatsiz tugadi (chiqish kodi 1), lekin servis ishlayapti — chunki eski versiyaga qaytdi.
Foydalanuvchi buzilishni umuman ko'rmadi. U faqat bir necha soniya kutdi.
Mana CD ning asosiy va'dasi: chiqarish xavfsiz bo'lishi uchun u qaytariladigan bo'lishi kerak.
Sog'liq tekshiruvi yetarlicha chuqur bo'lsin
Bizning /ready model yuklanganini tekshiradi. Bu yaxshi, lekin hamma narsani ushlamaydi.
Tasavvur qiling: model yuklandi, /ready 200 qaytardi, lekin model noto'g'ri model —
masalan boshqa loyihaniki. Sog'liq tekshiruvi buni sezmaydi.
Shuning uchun chuqurroq tekshiruv foydali: /ready ichida bitta ma'lum e'lon bo'yicha
bashorat qiling va natija kutilgan oraliqda ekanini tekshiring. Bu 25-bobdagi minimal
funksionallik testining ishga tushish paytidagi varianti.
Sekinroq, lekin u "ishlayapti, faqat noto'g'ri" holatini ushlaydi.
CD quvuri: to'liq rasm
diagramma( { "Birlashtirildi\n(main)": (0, 1.8, 2.2, 1.0, "manba"), "CI darvozasi\n(31-bob)": (3.0, 1.8, 2.2, 1.0, "qayta"), "Rasm qurish\n+ teg": (6.0, 1.8, 2.1, 1.0, "qayta"), "Chiqarish\n+ sog'liq": (8.9, 1.8, 2.1, 1.0, "kuzatuv"), "Ishlayapti": (11.8, 3.1, 2.0, 0.9, "xizmat"), "QAYTARISH": (11.8, 0.5, 2.0, 0.9, "manba"), }, [ ("Birlashtirildi\n(main)", "CI darvozasi\n(31-bob)"), ("CI darvozasi\n(31-bob)", "Rasm qurish\n+ teg"), ("Rasm qurish\n+ teg", "Chiqarish\n+ sog'liq"), ("Chiqarish\n+ sog'liq", "Ishlayapti", "sog'lom"), ("Chiqarish\n+ sog'liq", "QAYTARISH", "sog'liq yo'q"), ], nom="cd_quvuri.png", kenglik=15, izoh="Qaytarish - alohida jarayon emas, chiqarishning bir qismi.", )

Qaytarish - alohida jarayon emas, chiqarishning bir qismi.
Diqqat qiling: qaytarish alohida reja emas. U chiqarish jarayonining ichida, avtomatik.
Agar qaytarish "kerak bo'lsa qo'lda qilamiz" degan narsa bo'lsa, u kerak bo'lgan paytda ishlamaydi — chunki hech kim uni sinab ko'rmagan.
Modelni qaytarish: boshqa masala
Yuqorida kod qaytarildi. Lekin model buzilgan bo'lsa-chi?
28-bobdagi tanlovni eslang. Agar model rasm ichida bo'lsa, eski rasmga qaytish modelni ham qaytaradi — bitta harakat.
Agar model tashqarida bo'lsa (registrda), kod qaytarish modelni qaytarmaydi. U yerda
23-bobdagi alias ishlatiladi: production ni eski versiyaga ko'chirasiz.
import pandas as pd show(pd.DataFrame([ {"Buzilgan narsa": "Kod", "Qaytarish usuli": "Eski rasm tegi", "Vaqti": "Soniyalar"}, {"Buzilgan narsa": "Model (rasm ichida)", "Qaytarish usuli": "Eski rasm tegi", "Vaqti": "Soniyalar"}, {"Buzilgan narsa": "Model (registrda)", "Qaytarish usuli": "Alias ko'chirish (23-bob)", "Vaqti": "Soniyalar"}, {"Buzilgan narsa": "Ma'lumot sxemasi", "Qaytarish usuli": "Oson emas — migratsiya kerak", "Vaqti": "Soatlar"}, ]))
| Buzilgan narsa | Qaytarish usuli | Vaqti |
|---|---|---|
| Kod | Eski rasm tegi | Soniyalar |
| Model (rasm ichida) | Eski rasm tegi | Soniyalar |
| Model (registrda) | Alias ko'chirish (23-bob) | Soniyalar |
| Ma'lumot sxemasi | Oson emas — migratsiya kerak | Soatlar |
Oxirgi qatorga e'tibor bering: hamma narsa ham qaytarilmaydi. Ma'lumotlar bazasiga qo'shilgan ustun yoki o'zgartirilgan sxema — ularni orqaga qaytarish ancha qiyin.
Shuning uchun qoida: ma'lumot o'zgarishi va kod o'zgarishi bir chiqarishda bo'lmasin. Avval sxemani qo'shing (eski kod ham ishlaydigan qilib), keyin kodni chiqaring.
Tozalash
docker rm -f mlops-joriy > /dev/null 2>&1 docker rmi mlops-servis:v2 > /dev/null 2>&1 echo "tozalandi" docker ps --format '{{.Names}}' | grep -v k3d
tozalandi novavivo-postgres novavivo-redis stratix-med-frontend-1
Xulosa
| Tushuncha | Asosiy fikr |
|---|---|
| Darvoza yetarli emas | Ba'zi muammo faqat ishlab chiqarishda ko'rinadi |
| Asosiy savol | "Buzilmasinmi" emas — "qancha tez qaytamiz" |
| MTTR | Tiklanish vaqti — MTBF dan muhimroq |
:latest |
Versiya emas, nom — qaytish imkonini yo'q qiladi |
| O'zgarmas teg | v1, v2 yoki commit xeshi |
| Avtomatik qaytarish | Odam emas, skript qaror qilsin |
| Sog'liq tekshiruvi | /ready, va u yetarlicha chuqur bo'lsin |
| Qaytarish sinaladi | Sinovdan o'tmagan qaytarish — qaytarish emas |
| Ma'lumot sxemasi | Qaytarib bo'lmaydi — kod bilan alohida chiqaring |
Talaba ishi
chiqar.shni ikki marta ketma-ket buzuq teg bilan ishlating. Ikkinchisida nima bo'ldi?/readyga bashorat tekshiruvini qo'shing (ma'lum e'lon → kutilgan oraliq). Endi "noto'g'ri model" holatini ushlaydimi?KUTISHni 3 soniya qiling. Sog'lom versiya ham qaytarilib ketdimi? Bu qanday xato deb ataladi?- Skriptga chiqarish jurnalini qo'shing: qachon, qaysi teg, natija. Uni faylga yozing.
- Model registrda bo'lgan holatni yozing: alias ko'chirish bilan qaytarish. Kod qaytarish bilan farqi nimada?
Bu bobni bepul o'qidingiz.
Kitob o'rgatadi, lekin sizning kodingiz nega ishlamaganini ayta olmaydi. Kursda uy vazifangiz tekshiriladi.