Русский
Русский
English
Статистика
Реклама

Gcp

Парадокс доверия облачным решениям три сценария, в которых ключи шифрования хранятся не в облаке

16.03.2021 18:09:12 | Автор: admin

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

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

Сценарий 1. Данные, которые лучше не хранить в облаке

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

В каждой сфере и в каждой компании есть данные, которые попадают в эту категорию. Например, в одной международной организации действуют очень строгие правила в отношении хранения ключей. Чтобы использовать для этого облачные платформы, ей необходимо получать специальное разрешение. Другая организация руководствуется собственным вариантом стандарта PCI DSS. Кроме того, у нее есть внутренние требования по управлению главными ключами с помощью аппаратного модуля безопасности в соответствии со стандартом FIPS 140-2 (уровень 3).

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

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

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

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

С развитием облачных технологий порядок их использования во многом зависит от требований законодательства в тех или иных странах. В этом сценарии организация хочет использовать облачную платформу из другой страны, но ее не устраивает, что у поставщика услуг будут ключи шифрования для всех данных. Если в том же облаке будут обрабатываться незашифрованные данные, поставщик услуг получит доступ и к ним. Некоторые организации также не хотят хранить ключи на криптографических устройствах (например, аппаратных модулях безопасности), управляемых поставщиком услуг (физически или с помощью ПО). Они справедливо полагают, что такой подход не соответствует принципу Hold Your Own Key (HYOK).

Проблемы могут быть связаны как с требованиями законодательства, так и с описанными выше причинами. Кроме того, регулирующие органы ЕС, России, Японии, Индии, Бразилии и других стран постоянно принимают новые акты, запрещающие хранить незашифрованные данные и/или ключи шифрования за рубежом. В качестве примеров можно привести отраслевые стандарты (например, TISAX в Европе), которые указывают или подразумевают, что у поставщика облачных услуг ни при каких обстоятельствах не может быть доступа к данным, а во многих случаях и к ключам шифрования. Однакопредварительные результаты опросауказывают на то, что возможны варианты, когда ключи шифрования находятся только у клиента (в то время как зашифрованные данные могут храниться за рубежом).

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

По мнениюТомаса Куриана, "суверенитет данных позволяет клиентам запрещать доступ к своей информации поставщикам услуг, кроме тех случаев, которые сами клиенты сочтут необходимыми. Например, платформа Google Cloud разрешает клиентамхранить и использовать ключи шифрования вне облака.Они могутпредоставлять доступ к ключам только в случае крайней необходимости, будучи уверенными, чтоиспользуемые данные защищены. В результате клиент может самостоятельно распоряжаться доступом к своим данным".

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

Сценарий 3. Централизованное управление ключами шифрования

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

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

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

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

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

Дальнейшие действия

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

  • Прочитайтеэту статьюоб управлении ключами шифрования в облаке.

  • Оцените риски для данных с учетом уязвимостей, нормативных требований, отношений между странами ит.д.

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

Ознакомьтесь ссервисамиотGoogle Cloud EKM (External Key Manager) и партнеров (Ionic, Fortanix, Thales ит.д.), которые позволяют перенести управление ключами из облака в локальную среду.


Напоминаем что при первой регистрации в Google Cloud: вам доступны бонусы на сумму 300 долларов США, а более 20 бесплатных продуктов доступны всегда. Подробнее поспециальной ссылке.

А так же выражаем благодарность за помощь в подготовке материала коллегам: Антон Чувакин, Иль Сон Ли,Звиад Кардава

Подробнее..

Что такое Immutable Infrastructure

02.09.2020 12:08:46 | Автор: admin

Меня зовут Никита, я системный инженер в компании SEMrush. И в этой статье я расскажу вам, что такое Immutable Infrastructure, какие у этого подхода есть преимущества и недостатки и как мы его используем в компании.



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


Что это такое


Immutable Infrastructure подход к созданию неизменяемой инфраструктуры. Идея его не нова в мире, хоть и не слишком распространена. Мы начали его использовать, когда поняли, что не все можно запустить в Kubernetes, и нам нужны виртуальные машины.


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


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


Мы в компании активно используем облако GCP, поэтому не админим железо, на котором запускаются виртуалки. У GCP есть мощный API и множество SaaS продуктов, использование которых делает возможным применение Immutable подхода. Если у вас KVM-хосты, и вы выкатываете виртуалки скриптиком, то вряд ли вам подойдет такое решение. Но при использовании любого облака (Openstack, AWS, Azure и т.д.), можно имплементировать данный подход. Я опишу его применение совместно со всей мощью облака, где, например, создание виртуалки происходит POST-запросом, а увеличение диска производится на лету.


Преимущества Immutable


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


  1. Повторяемое окружение
    Обычно на сервер устанавливается операционная система определенной версии, настраивается окружение для приложения и происходит деплой самого приложения. Но если вы захотите через какое-то время развернуть точно такой же сервер с вашим приложением, то точно такой же у вас никак не получится: какие-то пакеты устарели, на другие пакеты выпущены security патчи, ядро уже тоже обновилось. В итоге вы получаете два похожих сервера. И вот эта разница часто является ключевой и может привести к багам и ошибкам. С Immutable Infrastructure у вас всегда есть образ виртуальной машины, который точно запустится и будет повторять реальное окружение точь-в-точь. В нем уже все предустановлено: все системные пакеты и библиотеки одной версии, а окружение приложения не изменится со временем. Вы можете повторно развернуть или масштабировать сервис спустя годы, лишь бы у вас был образ.
  2. Инфраструктура как код
    Immutable infrastructure всегда описана как код, потому что на каждый коммит (релиз) нам нужно создавать новый образ виртуальной машины, а также проводить его через пайплайны CI/CD. Это не получится делать руками.
  3. Неизменяемое окружение
    Как и в случае с Docker контейнером, виртуальная машина не может быть изменена. Не придет какой-нибудь configuration management инструмент или unattended upgrades, которые установят новые версии пакетов и все сломают. Там просто нет этих механизмов. Они не нужны и даже специально отключаются, потому что все, что нужно для функционирования приложения, уже установлено в системе. Окружение неизменяемо во времени и всегда одно и то же, пока не произошел релиз новой версии приложения.
  4. Отсутствие configuration drift
    Может быть такое, что у вас есть 100 серверов, на которые нужно вылить новый апдейт, и на несколько из них выкладка зафейлилась по какой-то причине. Тогда ваша конфигурация разъезжается, и вы не имеете одинакового окружения на всех машинах в вашей системе. Или у вас работает unattended upgrade, который периодически ставит обновления безопасности, и где-то ему удалось поставить пакет, а где-то нет. Immutable же гарантирует неизменяемость виртуалок во времени, а также то, что на них одна одинаковая версия всех приложений, зависимостей и операционной системы.
  5. Независимость от внешних источников
    В ходе настройки окружения приложению необходимы различные зависимости, которые тянутся из внешних источников. Если внешний источник недоступен, то создание новых инстансов может быть зафейлено. С Immutable такого не произойдет. Все зависимости уже установлены в образе, что гарантирует работоспособность приложения после старта. С таким подходом мы выносим failure point на этап билда образа, а не на этап деплоя, когда что-то пошло не так при обновлении на production VM. После того, как образ собран, мы точно знаем, что виртуалка рабочая, и осталось задеплоить ее как обычно.
  6. Отсутствие устаревших систем
    С Immutable нет проблемы "старых" серверов с высоким аптаймом, которые страшно не только обновить, но и даже перезагрузить. Любое изменение это новый билд образа и новая виртуалка.
  7. Простое масштабирование
    Всегда есть некий срез во времени вашего приложения, поднять новый инстанс которого можно по щелчку пальцев.
  8. Все плюсы облака
    В облаке дешево и легко создавать новые ресурсы, запрашивать столько CPU и RAM, сколько необходимо. Кроме того, можно интегрировать виртуалки с другими сервисами GCP: Load balancers, GCS для бэкапов, Autoscaler, Cloud SQL и т.д.
  9. Трансформация разработки
    Такой подход к инфраструктуре и осознание того, что инфраструктурная часть неотделима от самого кода и приложения, что минимальная единица это виртуальная машина, заставляет изменить и подход к разработке приложения. Нужно проектировать свое приложение исходя из того, что оно будет immutable. Приложение должно "осознавать" свою эфемерность и быть готовым быть замененным новой версией самого себя. Деплой таких приложений тоже отличается, поэтому нужно предусмотреть нюансы на этапе проектирования.
  10. Базовые образы
    Можно создать образы виртуальных машин различных ОС с предустановленным ПО, которые будут являться базовыми. Далее их можно расширять, устанавливая туда конкретные приложения и окружения для них. Все по аналогии с Docker образами.
  11. Простые откаты
    Чтобы откатиться на предыдущую версию, достаточно просто поднять виртуалку с предыдущим образом. Как будто бы запускаешь контейнер.
  12. Идентичные окружения
    Вы собираете новый образ виртуальной машины и запускаете его в Dev окружении на тестирование. Если тестирование прошло успешно, вы запускаете ТОТ ЖЕ САМЙ ОБРАЗ (только с другим конфигом для provisioner) в Prod окружении.

Но есть нюансы


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


  1. Более сложный деплой
    Immutable подразумевает, что каждый раз при любом изменении вы создаете новый образ, на основе которого запускаете виртуалку. После этого вам может понадобится сконфигурировать приложение (чтобы оно получило свои переменные, конфиги, вступило в кластер и т.д.). Это все необходимо автоматизировать и это может быть достаточно сложно. Пайплайн обновления и его логика могут получаться развесистыми.
  2. Даунтайм при обновлениях
    Если есть приложение, которое крутится на виртуалке и использует какие-то данные, хранящиеся локально, то выкладка новой версии приложения подразумевает ряд процессов: выключение текущей виртуалки, отсоединение от нее диска, поднятие нового инстанса, подключение диска к нему. Понятно, что это ведет к даунтайму (по правде сказать, в таком случае перерыв в работе сервиса, но просто более короткий, был бы даже если бы и не использовался Immutable подход). Узкие места: единственный инстанс и локальный storage. Решить это можно через системы динамической конфигурации, несколько инстансов (горячий, холодный резерв или одновременная работа), удаленный storage (но тут уже будет возможный downgrade производительности дисковой подсистемы). Все это зависит от конкретного кейса и архитектуры приложения. Если это Stateless воркеры, то для них данная концепция подходит как никакая другая. А у нас, например, на инфраструктурных сервисах есть SLA, в рамках которого мы иногда можем сделать даунтайм для обновления.
  3. Отсутствие постоянных апдейтов
    Как это ни странно, но у Immutable есть обратная сторона своего же преимущества это отсутствие постоянных апдейтов, security патчей и т.д., которые в обычной системе могут быть настроены на автоматическую установку. В образе не обновится ничего, пока вы не соберете и не задеплоите обновленный вами образ.

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


Push и Pull модели


При проектировании нужно учитывать, какой модели будет соответствовать ваше приложение. Существует два основных пути:


Push


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


Pull


При таком подходе может работать автоскейлинг, а виртуалки будут в инстанс группе (ну или использовать схожий механизм). Это значит, что создание новой виртуалки будет происходить автоматически, а не по воли оператора или процесса CI. Новосозданная машина должна иметь в себе все необходимое для само конфигурации. То есть конфигурация происходит изнутри пуллится самой виртуалкой (в себя).


В зависимости от модели нужно по-разному подходить к проектированию CI/CD пайплайна и процесса деплоя.


В главных ролях


При работе с неизменяемой инфраструктурой нам помогают эти инструменты:


  1. Packer программа от Hashicorp, которая позволяет создавать образы виртуальных машин, на базе разных облачных провайдеров. Packer берет указанный базовый образ, создает из него виртуалку в нужном облачном провайдере, накатывает в нее конфигурацию с помощью любого из множества провижинеров, а в конце создает из ее диска установочный образ, который можно использовать в выбранном облаке.
  2. Terraform еще одна утилита от Hashicorp, которая, наверное, уже не нуждается в представлении. Позволяет описать необходимые инфраструктурные ресурсы нужного облачного провайдера и, используя этот манифест, приводит конфигурацию облака к описанному в конфиге.
  3. Ansible инструмент, с которым также знакомы почти все. Он нам нужен для того, чтобы делать provision образа и создаваемой виртуалки настраивать окружение.
  4. Gitlab CI мы используем Gitlab, поэтому и всю автоматизацию пишем на нем.
  5. GCP собственно, облако, которое делает запуск виртуалки легким и простым, а также позволяет создавать множество других ресурсов.

Immutable Images


Образ VM является основным артефактом деплоя. У нас есть собственные базовые образы, которые собираются на основе образов Google, специально заточенных под работу в их облаке, образы приложений с каким-то предустановленным, но не сконфигуренным ПО (nginx, mysql, mongodb и т.д.), и продуктовые образы. Последние содержат в себе все необходимое для работы конкретного продукта или его компонента (это может быть образ с настроенной БД, вэб-сервером, бэкэндом). Как можно понять, каждый образ в иерархии базируется на каком-то родителе и расширяет его. Для конфигурации образов (подготовки окружения) мы используем Ansible отличный инструмент, позволяющий доставлять one-shot конфигурацию.


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


