RE:NODE

Как учить DevOps: с чего начать и что пропустить

Автор Команда RE:NODE
17 мин чтения


Если вы хотите запускать серверы и выпускать софт, учитесь в таком порядке: Linux и shell, затем один небольшой сервер, который вы проводите от чистой машины до работающего приложения с мониторингом и бэкапами, затем systemd, Nginx, Docker и пайплайн деплоя - именно в этом порядке, и каждый шаг заменяет то, что вы уже делали руками. Kubernetes, service mesh и multi-cloud идут позже, если вообще понадобятся. Большинство тех, кто застревает в DevOps, застревает потому, что начали с верха этого списка, а не с низа.

Мы развиваем хостинг-платформу RE:NODE, на которой работает более 1 200 серверов для более чем 500 клиентов. Платформа показывает, какие навыки на самом деле держат парк серверов на ходу по ночам, а типичные способы учиться - какие из этих навыков люди пытаются пропустить. Этот текст - путь для любого, кто начинает с нуля, вместе с причинами, потому что именно причины позволяют самостоятельно оценить следующий инструмент.

Порядок и почему именно такой#

Принцип простой: никогда не автоматизируйте то, что не делали руками. Каждый инструмент DevOps - обёртка над ручной работой: запустить процесс, направить запрос, скопировать файлы на сервер, проверить, что что-то работает. Если сначала учить обёртку, можно идти по туториалу, но в первый же сбой под ней не окажется ничего, на что можно опереться.

ЭтапЧто вы изучаетеВы закончили, когда
1. Linux и shellФайлы, права, процессы, логиМожете выяснить, почему умер процесс
2. Один VPSSSH, firewall, пользователи, обновленияМожете пересобрать его по заметкам
3. systemdСервисы, перезапуски, journaldПриложение переживает перезагрузку
4. NginxReverse proxy, TLS, статические файлыУ приложения есть домен и HTTPS
5. DockerОбразы, тома, сети, ComposeМожете перенести приложение на новую машину
6. CI/CDСборка, тесты, деплой по pushНикто не запускает scp вручную
7. Мониторинг и бэкапыАлерты, восстановлениеВы намеренно восстановили бэкап

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

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

Сначала Linux и shell#

Почти всё в этой области работает на Linux, и почти любая проблема, которую вы будете отлаживать, - это проблема Linux в маскарадном костюме. Контейнер, который не запускается, - обычно права, отсутствующий файл или занятый порт. Медленный деплой - обычно диск или сеть. "Случайный" сбой часто оказывается OOM killer ядра. Ничего из этого не увидеть, если shell для вас - место, куда заходят лишь вставить команды.

С чем нужно освоиться до первого контейнера:

  • Навигация и чтение файлов: cd, ls -la, cat, less, tail -f, grep, find.
  • Права и владельцы: что значит rwx, chmod, chown, почему сервис от www-data не прочитает файл root с режимом 600.
  • Процессы: ps aux, top или htop, kill, что такое сигнал, разница между SIGTERM и SIGKILL.
  • Диск и память: df -h, du -sh, free -h и почему "диск заполнен" может означать и "кончились inode".
  • Основы сети: ss -tlnp, чтобы увидеть, кто слушает, curl -v, чтобы увидеть, что на самом деле делает запрос, dig, чтобы увидеть, во что разрешается имя.
  • Логи: journalctl -u name, /var/log и привычка прочитать последние 50 строк, прежде чем гадать.
bash
# The five commands to answer before anyone says "it doesn't work"$ systemctl status myapp          # is it running, and what did it last say$ journalctl -u myapp -n 50       # the last 50 lines it logged$ ss -tlnp                        # what is listening, on which port, as which process$ df -h && free -h                # disk and memory, the two boring killers$ curl -v http://127.0.0.1:3000/  # does it answer locally, before blaming DNS

Важнее всего в shell не запомнить флаги, а привыкнуть спрашивать машину, а не гадать. Новички часто меняют три вещи сразу, перезапускают и надеются. Правило лучше такое: одно изменение, один перезапуск, чтение лога. Первые десять минут это медленнее, а всю дальнейшую карьеру значительно быстрее. Более подробный справочник - в статье команды Linux для администраторов серверов.

