Упрощённый сценарий изменения конфигурации kubelet выглядит так: сохранить резервную копию, записать новый файл, перезапустить сервис. Если что-то пошло не так — вернуть копию и повторить перезапуск.

Проблема в формулировке «пошло не так». Файл не записался? Kubelet не запустился? Нода не вернулась в рабочее состояние? Или всё восстановилось, но инструмент не смог сохранить итоговый статус?

Ключевой вопрос здесь другой: в каком состоянии осталась нода после ошибки и чем это подтверждено?

Наличие команды rollback само по себе на него не отвечает. Откату нужен отдельный контракт: условия запуска, точка возврата, критерии успеха и поведение при частичном выполнении.

Резервная копия — ещё не рабочее состояние

Полезно разделить четыре состояния:

  • Желаемая конфигурация — то, что мы собираемся применить
  • Конфигурация на диске — то, что сейчас записано в файле
  • Активная конфигурация — параметры, с которыми работает запущенный kubelet
  • Последняя проверенная рабочая конфигурация, или last-known-good, — состояние, для которого уже выполнены согласованные проверки

В нормальном состоянии они могут совпадать. Во время изменения — не обязаны.

Между заменой файла и перезапуском на диске уже находится новая конфигурация, а процесс продолжает работать со старой. Итоговые параметры kubelet также зависят от аргументов запуска: обычные флаги командной строки имеют приоритет над соответствующими значениями файла конфигурации. Для feature gates действует отдельный порядок объединения.1

Поэтому содержимое одного YAML нельзя автоматически считать активной конфигурацией.

Отсюда первое требование к откату: нужно знать не только какой файл сохранён, но и почему именно его допустимо использовать для восстановления.

Если очередной запуск сделал резервную копию уже повреждённого или ещё не проверенного файла, более свежая дата не делает эту копию лучше предыдущей.

И last-known-good — не пожизненная гарантия. Это конфигурация, проверенная в определённом окружении. Если одновременно изменились версия kubelet, аргументы запуска или другое состояние ноды, прежние результаты проверки могут уже не подходить.

Подготовка к откату начинается до изменения

Самая неприятная точка отказа находится между изменением системы и записью сведений об этом изменении.

Файл уже заменён, а инструмент ещё не сохранил, откуда его восстанавливать. Или kubelet уже перезапущен, но выполнение оборвалось до проверки результата.

Поэтому до первой изменяющей операции должны быть доступны сведения, необходимые для восстановления:

  • какая конфигурация была исходной
  • где находится её резервная копия
  • как проверить целостность копии
  • к какой операции она относится

Саму копию тоже нужно проверить до использования. Наличие пути недостаточно: файл может отсутствовать, быть недоступным или содержать не те данные.

Новая конфигурация проходит предварительные проверки отдельно. Корректный YAML подтверждает только корректность формата. Он не доказывает совместимость значений с версией kubelet и окружением ноды.

Атомарная замена файла полезна, но решает лишь часть задачи. rename может атомарно заменить один файл в пределах файловой системы, но не объединяет замену конфигурации, перезапуск сервиса и запись состояния операции в общую транзакцию.2

Надёжность здесь определяется не отсутствием промежуточных состояний, а возможностью распознать их и продолжить работу после сбоя.

Что подтверждает успешное применение

Один зелёный сигнал редко покрывает весь результат. У каждой проверки своя область ответственности.

Файл содержит ожидаемые данные

Контрольная сумма позволяет проверить, что на диске находятся ожидаемые байты. Это полезно и после применения, и после восстановления.

Но совпадение контрольных сумм не доказывает, что работающий kubelet прочитал этот файл.

Отдельно нужно различать несовпадение и невозможность проверки. Ошибка чтения файла или выполнения команды — это не пустая контрольная сумма, а отсутствие достоверного результата.

Сервис запущен

systemctl is-active kubelet проверяет состояние сервиса с точки зрения systemd.3 Это необходимый сигнал, но не проверка конкретных параметров kubelet и не доказательство устойчивой работы.

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

Нода доступна кластеру

Node Ready — отдельный сигнал. Он отражает состояние ноды, но не удостоверяет, что применена нужная редакция конфигурации.

Здесь важна свежесть наблюдений. Состояние Node и объект Lease обновляются независимо, поэтому сохранённое Ready=True нельзя считать подтверждением восстановления после только что выполненного перезапуска.4

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

Kubelet использует ожидаемые параметры

Kubernetes документирует endpoint /configz для просмотра итоговой конфигурации работающего kubelet.1 Он помогает проверить параметры процесса, а не только файл на диске.

Сравнивать стоит управляемые поля с учётом значений по умолчанию и переопределений.

Доступ к такой проверке нужно продумать заранее. В частности, широкое разрешение nodes/proxy нельзя считать безобидным доступом только на чтение: оно открывает доступ к kubelet API и может позволить выполнять действия с контейнерами.5

Если нужную проверку выполнить невозможно, результат остаётся неподтверждённым. Подменять его успехом по косвенному признаку нельзя.

Откат должен проходить собственную проверку

Операция применения отвечает на вопрос:

