Хранилище инструментов DevOps на NAS: структура каталогов, версионирование и контроль доступа | AdminWiki

Хранилище инструментов DevOps на NAS: структура каталогов, версионирование и контроль доступа

11 сентября 2026 13 мин. чтения

Каталог tools со 120 файлами без версий: поиск нужного kubectl занимает 5-10 минут, запуск бинарника не той версии ломает совместимость с кластером, а восстановить values.yaml недельной давности нечем. Так выглядит хранилище DevOps-инструментов, которое никто не упорядочивал. Проблему решает NAS или файловая шара: схема каталогов, версионирование и контроль доступа задаются один раз и работают для всей команды, дополнительное ПО покупать не нужно.

Готовая схема: корень /devops-tools, первый уровень - окружение (dev, stage, prod), второй - тип артефакта (cli, iac, containers, configs, scripts, docs), третий - инструмент, четвёртый - версия. Права выдаются группам AD/LDAP, prod открыт только на чтение, каждая версия неизменяема и закрыта контрольной суммой SHA-256. Ниже разобраны все слои: структура каталогов, версионирование, контроль доступа, порядок миграции, типичные ошибки, выбор NAS и автоматизация.

Четыре ситуации, с которых начинается наведение порядка:

  • «Где лежит последняя версия helm?» - ответ знает один человек и держит его в переписке.
  • «Кто перезаписал values.yaml?» - есть только текущий файл, предыдущего нет.
  • «Почему у меня скрипт работает, а у коллеги падает?» - версии kubectl разошлись на три минорных релиза.
  • «Можно ли повторить сборку полугодовой давности?» - артефакт удалён, зависимость обновилась, воспроизводить нечего.

Разметка каталогов занимает час и экономит десятки часов поисков. Какие инструменты вообще попадают в хранилище и как они связаны в пайплайне, разобрано в статье Руководство по DevOps-инструментам: как собрать рабочий контур.

Принципы именования и структура каталогов

Корень хранилища отделяет окружения от типов артефактов. Порядок уровней упрощает права: правило задаётся один раз на каталог окружения и наследуется вглубь.

/devops-tools/
|-- dev/
|   |-- cli/
|   |   `-- kubectl/
|   |       `-- 1.29.0/
|   |           |-- bin/kubectl
|   |           |-- checksum.sha256
|   |           `-- README.md
|   |-- iac/
|   |   `-- terraform/
|   |       `-- 1.7.0/
|   `-- configs/
|       `-- nginx/
|           `-- 1.24.0-2026-08-14/
|               |-- nginx.conf
|               `-- README.md
|-- stage/
`-- prod/
    |-- cli/
    |-- iac/
    |-- containers/
    |-- configs/
    |-- scripts/
    `-- docs/

Полные пути выглядят так: /devops-tools/prod/cli/kubectl/1.29.0/bin/kubectl, /devops-tools/dev/iac/terraform/1.7.0/terraform, /devops-tools/stage/configs/nginx/1.24.0-2026-08-14/nginx.conf.

Категории и их содержимое:

  • cli - бинарники командной строки: kubectl, helm, terraform, jq, yq, k9s;
  • iac - описания инфраструктуры: плейбуки Ansible, модули Terraform, манифесты и Helm-чарты;
  • containers - tar-архивы образов и docker-compose файлы для офлайн-развёртывания;
  • configs - эталонные конфигурации: nginx.conf, values.yaml, prometheus.yml, pg_hba.conf;
  • scripts - bash и python-утилиты обслуживания, бэкапы, ротации, проверки;
  • docs - runbook'и, схемы сети, описания стендов, чек-листы релизов.

В корне каждого инструмента лежит README.md: что это, откуда взято, кто добавил, дата, лицензия. Через полгода никто не вспомнит, зачем в хранилище стоит helm 2.16 и можно ли его удалить. Первую строку файла отводят под дату добавления и версию, тогда grep по каталогу даёт ответ за секунду.

Длина пути ограничена: SMB-клиенты Windows без поддержки длинных путей упираются в 260 символов. Глубина в шесть уровней и короткие имена снимают вопрос: /devops-tools/prod/cli/helm/3.14.0/bin/helm - 48 символов.

Разделение по окружениям и типам артефактов

В dev пишут разработчики и CI, stage читают тестировщики, prod доступен на чтение всем, кроме ops-team. Изоляция работает на уровне каталогов вместе с правами и снапшотами ZFS: изменения в dev не видны в prod, это физически разные деревья.

Типы артефактов разводят по подпапкам из-за разного жизненного цикла. Бинарник живёт до следующего релиза upstream, конфиг меняется еженедельно, образ контейнера занимает сотни мегабайт. Схемы версий тоже расходятся: у бинарников номер upstream (kubectl 1.29.0), у конфигов версия и дата (nginx 1.24.0 от 2026-08-14), у образов тег и digest (app 2.7.1, sha256:9f1c...).

Смешивание типов в одной папке ломает автоматизацию: скрипт очистки по маске *.tar удалит образы, ротация конфигов по mtime перезапишет бинарник. Аудит в таком каталоге бесполезен, потому что непонятно, какие изменения критичны.

Правила именования файлов и папок

Правила короткие и проверяемые:

  • только строчные латинские буквы, цифры и дефис;
  • точка - только для расширения файла;
  • версия всегда отдельный сегмент пути, а не суффикс имени;
  • запрещены пробелы, кириллица и символы : * ? " < > | \ /;
  • дата в формате ISO 8601 (2026-08-14) сортируется как строка.

Правильно: /prod/cli/kubectl/1.29.0/bin/kubectl, /dev/configs/nginx/1.24.0-2026-08-14/nginx.conf, /dev/scripts/db-backup/2026-08-14-a1b2c3d/backup.sh. Неправильно: /Tools/Kubectl Setup v2/kubectl (1).exe, /dev/Мои скрипты/бэкап_базы.sh, /prod/configs/nginx.conf.old.2026.

Единый стиль даёт измеримый результат: grep -r "kubectl/1\." по хранилищу показывает все используемые версии, а find с маской *2026-08-* отдаёт артефакты за нужный день. Имена без пробелов и кириллицы корректно проходят через SMB, NFS, rsync, tar и Windows-клиенты.

Версионирование артефактов и инструментов

Базовое правило: одна версия - одна папка, файлы внутри не перезаписываются. Правка артефакта на месте ломает воспроизводимость сборок и обесценивает аудит: контрольная сумма перестаёт совпадать с той, которую проверял CI неделю назад.

Структура версии:

/devops-tools/prod/cli/kubectl/1.29.0/
|-- bin/kubectl
|-- checksum.sha256
`-- README.md