Image Family


У образа в GCP есть имя, метки, статус, а также принадлежность к какой-то Image Family.


Image Family удобный механизм, объединяющий все версии одного образа под одной "семьей". Это упрощает использование базовых образов если вам не нужно точно знать, какую вы используете версию образа, его название, которое включает дату и т.д., вы просто указываете image family, на базе которого вы хотите собраться, и все. Это аналог тега latest в докере.


Однако, если при сборке образа использование Image Family вполне оправдано, то при деплое вам обязательно нужно использовать Image Name и указывать конкретный образ, который вы хотите задеплоить (только что собранный). Как и latest в докере, использование family может привести к дрифту версий или неожиданным изменениям на проде.


Кратко принцип работы с Image Family выглядит так:
У вас есть image-v1 это самая последняя версия образа вашего приложения. my-image-family указывает на данный образ


gcloud compute images create image-v1 \    --source-disk disk-1 \    --source-disk-zone us-central1-f \    --family my-image-familygcloud compute images describe-from-family my-image-familyfamily: my-image-familyid: '50116072863057736'kind: compute#imagename: image-v1

Вы создаете новый образ image-v2, и теперь my-image-family указывает на него.


gcloud compute images create image-v2 \    --source-disk disk-2 \    --source-disk-zone us-central1-f \    --family my-image-familygcloud compute images describe-from-family my-image-familyfamily: my-image-familyid: '50116072863057756'kind: compute#imagename: image-v2

По какой-то причине нужно откатиться на предыдущую версию, и теперь my-image-family снова указывает на image-v1:


gcloud compute images deprecate image-v2 \    --state DEPRECATED \    --replacement image-v1gcloud compute images describe-from-family my-image-familyfamily: my-image-familyid: '50116072863057736'kind: compute#imagename: image-v1

Обновление и ротация базовых образов


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


У образов виртуальных машин в GCP есть текущее состояние:
READY образ готов к использованию
DEPRECATED образ признан deprecated. Такие образы не отображаются в веб-консоли по-умолчанию, но доступны для gcloud и terraform. В случае их использования выдается предупреждение.
OBSOLETE образ в этом статусе уже недоступен для использования.
DELETED образ помечен удаленным, но еще существует физически.
REALLY_DELETED такого статуса в реальности нет, но спустя некоторое время, как образ был помечен DELETED, он будет удален по-настоящему.


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



Для базовых образов мы делаем автообновление. Раз в сутки производится автоматическая проверка наличия обновления пакетов, входящих в состав образа. Если обновления найдены, производится сборка новой версии образа и указатель image-family сдвигается на нее. После этого происходит ротация всех образов, относящихся к данной image-family.


Для автоматизации жизненного цикла мы написали скрипт image-rotator, который в ближайшее время мы выложим в публичный доступ (в статью будет добавлена ссылка). Его принцип работы следующий:


  1. Скрипту передаются нужные переменные, главной из которых является --image-family. Так он понимает, с чем ему нужно работать
  2. Скрипт находит все образы, принадлежащие данной Image Family, и дальше работает со всеми этими образами КРОМЕ последнего актуального образа, на который указывает Image Family в данный момент
  3. Далее среди этих образов он делает следующее:
    • Все READY образы делает DEPRECATED и проставляет им дату, когда они должны стать OBSOLETE
    • Все DEPRECATED образы, у которых дата obsolete меньше текущей даты, переводит в состояние OBSOLETE и выставляет дату, когда образ должен стать DELETED
    • Все OBSOLETE образы обрабатывает по аналогии с DEPRECATED
    • То же самое с DELETED. Если у DELETED образа подошла дата удаления, то скрипт удаляет образ навсегда

Схема пайплайна


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


На рисунке ниже, схематично, представлен данный процесс.


Мы подразумеваем, что сначала деплоим приложение в Dev-среду из Master-ветки (название ветки здесь не принципиально), где оно тестируется. После чего, деплоим тот же самый образ на Prod-окружение из другой ветки stable, посредством синхронизации двух веток через Merge Request.


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


  • Интеграция с Hashicorp Vault для получения секретов
  • Использование снапшотов дисков с данными Prod-инстанса для создания Dev окружения
  • Использование последнего бэкапа CloudSQL (примечание: база данных как сервис от Google (MySQL, PostgreSQL)) Prod-инстанса для создания базы данных в Dev-окружении
  • Удаление Dev-окружения в конце тестирования (это же облако, нам не хочется тратить лишние деньги)

Дальше Terraform создает виртуалку с приложением в Dev-окружении, создает диск со свежими данными из образа, сделанного в п.1. Так мы получаем свежие независимые данные, на которых протестируем новую виртуалку. Бонусом случайно проверяем бэкапы Prodа :)


Заключение


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


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


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

Подробнее..

DevOps-практики Кто? Где? Сколько?

12.03.2021 10:04:49 | Автор: admin

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

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

Итак, какие задачи решает DevOps-инженер?

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

  • Обеспечение полного жизненного цикла продукта;

  • Подготовка различных окружений (разработка тестирование production) и обеспечение поставок продукта на эти окружения;

  • Обеспечение автоматического прохождения продукта через различные стадии непрерывной интеграции (CI) и непрерывной доставки (CD);

  • Виртуализация и управление инфраструктурой, мониторинг.

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

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

  • CI/СD и интеграцию (Jenkins, TeamCity, GitLab, Bamboo);

  • Автоматизацию (Terraform, Puppit, Ansible);

  • Облачные платформы (AWS, Google Cloud Platform, Microsoft Azure, Huawei Cloud, Яндекс Облако, Mail.ru Cloud Solutions);

  • Мониторинг (Prometheus, Grafana, Zabbix, Nagios);

  • Системы логирования, трассировки (ELK Stack, Graylog, Gafana, Jaeger);

  • Контейнеризация и орекстрация (Docker, Kubernetes, Nomad).

Карьерная карта

В DevOps приходят из разных профессий. Основные доноры - это System administrator, Automation engineer, QA automation, Build Engineer/ Release Engineer, Developer. Представители этих специальностей уже обладают рядом навыков, которые необходимо развить и расширить.

Андрей Синицын, Head of IT Optimisation Departmen в ECommPay, рассказывает: Я занимаюсь компьютерами с середины 90-х я из того времени, когда эта профессия выбирала тебя. Передо мной никогда не стояло вопроса, чем заниматься по жизни. Сначала я работал программистом, потом понял, что мне интереснее эксплуатация, и ушел в DevOps. Живой продакшн это всегда интересно. И, на мой взгляд, интереснее, чем написание программы: ты видишь, как код эволюционирует, как он работает, как он выполняет (или, как это часто бывает, не выполняет) ту задачу, для решения которой был написан.

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

Сертификаты AWS, GCP, Azure, Kubernetes (CKA, CKAD) могут рассказать работодателю о том, что соискатель имеет навык работы с конкретными платформами, но, как правило, DevOps-инженером становятся только на практике.

Составляя идеальное DevOps-резюме, важно отразить в нём навыки, которыми вы владеете, задачи в рамках уже реализованных проектов, их особенности, зону ответственности; используемый стек технологий и, конечно, не забыть о soft-skills. Андрей Синицин подчёркивает, что для DevOps очень важны хорошие коммуникативные навыки, знание английского, обучаемость и out-of-box thinking стандартный набор для любой специализации в IT. Еще я бы добавил, что большое преимущество в DevOps дает понимание бизнеса (или стремление к этому). Эксплуатация никогда не зарабатывает деньги напрямую, и осознавать business value того, что ты делаешь, очень важно.

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

Кстати, нам вы также можете прислать резюме по этой ссылке.

Перспективы сегодня и завтра

DevOps-инженеры действительно зарабатывают больше всех в отрасли. В США, Канаде, UK заработная плата колеблется между 90 и 122 тысячами долларов в год. Что касается России, то в Москве работодатели готовы предложить такому специалисту в среднем 260 тыс. рублей в месяц (верхняя планка доходит до 350 тыс. ), в Санкт-Петербурге средняя зарплата составляет 200 тыс. рублей.

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

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

Что касается возможностей карьерного роста, то для DevOps-инженера открыт путь к следующим позициям: Devops Team Lead, DevRel (Developer relations), Delivery Manager, Devops architect, Head of Engineering.

DevOps 2021: основные тренды

Анализируя 2020 год, можно заметить, что в центре внимания стала, прежде всего, безопасность. В том числе, безопасность IT-продуктов, поэтому одним из самых заметных трендов является DevSecOps и в целом SDLC (Security development lifecycle). DevSecOps подразумевает встраивание процесса безопасной разработки в процесс DevOps, интеграцию парадигм безопасности в каждый из этапов разработки.

Внедрение таких подходов, как DevSecOps, невозможно без следующего тренда автоматизации, одного из основных китов DevOps-практики. Скрипты, автоматизация, внедрение подхода IaC (инфраструктура как код) все это обеспечивает гибкость, скорость процессов разработки и поставки продукта.

Стоит также выделить глобальный тренд, который существует уже несколько лет это переход в cloud-native-среду и разработка приложений с учетом особенностей облачных платформ, считает Элиса Данильсон, консультант направления IT&Telecoms в Санкт-Петербурге.

Подробнее..

Серия вебинаров по серверной разработке на Kotlin

07.12.2020 14:17:59 | Автор: admin
Все больше инженеров выбирают Kotlin для разработки серверных приложений. Полная совместимость с Java, корутины и высокая безопасность делают Kotlin отличным инструментом для подобных задач.

Мы организуем серию вебинаров (на английском языке), где расскажем о разработке бэкенда на Kotlin в сочетании с технологиями Apache Kafka, Spring Boot и Google Cloud Platform. Вебинары подойдут для Kotlin- и Java-разработчиков любого уровня подготовленности, в том числе для разработчиков мобильных приложений без опыта серверной разработки.

Kotlin и Apache Kafka, 10 декабря 2020, 19:30 20:30 МСК
Kotlin и Google Cloud Platform, 17 декабря 2020, 19:30 20:30 МСК
Kotlin и Spring Boot, 14 января 2021, 19:30 20:30 МСК

Подробнее о каждом из вебинаров читайте ниже.


Kotlin и Apache Kafka


image

Зарегистрироваться

O чем этот вебинар?


Виктор и Антон покажут, как использовать Apache Kafka в сочетании с Kotlin для управления потоками данных. Презентация также даст обзор внутренней архитектуры Apache Kafka.

Спикеры:
  • Антон Архипов, Developer Advocate в команде Kotlin, JetBrains
  • Виктор Гамов, Developer Advocate, Confluent

Когда состоится вебинар?


10 декабря 2020
19:30 20:30 МСК
Подробная информация

Kotlin и Google Cloud Platform


image

Зарегистрироваться

О чем этот вебинар?


На вебинаре мы расскажем, как применить Kotlin в проекте с кодовой базой на Java, поговорим о таких возможностях Kotlin, как корутины, и продемонстрируем процесс развертывания приложения на Google Cloud.

Спикер: Джеймс Уорд, Developer Advocate, Google Cloud Platform

Когда состоится вебинар?


17 декабря 2020
19:30 20:30 МСК
Подробная информация

Kotlin и Spring Boot


image

Зарегистрироваться

О чем этот вебинар?


В ходе вебинара Рэй поможет вам создать бэкенд-сервис с использованием Spring Boot и Spring Cloud GCP и покажет полезные сервисы Google Cloud для баз данных, хранения и мониторинга состояния. Когда приложение будет готово, Рэй покажет, как с помощью Google Cloud Platform сделать из него бессерверный сервис, и продемонстрирует возможности автоматического масштабирования.

Спикер: Рэй Цанг, Developer Advocate в Google Cloud Platform и Java Champion

Когда состоится вебинар?


14 января 2021
19:30 20:30 МСК
Подробная информация

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

Все вебинары бесплатные. Записи будут доступны на канале JetBrains TV в Youtube. Подпишитесь на JetBrains TV, чтобы не пропустить появление записей.

Узнайте больше о бэкенд-разработке на Kotlin


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

Ваша команда Kotlin
The Drive to Develop
Подробнее..

Перевод Google добавил поддержку Kubernetes в Confidential Computing

14.09.2020 20:08:14 | Автор: admin

TL;DR: Теперь можно запустить Kubernetes на Confidential VMs от Google.



Компания Google сегодня (08.09.2020, прим. переводчика) на мероприятии Cloud Next OnAir сообщила о расширении линейки своих продуктов запуском нового сервиса.


Узлы Confidential GKE добавляют больше секретности нагрузкам, запущенным в Kubernetes. В июле был запущен первый продукт под названием Confidential VMs, а сегодня эти виртуальные машины уже общедоступны всем.


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


Инициатива Confidential Computing от Google основана на сотрудничестве с консорциумом Confidential Computing, отраслевой группой для продвижения концепции надежных окружений исполнения (Trusted Execution Environments, TEEs). TEE защищенная часть процессора, в которой загруженные данные и код зашифрованы, что означает невозможность получения доступа к этой информации другими частями этого же процессора.


