שחררתם גרסה חדשה, ובתוך חצי שעה — מפולת של שגיאות וירידה בהמרות? פריסה קנרית (Canary Deployment) מונעת תרחישים כאלה: הגרסה החדשה מקבלת בהדרגה תנועה אמיתית, ואם המדדים מתדרדרים, היא מתבצעת חזרה אוטומטית. אנו מיישמים תכניות אלה במפתח מלא — מתצורת Nginx פשוטה ועד פריסה אוטומטית עם Prometheus. במשך שנים של ניסיון, ביצענו יותר מ-50 שחרורים מוצלחים עם פריסה קנרית. הניסיון שלנו מראה: ללא פריסה קנרית, הסיכון לכשל במהלך שחרור גדל פי חמישה.
פריסה קנרית — העברת תנועה הדרגתית לגרסה חדשה: תחילה 1–5% מהמשתמשים, לאחר מכן 10%, 25%, 50%, ולבסוף 100%. היא מאפשרת לזהות בעיות על תנועה אמיתית לפני המעבר המלא. חשוב לציין, אנו מבטיחים שכאשר סף השגיאות נחצה (בדרך כלל >1%), החזרה לגרסה הקודמת מתרחשת תוך שניות. גישה זו מספקת שלושה יתרונות: הפחתת MTTR משעות לדקות, יכולת לבצע בדיקות A/B ישירות בסביבת הייצור, והיעדר מוחלט של זמן השבתה. השוו: עם פריסה כחול-ירוק (blue-green), אתם מחזיקים שתי סביבות מלאות, בעוד שפריסה קנרית דורשת 30% פחות משאבים. לפי ההגדרה, פריסה קנרית היא אסטרטגיית שחרור שבה גרסה חדשה של יישום מקבלת בהדרגה תנועה אמיתית (ויקיפדיה).
אילו בעיות פותרת פריסה קנרית?
- זיהוי מוקדם של רגרסיות על חלק קטן מהתנועה: שגיאות שבדיקות יחידה לא תפסו יופיעו על 1% מהמשתמשים, לא על כולם.
- חזרה מיידית לגרסה קודמת ללא פריסה מלאה מחדש:只需 לשנות את המשקל ל-0% — והמשתמשים חוזרים לגרסה הישנה.
- בדיקת תכונות חדשות על משתמשים אמיתיים ללא עלויות סביבת staging: ניתן לכוון פריסה קנרית לקבוצות ספציפיות (לפי cookie או אזור גיאוגרפי).
לדוגמה, בפרויקט אחד גילינו שגרסת API חדשה גרמה לשאילתת N+1 למסד הנתונים — על 5% מהתנועה זמן האחזור גדל ב-200%. הפריסה הקנרית החזירה אוטומטית את הגרסה, ותיקנו את הבעיה ללא השבתה המונית.
שינוי ידני של משקל ב-Nginx פירושו 5 דקות של זמן השבתה לעריכת התצורה וטעינה מחדש. פריסה אוטומטית עם בדיקות מדדים מצמצמת זאת לאפס. אנו מיישמים pipeline שמחליט בעצמו: להגדיל משקל או לחזור לגרסה קודמת. ב-Kubernetes עם NGINX Ingress, החזרה מהירה פי 10 —只需 למחוק את ה-ingress הקנרי.
יישום: מ-Nginx ל-Kubernetes ו-AWS
התנועה מתחלקת בין גרסה יציבה לגרסה קנרית: 95% מהבקשות הולכות לגרסה הישנה, 5% לחדשה. מאזן העומס או ה-proxy קובעים לאיזה upstream לפנות.
Nginx split_clients
# /etc/nginx/nginx.conf
split_clients "${remote_addr}${http_user_agent}" $upstream_pool {
5% canary; # 5% → новая версия
* stable; # 95% → старая версия
}
upstream stable {
server 10.0.0.10:8080;
}
upstream canary {
server 10.0.0.11:8080; # новая версия
}
server {
location / {
proxy_pass http://$upstream_pool;
}
}כדי לשנות את האחוז — ערכו את התצורה וטענו מחדש את Nginx: # /etc/nginx/nginx.conf split_clients "${remote_addr}${http_user_agent}" $upstream_pool { 5% canary; # 5% → новая версия * stable; # 95% → старая версия } upstream stable { server 10.0.0.10:8080; } upstream canary { server 10.0.0.11:8080; # новая версия } server { location / { proxy_pass http://$upstream_pool; } } .
פריסה קנרית באמצעות Cookie (ניתוב דביק)
# Пользователь всегда попадает в ту же версию
map $cookie_canary $upstream_canary {
"1" canary;
default stable;
}
# Или принудительно включить для тестировщиков
map $http_x_canary_override $upstream_override {
"true" canary;
default $upstream_canary;
} איך להגדיר פריסה קנרית ב-Kubernetes?
---
# stable-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-stable
spec:
replicas: 10
selector:
matchLabels:
app: myapp
version: stable
template:
metadata:
labels:
app: myapp
version: stable
spec:
containers:
- name: myapp
image: registry/myapp:v1.0.0
---
# canary-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-canary
spec:
replicas: 2
selector:
matchLabels:
app: myapp
version: canary
template:
metadata:
labels:
app: myapp
version: canary
spec:
containers:
- name: myapp
image: registry/myapp:v1.1.0
---
# canary-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-canary
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "5" # 5% трафика
spec:
rules:
- host: example.com
http:
paths:
- path: /
backend:
service:
name: myapp-canary-svc
port: { number: 80 }
---
נהלו משקל באמצעות kubectl: nginx -s reload. במעבר מלא, עדכנו את ה-deployment היציב ומחקו את הקנרי: # Пользователь всегда попадает в ту же версию map $cookie_canary $upstream_canary { "1" canary; default stable; } # Или принудительно включить для тестировщиков map $http_x_canary_override $upstream_override { "true" canary; default $upstream_canary; } ו-# stable-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: myapp-stable spec: replicas: 10 selector: matchLabels: app: myapp version: stable template: metadata: labels: app: myapp version: stable spec: containers: - name: myapp image: registry/myapp:v1.0.0 --- # canary-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: myapp-canary spec: replicas: 2 selector: matchLabels: app: myapp version: canary template: metadata: labels: app: myapp version: canary spec: containers: - name: myapp image: registry/myapp:v1.1.0 --- # canary-ingress.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: myapp-canary annotations: nginx.ingress.kubernetes.io/canary: "true" nginx.ingress.kubernetes.io/canary-weight: "5" # 5% трафика spec: rules: - host: example.com http: paths: - path: / backend: service: name: myapp-canary-svc port: { number: 80 } .
AWS: קבוצות יעד משוקללות
import boto3
elbv2 = boto3.client('elbv2')
def set_canary_weight(listener_arn: str, stable_tg: str, canary_tg: str, canary_weight: int):
"""stable_weight + canary_weight должны давать 100"""
stable_weight = 100 - canary_weight
elbv2.modify_listener(
ListenerArn=listener_arn,
DefaultActions=[{
'Type': 'forward',
'ForwardConfig': {
'TargetGroups': [
{'TargetGroupArn': stable_tg, 'Weight': stable_weight},
{'TargetGroupArn': canary_tg, 'Weight': canary_weight},
],
'TargetGroupStickinessConfig': {
'Enabled': True,
'DurationSeconds': 3600, # stickiness 1 час
}
}
}]
)
פריסה קנרית אוטומטית עם ניתוח מדדים
# canary-rollout.py
import time
import boto3
import requests
PROMETHEUS_URL = "http://prometheus:9090"
def get_error_rate(version: str, duration: str = "5m") -> float:
query = f'rate(http_requests_total{{version="{version}",status=~"5.."}}[{duration}]) / rate(http_requests_total{{version="{version}"}}[{duration}])'
r = requests.get(f"{PROMETHEUS_URL}/api/v1/query", params={"query": query})
result = r.json()["data"]["result"]
return float(result[0]["value"][1]) if result else 0.0
def progressive_rollout():
steps = [5, 10, 25, 50, 75, 100]
canary_weight = 0
for target_weight in steps:
print(f"Setting canary weight to {target_weight}%")
set_canary_weight(LISTENER_ARN, STABLE_TG, CANARY_TG, target_weight)
# Ждать и проверять метрики
time.sleep(300) # 5 минут на каждом шаге
error_rate = get_error_rate("canary")
print(f"Canary error rate: {error_rate:.2%}")
if error_rate > 0.01: # >1% ошибок
print(f"Error rate too high ({error_rate:.2%}), rolling back!")
set_canary_weight(LISTENER_ARN, STABLE_TG, CANARY_TG, 0)
return False
print("Canary rollout complete!")
return True איך מתבצע יישום פריסה קנרית?
- ניתוח הארכיטקטורה והתנועה הנוכחית (1–2 ימים).
- תכנון התכנית הקנרית: בחירת כלי (Nginx, K8s Ingress, AWS ALB) (יום אחד).
- הגדרת תצורה ופריסה (2–4 ימים).
- אינטגרציה עם ניטור (Prometheus, Grafana, Datadog) (1–2 ימים).
- בדיקות והדרכת צוות (1–2 ימים).
- פריסה ותמיכה במהלך הימים הראשונים (יום אחד).
סה"כ: בין 5 ל-10 ימי עבודה בהתאם למורכבות.
| שיטה | מורכבות | זמן יישום | קנה מידה | חזרה לגרסה קודמת |
|---|---|---|---|---|
| Nginx split_clients | נמוכה | 1–2 ימים | מוגבל | ידני (5 דקות) |
| K8s NGINX Ingress | בינונית | 2–4 ימים | אוטומטי | אוטומטי |
| AWS ALB + Lambda | גבוהה | 3–5 ימים | אוטומטי | אוטומטי |
רשימת בדיקות לניטור פריסה קנרית
- שיעור שגיאות בגרסה החדשה < 1%
- זמן אחזור p95 עלה בלא יותר מ-10%
- שיעור ההמרה לא ירד (אם רלוונטי)
- CPU/זיכרון בטווח הנורמלי
- כל אינטגרציות ה-API החיצוניות פועלות
מה כלול בעבודה
| מה כלול | תיאור |
|---|---|
| תצורת פריסה קנרית (Nginx/K8s/AWS) | תכנית מוכנה עם תיעוד |
| ניטור והתראות | לוחות מחוונים של Prometheus + Grafana |
| אינטגרציית CI/CD | GitHub Actions, GitLab CI, או Jenkins |
| הדרכת צוות (מפגש אחד) | איך לנהל פריסה קנרית ידנית |
| תמיכה טכנית למשך שבועיים | סיוע במהלך ההשקה |
עם ניסיון של למעלה מ-7 שנים ו-50+ פרויקטים — הצוות שלנו מוסמך ומוכן לקחת על עצמו את הפרויקט שלכם. צרו קשר לייעוץ — נבחן את הפרויקט שלכם תוך יום אחד. הזמינו הגדרת פריסה קנרית במפתח מלא וקבלו שחרורים ללא זמן השבתה.
לוחות זמנים
- פריסה קנרית ב-Nginx על VPS: 1–2 ימים
- פריסה קנרית ב-Kubernetes NGINX Ingress: 2–3 ימים
- פריסה אוטומטית עם מדדים: 3–5 ימים







