Восстановление после катастрофы глобального кластера

Содержание

Обзор

Это решение предназначено для сценариев восстановления после катастрофы, связанных с кластером global. Кластер global служит управляющей плоскостью платформы и отвечает за управление другими кластерами. Чтобы обеспечить непрерывную доступность сервисов платформы при сбое кластера global, данное решение развертывает два кластера global: основной кластер и резервный кластер.

Механизм восстановления после катастрофы основан на синхронизации данных etcd в реальном времени с основного кластера на резервный. Если основной кластер становится недоступен из-за сбоя, сервисы могут быстро переключиться на резервный кластер.

Поддерживаемые сценарии катастроф

  • Неисправимый системный сбой основного кластера, делающий его непригодным к работе;
  • Сбой физических или виртуальных машин, на которых размещён основной кластер, приводящий к его недоступности;
  • Сбой сети в месте расположения основного кластера, вызывающий прерывание сервиса;

Неподдерживаемые сценарии катастроф

  • Сбои приложений, развернутых внутри кластера global;
  • Потеря данных, вызванная сбоями системы хранения (вне области синхронизации etcd);

Роли Основного кластера и Резервного кластера являются относительными: кластер, который в данный момент обслуживает платформу, считается Основным (DNS указывает на него), а резервный — Резервным. После переключения роли меняются местами.

Примечания

  • Это решение синхронизирует только данные etcd кластера global; данные из registry, chartmuseum или других компонентов не включены;

  • Для удобства устранения неполадок и управления рекомендуется называть узлы в стиле standby-global-m1, чтобы указывать, к какому кластеру принадлежит узел (Основной или Резервный).

  • Восстановление данных приложений внутри кластера не поддерживается;

  • Требуется стабильное сетевое соединение между двумя кластерами для обеспечения надежной синхронизации etcd;

  • Если кластеры основаны на гетерогенных архитектурах (например, x86 и ARM), используйте пакет установки с поддержкой двух архитектур;

  • Следующие пространства имён исключены из синхронизации etcd. Если в этих пространствах создаются ресурсы, пользователи должны выполнять их резервное копирование вручную:

    cpaas-system
    cert-manager
    default
    global-credentials
    cpaas-system-global-credentials
    kube-ovn
    kube-public
    kube-system
    nsx-system
    cpaas-solution
    kube-node-lease
    kubevirt
    nativestor-system
    operators
  • Если оба кластера настроены на использование встроенных реестров образов, контейнерные образы необходимо загружать отдельно в каждый;

  • Если в основном кластере развернут DevOps Eventing v3 (knative-operator) и его экземпляры, те же компоненты должны быть предварительно развернуты в резервном кластере.

Обзор процесса

  1. Подготовить единое доменное имя для доступа к платформе;
  2. Указать домен на VIP Основного кластера и установить Основной кластер;
  3. Временно переключить разрешение DNS на резервный VIP для установки Резервного кластера;
  4. Скопировать ключ шифрования ETCD Основного кластера на узлы, которые впоследствии станут управляющими узлами Резервного кластера;
  5. Установить и включить плагин синхронизации etcd;
  6. Проверить статус синхронизации и выполнять регулярные проверки;
  7. В случае сбоя переключить DNS на резервный кластер для завершения восстановления после катастрофы.

Требуемые ресурсы

  • Единое доменное имя, которое будет Platform Access Address, а также TLS-сертификат и приватный ключ для обслуживания HTTPS на этом домене;

  • Выделенный виртуальный IP-адрес для каждого кластера — один для Основного кластера и другой для Резервного;

    • Предварительно настроить балансировщик нагрузки для маршрутизации TCP-трафика на портах 80, 443, 6443, 2379 и 11443 на управляющие узлы за соответствующим VIP.

Процесс

Шаг 1: Установка Основного кластера

ПРИМЕЧАНИЯ ПО УСТАНОВКЕ DR (Среда восстановления после катастроф)

