kai.kzLab

Високосная секунда 30 июня 2012 года: как одна лишняя секунда загрузила процессоры Linux-серверов по всему миру

Команда KAI Lab · · 8 мин чтения

В ночь на 1 июля 2012 года к всемирному времени UTC добавили секунду 23:59:60, и Linux-серверы по всему миру внезапно загрузили процессоры до 100%. Причина — ошибка в ядре: при вставке секунды подсистема времени не уведомила таймеры высокого разрешения (hrtimer), таймеры по часам CLOCK_REALTIME начали срабатывать на секунду раньше, и программы на Java, MySQL и другие закрутились в цикле ожидания.

Лечилось без перезагрузки одной командой date -s "$(date)": повторная установка времени сбрасывала ошибочное состояние. Пострадали Mozilla, а по данным прессы — Reddit, LinkedIn, Yelp и другие. В Австралии час не работала система регистрации Amadeus Altea, и сотрудники Qantas и Virgin Australia регистрировали пассажиров вручную. Google этот сбой обошёл: с 2008 года он «размазывает» лишнюю секунду по нескольким часам.

Главное о сбое в одной таблице

ВопросОтвет
Когда30 июня 2012, 23:59:60 UTC (в Алматы — около 6 утра 1 июля)
Что сломалосьядро Linux: при вставке секунды не вызывалась функция clock_was_set(), таймеры CLOCK_REALTIME срабатывали на секунду раньше
Симптомвнезапная загрузка CPU в Java, MySQL и других программах с таймаутами futex
Кто пострадалMozilla (Hadoop, ElasticSearch, Socorro); по данным прессы — Reddit, LinkedIn, Yelp, Foursquare, StumbleUpon; Amadeus Altea у Qantas и Virgin Australia
Обходной путьdate -s "$(date)" или перезагрузка
Исправлениепатч Джона Штульца (John Stultz) в рассылке ядра 1 июля 2012
Кто не пострадалGoogle — размазывал високосную секунду с 2008 года

Что такое високосная секунда

Земля вращается неравномерно, и астрономическое время постепенно расходится с атомным. Чтобы UTC не уходило от вращения Земли, в него иногда вставляют лишнюю секунду: после 23:59:59 идёт 23:59:60, и только потом 00:00:00. О такой секунде объявляют заранее, серверы узнают о ней по NTP, а вставляет её ядро. В журнале это выглядит так:

dmesg | grep -i "leap second"
# Clock: inserting leap second 23:59:60 UTC

Для большинства программ високосная секунда — редкое событие, которое никто не тестирует. Прошлая была в конце 2008 года, три с половиной года назад.

Что сломалось в ядре

Разобрался в ошибке мейнтейнер подсистемы времени Джон Штульц. 1 июля 2012 года он отправил в рассылку ядра (LKML) патч с описанием: после вставки секунды в системах начинаются всплески нагрузки, связанные с futex, обычно в MySQL, Firefox, Thunderbird и Java. Причина — секунду добавляли, не вызывая clock_was_set(), то есть не сообщая подсистеме hrtimer, что время изменилось.

Механизм подробно разобрал Джонатан Корбет в LWN:

  1. У таймеров высокого разрешения есть внутренние базы времени со смещением относительно системного. Для CLOCK_REALTIME это смещение надо обновлять при каждом изменении часов.
  2. Вызов clock_was_set() в этом месте кода убрали ещё в 2007 году. После вставки секунды смещение осталось старым, и таймеры CLOCK_REALTIME стали срабатывать на секунду раньше, чем нужно.
  3. Любой таймер короче секунды срабатывал сразу. Программа снова ставила таймер, он снова срабатывал сразу — и так по кругу. Этот цикл и давал нагрузку.
  4. Особенно страдали программы, которые ждут на futex с абсолютным таймаутом по реальному времени: JVM, MySQL.
  5. Состояние держалось, пока кто-то не вызовет clock_was_set(). Проще всего — через settimeofday(), то есть заново выставить время.

Отсюда и обходной путь из письма Штульца:

# найти, кто ест процессор
ps -eo pid,comm,%cpu --sort=-%cpu | head -5
# заново установить текущее время: ядро пересчитает смещения таймеров
date -s "$(date)"

Патч отслеживает вставку секунды в update_wall_time() и вызывает clock_was_set(), когда снята блокировка timekeeper.

Кто пострадал

КомпанияЧто случилосьЧей отчёт
MozillaJava-сервисы — Hadoop, ElasticSearch, Socorro, HBase — загрузили процессоры. Баг «Java is choking on leap second» завели сразу после полуночи по ГринвичуBugzilla Mozilla
Amadeus, Qantas, Virgin AustraliaСистема Altea была недоступна час, пассажиров регистрировали вручную. Amadeus подтвердила: ошибка в ядре Linux, вызванная високосной секундойThe Register со ссылкой на Amadeus
Reddit, LinkedIn, Yelp, Foursquare, StumbleUponСообщалось, что их серверы задела та же ошибкаThe Register

Mozilla лечила так: останавливала ntp, заново выставляла дату командой date и перезапускала Java-сервисы. В баге отмечено, что нагрузка JVM падала сразу после установки даты. Часть кластеров HBase потом обновили и перезагрузили.

Leap smear: как Google обходит високосную секунду

Пока одни ловили цикл в ядре, у Google лишней секунды на серверах просто не было. Вместо скачка часов Google «размазывает» секунду: несколько часов подряд серверы времени отдают часы, которые идут чуть медленнее. К концу окна часы отстают ровно на секунду, а момента 23:59:60 не существует вовсе.