Confidential VMs от Google работают на виртуальных машинах N2D, запущенных на процессорах второго поколения EPYC компании AMD, использующих технологию Secure Encrypted Virtualization, позволяющую изолировать виртуальные машины от гипервизора, на котором они работают. Есть гарантия того, что данные остаются зашифрованными вне зависимости от их использования: рабочие нагрузки, аналитика, запросы на тренировку моделей для искуственного интеллекта. Эти виртуальные машины разработаны для удовлетворения потребностей любой компании, работающей с секретными данными в регулируемых областях, например в банковской отрасли.


Возможно более насущным является анонс о предстоящем beta-тестировании узлов Confidential GKE, которые, по словам Google, будут представлены в предстоящем выпуске 1.18 Google Kubernetes Engine (GKE). GKE управляемое, готовое к внедрению на производстве окружение для запуска контейнеров, в которых размещаются части современных приложений, которые можно запускатьв нескольких вычислительных окружениях. Kubernetes инструмент оркестровки с открытым исходным кодом, используемый для управления этими контейнерами.


Добавление узлов Confidential GKE обеспечивает большую секретность при запуске кластеров GKE. При добавлении нового продукта в линейке Confidential Computing мы хотели обеспечить новый уровень
секретности и переносимости для контейнеризированных нагрузок. Узлы Confidential GKE от Google построены на той же технологии, что и Confidential VMs, позволяют вам шифровать данные в оперативной памяти с помощью уникального для каждого узла ключа шифрования, создаваемого и управляемого процессором AMD EPYC. Такие узлы будут использовать аппаратное шифрование оперативной памяти на jснове функции SEV от компании AMD, что означает, что ваши рабочие нагрузки, выполняемые на таких узлах, будут зашифрованы во время их работы.

Sunil Potti и Eyal Manor, инженеры по облачным технологиям, Google


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


Многим предприятиям нужно еще больше секретности при использовании публичных облачных сервисов, чем для локальных рабочих нагрузок, запускаемых на своих мощностях, что нужно для защиты от злоумышленников. Google Cloud расширяя свою линейку Confidential Computing повышает эту планку, предоставляя пользователям возможность обеспечения секретности для кластеров GKE. А с учетом популярности Kubernetes это ключевой шаг вперед для отрасли, дающий компаниям больше возможностей для безопасного размещения приложений следующего поколения в публичном облаке.

Holger Mueller, аналитик Constellation Research.


N.B. Наша компания 28-30 сентября запускает обновлённый интенсив Kubernetes База для тех, кто ещё не знает Kubernetes, но хочет с ним познакомиться и начать работать. А после этого мероприятия 1416 октября мы запускаем обновлённый Kubernetes Мега для опытных пользователей Kubernetes, которым важно знать все последние практические решения в работе с Kubernetes последних версий и возможные грабли. На Kubernetes Мега разбирём в теории и на практике тонкости установки и конфигурации production-ready кластера (the-not-so-easy-way), механизмы обеспечения безопасности и отказоустойчивости приложений.

Кроме прочего Google заявила, что ее Confidential VMs получат некоторые новые возможности, поскольку они становятся общедоступными с этого дня. Например появились отчеты аудита, содержащие подробные журналы проверки целостности прошивки AMD Secure Processor, используемой для создания ключей для каждого экземпляра Confidential VMs.


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


Вы можете использовать комбинацию общих VPC с правилами firewall и ограничениями политики огранизации для обеспечения уверенности в том, что Confidential VMs могут обмениваться данными с другими Confidential VMs, даже если они работают в разных проектах. Кроме этого вы можете использовать VPC Service Controls для задания области ресурсов GCP для ваших Confidential VMs.

Sunil Potti и Eyal Manor

Подробнее..

Хранение данных. Или что такое NAS, SAN и прочие умные сокращения простыми словами

02.09.2020 14:13:27 | Автор: admin

TL;DR: Вводная статья с описанием разных вариантов хранения данных. Будут рассмотрены принципы, описаны преимущества и недостатки, а также предпочтительные варианты использования.



Зачем это все?


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


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


Хранение данных


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


По способу подключения есть следующие варианты:


  • Внутреннее. Сюда относятся классическое подключение дисков в компьютерах, накопители данных устанавливаются непосредственно в том же корпусе, где и будут использоваться. Типовые шины для подключения SATA, SAS, из устаревших IDE, SCSI.


подключение дисков в сервере


  • Внешнее. Подразумевается подключение накопителей с использованием некоторой внешней шины, например FC, SAS, IB, либо с использованием высокоскоростных сетевых карт.


дисковая полка, подключаемая по FC


По типу используемых накопителей возможно выделить:


  • Дисковые. Предельно простой и вероятно наиболее распространенный вариант до сих пор, в качестве накопителей используются жесткие диски
  • Ленточные. В качестве накопителей используются запоминающие устройства с носителем на магнитной ленте. Наиболее частое применение организация резервного копирования.
  • Flash. В качестве накопителей применяются твердотельные диски, они же SSD. Наиболее перспективный и быстрый способ организации хранилищ, по емкости SSD уже фактически сравнялись с жесткими дисками (местами и более емкие). Однако по стоимости хранения они все еще дороже.
  • Гибридные. Совмещающие в одной системе как жесткие диски, так и SSD. Являются промежуточным вариантом, совмещающим достоинства и недостатки дисковых и flash хранилищ.

Если рассматривать форму хранения данных, то явно выделяются следующие:


  • Файлы (именованные области данных). Наиболее популярный тип хранения данных структура подразумевает хранение данных, одинаковое для пользователя и для накопителя.
  • Блоки. Одинаковые по размеру области, при этом структура данных задается пользователем. Характерной особенностью является оптимизация скорости доступа за счет отсутствия слоя преобразования блоки-файлы, присутствующего в предыдущем способе.
  • Объекты. Данные хранятся в плоской файловой структуре в виде объектов с метаданными.


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


  • аппаратные, например RAID и HBA контроллеры, специализированные СХД.


RAID контроллер от компании Fujitsu


  • Программные. Например реализации RAID, включая файловые системы (например, BtrFS), специализированные сетевые файловые системы (NFS) и протоколы (iSCSI), а также SDS


пример организации LVM с шифрованием и избыточностью в виртуальной машине Linux в облаке Azure


Давайте рассмотрим более детально некоторые технологии, их достоинства и недостатки.


DAS


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



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


SAN


Storage area network, она же сеть хранения данных, является технологией организации системы хранения данных с использованием выделенной сети, позволяя таким образом подключать диски к серверам с использованием специализированного оборудования. Так решается вопрос с утилизацией дискового пространства серверами, а также устраняются точки отказа, неизбежно присутствующие в системах хранения данных на основе DAS. Сеть хранения данных чаще всего использует технологию Fibre Channel, однако явной привязки к технологии передачи данных нет. Накопители используются в блочном режиме, для общения с накопителями используются протоколы SCSI и NVMe, инкапсулируемые в кадры FC, либо в стандартные пакеты TCP, например в случае использования SAN на основе iSCSI.



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


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


NAS


Network attached storage, или сетевое файловое хранилище, представляет дисковые ресурсы в виде файлов (или объектов) с использованием сетевых протоколов, например NFS, SMB и прочих. Принципиально базируется на DAS, но ключевым отличием является предоставление общего файлового доступа. Так как работа ведется по сети сама система хранения может быть сколько угодно далеко от потребителей (в разумных пределах разумеется), но это же является и недостатком в случае организации на предприятиях или в датацентрах, поскольку для работы утилизируется полоса пропускания основной сети что, однако, может быть нивелировано с использованием выделенных сетевых карт для доступа к NAS. Также по сравнению с SAN упрощается работа клиентов, поскольку сервер NAS берет на себя все вопросы по общему доступу и т.п.



Unified storage


Универсальные системы, позволяющие совмещать в себе как функции NAS так и SAN. Чаще всего по реализации это SAN, в которой есть возможность активировать файловый доступ к дисковому пространству. Для этого устанавливаются дополнительные сетевые карты (или используются уже существующие, если SAN построена на их основе), после чего создается файловая система на некотором блочном устройстве и уже она раздается по сети клиентам через некоторый файловый протокол, например NFS.


SDS


Software-defined storage программно определяемое хранилище данных, основанное на DAS, при котором дисковые подсистемы нескольких серверов логически объединяются между собой в кластер, который дает своим клиентам доступ к общему дисковому пространству.


Наиболее яркими представителями являются GlusterFS и Ceph, но также подобные вещи можно сделать и традиционными средствами (например на основе LVM2, программной реализации iSCSI и NFS).



N.B. редактора: У вас есть возможность изучить технологию сетевого хранилища Ceph, чтобы использовать в своих проектах для повышения отказоустойчивости, на нашем практическим курсе по Ceph. В начале курса вы получите системные знания по базовым понятиям и терминам, а по окончании научитесь полноценно устанавливать, настраивать и управлять Ceph. Детали и полная программа курса здесь.


Пример SDS на основе GlusterFS


Из преимуществ SDS можно построить отказоустойчивую производительную реплицируемую систему хранения данных с использованием обычного, возможно даже устаревшего оборудования. Если убрать зависимость от основной сети, то есть добавить выделенные сетевые карты для работы SDS, то получается решение с преимуществами больших SAN\NAS, но без присущих им недостатков. Я считаю, что за подобными системами будущее, особенно с учетом того, что быстрая сетевая инфраструктура более универсальная (ее можно использовать и для других целей), а также дешевеет гораздо быстрее, чем специализированное оборудование для построения SAN. Недостатком можно назвать увеличение сложности по сравнению с обычным NAS, а также излишней перегруженностью (нужно больше оборудования) в условиях малых систем хранения данных.


Гиперконвергентные системы


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



Облака и эфемерные хранилища


Логическим продолжением перехода на виртуализацию является запуск сервисов в облаках. В предельном случае сервисы разбиваются на функции, запускаемые по требованию (бессерверные вычисления, serverless). Важной особенностью тут является отсутствие состояния, то есть сервисы запускаются по требованию и потенциально могут быть запущены столько экземпляров приложения, сколько требуется для текущей нагрузки. Большинство поставщиков (GCP, Azure, Amazon и прочие) облачных решений предлагают также и доступ к хранилищам, включая файловые и блочные, а также объектные. Некоторые предлагают дополнительно облачные базы, так что приложение, рассчитанное на запуск в таком облаке, легко может работать с подобными системами хранения данных. Для того, чтобы все работало, достаточно оплатить вовремя эти услуги, для небольших приложений поставщики вообще предлагают бесплатное использование ресурсов в течение некоторого срока, либо вообще навсегда.



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


Заключение


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

Подробнее..

Виртуальные машины А2 крупнейшие облачные образы с графическими процессорами NVIDIA A100 теперь доступны для всех

20.04.2021 12:16:22 | Автор: admin

Недавно, в нашем Google Cloud блоге, мы анонсировали, что в сервисе Compute Engine появились виртуальные машины A2 на базе графических процессоров NVIDIA Ampere A100 с тензорными ядрами. С их помощью пользователи смогут выполнятьмашинное обучениеивысокопроизводительные вычисленияна базе архитектуры NVIDIA CUDA, увеличивая рабочие нагрузки за меньшее время и цену.

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

Высочайшая производительность

Одна ВМ A2 поддерживает до 16графических процессоров NVIDIA A100. На сегодняшний день это самый производительный экземпляр графического процессора на одном узле среди всех конкурирующих решений от крупнейших поставщиков облачных услуг. В зависимости от масштабов рабочей нагрузкивы также можете выбрать виртуальные машины A2 с меньшим числом графических процессоров (1, 2, 4 и 8).

Конфигурации ВМ A2 доступные в сервисе Compute EngineКонфигурации ВМ A2 доступные в сервисе Compute Engine

Это позволяет исследователям, специалистам по обработке данных и разработчикам значительно увеличивать производительность масштабируемых рабочих нагрузок (например, машинное обучение, логический вывод и высокопроизводительные вычисления) на архитектуре CUDA. Семейство ВМ A2 на платформе Google Cloud Platform способно удовлетворить потребности самых требовательных приложений для высокопроизводительных вычислений, например при моделировании методами вычислительной гидродинамики вAltair ultraFluidX.

Для тех, кому нужны сверхпроизводительные системы, Google Cloud предлагает кластеры из тысяч графических процессоров для распределенного машинного обучения, а также оптимизированные библиотеки NCCL для горизонтального масштабирования. Версия ВМ с 16 графическими процессорами A100, объединенными через шинуNVIDIA NVLink, это уникальное предложение Google Cloud. Если вам нужно масштабировать требовательные рабочие нагрузки по вертикали, можно начать с одного графического процессора A100 и довести их число до 16 без настройки нескольких ВМ для машинного обучения на одном узле.

Новая ВМ A2-MegaGPU: 16 графических процессоров A100 со скоростью передачи данных 9,6 ТБ/с по интерфейсу NVIDIA NVLinkНовая ВМ A2-MegaGPU: 16 графических процессоров A100 со скоростью передачи данных 9,6 ТБ/с по интерфейсу NVIDIA NVLink