Файл checksum.sha256 содержит строку вида d6f2c1a9... bin/kubectl, проверка выполняется командой sha256sum -c checksum.sha256 из каталога версии. README.md фиксирует источник загрузки, дату, ответственного и причину, по которой версия оказалась в хранилище.

Симлинк latest в каталоге инструмента указывает на актуальную версию: /devops-tools/prod/cli/kubectl/latest -> 1.29.0. На NFS и Linux-клиентах ссылка работает штатно, SMB-клиенты Windows её часто игнорируют. Для смешанного парка рядом кладут файл stable.txt с номером версии, и скрипты читают его.

Retention: держите последние 5 версий плюс все, на которые ссылаются манифесты и пайплайны. Большие бинарники и образы, которые уже лежат в Git, хранят через указатели Git LFS или DVC. Каждый гигабайт образа в трёх копиях рано или поздно упирается в свободное место на NAS.

Схемы версионирования: SemVer, даты, хеши

SemVer (MAJOR.MINOR.PATCH) подходит внешним инструментам с публичными релизами: kubectl, helm, terraform, ansible. Номер берётся из upstream без переименований, чтобы путь в хранилище совпадал с официальным релизом.

Календарное версионирование (2026-08-14) удобно для внутренних скриптов и конфигов, у которых нет релизов, зато важна дата правки. Короткий хеш коммита добавляют к дате, если скрипт живёт в Git: script-2026-08-14-a1b2c3d.

Хеш как основную схему применяют для сборок из CI: app-2.7.1-sha256:9f1c4a. Идентификация однозначная, читаемость падает. Смешивание схем в одном каталоге допустимо: каждая версия изолирована в своей папке, terraform лежит с SemVer, соседние скрипты с датой, конфликтов нет.

Управление жизненным циклом версий

Политика: версии старше 12 месяцев уезжают в /archive, затем удаляются. Перед удалением проверяют, что версия не упоминается в манифестах, пайплайнах и образах. Скрипт ревизии печатает кандидатов:

#!/bin/bash
ROOT=/mnt/tank/devops-tools
CUTOFF=$(date -d "12 months ago" +%Y-%m-%d)
find "$ROOT" -mindepth 4 -maxdepth 4 -type d | while read -r v; do
    [ -f "$v/README.md" ] || { echo "SKIP, нет README: $v"; continue; }
    added=$(grep -m1 -oE '20[0-9]{2}-[0-9]{2}-[0-9]{2}' "$v/README.md")
    [ -z "$added" ] && continue
    [ "$added" \< "$CUTOFF" ] && echo "ARCHIVE: $v"
done

Скрипт только показывает кандидатов, удаление запускается вручную после сверки с CI. Автоматическое удаление по дате без проверки ссылок валит пайплайны: ночная сборка падает на скачивании helm 3.9.0, который «никто не использует», кроме одного job'а.

Контроль доступа к хранилищу инструментов

Права строятся на группах AD/LDAP и наследуются через ACL. Разрешения для отдельных людей не выдают, иначе через год картину доступов никто не восстановит.

Роли и группы: кто что может

Роль / группаdevstageprod
dev-teamчтение и записьчтениечтение
ops-teamчтение и записьчтение и записьчтение и запись
ci-serviceчтение и записьчтениечтение
auditorчтениечтениечтение
подрядчики и гостинет доступанет доступанет доступа

Сервисные учётки CI/CD получают минимум прав: запись только в свой подкаталог, доступ по ключу или токену, ротация раз в 90 дней. Учётка администратора домена в переменных пайплайна - самый короткий путь к компрометации всего хранилища.

Права на уровне файловой системы для NFS-клиентов и Linux:

setfacl -m g:ops-team:rwx /mnt/tank/devops-tools/prod
setfacl -m g:dev-team:r-x /mnt/tank/devops-tools/prod
setfacl -R -m g:dev-team:r-x /mnt/tank/devops-tools/prod
setfacl -d -m g:ops-team:rwx /mnt/tank/devops-tools/prod

Первые три команды задают права на каталог и содержимое, четвёртая - маску наследования для новых файлов. В TrueNAS права SMB-шары настраиваются в Shares > Edit > Advanced ACL, для NFS работает ZFS ACL. Базовые режимы: 750 для prod, 770 для dev, владелец root или служебная группа ops-team.

Режим 777, анонимный доступ к шаре и общий пароль на всю команду превращают хранилище в точку входа для атакующего. Как выстроить защиту без торможения разработки, разобрано в материале DevSecOps в 2026: практический справочник по интеграции безопасности в DevOps.

Аудит и логирование доступа

Аудит включают до появления prod в хранилище, а не после инцидента. В TrueNAS журнал доступен в разделе System > Audit и через API audit.query; фильтр по сервису SMB показывает, кто открывал и менял файлы. Для детального логирования действий с файлами подключают vfs-модуль full_audit:

[devops-tools]
   path = /mnt/tank/devops-tools
   vfs objects = full_audit
   full_audit:prefix = %u|%I|%S
   full_audit:success = rename unlink mkdir rmdir write
   full_audit:failure = none
   full_audit:facility = LOCAL5
   full_audit:priority = NOTICE

Записи модуля уходят в syslog и собираются централизованно. Практический минимум: 90 дней хранения, отдельное оповещение на любую запись в /prod, ежемесячный отчёт по операциям изменения. Без логов разбор инцидента упирается в вопрос «кто менял файл», на который нет ответа.

Пошаговое внедрение без риска для рабочей среды

Порядок работ: инвентаризация, пилот на dev, права и аудит, миграция по частям, проверка пайплайнов, перевод prod в режим только чтение. У каждого шага есть критерий успеха и точка отката.

  1. Инвентаризация: список инструментов, версий, мест хранения и владельцев. Критерий - таблица на 20-40 строк, где у каждого артефакта есть ответственный.
  2. Снапшот и бэкап: zfs snapshot -r tank/devops-tools@pre-migration. Критерий - снапшот виден в zfs list -t snapshot, дата совпадает с началом работ.
  3. Пилот на dev: создание дерева каталогов, перенос двух-трёх инструментов, проверка чтения и записи. Критерий - скрипты команды работают с новых путей.
  4. Права и аудит на dev: группы, ACL, включённое логирование. Критерий - тестовая запись видна в журнале, чужой пользователь получает отказ.
  5. Миграция stage, затем prod, по частям, в окно обслуживания. Критерий - снапшот перед каждым этапом, проверка пайплайнов в течение 24-48 часов.
  6. Перевод prod в режим только чтение для всех, кроме ops-team, и фиксация путей в документации. Критерий - попытка записи от учётки dev-team завершается отказом.

Пилот на dev-окружении

Пилот занимает один рабочий день и не затрагивает prod. Команды для создания дерева и переноса первого инструмента:

mkdir -p /mnt/tank/devops-tools/{dev,stage,prod}/{cli,iac,containers,configs,scripts,docs}
mkdir -p /mnt/tank/devops-tools/dev/cli/kubectl/1.29.0/bin
cp /opt/kubectl /mnt/tank/devops-tools/dev/cli/kubectl/1.29.0/bin/kubectl
sha256sum /mnt/tank/devops-tools/dev/cli/kubectl/1.29.0/bin/kubectl \
  > /mnt/tank/devops-tools/dev/cli/kubectl/1.29.0/checksum.sha256
ln -sfn 1.29.0 /mnt/tank/devops-tools/dev/cli/kubectl/latest
chmod -R 770 /mnt/tank/devops-tools/dev
chmod -R 750 /mnt/tank/devops-tools/prod

После переноса проверяют три сценария: CI читает и пишет в /dev, разработчик видит файлы через SMB и NFS, скрипты находят инструмент по новому пути. На пилоте удобно поймать проблемы с регистром имён, символическими ссылками на SMB и длиной пути.

Миграция и откат

Очерёдность: dev, затем stage, затем prod. Перед каждым этапом снимают снапшот, после этапа 24-48 часов наблюдения за пайплайнами.

zfs snapshot -r tank/devops-tools@2026-09-11-pre-migration
zfs list -t snapshot | grep pre-migration
zfs rollback -r tank/devops-tools@2026-09-11-pre-migration

Откат: остановить записи в хранилище, выполнить zfs rollback, вернуть прежние пути в конфигурации CI. Prod мигрируют в окно обслуживания: смена путей в манифестах требует перезапуска job'ов, иногда перевыпуска секретов, где прописаны пути к файлам.

Чек-лист перед переводом prod в режим только чтение:

  • снапшот ZFS или бэкап сделан в последние 24 часа;
  • восстановление проверено на тестовом датасете;
  • все пути в CI/CD обновлены и закоммичены;
  • права prod проверены тестовой учётной записью, запись отклоняется;
  • сервисные учётки CI имеют доступ только к нужным каталогам;
  • аудит включён, тестовая запись видна в журнале;
  • README.md есть у каждого инструмента;
  • checksum.sha256 совпадает с sha256 файла;
  • latest или stable.txt указывает на версию, проверенную в stage;
  • окно обслуживания согласовано, ответственный инженер на связи.

Типичные ошибки при организации хранилища

  • Плоская свалка файлов. Папка tools со 100 файлами без версий: поиск нужного бинарника занимает 8-10 минут, часть файлов скачана повторно. Исправление: разложить по схеме env/category/tool/version, старые копии убрать в /archive.
  • Версия в имени файла вместо отдельной папки. kubectl-1.29-linux-amd64 (2).tar не даёт положить рядом README и checksum, не работает как цель симлинка. Исправление: папка версии, внутри бинарник, сумма и описание.
  • Права 777 и общий пароль. Любой сотрудник или скомпрометированный скрипт меняет prod. Исправление: группы AD/LDAP, prod только чтение, отдельные сервисные учётки.
  • Отсутствие бэкапов. Ошибочная команда удаления или шифровальщик уничтожает хранилище целиком. Исправление: снапшоты ZFS, копия на второй NAS, restic в облако.
  • Дубликаты инструментов. Три копии terraform в разных папках, в проде используется четвёртая. Исправление: один канонический путь на инструмент, остальные ссылки удалить.
  • Устаревшие артефакты без ротации. Датасет забит под 100%, новые версии не публикуются. Исправление: политика хранения 5 версий плюс prod-версии, ревизия раз в квартал.
  • Нет README. Через год неизвестно происхождение файла и можно ли его удалить. Исправление: обязательный README с источником, датой и владельцем.
  • Смешивание dev и prod в одном каталоге. Тестовая сборка попадает в прод по ошибке. Исправление: окружение первым уровнем дерева и правами на каталоге.

Отдельная ошибка организационного плана: договорённости живут в головах, а не в документе. Как собрать такую договорённость в базу знаний, описано в статье База знаний IT в 2026: как систематизировать экспертизу и сократить простои команды.

Выбор NAS и файловой системы для хранилища

Две рабочие связки: TrueNAS с ZFS и OpenMediaVault с ext4 или XFS.

  • TrueNAS: снапшоты датасетов, контрольные суммы блоков с самовосстановлением в RAIDZ, квоты и отдельный датасет на окружение, ACL NFSv4, сжатие lz4, отправка zfs send на резервный узел. Требования к железу выше: 8-16 ГБ RAM под ARC.
  • OpenMediaVault: ext4 или XFS поверх mdadm, простой веб-интерфейс, низкие требования к железу, снапшоты только через LVM или Btrfs, возможностей для версионирования и аудита меньше.

