Свидетели DevOps: мифы и байки про девопсов и тех, кто их нанимает
Те, кто решил стать девопсом, видят в этой профессии заманчивые перспективы. Это новый уровень мышления, это творчество и возможность создавать, это безграничные просторы для самосовершенствования. Не секрет также, что девопсам хорошо платят. Вместе с тем, вокруг понятия DevOps сформировался некий культ, овеянный мифами и легендами.
Вот уже несколько лет я набираю на работу девопсов. Путеводная звезда приводила к нам в компанию разных соискателей, в том числе весьма курьезных: от программистов микроконтроллеров до арт-директора, который после 40 вдруг узрел новое призвание. Был даже студент-африканец, который едва говорил по-русски, но уже сделал головокружительную карьеру ростовой куклы, распугивающей пассажиров у выхода из метро. Но за анекдотическими ситуациями кроется главная проблема: по-настоящему квалифицированные люди — это крупицы и большая редкость
На эту тему было уже немало публикаций, но острота темы не отпускает. Под катом я поделюсь своими наблюдениями о том, какие типовые ошибки совершают и кандидаты, и практикующие девопсы, а также расскажу, что следует делать их по-разному везучим работодателям. Не обошлось и без злобных баек.
Трудности перевода
Справедливости ради оговорюсь, что DevOps — это не название профессии, а методология. Она описывает набор подходов и практик, которые помогают командной разработке. Но штампы преследуют нас повсюду. И вот уже не режет слух, когда уважаемый заказчик, представляя свою команду на установочном звонке, говорит: «А это Антон, наш девопс». Знакомьтесь, DevOps. Человек и пароход.
Помню, как в институтские годы мой школьный друг, поселившись в общаге, отгонял соседа по комнате от компа, кидаясь в него консервированной килькой и негромко приговаривая, что программистов нельзя подпускать к технике, так как они ее неизбежно ломают. В этой очаровательной бытовой зарисовке отражен давний конфликт, когда разработчик во всем винит окружение, а эксплуатация — кривой код.
Поэтому девопс в классической интерпретации — это либо программист, который стал админить, либо админ, который начал программировать. Это если уж совсем просто. Его задача — выступить связующим звеном между двумя лагерями, привнести в их работу синергию и тем самым сберечь запасы кильки и других ценных промысловых пород.
Однако, девопс девопсу рознь. И кажется, что девопс стал эдаким расхожим понятием, которое подменило нынче массу остальных профессий.
Байка про хромого девопса
Недавно нас позвали на помощь в один проект, где стояла, на первый взгляд, простая задача. Web-приложение работало через web-сокеты, но было развернуто внутри периметра, а на фронте стоял ISPManager, который в качестве reverse proxy использовал apache. Юный девопс, работавший в этом проекте, перепробовал все примеры конфига апача, которые нашел в Гугле, и вконец разочаровавшись в его поисковых способностях, перешел уже было к Яндексу, но тут менеджер проекта забил тревогу. На задачу к тому моменту было потрачено 72 часа. 72 часа, Карл! Кто вам сказал, что методология DevOps ускоряет разработку и сокращает time-to-market? ;)
К сожалению, я и мои коллеги все чаще замечаем, что новоиспеченные девопсы имеют довольно туманные представления об устройстве операционной системы, а навыки ее администрирования и траблшутинга оставляют желать лучшего. Не зная как следует матчасть, такой специалист, оказавшись в нештатной ситуации, быстро превращается в вареную морковку и разводит руками, пораженный чувством беспомощности. Клянет неизвестные баги, ссылается на мистику и чудовищное стечение обстоятельств.
Согласитесь, чтобы говорить на иностранном языке, недостаточно изучить только слова. В любом языке есть еще и правила — грамматические, лексические, стилистические. Более того, основу языка составляют уважаемые буквы. Практики DevOps — своего рода тоже язык, где работает та же логика. Недостаточно просто освоить модные инструменты. Без технической и концептуальной подготовки они рискуют просто оказаться микроскопом, которым колют орехи.
Но я не хочу возлагать всю вину только на ребят, так как у любой проблемы, как водится, причин много. Это и обилие технологий, и скорость, которая требуется в их освоении и применении, и тот самый кадровый дефицит. Многие осознают белые пятна в своих знаниях, но не находят времени и сил их целенаправленно закрывать. Для таких мы, кстати, запустили целый курс — будет полезно и тем, кто только грезит о новой профессии, и тем, кто уже попробовал свои силы, но чувствует, что нехватка основ мешает развиваться уверенно.
Про технологии
DevOps — это про культуру и философию совместной работы, но с этим понятием также сопряжен определенный технологический стек. Скорее всего я не ошибусь, если скажу, что какие-нибудь NetApp, Cisco, AIX или MS SQL воспринимаются как старый добрый олдскул (хотя это не совсем так, и классические вендоры делают гигантские шаги в новом направлении), а вот, скажем, Docker, Ansible, Jenkins и Prometheus в нашем сознании прочно ассоциируются с DevOps, SRE и новыми веяниями.
Но каким бы ни был стек, каждым инструментарием нужно владеть, разбираясь в его сути и основах. Делая настройку, нужно знать не только, что надо сделать, но и почему надо сделать так, и что будет, если сделать не так, а иначе.
Найти в гугле пример и скопипастить его к себе — еще один легкий путь отхватить проблем. Типичный пример — тюнинг и оптимизация сети и ядра через параметры sysctl. Конфиг, который удачно сработал для кого-то в интернете, не является волшебной пилюлей для любой другой системы. Как минимум, надо разобраться, что каждая директива значит. Может в вашей версии ядра она вообще deprecated.
И отдельная боль — это сеть. В сети надо разбираться, владеть инструментами диагностики. Сеть не зависит от платформы, она есть везде и напрямую (а порой больно) влияет на работоспособность и производительность всего остального. Когда человек, грезящий себя девопсом, наивно полагает, что надо установить свежую версию Kibana, потому что она умеет конвертировать адреса IPv6 в IPv4 — это звучит как анекдот. Но потом он, например, берет и орудует с сетью вот так:
или вот так:
Дальше хочу немного заострить внимание на двух технологиях, которые почти стали синонимами DevOps.
А давайте-ка все распилим на микросервисы, засунем в Docker и запустим в Kubernetes
Идея микросервисов прекрасна и выражается в том, чтобы программа перестала быть неповоротливым монстром, а превратилась в набор слабосвязанных компонентов, каждый из которых можно развивать отдельно. А вместе они взаимодействуют посредством унифицированных вызовов. Людей, изможденных поддержкой и обновлением монолита, микросервисная архитектура вдохновляет тревожной надеждой, что вот наконец-то судьба поспешила им на выручку.
Но не все следует доводить до маразма, даже если это увлекательно. Недавно моей команде на попечение был передан проект разработки мобильного приложения, в котором до нас один одаренный девопс настроил деплой бэкэнда на тестинг и продакшн, а затем от греха подальше уволился. Бэкэнд, по сути, представлял собой приложение на python, упакованное в один единственный контейнер. И этот одинокий контейнер исполнятся на одном физическом хосте. Мы читали путанный многоэтажный Dockerfile и искренне недоумевали, зачем все это надо было вообще совать в контейнер. Точнее, в контейнере ему и место, но не в этом.
Пока мы переваривали увиденное, в соседнем проекте разворачивалась новая драма. Этот же товарищ оставил после себя несколько обреченных проектов, но в этом размах был самым масштабным. Почерк автора угадывался повсюду среди двух десятков виртуалок: все в контейнерах, контейнеры случайным образом раскиданы по хостам, где-то живут в одиночку, но даже там, где они как-то совмещены, особой логики не просматривалось. Ребилд контейнера представляет собой варварскую бойню, когда затирается все, что установлено локально, а в конце с нуля воссоздается все окружение и празднично приезжает образ версии latest.
Вот, кстати, символичный фрагмент одного из скриптов по деплою:
Хорошо, что мы не дали запустить это в прод, так как не нашли в этой малопонятной архитектуре ни одного сервиса, который можно было бы безболезненно передернуть, не положив весь конечный функционал.
Хочу также на полях заметить, что микросервисная архитектура совсем не обязательно означает контейнеры. Просто контейнеры оказались удобной портативной упаковкой для этих модулей.
А про кубер вспоминается недавно гулявший ролик, где старый фильм озвучили новыми словами:
— А у вас есть kubernetes?
— Да, конечно, ну как у всех! Как полагается.
— А зачем?
— Ну как это зачем? Это же…
Дальше следует немая сцена, гримаса ужаса и спустя некоторое время человек, вероятно, идет топиться.
Я считаю себя евангелистом подхода Infrastructure as Code (IaC). Мне спокойно только тогда, когда продукт не просто освоен, а когда его развертывание и настройка автоматизированы. Специально не добавляю слово «документированы», потому что декларативный характер инструментов IaC — что приятно — во много порождает автодокументируемый код.
Кубер в этом смысле — апофеоз описательного подхода к управлению сервисами. Но надо понимать, что закатить свой приклад в кубер потребует немало усилий и времени, которые кратно превышают трудозатраты для развертывания в классическом окружении. И для кубера должны быть веские причины.
Для иллюстрации пример, который подвернулся на скорую руку — это варианты, как можно запустить телеграм-бот для Alertmanager (взято отсюда).
Просто через docker run:
docker rundocker run -d \
-e 'ALERTMANAGER_URL=http://alertmanager:9093' \
-e 'BOLT_PATH=/data/bot.db' \
-e 'STORE=bolt' \
-e 'TELEGRAM_ADMIN=1234567' \
-e 'TELEGRAM_TOKEN=XXX' \
-v '/srv/monitoring/alertmanager-bot:/data' \
--name alertmanager-bot \
metalmatze/alertmanager-bot:0.4.3
С помощью docker-compose
docker-composenetworks:
alertmanager-bot: {}
services:
alertmanager-bot:
command:
- --alertmanager.url=http://localhost:9093
- --log.level=info
- --store=bolt
- --bolt.path=/data/bot.db
environment:
TELEGRAM_ADMIN: "1234"
TELEGRAM_TOKEN: XXXXXXX
image: metalmatze/alertmanager-bot:0.4.3
networks:
- alertmanager-bot
ports:
- 8080:8080
restart: always
volumes:
- ./data:/data
version: "3"
А вот тот же сервис в Kubernetes
куберapiVersion: v1
items:
- apiVersion: v1
data:
admin: MTIzNA==
token: WFhYWFhYWA==
kind: Secret
metadata:
labels:
app.kubernetes.io/name: alertmanager-bot
name: alertmanager-bot
namespace: monitoring
type: Opaque
- apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/name: alertmanager-bot
name: alertmanager-bot
namespace: monitoring
spec:
ports:
- name: http
port: 8080
targetPort: 8080
selector:
app.kubernetes.io/name: alertmanager-bot
- apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app.kubernetes.io/name: alertmanager-bot
name: alertmanager-bot
namespace: monitoring
spec:
podManagementPolicy: OrderedReady
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: alertmanager-bot
serviceName: alertmanager-bot
template:
metadata:
labels:
app.kubernetes.io/name: alertmanager-bot
name: alertmanager-bot
namespace: monitoring
spec:
containers:
- args:
- --alertmanager.url=http://localhost:9093
- --log.level=info
- --store=bolt
- --bolt.path=/data/bot.db
env:
- name: TELEGRAM_ADMIN
valueFrom:
secretKeyRef:
key: admin
name: alertmanager-bot
- name: TELEGRAM_TOKEN
valueFrom:
secretKeyRef:
key: token
name: alertmanager-bot
image: metalmatze/alertmanager-bot:0.4.3
imagePullPolicy: IfNotPresent
name: alertmanager-bot
ports:
- containerPort: 8080
name: http
resources:
limits:
cpu: 100m
memory: 128Mi
requests:
cpu: 25m
memory: 64Mi
volumeMounts:
- mountPath: /data
name: data
restartPolicy: Always
volumes:
- name: data
persistentVolumeClaim:
claimName: data
volumeClaimTemplates:
- apiVersion: v1
kind: PersistentVolumeClaim
metadata:
labels:
app.kubernetes.io/name: alertmanager-bot
name: alertmanager-bot
namespace: monitoring
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: standard
kind: List
Если решение все же принято, вам предстоит перелопатить горы документации, написать тонны yaml-a, мучительно искать, где пропущен отступ, по 10 раз пересобирать контейнеры. И в этом момент вы еще и не знаете, что через пару недель пройдете новый круг ада, подстраивая ваш деплоймент под Pod Security Policy и разные энтерпрайзные фичи. Конечно, когда вы это дотащите до конца, вы получите красивый сервис, который легко скейлится, автоматически перезапускается при сбоях, который можно обновлять, используя, например, канареечные релизы или какой-нибудь blue-green deployment.
Но все же я хочу подчеркнуть — это нужно не везде и не всегда. Вместо того, чтобы слепо идти за зовом моды, нужно трезво оценивать баланс усилий и пользы. Девопсы, в том числе трушные, нередко имеют свойство увлекаться технологическом изяществом, благодаря чему постоянно создают на своем пути искусственные трудности, которые потом же мужественно преодолевают.
Автоматизация как истинный путь джедая
Наши бэкапшики помнят один случай, как сотрудник заказчика собирался в консоли что-то удалить — то ли ненужный симлинк, то ли копию конфига. А его то и дело дергали. По воле случая в один момент так сошлось, что товарищ успел набрать rm -rf /oradata, работая от рута, потом чихнул, что в свою очередь пробудило в его организме рута позывы на исход жидкости, а по дороге обратно он зацепился языками с товарищами. Когда он вернулся на рабочее месте, его экран спал. Не будучи в силах терпеть проделки этого вечно дремлющего устройства и дабы преподнести ему урок бодрости, товарищ решительно разбудил его точным ударом в Enter. В общем, когда все делаешь руками, нелепые вещи случаются сплошь и рядом.
Автоматизацию я считаю главной чертой современных подходов к управлению ИТ. Только автоматизация помогает действительно сократить время, которое обычно тратится на рутинные, повторяющиеся задачи, и только она может минимизировать влияние человеческого фактора.
Самое плохое в автоматизации — это время, которое надо на нее потратить. И самое хорошее в ней — тоже время, которое она впоследствие высвобождает. Например, пару лет назад нам потребовалось в нашем облаке IaaS развернуть инфраструктуру под нового e-commerce заказчика. Архитектура проекта: кластер БД, пул серверов приложений, распределенное хранилище, слой кэширования, сетевые балансировщики, WAF, ну и стандартная обвязка в виде телеметрии, СРК и сбора логов с визуализацией. Конечно, виртуальные машины мы давно создавали при помощи terraform, благо под наше облако можно использовать AWS-провайдер, так как мы по API совместимы. Программные компоненты и раньше ставили через ansible, и опыт настройки всего по отдельности, в общем, был. Но мы задались целью описать инфраструктуру проекта в виде единого пайплайна. На это ушло время, ну и до сих пор части этой автоматизации совершенствуются, так как еще много где были нами после переиспользованы.
Когда нам позже подвернулся аналогичный проект, различия описывались на уровне файла ответов. Мы развернули проект за 2 дня, причем большую часть времени занял перенос данных. В Gitlab CI запускался pipeline, который заполнял переменные для terraform, который затем запускался runner-ом. Тот создавал в облаке сети, диски и ВМ. ВМ запускались с cloud-init, который ставил внутрь puppet agent, который после старта связывался с foreman, забирал настройки для своей роли и деплоил все ПО. Через service discovery подключался мониторинг всех служб, везде встал и настроился filebeat, а бакап полился в S3. Voila! Все быстро и четко, без ошибок и ручных тестов на каждом шаге.
По нашим многолетним наблюдениям основные беды уже развернутых систем в основном сводятся к небольшому, довольно банальному списку причин. На борьбу с этими бедами расходуется много ресурсов, оттягивая их от куда более важных дел. Мы даже стали замечать, что крупный бизнес, пытаясь отгородить своих ценных гиков-девопсов от этого скучного труда, стал передавать такие задачи на аутсорс.
Вместе с тем, выполнение следующих правил способно практически нивелировать эффект самозагнивания (когда ломается само по себе с течением времени). Для этого нужно:
осмысленный сайзинг ресурсов;
отдельные точки монтирования (отдельный диск/раздел) под данные приложений и все, что может быстро пухнуть;
синхронизацию времени по ntp;
переход на использование ключей вместо паролей в ssh;
настроить ротацию всех логов;
иметь автоматический механизм обновления протухающих SSL-сертификатов
покрыть мониторингом все ключевые показатели жизнеспособности системы и не забыть про алерты;
если в системе есть данные, иметь автоматический бэкап по расписанию, и не хранить его рядом с данными.
Если система работает на физическом оборудования, сюда надо добавить дублирование дисков и агрегацию сетевых интерфейсов.
Эти простые меры — по принципу Парето — составляют не более 20% действий по первичной настройке, но дают 80% вклада в стабильную и автономную их работу в будущем.
Если у вас уже есть provision-система, то следом можно подключить инструмент IaC, и накатывать все эти настройки всегда по умолчанию, через какой-нибудь базовый профиль. Я в такой профиль еще включаю набор обязательных утилит, чтобы, к примеру, в экстренной ситуации не оказалось, что в системе нет lsof, tcpdump и т. п.
Время и внимание хорошего девопса такие проблемы не отнимают, потому что он их еще в самом начале решил.
Как не стать героем баек
В игре, которую мы ведем в жизни, многое зависит не только от того, что мы знаем и умеем, как и от того, насколько в себя верим. Между состояниями, когда ты еще просто админ, и когда ты уже причислен к сословию девопсов — граница весьма призрачная. И по упомянутым выше причинам люди стараются быстрее ее пересечь. Поучился по видосикам на ютубе — девопс. Запустил хром в докере у себя на компе — девопс. Засунул в гит всю свою папку с котиками — ну, тоже девопс.
Но на самом деле с изобретением DevOps наш мир радикально не поменялся. Он по-прежнему подчиняется законам физики, логики и здравого смысла. Просто невозможно стать качественным специалистом за несколько месяцев, пройдя курсы в онлайн-школе, обещающей сделать из вас гика. Настоящая квалификация куется годами, настоящий опыт мы получаем в основном на ошибках.
Нанимая ребят на позиции linux-инженеров/devops, мы в первую очередь смотрим на их способность мыслить, рассуждать, выстраивать цепочку связей. Немаловажен широкий технический кругозор и реальный практический опыт. И мы совершенно точно отдаем предпочтение тому кандидату, который лучше знает матчасть, так как больше уверены, что и с модными технологиями ему не составит труда разобраться.
И напоследок — завет работодателям
Порой из-за хайпа кажется, что эти космические люди, творящие чудеса в консоли, всемогущи –, но один девопс, даже самый талантливый, не может знать всего. ИТ давно уже превратилась в обширную отрасль, и в ней, как в медицине, два человека в белых халатах могут совсем друг друга не понимать. Когда стоматолог рассказывает проктологу про зубы, то вяло улыбается, потому что крыть нечем.
Если вам понадобился девопс, у вас вероятно уже есть разработка. Задачи, которые выполняет девопс — это та же разработка, только инфраструктуры и процессов, поэтому к ней в целом применимы те же правила. Над девопсом должен быть senior или тимлид, который через систему контроля версий делает code review, проверяет и одобряет PR/MR. И совершенно точно не стоит доверять архитектурные вопросы человеку без подтвержденного архитектурного опыта. Лучше поищите стороннюю экспертизу для подстраховки.
Мне также нравится концепция, когда отдельно от специалистов DevOps позиционируется еще одна команда — платформенных инженеров (Platform engineer). Она не работает непосредственно с девелоперами, но именно она снабжает девопса готовыми, отлаженными рычагами к этой платформе и уже настроенному инструментарию. Именно такой подход позволяет снизить планку требований к девопсу, позволяя ему спокойнее учиться и снижая риск его ошибок.
В этом месте ставлю не точку, а многоточие, так как тема неисчерпаемая и весьма холиварная. Комментарии, как говорится, покажут :)