Чтобы удовлетворить потребности разных приложений, доступны и менее производительные конфигурации ВМ A2 с встроенным SSD-диском на 3ТБ, который ускоряет доставку данных в графический процессор. Так, графический процессор A100 в Google Cloud более чем в 10раз увеличивает скорость предварительного обучения модели BERT-Large по сравнению с NVIDIA V100 прошлого поколения. При этом в конфигурациях с числом графических процессоров от 8 до 16 наблюдается линейный рост производительности. Кроме того, разработчики могут использовать предварительно настроенное ПО в контейнерах из хранилища NVIDIANGCдля быстрого запуска экземпляров A100 в Compute Engine.

Отзывы пользователей

Мы стали предлагать ВМ A2 с графическими процессорами A100 нашим партнерам в июле 2020 года. Сегодня мы работаем со множеством организаций и помогаем им достигать новых высот в области машинного обучения, визуализации и высокопроизводительных вычислений. Вот что они говорят о виртуальных машинах А2:

КомпаниюDessaнедавно приобрел холдинг Square. Она занимается исследованиями в сфере ИИ и стала использовать ВМ A2 одной из первых. На базе ее экспериментов и инноваций Square разрабатывает персонализированные сервисы и умные инструменты для Cash App, которые с помощью ИИ помогают неспециалистампринимать более взвешенные финансовые решения.

"Благодаря Google Cloud мы получили необходимый контроль над своими процессами, говорит Кайл де Фрейтас, старший разработчик ПО в Dessa. Мы понимали, что предлагаемые в Compute Engine ВМ A2 на базе графических процессоровNVIDIA A100с тензорными ядрами способны радикально сократить время вычислений и значительно ускорить наши эксперименты. Процессоры NVIDIA A100, используемые в Google Cloud AI Platform, позволяют нам эффективно развивать инновации и воплощать в жизнь новые идеи для наших клиентов".

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

"Экземпляры A2 с новыми графическими процессорами NVIDIA A100 на платформе Google Cloud поднимают производительность на совершенно новый уровень при настройке моделей глубокого обучения. Мы легко перешли на них с прошлого поколения графических процессоров V100. Благодаря конфигурации ВМ A2-MegaGPU мы не только ускорили обучение более чем в два раза по сравнению с V100, но и получили возможность масштабировать по вертикали рабочие нагрузки с большими нейронными сетями в Google Cloud. Эти инновации помогут нам оптимизировать модели и повышать удобство использования сервисов Hyperconnect", говорит Ким Бемсу, исследователь по машинному обучению в Hyperconnect.

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

"DeepMind занимается искусственным интеллектом. Наши исследователи проводят различные эксперименты в этой сфере с применением аппаратных ускорителей. Благодаря Google Cloud мы получили доступ к новому поколению графических процессоров NVIDIA, а виртуальная машина A2-MegaGPU-16G позволяет проводить обучение моделей быстрее, чем когда-либо. Мы с радостью продолжаем работать с платформой Google Cloud, которая поможет нам создавать будущую инфраструктуру машинного обучения и ИИ", Корай Кавукчуоглу (Koray Kavukcuoglu), вице-президент DeepMind по исследовательской деятельности.

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

"Наша основная миссия расширение возможностей компьютеров. В связи с этим мы сталкиваемся с двумя фундаментальными проблемами. Во-первых, современные алгоритмы ИИ требуют огромных вычислительных мощностей. Во-вторых, специализированное оборудование и ПО в этой области быстро меняются. И с этим нужно что-то делать. Процессоры A100 в GCP в четыре раза производительнее наших нынешних систем, и для их использования не требуется серьезно перерабатывать программный код. По большому счету достаточно минимальных изменений. Графический процессор A100 в Google Cloud позволяет значительно увеличить количество вычислений на доллар. Соответственно, мы можем проводить больше экспериментов и использовать больше данных", говорит Дирк Груневельд, старший разработчик Allen Institute for Artificial Intelligence.

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

"Уже около десяти лет мы расширяем границы возможного в сфере графической визуализации и облачных вычислений и стремимся устранить ограничения для художественного творчества. Благодаря процессорам NVIDIA A100 в Google Cloud с большим объемом видеопамяти и самым высоким рейтингом OctaneBench за всю историю мы первыми достигли уровня, когда художникам при реализации своих замыслов больше не нужно задумываться о сложности прорисовки. Система визуализации OctaneRender снизила стоимость спецэффектов. Она позволяет любому разработчику с графическим процессором NVIDIA создавать великолепную картинку кинематографического качества. Виртуальные машины с процессорами NVIDIA A100 в Google Cloud предоставляют пользователям OctaneRender и RNDR доступ к современным графическим процессорам NVIDIA, прежде доступным только для крупнейших голливудских студий", говорит Джулз Урбах, основатель и генеральный директор OTOY.

Цены и доступность графических процессоров

Экземпляры NVIDIA A100 теперь доступны в следующих регионах: us-central1, asia-southeast1 и europe-west4. В течение 2021года к ним добавятся дополнительные регионы. ВМ A2 в Compute Engine доступны по запросу со скидкой за вытесняемые экземпляры и обязательство по использованию, а также полностью поддерживаются в Google Kubernetes Engine (GKE), Cloud AI Platform и других сервисах Google Cloud. A100 предлагаются по цене всего 0,87доллара США за один графический процессор в вытесняемых ВМ A2. С полным прейскурантом можно ознакомитьсяздесь.

Начало работы

Вы можете быстро развернуть работу, приступить к обучению моделей и выполнять рабочие нагрузки с логическим выводом на графических процессорах NVIDIA A100 с помощьюобразов ВМ для глубокого обученияв доступных регионах. В этих образах собрано все необходимое ПО: драйверы, библиотеки NVIDIA CUDA-X AI и популярные фреймворки для ИИ, такие как TensorFlow и PyTorch. Оптимизированныеобразы TensorFlow Enterpriseтакже включают поддержку A100 для текущих и прошлых версий TensorFlow (1.15, 2.1 и 2.3). Вам не нужно беспокоиться об обновлении ПО, совместимости и настройке производительности всё это мы берем на себя. Наэтой страницеприводятся сведения о доступных в Google Cloud графических процессорах.


Напоминаем что при первой регистрации в Google Cloud: вам доступны бонусы на сумму 300 долларов США, а более 20 бесплатных продуктов доступны всегда. Подробнее поспециальной ссылке.

А так же выражаем благодарность за помощь в подготовке материала коллегам: Бхарат Партасарати, Крис Клебан и Звиад Кардава

Подробнее..

Мастерим задание на деплой в GKE без плагинов, смс и регистрации. Одним глазком заглядываем Jenkinsу под пиджак

12.08.2020 16:20:14 | Автор: admin
Все началось с того, что тимлид одной из наших команд разработчиков попросил в тестовом режиме выставить наружу их новое приложение, которое накануне было подвергнуто контейнеризации. Я выставил. Примерно через 20 минут поступила просьба обновить приложение, потому что там допилили очень нужную штуку. Я обновил. Еще через пару часов ну, вы и так догадываетесь, что стало происходить дальше

Я, признаться, довольно ленив (я же ранее в этом признавался? нет?), и, учитывая тот факт, что тимлиды имеют доступ в Jenkins, в котором у нас весь CI/CD, подумал: да пусть он сам деплоит, сколько заблагорассудится! Вспомнил анекдот: дай человеку рыбу и он будет сыт день; назови человека Сыт и он будет Сыт всю жизнь. И пошел мастрячить джобу, которая бы умела деплоить в кубер контейнер с приложением любой успешно собранной версии и передавать в него любые значения ENV (мой дедушка, филолог, преподаватель английского в прошлом, сейчас бы покрутил пальцем у виска и очень выразительно посмотрел бы на меня, прочитав это предложение).

Итак, в заметке я расскажу о том, как я научился:
  1. Динамически обновлять задания в Jenkins'е из самого задания или из других заданий;
  2. Подключаться к облачной консоли (Cloud shell) с ноды с установленным агентом Jenkins'а;
  3. Деплоить рабочую нагрузку (workload) в Google Kubernetes Engine.

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

Это очередная моя шпаргалка. Такие заметки мне хочется писать лишь в одном случае: передо мной стояла задача, я изначально не знал, как ее решить, решение не нагуглилось в готовом виде, поэтому я его гуглил по частям и в итоге задачу решил. И для того, чтобы в будущем, когда я забуду, как я это сделал, мне не пришлось вновь все гуглить по кускам и компилировать воедино, я пишу себе такие шпаргалки.
Disclaimer: 1. Заметка писалась для себя, на роль best practice не претендует. С удовольствием почитаю варианты а лучше было сделать так в комментариях.
2. Если прикладную часть заметки считать солью, то, как и все мои предыдущие заметки, эта слабосолевой раствор.

Динамическое обновление настроек заданий в Jenkins


Предвижу ваш вопрос: а при чем тут вообще динамическое обновление джобы? Вписал ручками значение строкового параметра и вперед!

Отвечаю: я правда ленивый, не люблю, когда жалуются: Миша, деплой крашится, все пропало! Начинаешь смотреть, а там опечатка в значении какого-нибудь параметра запуска задания. Поэтому предпочитаю все делать максимально фулпруфно. Если есть возможность лишить пользователя возможности вводить данные напрямую, дав вместо этого список значений для выбора, то я организовываю выбор.

План таков: создаем задание в Jenkins, в котором перед запуском можно было бы из списка выбрать версию, указать значения для параметров, передаваемых в контейнер через ENV, далее оно собирает контейнер и пушает его в Container Registry. Далее оттуда контейнер запускается в кубере как workload с параметрами, заданными в джобе.

Процесс создания и настройки задания в Jenkins'е рассматривать не будем, это оффтопик. Будем исходить из того, что задание готово. Для реализации обновляемого списка с версиями, нам нужны две вещи: уже имеющийся список-источник с априори валидными номерами версий и переменная типа Choice parameter в задании. В нашем примере пусть переменная будет носить имя BUILD_VERSION, на ней останавливаться подробно не будем. А вот на списке-источнике давайте остановимся подробнее.

Вариантов не такое уж и множество. Мне сходу в голову пришли два:
  • Использовать Remote access API, который предлагает Jenkins своим пользователям;
  • Запрашивать содержимое удаленной папки репозитория (в нашем случае это JFrog Artifactory, что не принципиально).

Jenkins Remote access API


По сложившейся прекрасной традиции предпочту избежать пространных объяснений.
Позволю себе лишь вольный перевод куска первого абзаца первой страницы документации по API:
Jenkins предоставляет API для удаленного машинно-понятного доступа к своему функционалу. <...> Удаленный доступ предлагается в REST'оподобном стиле. Это означает, что отсутствует единая точка входа ко всем возможностям, а вместо нее используется URL вида ".../api/", где "..." означает объект, к которому применяются возможности API.

Иными словами, если задание на деплой, о котором мы в данный момент говорим, доступно по адресу http://jenkins.mybuild.er/view/AweSomeApp/job/AweSomeApp_build, то API-свистульки для этого задания доступны по адресу http://jenkins.mybuild.er/view/AweSomeApp/job/AweSomeApp_build/api/

Далее у нас есть выбор, в каком виде получать вывод. Остановимся на XML, поскольку API только в этом случае позволяет использовать фильтрацию.
Давайте просто так попробуем получить список всех запусков задания. Нас интересует только имя сборки (displayName) и ее результат (result):
http://jenkins.mybuild.er/view/AweSomeApp/job/AweSomeApp_build/api/xml?tree=allBuilds[displayName,result]

Получилось?
Теперь отфильтруем только те запуски, которые в итоге с результатом SUCCESS. Используем аргумент &exclude и в качестве параметра передадим ему путь до значения не равного SUCCESS. Да-да. Двойное отрицание это утверждение. Исключаем все то, что нас не интересует:
http://jenkins.mybuild.er/view/AweSomeApp/job/AweSomeApp_build/api/xml?tree=allBuilds[displayName,result]&exclude=freeStyleProject/allBuild[result!='SUCCESS']
Скриншот списка успешных


Ну и просто для баловства убедимся, что фильтр нас не обманул (фильтры же никогда не врут!) и выведем список не-успешных:
http://jenkins.mybuild.er/view/AweSomeApp/job/AweSomeApp_build/api/xml?tree=allBuilds[displayName,result]&exclude=freeStyleProject/allBuild[result='SUCCESS']
Скриншот списка не-успешных


Список версий из папки на удаленном сервере


Есть и второй способ получить список версий. Он мне нравится даже больше, чем обращение к API Jenkins'а. Ну, потому что если приложение успешно собралось, значит его упаковали и положили в репозиторий в соответствующую папку. Типа, репозиторий это по умолчанию хранилище рабочих версий приложений. Типа. Ну вот и спросим у него, какие версии на храненнии. Удаленную папку будем curl'ить, grep'ать и awk'ать. Если кому-то интересен уанлайнер, то он под спойлером.
Команда одной строкой
Обратите внимание на две вещи: я передаю в заголовке реквизиты для подключения и мне не нужны прямо вообще все версии из папки, и я отбираю только те, что были созданы в течение месяца. Отредактируйте команду в соответствии с вашими реалиями и потребностями:
curl -H "X-JFrog-Art-Api:VeryLongAPIKey" -s http://arts.myre.po/artifactory/awesomeapp/ | sed 's/a href=//' | grep "$(date +%b)-$(date +%Y)\|$(date +%b --date='-1 month')-$(date +%Y)" | awk '{print $1}' | grep -oP '>\K[^/]+' )


