Ручное обновление
По этой инструкции выполните обновление для каждого сервиса:
neutron;barbican;billing-account-service;celery;cinder;gb;katana;magnum;magnum-rapid;manila;nova.
-
Задайте название сервиса:
$ SERVICE="<СЕРВИС>"Здесь
<СЕРВИС>— название обновляемого сервиса. -
Задайте целевую версию RabbitMQ:
$ RABBITMQ_NEW_VERSION="<ВЕРСИЯ>"Здесь
<ВЕРСИЯ>— версия RabbitMQ, на которую происходит обновление. Значение доступно в файле~/vkcloud/group_vars/vkcloud/versions.ymlв переменнойrabbitmq. -
Задайте дату:
$ DATE_TIME=$(date +%F_%H_%M) -
Создайте резервную копию StatefulSet:
$ kubectl get sts "rabbitmq-$SERVICE" -n rabbitmq -o yaml >"sts-$SERVICE-backup_$DATE_TIME.yaml" -
Измените тип 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)" -
Следите за пересозданием подов:
$ kubectl -n rabbitmq rollout status "sts/rabbitmq-$SERVICE"Дождитесь успешного завершения операции. При возникновении ошибок исправьте их.
-
Проверьте, что поды распределились в случайном порядке:
$ 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> -
Отметьте узлы как недоступные и перенесите поды вручную.
Пример ручного перераспределения:
-
Пересоздание пода
$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 -
Проверка, что
$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> -
Пересоздание пода
$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 -
Проверка, что
$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> -
Пересоздание пода
$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 -
Проверка, что
$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> -
Разрешение размещения подов на
cpn001иcpn002:$ kubectl uncordon cpn001 cpn002
-
-
Удалите StatefulSet, оставляя поды:
$ kubectl delete sts "rabbitmq-$SERVICE" -n rabbitmq --cascade=orphanПример ожидаемого результатаstatefulset.apps "rabbitmq-neutron" deleted -
Из резервной копии, созданной ранее, создайте 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" -
Проверьте созданный файл:
$ kubectl -n rabbitmq apply --dry-run=client -f "$OUT" >/dev/null && echo "OK: $OUT" -
Выполните развертывание манифеста StatefulSet:
$ kubectl -n rabbitmq apply -f "$OUT" -
Проверьте статус кластера:
Проверка статуса кластера$ kubectl -n rabbitmq exec "rabbitmq-$SERVICE-0" -- rabbitmqctl cluster_status | head -n 40В выводе этой команды в блоке
Versionsдолжно быть три пода с корректной версией RabbitMQ для текущего шага обновления.Если в выводе будет два пода, определите, какой под выбыл из кластера, и повторно добавьте его в кластер.
Если вывод для каждого пода (
$SERVICE-0,$SERVICE-1и$SERVICE-2) будет содержать только по одной записи, выберите любой под и присоедините к нему остальные. Для этого выполните следующую инструкцию для каждого выбывшего пода:-
Подключитесь к выбывшему поду:
$ kubectl -n rabbitmq exec -ti rabbitmq-<СЕРВИС>-<ВЫБЫВШИЙ_ПОД> -- shЗдесь:
<СЕРВИС>— название обновляемого сервиса.<ВЫБЫВШИЙ_ПОД>— номер выбывшего пода.
-
Выполните команды:
$ rabbitmqctl stop_app$ rabbitmqctl reset$ rabbitmqctl join_cluster rabbit@rabbitmq-<СЕРВИС>-<НОМЕР_ЦЕЛЕВОГО_ПОДА>.rabbitmq-<СЕРВИС>.rabbitmq.svc.kube$ rabbitmqctl start_appЗдесь:
<СЕРВИС>— название обновляемого сервиса.<НОМЕР_ЦЕЛЕВОГО_ПОДА>— номер пода, к которому нужно присоединить выбывший под.
-
Повторно проверьте статус кластера:
$ kubectl -n rabbitmq exec "rabbitmq-$SERVICE-0" -- rabbitmqctl cluster_status | head -n 40
-
-
Удалите поды по одному, чтобы они пересоздались с PVC:
-
Удалите под:
$ kubectl delete pod -n rabbitmq "rabbitmq-$SERVICE-0" -
Дождитесь успешного запуска пода:
$ kubectl wait --for=condition=Ready "pod/rabbitmq-$SERVICE-0" -n rabbitmq --timeout=600s -
Проверьте статус узла и кластера:
$ 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. -
-
Включите доступные Feature Flags:
$ kubectl exec -n rabbitmq rabbitmq-$SERVICE-0 -- rabbitmqctl enable_feature_flag all -
Проверьте статус кластера:
$ kubectl -n rabbitmq exec "rabbitmq-$SERVICE-0" -- rabbitmqctl cluster_status | head -n 40 -
Обновите образ 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 -
Дождитесь выполнения команды
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
-
Включите доступные Feature Flags:
$ kubectl exec -n rabbitmq rabbitmq-$SERVICE-0 -- rabbitmqctl enable_feature_flag all -
Проверьте статус кластера:
$ kubectl -n rabbitmq exec "rabbitmq-$SERVICE-0" -- rabbitmqctl cluster_status | head -n 40 -
Обновите образ StatefulSet до целевой версии:
$ kubectl set image sts/rabbitmq-$SERVICE -n rabbitmq rabbitmq-$SERVICE=<ХОСТ>:<ПОРТ>/infra/private/govcloud-rpms/rabbitmq:$RABBITMQ_NEW_VERSION -
Дождитесь выполнения команды
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 -
Очистите 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 -
Выполните плейбук
rabbitmq.yml:$ ansible-playbook -i vkcloud.yml -e distro_deploy=true -e env=vkcloud ../ansible-openstack/playbooks/rabbitmq.yml