Недавняя работа заключается в проверке фактического использования памяти службой за прошедший период и установке разумного верхнего предела на основе исторических данных для памяти POD на платформе K8S. Это не будет ограничивать нормальную работу службы, но также будет ограничивать ее. минимизируйте ненужную ловушку.
Изначально это была очень простая задача. Логически говоря, просто посмотрите на график и определите пиковое потребление памяти, и на этом все. Неожиданно я увидел что-то странное, рассматривая фотографии. После этого я потратил 2 дня на чтение более дюжины статей для исследования и только что написал электронное письмо на несколько страниц своим коллегам в США, чтобы поговорить об этой проблеме. .Подведите итог сами.
Давайте сначала поговорим о чуде. Объединив несколько графиков онлайн-мониторинга, я обнаружил, что при использовании разных индикаторов мониторинга использование памяти сильно различается.
Если вы используете RSS в качестве индикатора, память работает очень стабильно:
Но если использовать РАБОЧИЙ НАБОР в качестве индикатора, наша память, похоже, стремительно растет, и каждую минуту она будет подниматься до текущего верхнего предела POD...
Возникает вопрос: на какой индикатор нам следует обратить внимание, чтобы определить верхний предел использования памяти POD?
История начинается с Linux. Linux поддерживает разделение Cgroups на разные процессы, то есть формирование небольших групп в группе, которые совместно используют ресурсы группы, включая память, ЦП и т. д. Нижний уровень Docker использует Cgroups для управления ресурсами контейнера.
После разделения Cgroups для изоляции ресурсов для разных процессов Linux сам предоставляет множество индикаторов для отображения использования памяти внутри Cgroups. Здесь нас больше интересуют следующие значения:
$ cat /sys/fs/cgroup/memory/memory.stat
cache xxx
rss xxx
inactive_file xxx
active_file xxx
Среди четырех вышеуказанных значений:
Кэш, естественно, относится к кешу, включая файловый кеш.
RSS относится к резидентной памяти, которая представляет собой фактическую физическую память, выделенную процессу, включая память стека, память кучи и память общей библиотеки, используемую процессом.
Насколько я понимаю, Inactive_file и active_file являются файловыми кэшами. Разница между ними заключается в том, что при первом доступе к файлу он будет считаться неактивным. После двойного доступа он будет классифицирован как. неактивная файловая группа.
Что касается K8S, чтобы пользователи могли отслеживать потребление памяти POD, уровень K8S также предоставляет множество различных индикаторов памяти. Вот что нас больше всего беспокоит:
container_memory_cache -- Размер занимаемый кэшем
container_memory_rss -- Размер, занимаемый RSS
container_memory_usage_bytes -- Используемая в данный момент память, включая всю память, независимо от того, была ли она доступна или нет.
container_memory_working_set_bytes -- Текущее использование рабочего набора памяти
Из исходного кода K8S видно, что индикаторы K8S на самом деле рассчитываются после некоторых вычислений над приведенными выше индикаторами Linux:
Метод расчета RSS очень интуитивно понятен, то есть считывание общего RSS:
ret.Memory.RSS = s.MemoryStats.Stats["total_rss"]
Метод расчета РАБОЧЕГО НАБОРА создается K8S с использованием использования минус неактивный файл:
inactiveFileKeyName := "total_inactive_file"
if cgroups.IsCgroup2UnifiedMode() {
inactiveFileKeyName = "inactive_file"
}
workingSet := ret.Memory.Usage
if v, ok := s.MemoryStats.Stats[inactiveFileKeyName]; ok {
if workingSet < v {
workingSet = 0
} else {
workingSet -= v
}
}
ret.Memory.WorkingSet = workingSet
Как видно из вышесказанного, два интересующих нас показателя имеют разные источники: RSS заботится только о фактически используемой процессом памяти, но WORKING SET учитывает и активные файлы, то есть учитывается и часть файлового кэша.
Следующий вопрос: каковы стандарты K8S OOM? Разумеется, поскольку файловый кэш является кэшем, в период кризиса и при высокой нехватке памяти файловый кэш должен уступить место процессу. Эта часть кэша должна быть записана обратно на диск, чтобы освободить место. для использования процесса.
Но реальная ситуация такова, что когда кеш занимает огромное количество места, K8S подумает, что память достигла верхнего предела, и напрямую убьет POD и перепланирует его. Эта проблема была поднята как проблема на Github. Некоторые люди всегда обнаруживают, что RSS их POD очень низкий. Когда кэш очень велик, K8S также уничтожает его:
Эта проблема была обнаружена в 2017 году, и люди продолжали отвечать на нее четыре дня назад. Видно, что это старая проблема... Но, по крайней мере, можно сделать вывод, что память, занятая кешем, также может вызывать OOM. .
Просмотрев различные проблемы, я обнаружил, что у K8S, возможно, небезосновательно стоит рассмотреть возможность кэширования. В другом выпуске кто-то также столкнулся с подобной ловушкой и, наконец, обнаружил, что не все базовые файловые системы могут поддерживать обратную запись в грязный файловый кэш. Если кеш отказывается отдавать место, когда это необходимо, а сам процесс требует больше памяти, то все кончено...
Таким образом, хотя файловый кэш действительно не должен включаться в память, используемую процессом, на K8S очевидно, что его существование оказывает решающее влияние на жизнь и смерть POD. Подводя итог, считаю, что мониторинг WORKING SET более соответствует реальной ситуации, и на увеличение памяти здесь тоже нужно обратить внимание.
Вот и все.
Во время эпидемии я израсходовал все силы своего мозга на то, чтобы захватить еду на работе, но мне все равно хочется разобраться в проблеме. Может быть, это маленькая навязчивая идея мертвых рационалистов...
С Первомая вас!
Schönes Wochenende!