Первое осознание. Потом Продуктивность.

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

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

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

Когда качества недостаточно

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

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

Обновление от 22 сентября: Хадзиме Вукелич добавил комментарий к истории, указав, что я сделал так, будто чрезмерное индивидуальное выступление невозможно или нежелательно. Я все еще думаю, что это сложно в практике DevOps, но его вдумчивые рассуждения стоят сами по себе и побудили меня прочитать одну из его личных историй, озаглавленную Что такое высокодифференцированный разработчик. Я думаю, что это отличное дополнение к этой общей теме.

Вам нужны разработчики, которые работают на более высоком, но достижимом уровне (разработчик в 1,2 раза?), чтобы другие члены команды могли понимать и усваивать более продуктивные методы и модели поведения.

Урок 1 — Величие требует времени: в 27 раз больше.

Я имею в виду не «время», как «десятилетия опыта» — это тоже помогает, — а скорее «время» как фактическое время, необходимое для выполнения отличной работы.

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

Мой любимый метод оценки общей стоимости функции в производстве — создать рабочий прототип, а затем умножить время, затраченное на прототип, на 27. Это верно; если у меня уходит два дня на разработку прототипа, то может потребоваться почти три месяца (2x27=54 рабочих дня) совместных усилий всей команды, чтобы запустить его в производство.

Обновление от 9:22: пользователь Liquid Analytics сделал отличное замечание в разделе комментариев о том, что множитель 27x может стать препятствием для значимого прогресса. Я должен был упомянуть, что идея состоит в том, чтобы развернуть прототип с использованием современных подходов тестирования в производстве, таких как разработка на основе магистрали за темными запусками или флагами функций.

Почему 27x?

Фредерик Брукс-младший объяснил первый 9x в Мифическом человеко-месяце — своем знаменательном наборе эссе по разработке программного обеспечения в форме книги.

Первый трехкратный множитель — это стоимость перехода от работающего кода (в книге используется термин «программа», характерный для того времени) к надежному приложению (в книге используется термин «программный продукт»).

Второй 3-кратный множитель связан с дополнительным тестированием, необходимым для превращения этого надежного приложения в систему («системный продукт»).

Брукс рассказал об аспектах создания программного обеспечения для передачи клиентам для локального развертывания, что было характерно для бизнес-модели IBM того времени. Таким образом, он исключает затраты, связанные с операционными аспектами, где я добавляю последний 3-кратный коэффициент — на основе моего опыта в области проектирования операций, поэтому ваш множитель может варьироваться — чтобы превратить систему в работоспособную облачную службу.

Этот окончательный множитель включает в себя такие мероприятия по развитию, как:

  • Инструментарий системы для наблюдения
  • Документирование операционных процедур на основе конструкции системы
  • Разработка и поддержка конвейера непрерывного развертывания
  • Интеграционное тестирование с другими сервисами облачных провайдеров.

Объединение всех множителей (3x3x3) дает нам 27-кратную дополнительную стоимость запуска прототипа в производство.

Почему это важно. Хотя опытный разработчик не может недооценить размер новой функции на весь 27-кратный множитель, все, что выходит за пределы 2-кратного или 3-кратного коэффициента, гарантированно создаст непреодолимые сюрпризы для всей команды и, что еще более важно, лишить вас времени, необходимого для добавления и проверки всего, что вам нужно, чтобы не передать кошмар операционной группе.

Урок 2. Операционный инжиниринг превосходит искусство

Во что бы то ни стало, искусство имеет свое место, и некоторые уголки системы могут выглядеть умными или изысканными, но в конечном счете форма следует за функцией, и функция производственной системы состоит в том, чтобы запускать программное обеспечение, отвечающее требованиям и стоимостным показателям.

В этом разделе рассматриваются уроки, извлеченные в процессе эксплуатации, и то, как они должны повлиять на деятельность по проектированию и кодированию, учитывая часть этого 27-кратного множителя.

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

Больше компонентов. Больше затрат. Проверяйте бюджет каждого. Учет эксплуатационных расходов при проектировании и архитектуре — самый важный урок, который я когда-либо усвоил за время работы. Любой новый компонент в системе изменяет структуру затрат на эксплуатацию этой системы, поэтому вам нужно спросить себя, снижает ли этот компонент больше затрат, чем добавляет, и будьте готовы отказаться от добавления чего-то, что выглядит действительно весело входить в систему.