Выучите Bash настолько, чтобы написать скрипт на двадцать строк с переменной, if, циклом и set -euo pipefail в начале. Быть сильным в Bash не нужно. Нужно уметь читать скрипты, которые другие люди оставляют на серверах, а их будет много.

Один VPS от начала до конца#

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

Путь по порядку:

  1. Войдите по SSH, создайте обычного пользователя с sudo и переключитесь на вход по ключу. Отключите вход по паролю и вход под root, когда ключ заработает, не раньше, иначе вы запрёте себя снаружи.
  2. Включите firewall, который сначала разрешает SSH, а затем только нужные порты. В Ubuntu это ufw allow OpenSSH, затем ufw enable.
  3. Включите автоматические обновления безопасности и научитесь перезагружать машину без страха.
  4. Установите runtime и запустите приложение вручную, на переднем плане, пока оно не заработает.
  5. Превратите его в сервис systemd.
  6. Поставьте перед ним Nginx с доменом и сертификатом.
  7. Добавьте бэкап, проверку доступности и алерт по диску.
  8. Запишите каждый шаг, затем уничтожьте сервер и пересоберите его по своим заметкам.

Восьмой шаг пропускают чаще всего, и он учит больше всего. Первая пересборка - момент, когда обнаруживается забытая изменённая настройка, пакет, установленный при отладке, файл в /etc, отредактированный в полночь. Этот разрыв между "что, по-вашему, есть на сервере" и "что на нём на самом деле" - именно та проблема, ради которой существуют системы управления конфигурацией и контейнеры. Почувствуйте её один раз, и вы поймёте, зачем нужны эти инструменты, а не просто выучите их синтаксис.

Первые шаги подробно описаны в статьях первый час на новом VDS и SSH-ключи и защита.

Как практиковаться на дешёвом сервере

Много не нужно. Машина с 1-2 ГБ RAM и одним-двумя ядрами спокойно тянет небольшое веб-приложение, Nginx, базу данных и агент мониторинга в учебных целях. Важнее размера другое:

  • Это должен быть настоящий публичный сервер. Виртуальная машина на ноутбуке подойдёт для shell, но скрывает то, что болит: DNS, сертификаты, firewall, смотрящий в интернет, боты, которые подбирают SSH-пароли через считанные минуты после появления адреса.
  • Он должен быть одноразовым. Относитесь к нему как к тому, что вы сотрёте и соберёте заново. Если страшно сломать, на нём ничему не научиться.
  • Дайте ему домен. Дешёвый домен с A-записью на сервер позволяет нормально попрактиковаться с TLS, редиректами и виртуальными хостами, а не обходить их.
  • Поставьте оповещение о бюджете или выберите тариф с фиксированной ценой. Облачные аккаунты с поминутной оплатой и без лимита - плохое место для учёбы, потому что дорогая ошибка - та, которую не замечаешь.

Ломайте намеренно. Заполните диск с помощью fallocate -l и посмотрите, что откажет первым. Убейте приложение через kill -9 и проверьте, вернёт ли его systemd. Остановите Nginx и посмотрите, что скажет браузер. Удалите базу данных и восстановите её. Каждая из этих поломок встретится вам позже по-настоящему, а встретить её на учебной машине бесплатно.

systemd: часть, которую все пропускают#

Новички часто идут прямо от "работает в моём терминале" к "работает в Docker" и пропускают слой, который на самом деле поддерживает процессы живыми на Linux-машине. Это ошибка, потому что даже если в итоге всё работает в контейнерах, сам container runtime - сервис systemd, и навыки отладки переносятся напрямую.

Unit-файл короткий, и написать его вручную - значит понять, что такое "работать в продакшене": фиксированный пользователь, рабочий каталог, окружение, политика перезапуска и логи, которые уходят туда, где их можно прочитать.

/etc/systemd/system/myapp.service
[Unit]Description=My appAfter=network-online.targetWants=network-online.target[Service]User=myappWorkingDirectory=/opt/myappEnvironmentFile=/etc/myapp/envExecStart=/usr/bin/node /opt/myapp/server.jsRestart=on-failureRestartSec=5[Install]WantedBy=multi-user.target

Затем systemctl daemon-reload, systemctl enable --now myapp и journalctl -u myapp -f, чтобы наблюдать. Если вы понимаете, зачем здесь Restart=on-failure, почему приложение не запускается от root и почему секреты лежат в EnvironmentFile с жёсткими правами, а не в самом unit, вы знаете о продакшене больше многих, у кого в резюме указан Kubernetes. Полный разбор - в статье сервисы systemd для ваших приложений.