Перешла ли нода на целевую конфигурацию и сохранила ли требуемую работоспособность?

Операция отката отвечает на другой:

Вернулась ли нода к выбранной точке восстановления и подтверждена ли её работоспособность?

Возврат файла — только часть второго ответа.

После восстановления нужно проверить целостность данных, при необходимости активировать восстановленную конфигурацию, убедиться в работе kubelet и проверить параметры. Категории проверок остаются теми же, но ожидаемым результатом становится точка возврата, а не неудачная целевая конфигурация.

Полезно различать три исхода:

ИсходЧто известно
Применение не удалось, откат подтверждёнЦелевая конфигурация не принята, нода восстановлена
Применение не удалось, откат не удалсяЕсть подтверждённая ошибка восстановления
Применение не удалось, результат отката неизвестенНаблюдений недостаточно, чтобы определить состояние ноды

Третий исход особенно важен при потере связи или таймауте. Отсутствие ответа не доказывает ни выполнение команды, ни её невыполнение.

Успешная команда отката может завершиться с кодом 0. Но вся операция применения от этого не становится успешной: первоначальная цель не достигнута. В отчёте должны сохраняться оба результата.

Ошибка операции не всегда означает ошибку восстановления

Есть ещё один случай, который легко потерять за общим статусом failed.

Восстановленная конфигурация уже активна. Проверки kubelet прошли. Но инструмент не смог записать итоговое состояние операции.

Это ошибка, и скрывать её нельзя. Однако сообщение «откат не выполнен» тоже будет неверным: восстановление состоялось, не завершилась его фиксация.

Здесь нужно разделять наблюдаемое состояние ноды и состояние выполнения операции.

Такое разделение влияет и на повторный запуск. Он должен сначала выяснить, что уже произошло, а не безусловно повторять копирование и перезапуск. Иначе ошибка записи отчёта превращается в лишнее вмешательство в уже восстановленную ноду.

По той же причине нельзя считать повторный откат безопасным только потому, что он второй раз возвращает тот же файл. Нужно проверить, не изменил ли конфигурацию другой процесс и действительно ли повторный перезапуск необходим.

Кто выполнит откат, если kubelet не работает

Механизм восстановления нужно проверять вместе с его зависимостями.

Если для выполнения команд используется kubectl exec, такая цепочка зависит от доступности kubelet. Kubernetes использует соединения от API server к kubelet для операций с работающими контейнерами.6 Отказ kubelet может одновременно лишить инструмент привычного канала восстановления.

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

Таким исполнителем может быть заранее предусмотренный локальный механизм или отдельный административный канал. Его доступность нужно проверять именно при неработающем kubelet.

Здесь же проходит граница между ручным и автоматическим откатом. Наличие отдельной команды не означает, что она автоматически выполнится после неудачного применения. Автоматический запуск требует собственных условий срабатывания, ограничений и правил остановки.

Что откат конфигурации не обещает

Возврат YAML не равен возврату всей ноды в прошлое.

Некоторые изменения затрагивают дополнительное состояние. Например, смена политики CPU Manager требует отдельной процедуры и работы с сохранённым состоянием менеджера.7 Она не сводится к редактированию одного параметра.

Поэтому у механизма отката должен быть явно ограниченный набор поддерживаемых изменений. Всё, что требует миграции состояния, отдельной подготовки нагрузок или дополнительных действий, нельзя молча включать в обещание «вернём конфиг, если что».

Восстановление kubelet также не означает автоматического разрешения планировать новые поды. uncordon — отдельное действие, возвращающее ноду в планирование.8 Его следует выполнять только после нужных проверок и с учётом того, почему нода была выведена из работы.

После отката нужно определить и судьбу неудачной целевой конфигурации. Если следующий цикл автоматизации снова применит её, восстановление окажется лишь паузой между одинаковыми сбоями.

Неудачная редакция должна оставаться остановленной до отдельного решения, а не автоматически получать ещё одну попытку только потому, что нода снова доступна.

Какие проверки нужны на стенде

Проверять следует не только обычный сценарий, но и остановку на границах между действиями.

СценарийОжидаемое поведение
Резервная копия отсутствует или поврежденаВосстановление не начинается с недостоверными данными
Выполнение оборвалось после замены файлаСледующий запуск распознаёт незавершённую операцию
Файл восстановлен, но kubelet не запускаетсяВосстановление файла не выдаётся за успешный откат
Проверка завершилась таймаутомРезультат отмечается как неподтверждённый
Нода восстановлена, но итоговый статус не записалсяСостояние ноды и ошибка фиксации результата различаются
Откат запущен повторно или параллельно с изменениемНет слепого перезаписывания более нового состояния

Это критерии для испытаний механизма, а не утверждение, что любая реализация уже их выполняет.

Вывод

Резервная копия отвечает на вопрос «что можно вернуть». Команда перезапуска — «как попытаться активировать возвращённое».

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

Откат завершён не тогда, когда инструмент выполнил последнюю команду, а когда состояние ноды установлено с нужной достоверностью — либо честно зафиксировано, что установить его не удалось.