В конце концов, тот же самый мир, в котором финансовые директора (справедливо) говорят вам, что получение большего дохода важнее сокращения расходов, населен разработчиками, которые абстрагируют 50-миллисекундный SQL-запрос в серию вызовов RESTful с разбивкой на страницы, обернутые микросервисами (правдивая история).

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

Конечные точки состояния и работоспособности мирового класса. Никто не может позволить себе копаться в состоянии системы во время сбоя, особенно в микросервисных архитектурах с сотнями компонентов.

Производственной системе требуется общая точка работоспособности, объединяющая работоспособность различных зависимостей. Идея состоит в том, что оператор может быстро оценить (1) какие части системы не работают и (2) какие зависимости не работают — часть «почему» приходит позже.

Я перечислил свои предложения по проектированию конечных точек работоспособности в статье Готовность и жизнеспособность контейнеров Kubernetes — большинство рекомендаций в этой статье применимы и к системам, отличным от Kubernetes.

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

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

[ERROR|WARNING|INFO]: [Component X] attempted to [take action Y], which returned [response Z].

Поначалу этот формат может показаться очевидным — он выглядит как обычная конструкция субъект-глагол-объект, — но важнее всего терминология:

  • Существует ли компонент X в системной документации?
  • Доступно ли это действие Y для читателя?
  • Упоминается ли ответ Z где-нибудь в разделе по устранению неполадок?

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

В конечном счете, каждое сообщение в журнале должно вести к четкому шагу решения проблемы, который не требует обращения к автору сообщения или чтения исходного кода.

Написание системной документации: написание документации заставляет вас структурировать свое понимание системы в новом носителе. Эта деятельность приносит системе множество преимуществ, помимо обязательного информирования людей о том, как устанавливать, контролировать, защищать систему или устранять неполадки в ней.

Процесс написания требует от авторов обдумывания тех аспектов системы, которые может быть трудно объяснить.

Часто эта трудность может указывать на потенциальные недостатки конструкции, такие как попытки объяснить правильный порядок установки всех компонентов. В других случаях проблема может быть связана с «недоработанными» областями продукта, требующими для читателя длинных отрезков инструкций псевдокода («…затем щелкните здесь, введите это, подождите несколько секунд, затем появится панель вверх, найдите кнопку с именем…”)

Если все сделано правильно, документация также служит местом сбора для сотрудников, у которых может быть желание поделиться своими знаниями, но нет времени, чтобы понять, как это сделать. Эти виды вклада значительно повышают производительность всей экосистемы (разработчиков и пользователей) и, как правило, теряются в командных каналах и личных беседах.

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

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

Всегда ищите удаленные вызовы в коде и убедитесь, что вы знаете их ограничения и то, как ваш код будет обрабатывать эти ограничения:

  • Максимальное время ответа соединения
  • Максимальное время ответа на запрос
  • Максимальное количество попыток

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

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

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

Кроме того, убедитесь, что вы (и другие разработчики) имеете регулярный доступ к локальной настройке платформы телеметрии, используемой в операциях системы. Многие фреймворки поддерживают локальное выполнение на вашей рабочей станции или бесплатную пробную облачную учетную запись. Единая установка, обеспечивающая плавный переход от локальной к удаленной среде, требует разработки, проверки, документирования и обслуживания. Создание таких сред может быть очень увлекательным, но требует времени и денег.

Я не могу не подчеркнуть, что даже самые опытные и уверенные в себе разработчики всегда узнают что-то новое или неожиданное, просматривая телеметрию своего кода.

Подняв его на новый уровень, вместе с операционным отделом обеспечивайте договоренность об обмене данными с операционным отделом, уделяя особое внимание и усилия таким аспектам, как анонимизация данных и доступ к ним.

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

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

Однако, если вы не имеете дело с этими вариантами использования, вы можете серьезно пересмотреть включение асинхронной обработки сообщений в систему. Этот шаблон связи добавляет затраты, которые распространяются на всю длину бизнес-транзакции между производителем сообщения «А» и потребителем сообщения «Б». Вот лишь несколько примеров такой дополнительной сложности:

  • Операционные процедуры для системных администраторов при работе с размерами очередей, превышающими определенные пределы
  • Дополнительный дизайн и код для работы с сообщениями с истекающим сроком действия.
  • Операционные процедуры для обработки сообщений, отправленных в очереди недоставленных сообщений после истечения срока их действия.
  • Расширение системы для управления очередями недоставленных сообщений
  • Обработка распределенной трассировки для бизнес-транзакций, охватывающих доставку сообщения.

Урок 3 — Thread the Quad: код, сборка, поддержка, эксплуатация

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

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

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

Пример 1: Сборка

У нас была команда, которая в основном отвечала за развитие и поддержку системы сборки в предыдущем проекте. Сборка (компиляция и упаковка) всей кодовой базы на локальной рабочей станции заняла около двух минут. Напротив, та же операция в цикле сборки заняла, казалось бы, вечные пятнадцать минут.

Один из разработчиков, не входящих в команду сборки, провел полдня, добавляя различные записи журнала в сценарии сборки, чтобы изолировать проблему, сузив вероятную причину до шагов, на которых сборка записывала скомпилированные двоичные файлы на диск. Каким-то образом операции записи на диск в системе сборки, казалось, занимали на несколько порядков больше времени, чем на локальной рабочей станции (и да, на машине сборки было хранилище SDD :-)

Команда сборки проанализировала эти результаты и попробовала различные альтернативы (некоторые из тех, которые не относятся к набору навыков Unix от исходного разработчика), приземлившись на окончательное решение увеличения выделения памяти на виртуальных машинах и перемещения временных каталогов для каждой сборки в память. файловая система (tmpfs.)

Пример 2: Операции

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

Я всегда задавал несколько вопросов, прежде чем нажимать на кнопки, например:

  • «Когда будут развернуты компоненты, генерирующие эти новые оповещения?»
  • «Я не вижу в описании ссылки на playbook. Оперативная группа знает, где его искать?

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

Урок № 4 — Целенаправленное обучение: учитесь на каждой задаче

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

Это длинный список вещей; вы не хотите ждать десятилетия, чтобы приобрести эти навыки органически, несмотря на правило 10000 часов.

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

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

  1. Обзор. Если решение включает шаблонное решение для фреймворка, например определенный набор ресурсов для Terraform, вернитесь к просмотру полного определения этих ресурсов и, возможно, просмотрите смежные ресурсы от того же поставщика.
  2. Если решение включает в себя утилиту с определенными параметрами, вернитесь к руководству по утилите, чтобы изучить эти параметры, а также просмотреть другие параметры. Идея состоит не в том, чтобы запомнить их, а в том, чтобы проиндексировать их в уме, особенно в случае таких инструментов, как awk, где руководство может занимать целую книгу.
  3. Объясните, что вы узнали. Для исходного кода вытащите резиновую уточку и объясните исходный код неодушевленному предмету. Что касается понятий, вы можете даже не искать кого-то еще и использовать технику Фейнмана, делая вид, что представляете это понятие ребенку.
  4. Напишите на эту тему. Письмо — это более преднамеренная форма обучения, помогающая вам консолидировать и расширить свои знания о концепции (например, написание статьи), взаимосвязанных концепциях (с использованием чего-то вроде технической статьи) или всей области (например, о написании книги). Письмо выходит далеко за рамки обучения, поэтому оно может быть более полезным для организации смежных фрагментов знаний в вашей голове. Если вы все-таки решите заняться этим увлекательным занятием, обязательно прочитайте Письмо для инженеров Генриха Хартмана.

«Читали руководства по продукту? У кого есть на это время?»

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

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

«Если у вас нет времени читать, у вас нет времени (или инструментов) писать. Просто как тот."

Если вы не выделяете в расписании время для изучения технологии, используемой в ваших проектах, и расширения ее возможностей, вы ограничиваете себя обучением ровно столько, сколько нужно для выполнения ваших непосредственных задач. Эта динамика становится самоусиливающейся, когда окружающие считают, что вы способны только на те же самые задачи. И не нужно много времени, чтобы эти предположения оправдались.

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

Заключение

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

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

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

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

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

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