Nginx перед всем остальным#

Следующий слой - reverse proxy. Ваше приложение слушает 127.0.0.1:3000, а Nginx слушает порты 80 и 443, завершает TLS, отдаёт статические файлы и пересылает всё остальное. На этом паттерне держится большая часть веба, и если освоить его вручную, любой управляемый балансировщик и ingress controller, которые встретятся позже, станут очевидными.

/etc/nginx/sites-available/myapp
server {    listen 80;    server_name app.example.com;    location / {        proxy_pass http://127.0.0.1:3000;        proxy_set_header Host $host;        proxy_set_header X-Real-IP $remote_addr;        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;        proxy_set_header X-Forwarded-Proto $scheme;    }}

Получите сертификат через Certbot, проверьте продление командой certbot renew --dry-run и запускайте nginx -t перед каждой перезагрузкой конфигурации. Стоит понять, а не копировать: почему приложение должно слушать localhost, а не 0.0.0.0, зачем нужны forwarded-заголовки и почему в логах приложения для каждого посетителя виден 127.0.0.1, пока вы не объясните ему, что прокси надёжен. Руководство по Nginx reverse proxy идёт дальше, включая WebSocket и таймауты.

Docker, когда понятно, что он заменяет#

Docker - место, где больше всего путаницы, и почти вся она из-за слишком раннего знакомства. Если вы уже запускали приложение как сервис systemd за Nginx, Docker легко разместить на карте: образ - упакованная версия файлов и runtime, которые вы ставили вручную, контейнер - процесс, который запускал systemd, том - каталог данных, о бэкапе которого приходилось помнить, а опубликованный порт - строка listen, которую вы уже понимаете.

Что должен вынести из Docker учащийся на этом этапе:

  • Написать Dockerfile для собственного приложения, а не только скачивать чужие образы.
  • Понимать слои настолько, чтобы расположить инструкции так, чтобы зависимости кэшировались.
  • Знать, что файловая система контейнера выбрасывается, а всё важное живёт в томе.
  • Использовать Docker Compose, чтобы запускать приложение и его базу данных вместе, с именованным томом для данных.
  • Публиковать порты осознанно и знать, что опубликованные порты Docker могут обходить правила ufw на том же хосте, потому что Docker пишет собственные правила iptables.
compose.yaml
services:  app:    build: .    restart: unless-stopped    env_file: .env    ports:      - "127.0.0.1:3000:3000"    depends_on:      - db  db:    image: postgres:16    restart: unless-stopped    environment:      POSTGRES_PASSWORD_FILE: /run/secrets/db_password    volumes:      - dbdata:/var/lib/postgresql/data    secrets:      - db_passwordvolumes:  dbdata:secrets:  db_password:    file: ./db_password.txt

Обратите внимание на 127.0.0.1: перед опубликованным портом. Без него приложение доступно из интернета напрямую, в обход Nginx и firewall, который, как вам казалось, у вас есть. Эта деталь хорошо проверяет, выучил ли человек Docker или скопировал. Подробнее - в статьях Docker на VDS и Docker Compose для небольших стеков.

CI/CD: автоматизируйте то, что уже делаете руками#

К этому моменту вы уже несколько раз выкатывали руками: забрать код, поставить зависимости, собрать, перезапустить сервис. Эта ручная последовательность и есть ваш пайплайн. CI/CD - это запись её в файл, чтобы машина выполняла её каждый раз одинаково, а перед ней стояли тесты, чтобы сломанный коммит останавливался до сервера.

Начните с самого маленького честного пайплайна: запускайте тесты на каждый push и выкатывайте основную ветку, когда они проходят. GitHub Actions - разумное место для обучения, потому что бесплатного лимита для этого хватает с запасом, а синтаксис встречается повсюду.

.github/workflows/deploy.yml
name: test-and-deployon:  push:    branches: [main]jobs:  test:    runs-on: ubuntu-latest    steps:      - uses: actions/checkout@v4      - uses: actions/setup-node@v4        with:          node-version: 22      - run: npm ci      - run: npm test  deploy:    needs: test    runs-on: ubuntu-latest    steps:      - name: Deploy over SSH        run: |          echo "${{ secrets.DEPLOY_KEY }}" > key && chmod 600 key          ssh -i key -o StrictHostKeyChecking=accept-new \            deploy@${{ secrets.HOST }} 'cd /opt/myapp && ./deploy.sh'

Задача deploy просто вызывает deploy.sh, лежащий на сервере, - тот же скрипт, который вы запускали бы вручную. Такой вариант лучше, чем помещать весь деплой в файл workflow: когда пайплайн ломается, можно зайти по SSH и запустить скрипт самому, чтобы увидеть, что происходит. Дайте ключу деплоя отдельного пользователя с доступом только к этому каталогу и ни к чему больше.

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

Мониторинг и бэкапы входят в первый деплой#

Это неудобная часть. Большинство учебных планов считает мониторинг и бэкапы продвинутыми темами, которые добавляют "потом". Потом обычно наступает после первой потери. Мы считаем их частью первого развёртывания, потому что сервис без того и другого - демо, а не сервис.

Минимум небольшой:

ЧтоЗачемПростейший вариант
Проверка доступности снаружиВы узнаёте об отказах раньше пользователейБесплатная внешняя HTTP-проверка
Алерт по дискуПолные диски тихо ломают всёОповещение при 80% занятого
Логи, по которым можно искатьМожно ответить "что было в 03:00"journald с постоянным хранилищем
Бэкап вне машиныСам сервер можно потерятьНочной дамп, скопированный в другое место
Проверенное восстановлениеДоказывает, что бэкап настоящийРаз в месяц восстановление на тестовый сервер

Бэкап, который никто не восстанавливал, - гипотеза. Проверка простая: возьмите вчерашний дамп базы, восстановите его на чистой машине и запустите приложение на нём. Если вы не можете сделать это по своим заметкам, бэкапов у вас ещё нет. Допустим, диск ноды заполняется в три ночи - полезные вопросы такие: дошёл ли алерт до человека, пока диск не заполнился, и существуют ли данные до заполнения где-то помимо этого диска.

У мониторинга обратная беда. Новички часто ставят дашборд с двумястами графиков и без алертов, а это декорация. Начните с трёх-четырёх алертов, каждый из которых значит "человеку нужно что-то сделать сейчас", и добавляйте новые, только когда инцидент покажет пробел. Полезное правило такое: алерт, на который никто не реагирует, нужно удалять, а не заглушать. См. мониторинг, который что-то сообщает и бэкапы, которые действительно восстанавливаются.

Что пропустить в начале#

Пропускать - это навык. В этой области больше инструментов, чем способен выучить один человек, и большинство решают проблемы, которых у вас ещё нет. Вот что стоит оставить в покое, пока базовое не станет скучным:

Пока пропуститьПочемуВернуться, когда
KubernetesРешает планирование на многих машинахУ вас несколько хостов
Terraform в масштабеРаскрывается на множестве облачных ресурсовРучная пересборка стала мучительной
Service meshРешает трафик между множеством сервисовУ вас много сервисов
Multi-cloudУдваивает всё, что нужно учитьДля большинства никогда
МикросервисыДобавляют сетевые сбои вездеОдно приложение стало слишком большим
Десять сертификатовДоказывают учёбу, а не эксплуатациюОдин нужен для работы

Про Kubernetes нужно сказать прямо, потому что именно с него новички хотят начать чаще всего. Это хороший инструмент для планирования контейнеров на многих машинах. Но каждое его понятие - pod, service, ingress, persistent volume, probe, secret - абстракция над чем-то из предыдущих этапов: процессом, портом, reverse proxy, диском, проверкой работоспособности, файлом окружения. Если учить Kubernetes первым, вы выучите абстракции без того, что они абстрагируют, и отладка превращается в гадание. Если учить после одного VPS, Docker и Nginx, большая часть читается как "а, это то, что я уже делал, только описанное в YAML".

Мы не говорим, что Kubernetes плох или что он вам никогда не понадобится. Мы говорим, что для одного приложения на одном-двух серверах это большой объём механизмов, защищающих от проблем, которых у вас нет, и что изучение его первым замедляет.

Заблуждения, с которыми часто приходят новички#

Эти шаблоны встречаются достаточно часто, чтобы разобрать их в самом начале, и это не истории о конкретных людях.

  • "DevOps - это набор инструментов." Это способ работы: люди, которые пишут софт, отвечают и за то, как он работает, а всё, что делается дважды, автоматизируется. Инструменты меняются каждые несколько лет. Привычки нет.
  • "У меня на машине работает, значит, проблема в сервере." Обычно разница в конфигурации, версиях, переменных окружения или путях к файлам. Найти эту разницу - и есть работа.
  • "Контейнеры безопасны по умолчанию." Контейнер, запущенный от root, с опубликованным портом и смонтированным каталогом хоста, не изолирован ни в каком значимом смысле. Контейнеры - прежде всего упаковка.
  • "Больше инструментов значит профессиональнее." Лучшие системы скучны: мало подвижных частей, и каждая понятна. Каждый добавленный инструмент нужно обновлять, мониторить и отлаживать.
  • "На собственном сервере root - это нормально." Нормально, пока уязвимое приложение под root не отдаст злоумышленнику всю машину. Отдельные пользователи ничего не стоят.
  • "Бэкапы делает провайдер." Иногда. Выясните точно, что копируется, где хранится и как проходит восстановление, до того как оно понадобится.
  • "Мне нужно запоминать команды." Нужно знать, что возможно и где смотреть. Чтение man-страниц и логов - вот навык. Память приходит с практикой.

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

Чему платформа хостинга учит насчёт порядка#

Работа RE:NODE - это автоматизированная выдача, масштабирование и восстановление на десятках нод и 30+ сервисах, с RBAC, мониторингом, автоматизацией бэкапов и реагированием на инциденты поверх. Ничего из этого не начиналось как сложный инструментарий. Всё начиналось с ручных шагов, которые были понятны, потом они стали скриптами, потом сервисами, потом оркестрацией. Каждый слой автоматизации было безопасно строить, потому что нижний уже был понят.

В этом и состоит весь аргумент текста. Порядок не произвольный. Каждый этап превращает предыдущий в то, о чём можно больше не думать, а безопасно перестать думать можно только о том, что когда-то было продумано тщательно. Тем, кто начинает с верха, приходится спускаться вниз, когда что-то ломается, в худший момент. Те, кто начинает с низа, поднимаются вверх в своём темпе.

AI-агенты для кода сделали всё это правдивее, а не наоборот. Агент с готовностью напишет Dockerfile, unit-файл или пайплайн за секунды. Но правилен ли этот файл, безопасен ли и подходит ли вашему серверу - это суждение, которое может вынести только тот, кто понимает слои. Навык, который дешевеет, - набирать конфигурацию. Навык, который дорожает, - читать её.

FAQ#

Сколько времени нужно, чтобы выучить основы DevOps?

Зависит от того, сколько времени вы проводите в терминале, а не за чтением. Пройти описанные этапы на настоящем сервере, включая пересборку по заметкам и восстановление бэкапа, - это месяцы регулярной практики, а не недели. Дольше всего осваивается Linux, и каждый потраченный на него час окупается.

Нужно ли уметь программировать до изучения DevOps?

Нужно достаточно, чтобы читать код и писать небольшие скрипты: Bash, чтобы склеивать команды, и один универсальный язык вроде Python для всего более длинного. Также нужно понимать, как устроены и настраиваются приложения, которые вы выкатываете, потому что большинство проблем деплоя лежит на границе между приложением и сервером.

Учить сначала AWS, Azure или Google Cloud?

Ни один из них первым. Учитесь на одном обычном Linux-сервере, где ничто не спрятано за консолью. Облачные платформы переименовывают и оборачивают те же строительные блоки - машины, диски, сети, firewall, балансировщики - и их гораздо легче учить, когда уже знаешь, что это за блоки. Облако выбирайте позже, под ту работу, которую хотите получить.

Что важнее: Docker или Kubernetes?

Docker, с большим отрывом, и задолго до Kubernetes. Почти любой современный деплой где-то использует образы контейнеров, а без понимания образов, томов и сетей нельзя правильно пользоваться Kubernetes. Многие реальные системы спокойно работают на Docker Compose на одном сервере и никогда не требуют большего.

Можно ли практиковать DevOps без платного сервера?

Shell, Docker и скрипты можно изучать бесплатно в локальной виртуальной машине. Чего не потренировать локально - это публичный интернет: DNS, сертификаты, firewall под реальным трафиком и постоянный фон попыток входа. Небольшой платный сервер оправдан, когда вы доходите до этапа "от начала до конца".