По мере своего карьерного роста я все чаще и чаще испытываю чувство дежавю. Во время личной или деловой встречи моему собеседнику достаточно упомянуть какой-то малозначительный факт — и я сразу же вспоминаю о событии, которое произошло со мной несколько лет (или даже «работ») назад. Чаще всего это касается неверно принятых мною решений, последствия которых пришлось расхлебывать долгие месяцы. Такие флешбеки настолько сильны, что я едва сдерживаюсь, чтобы не закричать человеку в лицо: «Ни в коем случае не делай X!». Почему сдерживаюсь? Всё просто: моих коллег не было в том месте и в то время и они попросту не поймут, каких ужасов я натерпелся в подобной же ситуации. Именно поэтому я решил написать о худших ошибках, допущенных мною за годы работы. Возможно, эта статья сможет уберечь вас от неприятностей. Не переживайте: свои собственные ошибки вы всегда совершить успеете, на них я не покушаюсь. Но рассказ о моих заключениях наверняка пойдет вам на пользу. Ох уж эти облачные сервисы, в последние годы никуда от них не скроешься. Шучу, конечно. Я и сам большой поклонник облаков. Тем не менее, зачастую огульная миграция в облако приложений, написанных для физической инфраструктуры, оборачивается проблемами. Мне довелось поучаствовать в «переезде» трех крупномасштабных сервисов, изначально нацеленных на физические ресурсы. И каждый раз я сталкивался с подводными камнями, которые не покрывала ни одна официальная документация. По мере написания и тестирования приложений у разработчиков формируется представление о том, как оно будет вести себя в продуктивной среде. Сюда относится то, как работают серверы, какую производительность показывает приложение на конкретном «железе», насколько надежна сеть и как велики задержки. Всё это приводит к тому, что приложения, особенно старые, после переноса в новую инфраструктуру начинают вести себя очень странно. Всплывают новые, неожиданные ошибки, и вы буквально вынуждены на месте решать их самыми причудливыми путями. Вскоре оказывается, что ошибки и ограничения, с которыми вы столкнулись в новой среде, практически нивелируют ценность миграции. Что-то переносится с ошибками, что-то нельзя переносить вовсе — и вот вы уже оказались между Сциллой и Харибдой. С одной стороны — дата-центр, который приходится продолжать поддерживать. С другой — новая облачная среда. Не переносите просто так — портируйте приложение в облачную среду. Пусть разработчики получат доступ к новым ресурсам, как следует их изучат, внесут в приложение доработки и определят, насколько целесообразна миграция. Обязательно запланируйте даунтайм на 4-8 часов, в течение которых приложение будет простаивать. И не пытайтесь экономить на времени простоя. Делайте всё спокойно, уверенно и с расстановкой. Конечно же, самый лучший вариант — изначально разрабатывать приложение с прицелом на конечную среду. Но в ряде случаев это совершенно не применимый сценарий. Честно говоря, я не знаю, почему до сих пор я раз за разом сталкиваюсь с подобной ситуацией. Компаниям очень нравится делать собственные системы управления секретами. Я лично стал жертвой подобной идеи, подумав: «Хм, ну разве тут могут возникнуть сложности?». Я то ли встал не с той ноги, то ли сошел с ума — в тот злополучный день я решил, что управление секретами будет происходить через PostgrREST. Я написал утилиту, которая генерировала и отправляла приложениям JWT (JSON Web Token) на основе ряда критериев. Таким образом, думал я, приложения будут иметь доступ к своим секретам совершенно безопасным образом. В защиту PostgrREST я могу сказать, что он достойно справился со своей частью функциональности. Проблема в том, что управление секретами в реальности немного сложнее, чем кажется на первый взгляд. Взять хотя бы кеширование: как избежать обращения к службе по миллиону раз в час, при этом сохраняя концепцию «сервер —источник истины»? Мне удалось решить проблему через конфигурацию Nginx, но это заняло какое-то время. А потом мне в лоб прилетели смачные грабли ротации: обновить версию легко, но секреты, как правило, не передаются на клиентскую сторону. Поэтому во время ротации существуют сразу два верных секрета. Звучит вполне очевидно и ожидаемо, но во время разработки я не предусмотрел этот нюанс. Опять же, сделать быстрый фикс труда не составило, но со временем обнаруживались все новые и новые проблемы. Я понял, что совершил огромную ошибку, взвалив на себя самостоятельную разработку системы. Реальность такова, что управление секретами — это классический пример сервиса с высокими рисками и низкой отдачей. Задачи клиентов он не решает, руководителей не впечатляет, а для его разработки требуются уйма времени и набор специфических знаний. Мне пришлось переделать заново едва ли не все аспекты своей изначальной программы. Просто используйте AWS Secrets Manager или Vault. Я лично предпочитаю Secrets Manager, но тут выбор за вами. Только, заклинаю, не пишите свои собственные системы. В их разработке слишком много нюансов и сложностей, а на выходе вы получите крайне сомнительные преимущества. Экономия средств минимальна, но именно из-за вашего излишнего усердия все приложения в один прекрасный день перестанут работать. Да-да, у вас достаточно технических знаний и навыков. Может быть, вы вообще фанат etcd и настройки множества сертификатов. Но вот вам коротенькое дерево решений на случай, если вы решите запустить собственный кластер k8s: 1. Моя компания находится в списке Fortune 100? Да: запускайте кракена кластер смело! Нет: не стоит этого делать. Лучше пусть кто-нибудь другой запустит этот кластер, а вы будете пользоваться его преимуществами. Например, у AWS EKS есть масса потрясающих функций, от AWS SSO в вашем kubeconfig-файле до возможности использовать роли IAM внутри ServiceAccounts для доступа модулей к ресурсам AWS. Вдобавок ко всему, меньше чем за 1000 долларов в год AWS возьмет на себя административные функции. Я до сих пор не понимаю, почему эта проблема не на слуху. Да, вы можете самостоятельно и притом успешно запустить собственный кластер k8s, но — зачем? В случае с AWS буквально десятки тысяч бета-тестеров вперед меня убеждаются, что обновления EKS работают. Куча инженеров заняты поддержкой продукта. Если я и так размещаю в AWS свою инфраструктуру, с какой стати разворачивать собственный кластер? Разве что для поддержания иллюзии того, что в будущем я не буду привязан к одному провайдеру. Но об этом мы поговорим чуть ниже. Пусть провайдер облачных услуг занимается ваши кластером. А вы сосредоточьтесь на том, чтобы ваши собственные разработчики не испытывали сложностей или неудобств. Эта тема волнует меня на самом личном уровне. Один крайне способный менеджер убедил меня в том, что наша компания должна иметь возможность в любое время сменить облачного провайдера. Я попался на эту удочку и оказался в так называемой «команде преждевременных оптимизаторов». Через некоторое время я решил провести аудит новых сервисов на предмет совместимости с несколькими облачными платформами. Вместо SDK от AWS мы использовали свои собственные, чтобы без проблем переключиться, если придется выбрать нового провайдера. С учетом того, что текущее облако нас устраивало, переехать или расшириться мы могли только в случае экспансивного роста бизнеса — чего в ближайшие годы явно не предвиделось. Следующий пассаж я хотел бы адресовать в первую очередь провайдерам облачных услуг: не делайте вид, что клиенту на самом деле может потребоваться развернуть свои приложения в нескольких разных облаках. Экстренная надобность в этом может возникнуть только в том случае, если вы, провайдер, закроетесь одним днем. Все остальные сценарии миграции подразумевают, что у клиента найдется время на полноценную подготовку и переезд. На деле вероятность того, что облачный провайдер проживет дольше, чем ваша компания, крайне высока. И в подавляющем большинстве случаев не стоит задумываться о переезде с первого дня в новом облаке. Возвращаясь к моей истории — мы обросли кучей устаревших библиотек, поэтому наши разработчики лишь читали о замечательных новых функциях AWS, однако использовать их не могли. Ни один туториал с нашей прекрасной переносимой библиотекой не работал, разработчики злились, а до реальной миграции дело так и не дошло. Если кто-то говорит, что вы не должны быть привязаны к единственному поставщику облачных услуг, ответьте прямо: этот поезд ушел в момент регистрации, я остаюсь тут. Как и в случае миграции из ЦОДа в облако, приложение, разработанное и протестированное на совместимость с конкретной инфраструктурой, может начать чудить в новом облаке. С другой стороны, «максимальная мобильность» может выйти вам боком и ограничить возможности. Если вы оказались в ситуации, когда переход к новому провайдеру имеет финансовую подоплеку, выделите как минимум 3 месяца на тестирование и портирование каждого приложения. Получившийся ворох задач может запросто уничтожить все выгоды от миграции. Облачные провайдеры — это как язык программирования. Нельзя просто так взять и переключиться с одного на другой. Поэтому всегда оценивайте риски и преимущества — и, самое главное, не мешайте клиентам пользоваться вашими сервисами, если всё и так корректно работает. Я уверен, что вы лично не раз сталкивались с подобной ситуацией: где-то в офисе установлен экран, подключенный к системе мониторинга. Периодически на нем загорается какое-то предупреждение, но никто не торопится с ним разбираться. Мол, «это мелочь, мы просто следим, чтобы такая ерунда не происходила слишком уж часто». В конечном итоге, прямо как в сказке про мальчика, который слишком часто кричал «Волк!», произойдет действительно серьезный сбой — все из-за того, что дежурный инженер машинально проигнорирует важное оповещение из-за большого потока «мусорных». Именно в такой ситуации я и оказался. Мне пришлось поддерживать систему, построенную моим предшественником, и я не дал себе труда переписать непонятные модули или разобраться, откуда приходят лишние оповещения. Реальный сбой, который мы не заметили, не заставил себя долго ждать. Не допускайте «замусоривания» системы предупреждениями о всякой ерунде и не стесняйтесь избавляться от чужих «хвостов» и ошибок. Если система присылает вам alert-email 600 раз на дню, она бесполезна. Коротенький и простой совет. Никто не знает, как правильно устанавливать и упаковывать Python-приложения. Если вы пишете внутренний инструмент, он должен быть либо полностью переносимым, либо написанным на Go или Rust. Избавьте себя и пользователя от страданий с приложениями, которые не хотят корректно устанавливаться.