Продвинутый

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

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

Практическое руководство по навыкам, которые используют реальные инженеры в .agents проектах: от контейнеризации до автоматизации инфраструктуры.

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

Практическое руководство по навыкам, которые используют реальные инженеры в .agents проектах: от контейнеризации до автоматизации инфраструктуры.

Контейнерные навыки для инженеров

Docker и Docker Compose

Во-первых, Docker позволяет упаковать приложение вместе с его зависимостями в неизменяемый образ, что упрощает развертывание на любых «домашних серверах».
Для простого теста создайте образ с Nginx, используя следующий Dockerfile:

dockerfile
# Dockerfile
FROM nginx:alpine
COPY index.html /usr/share/nginx/html/

Поместите index.html рядом с файлом, затем соберите изображение:

bash
docker build -t my-nginx .

Запустите контейнер, пробросив порт 8080 наружу:

bash
docker run -d -p 8080:80 --name web-demo my-nginx

Для более сложных сценариев, когда требуется несколько контейнеров (например, Plex + PostgreSQL), удобно использовать Docker Compose. Пример docker-compose.yml:

yaml
version: "3.9"
services:
  plex:
    image: plexinc/pms-docker:latest
    ports:
      - "32400:32400"
    volumes:
      - /home/alexey/media:/config/media
    environment:
      - PLEX_CLAIM=xxxxxxxxxxxx
  db:
    image: postgres:15
    environment:
      POSTGRES_PASSWORD: secret
    volumes:
      - pgdata:/var/lib/postgresql/data

volumes:
  pgdata:

После docker compose up -d оба сервиса будут работать в изоляции, а их конфигурация хранится в одном файле, что упрощает воспроизводимость на любых «домашних серверах».

Дополнительные сведения о Docker можно найти в официальной документации Docker Docs.


Kubernetes в production

k3s — легковесный дистрибутив Kubernetes, который отлично подходит для небольших кластеров из трёх «домашних серверов». Он требует минимальной настройки и легко интегрируется с существующими инструментами мониторинга.

Для развертывания простого веб‑службы создайте манифест deployment.yaml:

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-world
spec:
  replicas: 2
  selector:
    matchLabels:
      app: hello
  template:
    metadata:
      labels:
        app: hello
    spec:
      containers:
        - name: hello
          image: nginx:alpine
          ports:
            - containerPort: 80

Создайте сервис service.yaml для доступа к Deployment:

yaml
apiVersion: v1
kind: Service
metadata:
  name: hello-svc
spec:
  selector:
    app: hello
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: LoadBalancer

Примените оба файла:

bash
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml

Для внешнего доступа используйте Ingress‑контроллер, например Nginx Ingress. Пример ingress.yaml:

yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: hello-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
    - host: example.home
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: hello-svc
                port:
                  number: 80

После kubectl apply -f ingress.yaml сервис будет доступен по адресу http://example.home.

Для мониторинга и алертинга в production‑кластере рекомендуется использовать Prometheus и Alertmanager, их настройка подробно описана в официальной документации Kubernetes Docs.

Таким образом, Docker обеспечивает простоту изоляции и быстрого старта, а Kubernetes — управляемость и масштабируемость для реальных нагрузок в production‑среде.

Автоматизация инфраструктуры

Автоматизация инфраструктуры

Когда масштаб домашней лаборатории перерастает уровень одной Raspberry Pi, ручная настройка каждого сервиса становится ловушкой. Вы тратите время не на развитие проекта, а на повторение одних и тех же действий: создание пользователей, установку пакетов, правку конфигов. С практической точки зрения, автоматизация нужна не ради моды, а для обеспечения предсказуемости. Если вам нужно развернуть ещё одну ноду в кластер, вы должны сделать это одной командой, а не вспоминать, какой именно флаг вы использовали при установке Nginx в прошлый раз.

Ansible для конфигурации

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