При установке основного кластера среды DR,

  • В первую очередь, задокументируйте все параметры, установленные при следовании руководству веб-интерфейса установки. Необходимо сохранить некоторые опции одинаковыми при установке резервного кластера.
  • ДОЛЖЕН быть предварительно настроен Пользовательский Load Balancer для маршрутизации трафика, направленного на виртуальный IP. Опция Self-built VIP НЕ доступна.
  • Поле Platform Access Address ДОЛЖНО быть доменом, а Cluster Endpoint ДОЛЖЕН быть виртуальным IP-адресом.
  • Оба кластера ДОЛЖНЫ быть настроены на использование An Existing Certificate (одинакового сертификата), при необходимости запросите легитимный сертификат. Опция Self-signed Certificate НЕ доступна.
  • При установке Image Repository в значение Platform Deployment поля Username и Password НЕ должны быть пустыми; поле IP/Domain ДОЛЖНО быть установлено в домен, используемый как Platform Access Address.
  • Поля HTTP Port и HTTPS Port для Platform Access Address ДОЛЖНЫ быть 80 и 443 соответственно.
  • На второй странице руководства установки (Шаг: Advanced) поле Other Platform Access Addresses ДОЛЖНО включать виртуальный IP текущего кластера.

Обратитесь к следующей документации для завершения установки:

Шаг 2: Установка Резервного кластера

  1. Временно укажите доменное имя на VIP резервного кластера;

  2. Войдите на первый управляющий узел Основного кластера и скопируйте конфигурацию шифрования etcd на все управляющие узлы резервного кластера:

    # Предположим, управляющие узлы основного кластера: 1.1.1.1, 2.2.2.2 и 3.3.3.3
    # управляющие узлы резервного кластера: 4.4.4.4, 5.5.5.5 и 6.6.6.6
    for i in 4.4.4.4 5.5.5.5 6.6.6.6  # Замените IP-адреса управляющих узлов резервного кластера
    do
      ssh "<user>@$i" "sudo mkdir -p /etc/kubernetes/"
      scp /etc/kubernetes/encryption-provider.conf "<user>@$i:/tmp/encryption-provider.conf"
      ssh "<user>@$i" "sudo install -o root -g root -m 600 /tmp/encryption-provider.conf /etc/kubernetes/encryption-provider.conf && rm -f /tmp/encryption-provider.conf"
    done
  3. Установите резервный кластер так же, как основной

ПРИМЕЧАНИЯ ПО УСТАНОВКЕ РЕЗЕРВНОГО КЛАСТЕРА

При установке резервного кластера среды DR, следующие параметры ДОЛЖНЫ быть установлены такими же, как в основном кластере:

  • Поле Platform Access Address.
  • Все поля Certificate.
  • Все поля Image Repository.
  • Важно: убедитесь, что учётные данные репозитория образов и пользователь admin совпадают с теми, что установлены в Основном кластере.

И ОБЯЗАТЕЛЬНО следуйте ПРИМЕЧАНИЯМ ПО УСТАНОВКЕ DR (Среда восстановления после катастроф) из Шага 1.

Обратитесь к следующей документации для завершения установки:

Шаг 3: Включение синхронизации etcd

  1. Настройте балансировщик нагрузки на переадресацию порта 2379 на управляющие узлы соответствующего кластера. Поддерживается ТОЛЬКО TCP-режим; переадресация на уровне L7 не поддерживается.

  2. Зайдите в веб-консоль резервного глобального кластера через его VIP и переключитесь в режим Administrator;

  3. Перейдите в Marketplace > Cluster Plugins, выберите кластер global;

  4. Найдите etcd Synchronizer, нажмите Install, настройте параметры:

    • Используйте интервал синхронизации по умолчанию;
    • Оставьте переключатель логирования отключённым, если не требуется отладка.

Проверьте, что Pod синхронизации запущен в резервном кластере:

kubectl get po -n cpaas-system -l app=etcd-sync
kubectl logs -n cpaas-system $(kubectl get po -n cpaas-system -l app=etcd-sync --no-headers | head -1) | grep -i "Start Sync update"

Когда появится “Start Sync update”, пересоздайте один из pod’ов, чтобы повторно инициировать синхронизацию ресурсов с зависимостями ownerReference:

kubectl delete po -n cpaas-system $(kubectl get po -n cpaas-system -l app=etcd-sync --no-headers | head -1)

Проверьте статус синхронизации:

mirror_svc=$(kubectl get svc -n cpaas-system etcd-sync-monitor -o jsonpath='{.spec.clusterIP}')
ipv6_regex="^[0-9a-fA-F:]+$"
if [[ $mirror_svc =~ $ipv6_regex ]]; then
  export mirror_new_svc="[$mirror_svc]"
else
  export mirror_new_svc=$mirror_svc
fi
curl $mirror_new_svc/check

Объяснение вывода:

  • LOCAL ETCD missed keys: Ключи есть в основном кластере, но отсутствуют в резервном. Часто вызвано GC из-за порядка ресурсов при синхронизации. Перезапустите один pod etcd-sync для исправления;
  • LOCAL ETCD surplus keys: Лишние ключи есть только в резервном кластере. Перед удалением этих ключей из резервного кластера согласуйте с командой эксплуатации.

Если установлены следующие компоненты, перезапустите их сервисы:

  • Log Storage для Elasticsearch:

    kubectl delete po -n cpaas-system -l service_name=cpaas-elasticsearch
  • Monitoring для VictoriaMetrics:

    kubectl delete po -n cpaas-system -l 'service_name in (alertmanager,vmselect,vminsert)'

Процесс восстановления после катастрофы

  1. При необходимости перезапустите Elasticsearch в резервном кластере:

    # Скопируйте installer/res/packaged-scripts/for-upgrade/ensure-asm-template.sh в /root:
    # НЕ пропускайте этот шаг
    
    # переключитесь на пользователя root, если необходимо
    sudo -i
    
    # проверьте, установлен ли Log Storage для Elasticsearch в глобальном кластере
    _es_pods=$(kubectl get po -n cpaas-system | grep cpaas-elasticsearch | awk '{print $1}')
    if [[ -n "${_es_pods}" ]]; then
        # Если скрипт вернул ошибку 401, перезапустите Elasticsearch
        # затем выполните скрипт для повторной проверки кластера
        bash /root/ensure-asm-template.sh
    
        # Перезапустите Elasticsearch
        xargs -r -t -- kubectl delete po -n cpaas-system <<< "${_es_pods}"
    fi
  2. Проверьте согласованность данных в резервном кластере (та же проверка, что и в Шаге 3);

  3. Удалите плагин синхронизации etcd;

  4. Уберите переадресацию порта 2379 с обоих VIP;

  5. Переключите DNS домена платформы на резервный VIP, который теперь становится Основным кластером;

  6. Проверьте разрешение DNS:

    kubectl exec -it -n cpaas-system deployments/sentry -- nslookup <platform access domain>
    # Если разрешение некорректно, перезапустите pod’ы coredns и повторяйте попытки до успеха
  7. Очистите кэш браузера и зайдите на страницу платформы, чтобы убедиться, что она отражает бывший резервный кластер;

  8. Перезапустите следующие сервисы (если установлены):

    • Log Storage для Elasticsearch:

      kubectl delete po -n cpaas-system -l service_name=cpaas-elasticsearch
    • Monitoring для VictoriaMetrics:

      kubectl delete po -n cpaas-system -l 'service_name in (alertmanager,vmselect,vminsert)'
    • cluster-transformer:

      kubectl delete po -n cpaas-system -l service_name=cluster-transformer
  9. Если рабочие кластеры отправляют данные мониторинга в Основной, перезапустите warlock в рабочем кластере:

    kubectl delete po -n cpaas-system -l service_name=warlock
  10. На исходном Основном кластере повторите шаги Включения синхронизации etcd, чтобы превратить его в новый резервный кластер.

