Временные сложности

‘If you knew Time as well as I do,’ said the Hatter, ‘you wouldn’t talk about wasting IT.’          

‘Если бы ты знала Время как знаю его я’ – произнес Шляпник, – ‘ты бы никогда не стала говорить о разбазаривании информационных технологий.’

Льюис Кэрролл.
На самом деле – Чарльз Лютвидж Доджсон.
Весьма фривольный перевод.

Всем привет, это снова я – krokokot.

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

  • виртуальная машина (ВМ) при старте получает время из эмулируемого хостом BIOS/RTC;
  • в дальнейшем большинство ОС не сверяются регулярно с RTC (Real Time Clock, часы реального времени, микросхема с батарейкой в железном компьютере, эмулируемая в гипервизоре), а сами ведут счет времени;
  • так как ВМ может ожидать освобождения виртуального процессора непредсказуемое количество времени – время в ней дрифтует; чаще отстает, но иногда и забегает вперед;
  • по перечисленным выше причинам время в ВМ нужно периодически принудительно синхронизировать, либо с помощью API-интерфейса к гипервизору (VMWare Tools, Hyper-V integration services), либо настройкой NTP клиента.

Если статья про VMWare – можно увидеть упоминание о том, что даже при выключенном чекбоксе «Synchronize guest time with host» при определенных действиях с ВМ время в ней все равно принудительно синхронизируется (VMWare Tools, конечно) с хостом, и как этого избежать если очень хочется.

Тот самый чекбокс.

Далее в статье, как правило, идет перечисление команд/утилит API-интерфейса к гипервизору и примеры настройки NTP клиента. Всё.

Но постойте, а как же промежуток с момента старта ВМ до момента, когда API гипервизора станет активным? А если NTP сервер недоступен? И что происходит с временем с момента остановки ВМ до момента старта? Вопросы отнюдь не праздные, ибо автор не раз сталкивался с ситуациями, когда ВМ с Windows, размещенная на облачном сервере c дешевым, а потому – очень популярным гипервизором KVM, «вдруг» после стопа и последующего старта начинает показывать время со сдвигом на установленный часовой пояс. Хотя при обычной перезагрузке со временем все в порядке! WTF??

Обычно, решением для нещепетильного администратора напрашивается win32tm /resync или его линуксовый аналог, присунутый в планировщик. Но что если администратор щепетильный, а до задачи в планировщике (или при временной недоступности NTP-сервера) успевает стартануть СУБД, в которой слишком большое или вообще отрицательное время между событиями А и Б рушит бизнес-логику, и вообще – зашквар? Пробуем разбираться.

‘И идет ли он на свист? И если да – то ЗАЧЕМ?’
Алан Александр
 Милн. На самом деле.
Перевод – Борис Заходер.

Итак, первый вопрос: откуда ВМ берет время при старте? Разумеется, с хоста. Точнее – гипервизор эмулирует BIOS (или UEFI – не важно, под BIOS тут подразумеваем и UEFI тоже) и при старте этого окружения устанавливает там время. Но вот беда – время на хосте как правило UTC. И, как предполагал автор в начале исследования, гипервизор в момент старта ВМ отдает единственное известное ему время – UTC. Ладно Линукс, он умеет работать с UTC временем в BIOS, через «хак и тюнинг», конечно. А как быть с Windows? Она-то, в отличие от «похаченного» линукса, всегда хранит в RTC локальное время! И любой владелец компьютера с Windows может в этом убедиться, достаточно перезагрузить компьютер и зайти в BIOS. И заодно не найти там настройки “часовой пояс”.

В этот момент админы VMWare с не одной сотней (тысяч?:) ВМ с Windows сказали мне: «Но у меня все работает, не пори чушь!». Сорри, пипл, но откуда гипервизор знает, что вот этой ВМ надо отдать время с часовым поясом +5, а вот этой, рядом: +3? VMWare Tools? Сомневаюсь… И оказываюсь прав.

По факту оказывается, что производители гипервизоров пытаются решать эту проблему каждый по-своему. VMWare, к примеру, в ESXi просто и элегантно запоминает в файле NVRAM разницу между временем хоста и временем в эмулируемом BIOS/RTC. В какие конкретно моменты это делается – установить не удалось. Но, полагаю, как минимум при рестарте ВМ и при её выключении. Ну и при изменении системного времени в ОС в ВМ. Пруф: создаем виртуальную машину без ОС, ставим чекбокс «Зайти в BIOS при следующем старте». Запускаем ВМ и видим там время хоста – UTC. Меняем время, к примеру, +5 часов, нажимаем F10. Можно даже поставить ОС и поменять время в ней – не важно. Останавливаем ВМ. При следующем старте ВМ (с тем же чекбоксом) видим время в BIOS: +5 часов. Все как на «железном компьютере», все работает как ожидает массовая ОС без всяких «хаков и тюнинга».