Настройка заданий и файл конфигурации задания в Jenkins


С источником списка версий разобрались. Давайте теперь полученный список вкрутим в задание. Для меня очевидным решением было добавить шаг в задании по сборке приложения. Шаг, который бы выполнялся в случае результата успех.
Открываем настройки задания на сборку и скроллим в самый низ. Жмакаем на кнопочки: Add build step -> Conditional step (single). В настройках шага выбираем условие Current build status, выставляем значение SUCCESS, выполняемое действие в случае успеха Run shell command.

И теперь самое интересное. Конфигурации заданий Jenkins хранит в файлах. В формате XML. По пути http://путь-до-задания/config.xml Соответственно, можно скачать файл с конфигурацией, отредактировать его нужным образом и положить на место, откуда взяли.

Помните, выше мы договорились, что для списка версий создадим параметр BUILD_VERSION?
Давайте скачаем файл конфигурации и заглянем внутрь него. Просто чтобы убедиться, что параметр на месте и в самом деле нужного вида.
Скриншот под спойлером.
У вас приведенный фрагмент config.xml должен выглядеть так же. За тем исключением, что содержимое элемента choices пока что отсутствует


Убедились? Ну все, пишем скрипт, который будет выполняться в случае успешной сборки.
Скрипт будет получать список версий, скачивать файл конфигурации, писать в него в нужное нам место список версий, а потом класть его обратно. Да. Все верно. Писать список версий в XML'ку в то место, где уже есть список версий (будет в будущем, после первого запуска скрипта). Я знаю, в мире еще живут лютые любители регулярных выражений. Я к ним не отношусь. Установите, пожалуйста, xmlstarler на ту машину, где будет редактироваться конфиг. Мне кажется, это не такая уж и большая плата за то, чтобы избежать редактирования XML с помощью sed'а.

Под спойлером привожу код, выполняющий вышеописанную последовательность целиком.
Пишем в конфиг список версий из папки на удаленном сервере
#!/bin/bash############## Скачиваем конфигcurl -X GET -u username:apiKey http://jenkins.mybuild.er/view/AweSomeApp/job/AweSomeApp_k8s/config.xml -o appConfig.xml############## Удаляем и заново создаем xml-элемент для списка версийxmlstarlet ed --inplace -d '/project/properties/hudson.model.ParametersDefinitionProperty/parameterDefinitions/hudson.model.ChoiceParameterDefinition[name="BUILD_VERSION"]/choices[@class="java.util.Arrays$ArrayList"]/a[@class="string-array"]' appConfig.xmlxmlstarlet ed --inplace --subnode '/project/properties/hudson.model.ParametersDefinitionProperty/parameterDefinitions/hudson.model.ChoiceParameterDefinition[name="BUILD_VERSION"]/choices[@class="java.util.Arrays$ArrayList"]' --type elem -n a appConfig.xmlxmlstarlet ed --inplace --insert '/project/properties/hudson.model.ParametersDefinitionProperty/parameterDefinitions/hudson.model.ChoiceParameterDefinition[name="BUILD_VERSION"]/choices[@class="java.util.Arrays$ArrayList"]/a' --type attr -n class -v string-array appConfig.xml############## Читаем в массив список версий из репозиторияreadarray -t vers < <( curl -H "X-JFrog-Art-Api:Api:VeryLongAPIKey" -s http://arts.myre.po/artifactory/awesomeapp/ | sed 's/a href=//' | grep "$(date +%b)-$(date +%Y)\|$(date +%b --date='-1 month')-$(date +%Y)" | awk '{print $1}' | grep -oP '>\K[^/]+' )############## Пишем массив элемент за элементом в конфигprintf '%s\n' "${vers[@]}" | sort -r | \                while IFS= read -r line                do                    xmlstarlet ed --inplace --subnode '/project/properties/hudson.model.ParametersDefinitionProperty/parameterDefinitions/hudson.model.ChoiceParameterDefinition[name="BUILD_VERSION"]/choices[@class="java.util.Arrays$ArrayList"]/a[@class="string-array"]' --type elem -n string -v "$line" appConfig.xml                done############## Кладем конфиг взадcurl -X POST -u username:apiKey http://jenkins.mybuild.er/view/AweSomeApp/job/AweSomeApp_k8s/config.xml --data-binary @appConfig.xml############## Приводим рабочее место в порядокrm -f appConfig.xml


Если вам больше понравился вариант с получением версий из Jenkins'а и вы так же ленивы, как я, то под спойлером тот же самый код, но список из Jenkins'а:
Пишем в конфиг список версий из Jenkins'а
Только учтите момент: у меня имя сборки состоит из порядкового номера и номера версии, разделенных двоеточием. Соответственно, awk отрезает ненужную часть. Для себя эту строку измените под ваши нужды.
#!/bin/bash############## Скачиваем конфигcurl -X GET -u username:apiKey http://jenkins.mybuild.er/view/AweSomeApp/job/AweSomeApp_k8s/config.xml -o appConfig.xml############## Удаляем и заново создаем xml-элемент для списка версийxmlstarlet ed --inplace -d '/project/properties/hudson.model.ParametersDefinitionProperty/parameterDefinitions/hudson.model.ChoiceParameterDefinition[name="BUILD_VERSION"]/choices[@class="java.util.Arrays$ArrayList"]/a[@class="string-array"]' appConfig.xmlxmlstarlet ed --inplace --subnode '/project/properties/hudson.model.ParametersDefinitionProperty/parameterDefinitions/hudson.model.ChoiceParameterDefinition[name="BUILD_VERSION"]/choices[@class="java.util.Arrays$ArrayList"]' --type elem -n a appConfig.xmlxmlstarlet ed --inplace --insert '/project/properties/hudson.model.ParametersDefinitionProperty/parameterDefinitions/hudson.model.ChoiceParameterDefinition[name="BUILD_VERSION"]/choices[@class="java.util.Arrays$ArrayList"]/a' --type attr -n class -v string-array appConfig.xml############## Пишем в файл список версий из Jenkinscurl -g -X GET -u username:apiKey 'http://jenkins.mybuild.er/view/AweSomeApp/job/AweSomeApp_build/api/xml?tree=allBuilds[displayName,result]&exclude=freeStyleProject/allBuild[result!=%22SUCCESS%22]&pretty=true' -o builds.xml############## Читаем в массив список версий из XMLreadarray vers < <(xmlstarlet sel -t -v "freeStyleProject/allBuild/displayName" builds.xml | awk -F":" '{print $2}')############## Пишем массив элемент за элементом в конфигprintf '%s\n' "${vers[@]}" | sort -r | \                while IFS= read -r line                do                    xmlstarlet ed --inplace --subnode '/project/properties/hudson.model.ParametersDefinitionProperty/parameterDefinitions/hudson.model.ChoiceParameterDefinition[name="BUILD_VERSION"]/choices[@class="java.util.Arrays$ArrayList"]/a[@class="string-array"]' --type elem -n string -v "$line" appConfig.xml                done############## Кладем конфиг взадcurl -X POST -u username:apiKey http://jenkins.mybuild.er/view/AweSomeApp/job/AweSomeApp_k8s/config.xml --data-binary @appConfig.xml############## Приводим рабочее место в порядокrm -f appConfig.xml


По идее, если вы протестировали код, написанный на основе примеров выше, то в задании на деплой у вас уже должен появиться выпадающий список с версиями. Вот примерно как на скриншоте под спойлером.
Корректно заполненный список версий


Если все отработало, то копипастите скрипт в Run shell command и сохраняйте изменения.

Подключение к Cloud shell


Сборщики у нас в контейнерах. В качестве средства доставки приложений и менеджера конфигураций мы используем Ansible. Соответственно, когда речь заходит о сборке контейнеров, вариантов в голову приходит три: установить Docker в Docker'е, установить Docker на машину с Ansible'ом, либо собирать контейнеры в облачной консоли. Про плагины для Jenkins мы договорились в этой заметке молчать. Помните?

Я решил: ну, раз контейнеры из коробки можно собирать в облачной консоли, то зачем городить огород? Keep it clean, верно? Хочу собирать контейнеры Jenkins'ом в облачной консоли, а потом оттуда же пулять их в кубер. Тем более, что внутри инфраструктуры у гугла ну ооочень жирные каналы, что благоприятно скажется на скорости деплоя.

Для подключения к облачной консоли необходимы две вещи: gcloud и права доступа к Google Cloud API для того экземпляра ВМ, с которой будет это самое подключение осуществляться.
Для тех, кто планирует подключаться вообще не из гуглового облака
Гугл допускает возможность отключения интерактивной авторизации в своих сервисах. Это позволит подключаться к консоли хоть с кофемашины, коли она под *nix'ами и у нее самой есть консоль.
Если есть потребность в том, чтобы я осветил этот вопрос подробнее в рамках этой заметки пишите в комментариях. Наберется достаточное количество голосов напишу апдейт по этой теме.

Простейший способ дать права через веб-интерфейс.
  1. Остановите экземпляр ВМ, с которого в дальнейшем будет выполняться подключение к облачной консоли.
  2. Откройте Сведения экземпляра и нажмите Изменить.
  3. В самом низу страницы выберите область действия доступа экземпляра Полный доступ ко всем Cloud API.
    Скриншот

  4. Сохраните изменения и запустите экземпляр.

По окончании загрузки ВМ, подключитесь к ней по SSH и убедитесь, что подключение происходит без ошибки. Воспользуйтесь командой:
gcloud alpha cloud-shell ssh

Успешное подключение выглядит примерно так


Деплой в GKE


Поскольку мы всячески стремимся полностью перейти на IaC (Infrastucture as a Code), докерфайлы у нас хранятся в гите. Это с одной стороны. А деплой в kubernetes описывается yaml-файлом, который используется только данным заданием, который сам по себе тоже как бы код. Это с другой стороны. В общем, я к тому, что план таков:
  1. Берем значения переменных BUILD_VERSION и, опционально, значения переменных, которые будут переданы через ENV.
  2. Качаем из гита докерфайл.
  3. Генерируем yaml для деплоя.
  4. Заливаем оба этих файла по scp в облачную консоль.
  5. Билдим там контейнер и пушаем его в Container registry
  6. Применяем файл деплоя нагрузки в кубер.

Давайте более конкретно. Раз заговорили об ENV, то предположим, нам надо будет передавать значения двух параметров: PARAM1 и PARAM2. Добавляем их задание на деплой, тип String Parameter.
Скриншот


Генерировать yaml будем простым перенаправлением echo в файл. Предполагатся, разумеется, что в докерфайле у вас присутcnвуют PARAM1 и PARAM2, что имя нагрузки будет awesomeapp, а собранный контейнер с приложением указанной версии лежит в Container registry по пути gcr.io/awesomeapp/awesomeapp-$BUILD_VERSION, где $BUILD_VERSION как раз и был выбран из выпадающего списка.
Листинг команд
touch deploy.yamlecho "apiVersion: apps/v1" >> deploy.yamlecho "kind: Deployment" >> deploy.yamlecho "metadata:" >> deploy.yamlecho "  name: awesomeapp" >> deploy.yamlecho "spec:" >> deploy.yamlecho "  replicas: 1" >> deploy.yamlecho "  selector:" >> deploy.yamlecho "    matchLabels:" >> deploy.yamlecho "      run: awesomeapp" >> deploy.yamlecho "  template:" >> deploy.yamlecho "    metadata:" >> deploy.yamlecho "      labels:" >> deploy.yamlecho "        run: awesomeapp" >> deploy.yamlecho "    spec:" >> deploy.yamlecho "      containers:" >> deploy.yamlecho "      - name: awesomeapp" >> deploy.yamlecho "        image: gcr.io/awesomeapp/awesomeapp-$BUILD_VERSION:latest" >> deploy.yamlecho "        env:" >> deploy.yamlecho "        - name: PARAM1" >> deploy.yamlecho "          value: $PARAM1" >> deploy.yamlecho "        - name: PARAM2" >> deploy.yamlecho "          value: $PARAM2" >> deploy.yaml


Агенту Jenkins'а после подключения с помощью gcloud alpha cloud-shell ssh интерактивный режим не доступен, поэтому передаем команды в облачную консоль с помощью параметра --command.
Чистим домашнюю папку в облачной консоли от старого докерфайла:
gcloud alpha cloud-shell ssh --command="rm -f Dockerfile"

Кладем свежескаченный докерфайл в домашнюю папку облачной консоли с помощью scp:
gcloud alpha cloud-shell scp localhost:./Dockerfile cloudshell:~

Собираем, тегируем и пушаем контейнер в Container registry:
gcloud alpha cloud-shell ssh --command="docker build -t awesomeapp-$BUILD_VERSION ./ --build-arg BUILD_VERSION=$BUILD_VERSION --no-cache"gcloud alpha cloud-shell ssh --command="docker tag awesomeapp-$BUILD_VERSION gcr.io/awesomeapp/awesomeapp-$BUILD_VERSION"gcloud alpha cloud-shell ssh --command="docker push gcr.io/awesomeapp/awesomeapp-$BUILD_VERSION"

