Високосная секунда 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:
- У таймеров высокого разрешения есть внутренние базы времени со смещением относительно системного. Для CLOCK_REALTIME это смещение надо обновлять при каждом изменении часов.
- Вызов
clock_was_set()в этом месте кода убрали ещё в 2007 году. После вставки секунды смещение осталось старым, и таймеры CLOCK_REALTIME стали срабатывать на секунду раньше, чем нужно. - Любой таймер короче секунды срабатывал сразу. Программа снова ставила таймер, он снова срабатывал сразу — и так по кругу. Этот цикл и давал нагрузку.
- Особенно страдали программы, которые ждут на futex с абсолютным таймаутом по реальному времени: JVM, MySQL.
- Состояние держалось, пока кто-то не вызовет
clock_was_set(). Проще всего — черезsettimeofday(), то есть заново выставить время.
Отсюда и обходной путь из письма Штульца:
# найти, кто ест процессор
ps -eo pid,comm,%cpu --sort=-%cpu | head -5
# заново установить текущее время: ядро пересчитает смещения таймеров
date -s "$(date)"Патч отслеживает вставку секунды в update_wall_time() и вызывает clock_was_set(), когда снята блокировка timekeeper.
Кто пострадал
| Компания | Что случилось | Чей отчёт |
|---|---|---|
| Mozilla | Java-сервисы — 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% на сотнях серверов в одну минуту. Что это подсказывает?
- Во всех сервисах одновременно появился баг
- Скорее всего, у всех машин общая внешняя причина: время, сеть, обновление или конфигурация
- Нужно срочно добавить серверов
- Сломались процессоры
Показать ответ
Верный ответ — 2. Одновременность — главный признак. Ищите то, что общее у всех затронутых машин. В 2012 году это было время: секунда 23:59:60 наступила везде в один момент.
Вопрос 2. Почему команда date -s "$(date)" снимала нагрузку?
- Она перезапускала Java
- Установка времени вызывает
settimeofday(), ядро пересчитывает смещения таймеров, и они перестают срабатывать раньше срока - Она отключала NTP
- Она очищала кэш процессора
Показать ответ
Верный ответ — 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, пример настройки размазывания.