Если остановить ВМ и ради эксперимента вручную сдвинуть время хоста – при старте увидим этот сдвиг и в BIOS. Это опровергает немного бредовое, но все же имевшее право на короткую жизнь предположение, что ESXi продолжает независимо «тикать часами» в файле NVRAM в каждой из зарегистрированных, хотя и остановленных ВМ. J Все проще и железобетоннее – взять время хоста, сдвинуть на значение, запомненное в NVRAM, запустить ВМ. Всё. Дальше пусть разбираются ОС, юзер, VMWare Tools, NTP клиент или лысые черти.

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

Но как показывает практика автора с облачными провайдерами, вынесенная в начало статьи – не все гипервизоры «одинаково полезны» в этом смысле одинаковы. Авторы того же «бесплатного и потому страшно популярного» KVM пошли своим путем. В нем для каждой ВМ администратор волен указать в конфиге ВМ, какое именно время отдавать при старте ВМ. И это, наверное, хорошо и вообще – Linux way.

А по умолчанию там – UTC. И что с этим делать нам, вымирающему 🙂 виду админов–виндузятников, волей или неволей попавших под железную пяту виртуализации бесплатными гипервизорами, если ковыряться в конфигах ВМ не хочется? Или невозможно, т.к. мы не знаем, какая таймзона взбредет в голову администратору ВМ после установки ОС? Или мы вообще – просто клиент массового сервиса облачных вычислений, типа моего любимого Хетцнера? Писать в поддержку, чтобы прикрутили к [двадцати [сотням]] ВМ кастомные конфиги? Результат немного предсказуем… Смириться с w32tm /resync при каждом старте ОС? А если ВМ ребутнется, NTP-клиент «немного протормозит», и автоматически фиксируемый системой контроля доступа промежуток времени между входом и выходом сотрудников фирмы окажется отрицательным, как и зарплата/премия админа по результатам разбора полетов? И это самый безобидный сценарий, более жёсткие можете придумать сами… Неужели за столько лет прогрессивное человечество не научило Windows понимать UTC в RTC?

‘Не верю!’
К. С. Станиславский.
На самом деле – К. С. Алексеев.

Согласно некоторым, широко уважаемым в узких кругах источникам, цитирую «Windows does not support UTC time in the BIOS», и довольно много «взрослого и опытного народа» держит это в памяти, и даже иногда цитирует. Но, пользуясь бессмертной фразой великого режиссера, автору (не без помощи коллег, спасибо им большое) таки-удалось найти столь же желанную и очевидную, сколь и малоизвестную, по крайней мере – в среде моих коллег-виртуализаторщиков, настройку в реестре! Так что нужно быть критичным к статьям, особенно восьмилетней давности, даже на уважаемых источниках.

Итак, имеем Windows в гипервизоре, выдающем UTC в RTC при старте. Вставляем в реестр заветное:

Важное мелким шрифтом: автор проверил работу этого registry hack в Windows 2012R2 с последними обновлениями на момент написания статьи. По непроверенным слухам может не работать в предшественниках Windows 2008. Использовать на свой страх и риск, результаты проверки – в комментарии, pls.

Результат: при старте ВМ в «похатченной» Windows имеем в таком гипервизоре правильное время «с самого начала». Именно при старте из состояния «выключено». А вот при первой перезагрузке после установки вышеприведенного параметра в реестр мы получим что? Правильно – сдвиг на установленный в системе часовой пояс. Самые догадливые уже поняли, почему так происходит. И почему в прошлом у автора происходили непонятки со сдвигом времени на часовой пояс именно после стопа и старта ВМ. И снова правильно – при рестарте ВМ время в эмулированном гипервизором RTC не сбрасывается, а продолжает «идти на свист», как Слонопотам у Милна, и потому остается локальным, как его и прописала туда ОС. И поэтому же при рестарте после установки заветного registry hack’а Windows взяла локальное время из RTC, но посчитала его UTC. А при стопе и старте на KVM и аналогах, не столь «заботливых» как ESXi, в эмулированном RTC сидит UTC.

Далее можем синхронизировать время в ВМ хоть с хостом через API гипервизора, хоть с NTP источником. При следующем и рестарте, и стопе-старте ВМ время в системе будет правильным. Разумеется, если оно правильное на хосте. Но это уже совсем другая история…

Leave a Reply

Your email address will not be published. Required fields are marked *