Аналогичным образом поступаем с файлом деплоя. Обратите внимания, что в командах ниже используются вымышленные имена кластера, куда происходит деплой (awsm-cluster) и имя проекта (awesome-project), где находется кластер.
gcloud alpha cloud-shell ssh --command="rm -f deploy.yaml"gcloud alpha cloud-shell scp localhost:./deploy.yaml cloudshell:~gcloud alpha cloud-shell ssh --command="gcloud container clusters get-credentials awsm-cluster --zone us-central1-c --project awesome-project && \kubectl apply -f deploy.yaml"

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


А далее и успешный деплой собранного контейнера
Скриншот



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

Вместо выводов


Все приведенные выше шаги, наверное, можно было не делать, а просто установить какой-нибудь плагин для Jenkins'а, их мууульон. Но я почему-то не люблю плагины. Ну, точнее, прибегаю к ним только от безысходности.
А еще мне просто нравится расковырять какую-нибудь новую для меня тему. Текст выше в том числе и способ поделиться находками, которые я сделал, решая описанную в самом начале задачу. Поделиться с теми, кто, как и, вовсе не лютый волк в девопсе. Если хотя бы кому-то мои находки помогут буду доволен.
Подробнее..

Перевод Ускоряем разработку для Cloud Run с помощью Cloud Code

13.10.2020 10:19:44 | Автор: admin

При разработке сервисов для полностью управляемой контейнерной платформы Cloud Run, вы, скорее всего, быстро устанете постоянно переключаться между редактором кода, терминалом и Google Cloud Console. Мало того, вам ещё придется по много раз, при каждом развертывании, выполнять одни и те же команды. Cloud Code это набор инструментов, включающий все необходимое для написания, отладки и развертывания облачных приложений. Он повышает эффективность разработки в Google Cloud за счет использования плагинов для популярных сред разработки, таких как VS Code и IntelliJ. С его помощью вы сможете легко заниматься разработкой в Cloud Run. Подробнее под катом.


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


Примечание от автора. На виртуальной конференции Google Cloud Next 2020 OnAir мы анонсировали несколько новых функций и сервисов, призванных ускорить процесс доставки и разработки приложений, а также платформу Cloud для модернизации приложений (Cloud Application Modernization Platform или CAMP).

Создание новых сервисов Cloud Run


На первый взгляд контейнеризация и бессерверные сервисы могут казаться чересчур сложными. Если вы только начинаете знакомиться с Cloud Run, обратите внимание на обновленный список примеров Cloud Run в Cloud Code. Примеры доступны на языках Java, NodeJS, Python, Go и .NET. Опираясь на них, вы сможете сразу приступить к написанию собственного кода с учетом всех рекомендаций.
Все примеры включают файл Dockerfile, чтобы вам не пришлось тратить время, разбираясь в конфигурациях контейнеров. Если вы переносите в Cloud Run существующий сервис, то, возможно, вы ещё не работали с файлами Dockerfile. Ничего страшного! В сервисе Cloud Code есть поддержка объектов Google Cloud Buildpack, позволяющих контейнеризовать сервис прямо в коде. Файл Dockerfile при этом не требуется. Cloud Code содержит все необходимое для развертывания вашего сервиса в Cloud Run.



Разработка и отладка сервисов Cloud Run в локальной среде


Прежде чем развернуть сервис в Google Cloud, вы, скорее всего, захотите попробовать его на своем компьютере, чтобы посмотреть, как он работает, внести необходимые правки и отладить ошибки. При разработке сервисы Cloud Run необходимо постоянно собирать и развертывать в облаке, чтобы тестировать изменения в репрезентативной среде Cloud Run. Отладить код можно и локально, подключив отладчик, однако, поскольку это осуществляется не на уровне всего контейнера, вам придется устанавливать инструменты локально. Запустить контейнер в локальной среде можно с помощью Docker, но команда, необходимая для этого, слишком длинна и не отражает особенности производственной среды.


В Cloud Code имеется эмулятор Cloud Run, позволяющий разрабатывать и отлаживать сервисы Cloud Run локально. Согласно исследованию, проведенному DevOps Research and Assessment (DORA), у команд, показавших высокую эффективность поставки ПО, сбои при внесении изменений случались в 7 раз реже, чем у менее эффективных команд. Благодаря возможности быстро выполнять итерацию кода локально и отлаживать его в репрезентативной среде, вы можете оперативно находить ошибки на ранних этапах разработки, а не во время непрерывной интеграции или, того хуже, в продакшене.


При запуске кода в эмуляторе Cloud Run можно включить режим просмотра. Каждый раз при сохранении файлов ваш сервис будет повторно развертываться в эмуляторе для непрерывной разработки.


Первый запуск Cloud Run Emulator:

Отладка сервисов Cloud Run с помощью Cloud Code осуществляется так же, как в привычной вам среде разработки. Выполните команду "Debug on Cloud Run Emulator" в среде VS Code (или выберите конфигурацию "Cloud Run: Run Locally" и выполните команду "Debug" в среде IntelliJ) и просто установите точки останова кода. Как только точка останова будет активирована в вашем контейнере, вы сможете переключаться между командами, наводить курсор на свойства переменных и проверять журналы из контейнера.


Отладка сервиса Cloud Run с помощью Cloud Code в VS Code и IntelliJ idea:


Развертывание сервиса в Cloud Run


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


Развернуть сервис из среды разработки не составит никакого труда. Мы добавили все параметры, необходимые для настройки сервиса перед развертыванием. Когда вы нажмете "Развернуть", Cloud Code выполнит все требуемые команды, чтобы создать образ контейнера, развернуть его в Cloud Run и передать URL-адрес сервису.


Развертывание сервиса в Cloud Run:

Управление сервисами Cloud Run


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



Кроме того, в проводнике Cloud Run можно быстро найти и просмотреть сведения обо всех управляемых сервисах Cloud Run и сервисах Cloud Run для Anthos в нужном проекте. Там же можно легко узнать, какой процент трафика перенаправляется и сколько выделено ресурсов ЦП.


Cloud Run explorer в VS Code и IntelliJ


Нажав на версию правой кнопкой мыши, можно посмотреть URL-адрес сервиса. В Cloud Console можно проверить трафик или настроить его перенаправление между сервисами.


Начало работы


Приглашаем вас поработать с Cloud Code в Cloud Run, чтобы оптимизировать процессы развертывания сервисов и ведения журналов. Дополнительные сведения можно найти в документации по Cloud Run для сред разработки Visual Studio Code и JetBrains. Если вы ещё не работали с этими средами, для начала установите Visual Studio Code или IntelliJ.


Присоединяйтесь к Google Cloud Next OnAir


Также хотелось бы напомнить нашим читателям, что прямо сейчас проходит онлайн конференция Google Cloud Next OnAir EMEA для которой мы подготовили контент как для разработчиков, так и для архитекторов решений и руководителей.


Более подробно узнать о сессиях, спикерах и получить доступ к контенту можно бесплатно зарегистрировавшись на странице Next OnAir EMEA. Вместе с уникальным контентом, который будет представлен для Next OnAir EMEA вы также получите полный доступ к более чем 250 сессиям с глобальной части Google Cloud Next 20: OnAir.

Подробнее..

Переход с Azure на GCP, с ASP.NET MVC на ASP.NET Core 3.1

26.01.2021 20:09:19 | Автор: admin

Автор: Андрей Жуков, .NET Team Leader, DataArt

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

Задача, поставленная заказчиком: Azure -> GCP

Заказчик решил перейти из одного облака (Azure) в другое (Google Cloud Platform). В некотором отдаленном будущем вообще планировалось перевести серверную часть на Node.js и развивать систему силами команды full-stack typescript-разработчиков. На момент моего входа в проект там существовала пара ASP.NET MVC приложений, которым решили продлить жизнь. Их мне и предстояло перенести в GCP.

Начальная состояние, факторы, мешающие сразу перейти на GCP

Первоначально имелось два ASP.NET MVC-приложения, которые взаимодействовали с одной общей MS SQL базой данных. Они были развернуты на Azure App Services.

Первое приложение назовем его Web Portal имело пользовательский интерфейс, построенный на базе Razor, TypeScript, JavaScript, Knockout и Bootstrap. С этими клиентскими технологиями никаких проблем не предвиделось. Зато серверная часть приложения использовала несколько сервисов, специфичных для Azure: Azure Service Bus, Azure Blobs, Azure Tables storage, Azure Queue storage. С ними предстояло что-то делать, т. к. в GCP ни один из них не поддерживается. Кроме того, приложение использовало Azure Cache for Redis. Для обработки длительных запросов была задействована служба Azure WebJob, задачи которой передавались через Azure Service Bus. По словам программиста, занимавшегося поддержкой, фоновые задачи могли выполняться до получаса.

Изначально архитектура Web Portal в нашем проекте выглядела такИзначально архитектура Web Portal в нашем проекте выглядела так

Azure WebJobs тоже предстояло чем-то заменить. Архитектура с очередью заданий для длительных вычислений не единственное среди возможных решений можно использовать специализированные библиотеки для фоновых задач, например, Hangfire, или обратиться к IHostedService от Microsoft.

Второе приложение назовем его Web API представляло собой ASP.NET WEB API. Оно использовало только MS SQL базы данных. Вернее, в конфигурационном файле были ссылки на несколько баз данных, в реальности же приложение обращалось только к одной их них. Но об этом нюансе мне только предстояло узнать.

Оба приложения были в работающем, но плохом состоянии: отсутствовала архитектура как таковая, было много старого неиспользуемого кода, не соблюдались принципы построения ASP.NET MVC приложений и т. д. Заказчик и сам признавал низкое качество кода, а человек, изначально написавший приложения, уже несколько лет не работал в компании. Был дан зеленый свет любым изменениям и новым решениям.

Итак, нужно было перевести ASP.NET MVC приложения на ASP.NET Core 3.1, перевести WebJob c .NET Framework на .NET Core, чтобы можно было разворачивать их под Linux. Использовать Windows на GCP возможно, но не целесообразно. Надо было избавиться от сервисов, специфичных для Azure, заменить чем-то Azure WebJob, решить, как будем развертывать приложения в GCP, т. е. выбрать альтернативу Azure App Services. Требовалось добавить поддержку Docker. При этом неплохо было бы внести хоть какую-то архитектуру и поправить качество кода.

Общие принципы и соображения

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

В конце каждого этапа приложение должно находиться в стабильном состоянии, т. е. пройти хотя бы Smoke tests.

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

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

При замене сервисов Azure можно либо подобрать альтернативный GCP-сервис, либо выбрать cloud-agnostic-решение. Выбор сервисов в этом проекте и его обоснование в каждом случае мы рассмотрим отдельно.

План работ

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

  1. Web Portal c ASP.NET MVC на ASP.NET Core

    1.1. Анализ кода и зависимостей Web Portal от сервисов Azure и сторонних библиотек, оценка необходимого времени.

    1.2. Перевод Web Portal на .NET Core.

    1.3. Рефакторинг с целью устранения основных проблем.

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

    1.5. Докеризация Web Portal.

    1.6. Тестирование Web Portal, устранение ошибок и развертывание новой версии на Azure.

  2. Web API c ASP.NET MVC на ASP.NET Core

    2.1. Написание E2E автоматических тестов для Web API.

    2.2. Анализ кода и зависимостей Web API от сервисов Azure и сторонних библиотек, оценка необходимого времени.

    2.3. Удаление неиспользуемого исходного кода из Web API.

    2.4. Перевод Web API на .NET Core.

    2.5. Рефакторинг Web API с целью устранения основных проблем.

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

    2.7. Докеризация Web API.

    2.8. Тестирование Web API, устранение ошибок и развертывание новой версии на Azure.

  3. Устранение зависимостей от Azure

    3.1. Устранение зависимостей Web Portal от Azure.

  4. Развертывание в GCP

    4.1. Развертывание Web Portal в тестовой среде в GCP.

    4.2. Тестирование Web Portal и устранение возможных ошибок.

    4.3. Миграция базы данных для тестовой среды.

    4.4. Развертывание Web API в тестовой среде в GCP.

    4.5. Тестирование Web API и устранение возможных ошибок.

    4.6. Миграция базы данных для prod-среды.

    4.7. Развертывание Web Portal и Web API в prod GCP.

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

.NET Framework -> .NET Core

Перед началом переноса кода я нашел статью о миграции .Net Framework на .Net Core от Microsoft и далее ссылку на миграцию ASP.NET на ASP.NET Core.

С миграцией не-Web-проектов все обстояло относительно просто:

  • преобразование формата хранения NuGet-пакетов с помощью Visual Studio 2019;

  • адаптирование списка этих пакетов и их версий;

  • переход с App.config в XML на settings.json и замена всех имеющихся обращений к конфигурационным значениям на новый синтаксис.

Некоторые версии NuGet-пакетов Azure SDK претерпели изменения, повлекшие несовместимость. В большинстве случаев удалось найти не всегда самую новую, зато поддерживаемую кодом .NET Core версию, которая не требовала бы изменений в логике старого программного кода. Исключением стали пакеты для работы с Azure Service Bus и WebJobs SDK. Пришлось с Azure Service Bus перейти на бинарную сериализацию, а WebJob перевести на новую, обратно несовместимую версию SDK.

C миграцией ASP.NET MVC на ASP.NET Core дело обстояло намного сложнее. Все перечисленные выше действия нужно было проделать и для Web-проектов. Но начинать пришлось с нового ASP.NET Core проекта, куда мы перенесли код старого проекта. Структура ASP.NET Core проекта сильно отличается от предшественника, многие стандартные классы ASP.NET MVC претерпели изменения. Ниже я привожу список того, что изменили мы, и большая его часть будет актуальна для любого перехода с ASP.NET MVC на ASP.NET Core.

  1. Создание нового проекта ASP.NET Core и перенос в него основного кода из старого ASP.NET MVC проекта.

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

  3. Замена Web.config на appsettings.json и все связанные с этим изменения в коде.

  4. Внедрение стандартного механизма Dependency injection от .NET Core вместо любой его альтернативы, использовавшейся в Asp.NET MVC проекте.

  5. Использование StaticFiles middleware для всех корневых папок статических файлов: изображений, шрифтов, JavaScript-скриптов, CSS-стилей и т. д.

app.UseStaticFiles(); // wwwrootapp.UseStaticFiles(new StaticFileOptions   {     FileProvider = new PhysicalFileProvider(         Path.Combine(Directory.GetCurrentDirectory(), "Scripts")),     RequestPath = "/Scripts"});

Можно перенести все статические файлы в wwwroot.

6. Переход к использованию bundleconfig.json для всех JavaScript и CSS-бандлов вместо старых механизмов. Изменение синтаксиса подключения JavaScript и CSS:

<link rel="stylesheet" href="~/bundles/Content.css" asp-append-version="true" /><script src="~/bundles/modernizr.js" asp-append-version="true"></script>

Чтобы директива asp-append-version="true" работала корректно, бандлы (bundles) должны находиться в корне, т. е. в папке wwwroot (смотри здесь).

Для отладки бандлов я использовал адаптированную версию хелпера отсюда.

7. Изменение механизма обработки UnhadledExceptions: в ASP.NET Core реализована его поддержка, остается с ней разобраться и использовать вместо того, что применялось в проекте раньше.

8. Логирование: я адаптировал старые механизмы логирования для использования стандартных в ASP.NET Core и внедрил Serilog. Последнее опционально, но, по-моему, сделать это стоит для получения гибкого structured logging c огромным количеством вариантов хранения логов.

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

10. Routing: в старом проекте использовался механизм, основанный на templates, его надо было чуть-чуть подправить.

11. JSON-сериализация: В ASP.NET Core по умолчанию используется библиотека System.Text.Json вместо Newtonsoft.Json. Microsoft утверждает, что она работает быстрее предшественницы, однако, в отличие от последней, она не поддерживает многое из того, что Newtonsoft.Json умела делать из коробки безо всякого участия программиста. Хорошо, что есть возможность переключиться обратно на Newtonsoft.Json. Именно это я и сделал, когда выяснил, что большая часть сериализации в Web API была сломана, и вернуть ее в рабочее состояние с помощью новой библиотеки, если и возможно, очень непросто. Подробнее об использовании Newtonsoft.Json можно прочитать здесь.

12. В старом проекте использовался Typescript 2.3. С его подключением пришлось повозиться, потребовалось установить Node.js, подобрать правильную версию пакета Microsoft.TypeScript.MSBuild, добавить и настроить tsconfig.json, поправить файл определений (Definitions) для библиотеки Knockout, кое-где добавить директивы //@ts-ignore.

13. Код для принудительной поддержки HTTPS включается автоматически при включении этой опции в визарде проекта. Старый код, использующий пользовательский атрибут HttpsOnly, был при этом убран.

14. Все низкоуровневые действия, такие как получение параметров из body запроса, URL запроса, HTTP Headers и HttpContext потребовали изменений, т. к. API для доступа к ним претерпел изменения по сравнению с ASP.NET MVC. Работы было бы заметно меньше, если бы в старом проекте чаще использовались стандартные binding механизмы через параметры экшенов (Actions) и контроллеров (Controllers).

15. Был добавлен Swagger c помощью библиотеки Swashbuckle.AspNetCore.Swagger.

16. Нестандартный механизм Authentication потребовал рефакторинга для приведения его к стандартному виду.

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

Что делать со специфичными сервисами Azure?

После перехода на ASP.NET Core предстояло избавиться от Azure-сервисов. Можно было либо подобрать решения, которые не зависят от облачной платформы, либо найти что-то подходящее из списка GCP. Благо у многих сервисов есть прямые альтернативы у других облачных провайдеров.

Azure Service Bus мы по настоятельной рекомендации заказчика решили заменить на Redis Pub/Sub. Это достаточно простой инструмент, не настолько мощный и гибкий как, например, RabbitMQ. Но для нашего простого сценария его хватало, а в пользу такого выбора говорило то, что Redis в проекте уже использовался. Время подтвердило решение было правильным. Логика работы с очередью была абстрагирована и выделена в два класса, один из которых реализует отправку произвольного объекта, другой получает сообщения и передает их на обработку. На выделение этих объектов ушло всего несколько часов, а если сам Redis Pub/Sub вдруг потребуется заменить, то и это будет очень просто.

Azure Blobs были заменены на GCP Blobs. Решение очевидное, но все-таки различие в функциональности сервисов нашлось: GCP Blobs не поддерживает добавление данных в конец существующего блоба. В нашем проекте такой блоб использовался для создания подобия логов в формате CSV. На платформе Google мы решили записывать эту информацию в Google Cloud operations suite, ранее известный как Stackdriver.

Хранилище Azure Table Storage использовалось для записи логов приложения и доступа к ним из Web Portal. Для этого существовал логгер, написанный самостоятельно. Мы решили привести этот процесс в соответствие с практиками от Microsoft, т. е. использовать их интерфейс ILogger. Кроме того, была внедрена библиотека для структурного логирования Serilog. В GCP логирование настроили в Stackdriver.

Какое-то время проект должен был параллельно работать и на GCP, и на Azure. Поэтому вся функциональность, зависящая от платформы, была выделена в отдельные классы, реализующие общие интерфейсы: IBlobService, IRequestLogger, ILogReader. Абстрагирование логирования было достигнуто автоматически за счет использования библиотеки Serilog. Но для того, чтобы показывать логи в Web Portal, как это делалось в старом приложении, понадобилось адаптировать порядок записей в Azure Table Storage, реализуя свой Serilog.Sinks.AzureTableStorage.KeyGenerator.IKeyGenerator. В GCP для чтения логов изGoogle Cloud operations были созданы Log Router Sinks, передающие данные в BigQuery, откуда приложение и получало их.

Что делать с Azure WebJobs?

Сервис Azure WebJobs доступен только для Azure App Services on Windows. По сути он представляет собой консольное приложение, использующее специальный Azure WebJobs SDK. Зависимость от этого SDK я убрал. Приложение осталось постоянно работающим консольным и следует похожей логике:

static async Task Main(string[] args){.   var builder = new HostBuilder();  ...              var host = builder.Build();  using (host)  {     await host.RunAsync();  }...}

За всю работу отвечает зарегистрированный с помощью Dependency Injection класс

public class RedisPubSubMessageProcessor : Microsoft.Extensions.Hosting.IHostedService{...public async Task StartAsync(CancellationToken cancellationToken)...public async Task StopAsync(CancellationToken cancellationToken)...}

Это стандартный для .NET Core механизм. Несмотря на отсутствие зависимости от Azure WebJob SDK, это консольное приложение успешно работает как Azure WebJob. Оно также без проблем работает в Linux Docker-контейнере под управлением Kubernetes, о чем речь в статье пойдет позже.

Рефакторинг по дороге

Архитектура и код приложения были далеки от идеала. В ходе многих шагов постепенно производились небольшие изменения кода, который они затрагивали. Были и специально запланированные этапы рефакторинга, согласованные и оцененные вместе с заказчиком. На этих этапах мы устраняли проблемы с аутентификацией и авторизацией, переводили их на практики от Microsoft. Был отдельный этап по внесению некой архитектуры, выделению слоев, устранению ненужных зависимостей. Работа с Web API началась с этапа удаления неиспользуемого кода. При замене многих Azure-сервисов на первом этапе производилось определение интерфейсов, выделение данных зависимостей в отдельные классы.

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

Docker

С поддержкой Docker все сложилось довольно гладко. Dockerfile можно легко добавить с помощью Visual Studio. Я добавил их для всех проектов, соответствующих приложениям, для Web Portal, Web API, WebJob (который в дальнейшем превратился просто в консольное приложение). Эти стандартные Dockerfile от Microsoft не претерпели особенных изменений и заработали из коробки за единственным исключением пришлось в Dockerfile для Web Portal добавить команды для установки Node.js. Этого требует build контейнер для работы с TypeScript.

RUN apt-get update && \apt-get -y install curl gnupg && \curl -sL https://deb.nodesource.com/setup_12.x  | bash - && \apt-get -y install nodejs

Azure App Services -> GKE

Нет единственно правильного решения для развертывания .NET Core-приложений в GCP, вы всегда можете выбрать из нескольких опций:

  • App Engine Flex.

  • Kubernetes Engine.

  • Compute Engine.

В нашем случае я остановился на Google Kubernetes Engine (GKE). Причем к этому моменту у нас уже были контейнеризованные приложения (Linux). GKE, оказалось, пожалуй, наиболее гибким из трех представленных выше решений. Оно позволяет разделять ресурсы кластера между несколькими приложениями, как в нашем случае. В принципе для выбора одного из трех вариантов можно воспользоваться блок-схемой по этой сслыке.

Выше описаны все решения по используемым сервисам GCP, кроме MS SQL Server, который мы заменили на Cloud SQL от Google.

Архитектура нашей системы после миграции в GCPАрхитектура нашей системы после миграции в GCP

Тестирование

Web Portal тестировался вручную, после каждого этапа я сам проводил простенький Smoke-тест. Это было обусловлено наличием пользовательского интерфейса. Если по завершении очередного этапа, новый кусок кода выпускался в Prod, к его тестированию подключались другие пользователи, в частности, Product Owner. Но выделенных QA-специалистов, в проекте, к сожалению, не было. Разумеется, все выявленные ошибки исправлялись до начала очередного этапа. Позднее был добавлен простой Puppeteer-тест, который исполнял сценарий загрузки одного из двух типов отчетов с какими-то параметрами и сравнивал полученный отчет с эталонным. Тест был интегрирован в CICD. Добавить какие-то юнит-тесты было проблематично по причине отсутствия какой-либо архитектуры.

Первым этапом миграции Web API, наоборот, было написание тестов. Для это использовался Postman, затем эти тесты вызывались в CICD с помощью Newman. Еще раньше к старому коду была добавлена интеграция со Swagger, который помог сформировать начальный список адресов методов и попробовать многие из них. Одним из следующих шагов было определение актуального перечня операций. Для этого использовались логи IIS (Internet Information Services), которые были доступны за полтора месяца. Для многих актуальных методов перечня было создано несколько тестов с разными параметрами. Тесты, приводящие к изменению данных в базе, были выделены в отдельную Postman-коллекцию и не запускались на общих средах выполнения. Разумеется, все это было параметризовано, чтобы можно было запускать и на Staging, и на Prod, и на Dev.

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

Azure MS SQL -> GCP Managed MS SQL

Миграция MS SQL из Managed Azure в GCP Cloud SQL оказалась не такой простой задачей, как представлялось вначале. Основных причин тому оказался несколько:

  • Очень большой размер базы данных (Azure портал показал: Database data storage /

    Used space 181GB).

  • Наличие зависимостей от внешних таблиц.

  • Отсутствие общего формата для экспорта из Azure и импорта в GCP Cloud SQL.

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

Перед началом миграции нужно удалить все ссылки на внешние таблицы и базы данных, иначе миграция будет неудачной. Azure SQL поддерживает экспорт только в формат bacpac, более компактный по сравнению со стандартным backup форматом. В нашем случае вышло 6 Гб в bacpac против 154 Гб в backup. Но GCP Cloud позволят импортировать только backup, поэтому нам потребовалась конвертация, сделать которую удалось лишь посредством восстановления в локальную MS SQL из bacpac и создания backup уже из нее. Для этих операций потребовалось установить последнюю версию Microsoft SQL Server Management Studio, причем локальный сервер MS SQL Server был версией ниже. Немало операций заняли по многу часов, некоторые и вовсе длились по несколько дней. Рекомендую увеличить квоту Azure SQL перед импортом и сделать копию prod базы, чтобы импортировать из нее. Где-то нам потребовалось передавать файл между облаками, чтобы ускорить загрузку на локальную машину. Мы также добавили SSD-диск на 1 Тб специально под файлы базы данных.

Задачи на будущее

