Недавно была опубликована информативная статья Мэтта Уильямса о Java в Docker и существующих ограничениях памяти. Автор поднимает интересную тему о скрытой проблеме ограничения памяти, с которой пользователи могут столкнуться во время работы с контейнерами.
Большое количество репостов и лайков показывает, что данная тема довольно популярна среди Java-разработчиков.
Поэтому хотелось бы более подробно проанализировать данную проблему и определить возможные пути ее решения.
Проблема
Мэтт описывает свое ночное «путешествие» в контейнере Docker со стандартным поведением памяти JVM. Он обнаружил, что ограничения RAM отображаются некорректно внутри контейнера. В результате, приложение Java, или любое другое, видит общий объем ресурсов оперативной памяти, выделенной для всей хост-машины, а JVM не может указать, сколько ресурсов было предоставлено родительскому контейнеру для работы. Это приводит к ошибке OutOfMemoryError, вызванной неправильным поведением динамической памяти JVM в контейнере.
Фабио Кунг, из Heroku, подробно описал основные причины возникновения этой проблемы в своей недавней статье "Память внутри контейнеров Linux. Или почему в контейнере Linux не работает free и top?"
Большинство инструментов Linux, предоставляющих метрики ресурсов системы, были созданы в то время, когда cgroups еще не существовали (например: free и top, как у procps). Они обычно читают метрики памяти из файловой системы proc: /proc/meminfo, /proc/vmstat, /proc/PID/smaps и других.
Читать полностью »