В моей практике Ansible отлично справляется с задачей «приведения сервера к эталонному виду». Например, когда я готовлю новую ноду на Debian для работы с Docker, я не ввожу команды в терминал. Вместо этого я запускаю playbook, который настраивает SSH, устанавливает нужные репозитории и конфигурирует systemd.

Пример простого плейбука для подготовки системы:

yaml
---
- name: Prepare base system
  hosts: all
  become: true
  tasks:
    - name: Install essential packages
      apt:
        name:
          - curl
          - git
          - ufw
          - htop
        state: present
        update_cache: yes

    - name: Configure UFW to allow SSH
      ufw:
        rule: allow
        name: OpenSSH

    - name: Ensure systemd-journald is running
      systemd:
        name: systemd-journald
        state: started
        enabled: yes

С точки зрения инженера, преимущество здесь в идемпотентности. Вы можете запускать этот сценарий десять раз подряд, и если система уже настроена, Ansible ничего не изменит. Это избавляет от страха «сломать то, что работает».

Terraform и Terraform Cloud

Если Ansible отвечает за то, что происходит внутри операционной системы, то Terraform управляет самой инфраструктурой: виртуальными машинами, сетями и дисковыми пространствами. В проектах, где используется Proxmox или облачные провайдеры, Terraform позволяет описать всю топологию вашей лаборатории в виде кода (Infrastructure as Code).

Представьте, что вы решили развернуть полноценный кластер k3s. Вместо того чтобы вручную создавать три виртуальные машины в интерфейсе Proxmox, вы описываете их в .tf файлах.

Пример описания ресурса (упрощённый пример для понимания логики):

hcl
resource "proxmox_vm_qemu" "k3s_node" {
  count       = 3
  name        = "k3s-node-${count.index}"
  target_node = "pve-01"
  clone       = "debian-12-template"

  memory = 4096
  cores  = 2

  network {
    model  = "virtio"
    bridge = "vmbr0"
  }
}

Для управления состоянием инфраструктуры, особенно если над проектом работает несколько человек, я рекомендую использовать Terraform Cloud. Основная проблема при работе с Terraform локально — это файл terraform.tfstate. Если вы храните его на диске, вы рискуете потерять актуальную информацию о состоянии ресурсов или создать конфликт версий.

Terraform Cloud берёт на себя хранение стейта и предоставляет удобный интерфейс для запуска планов. Это превращает процесс из «я запустил команду у себя на ноутбуке» в управляемый цикл: вы вносите изменения в код, отправляете его в репозиторий, и облачный сервис выполняет terraform plan, показывая вам, что именно изменится в вашей инфраструктуре до того, как изменения будут применены. Это и есть та самая предсказуемость, к которой должен стремиться любой инженер.

Мониторинг и логирование

Мониторинг и логирование

В моей практике мониторинг — это не просто красивые графики в браузере, а инструмент предсказуемости. Если вы не видите, что происходит с системой, вы не управляете ей, а просто надеетесь на удачу. В проектах на базе .agents нагрузка может быть крайне неравномерной: агенты то простаивают, то резко потребляют все доступные ресурсы CPU или RAM. Без системы алертов вы узнаете о проблеме только тогда, когда сервис перестанет отвечать.

Я придерживаюсь принципа: мониторинг должен быть разбит на две составляющие — метрики (что происходит) и логи (почему это происходит).

Prometheus и Grafana

Для сбора метрик я использую стандарт индустрии — связку Prometheus и Grafana. Prometheus отлично справляется с хранением временных рядов, а Grafana превращает эти данные в понятные визуальные отчеты.

В контексте контейнеризированных агентов важно не просто собирать метрики самого Docker, но и понимать состояние конкретных процессов. Для этого я использую node_exporter на хостах и cadvisor для контейнеров.

Если вы разворачиваете инфраструктуру через Docker Compose, конфигурация для сбора метрик с контейнеров может выглядеть так:

yaml
services:
  prometheus:
    image: prom/prometheus:latest
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
    ports:
      - "9090:9090"

  cadvisor:
    image: gcr.io/cadvisor/cadvisor:latest
    volumes:
      - /:/rootfs:ro
      - /var/run:/var/run:ro
      - /sys:/sys:ro
      - /var/lib/docker/:/var/lib/docker:ro
      - /dev/disk/:/dev/disk:ro
    ports:
      - "8080:8080"

С практической точки зрения, самое важное здесь — правильно настроить алерты. Не нужно спамить уведомлениями о каждом скачке CPU до 80%. Настройте Prometheus Alertmanager, чтобы получать уведомления только при критических отклонениях, например, когда свободное место на диске падает ниже 10% или когда агент не отвечает более пяти минут.

Loki и journalctl

Метрики скажут вам, что память закончилась. Но чтобы понять, какой именно процесс вызвал утечку, нужно смотреть логи.

В современных Linux-системах основным источником событий является journald. Если вы работаете с bare-metal или виртуальными машинами (например, в Proxmox), вы будете использовать journalctl для первичной отладки. Например, чтобы посмотреть логи конкретного сервиса с момента последней загрузки, используйте:

bash
# Просмотр логов сервиса с фильтрацией по приоритету (ошибки и выше)
journalctl -u my-agent-service.service -p err -b

Однако для централизованного сбора логов в распределенной среде я предпочитаю стек Grafana Loki. Loki работает по принципу, похожему на Prometheus: он индексирует только метаданные (лейблы), а не весь текст лога. Это делает его гораздо менее требовательным к ресурсам диска, что критично для домашних серверов.

Чтобы связать логи с вашими метриками, настройте promtail — это агент, который читает логи и отправляет их в Loki. В конфигурации promtail важно правильно указать пути к логам:

yaml
# Пример фрагмента конфигурации promtail
scrape_configs:
  - job_name: system
    static_configs:
      - targets:
          - localhost
        labels:
          job: varlogs
          __path__: /var/log/*.log  # Собираем системные логи
  - job_name: journal
    journal:
      max_age: 12h
      labels:
        job: systemd-journal
    relabel_configs:
      - source_labels: ['__journal__systemd_unit']
        target_label: 'unit'

Такой подход позволяет вам в интерфейсе Grafana переходить от графика резкого роста потребления памяти к соответствующим строкам логов одним кликом. Это и есть системный подход к диагностике.

Хранение данных и резервное копирование

Хранение данных и резервное копирование

Когда мы говорим о надёжном хранении в рамках домашней лаборатории или небольшого проекта, главная задача — обеспечить предсказуемость. Вы должны точно знать, что данные не «рассыплются» при выходе из строя одного диска и что процесс восстановления не превратится в гадание на кофейной гуще. В моей практике я разделяю хранение на два уровня: уровень файловой системы и уровень протоколов доступа.

ZFS и TrueNAS

Если вы планируете использовать домашний сервер как основное хранилище, ZFS — это стандарт де-факто. Я не сторонник решений «на коленке», поэтому для работы с данными я использую TrueNAS. Это позволяет получить полноценный управляемый сторадж с отличной поддержкой ZFS.

Главное преимущество ZFS — это контроль целостности. Благодаря контрольным суммам (checksums) система сама обнаруживает «тихое повреждение» данных (bit rot) и, если у вас настроен зеркальный массив или RAID-Z, автоматически исправляет ошибки.

При создании пула (vdev) важно помнить о балансе между объёмом и отказоустойчивостью. Для критически важных данных, например, семейного архива или баз данных, я всегда выбираю RAID-Z2. Это позволяет пережить одновременный выход из строя двух дисков.

Пример создания пула через командную строку (если вы не используете GUI TrueNAS):

bash
# Создание пула 'tank' из трех дисков в режиме RAID-Z1
# Внимание: для критических данных лучше использовать RAID-Z2
zpool create tank raidz1 /dev/sda /dev/sdb /dev/sdc

После создания пула важно настроить автоматические снимки (snapshots). Снапшоты в ZFS — это не бэкап, но это важнейший инструмент для быстрого отката состояния системы. Если вы случайно удалили важный конфиг или файл, вы вернёте его за секунды.

Для автоматизации я использую zfs-autosnap или настраиваю systemd-таймер, который будет выполнять команду:

bash
# Создание снапшота текущего датасета
zfs snapshot tank/data@manual_backup_2023_10_27

Samba и NFS

Когда данные лежат на сервере, их нужно как-то раздать потребителям: Docker-контейнерам, виртуальным машинам или вашему ноутбуку. Здесь мы сталкиваемся с выбором между Samba (SMB) и NFS.

С практической точки зрения выбор зависит от того, кто клиент:

  1. NFS (Network File System) — идеален для Linux-сред. Если у вас кластер на Proxmox или набор нод с Docker, используйте NFS. Он работает быстрее, имеет меньше оверхеда и нативно понимает права доступа Linux (UID/GID).
  2. Samba (SMB) — необходим, если в вашей сети есть Windows-машины или если вы хотите удобно работать с файлами через проводник macOS.

Для настройки NFS на стороне сервера (например, на базе Debian) сначала установите пакет:

bash
sudo apt update && sudo apt install nfs-kernel-server

Затем отредактируйте файл /etc/exports, чтобы разрешить доступ конкретной подсети к вашему датасету. Я всегда придерживаюсь принципа минимальных привилегий: не открывайте доступ для всей сети, если в этом нет необходимости.

conf
# /etc/exports
# Разрешаем доступ подсети 192.168.1.0/24 к папке data с правами read/write
# no_root_squash позволяет клиенту с root-правами сохранять права root на сервере
/mnt/tank/data 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash)

После правки конфига примените изменения:

bash
sudo exportfs -ra

Для Samba конфигурация в /etc/samba/smb.conf выглядит чуть более громоздко, но она дает гибкость в управлении пользователями. Если вы настраиваете доступ для медиасервера (например, Plex), убедитесь, что у пользователя, под которым работает сервис, есть права на чтение этой директории в самой файловой системе.

ini
# /etc/samba/smb.conf
[Media]
   path = /mnt/tank/media
   browseable = yes
   read only = no
   guest ok = no
   valid users = alexey

В итоге: ZFS обеспечивает сохранность данных «внутри» железа, а правильно настроенные протоколы NFS или Samba — их доступность для ваших сервисов. Если эти два уровня работают предсказуемо, вы можете спать спокойно.

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

Как обеспечить предсказуемость при обновлении контейнеров

Для стабильной работы инфраструктуры не стоит использовать тег latest в конфигурациях Docker Compose или манифестах Kubernetes. С практической точки зрения лучше указывать конкретную версию образа, например postgres:15.4, чтобы при перезапуске сервиса не подтянулась новая версия с несовместимыми изменениями. Это гарантирует, что состояние вашей системы останется идентичным после любого сбоя или планового обслуживания.

В чём разница между использованием Docker и k3s в домашних лабораториях

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

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

При работе с контейнерами важно отделять жизненный цикл приложения от жизненного цикла данных. Для этого используйте монтирование внешних томов (volumes) или привязку директорий (bind mounts) к вашему основному хранилищу, например к ZFS-пулу на TrueNAS. Если хранить данные внутри слоя контейнера, вы потеряете их при первом же обновлении образа, что недопустимо для таких сервисов, как PostgreSQL или Plex.

Нужно ли использовать систему мониторинга для небольших проектов

Даже если у вас всего пара серверов, мониторинг необходим для понимания того, как распределяются ресурсы. Без Prometheus и Grafana вы узнаете о проблеме только тогда, когда сервис перестанет отвечать, а не когда у него закончится свободное место на диске или переполнится оперативная память. Настройка базовых алертов позволяет перейти от режима «тушения пожаров» к плановому обслуживанию инфраструктуры.

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