0
0
Lập trình
TT

Triển khai dịch vụ Docker không gián đoạn với Blue-Green

Đăng vào 7 tháng trước

• 6 phút đọc

Giới thiệu

Như một người lãnh đạo DevOps, bạn có thể đã chứng kiến sự hoảng loạn khi dịch vụ gặp sự cố. Tin tốt là, với Docker, Nginx và quy trình làm việc blue-green có kỷ luật, bạn có thể cập nhật mà không bao giờ làm gián đoạn trải nghiệm của người dùng. Bài hướng dẫn này sẽ dẫn bạn qua một thiết lập thực tế, từ đầu đến cuối, có thể tích hợp vào bất kỳ quy trình CI/CD nào.

Các yêu cầu cần có

  • Docker Engine ≥ 20.10 trên máy chủ xây dựng và sản xuất của bạn
  • Docker Compose để kiểm tra cục bộ
  • Nginx hoạt động như một reverse proxy trước các container của bạn
  • Một repository Git kích hoạt hệ thống CI của bạn (GitHub Actions, GitLab CI, v.v.)
  • Kiến thức cơ bản về Bash và YAML

Nếu bất kỳ điều gì trong số này còn thiếu, hãy khởi động chúng trước; các bước dưới đây giả định rằng chúng đã có sẵn.

1. Cấu trúc Repository cho Blue-Green

Tạo một bố cục thư mục tách biệt hai môi trường:

Copy
my-app/
├─ docker-compose.yml          # dịch vụ chung (db, redis, …)
├─ nginx/
│   └─ nginx.conf            # cấu hình proxy với các nhóm upstream
├─ blue/
│   └─ Dockerfile            # hình ảnh cho phiên bản "blue"
├─ green/
│   └─ Dockerfile            # hình ảnh cho phiên bản "green"
└─ .github/workflows/
    └─ ci.yml                # định nghĩa quy trình CI

Cả bluegreen có thể có Dockerfile giống nhau; sự khác biệt duy nhất là thẻ bạn đẩy lên registry của mình (ví dụ: my-app:blue-v123). Việc giữ chúng trong các thư mục riêng giúp dễ dàng tham chiếu đến ngữ cảnh xây dựng đúng trong CI.

2. Cấu hình Nginx cho Upstream Động

Sự kỳ diệu nằm trong khối upstream của Nginx. Bằng cách sử dụng resolverbiến, bạn có thể hoán đổi upstream đang hoạt động mà không cần tải lại Nginx.

Copy
http {
    upstream app_upstream {
        # Biến $upstream_name sẽ được thiết lập bởi một script kiểm tra sức khỏe
        server unix:/var/run/${upstream_name}.sock;
    }

    server {
        listen 80;
        location / {
            proxy_pass http://app_upstream;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
    }
}

Khi bạn muốn nâng cấp green lên hoạt động, chỉ cần cập nhật symlink /var/run/green.sock để trỏ đến socket của container mới và thay đổi biến $upstream_name thông qua lệnh nginx -s reload hoặc, tốt hơn, một lệnh zero-downtime nginx -s reload chỉ hoán đổi tham chiếu upstream.

3. Quy trình CI/CD – Nhịp đập chính

Dưới đây là một quy trình GitHub Actions tối thiểu xây dựng cả hai hình ảnh, đẩy chúng lên Docker Hub và sau đó kích hoạt một script nâng cấp trên máy chủ sản xuất.

Copy
name: CI
on:
  push:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Cài đặt Docker Buildx
        uses: docker/setup-buildx-action@v2

      - name: Đăng nhập vào Docker Hub
        uses: docker/login-action@v2
        with:
          username: ${{ secrets.DH_USERNAME }}
          password: ${{ secrets.DH_PASSWORD }}

      - name: Xây dựng & đẩy hình ảnh blue
        run: |
          docker build -t myorg/my-app:blue-${{ github.sha }} ./blue
          docker push myorg/my-app:blue-${{ github.sha }}

      - name: Xây dựng & đẩy hình ảnh green
        run: |
          docker build -t myorg/my-app:green-${{ github.sha }} ./green
          docker push myorg/my-app:green-${{ github.sha }}

      - name: Triển khai green (không gián đoạn)
        env:
          SSH_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
        run: |
          ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no user@prod-host \
            "./deploy_green.sh ${{ github.sha }}"

Script deploy_green.sh là nơi hoán đổi diễn ra. Hãy giữ nó idempotent và an toàn.

4. Script nâng cấp (deploy_green.sh)

Copy
#!/usr/bin/env bash
set -euo pipefail

SHA=$1
APP_NAME="my-app"
GREEN_TAG="green-${SHA}"

# Kéo hình ảnh mới
docker pull myorg/${APP_NAME}:${GREEN_TAG}

# Dừng bất kỳ container green cũ nào
docker rm -f ${APP_NAME}_green || true

# Bắt đầu container green mới liên kết với một Unix socket
docker run -d \
  --name ${APP_NAME}_green \
  -v /var/run/${APP_NAME}_green.sock:/tmp/app.sock \
  myorg/${APP_NAME}:${GREEN_TAG}

# Kiểm tra điểm sức khỏe
if curl -sSf http://localhost:8080/health; then
  echo "✅ Container green khỏe mạnh"
else
  echo "❌ Kiểm tra sức khỏe thất bại, hủy bỏ"
  exit 1
fi

# Hoán đổi upstream Nginx bằng cách cập nhật symlink
ln -sffn /var/run/${APP_NAME}_green.sock /var/run/${APP_NAME}.sock

# Tải lại Nginx (không gián đoạn)
nginx -s reload

# Tùy chọn: dọn dẹp container blue cũ
docker rm -f ${APP_NAME}_blue || true

echo "🚀 Triển khai ${GREEN_TAG} hoàn tất"

Điểm chính:

  • Kiểm tra sức khỏe trước khi hoán đổi ngăn chặn các bản phát hành kém đến với lưu lượng truy cập.
  • Hoán đổi symlink là nguyên tử trên Unix, đảm bảo chuyển đổi ngay lập tức.
  • nginx -s reload chỉ tải lại cấu hình, không phải các tiến trình worker, do đó các kết nối hiện tại vẫn sống.

5. Quan sát & Ghi log

Các triển khai không gián đoạn chỉ tốt như mức độ hiển thị bạn có. Kết nối những điều sau vào ngăn xếp của bạn:

  • Prometheus quét /metrics từ cả hai container. Gán các chỉ số với environment=blue|green.
  • Biểu đồ Grafana cho thấy độ trễ yêu cầu theo phiên bản, cho phép bạn phát hiện sự thoái lui ngay lập tức.
  • ELK stack (hoặc Loki) thu thập log Docker. Sử dụng định dạng log JSON nhất quán để bạn có thể lọc theo container_name.

Một lệnh nhanh để theo dõi log cho việc xử lý sự cố:

Copy
docker logs -f my-app_green --tail 100

6. Chiến lược Rút lui

Nếu phiên bản green mới cho thấy sự gia tăng tỷ lệ lỗi, hãy quay lại với một lệnh duy nhất:

Copy
# Chuyển lại socket về blue
ln -sffn /var/run/${APP_NAME}_blue.sock /var/run/${APP_NAME}.sock
nginx -s reload

Bởi vì container blue vẫn đang chạy (bạn không docker rm -f nó cho đến khi kiểm tra sức khỏe của green vượt qua), việc hoán đổi là tức thì. Chỉ sau một khoảng thời gian thành công, bạn nên dọn dẹp phiên bản cũ.

7. Bonus: Blue-Green với Kubernetes (Tùy chọn)

Nếu nhóm của bạn chuyển sang K8s, các nguyên tắc tương tự áp dụng sử dụng DeploymentsServices với strategy.type: RollingUpdate được thiết lập thành maxSurge: 0maxUnavailable: 0. Tuy nhiên, phương pháp Docker-Nginx vẫn nhẹ nhàng cho các sản phẩm SaaS nhỏ và vừa.

Kết luận

Các triển khai không gián đoạn không còn là lý tưởng xa vời; chúng là một mô hình thực tế mà bạn có thể thực hiện ngay hôm nay với Docker, Nginx và một quy trình CI kỷ luật. Bằng cách tách biệt các bản dựng blue và green, sử dụng hoán đổi socket nguyên tử và kết hợp kiểm tra sức khỏe với khả năng quan sát, bạn bảo vệ người dùng trong khi vẫn di chuyển nhanh.

Nếu bạn cần hỗ trợ trong việc triển khai điều này, đội ngũ tại ramerlabs.com có thể giúp bạn.

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào