Настройка Blue-Green деплоя для веб-приложения
Blue-Green деплой — стратегия zero-downtime деплоя с двумя идентичными production-окружениями. В каждый момент только одно из них принимает трафик. Новая версия разворачивается в «холодное» окружение, тестируется, затем трафик переключается мгновенно.
Принцип работы
┌─────────────────┐
Пользователи → │ Load Balancer │
└────────┬────────┘
│
┌───────────┴───────────┐
▼ ▼
┌──────────────┐ ┌──────────────┐
│ Blue (v1.0) │ ← │ Green (v1.1) │
│ ACTIVE │ ←── │ STANDBY │
└──────────────┘ └──────────────┘
После переключения:
┌──────────────┐ ┌──────────────┐
│ Blue (v1.0) │ │ Green (v1.1) │
│ STANDBY │ ──→ │ ACTIVE │
└──────────────┘ └──────────────┘
Реализация через Nginx
# /etc/nginx/conf.d/upstream.conf
upstream blue {
server 10.0.0.10:8080;
}
upstream green {
server 10.0.0.11:8080;
}
# Симлинк указывает на активное окружение
# /etc/nginx/conf.d/active → blue.conf или green.conf
# /etc/nginx/conf.d/blue.conf
upstream active {
server 10.0.0.10:8080;
}
# /etc/nginx/conf.d/myapp.conf
server {
listen 80;
location / {
proxy_pass http://active;
}
}
# Скрипт переключения
#!/bin/bash
CURRENT=$(readlink /etc/nginx/conf.d/active.conf | grep -o 'blue\|green')
TARGET=$([ "$CURRENT" = "blue" ] && echo "green" || echo "blue")
echo "Switching from $CURRENT to $TARGET"
# Переключить симлинк
ln -sfn /etc/nginx/conf.d/${TARGET}.conf /etc/nginx/conf.d/active.conf
# Перезагрузить Nginx (без даунтайма)
nginx -t && nginx -s reload
echo "Traffic now flowing to $TARGET"
Blue-Green на AWS с ALB
# boto3 — переключение Target Groups
import boto3
elbv2 = boto3.client('elbv2', region_name='eu-west-1')
def switch_traffic(listener_arn: str, target_blue: str, target_green: str):
listener = elbv2.describe_listeners(ListenerArns=[listener_arn])
current_action = listener['Listeners'][0]['DefaultActions'][0]
current_tg = current_action['TargetGroupArn']
# Определить, какой активен
new_tg = target_green if current_tg == target_blue else target_blue
environment = 'green' if new_tg == target_green else 'blue'
# Переключить
elbv2.modify_listener(
ListenerArn=listener_arn,
DefaultActions=[{
'Type': 'forward',
'TargetGroupArn': new_tg,
}]
)
print(f"Traffic switched to {environment} ({new_tg})")
Blue-Green в Docker Swarm
#!/bin/bash
SERVICE=myapp
REGISTRY=registry.example.com
NEW_IMAGE=$REGISTRY/myapp:$BUILD_TAG
# Определить текущий слот
CURRENT_SLOT=$(docker service inspect $SERVICE --format '{{index .Spec.Labels "slot"}}')
NEW_SLOT=$([ "$CURRENT_SLOT" = "blue" ] && echo "green" || echo "blue")
# Запустить новую версию
docker service create \
--name "${SERVICE}-${NEW_SLOT}" \
--label slot=$NEW_SLOT \
--network myapp-network \
--replicas 2 \
$NEW_IMAGE
# Дождаться готовности
echo "Waiting for $NEW_SLOT to be ready..."
until docker service ls --filter "name=${SERVICE}-${NEW_SLOT}" --format "{{.Replicas}}" | grep -q "2/2"; do
sleep 2
done
# Health check
HEALTH=$(curl -sf https://green.internal.example.com/health && echo "ok" || echo "fail")
if [ "$HEALTH" = "fail" ]; then
echo "Health check failed, aborting"
docker service rm "${SERVICE}-${NEW_SLOT}"
exit 1
fi
# Переключить трафик
./switch-nginx.sh $NEW_SLOT
# Удалить старое окружение через 30 секунд
sleep 30
docker service rm "${SERVICE}-${CURRENT_SLOT}"
Blue-Green в Kubernetes
# Два Deployment'а — blue и green
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-green
labels:
app: myapp
slot: green
spec:
replicas: 3
selector:
matchLabels: { app: myapp, slot: green }
template:
metadata:
labels: { app: myapp, slot: green }
spec:
containers:
- name: myapp
image: registry.example.com/myapp:v1.1.0
# Переключение трафика в k8s
kubectl patch service myapp-svc \
-p '{"spec":{"selector":{"app":"myapp","slot":"green"}}}'
# Проверка
kubectl rollout status deployment/myapp-green
# Rollback
kubectl patch service myapp-svc \
-p '{"spec":{"selector":{"app":"myapp","slot":"blue"}}}'
Пайплайн с Blue-Green
# GitHub Actions
deploy-green:
needs: [test]
steps:
- name: Deploy to Green
run: docker stack deploy -c docker-compose.green.yml myapp-green
- name: Health Check
run: |
for i in $(seq 1 30); do
curl -sf https://green.internal/health && exit 0
sleep 2
done
exit 1
- name: Switch Traffic
run: ./switch-traffic.sh green
- name: Cleanup Blue (after 5 min)
run: sleep 300 && docker service rm myapp-blue
Срок реализации
- Nginx Blue-Green на VPS: 2–3 дня
- AWS ALB + Target Groups: 3–4 дня
- Kubernetes Blue-Green: 3–5 дней







