Вечером разработчики ушли, а их рабочие окружения продолжают занимать большую часть сервера. Мониторинг показывает занятую память, в списке процессов — собранные за день dev-серверы, watcher'ы и забытые терминалы. Людей в офисе уже нет, но ночью работа идёт только у процессов. Это удобный момент, чтобы разобраться, как Coder устроен изнутри и что именно он позволяет делать с окружениями, которые никто не использует.
Разбор удобнее вести не по списку настроек, а по одному рабочему дню. Так лучше видно, где у среды есть владелец, где работает общий шаблон, что остаётся после остановки и в какой момент остановка превращается в потерю данных.
Утро: откуда берётся окружение
Разработчик заходит в панель Coder и создаёт workspace. Для читателя это одна кнопка, но за ней стоит цепочка. По документации жизненного цикла Coder, workspace создаётся из Terraform-шаблона, им управляет control plane, а доступ к самой среде обеспечивает agent. Три роли здесь разные:
- шаблон описывает, из чего собирается среда: образ, диски, переменные, размер ресурсов;
- control plane принимает команды «создать», «запустить», «остановить», «удалить» и приводит инфраструктуру в соответствие с ними;
- agent живёт внутри среды и даёт разработчику вход: терминал, редактор, порты.
Отсюда первое практическое следствие. Окружение — не виртуальная машина, которую кто-то вручную поднял и теперь обслуживает. Это результат применения шаблона. Если шаблон правильный, у десяти людей будут одинаковые стартовые условия, и «у меня не собирается» перестаёт быть загадкой, зависящей от версии Node на чьём-то ноутбуке.
Кто чем владеет: человек, шаблон, платформа
Теперь удобно развести три уровня ответственности, потому что на них строятся все решения об остановке.
Владелец workspace — разработчик. Он запускает среду, пишет код, держит там свои процессы и решает, когда сделать перерыв. Его зона — содержимое домашнего каталога, ветки, локальные конфиги, открытые сессии.
Шаблон — общая договорённость команды. Именно шаблон определяет, какие ресурсы привязаны к окружению и как они ведут себя при остановке. Автоостановка тоже связана с настройками шаблона: по описанию планирования в Coder, она учитывает и активность пользователя, и параметры, заданные шаблоном. Иначе говоря, разработчик не может выбрать произвольное поведение, выходящее за рамки, которые задал администратор.
Администратор платформы отвечает за то, на чём всё это работает: сам сервер с Coder, диски, сеть, доступные образы, обновления. Он не обязан знать, над чем работает каждый разработчик, но обязан понимать, сколько ресурсов суммарно могут потребить окружения.
Эта схема полезна в споре «почему мою среду остановили». Ответ может лежать на любом из трёх уровней: человек не проявлял активности, шаблон задаёт короткий срок, платформа ограничена ресурсами. Пока уровни смешаны, разговор превращается в поиск виноватого. Когда они разделены, это обычная настройка.
День: файлы, процессы и «активность»
Днём разработчик правит код, запускает тесты, открывает терминал, подключает редактор. Для автоостановки главный вопрос: как Coder понимает, что человек ещё работает? В документации сказано, что механизм activity detection отслеживает поддерживаемые сессии разработки. Слово «поддерживаемые» важно. Это не «любая загрузка процессора» и не «любой запущенный процесс». Система смотрит на подключения, через которые человек действительно работает со средой.
Из этого вытекает наблюдение, которое стоит держать в голове при проектировании. Фоновый процесс сам по себе не обязательно считается признаком жизни. Если разработчик запустил долгую задачу и закрыл все сессии, с точки зрения человека работа идёт, а с точки зрения механизма активности подключений может уже не быть. Это не ошибка, это следствие выбранной модели, и к ней нужно подготовиться заранее. Мы вернёмся к этому в разделе про долгие процессы.
Пока же вспомним про пример перерыва. Разработчик ушёл на обед, закрыл ноутбук. Окружение продолжает занимать память, но активности нет. Через время, заданное настройками, Coder остановит его. Вернувшись, человек нажимает «запустить» и продолжает работу. Вопрос только в том, что именно он найдёт после запуска.
Разберём этот возврат по шагам, потому что от него зависит, как разработчик воспринимает платформу. Допустим, человек ушёл на обед в 13:00, а правило простоя в шаблоне рассчитано на несколько часов. Если он вернулся раньше, то окружение просто продолжает работать, и никакой остановки он не заметит. Если позже, то Coder уже выполнил остановку по правилам планирования, и кнопка «запустить» запускает среду заново из шаблона. Для человека это выглядит как продолжение, но технически это новый запуск: agent стартует снова, подключения устанавливаются заново.
Отсюда полезная привычка для команды: перед перерывом проверять не «сохранён ли файл», а «что у меня живёт только в процессе». Несохранённый буфер редактора, переменные окружения, выставленные в открытой оболочке, история отладочной сессии, запущенный dev-сервер с локальным состоянием в памяти — всё это принадлежит процессам, а не тому, что лежит на диске. После остановки процессов как раньше уже не будет, и разумнее принять это как условие работы, чем каждый раз удивляться.
Хороший тест для вашего шаблона: после остановки и запуска разработчик должен за пару минут вернуться к прежнему состоянию, выполнив только команды из README проекта. Если для этого нужно вспоминать, какие пакеты он ставил руками, значит, часть настройки живёт вне шаблона, и его пора доработать.
Что переживает остановку, а что нет
Здесь находится самое важное различие всей статьи: остановка и удаление — разные операции с разными последствиями. Документация описывает это так: при остановке ephemeral-ресурсы удаляются, persistent остаются; при удалении workspace уничтожаются все ресурсы.
Это правило легко прочитать и так же легко недооценить. Чтобы оно стало осязаемым, разложим окружение на слои.
| Часть окружения | Если ресурс ephemeral | Если ресурс persistent |
|---|---|---|
| Контейнер или машина с процессами | Удаляется при остановке, процессы пропадают | Сохраняется, но процессы всё равно не продолжат работу как раньше |
| Домашний каталог на томе | Пропадёт вместе с ресурсом | Остаётся для следующего запуска |
| Что-то, установленное вне тома | Исчезнет | Зависит от того, где это лежит |
Обратите внимание на последнюю строку. Типичная ловушка: разработчик установил системный пакет вручную, а шаблон хранит персистентно только домашний каталог. Утром после остановки пакета нет. Это не поломка, а ровно то, что описано в модели. Решение лежит на стороне шаблона: либо добавить установку в образ, либо в стартовый сценарий, либо продумать, что именно хранить на постоянном диске.
Теперь про удаление. Если workspace удалён, уничтожаются все его ресурсы, включая persistent. Пользователь, привыкший, что «остановил — значит всё сохранилось», может поставить знак равенства между «остановить» и «убрать». В интерфейсе это разные действия, но в голове людей они сливаются. Поэтому командные договорённости полезно проговорить: остановка — это ночь, удаление — это расставание с данными.
Чтобы различие не оставалось абстрактным, проследим судьбу одной и той же работы в двух сценариях. Разработчик создал ветку, внёс правки, не отправил их в удалённый репозиторий и ушёл домой. Если рабочий каталог лежит на persistent-ресурсе, ночная остановка ему ничем не грозит: утром ветка и незакоммиченные изменения на месте, как и описано в описании жизненного цикла. Если тот же человек через месяц удалит workspace, чтобы «пересоздать с чистого листа», та же ветка исчезнет вместе с томом.
Поэтому в командных правилах стоит закрепить простую привычку: всё, что имеет ценность вне окружения, должно быть отправлено в удалённый репозиторий до удаления, а не до остановки. Остановка не требует подготовки, удаление требует. Это разные уровни внимания, и хорошо, если интерфейс и договорённости их разделяют: никто не боится нажать «остановить», но каждый дважды подумает перед «удалить».
Есть и обратная сторона. Если шаблон делает persistent слишком много, например весь системный диск вместе с кэшами, остановка перестаёт чистить среду, и мусор копится месяцами. Тогда преимущество одинаковых стартовых условий, ради которого и затевался Coder, тихо исчезает: у каждого workspace накапливается собственная история ручных изменений. Выбор того, что считать постоянным, — это выбор между сохранностью и воспроизводимостью, и он принадлежит шаблону.
Расписание: что можно задать и где его границы
Теперь к главному инструменту. Автоостановка в Coder — это не просто таймер «выключить в 21:00». Как уже сказано, она учитывает активность и настройки шаблона. Практически это даёт два типа поведения, которые стоит держать раздельно:
- остановка по простою — среда останавливается, если сессий разработки нет заданное время;
- остановка по расписанию — среда останавливается к определённому времени с учётом правил, которые допускает шаблон.
Какие именно параметры доступны в вашей установке, зависит от версии и настроек шаблона, поэтому перед проектированием политики откройте раздел планирования в своей панели и сверьтесь с документацией. Здесь легко пообещать лишнего, а ошибка в обещании обойдётся ночной остановкой чужого процесса.
Есть и граница, связанная с редакцией продукта. В документации указано, что dormancy с автоматическим удалением относится к Premium-функциям. Разберём, что это значит на практике. Dormancy — это состояние долго неиспользуемого окружения, после которого его можно автоматически удалить. Если у вас нет Premium, этот механизм вам недоступен, и вы не можете полагаться на то, что платформа сама подчистит давно заброшенные среды вместе с их данными. Тогда уборка превращается в человеческий процесс: администратор периодически смотрит список, спрашивает владельцев и удаляет вручную.
Это не недостаток, а выбор. Автоматическое удаление данных — рискованная операция, и в небольшой команде ручная проверка раз в месяц иногда безопаснее любого таймера. Но решать нужно осознанно, а не обнаруживать через полгода, что диски забиты средами уволившихся сотрудников.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации Россия, США, Франция и Великобритания. Оплата картой РФ и по СБП.
Что дают сами ресурсы VPS
Теперь про сервер. Если Coder и окружения живут на одном VPS, то остановка окружения освобождает процессорное время и оперативную память, но не освобождает диск. Persistent-том остаётся там, где был, и занимает место независимо от того, работает ли среда. Это ключевая деталь: остановленные workspaces не означают автоматически бесплатную инфраструктуру. Вы продолжаете платить за диск, за сам сервер и за control plane, который тоже потребляет ресурсы.
Посчитаем на условном примере, который нужен только для иллюстрации хода рассуждения. Допустим, на сервере с 8 ГБ памяти работают четыре окружения, каждое занимает в среднем около 1,5 ГБ в рабочие часы. Сам Coder и операционная система занимают ещё какую-то долю. Тогда днём память почти исчерпана, а ночью остановленные среды возвращают всё, кроме доли самой платформы. Диски при этом заполнены так же, как и в разгар дня. Если у каждого окружения по 20 ГБ данных, это 80 ГБ, которые остаются на месте.
Из такого расчёта следуют два вывода, и ни один из них не про процент экономии. Во-первых, автоостановка решает проблему пиковой памяти и процессора, но не проблему дискового пространства. Во-вторых, чем больше людей в команде, тем важнее, что именно вы кладёте на постоянные тома: кэши сборки и тяжёлые зависимости разрастаются быстрее исходников.
Полезно увидеть, как это выглядит при смене числа окружений. Возьмём те же условные цифры: 8 ГБ памяти, по 1,5 ГБ на среду в рабочие часы. Четыре среды дают около 6 ГБ, а на систему и сам Coder остаётся примерно 2 ГБ. Пятая среда уже упирается в потолок, и сервер начинает использовать подкачку или убивать процессы по нехватке памяти. Остановка простаивающих окружений здесь помогает именно тем, что сглаживает пик: если двое ушли на обед, третий может запустить свою среду, не дожидаясь вечера.
С диском картина другая. Пять окружений по 20 ГБ — это уже 100 ГБ постоянных данных, и они занимают место, даже когда все пять остановлены. Если у вас есть нужда в запасе, его лучше считать по дискам, а не по памяти: память возвращается после остановки, диск возвращается только после удаления данных. Поэтому два показателя нужно смотреть отдельно: пиковое потребление RAM в рабочие часы и суммарный объём томов в любое время суток.
| Ресурс сервера | После остановки | Что с этим делать |
|---|---|---|
| Процессор и память | Освобождаются, кроме доли Coder и системы | Измерять пик в рабочие часы |
| Persistent-том | Остаётся занятым | Следить за кэшами и устаревшими средами |
| Сам Coder и сервер | Продолжают работать и потреблять ресурсы | Учитывать как постоянную долю |
Если смотреть на ресурсы публичных планов MAATRIX как на отправную точку, то картина такая: Ba даёт 1 vCPU, 2 ГБ RAM и 40 ГБ NVMe, Uab — 2 vCPU, 4 ГБ и 80 ГБ, Heka — 4 vCPU, 8 ГБ и 160 ГБ, Maat — 8 vCPU, 16 ГБ и 240 ГБ, Djed — 16 vCPU, 32 ГБ и 320 ГБ. Эти цифры не являются обещанием ёмкости: сколько окружений поместится, определяется вашими проектами, а не названием плана. Для небольшой команды, которая впервые пробует Coder, разумнее взять запас по диску и измерить реальное потребление в рабочий день, чем угадывать. Сервер с NVMe и root-доступом на VPS MAATRIX позволяет самому настроить и Coder, и Docker или другой способ запуска окружений, и посмотреть, как ведут себя нагрузка и диски на вашем наборе проектов. Расположение можно выбрать из публично перечисленных локаций: UK, US, RU и FR; наличие конкретных образов и ОС проверяйте в форме заказа.
Отдельно о резервных копиях. Persistent-том переживает остановку, но это не копия. Он не защищает от удаления workspace, ошибки в шаблоне или потери сервера. Автоматические резервные копии во всех тарифах мы не обещаем, поэтому план копирования данных разработчиков нужно решать отдельно, а не надеяться, что «диск ведь сохраняется».
Исключение: процесс, которому нельзя мешать
Теперь вернёмся к долгим процессам. Допустим, разработчик запустил миграцию данных или многочасовую сборку и закрыл ноутбук. Сессий разработки нет, расписание говорит «ночью остановить». Что произойдёт? Исходя из того, как описана активность, нельзя рассчитывать, что сам факт работающего процесса удержит среду включённой. Остановка может прервать задачу, а ephemeral-часть окружения при этом пропадёт.
Есть несколько способов с этим жить, и выбор зависит от характера задачи.
- Вынести долгую работу из персональной среды. Если процесс важен и длится часами, ему место в CI или на отдельном сервере, а не в окружении, которое по замыслу эфемерно. Это самое надёжное решение: персональный workspace остаётся местом для разработки, а не для производства результатов.
- Сделать задачу возобновляемой. Сохранять промежуточное состояние на persistent-том и уметь продолжить с контрольной точки. Тогда ночная остановка превращается в паузу, а не в катастрофу.
- Предусмотреть исключение в шаблоне. Отдельный шаблон для длительных задач с более мягкой политикой остановки. Возможности зависят от того, что допускает ваша версия и настройки, поэтому проверяйте их в панели до того, как строить на них процесс.
- Договориться о предупреждении. Если ничего из этого не подходит, разработчик должен знать, что среда может быть остановлена, и планировать задачу соответственно.
Рассмотрим второй вариант подробнее, потому что он самый дешёвый в реализации. Допустим, миграция обрабатывает данные порциями. Если скрипт после каждой порции записывает номер последней обработанной записи в файл на persistent-томе, ночная остановка стоит только времени текущей порции. Утром разработчик запускает тот же скрипт, он читает контрольную точку и продолжает. Без такой точки остановка в три часа ночи означает повторный прогон с нуля, и разработчик узнаёт об этом утром.
Важна и идемпотентность: повторная обработка уже сделанной порции не должна портить результат. Если скрипт при перезапуске дублирует записи, контрольная точка спасёт время, но создаст новую проблему. Поэтому перед тем как доверить долгую задачу персональной среде, стоит проверить её на искусственной остановке: прервать посреди работы и запустить заново. Если результат совпал с непрерывным прогоном, ночная остановка не страшна. Если нет, задача относится к первому варианту — в CI или на отдельный сервер.
С третьим вариантом осторожнее. Отдельный шаблон с мягкой политикой удобен, но легко превращается в лазейку: если «долгие» окружения не останавливаются никогда, они снова занимают память всю ночь, а ради этого мы и затеяли разговор. Разумно ограничить круг тех, кто может его использовать, и пересматривать список раз в какое-то время.
Хороший признак здоровой политики: ни один сотрудник не узнаёт о правилах остановки в момент потери результата. Правило, о котором все знают, превращается в удобную особенность. Правило, о котором узнают постфактум, становится поводом не доверять платформе.
Если вы ещё взвешиваете, нужен ли вам Coder вообще или хватит обычного SSH с редактором, посмотрите разбор про выбор между Coder и SSH: там обсуждается, за что платят сложностью.
Вечер: две причины, по которым окружение перестаёт быть нужным
Вернёмся к вечеру из начала статьи. Окружение остановилось ночью, утром разработчик вернулся, всё на месте, кроме запущенных процессов. Это нормальный цикл, и именно ради него придуманы эфемерные ресурсы и персистентные тома.
Но «ушёл домой» и «ушёл из команды» — два разных события, и поведение среды в них должно быть разным. В первом случае нужно сохранить всё, что человек будет ожидать утром: домашний каталог, настройки, ветки. Во втором нужно решить, что делать с данными: передать коллегам нужные репозитории и черновики, проверить, не лежат ли в окружении секреты и ключи, и только потом удалять, помня, что удаление уничтожает все ресурсы, включая persistent.
Между этими событиями есть промежуточная зона: отпуск, больничный, длинная пауза между проектами. Здесь и проявляется различие редакций. Без Premium вам не доступно автоматическое удаление через dormancy, поэтому окружение отпускника будет лежать остановленным вместе со своим диском, пока вы сами не решите иначе. С Premium можно настроить автоматику, но тогда нужно очень точно задать срок и убедиться, что владелец узнает о нём заранее.
Так что вопрос к вашей команде такой: что должна делать среда, когда человек закрыл ноутбук вечером, и что она должна делать, когда он закрыл за собой дверь насовсем? Первое событие почти всегда означает «остановить и ждать». Второе требует решения человека, а не таймера. Если у этих двух сценариев в вашей конфигурации одинаковое поведение, самое время открыть шаблон и это исправить.