Налаштування Shadow Deployment для ML-моделей
Shadow deployment (mirror deployment) — стратегія, коли нова версія моделі отримує самі запити, як і production, та її відповіді не віддаються користувачам. Мета - протестувати поведінку нової моделі на реальному трафіку без будь-якого ризику для користувачів.
Коли застосовувати shadow deployment
- Кардинальна зміна архітектури моделі (наприклад, перехід від gradient boosting до нейронної мережі)
- Нова версія ще не пройшла повне тестування, але потрібно подивитися на реальні дані
- Перевірка latency та resource utilization під реальним навантаженням
- Валідація пайплайну обробки даних перед новою версією
- Тестування великої LLM-моделі перед заміною меншої
Архітектура
[User Request]
|
├──→ [Production Model V1] ──→ [Response to User]
|
└──→ [Shadow Model V2] ──→ [Prediction logged, not returned]
|
[Comparison DB]
|
[Metrics Dashboard]
Реалізація з Envoy / Istio
Istio mirror:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ml-inference
spec:
hosts:
- ml-inference
http:
- route:
- destination:
host: ml-inference
subset: v1
weight: 100
mirror:
host: ml-inference
subset: v2-shadow
mirrorPercentage:
value: 100 # Зеркалировать 100% трафика
Nginx mirror:
location /predict {
proxy_pass http://model-v1;
mirror /shadow;
mirror_request_body on;
}
location = /shadow {
internal;
proxy_pass http://model-v2-shadow/predict;
}
Реалізація на рівні програми
Для більш гнучкого логування та порівняння – реалізація в коді:
import asyncio
import logging
async def predict_with_shadow(request_features):
# Production модель — синхронно
production_result = production_model.predict(request_features)
# Shadow модель — асинхронно, не блокирует ответ
asyncio.create_task(
run_shadow_prediction(request_features, production_result)
)
return production_result
async def run_shadow_prediction(features, production_result):
try:
shadow_result = shadow_model.predict(features)
# Логирование для сравнения
comparison_store.log({
'timestamp': datetime.utcnow(),
'production_score': float(production_result),
'shadow_score': float(shadow_result),
'agreement': abs(production_result - shadow_result) < 0.1,
'features_hash': hash_features(features)
})
except Exception as e:
logging.error(f"Shadow prediction failed: {e}")
# Ошибка в shadow не влияет на production
Метрики порівняння
Agreement rate — відсоток запитів, де передбачення моделей збігаються (із заданим допуском):
df['agreement'] = abs(df['production'] - df['shadow']) < threshold
agreement_rate = df['agreement'].mean()
# Цель: > 95% agreement для критичных систем
Prediction distribution comparison:
from scipy.stats import ks_2samp
ks_stat, p_value = ks_2samp(df['production'], df['shadow'])
# Если p_value < 0.05 — распределения значимо отличаются
Latency comparison: shadow модель може працювати повільніше без наслідків для користувачів, але це вказує на майбутні latency проблеми під час переходу.
Коли переходити з shadow на canary
Рекомендації щодо переходу:
- Shadow тест пройшов щонайменше 1 тиждень на реальному трафіку
- Agreement rate > 95% (або узгоджене business рішення про допустиме розходження)
- Latency shadow-моделі <SLA (навіть з урахуванням того, що поки що вона не критична)
- Resource utilization в нормі при піковому навантаженні
- Немає несподіваних помилок у логах shadow-сервісу
Shadow deployment — найбезпечніша стратегія тестування, особливо для систем, де ціна помилки висока: фінансові рішення, медична діагностика, системи безпеки.







