Привет, Хабр!  Думаю, для вас не секрет, что в последние годы контейнеризация вышла в лидеры на DevOps благодаря своим возможностям, включая эффективное использование ресурсов и гибкость. Так что Microsoft и Docker потратили немало времени на создание удобной среды, в которой можно было бы провести запуск приложений .NET внутри контейнеров.  Наша команда в разработке использует Kubernetes кластеры, в которых разворачиваются контейнеры на базе Linux систем с различными .Net приложениями и сервисами. Так что в какой-то момент мы встали перед вопросом, как проводить мониторинг не только контейнеров, но и дампов. За помощью мы обратились к всемогущему интернету, и после нескольких часов изучения данного вопроса, наш выбор пал  на использование “sidecar” контейнеров. Если же вы ранее не сталкивались с “sidecar” контейнерами, то могу немного пояснить. Sidecar-контейнер — это дополнительный контейнер, который запускается рядом с основным контейнером приложений внутри того же пода. Грубо говоря, эта схема позволяет добавить некоторые расширения функциональности приложения в основном контейнере без внесения в него дополнительных изменений.  Наша команда применяла эту идею для профилирования / отладки контейнеров .NET Linux. Лично я выделил следующие преимущества этого подхода:  Контейнеры приложений не нуждаются в повышенных привилегиях; Образы контейнеров приложений остаются, в основном, без изменений. Они не раздуваются пакетами инструментов, которые не требуются для запуска приложений; Профилирование не использует ресурсы контейнера приложения, которые обычно ограничиваются квотой. Мы выводили все мониторинги приложений и контейнеров в отдельную систему мониторинга, поэтому нам нужно было автоматизировать создание дампов. Из-за некоторых особенностей проекта стандартные образы dotnet-monitor различных версий не подходили или работали не корректно. Так, например, если в деплойменте стоит не одна, а несколько реплик для приложений, то дампы работают, увы, только на одной реплике. Стандартные контейнеры dotnet-monitor (или dotnet/nightly/monitor) можно посмотреть на докерхабе тут. Сразу предупреждаю, что они подойдут далеко не всем, особенно если учитывать версию .Net, специфику проекта, а также особенности основных контейнеров. Увы, в нашем случае через sidecar не удалось реализовать корректную работу и создание дампов приложений дотнет с помощью имеющихся образов dotnet-monitor. Так что, подумав как следует, мы решили сделать sidecar контейнер для .Net 5 Пример докер файла: Потом мы добавили в деплоймент сервиса в кубернейтс:  Это поможет sidecar контейнеру видеть процессы основного контейнера. Также мы с командой примонтировали общую папку для обоих контейнеров. По итогу получился такой вот yaml: <myregistry> — указывается хранилище контейнеров.  Попробовали запустить это образ рядом с основным контейнером приложения и сделать dump из командной строки sidecar контейнера.  Это сработало!  Следующим этапом для нас стало автоматизирование. В нашем случае по мониторингам было видно, что некоторые сервисы потребляют много оперативной памяти. Со временем это потребление только возрастает.  Проанализировав сложившеюся ситуацию наша команда пришла к следующему алгоритму снятия дампов: Необходимо снимать дамп при достижении сервисом значения по оперативной памяти равное 1Гб;  После этого необходимо увеличивать переменную для сравнения значения вдвое: т.е. следующий дамп увеличивается на 2 Гб, потом на 4 Гб и так далее. Теперь за нами осталась лишь реализация. Первое, что может спросить любой разработчик, кто хоть немного использует кубернейт, так это куда складировать дампы и где стоит их хранить? Вполне очевидно, что если дамп делается внутри памяти пода, то после рестарта пода его не будет. Поэтому нам необходимо было примонтировать хранилище ко всем необходимым сервисам. Учитывая, что проект был на Ажуре, то все эти проблемы можно было легко решить за счет использования стандартной учётной записи хранения — Standard_LRS. Вот так выглядит сам yaml файл для создания класса хранения: Хотел бы также оставить небольшой комментарий по последним двум параметрам:  allowVolumeExpansion: true — необходим для возможности изменения размера PVC из кубера; reclaimPolicy: Retain — для динамически подготовленных PersistentVolumes. Политика возврата по умолчанию — «Удалить» (Delete).  Это означает, что динамически подготовленный том автоматически устраняется, когда пользователь удаляет соответствующий PersistentVolumeClaim.  Меня такое автоматическое поведение не очень устраивало, ведь в моем случае куда целесообразнее было использовать политику «Сохранить» (Retain). А при использовании политики «Сохранить», если пользователь удаляет PersistentVolumeClaim, соответствующий PersistentVolume не удаляется. Вместо этого он перемещается в фазу выпуска, где все его данные можно восстановить вручную. Иными словами, даже удалив все упоминания об SC, PVC, PV из кубера, данные дампов останутся в учётной записи хранения в Ажуре.  PVC создавался следующим скриптом:  Ну и, соответственно, монтирование к sidecar контейнеру происходит следующим образом: По алгоритму автоматизации дампов мы рассматривали два варианта: Через cron; В цикле. Моя команда решила пойти вторым путем. Тут стоит отметить, что через крон есть определенные особенности реализации, но этот вариант тоже вполне рабочий. И вот у нас уже написался небольшой bash скрипт) Мы исходили из следующих соображений: Нужно было как-то высчитывать потребляемую память конкретным процессом dotnet. В нашем случае это и будет процесс с наибольшим потреблением; Нужно было считывать id процесса; Необходимо было сравнивать потребляемую память конкретным процессом dotnet с переменной и увеличивать эту переменную; А еще была необходимость в создании и архивации дампов таким образом, чтобы они занимали не так много места на учетной записи хранения; Нам хотелось, чтобы дамп имел красивое название, в котором бы отображалось имя сервиса, дата и время. Для этого в sidecar контейнер в деплойменте передавались соответствующие параметры.  В итоге скрипт (script.sh) выглядит так:  *его я монтировал в configmap Думаю, тут не стоит расписывать объяснение ко всем строкам. Эту информацию можно с легкостью найти в интернете. Остановлюсь лишь на интересном способе просмотра “top1 максимально потребляемой памяти”:  Я достаточно долго размышлял над тем как лучше это сделать… И, если у кого-то найдутся более интересные способы, то буду очень рад увидеть их в комментариях. В итоге, учитывая вышеописанное, деплоймент самого sidecar изменился до следующего варианта: Следующая схема заработала корректно и позволила автоматизировать дампы .Net для сервисов и приложений, что, в свою очередь, повысило оперативность в выявлении ошибок в коде и скорость разработки.  P.S.: Для удобства скачивания дампов и работы с учетными записями хранения Ажуры лично мне понравилось использовать Microsoft Azure Storage Explorer.