Продвинутый

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

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

Практическое руководство по навыкам, которые нужны инженерам, взятые из .agents‑директории. Как развивать профессиональные компетенции в реальном мире.

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

Практическое руководство по навыкам, которые нужны инженерам, взятые из .agents‑директории. Как развивать профессиональные компетенции в реальном мире.

Почему реальные навыки важнее формального образования

Определение реальных инженерных навыков

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

  • умение читать и интерпретировать логи (journald, Loki, syslog);
  • репродукцию ошибки в локальном окружении (docker run, pod sandbox);
  • написание автоматизированных решений (systemd‑юниты, скрипты на bash/python);
  • понимание зависимостей между сервисами (сетевые порты, конфиги);
  • поддержание предсказуемости конфигураций (версионирование, CI/CD).

Пример. При падении контейнера с Nginxtypical workflow выглядит так:

bash
# 1. проверка статуса сервиса
systemctl status nginx

# 2. просмотр последних записей журнала
journalctl -u nginx -f

# 3. воспроизведение ошибки в контейнере
docker run --rm -p 8080:80 nginx:latest

Такие практические приёмы rarely попадают в учебники, но они спасают в реальном времени.

Документация systemd описывает подробно работу с юнитами, что является фундаментом для надёжной автоматизации.

Как .agents‑директория формирует практические компетенции

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

  1. Описание ситуации – что именно «сломалось» в продакшене;
  2. Требования – какие инструменты и команды нужно использовать;
  3. Ключевые файлы – пример конфигураций, которые необходимо отредактировать;
  4. Ожидаемый результат – как проверить, что всё работает.

Пример задачи: настроить автоматический бэкап домашней базы данных PostgreSQL с помощью rsync и systemd‑timer.

ini
# /etc/systemd/system/pg-backup.service
[Unit]
Description=Бэкап PostgreSQL

[Service]
Type=oneshot
ExecStart=/usr/bin/rsync -a /var/lib/postgresql/13/main/ /backup/pg/
ini
# /etc/systemd/system/pg-backup.timer
[Unit]
Description=Расписание бэкапа PostgreSQL

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

[Install]
WantedBy=timers.target
bash
# Активация таймера
systemctl enable --now pg-backup.timer

Выполняя такие задачи, инженер привыкает:

  • работать с системными юнитами;
  • планировать расписание через systemd;
  • использовать rsync дляincremental‑бэкапов;
  • проверять результат через systemctl status pg-backup.service.

Кроме того, в .agents есть готовые примеры docker-compose.yml для микросервисных наборов, манифестов Kubernetes и Ansible‑playbook‑ов, что позволяет отработать навыки контейнеризации, оркестрации и конфигурационной автоматизации в условиях, близких к реальному производству.

Таким образом, .agents превращает абстрактные знания в отрабатываемые компетенции, делая инженера готовым к решению реальных задач без «решений на коленке».

Ключевые навыки, которые должны быть в портфолио инженера

Работа с системами и инфраструктурой

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

  • Системный мониторинг и логирование. На сервере с Ubuntu 22.04 я обычно ставлю prometheus-node-exporter и node_exporter, а затем визуализирую метрики в Grafana. Для быстрого поиска причин сбоев использую journalctl -u <service> --since "1 hour ago".

    bash
    # пример запроса журналов systemd‑сервиса
    journalctl -u nginx --since "2024-10-01 08:00" | grep -i error
    

    Документация systemd

  • Управление сервисами через systemd. Не полагайтесь на service‑скрипты – они устарели. Вместо этого пишем юнит‑файлы, которые гарантируют автозапуск и автоперезапуск. Пример unit‑файла для Nginx:

    ini
    [Unit]
    Description=NGINX web server
    After=network.target
    
    [Service]
    ExecStart=/usr/sbin/nginx -g 'daemon off;'
    Restart=on-failure
    RestartSec=5
    
    [Install]
    WantedBy=multi-user.target
    

    После размещения файла в /etc/systemd/system/nginx.service выполняем systemctl daemon-reload && systemctl enable --now nginx.

  • Резервное копирование. На моём Proxmox‑кластере использую zfs snapshot для быстрых инкрементальных снимков, а для файловой части — rsync с опцией --delete. Пример скрипта, который делает ежедневный бэкап домашней директории на TrueNAS:

    bash
    #!/usr/bin/env bash
    SRC="/home/alexey"
    DST="backup@truenas:/mnt/backup/home"
    DATE=$(date +%Y-%m-%d)
    
    zfs snapshot -r "tank/home@backup-$DATE"
    rsync -a --delete "$SRC"/ "$DST"/
    

    ZFS snapshots guide

  • Виртуализация и контейнеры. На Proxmox я размещаю VM‑ы с Debian 12, а для микросервисов — Docker‑контейнеры. Чтобы избежать «конфликтов» зависимостей, использую docker compose:

    yaml
    version: "3.9"
    services:
      plex:
        image: linuxserver/plex
        container_name: plex
        ports:
          - "32400:32400"
        volumes:
          - "/mnt/storage/media:/data"
        restart: unless-stopped
      nextcloud:
        image: linuxserver/nextcloud
        container_name: nextcloud
        ports:
          - "8080:80"
        volumes:
          - "/mnt/storage/nextcloud:/config"
        restart: unless-stopped
    

    Docker Compose official docs

Автоматизация и скриптование

Автоматизация — это то, что превращает рутинные операции в «один клик». На практике я использую несколько подходов:

  • Bash‑скрипты + cron. Простейший пример — скрипт, который раз в час проверяет, что диск не заполнен более 80 % и отправляет уведомление в Telegram:

    bash
    #!/usr/bin/env bash
    THRESHOLD=80
    USAGE=$(df / | tail -1 | awk '{print $5}' | tr -d '%')
    if [ "$USAGE" -gt "$THRESHOLD" ]; then
        curl -s "https://api.telegram.org/bot<token>/sendMessage?chat_id=<chat_id>&text=Disk usage is $USAGE%"
    fi
    

    Добавляем в crontab: 0 * * * * /home/alexey/scripts/disk_check.sh.

  • Systemd‑таймеры. Вместо cron я предпочитаю systemd-timer, потому что они интегрированы с системой и позволяют отслеживать статус выполнения. Пример таймера, который запускает резервный скрипт каждый день в 03:00:

    ini
    # /etc/systemd/system/backup.timer
    [Unit]
    Description=Run daily backup
    
    [Timer]
    OnCalendar=*-*-* 03:00:00
    Persistent=true
    
    [Install]
    WantedBy=timers.target
    

    А сам юнит‑файл:

    ini
    # /etc/systemd/system/backup.service
    [Unit]
    Description=Backup home directory
    
    [Service]
    Type=oneshot
    ExecStart=/home/alexey/scripts/backup.sh
    
    bash
    systemctl enable --now backup.timer
    
  • Ansible для конфигурации. Хотя я не использую Ansible для деплоя, он удобен для одноразовой настройки серверов. Минимальный playbook, который устанавливает nginx и htop:

    yaml
    - hosts: all
      become: true
      tasks:
        - name: Install nginx
          apt:
            name: nginx
            state: present
          when: ansible_os_family == "Debian"
    
        - name: Install htop
          apt:
            name: htop
            state: present
    

    Запуск: ansible-playbook -i inventory.ini site.yml.

  • CI/CD в контейнере. На работе с Kubernetes (k3s) я храню манифесты в Git‑репозитории и использую GitHub Actions для автоматического применения изменений:

    yaml
    name: Deploy to k3s
    on:
      push:
        branches: [ main ]
    jobs:
      deploy:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v3
          - name: Set up kubectl
            uses: azure/setup-kubectl@v2
            with:
              version: 'v1.27.0'
          - name: Deploy
            run: |
              kubectl apply -f k8s/
    

    GitHub Actions docs

Во-вторых, автоматизация должна быть прозрачной. Каждый скрипт или playbook документируется в комментариях, а результаты логируются в централизованный сервис (например, Loki). Это позволяет быстро находить причины сбоев без «гашения пожаров» на коленке.

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

Инструменты и технологии, используемые в реальных проектах

Инструменты и технологии, используемые в реальных проектах

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

Во-первых, Docker остаётся базовым инструментом для изоляции сервисов. На практике я обычно стартую с официального образа, а затем добавляю необходимые зависимости в Dockerfile. Пример минимального Dockerfile для небольшого веб‑сервиса на Python:

dockerfile
# Dockerfile
FROM python:3.11-slim

# Устанавливаем системные зависимости
RUN apt-get update && apt-get install -y --no-install-recommends \
    build-essential && \
    rm -rf /var/lib/apt/lists/*

# Копируем код и ставим зависимости из requirements.txt
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .
EXPOSE 8000
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "app:app"]

Сборка и запуск выглядит так:

bash
# Сборка образа
docker build -t myapp:latest .

# Запуск контейнера в режиме detached с пробросом порта
docker run -d --name myapp \
    -p 8000:8000 \
    -v /path/to/config:/app/config \
    myapp:latest

Для локального разработки удобно использовать Docker Compose. Пример docker-compose.yml для стека из веб‑сервиса и базы данных PostgreSQL:

yaml
# docker-compose.yml
version: "3.9"
services:
  web:
    build: .
    ports:
      - "8000:8000"
    environment:
      - DATABASE_URL=postgresql://user:password@db:5432/mydb
    depends_on:
      - db

  db:
    image: postgres:15-alpine
    environment:
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=password
      - POSTGRES_DB=mydb
    volumes:
      - pgdata:/var/lib/postgresql/data

volumes:
  pgdata:

Запуск всего стека одной командой:

bash
docker compose up -d

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

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

CI/CD и автоматизация развертывания

С практической точки зрения автоматизация развертывания сокращает количество «ручных» операций и повышает предсказуемость. В моём workflow я использую GitHub Actions для CI и простую Ansible‑playbook для CD, потому что Ansible позволяет описать состояние инфраструктуры в виде кода, а не в виде последовательных команд.

CI‑pipeline в GitHub Actions

Файл .github/workflows/ci.yml:

yaml
name: CI

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

jobs:
  build:
    runs-on: ubuntu-latest

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

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

      - name: Build image
        run: |
          docker build -t myapp:${{ github.sha }} .
          docker tag myapp:${{ github.sha }} myrepo/myapp:${{ github.sha }}

      - name: Push image to Docker Hub
        uses: docker/login-action@v2
        with:
          username: ${{ secrets.DOCKER_USER }}
          password: ${{ secrets.DOCKER_TOKEN }}
      - run: docker push myrepo/myapp:${{ github.sha }}

Эта конфигурация собирает образ, тегирует его SHA‑хешем и пушит в Docker Hub. При каждом push в main pipeline автоматически запускается, что позволяет быстро проверять корректность кода и сборки.

CD‑playbook на Ansible

Для развертывания на Proxmox‑нодах я использую Ansible, потому что он работает без постоянного доступа к SSH‑сессиям и позволяет хранить инвентарь в виде простого YAML‑файла.

inventory.ini:

ini
[proxmox]
proxmox01 ansible_host=192.168.1.10 ansible_user=root
proxmox02 ansible_host=192.168.1.11 ansible_user=root

deploy.yml:

yaml
---
- name: Deploy Docker stack
  hosts: proxmox
  become: true
  tasks:
    - name: Install Docker and Docker Compose
      apt:
        name:
          - docker.io
          - docker-compose
        state: present
        update_cache: yes

    - name: Pull latest image
      command: docker pull myrepo/myapp:latest
      environment:
        DOCKER_HOST: unix:///var/run/docker.sock

    - name: Deploy stack with Docker Compose
      command: docker compose -f /opt/myapp/docker-compose.yml up -d
      args:
        chdir: /opt/myapp

Запуск playbook:

bash
ansible-playbook -i inventory.ini deploy.yml

Таким образом, после пуша в репозиторий образ автоматически попадает в Docker Hub, а Ansible гарантирует, что на всех нодах кластера запущен актуальный стек. Если какая‑то нода не отвечает, playbook просто завершится с ошибкой, и я получу алерт от Prometheus, а не «пожар» вручную.

Документация GitHub Actions
Ansible official guide


Таким образом, Docker и CI/CD‑инструменты становятся неотъемлемыми частями современной инфраструктуры домашнего сервера. Они позволяют держать окружение в надёжном и воспроизводимом состоянии, а также быстро реагировать на изменения в коде. Если вы только начинаете, начните с простого Dockerfile и GitHub Actions, а затем постепенно добавляйте Ansible и мониторинг. Это путь, который я прошёл от LAMP‑стека до многонодового кластера, и он проверен годами реального использования.

Практика и постоянное развитие: как стать настоящим инженером

### Домашняя лаборатория и эксперименты

Создание домашней лаборатории — это не просто хобби, а постоянный полигон для отработки навыков. На моём сервере на базе Dell PowerEdge R730 я разместил три виртуальные машины в Proxmox VE: Винни‑Пух (основной контроллер), Пятачок (служба баджа) и Сова (тестовая среда для Kubernetes).

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

yaml
version: "3.8"
services:
  plex:
    image: linuxserver/plex
    container_name: plex
    ports:
      - "32400:32400/tcp"
    volumes:
      - /mnt/storage/media:/config/media
      - /mnt/storage/config:/config
    restart: unless-stopped

  nextcloud:
    image: linuxserver/nextcloud
    container_name: nextcloud
    ports:
      - "8080:80"
    volumes:
      - /mnt/storage/nextcloud:/config
    environment:
      - MYSQL_PASSWORD=secret
    restart: unless-stopped

  backup:
    image: alpine:latest
    container_name: backup
    volumes:
      - /mnt/storage:/data
    entrypoint: ["sh", "-c", "tar czf /backup/$(date +%F).tar.gz /data && echo 'backup completed'"]
    restart: "no"

Команда запуска:

bash
docker compose up -d

После старта проверяю, что контейнеры работают предсказуемо, смотрю логи через docker logs <container> и убеждаюсь, что каждый сервис имеет отдельный лог‑файл в journald.

Для периферии использую два Raspberry Pi: один как контроллер домашнего Wi‑Fi (hostapd + dnsmasq), второй — как точку доступа для камер surveillance (mjpg‑streamer). Оба устройства подключены к домашней сети через VLAN, что позволяет изолировать экспериментальный трафик от основной инфраструктуры.

Практический совет: фиксируйте каждую экспериментальную конфигурацию в Git‑репозитории. Даже простая docker-compose.yml в отдельном каталоге позволяет откатиться к предыдущей версии и понять, какие изменения привели к проблеме.


### Регулярный аудит и улучшение

Аудит — это не разовый акт, а циклический процесс, который делает инфраструктуру предсказуемой. Я планирую аудит раз в квартал, чётко расписывая задачи в TODO‑файле, а затем проверяю их статус в git commit -am "audit: check X".

Шаг 1. Проверка системных сервисов
Системд‑юниты отвечают за предсказуемость. Команда для просмотра статуса всех юнитов:

bash
systemctl list-units --type=service --state=running

Если найдены юниты в состоянии failed, сразу же анализирую их журнал:

bash
journalctl -u <unit_name> --since "1 day ago"

Шаг 2. Состояние хранилищ
Для ZFS‑пула tank использую zpool status и zfs list. Пример вывода, который меня интересует:

bash
zpool status tank
  pool: tank
 state: ONLINE
  scan: none required
config:

        NAME        STATE     READ WRITE CKSUM
    tank        ONLINE       0     0     0
      raidz1-0  ONLINE       0     0     0
        sda3    ONLINE       0     0     0

Если SMART‑данные указывают на износ дисков, планирую замену до полной отказности.

Шаг 3. Обновление пакетов и образов
Для поддержания безопасности применяю автоматические обновления через unattended-upgrades (Debian/Ubuntu) и docker pull в CI‑pipeline. Пример скрипта, который можно добавить в cron:

bash
#!/bin/bash
apt update && apt upgrade -y
docker pull linuxserver/plex:latest
docker pull linuxserver/nextcloud:latest

Шаг 4. Аудит сетевых правил
Проверяю правила ufw или nftables. Пример вывода ufw status verbose:

bash
Status: active

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW       Anywhere
80/tcp                     ALLOW       Anywhere
443/tcp                    ALLOW       Anywhere
22/tcp (v6)                ALLOW       Anywhere (v6)
80/tcp (v6)                ALLOW       Anywhere (v6)
443/tcp (v6)               ALLOW       Anywhere (v6)
23/tcp                     DENY        Anywhere

Если в правилах присутствуют устаревшие порты, удаляю их:

bash
ufw delete allow 23/tcp

Шаг 5. Мониторинг и оповещения
Prometheus собирает метрики, а Alertmanager генерирует уведомления в Slack. Пример правила в alerts.yml:

yaml
groups:
- name: node_exporter
  rules:
  - alert: HighLoad
    expr: node_load1 > 0.8
    for: 5m
    labels:
      severity: warning
    annotations:
      summary: "High load on {{ $labels.instance }}"
      description: "Load average is above 0.8 for more than 5 minutes."

Эти оповещения позволяют быстро реагировать, не дожидаясь обращения пользователя.

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

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

Как быстро начать применять эти навыки на практике?

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

Нужно ли учить теорию, если я сосредоточусь на практике?

Теория и практика — это две стороны одной медали, и пытаться развиваться только в одном направлении неэффективно. Если вы понимаете, как работает systemd, но не знаете основ сетевого взаимодействия (модель OSI или работу протокола TCP), вы столкнётесь с трудностями при отладке сетевых задержек. Хороший инженер использует практику для закрепления фундаментальных знаний, превращая абстрактные концепции в предсказуемые инструменты.

Какие инструменты стоит освоить в первую очередь?

Если вы только начинаете путь, я рекомендую сфокусироваться на Linux-окружении и контейнеризации. В первую очередь разберитесь с управлением процессами через systemd, научитесь работать с текстовыми редакторами в терминале и освойте базовые команды docker и docker-compose. Эти инструменты являются стандартом индустрии, и владение ими обеспечит вам базу для работы с любыми современными распределёнными системами.

Как понять, что я действительно освоил навык, а не просто скопировал команду?

Критерием успешного освоения является предсказуемость ваших действий и понимание того, что именно делает каждая строка в конфиге или скрипте. Если вы можете объяснить, почему вы используете именно этот флаг в команде journalctl или зачем в systemd-юните указана директива Restart=on-failure, значит, навык закреплён. Всегда стремитесь к тому, чтобы любая ваша команда была обоснована логикой работы системы, а не простым копированием из документации.

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