Диагностика скрытых процессов - передовой опыт технической команды Alibaba

Ло Цзяньлун, старший инженер по послепродажному обслуживанию из технической группы Alibaba, помогал устранять неполадки с процессором клиента, когда проблема внезапно исчезла сама по себе. Теперь он рассказывает о том, что обнаружил, когда начал копать немного глубже, и о том, почему стоит заглянуть за поверхность.

«Привет, Алибаба, что меня награждает?»

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

Как показано в третьей строке следующего графика, основная статистика использования ЦП состоит из восьми показателей: пользовательское время ЦП (us), системное время ЦП (sy), удобное время ЦП пользователя (ni), время простоя ЦП (id), io wait Время ЦП (wa), время ЦП, потраченное на обработку аппаратных прерываний (привет), время ЦП, потраченное на обработку программных прерываний (si), и время кражи (st). Теоретически сумма этих восьми показателей должна составлять 100%. Вместе id и wa отражают время простоя ЦП. Чем меньше их сумма, тем загруженнее процессор. В случае с сервером этого клиента идентификаторы id и wa записали суммарное значение 0, что означает, что загрузка ЦП была на уровне 100%, при этом львиная доля использования ЦП приходилась на ni.

Помимо общей статистики использования ЦП, показанной в третьей строке, в верхней части также учитывается использование ЦП процессами в столбце ЦП. Рассматриваемый сервер имеет 16 ядер, поэтому загрузка ЦП каждым процессом (многопоточность) может превышать 100%. В то же время общая загрузка ЦП всеми процессами не может превышать 1600% (в среднем возвращаясь к 100% для каждого ядра).

Самая интересная часть этой проблемы заключалась в том, что выполнялись 787 процессов, в то время как общая загрузка ЦП оставалась намного ниже максимального значения 1600%.

Проблема исчезает…

Как раз когда я собирался глубже вникнуть в проблему, сервер перезапустился. Как-то после перезагрузки проблема просто исчезла! Однако вопросов клиента не последовало. Он настоял на том, чтобы я объяснил, почему ЦП сервера был полностью загружен.

Стоит отметить, что мы часто связываем причину неизвестной проблемы с ее «черным ящиком». Вот почему многие клиенты обращают внимание на виртуальный или физический уровень, когда им сложно объяснить, что происходит. В худшем случае клиенты могут даже задаться вопросом, поставила ли Alibaba Cloud скомпрометированный продукт.

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

Изучение метрики Ni

В первом разделе этой статьи я упоминал, что ni означает использование ЦП, заявленное процессами пользовательского пространства с высокими значениями nice. Но что такое хорошее значение? Проще говоря, хорошие значения представляют собой приоритет, присвоенный процессу для использования ресурсов ЦП. Каждый процесс имеет определенную ценность. Чем выше значение nice, тем ниже приоритет процесса при использовании ресурсов ЦП, что приводит к сокращению процессорного времени. Метрика ni учитывает использование ЦП всеми процессами пользовательского пространства со значениями nice больше 0.

Обычно 0 - это хорошее значение процесса по умолчанию. Когда процессам требуется более высокий приоритет, мы уменьшаем их значения nice, и другие процессы могут принимать более низкий приоритет. Например, запуск компилятора gcc для компиляции ядра может занять несколько часов. В ответ мы можем увеличить значение nice этого процесса gcc.

Linux делит использование ЦП в истинном пользовательском режиме для отображения процессов на два раздела: ni для процессов с хорошими значениями больше 0 и us для тех, у которых хорошие значения меньше 0.

Проведите тест на содержание никеля для себя

Давайте проверим вышеупомянутые теории с помощью простого теста. Мы можем использовать оператор for для создания простой программы с бесконечным циклом и использовать objdump для просмотра скомпилированной программы сборки. Эта сборка проста. Первые две строки подготавливают указатели стека, третья строка инициализирует переменную, помещенную в rbp-0x4 стека, и переменная получает повторяющиеся приращения в четвертой и пятой строках.

00000000004004ed ‹main›:
4004ed: 55 push% rbp
4004ee: 48 89 e5 mov% rsp,% rbp
4004f1: c7 45 fc 00 00 00 00 movl $ 0x0, -0x4 (% rbp)
4004f8: 83 45 fc 01 addl $ 0x1, -0x4 (% rbp)
4004fc: eb fa jmp 4004f8 ‹main + 0xb›
4004fe: 66 90 xchg % ax,% ax

