VK Private Cloud logo
Помощь
Обновлена 21 августа 2026 г. в 11:12

Ручное обновление

По этой инструкции выполните обновление для каждого сервиса:

  • neutron;
  • barbican;
  • billing-account-service;
  • celery;
  • cinder;
  • gb;
  • katana;
  • magnum;
  • magnum-rapid;
  • manila;
  • nova.

Шаг 1. Создание резервной копии StatefulSet

  1. Задайте название сервиса:

    $ SERVICE="<СЕРВИС>"

    Здесь <СЕРВИС> — название обновляемого сервиса.

  2. Задайте целевую версию RabbitMQ:

    $ RABBITMQ_NEW_VERSION="<ВЕРСИЯ>"

    Здесь <ВЕРСИЯ> — версия RabbitMQ, на которую происходит обновление. Значение доступно в файле ~/vkcloud/group_vars/vkcloud/versions.yml в переменной rabbitmq.

  3. Задайте дату:

    $ DATE_TIME=$(date +%F_%H_%M)
  4. Создайте резервную копию StatefulSet:

    $ kubectl get sts "rabbitmq-$SERVICE" -n rabbitmq -o yaml >"sts-$SERVICE-backup_$DATE_TIME.yaml"
  5. Измените тип podAntiAffinity на preferred:

    $ kubectl -n rabbitmq patch sts "rabbitmq-$SERVICE" --type=json -p "$(
    Пример ожидаемого результата
    cat <<EOF[{"op":"remove","path":"/spec/template/spec/affinity/podAntiAffinity/requiredDuringSchedulingIgnoredDuringExecution"},{"op":"add","path":"/spec/template/spec/affinity/podAntiAffinity/preferredDuringSchedulingIgnoredDuringExecution","value":[{"weight":100,"podAffinityTerm":{"topologyKey":"kubernetes.io/hostname","labelSelector":{"matchExpressions":[{"key":"app","operator":"In","values":["rabbitmq-$SERVICE"]}]}}}]}]EOF)"
  6. Следите за пересозданием подов:

    $ kubectl -n rabbitmq rollout status "sts/rabbitmq-$SERVICE"

    Дождитесь успешного завершения операции. При возникновении ошибок исправьте их.