Регулярные проверки

Регулярно проверяйте статус синхронизации в резервном кластере:

curl $(kubectl get svc -n cpaas-system etcd-sync-monitor -o jsonpath='{.spec.clusterIP}')/check

Если есть отсутствующие или лишние ключи, следуйте инструкциям в выводе для их устранения.

Загрузка пакетов

При использовании violet для загрузки пакетов в резервный кластер необходимо указывать параметр --dest-repo с VIP резервного кластера. Если этот параметр опущен, пакет будет загружен в репозиторий образов основного кластера, что помешает резервному кластеру устанавливать или обновлять соответствующее расширение.

FAQ

  • Инструкция на случай, если ключ шифрования ETCD резервного кластера не был синхронизирован с ключом основного кластера до установки резервного кластера.
  1. Получите ключ шифрования ETCD на любом управляющем узле резервного кластера:

    ssh <user>@<STANDBY cluster control plane node> sudo cat /etc/kubernetes/encryption-provider.conf

Он должен выглядеть так:

apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
    - secrets
    providers:
    - aescbc:
        keys:
        - name: key1
          secret: MTE0NTE0MTkxOTgxMA==
  1. Объедините этот ключ шифрования ETCD с файлом /etc/kubernetes/encryption-provider.conf основного кластера, убедившись, что имена ключей уникальны. Например, если ключ основного кластера называется key1, переименуйте ключ резервного в key2:

    apiVersion: apiserver.config.k8s.io/v1
    kind: EncryptionConfiguration
    resources:
      - resources:
        - secrets
        providers:
        - aescbc:
            keys:
            - name: key1
              secret: My4xNDE1OTI2NTM1ODk3
            - name: key2
              secret: MTE0NTE0MTkxOTgxMA==
  2. Убедитесь, что новый файл /etc/kubernetes/encryption-provider.conf перезаписывает ВСЕ копии на управляющих узлах обоих кластеров:

    # Предположим, управляющие узлы основного кластера: 1.1.1.1, 2.2.2.2 и 3.3.3.3
    # управляющие узлы резервного кластера: 4.4.4.4, 5.5.5.5 и 6.6.6.6
    
    # Предположим, что 1.1.1.1 уже настроен на использование обоих ключей ETCD,
    # войдите на узел 1.1.1.1 и выполните следующие команды:
    for i in \
        2.2.2.2 3.3.3.3 \
        4.4.4.4 5.5.5.5 6.6.6.6 \
    ; do
        scp /etc/kubernetes/encryption-provider.conf "<user>@${i}:/tmp/encryption-provider.conf"
        ssh "<user>@${i}" '
    #!/bin/bash
    set -euo pipefail
    
    sudo install -o root -g root -m 600 /tmp/encryption-provider.conf /etc/kubernetes/encryption-provider.conf && rm -f /tmp/encryption-provider.conf
    _pod_name="kube-apiserver"
    _pod_id=$(sudo crictl ps --name "${_pod_name}" --no-trunc --quiet)
    if [[ -z "${_pod_id}" ]]; then
        echo "FATAL: could not find pod `kube-apiserver` on node $(hostname)"
        exit 1
    fi
    sudo crictl rm --force "${_pod_id}"
    sudo systemctl restart kubelet.service
    '
    done
  3. Перезапустите kube-apiserver на узле 1.1.1.1

    _pod_name="kube-apiserver"
    _pod_id=$(sudo crictl ps --name "${_pod_name}" --no-trunc --quiet)
    if [[ -z "${_pod_id}" ]]; then
        echo "FATAL: could not find pod `kube-apiserver` on node $(hostname)"
        exit 1
    fi
    sudo crictl rm --force "${_pod_id}"
    sudo systemctl restart kubelet.service