Как только процесс цикла отправляется в ЦП, ЦП полностью загружается. На следующем графике показаны два дисплея: левый рисунок показывает сценарий, когда nice равен 0, а правый - сценарий, когда nice равен 19. Значения nice процессов можно увидеть в столбце NI под графиками.

Как использование ЦП распределяется и распределяется между ядрами, показано ниже:

Я хотел помочь заказчику понять теории, относящиеся к ni, и мой вывод - что проблема не имеет ничего общего с физической машиной. Заказчик не купил. Он подчеркнул, что перед запуском машины он проверил использование ЦП всеми процессами и был уверен, что нет никаких аномальных признаков. Было запущено более 100 java-процессов, все с очень низкой загрузкой ЦП.

Введите магию временной последовательности

Иногда мы можем потеряться, решая проблемы с зависанием системы. Только представьте себе сложную систему, в которой одновременно работают десятки тысяч процессов. Если система зависает, многие из этих процессов запутываются. Затем нам нужно выяснить отношения зависимости между этими процессами и определить, какие из них нарушают спокойствие, а какие - жертвы. Это в основном зависит от того, как процессы удерживают ресурсы и ждут их.

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

Там, где этот подход не работает, приходит другой. Мы можем проанализировать временную последовательность процессов, переходящих в состояние ожидания. Это называется «магией временной последовательности».

Обнаружена горная программа

Мне некуда было деваться (проблема не могла быть отображена снова), и магия временной последовательности дала мне выход. Сначала я проверил журнал sar и подтвердил, что загрузка процессора достигла 100% в 6:40 утра 29 апреля. Я просмотрел почти все системные файлы и нашел два файла конфигурации, которые были созданы всего за минуту до 6:39. am Каталог, в котором хранились эти два файла, содержал два подозрительных файла библиотеки: libxmr-stak-ca и libxmr-stak-backend.a. Быстрый поиск в Интернете показал, что это были программы, используемые для добычи монет Monero.

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

Три распространенных метода сокрытия процессов Linux

Если предположить, что заказчик был прав, тогда вопрос заключался в том, какие методы сокрытия процессов Linux могут препятствовать отображению их деталей в ps или топовых выходах? Для этой цели применимы три общих метода: изменение pid на 0 при создании процессов в ядре, прямое изменение кода ps и top и подключение функций readdir и opendir в libc. (Для реализации ps и top используются функции libc, такие как readdir и opendir, для прямого доступа к файлам / proc и их подкаталогам.)

Я внезапно вспомнил другой файл, который также был изменен в 6:39 утра - ld.so.preload. Когда я впервые проверил этот файл, я обнаружил, что в него записан libjdk.so. В то время я считал само собой разумеющимся, что этот файл связан с java, и игнорировал его.

Первопричина появляется!

С этого момента вся проблема начала распутываться. В 6:39 кто-то добавил файл библиотеки в ld.so.preload. После этого при запуске все процессы загружали эту библиотеку перед загрузкой других. Результат? Каждый раз, когда процесс вызывал внешнюю функцию, предназначенную для реализации в другой библиотеке, эта функция также была реализована в этой предварительно загруженной библиотеке. Это означало, что динамические ссылки сначала должны были использовать функцию, определенную в предварительно загруженной библиотеке.

Прошли годы с тех пор, как я последний раз использовал этот метод для записи трассировки opengl. После перехода на Windows эти навыки работы с Linux практически исчезли из моей памяти. С помощью ld.so.preload мы можем создавать инструменты фильтрации, которые включают фильтрацию, отслеживание, проверку параметров и многое другое. Чтобы убедиться, что процессы работают нормально, одноименные функции фильтрации в конечном итоге вызывают исходную функцию.

Результаты проверки показали, что все перезапущенные системные процессы загрузили файл libjdk в свои адресные пространства. На следующем изображении показан вывод / proc / ‹pid› / maps при чтении bash:

Маленькие хитрости с libjdk

Библиотека libjdk не имеет ничего общего с java. Он небольшой, и его легко разобрать и изучить настолько, что мы даже можем понять его поведение, прочитав код сборки. Как и предполагалось, библиотека подключила такие функции, как readdir, и отфильтровала результаты чтения папки / proc. В результате заказчик получал только отфильтрованные результаты при запуске top или ps. Поразмыслив, я решил, что не стоит углубляться в коды компиляции libjdk. Вместо этого мы можем рассмотреть строки, включенные в файл библиотеки, которые могут примерно сказать нам, что делает библиотека.

Рассмотрение дела

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

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

Alibaba Tech

Подробная информация о последних технологиях Alibaba из первых рук → Facebook: Alibaba Tech. Twitter: « AlibabaTech ».