При переходе с Azure App Services на GCP Kubernetes мы потеряли CICD, Feature Branch deployments, Blue/Green deployment. На Kubernetes все это несколько сложнее и требует иной реализации, но наверняка делается посредством все тех же Github Actions. В новом облаке следуем концепции Iac (Infrastructure-as-Code) вместе с Pulumi.

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

Подробнее..

Перевод Как магия машинного обученияменяет нашу жизнь

05.04.2021 16:10:13 | Автор: admin

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

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

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

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

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

Обычно я советую обратиться к таким ресурсам, как курс компании Google под названиемMachine Learning Crash Course, а также книгаПрикладное машинное обучение с помощью Scikit-Learn, Keras и TensorFlowи курс на сайте CourseraМашинное обучение(автор: Andrew Ng), который нацелен не только на теоретические основы, но и на практику.

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

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

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

Внедрение машинного обучения в свои проекты

Умный архив семейных видео

  • Вы создадите: архив, который сможет предоставлять видео по фразе или объекту из записи (например, "день рождения", "велосипед" или "видеоигры").

  • Вы узнаете:

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

    • как использовать Video Intelligence API;

    • как проектировать приложение, в основе которого лежит машинное обучение (в этом помогут инструментыFlutter для создания клиентской части,Firebase для написания кода без использования серверов, и поиск как сервис, предоставленныйAlgolia).

Бот-модератор в Discord

  • Вы создадите: бот для чат-платформыDiscord,который помогает находить оскорбительные и нецензурные сообщения, а также спам.

  • Вы узнаете:

    • как использоватьPerspective APIдля анализа текста;

    • как применять машинное обучение в приложениях для чата;

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

  • Вы создадите: блокнот Jupyter, который отслеживает подачу и траекторию теннисного мяча (может также пригодиться в гольфе и баскетболе), а также анализирует данные, чтобы дать полезные советы. Для этого перейдите вQwiklabs.

  • Вы узнаете:

    • как выполнять сложное машинное обучение с помощью небольших наборов данных;

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

    • как использовать Video Intelligence API;

    • как работать c AutoML Vision.

Умный игровой мир с технологией обработки естественного языка

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

  • Вы создадите:

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

  • Вы узнаете:

    • как использовать одну из самых полезных методик обработки естественного языка встраивание предложений;

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

    • как разделять текст на кластеры;

    • как добавлять простые чат-боты;

    • как выполнять эти действия в Google Таблице.

Преобразование PDF-документа в аудиокнигу

  • Вы создадите: код, который преобразует PDF-файлы в аудиокниги формата MP3.

  • Вы узнаете:

    • как извлекать текст из PDF-файлов при помощи Vision API;

    • как озвучивать текст при помощи Text-to-Speech API;

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

Перевод и озвучивание видео с помощью машинного обучения

  • Вы создадите: код, который автоматически преобразовывает речь из видео в текст, а затем переводит и озвучивает его.

  • Вы узнаете:

    • как совмещать технологии распознавания, перевода и синтеза речи;

    • как улучшать качество перевода и преобразования речи в текст;

    • как работать с видео и аудио на языке Python.

Создание рецептов выпечки с помощью ИИ

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

  • Вы узнаете:

    • как создавать модели машинного обучения в AutoML Tables с помощью табличных данных без написания кода;

    • как определять причину решений модели с помощью функций.

Создание модели машинного обучения в браузере без написания кода

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

  • Вы узнаете:

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

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

Создание образов с помощью ИИ

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

  • Вы узнаете:

    • как использовать Product Search и Vision API;

    • как проектировать приложения на основе машинного обучения с помощью React и Firebase.

Подробнее..

Перевод Как мы случайно сожгли 72000 за два часа в Google Cloud Platform и чуть не обанкротились

12.12.2020 02:23:46 | Автор: admin


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

В марте 2020 года, когда COVID поразил весь мир, наш стартап Milkie Way тоже сильно пострадал и почти закрылся. Мы сожгли 72 000 долларов во время изучения и внутреннего тестирования Cloud Run с Firebase в течение нескольких часов.

Я начал разработку сервиса Announce в ноябре 2019 года. Главная цель состояла в выпуске минимально функциональной первой версии продукта, поэтому код работал на простом стеке. Мы использовали JS, Python и развернули наш продукт на Google App Engine.

С очень маленькой командой мы сосредоточились на написании кода, разработке пользовательского интерфейса и подготовке продукта. Я практически не тратил времени на управление облаком потратил ровно столько, чтобы поднять систему и обеспечить базовый процесс разработки (CI/CD).


Десктопный Announce

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

Разве не здорово сгенерировать на платформе немного данных, когда пользователи ещё не закачали свою информацию? Эта мысль привела к появлению другого проекта Announce-AI для генерации контента. Богатые данные это различные события, такие как оповещения о землетрясениях и, возможно, релевантные местные новости.

Некоторые технические детали


Для начала разработки Announce-AI мы использовали Cloud Functions. Поскольку наш бот для скрапинга был ещё на начальной стадии, мы решили взять эти легковесные функции. Но при масштабировании возникли проблемы, потому что у облачных функций тайм-аут около 9 минут.

И вдруг мы узнали о системе Cloud Run, у которой тогда был большой лимит бесплатного использования! Не разобравшись полностью, я попросил команду развернуть тестовую функцию Announce-AI в Cloud Run и оценить её производительность. Цель состояла в том, чтобы поиграться с Cloud Run для накопления опыта.


Google Cloud Run

Поскольку у нас очень маленький сайт, то для простоты мы использовали БД Firebase, так как у Cloud Run нет никакого хранилища, а деплой SQL Server или другую БД слишком чрезмерен для теста.

Я создал новый проект GCP ANC-AI Dev, настроил бюджет облачного биллинга на 7 долларов, сохранил проект Firebase по бесплатному плану (Spark). Худший вариант, который мы представляли, это превышение ежедневного лимита Firebase.

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

Кошмар начинается


В день тестирования всё прошло нормально, и мы вернулись к разработке Announce. На следующий день после работы ближе к вечеру я пошёл слегка вздремнуть. Проснувшись, я увидел несколько писем из Google Cloud, все с интервалом в несколько минут.

Первое письмо: автоматический апгрейд нашего проекта Firebase


Второе письмо: бюджет превышен


К счастью, на моей карте был установлен лимит в $100. Из-за этого платежи не прошли, а Google приостановил обслуживание наших аккаунтов.

Третье письмо: карта отклонена


Я вскочил с кровати, вошёл в биллинг Google Cloud и увидел счёт примерно на $5000. В панике начал щёлкать по клавишам, не понимая, что происходит. В фоновом режиме начал размышлять, как такое могло произойти и как оплатить счёт на $5000, в случае чего.

Проблема была в том, что с каждой минутой счёт продолжал расти.

Через пять минут он показывал $15000 долларов, через 20 минут $25000. Я не понимал, когда цифры перестанут увеличиваться. Может, они будут расти до бесконечности?

Через два часа цифра остановилась на отметке чуть меньше $72000.

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

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

Кошмар продолжается


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


Все наши облачные проекты приостановлены, разработка остановлена

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

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

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

Для нас как начинающего стартапа не было никакой возможности возместить $72000.

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

Некоторая передышка: лазейки GCP


В субботу после рассылки электронных писем юристам я начал дальше читать и просматривать каждую страницу документации GCP. Мы действительно совершали ошибки, но не было никакого смысла в том, что Google позволил нам резко потратить $72000, если раньше мы вообще не делали никаких платежей!


GCP и Firebase

1. Автоматический апгрейд аккаунта Firebase на платный аккаунт


Мы такого не ожидали, и об этом нигде не предупреждалось при регистрации на Firebase. Наш биллинг GCP был подключён к исполнению Cloud Run, но Firebase шла под бесплатным планом (Spark). GCP просто ни с того ни с сего провела апгрейд на платный тариф и взяла с нас необходимую сумму.

Оказывается, этот процесс у них называется глубокая интеграция Firebase и GCP.

2. Биллинговых лимитов не существует. Бюджеты запаздывают минимум на сутки


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

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

3. Google должен был взять 100 долларов, а не 72 тысячи!


Поскольку с нашего аккаунта до сих пор не проходило никаких платежей, GCP должен был сначала взять плату в размере 100 долларов в соответствии с платёжной информацией, а при неуплате прекратить услуги. Но этого не произошло. Я понял причину позже, но это тоже не по вине пользователя!

Первый счёт для нас составил около $5000. Следующий на $72тыс.


Порог выставления счетов для нашего аккаунта составляет $100

4. Не полагайтесь на панель управления Firebase!


Не только биллинг, но и обновление панели управления Firebase заняло более 24-х часов.

Согласно документации Firebase Console, цифры в панели управления могут незначительно отличаться от отчётов биллинга.

В нашем случае они отличались на 86585365,85%, или 86 миллионов процентных пунктов. Даже когда пришёл счёт, панель управления Firebase Console ещё показывала 42000 операций чтения и записи в месяц (ниже дневного лимита).

Новый день, новый вызов


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

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


Последний день в Google

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

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

Стойкие Гималаи нам говорят


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

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


Стихотворение Стойкие Гималаи нам говорят

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

Что мы на самом деле сделали?


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

Один инстанс будет постоянно скрапить URL-адреса со страницы. Но через 9 минут наступит тайм-аут.

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


Концепт Announce-AI на Cloud Run

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


Скрапер на Cloud Run

Если присмотреться, в процессе не хватает нескольких важных деталей.

  1. Происходит непрерывная экспоненциальная рекурсия: инстансы не знают, когда остановить работу, потому что оператора break не предусмотрено.
  2. У POST-запросов могут быть одни и те же URL. Если есть обратная ссылка на предыдущую страницу, то сервис Cloud Run застрянет в бесконечной рекурсии, но хуже всего то, что эта рекурсия умножается экспоненциально (максимальное количество инстансов было установлено на 1000!)

Как вы можете себе представить, это привело к ситуации, в которой 1000 инстансов делают запросы и записи в Firebase DB каждые несколько миллисекунд. Мы увидели, что по операциям чтения Firebase в какой-то момент проходило около 1 миллиарда запросов в минуту!


Сводка транзакций на конец месяца для GCP

116 миллиардов операций чтения и 33 миллиона записей


Экспериментальная версия нашего приложения на Cloud Run сделала 116 миллиардов операций чтения и 33 миллиона записей в Firestore. Ох!

Стоимость операций чтения на Firebase:

$ (0.06 / 100,000) * 116,000,000,000 = $ 69,600

16 000 часов работы Cloud Run


После тестирования из остановки логов мы сделали вывод, что запрос умер, но на самом деле он ушёл в фоновый процесс. Поскольку мы не удалили сервисы (мы первый раз использовали Cloud Run, и тогда действительно не понимали этого), то несколько сервисов продолжали медленно работать.

За 24 часа все эти службы на 1000 инстансах отработали в общей сложности 16022 часа.

Все наши ошибки


Деплой ошибочного алгоритма в облаке


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

Деплой Cloud Run с параметрами по умолчанию


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

Если бы мы выбрали max-instances=2, затраты были бы в 500 раз меньше.

Если бы установили concurrency=1, то даже не заметили бы счёт.

Использование Firebase без полного понимания


Кое-что понимаешь только на опыте. Firebase это не язык, который можно выучить, это контейнерная платформа. Её правила определены конкретной компанией Google.



Кроме того, при написании кода на Node.js нужно подумать о фоновых процессах. Если код уходит в фоновые процессы, разработчику нелегко узнать, что служба работает. Как мы позже узнали, это ещё и стало причиной большинства таймаутов наших Cloud Functions.

Быстрые ошибки и быстрые исправления плохая идея в облаке


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

Если посчитать количество страниц в документации GCP, то можно издать несколько толстенных томов. Чтобы всё понять, в том числе тарификацию и использование функций, требуется много времени и глубокое понимание, как работают облачные сервисы. Неудивительно, что для этого нанимают отдельных сотрудников на полный рабочий день!

Firebase и Cloud Run действительно мощны


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

То же самое относится и к Cloud Run! Если установить количество параллельных процессов 60, max_containers== 1000, то при запросах по 400мс Cloud Run может обрабатывать 9 миллионов запросов в минуту!

60 * 1000 * 2.5 * 60 = 9 000 000 запросов в минуту

Для сравнения, поиск Google обрабатывает 3,8 миллиона запросов в минуту.

Используйте мониторинг


Хотя Google Cloud Monitoring не остановит биллинг, он отправляет своевременные оповещения (задержка 3-4 минуты). Поначалу не так просто освоить терминологию Google Cloud, но если вы потратите время, то панель мониторинга, оповещения и метрики немного облегчат вашу жизнь.

Эти метрики доступны только в течение 90 дней, у нас они уже не сохранились.

Мы выжили



Фух, пронесло

Изучив наш длинный отчёт об инциденте, описывающий ситуацию с нашей стороны, после различных консультаций, бесед и внутренних обсуждений, Google простила нам счёт!

Спасибо тебе, Google!


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

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

(Примечание: это моё личное мнение как индивидуального разработчика. Наша компания никоим образом не спонсируется и не связана с Google).

Что дальше?


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

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

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

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

Мы также запустились на всех платформах, а не только в интернете.

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

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru