• Русский
  • Мажорное обновление версии (Blue-Green Deployment)

    RabbitMQ 3.12.x нельзя напрямую обновить до 4.2.x через обновление на месте. Необходимо создать новый экземпляр 4.2.x и перенести данные из старого экземпляра. В этом документе описаны два подхода к миграции в зависимости от того, допустим ли простой.

    Выберите подходящий вариант
    • Вариант 1: Drain & Migrate — Если вы можете допустить кратковременный перерыв в обслуживании, сначала обработайте все сообщения, а затем переключитесь на новый экземпляр. Это самый простой подход.
    • Вариант 2: Blue-Green Upgrade — Если простой недопустим, используйте плагин Federation для бесшовной миграции без потери сообщений.

    Вариант 1: Drain & Migrate (допустимый простой)

    Этот подход предполагает кратковременный перерыв в обслуживании. Если ваш бизнес может выдержать простой, это самый прямолинейный вариант:

    1. Слить сообщения: Остановите всех producer'ов и дождитесь, пока consumer'ы обработают все оставшиеся сообщения. Убедитесь, что все очереди пусты.
    2. Экспортировать определения: Экспортируйте определения (exchanges, queues, bindings, users, vhosts) из старого экземпляра 3.12.x.
    3. Создать новый экземпляр: Разверните новый экземпляр RabbitMQ 4.2.x.
    4. Импортировать определения: Импортируйте определения в новый экземпляр 4.2.x.
    5. Переключить трафик: Обновите конфигурации приложений для подключения к новому экземпляру и перезапустите их.
    6. Вывести из эксплуатации: После того как все будет подтверждено как работающее, удалите старый экземпляр 3.12.x.

    Вариант 2: Blue-Green Upgrade (без простоя)

    Этот подход использует плагин RabbitMQ Federation для бесшовной передачи сообщений из старого экземпляра (blue) в новый экземпляр (green) без остановки producer'ов или consumer'ов. Дополнительные сведения см. в официальном руководстве по Blue-Green Deployment.

    Как это работает

    1. Разверните новый экземпляр 4.2.x (green) рядом с существующим экземпляром 3.12.x (blue).
    2. Импортируйте определения из blue в green (exchanges, queues, bindings, users и т. д.).
    3. Настройте queue federation в кластере green с upstream, указывающим на blue.
    4. Перенесите consumer'ов на green — federation автоматически будет подтягивать сообщения из blue в green.
    5. Слейте оставшиеся сообщения из blue.
    6. Перенесите producer'ов на green.
    7. Выведите из эксплуатации кластер blue.
    Принцип Federation

    Федеративные очереди работают по принципу, согласно которому consumer'ы, подключенные к кластеру green, будут получать сообщения, опубликованные в кластере blue, если для этих очередей на blue нет локальных consumer'ов. Локальные consumer'ы всегда имеют приоритет.

    Предварительные требования

    • Старый экземпляр RabbitMQ 3.12.x (blue) исправен и находится в состоянии Active.
    • Плагин rabbitmq_federation доступен в обоих экземплярах.

    Порядок действий

    CLI

    Шаг 1: Создайте новый экземпляр 4.2.x (кластер green)

    cat << 'EOF' | kubectl -n <namespace> create -f -
    apiVersion: rabbitmq.com/v1beta1
    kind: RabbitmqCluster
    metadata:
      name: <green-instance-name>
    spec:
      replicas: 3
      version: "4.2"
      resources:
        limits:
          cpu: 1
          memory: 2Gi
        requests:
          cpu: 1
          memory: 2Gi
      persistence:
        storage: 1Gi
        storageClassName: <storage-class>
      service:
        type: ClusterIP
      rabbitmq:
        additionalPlugins:
          - rabbitmq_federation
          - rabbitmq_federation_management
        additionalConfig: |-
          channel_max=1000
          default_vhost=/
          handshake_timeout=10000
          heartbeat=60
          max_message_size=134217728
          queue_index_embed_msgs_below=4096
          raft.wal_max_size_bytes=64000000
          vm_memory_calculation_strategy=allocated
          vm_memory_high_watermark.relative=0.4
    EOF

    Дождитесь, пока экземпляр green перейдет в состояние Active:

    kubectl -n <namespace> get rabbitmqclusters <green-instance-name> -w

    Шаг 2: Экспортируйте определения из blue и импортируйте их в green

    # Export definitions from blue
    kubectl exec -n <namespace> <blue-pod-0> -- \
      rabbitmqctl export_definitions /tmp/definitions.json
    
    # Copy to local
    kubectl cp <namespace>/<blue-pod-0>:/tmp/definitions.json ./definitions.json
    
    # Copy to green pod
    kubectl cp ./definitions.json <namespace>/<green-pod-0>:/tmp/definitions.json
    
    # Import definitions into green
    kubectl exec -n <namespace> <green-pod-0> -- \
      rabbitmqctl import_definitions /tmp/definitions.json

    Убедитесь, что определения импортированы корректно:

    # Check exchanges, queues, and bindings on green
    kubectl exec -n <namespace> <green-pod-0> -- rabbitmqctl list_exchanges name type
    kubectl exec -n <namespace> <green-pod-0> -- rabbitmqctl list_queues name
    kubectl exec -n <namespace> <green-pod-0> -- rabbitmqctl list_bindings

    Шаг 3: Настройте federation upstream в кластере green

    Сначала получите внутренний адрес службы кластера blue:

    kubectl -n <namespace> get svc -l app.kubernetes.io/name=<blue-instance-name>

    Затем получите учетные данные кластера blue:

    # Get the default user secret name
    kubectl -n <namespace> get rabbitmqclusters <blue-instance-name> \
      -o jsonpath='{.status.defaultUser.secretReference.name}'
    
    # Retrieve username and password
    BLUE_USER=$(kubectl -n <namespace> get secret <blue-secret-name> \
      -o jsonpath='{.data.username}' | base64 -d)
    BLUE_PASS=$(kubectl -n <namespace> get secret <blue-secret-name> \
      -o jsonpath='{.data.password}' | base64 -d)
    
    echo "Blue cluster credentials: $BLUE_USER / $BLUE_PASS"
    URL-кодирование

    Если ваше имя пользователя или пароль содержит специальные символы (например, @, :, /), убедитесь, что они URL-кодированы в URI подключения ниже.

    Настройте upstream в кластере green, указывающий на blue:

    kubectl exec -n <namespace> <green-pod-0> -- \
      rabbitmqctl set_parameter federation-upstream blue \
      '{"uri":"amqp://<blue-user>:<blue-password>@<blue-service-name>.<namespace>.svc.cluster.local"}'

    Задайте policy federation, которая будет соответствовать всем очередям:

    kubectl exec -n <namespace> <green-pod-0> -- \
      rabbitmqctl set_policy --apply-to queues blue-federation ".*" \
      '{"federation-upstream":"blue"}'
    Примечание о приоритете policy

    В RabbitMQ, если нескольким policy соответствует одна и та же очередь, применяется только policy с наивысшим приоритетом. Если импортированные определения уже содержат policy, охватывающие ваши очереди, универсальная policy blue-federation, указанная выше, может не вступить в силу (или может перезаписать существующие правила, если ей будет назначен более высокий приоритет).

    В таких случаях следует вручную обновить существующие policy в кластере green, добавив ключ "federation-upstream": "blue" рядом с их текущими определениями.

    Проверьте состояние federation:

    kubectl exec -n <namespace> <green-pod-0> -- rabbitmqctl eval \
      'rabbit_federation_status:status().'

    Шаг 4: Перенесите consumer'ов в кластер green

    Обновите конфигурации приложений consumer'ов, чтобы они указывали на адрес службы кластера green. На этом этапе:

    • Producer'ы по-прежнему публикуют сообщения в кластер blue.
    • Consumer'ы читают сообщения из кластера green.
    • Federation автоматически подтягивает сообщения из blue в green.

    Получить адрес службы кластера green можно с помощью следующей команды:

    # Get the green cluster's service address
    kubectl -n <namespace> get svc -l app.kubernetes.io/name=<green-instance-name>

    Убедитесь, что сообщения передаются через federation:

    # Check that consumers on green are receiving messages
    kubectl exec -n <namespace> <green-pod-0> -- \
      rabbitmqctl list_queues name messages consumers
    
    # Check federation link status
    kubectl exec -n <namespace> <green-pod-0> -- \
      rabbitmqctl eval 'rabbit_federation_status:status().'
    Важно

    Перед переносом consumer'ов с кластера blue убедитесь, что связи federation на green находятся в состоянии running. Если связь не запущена, сообщения не будут передаваться.

    Шаг 5: Слейте сообщения из кластера blue

    После того как все consumer'ы перейдут на green, federation будет сливать оставшиеся сообщения из blue. Отслеживайте прогресс:

    # Watch queue message counts on blue decrease to 0
    kubectl exec -n <namespace> <blue-pod-0> -- \
      rabbitmqctl list_queues name messages

    Для больших очередей можно дополнительно использовать плагин Shovel, чтобы ускорить слив:

    # Enable shovel on green if not already enabled
    kubectl exec -n <namespace> <green-pod-0> -- rabbitmq-plugins enable rabbitmq_shovel
    
    # Create a shovel for a specific queue with large backlog
    kubectl exec -n <namespace> <green-pod-0> -- \
      rabbitmqctl set_parameter shovel shovel-blue-queue1 \
      '{"src-protocol":"amqp091","src-uri":"amqp://<blue-user>:<blue-password>@<blue-service-name>.<namespace>.svc.cluster.local","src-queue":"<queue-name>","dest-protocol":"amqp091","dest-uri":"amqp://","dest-queue":"<queue-name>"}'
    Примечание

    Использование shovel одновременно с federation приведет к параллельной передаче сообщений, что может вызвать их приход не в порядке отправки. Если порядок сообщений критичен, используйте только federation.

    Шаг 6: Перенесите producer'ов в кластер green

    Когда очереди на blue станут почти пустыми:

    1. Остановите всех producer'ов.

    2. Дождитесь, пока оставшиеся сообщения будут полностью слиты через federation.

    3. Убедитесь, что все очереди на blue пусты:

      kubectl exec -n <namespace> <blue-pod-0> -- \
        rabbitmqctl list_queues name messages
    4. Обновите конфигурации producer'ов так, чтобы они указывали на кластер green, и перезапустите их.

    Шаг 7: Очистите конфигурацию и выведите из эксплуатации кластер blue

    Удалите policy federation и конфигурацию upstream из green:

    kubectl exec -n <namespace> <green-pod-0> -- \
      rabbitmqctl clear_policy blue-federation
    
    kubectl exec -n <namespace> <green-pod-0> -- \
      rabbitmqctl clear_parameter federation-upstream blue

    Удалите кластер blue:

    kubectl -n <namespace> delete rabbitmqcluster <blue-instance-name>

    Контрольный список проверки

    Используйте следующий контрольный список, чтобы проверить каждый этап миграции. Для каждого шага приведена команда CLI, которую можно выполнить напрямую.

    Проверка с помощью AI

    Приведенные ниже команды предназначены для пошагового выполнения. Перед запуском замените все заполнители (например, <namespace>, <blue-pod-0>) на реальные значения.

    #Проверяемый пунктКомандаОжидаемый результат
    1Кластер green находится в состоянии Activekubectl -n <namespace> get rabbitmqclusters <green-instance-name>PHASE: Active
    2Определения импортированыkubectl exec -n <namespace> <green-pod-0> -- rabbitmqctl list_queues nameТе же очереди, что и в blue
    3Плагин Federation включенkubectl exec -n <namespace> <green-pod-0> -- rabbitmq-plugins list -eВ списке есть rabbitmq_federation
    4Federation upstream настроенkubectl exec -n <namespace> <green-pod-0> -- rabbitmqctl list_parametersСуществует federation-upstreamblue
    5Связи federation работаютkubectl exec -n <namespace> <green-pod-0> -- rabbitmqctl eval 'rabbit_federation_status:status().'Состояние running
    6Consumer'ы на green получают сообщенияkubectl exec -n <namespace> <green-pod-0> -- rabbitmqctl list_queues name messages consumersconsumers > 0
    7Очереди blue сливаютсяkubectl exec -n <namespace> <blue-pod-0> -- rabbitmqctl list_queues name messagesКоличество сообщений уменьшается
    8Очереди blue пустыТо же, что и вышеВо всех очередях 0
    9Producer'ы на greenkubectl exec -n <namespace> <green-pod-0> -- rabbitmqctl list_queues name messagesКоличество сообщений увеличивается
    10Federation очищенkubectl exec -n <namespace> <green-pod-0> -- rabbitmqctl list_parametersПараметры federation отсутствуют

    Откат

    Если в ходе миграции возникнут проблемы:

    1. До переноса consumer'ов: Просто удалите кластер green. На существующие сервисы это не повлияет.
    2. После переноса consumer'ов, но до переноса producer'ов: Переключите consumer'ов обратно на кластер blue. Удалите кластер green.
    3. После полной миграции: Если в кластере green возникнут проблемы, создайте новый экземпляр 3.12.x, импортируйте определения и переключитесь обратно. Учтите, что сообщения, опубликованные в green после переключения, потребуется слить обратно с помощью shovel или federation в обратном направлении.