Для хранилища с артефактами и аудитом подходит TrueNAS: отдельный датасет на окружение, снапшот перед миграцией, контрольная сумма ловит битый бинарник ещё до публикации. Команде из 3-5 человек с парой сотен гигабайт хватает OMV.

Минимальная конфигурация под 1-2 ТБ артефактов: 8 ГБ RAM (комфортно 16 ГБ), два диска в mirror, сеть 1 Гбит/с. Дедупликацию ZFS для бинарников включать не стоит: выигрыш близок к нулю, потребление памяти растёт линейно, при 8 ГБ RAM пул деградирует. Сжатие lz4 даёт 5-15% экономии на текстовых конфигах и скриптах почти без нагрузки на CPU.

Доступ: SMB для Windows-клиентов и офисной сети, NFS для Linux-серверов и узлов Kubernetes. Один датасет отдаётся обоими протоколами, права берутся из ZFS ACL, поэтому набор групп остаётся единым.

Автоматизация публикации и синхронизации артефактов

В dev публикация автоматическая, в prod только после подтверждения человеком. Шаг пайплайна для dev:

STAGE=/mnt/tank/devops-tools/dev/cli/helm/3.14.0
mkdir -p "$STAGE/bin"
cp helm "$STAGE/bin/helm"
sha256sum "$STAGE/bin/helm" > "$STAGE/checksum.sha256"
printf 'helm 3.14.0\nsource: upstream release\nadded: %s\n' "$(date -u +%F)" > "$STAGE/README.md"
ln -sfn 3.14.0 /mnt/tank/devops-tools/dev/cli/helm/latest
sha256sum -c "$STAGE/checksum.sha256"

Проверка суммы перед публикацией обязательна. Битый артефакт в хранилище опаснее отсутствующего: его скачивают, запускают и получают необъяснимую ошибку на стенде.

Для prod в пайплайн добавляют ручное подтверждение и перенос из dev после сверки:

rsync -aH --checksum /mnt/tank/devops-tools/dev/cli/helm/3.14.0/ \
  /mnt/tank/devops-tools/prod/cli/helm/3.14.0/

Права и структуру описывают декларативно: Ansible управляет ACL, владельцами и раскладкой каталогов, Terraform с провайдером TrueNAS создаёт датасеты, шары и политики снапшотов. Новый стенд тогда появляется из кода, а не из памяти администратора. S3-совместимый шлюз на NAS даёт артефактам HTTP-доступ, и CI тянет файлы стандартными клиентами.

Вебхуки на появление файла применяют только в dev. В prod триггер по изменению каталога обходит подтверждение и превращает выкладку в неконтролируемый процесс.

Мониторинг, бэкапы и восстановление

Мониторинг закрывает четыре метрики: свободное место на датасетах, состояние дисков и пулов, возраст последнего снапшота, ошибки контрольных сумм. В TrueNAS работают встроенные алерты и отчёты, для единой панели поднимают Prometheus с node_exporter и экспортёром ZFS, графики собирают в Grafana. Порог по свободному месту ставят на 20%, по температуре дисков на 45-50 °C.

Бэкап по схеме 3-2-1 для хранилища инструментов:

  • снапшоты ZFS каждые 4 часа с удержанием 7 дней: быстрый откат от случайной перезаписи;
  • rsync на второй NAS раз в сутки: копия на независимом железе;
  • restic в облако раз в сутки: защита от потери площадки. Для облачного плеча подойдёт S3-совместимое хранилище, например Timeweb Cloud.
zfs snapshot -r tank/devops-tools@daily-2026-09-11
zfs send -R tank/devops-tools@daily-2026-09-11 | ssh backup-nas zfs receive -F tank/tools
rsync -aH --delete /mnt/tank/devops-tools/ backup@nas2:/mnt/tank2/devops-tools/
restic -r "$RESTIC_REPOSITORY" backup /mnt/tank/devops-tools --exclude-caches
restic -r "$RESTIC_REPOSITORY" snapshots

Раз в квартал проверяйте восстановление: restic restore latest --target /tmp/restore-test либо клон снапшота в отдельный датасет, затем сверка checksum.sha256. Бэкап, из которого ни разу не восстанавливали файлы, ничего не подтверждает. Начните с одной команды mkdir -p /mnt/tank/devops-tools/{dev,stage,prod}, перенесите два инструмента в dev и проверьте, что скрипты команды работают с новых путей. Дальше структура и правила доступа масштабируются на все окружения без переделки.

Поделиться:
Сохранить гайд? В закладки браузера