Как этот приём вышел наружу:

  • 2008 год. Google начинает размазывать високосные секунды внутри компании. Первый вариант — косинусное размазывание за 20 часов до вставки, с 04:00 до 00:00.
  • Сентябрь 2011 года. Google рассказывает о приёме в официальном блоге: пост «Time, technology and leaping seconds» инженера SRE Кристофера Паскоу.
  • Конец 2016 года. Google открывает публичные NTP-серверы time.google.com, которые отдают размазанное время всем желающим, — как раз перед високосной секундой 31 декабря 2016 года.
  • Сейчас. Стандарт Google — линейное размазывание за 24 часа, с полудня до полудня UTC, частота меняется примерно на 11,6 ppm. По словам Google, то же размазывание использует AWS.

Размазать секунду можно и у себя. У chrony для этого есть готовая конфигурация сервера:

# /etc/chrony/chrony.conf на своих серверах времени
leapsecmode slew
maxslewrate 1000
smoothtime 400 0.001024 leaponly

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

Уроки для DevOps

1. Время — такая же зависимость, как сеть и DNS

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

2. Нагрузка выросла везде сразу — ищите общую причину

Внезапная загрузка CPU на сотнях машин в одну минуту почти никогда не означает, что во всех сервисах одновременно появился баг. Ищите общее: время, сеть, обновление, конфигурацию. Как отличить загрузку процессора от ожидания диска, мы разбирали в статье про load average в Linux.

3. Знать механизм — значит чинить без перезагрузки

Команда date -s "$(date)" выглядит как шаманство, пока не знаешь, что она вызывает settimeofday(), а та — пересчёт смещений таймеров. Mozilla и другие вернули сервисы за минуты, не перезагружая кластеры.

4. Редкие события требуют плановой подготовки

О високосной секунде известно за месяцы. Это повод заранее проверить версии ядра и JVM, выбрать режим chrony или ntpd и договориться, кто дежурит в полночь по UTC. Та же логика работает для всего, что случается по календарю: 29 февраля сломало облако Microsoft, разбор — в статье про сбой Azure 2012, а истёкший сертификат — сеть Ericsson, см. сбой Ericsson 2018.

Что проверить у себя завтра:

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

Реши сам

Два вопроса по этому сбою. Ответы — под спойлером.

Вопрос 1. CPU вырос до 100% на сотнях серверов в одну минуту. Что это подсказывает?

  1. Во всех сервисах одновременно появился баг
  2. Скорее всего, у всех машин общая внешняя причина: время, сеть, обновление или конфигурация
  3. Нужно срочно добавить серверов
  4. Сломались процессоры
Показать ответ

Верный ответ — 2. Одновременность — главный признак. Ищите то, что общее у всех затронутых машин. В 2012 году это было время: секунда 23:59:60 наступила везде в один момент.

Вопрос 2. Почему команда date -s "$(date)" снимала нагрузку?

  1. Она перезапускала Java
  2. Установка времени вызывает settimeofday(), ядро пересчитывает смещения таймеров, и они перестают срабатывать раньше срока
  3. Она отключала NTP
  4. Она очищала кэш процессора
Показать ответ

Верный ответ — 2. Ошибка была в том, что при вставке секунды не вызывался clock_was_set(). Установка времени вызывает его, и таймеры CLOCK_REALTIME снова срабатывают вовремя.

Частые вопросы

Когда была високосная секунда 2012 года? 30 июня 2012 года в 23:59:60 UTC. В Казахстане это было утро 1 июля.

Почему из-за одной секунды загружался процессор? Ядро не пересчитало смещение таймеров после вставки секунды. Таймеры по реальному времени срабатывали на секунду раньше, короткие — сразу, и программы крутились в цикле ожидания.

Помогала ли перезагрузка? Да, но проще было заново выставить время командой date -s "$(date)": она вызывает clock_was_set() и снимает нагрузку без перезапуска сервера. Позже ошибку исправили в ядре.

Что такое leap smear? Приём, при котором лишнюю секунду не вставляют скачком, а распределяют на несколько часов, слегка замедляя часы. Google использует его с 2008 года, сейчас — линейно за 24 часа, с полудня до полудня UTC.

Пройти похожий сбой самому

В симуляторе DevOps KAI Lab второй месяц посвящён Linux. В нём есть разбор этого сбоя и тикет «Сервер файлов загружен на 350%», где нужно понять, откуда нагрузка. Все разборы собраны в подборке 18 сбоев, которые должен знать DevOps-инженер.

Начать можно бесплатно: тест навыков и первые задания первого месяца.

Источники

  • LKML, John Stultz. [[PATCH] [RFC] Potential fix for leapsecond caused futex related load spikes](https://lkml.iu.edu/hypermail/linux/kernel/1207.0/00026.html), 01.07.2012 — симптомы, причина, обходной путь, суть патча.
  • LWN, Jonathan Corbet. Leaping seconds and looping servers, 02.07.2012 — механизм ошибки в hrtimer.
  • Mozilla Bugzilla. Bug 769972 — Java is choking on leap second, заведён в ночь на 1 июля 2012 — какие сервисы Mozilla пострадали и как их чинили.
  • The Register, Gavin Clarke. Leap second bug cripples Linux servers at airlines, Reddit, LinkedIn, 02.07.2012 — Amadeus, Qantas, Virgin Australia, список пострадавших сайтов.
  • Google. Leap Smear — размазывание с 2008 года, текущий стандарт на 24 часа, использование в AWS.
  • The Register. Google turns on free public NTP servers that smear time, 02.12.2016 — запуск публичных NTP-серверов Google с размазанным временем.
  • Google, Christopher Pascoe. Time, technology and leaping seconds, 15.09.2011 — первый публичный рассказ о приёме.
  • chrony. chrony.conf(5) — leapsecmode, smoothtime, пример настройки размазывания.

Читать дальше