Шаг 2. Ручное распределение подов по управляющим узлам

  1. Проверьте, что поды распределились в случайном порядке:

    $ kubectl get pod -n rabbitmq -o wide -l "app=rabbitmq-$SERVICE"
    Пример ожидаемого результата
    NAME                 READY   STATUS    RESTARTS   AGE   IP             NODE     NOMINATED NODE   READINESS GATESrabbitmq-neutron-0   1/1     Running   0          11m   10.220.0.74    cpn003   <none>           <none>rabbitmq-neutron-1   1/1     Running   0          11m   10.220.0.27    cpn002   <none>           <none>rabbitmq-neutron-2   1/1     Running   0          12m   10.220.1.212   cpn001   <none>           <none>
  2. Отметьте узлы как недоступные и перенесите поды вручную.

    Пример ручного перераспределения:

    1. Пересоздание пода $SERVICE-0 на cpn001:

      $ kubectl cordon cpn002 cpn003$ kubectl -n rabbitmq delete pod "rabbitmq-$SERVICE-0"$ kubectl -n rabbitmq wait --for=condition=Ready "pod/rabbitmq-$SERVICE-0" --timeout=600s
      Пример ожидаемого результата
      node/cpn003 cordonedpod "rabbitmq-neutron-0" deletedpod/rabbitmq-neutron-0 condition met
    2. Проверка, что $SERVICE-0 размещен на cpn001:

      $ kubectl get pod -n rabbitmq -o wide "rabbitmq-$SERVICE-0"
      Пример ожидаемого результата
      NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATESrabbitmq-neutron-0 1/1 Running 0 7m49s 10.220.1.241 cpn001 <none> <none>
    3. Пересоздание пода $SERVICE-1 на cpn002:

      $ kubectl uncordon cpn002 cpn003$ kubectl cordon cpn001 cpn003$ kubectl -n rabbitmq delete pod "rabbitmq-$SERVICE-1"$ kubectl -n rabbitmq wait --for=condition=Ready "pod/rabbitmq-$SERVICE-1" --timeout=300s
      Пример ожидаемого результата
      node/cpn001 cordonednode/cpn003 cordonedpod "rabbitmq-neutron-1" deletedpod/rabbitmq-neutron-1 condition met
    4. Проверка, что $SERVICE-1 размещен на cpn002:

      $ kubectl get pod -n rabbitmq -o wide "rabbitmq-$SERVICE-1"
      Пример ожидаемого результата
      NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATESrabbitmq-neutron-1 1/1 Running 0 57s 10.220.0.27 cpn002 <none> <none>
    5. Пересоздание пода $SERVICE-2 на cpn003:

      $ kubectl uncordon cpn001 cpn003$ kubectl cordon cpn001 cpn002$ kubectl -n rabbitmq delete pod "rabbitmq-$SERVICE-2"$ kubectl -n rabbitmq wait --for=condition=Ready "pod/rabbitmq-$SERVICE-2" --timeout=300s
      Пример ожидаемого результата
      node/cpn001 cordonednode/cpn002 cordonedpod "rabbitmq-neutron-2" deletedpod/rabbitmq-neutron-2 condition met
    6. Проверка, что $SERVICE-2 размещен на cpn003:

      $ kubectl get pod -n rabbitmq -o wide "rabbitmq-$SERVICE-2"
      Пример ожидаемого результата
      NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATESrabbitmq-neutron-2 1/1 Running 0 60s 10.220.0.74 cpn003 <none> <none>
    7. Разрешение размещения подов на cpn001 и cpn002:

      $ kubectl uncordon cpn001 cpn002
  3. Удалите StatefulSet, оставляя поды:

    $ kubectl delete sts "rabbitmq-$SERVICE" -n rabbitmq --cascade=orphan
    Пример ожидаемого результата
    statefulset.apps "rabbitmq-neutron" deleted
  4. Из резервной копии, созданной ранее, создайте StatefulSet с PVC:

    $ dnf install -y yq$ IN="sts-$SERVICE-backup_$DATE_TIME.yaml"$ OUT="sts-$SERVICE-pvc.yaml"$ STORAGE_SIZE=$(kubectl -n "$NAMESPACE" get pvc "rabbitmq-data-neutron-rabbitmq-$SERVICE-0" -o jsonpath='{.status.capacity.storage}')$ yq '   del(.metadata.uid,      .metadata.resourceVersion,      .metadata.generation,      .metadata.creationTimestamp,      .status)   | .spec.podManagementPolicy = "Parallel"   | .spec.volumeClaimTemplates = [{      "apiVersion":"v1",      "kind":"PersistentVolumeClaim",      "metadata":{"name":"rabbitmq-data-'$SERVICE'"},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"'"$STORAGE_SIZE"'"}},"volumeMode":"Filesystem"}}]' "$IN" >"$OUT"
  5. Проверьте созданный файл:

    $ kubectl -n rabbitmq apply --dry-run=client -f "$OUT" >/dev/null && echo "OK: $OUT"
  6. Выполните развертывание манифеста StatefulSet:

    $ kubectl -n rabbitmq apply -f "$OUT"
  7. Проверьте статус кластера:

    Проверка статуса кластера
    $ kubectl -n rabbitmq exec "rabbitmq-$SERVICE-0" -- rabbitmqctl cluster_status | head -n 40

    В выводе этой команды в блоке Versions должно быть три пода с корректной версией RabbitMQ для текущего шага обновления.

    Если в выводе будет два пода, определите, какой под выбыл из кластера, и повторно добавьте его в кластер.

    Если вывод для каждого пода ($SERVICE-0, $SERVICE-1 и $SERVICE-2) будет содержать только по одной записи, выберите любой под и присоедините к нему остальные. Для этого выполните следующую инструкцию для каждого выбывшего пода:

    1. Подключитесь к выбывшему поду:

      $ kubectl -n rabbitmq exec -ti rabbitmq-<СЕРВИС>-<ВЫБЫВШИЙ_ПОД> -- sh

      Здесь:

      • <СЕРВИС> — название обновляемого сервиса.
      • <ВЫБЫВШИЙ_ПОД> — номер выбывшего пода.
    2. Выполните команды:

      $ rabbitmqctl stop_app$ rabbitmqctl reset$ rabbitmqctl join_cluster rabbit@rabbitmq-<СЕРВИС>-<НОМЕР_ЦЕЛЕВОГО_ПОДА>.rabbitmq-<СЕРВИС>.rabbitmq.svc.kube$ rabbitmqctl start_app

      Здесь:

      • <СЕРВИС> — название обновляемого сервиса.
      • <НОМЕР_ЦЕЛЕВОГО_ПОДА> — номер пода, к которому нужно присоединить выбывший под.
    3. Повторно проверьте статус кластера:

      $ kubectl -n rabbitmq exec "rabbitmq-$SERVICE-0" -- rabbitmqctl cluster_status | head -n 40
  8. Удалите поды по одному, чтобы они пересоздались с PVC:

    1. Удалите под:

      $ kubectl delete pod -n rabbitmq "rabbitmq-$SERVICE-0"
    2. Дождитесь успешного запуска пода:

      $ kubectl wait --for=condition=Ready "pod/rabbitmq-$SERVICE-0" -n rabbitmq --timeout=600s
    3. Проверьте статус узла и кластера:

      $ kubectl exec -n rabbitmq "rabbitmq-$SERVICE-0" -- rabbitmq-diagnostics -q ping$ kubectl exec -n rabbitmq "rabbitmq-$SERVICE-0" -- rabbitmqctl cluster_status | head -n 40

    Повторите шаги для оставшихся подов, изменяя индекс переменной $SERVICE-n.

