Продвинутый

Навыки реальных инженеров: практика из .agents directory

Алексей Кузнецов
Алексей Кузнецов
Системный администратор31 октября 2026 г.13 мин чтения

Практическое руководство по навыкам, необходимым реальным инженерам: Docker, Ansible, Proxmox, TrueNAS, мониторинг и оптимизация инфраструктуры.

Навыки реальных инженеров: практика из .agents directory

Практическое руководство по навыкам, необходимым реальным инженерам: Docker, Ansible, Proxmox, TrueNAS, мониторинг и оптимизация инфраструктуры.

Основательные инженерные практики

Основательные инженерные практики

Контейнеризация с Docker

Для работы с контейнерами удобно использовать Docker Engine — официальную реализацию контейнерного движка. На хосте, где планируется развертывание сервисов, сначала проверьте наличие пакета и его версию:

bash
docker version

Если пакет отсутствует, его можно установить из репозитория «stable»:

bash
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io

После установки запустите демон и проверьте его статус:

bash
sudo systemctl enable --now docker
sudo systemctl status docker

Сборка образа
Для простых веб‑служб удобно собрать образ из базового дистрибутива и скопировать нужные файлы:

dockerfile
FROM ubuntu:22.04

RUN apt-get update && apt-get install -y nginx && \
    rm -rf /var/lib/apt/lists/*

COPY index.html /var/www/html/
CMD ["nginx", "-g", "daemon off;"]

Поместите index.html рядом с Dockerfile, затем соберите образ:

bash
docker build -t my-nginx .

Запуск с Docker Compose
Для локального тестирования удобно использовать Docker Compose. Пример docker-compose.yml для сервиса Nginx, монтирующего локальный каталог с конфигурацией:

yaml
version: "3.9"
services:
  web:
    image: nginx:alpine
    ports:
      - "8080:80"
    volumes:
      - ./html:/usr/share/nginx/html:ro
    restart: unless-stopped

Запустите стек в фоне:

bash
docker compose up -d

Для получения более детальных рекомендаций по установке и использованию Docker см. официальную документацию — Docker documentation.

Автоматизация через Ansible

Ansible позволяет управлять конфигурацией множества хостов из одного места. Начните с создания инвентори — файла, где указаны адреса ваших серверов.

ini
[home_lab]
server1 ansible_host=192.168.1.10
server2 ansible_host=192.168.1.11

Сохраните файл как hosts.ini и укажите путь к нему в командной строке.

Playbook для установки Docker
Ниже пример playbook, который устанавливает Docker Engine, включает его в автозапуск и запускает сервис:

yaml
- hosts: home_lab
  become: true
  tasks:
    - name: Install Docker package
      apt:
        name: docker.io
        state: present
        update_cache: yes

    - name: Ensure Docker service is started and enabled
      systemd:
        name: docker
        state: started
        enabled: yes

Запустите playbook командой:

bash
ansible-playbook -i hosts.ini site.yml

Идемпотентность и повторное применение
Ansible гарантирует, что каждый запуск playbook приведёт систему к желаемому состоянию. Если Docker уже установлен, задача apt будет пропущена, а сервис — оставлен без изменений, если только его состояние не отличается от требуемого.

Для более сложных сценариев, например, развертывания нескольких сервисов в контейнерах, удобно использовать роли и переменные. Пример переменной, задающей порт для контейнера:

yaml
# group_vars/all.yml
docker_services:
  - name: web
    image: nginx:alpine
    port: 8080

В playbook можно entonces iterate over docker_services и генерировать нужные задачи динамически.

Проверка результата
После выполнения playbook убедитесь, что контейнеры работают:

bash
docker ps

Если все контейнеры в статусе Up, значит автоматизация завершена успешно.


Системный подход, использование systemd и документирование всех изменений позволяют поддерживать инфраструктуру в предсказуемом состоянии.

Инфраструктурный стек для реальных инженеров

Proxmox и виртуализация

Во-первых, Proxmox VE — это полноценный гипервизор, который позволяет запускать как виртуальные машины (VM), так и контейнеры (LXC). Для домашней лаборатории удобно использовать один сервер с несколькими нодами, объединёнными в кластер.

Создание VM

bash
# создаём VM с Ubuntu 22.04, 2 ядра, 4 ГБ RAM и диском 20 ГБ
qm create 101 --name ubuntu-home --memory 4096 --cores 2 --net0 virtio,bridge=vmbr0 --scsi0 storage:vm-101-disk-0,20G

Настройка хранилища ZFS
Если у вас уже есть пул ZFS на TrueNAS, его удобно подключить к Proxmox как отдельное хранилище.

bash
# добавляем ZFS‑пул как локальное хранилище (пример пути /mnt/zfs)
qm set 101 -scsi0 /mnt/zfs/ubuntu.qcow2

Бэкап и восстановление
Регулярные бэкапы — один из краеугольных камней предсказуемости.

bash
# создаём бэкап VM 101, сохраняем на отдельном диске
qm backup 101 --mode snapshot --storage backup-storage

Для автоматического создания ежедневных снимков удобно использовать systemd‑таймер:

ini
# /etc/systemd/system/qm-backup.timer
[Unit]
Description=Запуск бэкапа Proxmox VM каждый день в 02:00

[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true

[Install]
WantedBy=timers.target
ini
# /etc/systemd/system/qm-backup.service
[Unit]
Description=Выполнение бэкапа Proxmox VM

[Service]
Type=oneshot
ExecStart=/usr/bin/qm backup 101 --mode snapshot --storage backup-storage

После перезагрузки сервера таймер будет запускать бэкап автоматически.

Практическая точка зрения
Если требуется изолировать сети, создайте несколько виртуальныхbrücke в Proxmox (vmbr0 — для управления, vmbr1 — для Gastnet). Затем привяжите каждый интерфейс к нужному набору VM. Это позволяет разделить трафик управления и Gastnet‑трафика, что упрощает настройку firewall‑правил в Proxmox.

Официальная документация по работе с Proxmox VE: Proxmox VE Documentation.


TrueNAS и хранилище данных

Справедливо, TrueNAS (CORE или Scale) — это специализированная ОС для создания надёжного хранилища на базе ZFS. В домашней лаборатории я использую TrueNAS Scale, потому что она поддерживает Docker‑контейнеры и легко интегрируется с Kubernetes‑кластерами.

Создание пула ZFS

bash
# создаём пул 'tank' из трёх дисков (по 8 ТБ каждый) в режиме mirror+striped
zpool create -f tank mirror /dev/disk/by-id/ata-WDC_WD5000AAKX-001CA0_WD-WCAW5E1M4013_1 /dev/disk/by-id/ata-WDC_WD5000AAKX-001CA0_WD-WCAW5E1M4013_2 \
mirror /dev/disk/by-id/ata-WDC_WD5000AAKX-001CA0_WD-WCAW5E1M4013_3 /dev/disk/by-id/ata-WDC_WD5000AAKX-001CA0_WD-WCAW5E1M4013_4

Dataset для медиа‑файлов

bash
# создаём dataset 'media' с компрессией gzip и квотой 5 ТБ
zfs create -o compression=gzip tank/media
zfs set quota=5T tank/media

Экспорт NFS‑шаренга

bash
# добавляем NFS‑экспорт для каталога /mnt/tank/media
mkdir -p /mnt/tank/media
chmod 2775 /mnt/tank/media
echo "/mnt/tank/media *(rw,sync,no_subtree_check,no_root_squash)" >> /etc/exports
exportfs -ra

SMB‑шар (для Windows‑клиентов)

bash
# в веб‑интерфейсе TrueNAS → Services → SMB → Enable, затем:
# Create a share
# Path: /mnt/tank/media
# Name: Media
# Allow guest access: Yes (или настройте авторизацию)

Репликация между узлами
Если у вас есть второй сервер TrueNAS, настройте репликацию пула:

bash
# на основном сервере
zfs send -R tank@snap1 | ssh user@remote trueNAS zfs receive -F remote/tank

Для автоматизации репликации используйте midclt (CLI TrueNAS):

bash
midclt call replication.create_replication_task '{
    "replication": {
        "task": "tank",
        "direction": "outgoing",
        "remote": "ssh://user@remote",
        "schedule": "daily",
        "recursive": true
    }
}'

Мониторинг и алерты
В TrueNAS Scale можно подключить Prometheus‑exporter, а в CORE — использовать встроенную систему уведомлений (email, Slack). Пример настройки email‑уведомлений:

bash
# в веб‑интерфейсе → Alerting → Email
# SMTP‑сервер: smtp.example.com:587
# Логин: user@example.com
# Пароль: <your_password>
# Отправитель: trueNAS@example.com

Практическая точка зрения
Если требуется быстрый доступ к большим файлам с нескольких серверов, экспортируйте NFS‑шар. При этом рекомендуется использовать no_subtree_check и async для повышения производительности.

Официальная документация TrueNAS: TrueNAS Documentation.


Если понадобится более детальная настройка или примеры конфигураций, дайте знать — подготовлю дополнительные материалы.

Мониторинг и надёжность системы

Мониторинг и надёжность системы

Prometheus и Grafana

Во-первых, Prometheus собирает метрики через pull‑модель, а Grafana визуализирует их. Это сочетание позволяет быстро находить «пробелы» в производительности и реактивно реагировать.

Для быстрого старта удобно использовать Docker‑Compose. Ниже пример файла docker-compose.yml, который поднимает Prometheus и Grafana:

yaml
version: '3.8'
services:
  prometheus:
    image: prom/prometheus
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    ports:
      - "9090:9090"
    restart: unless-stopped

  grafana:
    image: grafana/grafana
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
    restart: unless-stopped

Файл prometheus.yml выглядит так:

yaml
global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'node'
    static_configs:
      - targets: ['localhost:9100']

Запуск:

bash
docker compose up -d

После этого Prometheus доступен по http://localhost:9090, а Grafana — по http://localhost:3000 (логин admin, пароль admin). В Grafana добавляем дата‑состав (datasource) → Prometheus → указываем URL http://prometheus:9090. Дашборд «Node Exporter Full» уже содержит готовые панели для CPU, памяти, сетевых статистик.

Для алертинга в Prometheus создаём файл alerts.yml:

yaml
groups:
  - name: node_alerts
    rules:
      - alert: NodeDown
        expr: up{job="node"} == 0
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "Узел node недоступен"
          description: "Метрика up равна 0 более 2 минут."

Подключаем файл в конфигурацию Prometheus и перезапускаем сервис. Аллерты будут приходить в Pushover, Slack или e‑mail через Alertmanager.

Официальная документация Prometheus
Grafana docs

Systemd и логирование

Системный менеджер systemd — это базовый инструмент управления сервисами в Linux. Он обеспечивает автозапуск, контроль состояния и журналирование. Правильный unit‑файл позволяет задать «предсказуемость» работы сервиса.

Пример unit‑файла для Docker‑Compose‑приложения myapp:

ini
[Unit]
Description=MyApp service
After=network.target

[Service]
ExecStart=/usr/local/bin/docker-compose -f /opt/myapp/docker-compose.yml up
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal
# Watchdog может быть включён, если приложение умеет посылать ready‑сигнал
# WatchdogSec=30

[Install]
WantedBy=multi-user.target

Помещаем файл в /etc/systemd/system/myapp.service, затем:

bash
systemctl daemon-reload
systemctl enable myapp.service
systemctl start myapp.service

Проверка статуса и журналов:

bash
systemctl status myapp.service
journalctl -u myapp.service -f          # follow‑mode
journalctl -p err -b                  # ошибки за текущий boot

Логирование через journald удобно, потому что все сообщения уже структурированы. Если требуется более продвинутый сборщик, можно настроить rsyslog или fluentd для отправки в Loki, а затем визуализировать в Grafana.

Для надёжности важно задать ограничения ресурсов, например:

ini
MemoryLimit=500M
CPUQuota=50%

Это предотвращает «залипание» сервиса и гарантирует, что при росте нагрузки система не будет полностью «забита».

man systemd.service


Эффективный мониторинг и надёжность — это фундамент, без которого даже самый продвинутый кластер будет хрупким. Системный подход, проверенные инструменты и чёткая документация позволяют держать инфраструктуру под контролем годами.

Оптимизация и поддержка инженерных решений

ZFS и резервное копирование

ZFS — это не просто файловая система, а набор средств, которые позволяют обеспечить предсказуемость данных на домашних серверах. Основные идеи: снимки (snapshots) — мгновенные копии данных, реplikция — передача снимков между системами, автоматическое управление — политики хранения снимков.

1. Создание и управление снимками

bash
# Посмотреть файловую систему и её свойства
zfs list -t all

# Создать снимок pool/data@backup_2024-09-01
zfs snapshot pool/data@backup_2024-09-01

Снимки хранятся в виде читаемого только‑для‑чтения слоя, поэтому их можно использовать для быстрого восстановления отдельных файлов или всего файла системы.

2. Репликация снимков на внешний хранилище

Если у вас есть второй сервер (например, NAS на базе TrueNAS), удобно отправлять снимки по SSH:

bash
# Отправитьincremental‑снимок с предыдущего backup_2024-08-01
zfs send -R pool/data@backup_2024-09-01 | ssh user@backup-host zfs receive -F backup/pool/data

Для автоматизации удобно добавить задачу в cron:

cron
0 2 * * * /usr/sbin/zfs snapshot -r pool/data@$(date +\%Y-\%m-\%d) && \
/usr/sbin/zfs send -R pool/data@$(date +\%Y-\%m-\%d) | ssh user@backup-host zfs receive -F backup/pool/data

3. Плановый очист (pruning) старых снимков

Не стоит хранить все снимки бесконечно. Пример скрипта, который удаляет снимки старше 30 дней:

bash
#!/bin/bash
POOL="pool/data"
DAYS=30

# Список снимков старше заданного количества дней
OLD_SNAPSHOTS=$(zfs list -t snapshot -o name -s creation -r $POOL | \
                awk -v d=$DAYS '$1 >= strftime("%Y-%m-%d", systime() - d*86400) {print $1}')

# Удаляем найденные снимки
for snap in $OLD_SNAPSHOTS; do
    zfs destroy $snap
done

Сохраните скрипт, например, как /usr/local/bin/zfs-prune.sh и добавьте его в cron ежедневно.

4. Интеграция с системой бэкапа

Для полной защиты рекомендуется комбинировать локальные снимки и удаленные копии. Локальные снимки позволяют быстро откатиться в случае случайного удаления файла, а удалённые копии защищают от физической гибели всего сервера.

Практический совет: если у вас есть TrueNAS, настройте репликацию через UI – это упрощает процесс и избавляет от необходимости писать скрипты вручную.


CI/CD и GitHub Actions

Автоматизация сборки, тестирования и деплоя — ключевой элемент современной инфраструктуры. GitHub Actions предоставляет простой способ orchestrать эти процессы без отдельного сервера CI.

1. Пример workflow для сборки Docker‑образа

Создайте файл .github/workflows/docker.yml в репозитории:

yaml
name: Build Docker image

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Log in to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USER }}
          password: ${{ secrets.DOCKER_PASS }}

      - name: Build and push image
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ${{ secrets.DOCKER_USER }}/my-app:latest

Что делает workflow:

  • При пуше в ветку main или pull‑request запускает сборку.
  • Использует buildx для мульти‑платформенной сборки (если нужно).
  • Авторизуется в Docker Hub через секреты, что не раскрывает пароль.
  • Собирает образ и сразу пушит его в реестр.

2. Деплой на Proxmox через API

Proxmox предоставляет REST‑API, которое удобно вызывать из GitHub Actions. Пример шага деплоя:

yaml
      - name: Deploy to Proxmox
        env:
          PM_API_URL: https://proxmox.example.com/api2/json
          PM_TOKEN: ${{ secrets.PM_TOKEN }}
        run: |
          # Получаем список контейнеров
          curl -s -H "Authorization: PVEAPIToken $PM_TOKEN" $PM_API_URL/nodes/node1/containers | jq .
          # Создаём новый контейнер из только‑что построенного образа
          curl -s -X POST -H "Authorization: PVEAPIToken $PM_TOKEN" \
               -H "Content-Type: application/json" \
               $PM_API_URL/nodes/node1/containers \
               -d '{
                     "args": ["--image", "'"$DOCKER_USER/my-app:latest"'"],
                     "net0": "virtio",
                     "name": "my-app",
                     "memory": 1024,
                     "netdev1": "bridge",
                     "ostype": "lxc",
                     "features": "nesting"
                   }'

Пояснение:

  • PM_TOKEN — токен с правами администратора, хранящийся в секретах.
  • jq используется для проверки ответа API (можно убрать, если не нужен).
  • Параметры контейнера (память, сеть) настраиваются в соответствии с вашими требованиями.

3. Тесты перед продакшном

В CI‑pipeline полезно добавить шаг, который запускает автоматические тесты контейнера:

yaml
      - name: Run container tests
        run: |
          docker run --rm -d -p 8080:80 ${{ secrets.DOCKER_USER }}/my-app:latest
          sleep 10
          curl -f http://localhost:8080/health || exit 1
          docker stop $(docker ps -q --filter ancestor=${{ secrets.DOCKER_USER }}/my-app:latest)

Этот блок проверяет, что приложение отвечает на эндпоинт /health и завершает контейнер после теста.

4. Роль GitHub Actions в системе мониторинга

После деплоя удобно включить мониторинг вsame workflow:

yaml
      - name: Notify Slack
        if: always()
        uses: 8398a7/action-slack@v3
        with:
          status: ${{ job.status }}
          fields: repo,commit,author
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}

Таким образом, команда сразу получает уведомление о успехе или провале сборки и деплоя, что уменьшает время отклика при возникновении проблем.

Итого: правильно настроенный CI/CD — это не просто автоматическое построение образа, а полностью проверенный путь от кода до работающего контейнера в домашней лаборатории. Используйте GitHub Actions для оркестрации, а Proxmox API — для гибкого деплоя. При этом всегда проверяйте результаты (тесты, логи) и поддерживайте чистоту конфигураций, чтобы система оставалась предсказуемой.

Часто задаваемые вопросы

Как обеспечить автоматический запуск Docker‑контейнеров после перезагрузки хоста?

Установите политику восстановления --restart unless-stopped при запуске контейнера или в файле docker‑compose.yml через параметр restart: unless-stopped. Это гарантирует, что Docker будет пытаться запустить контейнер при загрузке системы, даже если он был остановлен вручную. additionally, убедитесь, что сервис Docker включён в автозапуск (systemctl enable docker).

Как правильно организовать инвентори Ansible для разных окружений?

Разделяйте инвентори на поддиректории environments/dev, environments/staging и environments/prod, каждая из которых содержит свои файлы hosts.ini или inventory.yml и каталоги group_vars/ и host_vars/. Загружайте нужный инвентори через параметр -i или задайте путь в ansible.cfg. Такой подход упрощает поддержку и исключает конфликт настроек между средами.

Какие настройки ZFS рекомендуются для TrueNAS при работе с несколькими датасетами?

Создавайте отдельные датасеты для разных типов данных (например, media, backups, vm‑disks) и включайте сжатие lz4 для экономии места. Установите оптимальный recordsize (например, 128 КБ для баз данных, 4 МБ для больших файлов) и включите периодические скрипы (zfs scrub). Также используйте квоты и ограничения на запись, чтобы предотвратить переполнение отдельного датасета.

Какие метрики мониторинга следует отслеживать в Proxmox VE для выявления узких мест?

Отслеживайте нагрузку на CPU (steal time, %idle), объём используемой памяти и swap, IOPS и задержку диска (через iostat или zpool iostat), а также сетевой трафик и потери пакетов. Настройте алерты в Prometheus + Grafana на превышение порогов (например, CPU > 80 % в течение 5 минут или IOPS < baseline). Эти показатели позволяют быстро обнаружить узкие места в виртуальных машинах или в самом хосте.

Поделиться:TelegramX / TwitterVK