Если вы хотите запускать серверы и выпускать софт, учитесь в таком порядке: Linux и shell, затем один небольшой сервер, который вы проводите от чистой машины до работающего приложения с мониторингом и бэкапами, затем systemd, Nginx, Docker и пайплайн деплоя - именно в этом порядке, и каждый шаг заменяет то, что вы уже делали руками. Kubernetes, service mesh и multi-cloud идут позже, если вообще понадобятся. Большинство тех, кто застревает в DevOps, застревает потому, что начали с верха этого списка, а не с низа.
Мы развиваем хостинг-платформу RE:NODE, на которой работает более 1 200 серверов для более чем 500 клиентов. Платформа показывает, какие навыки на самом деле держат парк серверов на ходу по ночам, а типичные способы учиться - какие из этих навыков люди пытаются пропустить. Этот текст - путь для любого, кто начинает с нуля, вместе с причинами, потому что именно причины позволяют самостоятельно оценить следующий инструмент.
Порядок и почему именно такой#
Принцип простой: никогда не автоматизируйте то, что не делали руками. Каждый инструмент DevOps - обёртка над ручной работой: запустить процесс, направить запрос, скопировать файлы на сервер, проверить, что что-то работает. Если сначала учить обёртку, можно идти по туториалу, но в первый же сбой под ней не окажется ничего, на что можно опереться.
| Этап | Что вы изучаете | Вы закончили, когда |
|---|---|---|
| 1. Linux и shell | Файлы, права, процессы, логи | Можете выяснить, почему умер процесс |
| 2. Один VPS | SSH, firewall, пользователи, обновления | Можете пересобрать его по заметкам |
| 3. systemd | Сервисы, перезапуски, journald | Приложение переживает перезагрузку |
| 4. Nginx | Reverse 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 строк, прежде чем гадать.
# 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 от начала до конца#
Самое полезное упражнение такое: арендуйте один небольшой сервер и доведите его от чистой установки до настоящего приложения, которое не стыдно показать людям. Не кластер, не три провайдера, одна машина. Один раз пройти весь путь - значит понять, как части соединяются, а этому не научит никакое изучение частей по отдельности.
Путь по порядку:
- Войдите по SSH, создайте обычного пользователя с
sudoи переключитесь на вход по ключу. Отключите вход по паролю и вход под root, когда ключ заработает, не раньше, иначе вы запрёте себя снаружи. - Включите firewall, который сначала разрешает SSH, а затем только нужные порты. В Ubuntu это
ufw allow OpenSSH, затемufw enable. - Включите автоматические обновления безопасности и научитесь перезагружать машину без страха.
- Установите runtime и запустите приложение вручную, на переднем плане, пока оно не заработает.
- Превратите его в сервис systemd.
- Поставьте перед ним Nginx с доменом и сертификатом.
- Добавьте бэкап, проверку доступности и алерт по диску.
- Запишите каждый шаг, затем уничтожьте сервер и пересоберите его по своим заметкам.
Восьмой шаг пропускают чаще всего, и он учит больше всего. Первая пересборка - момент, когда обнаруживается забытая изменённая настройка, пакет, установленный при отладке, файл в /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-файл короткий, и написать его вручную - значит понять, что такое "работать в продакшене": фиксированный пользователь, рабочий каталог, окружение, политика перезапуска и логи, которые уходят туда, где их можно прочитать.
[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, которые встретятся позже, станут очевидными.
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.
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 - разумное место для обучения, потому что бесплатного лимита для этого хватает с запасом, а синтаксис встречается повсюду.
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 под реальным трафиком и постоянный фон попыток входа. Небольшой платный сервер оправдан, когда вы доходите до этапа "от начала до конца".