Шаг 3. Обновление RabbitMQ с версии 3.11 до 3.12

  1. Включите доступные Feature Flags:

    $ kubectl exec -n rabbitmq rabbitmq-$SERVICE-0 -- rabbitmqctl enable_feature_flag all
  2. Проверьте статус кластера:

    $ kubectl -n rabbitmq exec "rabbitmq-$SERVICE-0" -- rabbitmqctl cluster_status | head -n 40
  3. Обновите образ StatefulSet до версии 3.12.X:

    $ kubectl set image sts/rabbitmq-$SERVICE -n rabbitmq rabbitmq-$SERVICE=<ХОСТ>:<ПОРТ>/infra/private/govcloud-rpms/rabbitmq:3.12.14statefulset.apps/rabbitmq-neutron image updated
  4. Дождитесь выполнения команды rollout на каждом узле и проверьте статус кластера:

    $ kubectl rollout status sts/rabbitmq-$SERVICE -n rabbitmq --timeout=10m$ kubectl exec -n rabbitmq "rabbitmq-$SERVICE-0" -- rabbitmq-diagnostics -q ping$ kubectl exec -n rabbitmq "rabbitmq-$SERVICE-0" -- rabbitmqctl cluster_status | head -n 40

Шаг 4. Обновление RabbitMQ с версии 3.12 до 3.13

  1. Включите доступные Feature Flags:

    $ kubectl exec -n rabbitmq rabbitmq-$SERVICE-0 -- rabbitmqctl enable_feature_flag all
  2. Проверьте статус кластера:

    $ kubectl -n rabbitmq exec "rabbitmq-$SERVICE-0" -- rabbitmqctl cluster_status | head -n 40
  3. Обновите образ StatefulSet до целевой версии:

    $ kubectl set image sts/rabbitmq-$SERVICE -n rabbitmq rabbitmq-$SERVICE=<ХОСТ>:<ПОРТ>/infra/private/govcloud-rpms/rabbitmq:$RABBITMQ_NEW_VERSION
  4. Дождитесь выполнения команды rollout на каждом узле и проверьте статус кластера:

    $ kubectl rollout status sts/rabbitmq-$SERVICE -n rabbitmq --timeout=10m$ kubectl exec -n rabbitmq "rabbitmq-$SERVICE-0" -- rabbitmq-diagnostics -q ping$ kubectl exec -n rabbitmq "rabbitmq-$SERVICE-0" -- rabbitmqctl cluster_status | head -n 40
  5. Очистите StatefulSet:

    $ kubectl get sts -n rabbitmq -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' | grep "^rabbitmq-$SERVICE" | xargs -r -n1 -I{} kubectl delete sts {} -n rabbitmq --cascade=orphan
  6. Выполните плейбук rabbitmq.yml:

    $ ansible-playbook -i vkcloud.yml  -e distro_deploy=true -e env=vkcloud ../ansible-openstack/playbooks/rabbitmq.yml
Была ли статья полезна?