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

Google cloud platform

WebRTC CDN на Google Cloud Platform с балансировкой и автоматическим масштабированием

18.06.2021 10:22:12 | Автор: admin

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

Кратко напомним основные тезисы:

  • В CDN низкая задержка в трансляциях обеспечивается использованием технологии WebRTC для передачи видеопотока от Origin сервера к Edge серверам, которые, в свою очередь, позволяют подключить большое количество зрителей.

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

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

Инфраструктура Google Cloud Platform, как и в случае с AWS, поддерживает автоматическое масштабирование и балансировку распределения нагрузки, поэтому не приходится беспокоиться о лишних расходах на оплату виртуальных серверов вы платите только за то, что используете.

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

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

Разворачиваем WebRTC CDN с балансировщиком и автоматическим масштабированием на Google Cloud Platform

Конфигурация CDN будет следующей:

  • один Origin сервер;

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

Для развертывания потребуется настроить следующие компоненты в консоли Google Cloud Platform:

  • глобальный файрволл на уровне проекта Google Cloud;

  • виртуальные машины WCS CDN Origin и WCS CDN Edge;

  • шаблон развертывания на основе образа диска WCS CDN Edge;

  • группу масштабирования;

  • балансировщик нагрузки.

Итак, приступим.

Настраиваем глобальный файрволл на уровне проекта Google Cloud для прохождения WebRTC трафика

Настройка межсетевого экрана действует на все запущенные в вашем проекте сервера, поэтому начнем развертывание с нее.

В основном меню консоли Google Cloud откройте раздел "VPC networks" и выберите пункт "Firewall":

На открывшейся странице нажмите кнопку "Create Firewall Rule" :

В открывшемся мастере задайте имя правила:

Ниже на странице разрешите входящий трафик с любых компьютеров:

Еще ниже в секции "Protocols and ports" укажите порты для работы WCS и нажмите кнопку "Create":

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

Разворачиваем WCS сервер с ролью Origin для WebRTC CDN

В консоли Google Cloud откройте раздел "Compute Engine" и выберите из меню в левой части пункт "VM instances". Нажмите кнопку "Create" в диалоге создания нового экземпляра сервера:

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

Ниже на странице в секции "Boot disk" нажмите кнопку "Change" и выберите образ "CentOS 7":

Разверните секцию "Management, security, disks, networking, sole tenancy":

На вкладке "Security" добавьте публичный ключ для доступа к серверу по SSH:

На вкладке "Networking" в секции "Network interfaces" настройте внешний и внутренний IP адреса для сервера. Для работы в составе CDN серверу нужно назначить статический внутренний IP адрес:

После всех настроек нажмите кнопку "Create" для создания нового экземпляра WCS сервера с ролью CDN Origin:

Спустя пару минут сервер будет создан и запущен. Подключаемся к нему по ssh и устанавливаем WCS. Все действия - установка, изменение настроек, запуск или перезапуск WCS - должны выполняться с root правами, либо через sudo.

1.Установите Wget, Midnight Commander и дополнительные инструменты и библиотеки

sudo yum -y install wget mc tcpdump iperf3 fontconfig

2.Установите JDK. Для работы в условиях больших нагрузок рекомендуется JDK 12 или 14. Удобнее провести установку при помощи скрипта на bash. Текст скрипта:

#!/bin/bashsudo rm -rf jdk*curl -s https://download.java.net/java/GA/jdk12.0.2/e482c34c86bd4bf8b56c0b35558996b9/10/GPL/openjdk-12.0.2_linux-x64_bin.tar.gz | tar -zx[ ! -d jdk-12.0.2/bin ] && exit 1sudo mkdir -p /usr/java[ -d /usr/java/jdk-12.0.2 ] && sudo rm -rf /usr/java/jdk-12.0.2sudo mv -f jdk-12.0.2 /usr/java[ ! -d /usr/java/jdk-12.0.2/bin ] && exit 1sudo rm -f /usr/java/defaultsudo ln -sf /usr/java/jdk-12.0.2 /usr/java/defaultsudo update-alternatives --install "/usr/bin/java" "java" "/usr/java/jdk-12.0.2/bin/java" 1sudo update-alternatives --install "/usr/bin/jstack" "jstack" "/usr/java/jdk-12.0.2/bin/jstack" 1sudo update-alternatives --install "/usr/bin/jcmd" "jcmd" "/usr/java/jdk-12.0.2/bin/jcmd" 1sudo update-alternatives --install "/usr/bin/jmap" "jmap" "/usr/java/jdk-12.0.2/bin/jmap" 1sudo update-alternatives --set "java" "/usr/java/jdk-12.0.2/bin/java"sudo update-alternatives --set "jstack" "/usr/java/jdk-12.0.2/bin/jstack"sudo update-alternatives --set "jcmd" "/usr/java/jdk-12.0.2/bin/jcmd"sudo update-alternatives --set "jmap" "/usr/java/jdk-12.0.2/bin/jmap"

3.Загрузите архив для установки самой свежей стабильной версии WebCallServer:

sudo wget https://flashphoner.com/download-wcs5.2-server.tar.gz

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

sudo tar -xvzf FlashphonerWebCallServer-5.2.714.tar.gz && cd FlashphonerWebCallServer-5.2.714 && ./install.sh

5.Для активации лицензии запустите скрипт "./activation.sh" из каталога установки WCS. Этот шаг, при желании, можно пропустить и активировать лицензию позже через веб-интерфейс:

sudo cd /usr/local/FlashphonerWebCallServer/bin && sudo ./activation.sh

6.Отключите firewalld и SELinux. Сетевой экран мы ранее настроили на уровне Google Cloud Platform, поэтому нет необходимости закрывать порты в операционной системе:

sudo systemctl stop firewalld && systemctl disable firewalld && setenforce 0

7.Откройте любым удобным редактором файл flashphoner.properties, который можно найти по пути:

/usr/local/FlashphonerWebCallServer/conf/flashphoner.properties

и внесите в него настройки для запуска CDN. В параметре "cdn_ip" укажите внутренний IP адрес вашей виртуальной машины с ролью CDN Origin:

cdn_enabled=truecdn_ip=10.128.0.3 # Local IP address CDN Origincdn_nodes_resolve_ip=falsecdn_role=origin

На скриншоте ниже примерный вид файла flashphoner.properties для WCS с ролью CDN Origin:

После изменения настроек запустите (или перезапустите) Web Call Server:

systemctl start webcallserver

На этом запуск и настройка Origin закончены. Перейдем к настройке балансировщика нагрузки и автоматического масштабирования.

Запускаем балансировщик нагрузки и автоматическое масштабирование в Google Cloud для WebRTC CDN

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

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

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

  • группа масштабирования;

  • балансировщик нагрузки;

  • настройки контроля активности сервера.

Создаем образ диска WCS сервера с ролью Edge для WebRTC CDN

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

Повторите инструкцию по подготовке сервера Origin до пункта о внесении настроек в файл flashphoner.properties. Для роли Edge внесите в этот файл следующие настройки:

cdn_enabled=truecdn_ip=10.128.0.4cdn_nodes_resolve_ip=falsecdn_point_of_entry=10.128.0.3cdn_role=edgehttp_enable_root_redirect=false

После внесения и сохранения настроек, остановите в консоли Google Cloud виртуальную машину WCS CDN Edge, выберите из меню в левой части пункт "Images" и нажмите кнопку "Create Image":

В открывшемся мастере укажите имя нового образа, выберите в качестве источника диск виртуальной машины WCS CDN Edge и нажмите кнопку "Create":

После того, как образ диска создан переходим к созданию шаблона развертывания Edge сервера на основе созданного образа.

Создаем шаблон развертывания Edge сервера

Выберите из меню в левой части окна консоли Google Cloud пункт "Instance templates" и нажмите кнопку "Create Instance template":

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

Ниже на странице в секции "Boot disk" нажмите кнопку "Change". в Открывшемся окне перейдите на вкладку "Custom Images" и выберите образ диска WCS CDN Edge, который мы создали ранее. Нажмите кнопку "Select":

Разверните секцию "Management, security, disks, networking, sole tenancy". На вкладке "Security" добавьте публичный ключ для доступа к серверу по SSH и нажмите кнопку "Create":

Шаблон развертывания для WCS с ролью CDN Edge создан. Теперь перейдем к созданию группы масштабирования.

Создаем группы масштабирования для Edge серверов

Из меню в левой части окна консоли Google Cloud выберите пункт "Instance groups" и нажмите кнопку "Create Instance group":

На открывшейся странице выберите регион и зону расположения группы и укажите шаблон развертывания WCS Edge, который мы создали ранее:

В секции "Autoscaling" на этой же странице настройте триггер запуска дополнительных серверов Edge. В качестве триггера будем использовать загрузку процессора более 80% . В поле "Maximum number of instances" укажите максимальное количество виртуальных машин, которые будут запущены при срабатывании триггера:

Затем включите проверку состояния виртуальной машины в секции "Autohealing". Для того, что бы создать настройку проверки сервера выберите из списка в поле "Health check" пункт "Сreate a health check":

В открывшемся мастере создания проверки состояния сервера укажите имя проверки, протокол TCP, порт 8081 и запрос /health-check. Настройте критерии проверки и нажмите кнопку "Save and continue":

Разверните секцию "Advanced creation options" и активируйте чекбокс "Do not retry machine creation". После чего нажмите "Create":

Будет создана группа масштабирования и запущен один WCS с ролью CDN Edge. Последним этапом настройки нашей CDN с балансировщиком нагрузки и автоматическим масштабированием будет настройка балансировщика.

Создаем балансировщик нагрузки

Сначала зарезервируем для балансировщика внешний IP адрес. В главном меню Google Cloud Platform в секции "VPC network" выберите пункт "External IP addresses" и нажмите кнопку "Reserve static address":

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

Затем переходим к настройке балансировщика.

Выбираем пункт "Load balancing" в разделе "Network services" секции "Networking" основного меню Google Cloud Platform:

Нажимаем кнопку "Create load balancer":

Затем выберите тип балансировщика "TCP Load Balancing" и нажмите кнопку "Start configuration":

На открывшейся странице укажите внешний балансировщик "From Internet to my VMs" и регион размещения серверов балансировщика. После выбора настроек нажмите кнопку "Continue":

На следующей странице задайте имя балансировщика, Затем перейдите в раздел настроек "Backend configuration" и укажите в каком регионе будут созданы сервера входящие в состав балансировщика. На вкладке "Select existing instance groups" выберите группу масштабирования Edge серверов, которую мы создали ранее. Затем в поле "Health check"выберите из выпадающего списка пункт "Сreate a health check":

На открывшейся странице укажите параметры для проверки состояния работы балансировщика порт 8081 и запрос /, после чего нажмите кнопку "Save and continue":

Затем перейдите к настройкам раздела "Frontend configuration". В этом разделе нужно создать привязку портов к внешнему IP адресу. Укажите внешний IP адрес для балансировщика, который мы зарезервировали выше и создайте конфигурации для TCP портов 8081, 8080, 8443, 8444 для HTTP(S) и WS(S). После создания необходимых портов нажмите кнопку "Create":

Балансировщик будет запущен. На этом развертывание CDN с балансировщиком и масштабированием можно считать завершенным. Переходим к тестированию.

Тестирование WebRTC CDN с балансировщиком и масштабированием на базе Google Cloud Platform

Методика тестирования

Для проведения нагрузочного тестирования, при создании группы масштабирования мы выставили порог загрузки процессора для срабатывания триггера на 20%. Тестирование будем проводить с использованием браузера Google Chrome и виртуальной вебкамеры для организации трансляции видеопотока. Что бы сымитировать повышение нагрузки на процессор запустим воспроизведение потока с транскодированием с помощью примера "Media Devices".

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

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

В браузере Google Chrome открываем web интерфейс WCS с ролью CDN Origin Авторизуемся, открываем пример "Two-way Streaming", устанавливаем соединение с сервером по WebSocket и публикуем видеопоток.

Затем, запускаем web интерфейс WCS CDN Edge сервера по IP адресу, который был зарезервирован при создании балансировщика.

Авторизуемся, открываем пример "Media Devices" и устанавливаем соединение с балансировщиком по WebSocket. В правом столбце настроек снимаем чек бокс "default" для параметра "Size" и задаем значения для транскодирования видеопотока. Например, если поток на Origin сервере опубликован с размерами 320х240 задаем значение 640х480. Повторите действия в нескольких вкладках браузера, для имитации большого количества зрителей.

В консоли Google Cloud видим, что были запущены две дополнительные виртуальные машины:

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

http://<WCS instance IP address>:8081/?action=stat

Откройте страницу статистики для каждой виртуальной машины, запущенной балансировщиком. Значение "connection_websocket" показывает количество активных WebSocket сессий на каждой виртуальной машине.

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

Хорошего стриминга!

Ссылки

Наш демо сервер

CDN для стриминга WebRTC с низкой задержкой - CDN на базе WCS

Документация по быстрому развертыванию и тестированию WCS сервера

Документация по развертыванию WCS в Google Cloud Platform

Документация по настройке балансировки нагрузки с масштабированием в GCP

Подробнее..

Перевод Calico Enterprise обзор

09.02.2021 02:22:17 | Автор: admin

Translation of this article written by John Armstrong on Jan 20, 2021

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

Архитектура корпоративных решений Calico:

Calico Enterprise является родным для Kube

Cначала следует вспомнить несколько важных вещей. Calico Enterprise - это Kubernetes-native, Kube-native решение, в котором все, что делается, является расширением примитивов Kubernetes. Вся мощь Kubernetes используется путем интеграции с Kubernetes через API плюс путем создания собственного агрегированного API сервера. Операторная модель, взятая целиком из Kubernetes, используется для доступа и управления ресурсами, для выполнения таких функций, как, например, RBAC. Calico Enterprise, будучи родным для Kubernetes, по мере развития Kubernetes автоматически поддерживает взаимно совместимость.

Модель безопасности, работающая всюду

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

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

Подключаемый, ориентированный на будущее Data Plane - Linux, Windows и eBPF

Calico Enterprise с самого начала разрабатывался с полностью подключаемым data planes, поэтому клиенты могут выбрать между разными data planes. Сетевой уровень Kubernetes выделяет три уровня data planes, и все они представлены в Calico Enterprise. Большинство пользователей используют стандартный data plane ядра Linux, потому что они еще не используют последние версии Linux, необходимые для поддержки eBPF. Некоторое количество рабочих приложений выполняется в Windows, и для этих клиентов предлагается то же единое решение, которое работает в Linux. Для пользователей, которые хотят расширить пределы производительности с использованием последних ядер Linux, Calico Enterprise предлагает eBPF data plane. В ближайшие несколько лет неизбежно появятся более быстрые data plane технологии, и Calico Enterprise планирует добавить их поддержку. Это еще один способ, которым Tigera защищает будущие инвестиции клиентов Calico Enterprise и демонстрирует приверженность предоставлять наиболее продвинутые, масштабируемые и надежные решения для пользователей Kubernetes.

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

Управление трафиком North-South

Calico Enterprise обеспечивает контроль безопасности как North-South, так и East-West трафика. В среде Kubernetes North-South принято обозначать трафик, который следует внутрь сети и из сети, а East-West - трафик, следующий внутри сети. Именно на стыке North-South между кластером Kubernetes и внешней средой мы сталкиваемся с наибольшими проблемами безопасности. Используя средства Calico Enterprise для управления политикой (policy) DNS и средства контроля входящего / исходящего доступа (ingress/egress access controls), пользователи контролируют North-South трафик. Корпоративный универсальный межсетевой экран Calico и интеграция с SIEM (Calico Enterprise universal firewall and SIEM integration) - это два метода, которые поддерживают интеграцию существующих средств управления безопасностью предприятия со средой Kubernetes.

Управление трафиком East-West

Контроль трафика East-West ограничивает область разрушения в случае нарушений безопасности, которые приводят к APT (advanced persistent threat). Есть несколько способов, с помощью которых Calico Enterprise помогает настроить эти средства контроля. Подход Calico Enterprise с глубокой защитой (defense-in-depth) обеспечивает защиту на трех уровнях: хост, контейнер / виртуальная машина и приложение. Используя единую структуру политики безопасности, вы настраиваете все эти уровни с помощью декларативной модели. Можно установить очень мелкие элементы управления доступом и фильтровать трафик на уровне протокола приложения, например, по протоколам http, https или MongoDB. Можно выполнять микросегментацию как для контейнерных рабочих нагрузок, так и для рабочих нагрузок виртуальных машин.

Безопасность и постоянное соответствие нормативам (Continuous Compliance)

По мере расширения зоны использования Kubernetes наблюдается потребность в еще более глубоком подходе к защите конфиденциальных данных, подпадающих под действие нормативных требований. Для обеспечения безопасности и постоянного соответствия нормативам (Continuous Compliance) Calico Enterprise обеспечивает шифрование данных в пути (data-in-transit encryption) с лучшей в отрасли производительностью, а также непрерывную отчетность о соответствии политик безопасности и средств управления. В Calico Enterprise есть богатый набор функций обнаружения вторжений (Intrusion Detection), который включает обнаружение различных угроз, настраиваемые оповещения об известных атаках, обнаружение аномалий поведения и приманки (honeypod). Calico Enterprise использует автоматизированный подход к обнаружению вредоносных программ и реагированию на них. Например, Tigera создала алгоритм машинного обучения в Calico Enterprise, который специально нацелен на обнаружение DGA (Domain Generation Algorithm), облегчая группам безопасности обнаружение DGA активности. Calico Enterprise может запускать автоматическое исправление, удаляя мошенническую микросервис из сети за миллисекунды, и генерируя затем рекомендации по политике предотвращения возможных атак.

Мониторинг и устранение неисправностей

Время простоя обходится дорого, а мониторинг распределенных приложений очень сложен. Calico Enterprise динамически генерирует диаграмму сервисов (Service Graph), которая позволяет легко понять, как микросервисы ведут себя и взаимодействуют друг с другом во время работы, упрощая тем самым процесс отладки и мониторинга. Динамическая диаграмма сервисов предоставляет очень богатый набор информации, включая информацию о том, в каких пространствах имен взаимодействуют рабочие нагрузки, подробную DNS информацию , подробные журналы событий (flow logs) для каждого отдельного потока в вашем кластере и то, как оцениваются сетевые политики. Горячие точки производительности автоматически идентифицируются и выделяются, а предупреждения (alerts) выдаются в контексте диаграммы сервисов. Пользуясь этой диаграммой, а также с помощью функции автоматического захвата пакетов, инженеры и программисты могут быстро находить источник проблемы на уровне приложения, процесса и сокета.

Единое управление и автоматизация

Унифицированные элементы управления обеспечивают безопасность и наблюдаемость в средах с несколькими кластерами, несколькими облаками и гибридными облачными средами, а также предоставляют единую панель для обеспечения согласованного применения элементов управления безопасностью. Они также поддерживают непрерывную интеграцию CI / CD для опытных пользователей. Calico Enterprise ввела в действие концепцию уровней политик, которые поддерживают делегирование полномочий по организационной структуре и областям ответственности для различных групп с разными потребностями (безопасность, сеть, платформа, DevOps, SRE, разработка). Уровни политик определяют порядок, в котором оцениваются политики сетевой безопасности, и используются для реализации средств управления безопасностью, которые не могут быть изменены или отменены неавторизованными пользователями. Например, средства контроля доступа в масштабе предприятия, созданные группой безопасности, имеют первостепенное значение и находятся на самом высоком уровне. Уровни политик могут объединяться в несколько кластеров с использованием возможностей централизованного управления Calico Enterprise, что позволяет использовать единое управление безопасностью, применяющиеся ко всем кластерам.

Подробнее..

Перевод Google признала сложность Kubernetes, поэтому разработала режим Автопилот

26.02.2021 18:20:16 | Автор: admin

Новый режим GKE более дорогой и менее гибкий, но зато проще и безопаснее



Автопилот в GKE управляет подами за вас

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

Чтобы упростить развёртывание и управление кластерами, компания представила всем клиентам GKE доступ к сервису Автопилот, который Google уже давно использует в собственных кластерах Borg. Это автоматическая конфигурация ресурсов на основе машинного обучения.

Несмотря на 6 лет прогресса, Kubernetes по-прежнему невероятно сложен, сказал Дрю Брэдсток (Drew Bradstock), руководитель продукта Google Kubernetes Engine (GKE), в интервью The Register. В последние годы мы видели, что многие компании принимают Kubernetes, но затем сталкиваются с трудностями.

GKE это платформа Kubernetes, которая работает в основном на Google Cloud Platform (GCP). Она также доступна и на других облаках или локально как часть Anthos.

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


Использование Автопилота в собственной инфраструктуре Google, источник

В Kubernetes есть понятия кластеров (набор физических или виртуальных серверов), узлов (отдельные серверы), подов (блок управления, представляющий один или несколько контейнеров на узле) и самих контейнеров. GKE полностью управляется на уровне кластера. Автопилот распространяет это на узлы и поды.

Проще всего понять особенности и ограничения Автопилота из описания системы. Обратите внимание на предварительно настроенные параметры (pre-configured), которые нельзя изменить.

Сравнение режимов Autopilot и Standard

По сути, это ещё один способ резервирования и управления ресурсами GKE, который жертвует гибкостью ради удобства. Поскольку Google управляет большей частью конфигурации, то для подов Автопилота с распределением по многим зонам она гарантирует более высокий аптайм 99,9% (см. SLA).

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

Другое ограничение Автопилота предустановленная операционная система Linux с Containerd, оптимизированная для контейнеров. Нет возможности использовать Linux с Docker или Windows Server. Максимальное количество подов на узел 32, а не 110, как на стандартном GKE.

SSH-доступ к узлам отсутствует, узлы Автопилота заблокированы. Поддержка GPU и TPU (Tensor Processing Unit) недоступна, хотя и запланирована на будущее. Отказ от SSH был сложным решением, говорит Брэдсток. Конечно, это ограничивает возможности управления. Но Брэдсток сказал, что такое решение было принято по результатам исследований, показавших большой уровень критических ошибок в конфигурировании кластеров.

Деньги


Модель ценообразования здесь тоже отличается. Плату берут не за вычислительные инстансы (виртуальные машины), а за реальное использование CPU, памяти и хранилища всеми подами. Плюс $0,10 в час за каждый кластер на Автопилоте, как в стандартном GKE.

Очевидный вопрос: что будет дороже, стандартный кластер или Автопилот. Ответить непросто. Поскольку это в каком-то смысле премиальный сервис, Автопилот обойдётся дороже, чем тщательно оптимизированное стандартное развертывание GKE. Существует премия по сравнению с обычным GKE, сказал Брэдсток, потому что мы обеспечиваем не только функциональность, но полную поддержку SRE (Site Reliability Engineering) и гарантии SLA.

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


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


Снижение ошибок памяти (OOM) и доли неиспользуемой памяти для 500 задач после включения Автопилота в инфраструктуре Google, источник

Почему просто не использовать Cloud Run, который запускает рабочие нагрузки контейнеров без какой-либо конфигурации кластеров, узлов и подов, даже на GKE? Cloud Run отличная среда для разработчиков, одно приложение может раскрутиться с нуля до 1000 инстансов и обратно опуститься до нуля, для того и созданы облака, объясняет Брэдсток. Автопилот облегчает жизнь людям, которые хотят использовать именно Kubernetes, хотят всё видеть и держать под контролем, хотят использовать сторонние скрипты, хотят построить свою собственную платформу.

Определённой проблемой является совместимость с существующими надстройками сторонними инструментами для Kubernetes. Некоторые из них пока не совместимы с Автопилотом, но другие уже работают, такие как мониторинг Datadog. Также поддерживается DaemonSets эту функцию для запуска демонов на всех узлах используют многие инструменты.

Конфигурация хранилища, вычислений и сети вынудила отказаться от некоторого уровня гибкости и некоторых интеграций: Но мы определённо хотим, чтобы на нём [Автопилоте] работала сторонняя экосистема, говорит Брэдсток.

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

У инженерной службы Google репутация гораздо лучше, чем службы поддержки клиентов. Разработчик Кевин Лин (Kevin Lin) недавно описал, как выглядит схема зачисления бонусов для стартапов в AWS и Google.

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

Это ещё одно доказательство, что хорошие инженеры не единственный важный фактор при выборе облака.
Подробнее..

Как готовить Helm правильно несколько полезных рецептов

16.05.2021 18:12:28 | Автор: admin
(источник фото -https://unsplash.com/photos/XWNbUhUINB8(источник фото -https://unsplash.com/photos/XWNbUhUINB8

Когда-то давно, когда ножей не знали,х@#$ говядину рубили... ой нет, это другая сказка, простите. Вот, правильная эта. Когда-то давно, деды сказывают, для обновления сервиса в среде инженерам приходилось самим писать скрипты для деплоймента, а некоторые даже запускали их сами из консоли, руками. Были даже причудливые инструменты вроде ClusterSSH, чтобы делать сеанс одновременной игры на всех нодах кластера.

Но тотальная контейнеризация, ввод в обиход универсального понятия "workload", и оркестризация привели к появлению Kubernetes, на котором сейчас работает примерно 3/4 мировых production сред.

Kubernetes ввёл в обиход концепцию управления конфигурацией при помощи дескрипторов - kubectl apply что в переводе означает "я не хочу объяснять что делать, я говорю как хочу чтобы в среде всё стало - а ты делай что должен, блестящий металлический зад!".

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

Поэтому Helm стал де-факто стандартом в автоматизированных деплойментах Kubernetes, добавляя новые интересные возможности, которые идут гораздо дальше простой альтернативы выполнению kubectl apply -f ...

Ниже мы расссмотрим несколько примеров того, что можно получить от Helm по сравнению с простой командой kubectl apply, с чем разработчик сталкивается в реальной жизни. Мы покажем, как организовать доставку новых версий сервисов в разные среды, описывая параметры так, что не требуется копипастных повторений, которые ведут к ошибкам. Мы также увидим несколько других полезных приёмов - для удобного управления секретами и организации надёжных пайплайнов.

Итак, напомним, что Helm в принципе может делать три основные вещи:

  • сделать дескрипторы по шаблонам

  • накатить дескрипторы на кластер

  • использовать репозитории charts - взять шаблоны дескрипторов из центральной среды

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

Шаблонизатор Helm работает примерно так:

Другими словами, Helm берёт исходники:

  • файлы, текстовые и бинарные

  • шаблоны .yaml

  • значения из одного или нескольких .yaml файлов, и, возможно, командной строки

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

При этом файлы вставляются в Secrets и ConfigMaps, а значения занимают свои места в шаблонах.

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

Рассмотрим некоторые полезные техники Helm для решения типичных задач, с которыми девопс инженер сталкивается за пределами простого, понятного, нежно-розового мира hello world:

  • управление конфигурацией множества сред

  • использование секретов

  • повышение стабильности пайплайнов

Конфигурация множества сред

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

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

Production-среды имеют общие моменты, характерные для production, например реальный секретный ключ для платёжной системы. Но, тем не менее, могут различаться в других аспектах: например по региону, среда для "канареечных" релизов для тестов на малой группе, или по регионам. Или же может быть несколько production сред для каждого клиента или их группы, если ваш сервис больше похож на SaaS.

12 заповедей

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

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

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

Код с конфигурацией - как мясное с молочным? Код с конфигурацией - как мясное с молочным?

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

Каждый новый билд порождает неизменяемые (immutable) контейнер(ы) с кодом, и Helm chart, который можно применить для любой среды - от локального docker-desktop до production кластера в AWS.

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

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

Следовательно:

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

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

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

    • каждое значение конфигурации и/или файл должны храниться в одном и только в одном месте,

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

    • добавление файла в конфигурацию должно требовать именно этого - добавление файла: никаких изменений в пицот других yaml-ов!

Мы будем хранить конфигурации всех наших сред в диаграмме Helm как часть chart.

Пример ниже, дополнительные каталоги выделены (+).

/env             // (+) значения для сред /<chart-name>    // chart    /files         // (+) конфигурационные файлы и их шаблоны     /templates     // шаблоны Helm   Chart.yaml     // заглавный файл chart  values.yaml    // значения по умолчанию

Файлы со значениями для сред

Давайте посмотрим подробнее на структуру ваших сред.

Допустим у вас есть два типа, TEST и PROD для тестовых и продакшен сред, соответственно. тип TEST делится на две разновидности -STABLE и -PR (пул реквест, нестабильная среда), а для типа PROD у вас разновидности это регионы, EU и US.

Получается примерно такая структура для /env (значения для сред) и /files (файлы конфигурации):

/env                  TEST.yaml            // общие значения для всех тестовых сред  TEST-PR.yaml         // только для PR/нестабильной  TEST-STABLE.yaml     // только для стабильной     PROD.yaml            // общие значения для всех продакшен сред  PROD-EU.yaml         // продакшен EU     PROD-US.yaml         // продакшен US /files                     /TEST                // общие файлы для всех тестовых сред  /TEST-PR             // ...  /TEST-STABLE         // ...    /PROD                // общие файоы для всех продакшен сред   /PROD-EU             // ...  /PROD-US             // ...  /shared              // файлы общие для всех средvalues.yaml             // значения общие для всех сред

Теперь посмотрим что внутри /files - текстовые и бинарные файлы конфигурации.

.../PROD    /binary    /text/PROD-EU    /binary    /text .../shared    /binary    /text    /secret-text

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

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

1. Мы предполагаем что секретные файлы только текстовые а не бинарные. Почему? Потому что так проще. Секретный двоичный файл (например .p12 сертификат) становится несекретным, если зашифровать его секретным ключом с достаточной (скажем 120+ бит) энтропией - и можно хранить его просто в гите, даже если он размеров в несколько (десятков) килобайт. С точки зрения безопасности - это просто рандомный набор битов. А вот ключ, отпирающий этот бинарник, мы будем хранить в строгом секрете - как и все другие-остальные пароли.

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

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

  • среда - разновидность (TEST-STABLE.yaml)

  • среда - тип (TEST.yaml)

  • общие значения (values.yaml)

Helm позволяет это сделать, указав файлы со значениями как последовательность опций --values:

helm upgrade --install <chart> path/to/<chart> --strict \     --values env/<env>.yaml --values env/<env>-<flavour>.yaml

В .yaml-файлах разновидности и типа среды содержатся атрибуты, например TEST-STABLE.yaml среди прочего содержит:

envFlavour: STABLE

а TEST.yaml содержит

envClass: TEST

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

Один ConfigMap и один Secret для всех файлов

Смотрим внимательно - вот одна, единая конфигурация для одного единственного ConfigMap и одного Secret, куда поместятся все ваши файлы. Бинарные файлы и текстовые несекретные файлы пойдут в ConfigMap, а секретные текстовые файлы в Secret.

# это нужно для вложенных range{{- $self := . -}} # список директорий, откуда берутся файлы - среда-разновидность, среда-тип и потом общие файлы из shared{{ $sources := (list "shared" .Values.envClass (printf "%s-%s" .Values.envFlavour .Values.envClass ) }}apiVersion: v1kind: ConfigMapmetadata:  name: myapp# вставить несекретные текстовые файлы как шаблоныdata:{{ range $env := $sources }}{{ range $path, $bytes := $self.Files.Glob (printf "files/%s/text/*" $env) }}  {{ base $path }}: {{ tpl ($self.Files.Get $path) $ | quote }}{{ end }}{{ end }}# вставить двоичные файлыbinaryData:{{ range $env := $sources }}{{ range $path, $bytes := $self.Files.Glob (printf "files/%s/binary/*" $env) }}  {{ base $path }}: {{ $self.Files.Get $path | b64enc | quote }}{{ end }}{{ end }}---apiVersion: v1kind: Secretmetadata:  name: myapp  labels:type: Opaquedata:# вставить секретные текстовые файлы как шаблоны{{ range $env := $sources }}{{ range $path, $bytes := $self.Files.Glob (printf "files/%s/secret-text/*" $env) }}  {{ base $path }}: {{ tpl ($self.Files.Get $path) $ | b64enc | quote }}{{ end }}{{ end }}

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

Тотальная шаблонизация

Имеющие опыт с Helm, возможно, задаются вопросом, к чему все эти хитрые танцы, если у Helm уже есть набор функций для ConfigMaps и Secrets?

А вот почему. Заметили маленькую функцию tpl, применяемую на каждый файл? Правильно, именно поэтому она нужна, чтобы каждый текстовый файл обрабатывался как отдельный шаблон - вы можете вставлять ссылки на значения как {{ .Values.myValue }}в любое место ваших текстовых файлов конфигурации.

Шаблон может использоваться для любого типа конфигурации, .properties, yaml, HOCON, например:

akka {  persistence {    cassandra {        keyspace = {{ .Values.cassandra.keyspace | quote }}        table = "{{ .Values.cassandra.tablePrefix }}messages"

Коварные кавычки

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

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

databasePassword: {{ .Values.databasePassword | quote }}

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

param/username={{ .Values.username | trimAll "\"" }}

Проецируемые тома (projected volumes)

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

Для этого в Kubernetes удачно завезли projected volumes - проецируемые тома, которые можно собирать из нескольких ConfigMaps и Secrets.

volumes:  - name: properties    projected:      defaultMode: 0640      sources:        - configMap:            name: myapp        - secret:            name: myapp

Очень просто смонтировать такой "сборный" том в директорию/confвашего приложения.

Линтер

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

У Helm есть для этого команды lint и template:

helm lint --debug path/to/<chart> --strict --values env/<env>.yaml \  --values env/<env>-<flavour>.yaml  helm template <chart> path/to/<chart> --strict --values env/<env>.yaml \  --values env/<env>-<flavour>.yaml

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

Но совершенству нет пределов (почти) - можно пойти ещё на шаг дальше и использовать yamllint для валидации yaml-дескрипторов. Это позволит отловить проблемы, которые иначе не получается ловить - например два файла с одним и тем же именем, которые оказались в PROD и PROD-EU, будут дважды вставлены в ConfigMap, что приведёт к ошибке при деплойменте.

Управление секретами

Теперь немного про то, как обращаться с секретами - например ключами платных API, паролями для баз данных и паролями от TLS-сертификатов, которые мы не хотим показывать никому, кроме самого сервиса.

Обычно секретные значения хранятся в отдельном сервисе, типа Heroku Vault, Azure Vault, Google Cloud KMS и подобных. В Helm даже есть плагин для управления секретами,но в большинстве компаний управление секретами централизовано, и инженерам не позволено, да и не нужно, трогать секреты из production.

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

Для этого мы добавим секцию в values.yaml

# secretsdatabase_username: "${UserNameSecret}"database_password: "${DatabasePasswordSecret}"

И в нашем пайплайне испольуемenvsubstили нечто похожее:

cat <chart>/values.yaml | envsubst > <chart>/values-injected.yamlmv <chart>/values-injected.yaml <chart>/values.yaml

Такой подход позволяет ссылаться на секреты просто как {{ .Value.xxx }} в любом шаблоне, вставляя их туда куда им положено быть.

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

Чтобы решить этот вопрос, можно ввести конвенцию называть секреты как XXXSecret, и добавить что-то типа такого:

EXPOSED_SECRETS=$(grep Secret <chart>/files | grep -v secret-files | wc -l)if [ $EXPOSED_SECRETS -gt 0 ]; then fail "Secrets are exposed"; fi

Это добавит уровень защиты против случайной потери секрета.

Атомарные обновления сред

Теперь последний раздел - как использовать Helm hooks для того, чтобы повысить надёжность ваших пайплайнов.

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

Это может показаться сложным - особенно если вы хотите реализовать это самостоятельно, вооружившись простым kubectl apply -f ... Но, к счастью, Helm многое делает "прямо из коробки".

Флаг --atomic

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

helm upgrade --install my-chart some/path/to/my-chart \    --atomic --debug --timeout 300s

Helm откатит обновление, если проверки проб health/readiness не дали положительного результата в указанный срок. Хорошо, но можно лучше.

Hooks

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

И разумеется, сигнализировать Helm откатить обновление, если тест не прошёл.

apiVersion: batch/v1kind: Jobmetadata:  name: myapp  labels:  annotations:     "helm.sh/hook": post-install,post-upgrade     "helm.sh/hook-delete-policy": before-hook-creation,hook-succeededspec:  template:    metadata:      name: myapp-smoke-test    spec:      restartPolicy: Never      containers:        - name: tests          image: test-image:           command: ['/bin/sh',                    '-c',                    '/test/run-test.sh']

Если вы используете--atomicфлаг и post-upgrade/post-install hook для тестов в пайплайне, вы можете со значительной долей уверенности считать пайплайн надёжным. Он будет иметь "зелёный" статус тогда, и только тогда, когда сервис был успешно обновлён, запущен и прошёл базовые тесты.

А если что-то пошло не так - Helm возвратит среду в то состояние, которое было до этого обновление, включая все конфигурации и дескрипторы.

Автоматически!

Заключение

Helm это бесплатный инструмент с открытым кодом для управления обновлениями сервисов и их конфигураций в кластерах Kubernetes.

Используя шаблоны и hooks, можно добиться того, что ваш continuous delivery плавен и надёжен настолько, что его практически никто не замечает.

***

Этот текст является авторским переводом, оригинал статьи этого же автора
https://jacum.medium.com/advanced-helm-practices-for-perfect-kubernetes-deployments-7fc4e00cc41c

Подробно об авторе - https://www.linkedin.com/in/tim-evdokimov/

Подробнее..

Веб-клиент Google Cloud Text to Speech за завтраком в бастионе Сен-Жерве

13.04.2021 04:20:54 | Автор: admin

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

Вообще, если интерес возникнет, то это всегда 90% успеха, поверьте... ну, а если не возникнет, что ж. Сэкономите время: стало быть, не ваше. Сейчас, таким образом, самонадеянный и скорый на подъем аффтор, всегда готовый выхватить шпагу при виде гнусного тролля на любом интернет-форуме - предлагает всем dbutants потратить всего лишь полчаса-час на то, чтобы заинтересоваться сразу несколькими технологиями, в числе которых язык программирования Ruby, API Google Cloud Text to Speech, облачная PaaS-платформа Heroku и git.

К слову. Предвидя сделанные на языке растреклятых англичан, исконных врагов любого истинного француза комментарии в стиле "Is ruby dead?", в том смысле, а есть ли смысл вообще этим заниматься... автор предлагает всем любителям потрепаться-ни-о-чем-в-инете временно оставить эту животрепещущую тематику, сменив ее на рекомендации по изготовлению чудодейственного бальзама, наподобие того, что дала в путь-дорогу д`Артаньяну любящая его матушка, и который помог бы, в духе дня, раз и навсегда избавиться от спама за подписью того или иного эйчара, русскоговорящего или европейца/американца, несколько раз в неделю присылающих абсолютно ненужные автору инвайты на позицию Ruby Developer. Ненужные не потому, что автор, вволю напрактиковавшись и слегка "подточив" теорию, привык получать приглашения исключительно и самолично из рук аж самого CTO Armand-Jean du Plessis, duc de Richelieu... а потому, что за все годы работы - ни одного проекта, ни одной должности от HR он не получил, так уж сложилось.

Чего и вам от души желает. Если какой-либо институт и мертв, то это почти наверняка Human Resource, по крайней мере, у нас в России (как с этим обстоят дела у Бекингема - Бог весть, не знаю). Все остальное покамест работает... это была, так сказать, литературная прелюдия, ну а теперь сходу к практике, с места в карьер. "Сударь, вы ошиблись! Нас не трое, нас четверо!"

Итак. Цель сегодняшних наших упражнений - построение приложения, работающего с API Google Cloud Text to Speech, иными словами - конвертера текста в звук, и с очень неплохим качеством. Правда, все чаще раздаются голоса, дескать, IBM Text-to-Speech API круче, но это мы оставим, с вашего позволения, для следующей статьи... "голоса" обычно не скрывают, что IBM API обходится недешево, гугловский же сервис возможно использовать практически бесплатно (находим и внимательно читаем Terms of Service). Но вам понадобится волшебный ключ, нечто в стиле "то, что сделал предъявитель сего, сделано по моему приказанию и для блага государства" в формате JSON, для получения которого, вполне возможно, придется засветить ваш MasterCard здесь. Может быть, даже заморозят на недельку кровный ваш $1, ничего? - ну всяко это не так страшно, как в военное де-факто время совершать вояж за линию фронта, будучи вдохновленным одним лишь лукавым взглядом г-жи Бонасье, согласитесь.

Также зарегистрируйте Free account Heroku, куда мы с вами намереваемся пушить ваше первое приложение на основе фреймворка Ruby on Rails, скачайте и установите git и Heroku toolbelt для своей OS.

Немного о структуре приложения. Как уже сказано выше, это rails-app, полноценный веб-интерфейс для API Google Cloud Text to Speech: аутентификация реализована посредством device (полистайте доку, там немало интересного на случай, если захотите что-то изменить в предлагаемом техническом решении), сконфигурированного таким образом, что возможен лишь один пользователь. Что нам и нужно: сразу после деплоя приложения на Heroku вы зарегистрируетесь в нем, подтвердив указанный вами email, и дальнейшие регистрации будут невозможны (изменить или сбросить пароль вы, при необходимости, сможете).

Интерфейс выполнен в духе минимализма, под которым автор понимает Bootstrap 4 и кое-какие джаваскрипты; информационные flash-сообщения панели управления - средствами ajax, благо он как никто родной для Ruby on Rails. Заказчик-киевлянин, для которого был выполнен этот rails-app, он же старый мой приятель, скупой как кардинал Мазарини - очень просил "без излишеств, можно вообще без стилей", ну и вот... впрочем, помимо ожидания, получилось вполне элегантно. Представленный далее короткий ролик не самый новый, с момента его создания приложение было рефакторено и получило новые свойства, но какое-то визуальное представление способен дать.

Да, и "о фичах". На момент публикации этого материала Google-Cloud-TTS-Rails способен работать с текстом (также поддерживается SSML) на любом из 18 языков, конвертируя в один из следующих, по желанию, форматов: MP3 (MPEG Audio Layer III), WAV (LINEAR16) and OGG (OGG_OPUS), поддерживаются оба доступных voice type: WaveNet и Basic. Также интерфейс приложения позволяет корректировать скорость произношения...

...с чего, пожалуй, и начнем этот краткий экскурс в программный код. Меню регулировки скорости реализовано как хелпер, посредством которого получаем в HTML выпадающее меню (drop-down list), диапазон значений от 0.25 до 4.0 (обусловлено API), шаг 0.25, значение по-дефолту 1.0. Привыкайте, это рельсы:

module SoundHelper  def speaking_rate    select_tag 'speaking_rate', options_for_select(      0.25.step(by: 0.25, to: 4.0), selected: '1.0'    ), { class: 'btn' }  endend

Да, к слову. Те, кто не хотят вникать в код, возможно, им это сто лет не нужно... имеют возможность пропустить вышесказанное/поименованное мимо, соответственно, ушей и глаз, равно как и еще парочку фрагментов кода, воспоследующих далее. Имеете полное право, почему нет. Я сейчас сделаю краткую паузу на то, чтобы in two words рассказать, как залить из гитхаба на Heroku полностью готовое к работе приложение, вам понадобятся на вашем рабочем компе лишь Heroku CLI и git, как уже и говорил. Ruby и postgreSQL в этом случае без надобности.

Клонируйте приложение с гитхаба и по окончании перейдите во вновь созданный каталог, набрав в консоли:

git clone https://github.com/cmirnow/Google-Cloud-TTS-Rails.gitcd Google-Cloud-TTS-Rails

Бросьте файл, содержащий ваш персональный ключ YOUR_KEY_NAME.json, в корень директории приложения (название значения не имеет). Далее:

git add .   git commit -m "my first commit"heroku creategit push heroku masterheroku run rake db:migrate

Откройте панель администрирования Heroku, YOUR_NEW_APPLICATION -> 'Settings' -> 'Reveal Config Vars', и введите следующие пары key/value:


key: GOOGLE_APPLICATION_CREDENTIALS value: YOUR_KEY_NAME.json

key: DOMAIN_NAME value: YOUR_HEROKU_DOMAIN ### i.e 'https://***************.herokuapp.com' without quotes.

key: GMAIL_USER_NAME value: YOUR_GMAIL_LOGIN

key: GMAIL_PASSWORD value: YOUR_GMAIL_PASSWORD ### (An App Password is a 16-digit passcode that gives an app or device restricted access to your Google Account without having to divulge your personal password and complete access to your Google Account).


Как видите, потребуется указать доступ к почтовому серверу, чтобы Google-Cloud-TTS-Rails смог отослать вам письмо в ходе регистрации аккаунта, также на случай необходимости сброса забытого пароля. И - на этом все, после регистрации приложение полностью готово к работе. Лимит текста "за один раз" - 5000 знаков, обусловлено Google. Надеюсь, вам понравится.

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

class Validationinclude ActiveModel::Modelattr_accessor :requestvalidates :request, presence: true, length: {in:3..4999}end

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

  def conversion    audio_format = TtsConversion.index(client, synthesis_input, voice, audio, params[:codec])    success_info(audio_format)  end  def client    Google::Cloud::TextToSpeech.text_to_speech  end  def synthesis_input    { params[:text_or_ssml] => params[:request] }  end  def voice    { language_code: params[:lang], name: params[:voicename] }  end  def audio    { audio_encoding: params[:codec], speaking_rate: params[:speaking_rate].to_f }  end
class TtsConversion  def self.index(*args)    response = args[0].synthesize_speech input: args[1], voice: args[2], audio_config: args[3]    File.open 'public/output/output.' + audio_format(args[4]).to_s, 'wb' do |file|      file.write response.audio_content      audio_format(args[4]).to_s    end  end  def self.audio_format(codec)  case codec  when "LINEAR16"  'wav'    when "OGG_OPUS"      'ogg'  else  'mp3'  end  endend

Всю работу свершает, по сути, gem 'google-cloud-text_to_speech', передавая конвертируемый текст и выбранные параметры в API Google Cloud Text to Speech и получая обратно звук в цифре. Вот, пожалуй, и все.

Подробнее..

Перевод Обучение на табличных данных. TABNet. Часть 2. Реализация

22.12.2020 10:22:28 | Автор: admin

Продолжение перевода про архитектуру TABNet. Первая часть здесь

4 .Самостоятельное обучение для табличного представления.

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

Цель самообучения: Предлагаем задачу прогнозирования отсутствующих столбцов из других. Рассмотрим двоичную маску

S \{0, 1 \} ^{BD}.

TabNet кодирует вход

(1-S) * \hat{f}

и TabNet декодирует выход реконструированных объектов,

S * \hat{f}

Мы инициализируем P[0] = (1 S)

в кодере так, чтобы модель делала упор только на известные объекты, а последний слой FC декодера умножаем на S, чтобы просто вывести неизвестные объекты. Мы рассматриваем потери на оптимизирующие преобразования в фазе самообучения:

\sum_{b=1}^{B} \sum_{j=1}^{D} \mid (\hat{f}_{b,j} - f_{b,j}) * S_{b,j} / \sqrt{\sum_{b=1}^{B}(f_{b,j}-1/B\sum_{b=1}^{B}f_{b,j})^2} \mid ^2 .

Нормализация среднеквадратичного отклонения начальных данных с помощью достоверных данных имеет важное значение, так как характеристики могут иметь колебания в различных диапазонах. Мы выберем записи Sb,j независимо от распределения Бернулли с параметром ps на каждой итерации.

5.Эксперименты.

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

Мы используем стандартные классификационные (обобщение логистическойфункции для многомерного случая, перекрёстнаяэнтропия) и регрессионные (среднеквадратичная ошибка) целевые функции и исследуем сходимость в различных случаях. Гиперпараметры модели TabNet оптимизированы на обучающей выборке и перечислены в Приложении. Производительность TabNet не очень чувствительна к большинству гиперпараметров, как показано в исследованиях (приложениях). Во всех экспериментах, где мы приводим результаты из других работ, мы используем одни и те же данные обучения, проверки и тестирования, как и в оригинальных работах. Для обучения всех моделей используются алгоритм оптимизации Adam [32] и равномерная инициализация Glorot. Реализацию с открытым исходным кодом можно найти на сайте https://github.com/google-research/google-research/tree/master/tabnet.

5.1 Выбор объекта по экземпляру

Выбор наиболее информативных объектов может иметь решающее значение для высокой производительности, особенно для небольших наборов данных. Мы рассмотрим 6 синтетических табличных наборов данных из [6] (состоящих из 10k обучающих выборок). Синтетические наборы данных построены таким образом, что только подмножество объектов определяет выходные данные. Для наборов данных Syn1, Syn2 и Syn3 эталонные объекты одинаковы для всех экземпляров, поэтому общий механизм выбора объектов должен быть оптимальным. Например, истинный результат набора данных Syn2 зависит только от объектов X3-X6. Для наборов данных Syn4, Syn5 и Syn6 существенные особенности зависят от рассматриваемого экземпляра. Например, для набора данных Syn4 индикатором является X11, а результирующий исход зависит либо от X1-X2, либо от X3-X6, в зависимости от значения X11. Эта зависимость от экземпляра делает глобальный выбор объектов неоптимальным, поскольку глобально значимые объекты были бы избыточными для некоторых экземпляров. В таблице 1 показана производительность кода TabNet по сравнению с другими методами, включая отсутствие выбора, использование только глобально значимых признаков, древовидных ансамблей [16], регуляризации LASSO, L2X [6] и INVASE [61]. Мы наблюдаем, что TabNet превосходит все другие методы и сравним по уровню с INVASE. Для наборов данных Syn1, Syn2 и Syn3 мы наблюдаем, что производительность TabNet очень близка к глобальному выбору объектов. Для наборов данных Syn4, Syn5 и Syn6 получено, что TabNet улучшает глобальный выбор объектов, который будет содержать избыточные объекты. (Выбор объекта визуализируется в разделе 5.3.) Все остальные методы используют прогностическую модель с 43k параметрами, а общее число обучаемых параметров составляет 101k для INVASE, благодаря другим двум сетям в рамках "актор-критик". С другой стороны, TabNet - это единая архитектура ГНС (Глубокая Нейронная Сеть), и ее размер модели составляет 26k для наборов данных Syn1-Syn3 и 31k - для наборов данных Syn4-Syn6.

Это компактное сквозное представление является одним из ценных свойств TabNet.

таблица 1. Среднее и стандартное квадратичное отклонение тестовой области под кривой (AUC) на 6 синтетических наборах данных из [6], для TabNet и других моделей ГНС на основе выбора признаков: Нет выбора: использование всех функций без какого-либо выбора функций, Глобальный: использование только глобально значимых функций, Дерево: Ансамбли деревьев [16], LASSO: регуляризованная модель, L2X [6] и INVASE [61].таблица 1. Среднее и стандартное квадратичное отклонение тестовой области под кривой (AUC) на 6 синтетических наборах данных из [6], для TabNet и других моделей ГНС на основе выбора признаков: Нет выбора: использование всех функций без какого-либо выбора функций, Глобальный: использование только глобально значимых функций, Дерево: Ансамбли деревьев [16], LASSO: регуляризованная модель, L2X [6] и INVASE [61].

5.2 Производительность на реальных наборах данных

Многоклассовая классификация объектов Forest Cover Type [14]: Этот набор данных соответствует задаче классификации типа леса (лесного покрова) по картографическим переменным. Таблица 2 показывает, что TabNet значительно превосходит ансамблевые древовидные подходы, которые, как известно, достигают солидной производительности в этой задаче [38]. Кроме того, мы рассматриваем AutoInt [51] для этой задачи, учитывая его силу для задач с высокой размерностью функций. AutoInt моделирует попарное взаимодействие объектов с ГНС, основанным на внимании [51] и значительно уступает TabNet, который использует выбор объектов по экземплярам и рассматривает взаимодействие между различными объектами, если модель делает вывод о том, что это подходящая обработка для применения. Наконец, рассмотрены таблицы AutoML [2], автоматизированная система поиска, основанная на ансамбле моделей, включающих линейную обратную связь ГНС, градиентное усиление дерева решений, AdaNet [10] и ансамбли [2]. Для таблиц AutoML количество узловых часов отражает меру количества искомых моделей для ансамбля и их сложность. Одна модель TabNet без детального гиперпараметрического поиска превосходит точность ансамблевых моделей при обучении с подкреплением.

таблица 2. Производительность для набора данных типа лесного покрова.таблица 2. Производительность для набора данных типа лесного покрова.

Покер [14]: этот набор данных соответствует задаче классификации при раздаче карт в покере по необработанным мастям и ранговым атрибутам карт. Отношение ввода-вывода является детерминированным, и правила ручной раздачи, реализованные с помощью нескольких строк кода, могут получить 100% точность. Тем не менее, обычные ГНС, деревья решений и даже гибридный вариант моделей глубокого нейронного дерева решений [60] сильно зависимы от несбалансированности данных и не могут освоить необходимые операции сортировки и ранжирования с необработанными входными признаками [60]. Настроенные процедуры XGBoost, CatBoost и LightGBM показывают очень незначительные улучшения по сравнению с ними. С другой стороны, TabNet значительно превосходит другие методы и подходы к точности детерминированных правил, поскольку может выполнять сильно нелинейную обработку с большой глубиной обработки без переоценки, благодаря индивидуальному выбору функций потерь.

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

Sarcos Robotics Arm, обратная динамика [57]: этот набор данных соответствует задаче регрессии обратной динамики семи степеней свободы антропоморфной руки робота. В [53] показано, что приличная производительность с очень компактной моделью возможна для ансамбля решающих деревьев (random forest), но лучшая производительность достигается с адаптивным нейронным деревом (adaptive neural tree), которое немного превосходит дерево градиентного бустинга (gradient boosted tree). В режиме модели очень малой размерности, производительность TabNet находится на одном уровне с лучшей предложенной моделью со 100-кратным увеличением параметров. TabNet распределяет свою емкость по базовым функциям и дает более компактную модель. Когда размерность модели не ограничена, TabNet показывает на порядок меньше в тесте, чем MSE.

таблица 4. Производительность для набора данных обратной динамики Sarcos Robotics Arm. расчет дерева моделей TabNet разных размеров (обозначается -S, -M и -L).таблица 4. Производительность для набора данных обратной динамики Sarcos Robotics Arm. расчет дерева моделей TabNet разных размеров (обозначается -S, -M и -L).

Бозон Хиггса [14]: этот набор данных соответствует задаче различения сигнального процесса, который производит бозоны Хиггса, и фонового процесса. Из-за своего очень большого размера (10,5 млн обучающих примеров) ГНС превосходят варианты дерева решений в этой задаче даже с очень большими ансамблями. Мы показываем, что TabNet превосходит MLPs с более компактными представлениями. Также сравниваем с современным алгоритмом эволюционной разреженности [39], который применяет неструктурированную разреженность, интегрированную в обучение, с низким количеством параметров. Благодаря своему компактному представлению TabNet дает почти такую же производительность, как и разреженное эволюционное обучение для того же числа параметров. Эта разреженность, изученная TabNet, структурирована иначе, чем альтернативные подходы она не ухудшает вычислительную способность модели [59] и может эффективно использовать современные многоядерные процессоры.

таблица 5. Производительность на наборе данных Бозона Хиггса. Расчет двух моделей TABNet (обозначены как -S и -M)таблица 5. Производительность на наборе данных Бозона Хиггса. Расчет двух моделей TABNet (обозначены как -S и -M)

Магазин Россманна [29]: Этот набор данных соответствует задаче прогнозирования продаж магазина со статическими и сезонными признаками. Мы заметили, что TabNet превосходит XGBoost, LightGBM и CatBoost, которые обычно используются для таких проблем. Временные характеристики (например, день) приобретают большое значение, и преимущество выбора функции по экземпляру особенно заметно в праздники, когда динамика продаж изменяется.

таблица 6. Производительность на наборе данных магазина Россмана.таблица 6. Производительность на наборе данных магазина Россмана.

Наборы данных KDD. Наборы данных Appetency, Churn и Upselling используются в задачах классификации для управления взаимоотношениями с клиентами, а набор данных KDD Census Income [14] предназначен для прогнозирования доходов на основе демографических переменных и переменных, связанных с занятостью. Эти наборы данных демонстрируют интенсивную производительность (даже простые модели дают аналогичные результаты). Таблица 7 показывает, что TabNet достигает очень похожих или немного худших результатов, чем у XGBoost и CatBoost, которые известны своей надежностью, поскольку содержат большое количество ансамблей.

таблица 7. Производительность на наборе данных KDD.таблица 7. Производительность на наборе данных KDD.

5.3 Интерпретируемость.

Маски выбора функций в TabNet можно интерпретировать выбранными особенностями на каждом этапе. Такая возможность недоступна для обычных ГНС, таких как MLP, поскольку каждый последующий уровень совместно обрабатывает все функции без механизма выбора с контролируемой разреженностью. Для масок выбора признаков, если Mb, j [i] = 0, то j-ая особенность из b-ого образца не должна влиять на принятие решения. Если бы fi была линейной функцией, коэффициент Mb, j [i] соответствовал бы важности признака fb, j. Хотя на каждом этапе принятия решения используется нелинейная обработка, их результаты позже агрегируются линейным образом. Наша цель - количественно оценить общую важность функции в дополнение к анализу каждого шага. Объединение масок на разных этапах требует учета коэффициента, который может отражать относительную важность каждого этапа в принятии решения. Мы используем

\eta_{b}[i] = \sum_{c=1}^{N_d}ReLU(d_{b,c}[i])

обозначают совокупный вклад решения на i-м шаге решения для b-й выборки. Интуитивно понятно, что если d b, c [i] <0, то все функции i-го шага решения должны иметь нулевой вклад в общее решение. По мере увеличения его значения, оно играет более важную роль в общем линейном сочетании. Масштабируя маску принятия решения на каждом шаге с помощью nb [i], мы предлагаем маску важности агрегированного признака

M_{agg-b,j} = \sum_{i=1}^{N_{steps}} \eta_b[i]M_{b,j}[i] / \sum_{j=1}^{D} \sum_{i=1}^{N_{steps}} \eta_b[i] M_{b,j}[i].

Нормализация используется для обеспечения:

\sum_{j=1}^{D} M_{agg-b_{b,j}} = 1

Синтетические данные. На рис. 5 показаны совокупные маски важности признаков для синтетических наборов данных, обсуждаемых в разд. 5.1. Истинный результат для набора данных Syn2 зависит только от функций X3-X6. Мы видим, что совокупные маски почти все равны нулю для нерелевантных функций, они просто фокусируются на релевантных. Для набора данных Syn4 X11 является индикатором, а исходные данные зависят от X1-X2 или X3-X6 в зависимости от значения X11. TabNet обеспечивает точный выбор функций для каждого экземпляра - он выделяет маску, чтобы сосредоточиться на X11, и присваивает близкие нулю веса нерелевантным функциям (тем, которые не относятся к одной из двух групп функций).

таблица 8. Рейтинг важности характеристик Дохода взрослого населения в переписи. TabNet составляет рейтинг важности функций в соответствии с хорошо известными методами.таблица 8. Рейтинг важности характеристик Дохода взрослого населения в переписи. TabNet составляет рейтинг важности функций в соответствии с хорошо известными методами.

Наборы данных из реального мира: сначала мы рассмотрим простую реальную задачу предсказания съедобности грибов [14]. TabNet прошел 100% тест точности этого набора данных. Действительно, известно [14], что запах является наиболее отличительным признаком для этой задачи, только с функцией запах модель может получить точность теста> 98,5% [14]. Таким образом, для него ожидается высокая важность функции. TabNet присваивает ему коэффициент важности 43%, в то время как другие известные методы, такие как LIME [48], Интегрированные градиенты [52] и DeepLift [49] присваивают оценку важности с коэффициентом менее 30% [27].

Рисунок 5. Маски важности признаков M [i] (которые указывают, какие объекты выбираются на i-м шаге) и совокупная маска важности признаков Magg, показывающая глобальный выбор объекта по экземплярам для наборов данных Syn2 и Syn6 из [6]. Более яркие цвета показывают более высокую ценность. Например, для набора данных Syn2 используются только четыре функции (X3-X6). Рисунок 5. Маски важности признаков M [i] (которые указывают, какие объекты выбираются на i-м шаге) и совокупная маска важности признаков Magg, показывающая глобальный выбор объекта по экземплярам для наборов данных Syn2 и Syn6 из [6]. Более яркие цвета показывают более высокую ценность. Например, для набора данных Syn2 используются только четыре функции (X3-X6).

Затем мы рассмотрим доход взрослого населения от переписи населения, где задача состоит в том, чтобы определить, превышает ли доход человека 50 000 долларов. Таблица 8 показывает ранжирование важности функций для TabNet по сравнению с другими методами объяснимости из [36], [42]. Мы наблюдаем общность наиболее важных характеристик Age (Возраст), Capital gain/loss (Прирост / потеря капитала), Education number (Уровень образования), Relationship (Родство)) и наименее важных Native country (Родная страна), Race (Раса) , Gender (Пол). Для той же проблемы на рис. 6 (c) показано влияние наиболее важной функции на решение о выходе путем визуализации T-SNE многообразия решений. Наблюдается четкое разделение возрастных групп, так как Age (Возраст) является наиболее важной характеристикой TabNet.

Рисунок 6. T-SNE многообразия решений для тестовых выборок переписи дохода взрослого населения и влияние главного признака Age (Возраст).Рисунок 6. T-SNE многообразия решений для тестовых выборок переписи дохода взрослого населения и влияние главного признака Age (Возраст).

5.4 самостоятельное обучение под наблюдением

Мы изучаем самообучение на наборах данных типа Хиггса и лесного покрова. Для предварительного обучения предсказанию (заполнению) недостающих столбцов мы используем параметр маскирования ps = 0.8 и процесс обучения с 1 миллионом итераций. Используем подмножество помеченного набора данных для контролируемой тонкой настройки с набором проверки для определения количества итераций для ранней остановки. Большой набор данных при проверке был бы нереалистичным для небольших наборов обучающих данных, поэтому в этих экспериментах мы предполагаем, что его размер равен набору обучающих данных. Таблица 9 показывает, что предварительное обучение без учителя значительно улучшает производительность задачи классификации с учителем, особенно в режиме, когда немаркированный набор данных намного больше, чем маркированный. Как показано на рис. 7, сходимость модели происходит намного быстрее при предварительном обучении без учителя. Очень быстрая сходимость может быть очень полезной, особенно в таких сценариях, как непрерывное обучение, адаптивное предметной области.

Рисунок 7. Сходимость с предварительным обучением без учителя происходит намного быстрее, что показано для набора данных Хиггса с выборкой в 10 тыс..Рисунок 7. Сходимость с предварительным обучением без учителя происходит намного быстрее, что показано для набора данных Хиггса с выборкой в 10 тыс..таблица 9. Табличные результаты обучения с самостоятельным контролем. Среднее и стандартное отклонение точности (более 15 прогонов) по Хиггсу с TabNet-М модель, варьируя размером обучающего набора данных для контролируемой тонкой настройки.таблица 9. Табличные результаты обучения с самостоятельным контролем. Среднее и стандартное отклонение точности (более 15 прогонов) по Хиггсу с TabNet-М модель, варьируя размером обучающего набора данных для контролируемой тонкой настройки.таблица 10. Табличные результаты обучения с самоконтролем. Среднее и стандартное отклонение точности (более 15 прогонов) для типа леса, с варьированием размера обучающего набора данных и контролируемой точной настройкитаблица 10. Табличные результаты обучения с самоконтролем. Среднее и стандартное отклонение точности (более 15 прогонов) для типа леса, с варьированием размера обучающего набора данных и контролируемой точной настройки

Заключение

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

Перевод, коррекция, редактирование Гилязов Айрат, Шигапова Фирюза.


Ссылки

[1] Dario Amodei, Rishita Anubhai, Eric Battenberg, Carl Case, Jared Casper, et al. 2015. Deep Speech 2: End-to-End Speech Recognition in English and Mandarin. arXiv:1512.02595 (2015).

[2] AutoML. 2019. AutoML Tables Google Cloud. https://cloud.google.com/ automl-tables/

[3] J. Bao, D. Tang, N. Duan, Z. Yan, M. Zhou, and T. Zhao. 2019. Text Generation From Tables. IEEE Trans Audio, Speech, and Language Processing 27, 2 (Feb 2019), 311320.

[4] Yael Ben-Haim and Elad Tom-Tov. 2010. A Streaming Parallel Decision Tree Algorithm. JMLR 11 (March 2010), 849872.

[5] Catboost. 2019. Benchmarks. https://github.com/catboost/benchmarks. Accessed: 2019-11-10.

[6] Jianbo Chen, Le Song, Martin J. Wainwright, and Michael I. Jordan. 2018. Learning to Explain: An Information-Theoretic Perspective on Model Interpretation. arXiv:1802.07814 (2018).

[7] Tianqi Chen and Carlos Guestrin. 2016. XGBoost: A Scalable Tree Boosting System. In KDD.

[8] Michael Chui, James Manyika, Mehdi Miremadi, Nicolaus Henke, Rita Chung, et al. 2018. Notes from the AI Frontier. McKinsey Global Institute (4 2018).

[9] Alexis Conneau, Holger Schwenk, Loc Barrault, and Yann LeCun. 2016. Very Deep Convolutional Networks for Natural Language Processing. arXiv:1606.01781 (2016).

[10] Corinna Cortes, Xavi Gonzalvo, Vitaly Kuznetsov, Mehryar Mohri, and Scott Yang. 2016. AdaNet: Adaptive Structural Learning of Artificial Neural Networks. arXiv:1607.01097 (2016).

[11] Zihang Dai, Zhilin Yang, Fan Yang, William W. Cohen, and Ruslan Salakhutdinov. 2017. Good Semi-supervised Learning that Requires a Bad GAN. arxiv:1705.09783 (2017).

[12] Yann N. Dauphin, Angela Fan, Michael Auli, and David Grangier. 2016. Language Modeling with Gated Convolutional Networks. arXiv:1612.08083 (2016).

[13] Jacob Devlin, Ming-Wei Chang, Kenton Lee, and Kristina Toutanova. 2018. BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding. arXiv:1810.04805 (2018).

[14] Dheeru Dua and Casey Graff. 2017. UCI Machine Learning Repository. http: //archive.ics.uci.edu/ml

[15] Jonas Gehring, Michael Auli, David Grangier, Denis Yarats, and Yann N. Dauphin. 2017. Convolutional Sequence to Sequence Learning. arXiv:1705.03122 (2017).

[16] Pierre Geurts, Damien Ernst, and Louis Wehenkel. 2006. Extremely randomized trees. Machine Learning 63, 1 (01 Apr 2006), 342.

[17] Ian Goodfellow, Yoshua Bengio, and Aaron Courville. 2016. Deep Learning. MIT Press.

[18] K. Grabczewski and N. Jankowski. 2005. Feature selection with decision tree criterion. In HIS.

[19] Yves Grandvalet and Yoshua Bengio. 2004. Semi-supervised Learning by Entropy Minimization. In NIPS.

[20] Isabelle Guyon and Andre Elisseeff. 2003. An Introduction to Variable and Feature Selection. JMLR 3 (March 2003), 11571182.

[21] Kaiming He, Xiangyu Zhang, Shaoqing Ren, and Jian Sun. 2015. Deep Residual Learning for Image Recognition. arXiv:1512.03385 (2015).

[22] Joel Hestness, Sharan Narang, Newsha Ardalani, Gregory F. Diamos, Heewoo Jun, Hassan Kianinejad, Md. Mostofa Ali Patwary, Yang Yang, and Yanqi Zhou. 2017. Deep Learning Scaling is Predictable, Empirically. arXiv:1712.00409 (2017).

[23] Tin Kam Ho. 1998. The random subspace method for constructing decision forests. PAMI 20, 8 (Aug 1998), 832844.

[24] Elad Hoffer, Itay Hubara, and Daniel Soudry. 2017. Train longer, generalize better: closing the generalization gap in large batch training of neural networks. arXiv:1705.08741 (2017).

[25] Drew A. Hudson and Christopher D. Manning. 2018. Compositional Attention Networks for Machine Reasoning. arXiv:1803.03067 (2018).

[26] K. D. Humbird, J. L. Peterson, and R. G. McClarren. 2018. Deep Neural Network Initialization With Decision Trees. IEEE Trans Neural Networks and Learning Systems (2018).

[27] Mark Ibrahim, Melissa Louie, Ceena Modarres, and John W. Paisley. 2019. Global Explanations of Neural Networks: Mapping the Landscape of Predictions. arxiv:1902.02384 (2019).

[28] Kaggle. 2019. Historical Data Science Trends on Kaggle. https://www.kaggle. com/shivamb/data-science-trends-on-kaggle. Accessed: 2019-04-20.

[29] Kaggle. 2019. Rossmann Store Sales. https://www.kaggle.com/c/ rossmann-store-sales. Accessed: 2019-11-10.

[30] Guolin Ke, Qi Meng, Thomas Finley, Taifeng Wang, Wei Chen, et al. 2017. LightGBM: A Highly Effcient Gradient Boosting Decision Tree. In NIPS.

[31] Guolin Ke, Jia Zhang, Zhenhui Xu, Jiang Bian, and Tie-Yan Liu. 2019. TabNN: A Universal Neural Network Solution for Tabular Data. https://openreview.net/forum?id=r1eJssCqY7

[32] Diederik P. Kingma and Jimmy Ba. 2014. Adam: A Method for Stochastic Optimization. In ICLR.

[33] P. Kontschieder, M. Fiterau, A. Criminisi, and S. R. Bul. 2015. Deep Neural Decision Forests. In ICCV.

[34] Siwei Lai, Liheng Xu, Kang Liu, and Jun Zhao. 2015. Recurrent Convolutional Neural Networks for Text Classification. In AAAI.

[35] Tianyu Liu, Kexiang Wang, Lei Sha, Baobao Chang, and Zhifang Sui. 2017. Table-to-text Generation by Structure-aware Seq2seq Learning. arXiv:1711.09724 (2017).

[36] Scott M. Lundberg, Gabriel G. Erion, and Su-In Lee. 2018. Consistent Individualized Feature Attribution for Tree Ensembles. arXiv:1802.03888 (2018).

[37] Andre F. T. Martins and Ram on Fern andez Astudillo. 2016. From Softmax to Sparsemax: A Sparse Model of Attention and Multi-Label Classification. arXiv:1602.02068 (2016).

[38] Rory Mitchell, Andrey Adinets, Thejaswi Rao, and Eibe Frank. 2018. XGBoost: Scalable GPU Accelerated Learning. arXiv:1806.11248 (2018).

[39] Decebal Mocanu, Elena Mocanu, Peter Stone, Phuong Nguyen, Madeleine Gibescu, and Antonio Liotta. 2018. Scalable training of artificial neural networks with adaptive sparse connectivity inspired by network science. Nature Communications 9 (12 2018)

[40] Alex Mott, Daniel Zoran, Mike Chrzanowski, Daan Wierstra, and Danilo J. Rezende. 2019. S3TA: A Soft, Spatial, Sequential, Top-Down Attention Model. https://openreview.net/forum?id=B1gJOoRcYQ

[41] Sharan Narang, Gregory F. Diamos, Shubho Sengupta, and Erich Elsen. 2017. Exploring Sparsity in Recurrent Neural Networks. arXiv:1704.05119 (2017).

[42] Nbviewer. 2019. Notebook on Nbviewer. https://nbviewer.jupyter.org/github/ dipanjanS/data science for all/blob/master/tds model interpretation xai/ Human-interpretableMachineLearning-DS.ipynb#

[43] N. C. Oza. 2005. Online bagging and boosting. In IEEE Trans Conference on Systems, Man and Cybernetics.

[44] German Ignacio Parisi, Ronald Kemker, Jose L. Part, Christopher Kanan, and Stefan Wermter. 2018. Continual Lifelong Learning with Neural Networks: A Review. arXiv:1802.07569 (2018).

[45] Liudmila Prokhorenkova, Gleb Gusev, Aleksandr Vorobev, Anna Veronika Dorogush, and Andrey Gulin. 2018. CatBoost: unbiased boosting with categorical features. In NIPS.

[46] Alec Radford, Luke Metz, and Soumith Chintala. 2015. Unsupervised Representation Learning with Deep Convolutional Generative Adversarial Networks. arXiv:1511.06434 (2015).

[47] Rajat Raina, Alexis Battle, Honglak Lee, Benjamin Packer, and Andrew Y. Ng. 2007. Self-Taught Learning: Transfer Learning from Unlabeled Data. In ICML.

[48] Marco Ribeiro, Sameer Singh, and Carlos Guestrin. 2016. fiWhy Should I Trust You?fi: Explaining the Predictions of Any Classifier. In KDD.

[49] Avanti Shrikumar, Peyton Greenside, and Anshul Kundaje. 2017. Learning Important Features Through Propagating Activation Differences. arXiv:1704.02685 (2017).

[50] Karen Simonyan and Andrew Zisserman. 2014. Very Deep Convolutional Networks for Large-Scale Image Recognition. arXiv:1409.1556 (2014).

[51] Weiping Song, Chence Shi, Zhiping Xiao, Zhijian Duan, Yewen Xu, Ming Zhang, and Jian Tang. 2018. AutoInt: Automatic Feature Interaction Learning via SelfAttentive Neural Networks. arxiv:1810.11921 (2018).

[52] Mukund Sundararajan, Ankur Taly, and Qiqi Yan. 2017. Axiomatic Attribution for Deep Networks. arXiv:1703.01365 (2017).

[53] Ryutaro Tanno, Kai Arulkumaran, Daniel C. Alexander, Antonio Criminisi, and Aditya V. Nori. 2018. Adaptive Neural Trees. arXiv:1807.06699 (2018).

[54] Tensorflow. 2019. Classifying Higgs boson processes in the HIGGS Data Set. https://github.com/tensorflow/models/tree/master/offcial/boosted trees

[55] Trieu H. Trinh, Minh-Thang Luong, and Quoc V. Le. 2019. Selfie: Self-supervised Pretraining for Image Embedding. arXiv:1906.02940 (2019).

[56] Aaron van den Oord, Sander Dieleman, Heiga Zen, Karen Simonyan, Oriol Vinyals, et al. 2016. WaveNet: A Generative Model for Raw Audio. arXiv:1609.03499 (2016).

[57] Sethu Vijayakumar and Stefan Schaal. 2000. Locally Weighted Projection Regression: An O(n) Algorithm for Incremental Real Time Learning in High Dimensional Space. In ICML.

[58] Suhang Wang, Charu Aggarwal, and Huan Liu. 2017. Using a random forest to inspire a neural network and improving on it. In SDM.

[59] Wei Wen, Chunpeng Wu, Yandan Wang, Yiran Chen, and Hai Li. 2016. Learning Structured Sparsity in Deep Neural Networks. arXiv:1608.03665 (2016).

[60] Yongxin Yang, Irene Garcia Morillo, and Timothy M. Hospedales. 2018. Deep Neural Decision Trees. arXiv:1806.06988 (2018).

[61] Jinsung Yoon, James Jordon, and Mihaela van der Schaar. 2019. INVASE: Instancewise Variable Selection using Neural Networks. In ICLR

Подробнее..

Выжать максимум Cloud Composer как fully-managed решение для Airflow

29.01.2021 14:10:10 | Автор: admin

Привет,Хабр! Меня зовут Сергей, яLeadSoftwareEngineer/SreamLeadв ЕРАМ,сертифицированныйGoogleCloudинженер и архитектор. Уже более 10лет занимаюсь коммерческой разработкой для различныхглобальныхкомпаний,в основном с фокусом набэкенд.А еще яочень люблю делиться своими знаниями.Сегодня хочу рассказать проApacheAirflow, который, на мой взгляд, является хорошиминструментом для построениявашихпайплайнов.

Какой план?

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

  • Посмотрим, что такоеGoogleCloudComposer, как он используетAirflowиупрощает разработкунареальных проектах.

  • Взглянем наdevelopmentиdeploymentпрактикив рамкахGoogleCloudComposer,а такжетрудностииограничения,с которыми можно столкнутьсяво времязапускаAirflowвCloudComposer.

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

Airflowв нескольких абзацах

Итак, этоинструментдля планирования, построения и мониторингапайплайнов, написанных наPython.Есть и другие готовые решения дляоркестровки процессов, напримерLuigi. Но сейчас поговорим о достоинствахAirflow:

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

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

  3. Веб-интерфейс: простой, хороший и удобный.

  4. Идет в пачке сREST API, а значитзапускатьпайплайныили получатьинформациюоихсостояниимы можемспомощьюAPI.

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

Разберемся состроительнымиблокамиAirflow.Первым идетDAG(DirectedAcyclicGraph)ацикличный направленныйграф,основаAirflow. В целом это коллекция задач, которые мы хотим запустить. Они организованы специальным образом,могутиметьмежду собой зависимости.

Tasksопределяют единицу работы DAG и выражены как его узлы.Если проще, то задачиобозначают,чтоконкретно нам нужносделать.АOperatorsв свою очередь описывают,какмы хотим это сделать, конкретизируют действияв рамках задачи.На картинкехорошовидно, что задачи это узлыDAG-а. Ониявляются сущностямиразных операторовDataLoadOperator,GoogleCloudStorageListOperatorиUpdateStatusOperatorкаждый из которыхописывает некую единицу логики, которую нужно будет сделать.Как видно, некоторые задачи, выстроенные вDAG-е, могутвыполняться параллельно. Всезависит оттипаисполнителязадачи количестваворкеров.

EщеестьDAGsRunиTasksInstances.DAGsRun это объект самогоDAGа,предназначенныйк запуску в конкретные логические время и дату.TasksInstance объект задачи,ассоциированныйс конкретнымDAGRun.А логические дата и время дляDAGRunи егоTasksInstances этоexecutiondate.

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

Плавно переходим ккомпонентам, которыеучаствуютв исполнениипайплайнавнутриAirflow:

  • Планировщик(Scheduler)мониторит всеDAG-и,задачи иотвечаетзаихсвоевременный запускиотправку на исполнение.

  • Исполнители(илиExecutor)сущность, котораяследитзаорганизациейисполнениязадач.Они бывают разные:SequentialExecutor,CeleryExecutorи др. А некоторыеиз исполнителей могут иметь дополнительные зависимости. Например,CeleryExecutorтребуетQueueBroker.

  • Воркеры(Workers)просто исполняют наши задачи(подобноворкерамCelery).

  • Веб-сервернужен, чтобы при помощи, например,тех жеHTTP-запросов, предоставлять информацию поDAG-амизадачам.Онвзаимодействует с базой,где хранятсяданныео статусе задач, переменныхAirflow,DAG-ах, соединениях ит. д.

  • Всяинформацияпроисполнениезадачпишется вLogs.Логированиепроисходитво время исполнения задач из самого кода,а такжепишутсясистемныелогиAirflow.Местомхранения логовмогут быть просто файлы, база данных либо какое-нибудь решение отсloud-провайдера. Например,можно писать вStackdriverиливGCSbucket.

  • С помощьюAdminPanelмыактивируем/деактивируемизапускаемDAG-и,устанавливаемпеременные,смотримлоги,находимпричиныпроблем(например, почемупайплайныупали).

Как это всеработает вместе?

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

GoogleCloudComposerизнутри

GoogleCloudComposerилипростоComposer этоfullymanagedсервисоркестрации, который позволяет создавать, планировать и мониторитьвашипайплайн вcloud.

Сразунесколько примеров, почему это удобно и классно.Допустим,у насестьклиент, который хочет автоматизироватьежедневныйпереносданных изstorageA вstorageB.Для этого мы напишемAirflowDAG,задеплоимего вComposerибудемзапускатьнашпайплайнвконкретный интервал времени.Задачимогут исполняться синхронно,стартоватьв определенном порядкеили параллельно.Если вдруг что-то упадет, тоестьмеханизмretry, которыйподнимет задачу ипопробуетзановоее исполнить.В общем, весь процесс зависит от настроек задачи.Теперь представьте, что нам нужно было бы сделатьcronjobs, строя при этом 100 разныхпайплайнов,без помощиAirflowиComposerоперирование, запуск и отладка дались бы гораздо труднее.

И еще немного о плюсахComposer:

  • Во-первых,с нимлегко разрабатывать идеплоить.Composerпостроен поверхAirflowипредоставляетвнутриGoogleConsoleвесь необходимый UI из коробки, чтобыбылоудобно работать,создавать окруженияизагружать файлыDAG-овс легкостью. Тамужевсе есть, мы просто создаемфайлыDAG-ов,плагиновиоператоров, указываем дополнительныезависисмости, а после загружаем в заранее созданныйComposerbucketвGCS.Дальшефайлы из бакета будут исполняться вузлахворкеров.

  • Во-вторых,уComposerестьмеханизмдля управления окружениями, причемвсе делается через UI.То есть мы можем создаватьнужное количествоокруженийсо своими версиямииотдельнымиAirflow, которые никак не будут пересекаться.

  • В-третьих,Composerтесно интегрирован сsecurity-подходами и инструментами, которые есть вGoogleCloud. Например,PrivateIPs,Authorizationит. д.

  • В-четвертых,ComposerConsoleпредоставляетстраницу метрикзапущенныхокружений.

Давайтепосмотримна компонентыComposer.На возможноеЗачем, если этоfullymanagedсервис и в нем все можно накликать?сразу скажу,чтознаниемеханизмов, сильных и слабых сторонпомогаетсделать разработку решений более эффективной.Итак,компоненты:

Пройдемся по некоторым(держим в голове, чтоComposerвсе делает сам).Накартинке видимTenantProject это для того, чтобы унифицироватьIdentityAccessManagement. Просто реализован дополнительный уровень безопасности.AppEngineFlexibleиспользуетсядля веб-сервера,CloudSQLкак база данныхAirflow.УCloudSQLестьопределенные плюсы, например,он даетограниченный доступ для сервис-аккаунта, а еще каждый день автоматически делает бэкапы.ВнутриCloudStorageComposerсоздаетbucket, который становится единой точкой для того, чтобы автоматическизагружать/обновлятьDAG-и,плагины и зависимости к ним. Файлы избакетабудут использоваться всемиворкерами, поднятымивKubernetesкластере.Core-компоненты, такие какпланировщик,worker-нодыи, например,Redis, который используетсядляCeleryExecutor,поднимаются внутриGoogleKubernetesEngine.Все это тоже автоматизировано:вместе с окружениемсоздаютсяKubernetesкластер, необходимое количествонодов,отдельноподнимаютсяворкерыиRedis.Кстати,RedisобслуживаеточередьзадачвнутриAirflow, а также нуженкак персистентное хранилище между рестартами контейнеров внутриKubernetesEngine.Большой плюс, чтоComposerхорошо интегрирован соStackdriverдля мониторинга илоггинга можно вселогии метрикисобиратьв одном месте.Это очень удобно, особенно когда у нас 100 узлов в кластере, а то и больше.

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

Кстати, воткакпроисходитмасштабированиеокружения:

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

Deploymentиdevelopment, трудности и ограничения

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

Обратите внимание, что код разбит подиректориямвендоров либоподоменным областямпродукта. А ещеAirflowдобавляетпеременныеDAGS_FOLDERиPLUGINS_FOLDERвsys.pathи потом автоматическипроцесситфайлы, которые в них находятся.Тутпросто: вDAGS_FOLDERищемDAG-и, а вPLUGINS_FOLDERсущности плагинов дляAirflow.

Итак, мы разделяем все на папки вендоров, каждаяизкоторыхможет содержатьвнутриподпапку библиотекlibsилиutils. Все зависит от того,каквам будетудобнеедержатьвместе файлы.Подпапки внутриpluginsотносятся кAirflowPLUGINS,их структурасоответствует конвенции оформления плагинов вAirflow.Я имею в видуoperators,hooks,macrosвсе, чтоAirflowпредоставляет из коробки.

Теперь поговорим прозависимостивнутри проекта.Ярекомендуюиспользоватьpipиrequirements.txtфайлкак можно чаще.Еслиработаем вComposer,тоуказывать в настройках UI,какие пакеты и версиинеобходимоустановитьв каждом из контейнеров. Или,если вы управляете окружениями внутри ваших CI/CDпайплайнов, можно устанавливать зависимости используя утилитуgcloud.Установка зависимостей с помощьюpipхорошо описана в документацииComposer.

Так какAirflowдобавляетDAGS_FOLDERиPLUGINS_FOLDERвsys.path,необходимо,по возможности,держатьлокальные зависимости вDAGS_FOLDER, а не вPLUGINS_FOLDER.Все дело в том, как работаетAirflow,ивего механизмахпоиска, сканированияи исполненияэтихдиректорий.Например,вAirflowестьнастройка, которая позволяет указать, с какой периодичностьюресканироватьпапку сDAG-ами. АвPLUGINS_FOLDERвсегораздосложнее.Поэтому не стоитпомещать много исполняемого кодаилимодулей внутрьpluginsпри каждомресканеили запуске все файлы будут исполняться и загружаться.А это может нести за собой дополнительные накладные расходы.Вообще многие команды сталкиваются с тем, что перезагрузка окружения происходит так долго, что задачисильно подвисают ипросто не могут исполняться.

Стоитьсказатьпроограничения настроекAirflow:их не все можно переопределить.Composerоставляетза собойправопредоставлять некоторые настройки только в режимеread-only. Полный список защищенных настроек можно подсмотретьв документации.

Ябыещепосоветовал использовать.airflowignoreфайл. Он работает как.gitignoreфайл, который можно помещать в директории либо описывать в нем паттерны для того, чтобымеханизмамиAirflowисключать из сканирования эти директорииилитипы файлов внутри. Это достаточно удобно, когда у нас есть большая директория. Например, в PLUGINS_FOLDER очень много кода,анамнужно хранить зависимости рядом с оператором в той же директории.Благодаря.airflowignoreзависимостибудут доступны внутриPythonкода, носам сканер их проигнорирует.

Немного про плагины вAirflow.Я рекомендуюне использовать встроенныйвAirflowмеханизмплагинов, разве что толькодля UI-вещей, например для созданияView.А дляoperators,hooksилибольшой общей логики я бывзялпростые классы.За счет того, чтоAirflowавтоматически добавляетPLUGINS_FOLDER вsys.path, можнобез проблемприменятьобычный импорт, как например,fromvnd.operators.my_operator. Такмы небудемиспользоватьникакие сущности,динамическую загрузкуилинейминг, которые предоставляет намAirflow. Пример, как может быть организован импорт внутри модулей:

from vnd.operators.my_operator import MyOperatorfrom vnd.sensors.my_sensor import MySensor

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

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

CI/СD подходтут нет ничего сложного. Мы используем те же самые подходысlinters,isortsдляGitlabCI/CDпайплайнов.В целомможнобрать любой CI/СDинструментна ваше усмотрение, ведьвсе они работают примерно одинаково:Jenkins,Gitlabpipeline,Spinnaker.

Например,мыв своемпроектеиспользуемlinters,потомидет шагunitтестов,дальшеинтеграционных.Чтобы доставить это вComposer,вызываемgcloudrsync.

Так как весь код вComposerдеплоитсявбакет,то нам нужнопросто обновить файлы до последней версиипри помощиrsync,которые в последствии будут использованыворкерамиAirflow.Конечно, можновзять командуgcloudcomposer,сее помощью регистрировать новыеDAG-и,плагиныи из каких-то своих исходных файлов все будет автоматическидоставляться внужныйбакет. Но,намой взгляд, этовыглядиткак-то сложно. Поэтому хорошо бы иметь свойrsync, который будет складыватьлибообновленные файлы,либо все фалы проекта вбакетоднимобщим подходом/способом.

Инструменты

Как и любая полноценная популярная система,Airflowпоощряет и поддерживает разработкурасширений. Они легко интегрируются,пишутся,сегодняихестьдостаточное количество в плане операторов.Но, ксожалению,не так много инструментов относятся к самомуAirflow. Один из них я могу привести. Этоafctlутилита командной строкиилиCLI-инструмент, который позволяет управлятьAirflowпроектом из командной строки. У него естьсвоибойлерплейтыилишаблоны, на базе которых можно создавать модули,DAG-иидр. Причем структура, в которойafctlсоздает свои директории,очень похожана ту,что мы используем в своем проекте (ячуть вышеотмечалее как рекомендованную).

А ещеесть достаточно много готовых интеграций, рабочих и хороших,дляAirflow.Например,GoogleCloudPlatform,AWS,Azure, различныеконнекторы кбазамданных.Их можно найтив папкеprovidersвнутри самого пакетаAirflow.

Стоит такжезайти напроектAirflowPluginsнайдетевсевозможные плагины, коннекторы к CRMсистемам, социальным сетямит. д.Не забывайтезаглядывать в поискGitHub: популярностьAirflowисообществорастут,а значит постояннопоявляются новые решения, которые можно подсмотреть.


Суммируем и резюмируем:

Все, что относится кAirflowи что можносделатьвself-service, запускаетсявCloudComposer.

CloudComposer, к сожалению, не масштабируется в ноль(scalingtozero). Тоесть,создавокружение, мы будем платить за него деньги. Но за счет этого можноуправлятьComposerинвайронментом:строитьновый,проводитьA/B-тесты, презентовать заказчику иудалить его. Естественно,еслинет окруженийиподнятогоGKE кластера, томы ни за что не платим.

Стоит разделять окружения внутриComposer, например,Prod/Dev/Staging.Иеще держать их обновленными.ВComposerиспользуется версияAirflow,адаптированная под работу с ним,акомандаGoogleтожеактивно обновляет свои версииAirflow.Поэтому время от времениComposerпредлагаетапдейтнутьокружение:появляется кнопка,автоматическисоздаетсяновыйimage, контейнеры и вашинвайронментпереводитсявновую версиюAirflow.

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

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

По возможности не используемAirflowPluginсущноститолько дляUI вещей, которыепредоставляетAirflow. Но для операторов я бы не рекомендовал.

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

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

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

ИспользуйтеKubernetesPodOperatorдля запуска зависимостей и утилит, написанных не наPython. Так как у нас все окружение загружается и исполняется вкластереKubernetes,Airflowбудет инициироватьисполнение задачив отдельномPod-е. Для этого будут использованы дополнительные ноды кластера, созданные Composer-ом.

Помните проограничениеComposer, а именно проread-onlyнастройкиAirflow.Полный список защищенных настроек можно подсмотретьв документации.

Уверен, что вы сможете оптимизировать свои пайпланы, а Airflow и Composer станут в этом отличными помощниками :)

Подробнее..

Бесплатные сервисы для разработчиков огромный список

06.04.2021 12:11:10 | Автор: admin

Бесплатное хранилище артефактов PackageCloud

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

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

Но для некоторых бесплатный тариф единственный способ завлечь новых клиентов. Это просто замечательно с точки зрения самих пользователей. Ведь перед нами десятки бесплатных хостингов, API, CMS, CDN, сервисов обработки данных, поисковых движков, репозиториев, инструментов проверки кода и других. Бесплатный тариф идеален для опенсорс-разработчиков, любительских и некоммерческих проектов, маленьких стартапов. Ни за что не надо платить.

Например, огромный список бесплатных сервисов для разработчиков ведётся в репозитории free-for-dev. Список составлен пул-реквестами более 900 участников.

Важно подчеркнуть, что конкретно в этом списке отсутствуют альтернативы на своём хостинге (о них см. ниже). Здесь исключительно онлайновые сервисы, то есть SaaS, PaaS, IaaS.

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

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

Основные облачные провайдеры


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

Google Cloud Platform

  • App Engine 28 часов фронтенд-инстансов в день, 9 часов бэкенд-инстансов в день
  • Cloud Firestore 1ГБ места, 50000 чтений, 20000 записей, 20000 удалений в день
  • Compute Engine 1 невытесняемый инстанс f1-micro, 30ГБHDD, 5ГБ для снапшотов (не для всех регионов), сеть 1ГБ из Северной Америки во все регионы (кроме Китая и Аргентины) в месяц
  • Cloud Storage 5ГБ, трафик 1ГБ
  • Cloud Shell веб-терминал Linux и базовая IDE с хранилищем на 5ГБ. Лимит 60 часов в неделю
  • Cloud Pub/Sub 10ГБ сообщений в месяц
  • Cloud Functions 2 млн вызовов в месяц (включая все фоновые и HTTP-вызовы)
  • Cloud Run 2 млн запросов в месяц, 360000гигабайт-секунд памяти, 180000 vCPU-секунд вычислительного времени, трафик 1ГБ в месяц из Северной Америки в другие регионы
  • Google Kubernetes Engine отсутствие платы за управление для одного зонального кластера. Но при этом все узлы оплачиваются по стандартной цене Compute Engine
  • BigQuery 1ТБ запросов в месяц, 10ГБ хранилище на месяц
  • Cloud Build 120 минут сборки в день
  • Cloud Source Repositories до 5 пользователей, хранилище 50ГБ, трафик 50ГБ
  • Полный список бесплатных тарифов Google Cloud

Amazon Web Services

  • Amazon DynamoDB СУБД NoSQL на 25ГБ
  • Amazon Lambda 1млн запросов в месяц
  • Amazon SNS 1млн нотификаций в месяц
  • Amazon Cloudwatch 10 пользовательских метрик и 10 предупреждений
  • Amazon Glacier 10ГБ долговременного хранилища объектов
  • Amazon SQS 1 млн запросов из очереди сообщений
  • Amazon CodeBuild 100 минут сборки в месяц
  • Amazon Code Commit 5 активных пользователей в месяц
  • Amazon Code Pipeline 1 активный конвейер в месяц
  • Полный список бесплатных тарифов AWS

Microsoft Azure

  • Virtual Machines 1 виртуальная машина B1S под Linux, одна B1S под Windows
  • App Service 10 приложений (веб, мобильные или API)
  • Functions 1 млн запросов в месяц
  • DevTest Labs среда разработки и тестирования
  • Active Directory 500000 объектов
  • Active Directory B2C хранилище на 50000 пользователей в месяц
  • Azure DevOps 5 активных пользователей, неограниченные приватные репозитории Git
  • Azure Pipelines 10 бесплатных параллельных задач с неограниченным временем выполнения для опенсорсных проектов под Linux, macOS и Windows
  • Microsoft IoT Hub 8000 сообщений в день
  • Load Balancer 1 бесплатный публичный IP (VIP) с балансировкой нагрузки
  • Notification Hubs 1млн пуш-нотификаций
  • Bandwidth внешний трафик 5ГБ в месяц
  • Cosmos DB 5ГБ хранилище и обеспеченная пропускная способность на 400 RU (реквест-юнитов)
  • Static Web Apps сборка, деплой и хостинг статичных приложений и бессерверных функций, с бесплатным SSL, аутентификацией/авторизацией и пользовательскими доменами
  • Storage хранилище для файлов и блобов на 5ГБ в LRS (locally redundant storage)
  • Cognitive Services AI/ML API (компьютерное зрение, перевод, распознавание лиц, боты...) с бесплатным лимитом использования
  • Cognitive Search сервис индексации текстов и поиск на основе ИИ, бесплатно на 10000 документов
  • Azure Kubernetes Service бесплатное управление кластером Kubernetes (хотя при этом оплачиваются сами виртуальные машины, хранение данных и другие сервисы за пределами бесплатных лимитов)
  • Event Grid 100тыс. операций в месяц
  • Полный список бесплатных тарифов Azure

Oracle Cloud

  • Compute два инстанса VM.Standard.E2.1.Micro 1ГБ RAM
  • Block Volume 2 тома, в сумме 100ГБ (используется для вычислений)
  • Object Storage 10 ГБ
  • Load Balancer 1 инстанс на 10 Мбит/с
  • Databases 2 базы данных, по 20 ГБ каждая
  • Monitoring приём до 500млн точек данных, выдача до 1млрд точек данных
  • Bandwidth внешний трафик 10ТБ в месяц с ограничением скорости 5Мбит/с
  • Notifications 1 млн нотификаций в месяц, 1000 отправленных писем
  • Полный список бесплатных тарифов Oracle Cloud

IBM Cloud

  • Cloud Functions 5 млн выполнений в месяц
  • Object Storage 25ГБ в месяц
  • Cloudant Database хранилище на 1 ГБ
  • Db2 Database хранилище на 100МБ
  • API Connect 50000 вызовов API в месяц
  • Availability Monitoring 3 млн точек данных в месяц
  • Log Analysis анализ логов до 500МБ в сутки
  • Полный список бесплатных тарифов IBM Cloud

Аналитика, статистика, логи


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

Примечание. Программы self-hosted см. в отдельной категории.

  • AO Analytics бесплатная аналитика для любых сайтов, без ограничений по объёму
  • Indicative платформа аналитики до 50млн событий в месяц
  • Amplitude 1 млн событий в месяц, до 2 приложений
  • GoatCounter опенсорсная платформа веб-аналитики бесплатно для некоммерческого использования или self-hosted версия бесплатно для всех. Позиционируется как более приватная альтернатива коммерческим сервисам Google Analytics и Matomo. Бесплатный лимит 6 месяцев хранения данных и 100тыс. просмотров в месяц.
  • Google Analytics, без комментариев
  • Expensify учёт расходов, контроль личных финансов
  • GetInsights система аналитики без куков, бесплатно до 5000 событий в месяц.
  • Heap автоматический трекинг действий пользователя в iOS или веб-приложениях. Бесплатно до 5000 визитов в месяц
  • Keen разнообразные инструменты для сбора данных, анализа и визуализации. Бесплатно до 50000 событий в месяц
  • Яндекс.Метрика российская альтернатива GA, но не лишённая недостатков последнего (в том числе угроза приватности со стороны материнской корпорации)
  • Mixpanel лимит 100000 пользователей в месяц, неограниченный срок хранения данных


    Mixpanel
  • Moesif аналитика API для REST и GraphQL, бесплатно до 500000 вызовов API в месяц
  • Molasses Флаги функций и A/B-тестирование, бесплатно до 3 окружений по 5 флагов функций в каждом.
  • Optimizely A/B-тестирование, бесплатный стартовый план на 1 сайт, 1 приложение iOS и 1 приложение Android
  • Quantcast новый сервис бесплатной аналитики, запущен в марте 2021 года, лимиты бесплатного тарифа официально не объявлены
  • Sematext бесплатно до 50тыс. действий в месяц, хранение данных 1 день
  • Tableau Developer Program бесплатная версия для разработчиков (предрелизная тестовая версия аналитической платформы)
  • UsabilityHub тестирование юзабилити и эффективности разных вариантов веб-дизайна. Бесплатные тесты до 2 минут
  • Woopra бесплатная платформа аналитики для любых продуктов, до 500тыс. действий в месяц, хранение данных до 90 дней

Другие категории



Эмулятор основных операционных систем в браузере copy.sh

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


Опенсорсные инструменты безопасности


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

Например, в нём есть системы для управления уязвимостями Faraday, Archery Sec, Jackhammer,
Watchdog и OpenVAS, сканер контейнеров trivy, менеджеры конфигурация вроде MGMT, Chef и Puppet, бесплатные системы SIEM (анализ событий в реальном времени и реагирование), VPN, инструменты для улучшения безопасности систем на Linux и Windows (Bastille, JShielder, nixarmor, Zeus (AWS), Docker-bench и др.), защита аутентификации в Linux, чёрные списки IP и доменов, прокси, socks-серверы, HTTP-туннели, FTP-прокси, DNS-прокси, инструменты сетевого и серверного мониторинга, системы для определения вторжений в сеть и на хост (NIDS и HIDS, соответственно), мониторинг и анализ логов, антивирусы, спам-фильтры, симуляторы инфраструктуры, файрволы для веб-приложений, сетевые сканеры, системы форензики (поиск цифровых улик), программы анализа файлов, метаданных, оперативной памяти и многие другие инструменты.

Всё бесплатно и с открытыми исходниками.

Бесплатные альтернативы на своём хостинге


Вышеупомянутый список free-for-dev не включает бесплатные инструменты на своём хостинге. Однако их очень много. Обычно это опенсорсные программы. Бывает, что какой-то коммерческий сервис SaaS одновременно публикует исходники, то есть предлагает параллельно платный и бесплатный тариф.

Вот список бесплатных альтернатив на своём хостинге в 81 категории из коллекции awesome-selfhosted:



Списки бесплатных ресурсов для разработчиков также ведутся в проектах FOSS-for-Dev, getAwesomeness и De-google-ify Internet.

Надеемся, что эта подборка окажется кому-то полезной.



Наша компания предлагает облачные серверы для любых задач и на любой операционной системе. Создавайте собственные конфигурации в течение минуты, минимальный тариф всего 6.5 рублей в день!
Зарегистрируйтесь по ссылке выше или кликнув на баннер и получите 10% скидку на первый месяц аренды сервера любой конфигурации!

Подробнее..

Работа с Google BigQuery. Считаем деньги

05.02.2021 12:22:10 | Автор: admin

Введение

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

Знакомство с BigQuery

BigQuery это бессерверное, масштабируемое облачное хранилище данных с мощной инфраструктурой от Google, которое имеет на борту RESTful веб-сервис. Имеет тесное взаимодействие с другими сервисами от Google. Создатели обещают молниеносное выполнение запросов с максимальной задержкой в RESTful до 1 секунды. BigQuery поддерживает диалект Standard SQL. Имеется возможность контроля доступа к данным и разграничение прав пользователей. Также есть возможность задавать квоты и лимиты для операций с БД.Доступ к BigQuery возможен через Google Cloud Console, с помощью внутренней консоли BigQuery, а также через вызовы BigQuery REST API как напрямую, так и через различные клиентские библиотеки java, python, .net и многие другие.

Есть возможность подключения через ODBC/JDBC-драйвер с помощью Magnitude Simba ODBC. В состав BigQuery входит довольно мощный визуальный SQL-редактор, в котором можно увидеть историю выполнения запросов, проанализировать потребляемый объём данных, не выполняя запрос, что позволяет существенно сэкономить финансы.

Ценообразование

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

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

  • обработка данных во время выполнения запросов.

Стоимость хранения зависит от объёма данных, хранящихся в BigQuery.

  • Active. Ежемесячная плата за данные, хранящиеся в таблицах или разделах, которые были изменены за последние 90 дней. Плата за активное хранение данных составляет 0,020$ за 1ГБ, первые 10ГБ бесплатно каждый месяц. Стоимость хранилища рассчитывается пропорционально за МБ в секунду.

  • Long-term. Плата за данные, хранящиеся в таблицах или разделах, которые не были изменены в течение последних 90 дней. Если таблица не редактируется в течение 90 дней подряд, стоимость хранения этой таблицы автоматически снижается примерно на 50%.

Что касается затрат на запрос, вы можете выбрать одну из двух моделей ценообразования:

  • On-demand. Цена зависит от объёма данных, обрабатываемых каждым запросом. Стоимость каждого терабайта обработанных данных составляет 5,00$. Первый обработанный 1 ТБ в месяц бесплатно, минимум 10 МБ обрабатываемых данных на таблицу, на которую ссылается запрос, и минимум 10 МБ обрабатываемых данных на запрос. Важный момент: оплата происходит за обработанные данные, а не за данные, полученные после выполнения запроса.

  • Flat-rate. Фиксированная цена. В данной модели выделяется фиксированная мощность на выполнение запросов. Запросы используют эту мощность, и вам не выставляется счёт за обработанные байты. Мощность измеряется в слотах. Минимальное количество слотов100. Стоимость за 100 слотов 2000$ в месяц.

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

  • Загрузка данных. Не нужно платить за загрузку данных из облачного хранилища или из локальных файлов в BigQuery.

  • Копирование данных. Не нужно платить за копирование данных из одной таблицы BigQuery в другую.

  • Экспорт данных. Не нужно платить за экспорт данных из других сервисов, например из Google Analytics (GA).

  • Удаление наборов данных (датасетов), таблиц, представлений, партиций и функций.

  • Операции с метаданными таблиц. Не нужно платить за редактирование метаданных.

  • Чтение данных из метатаблиц __PARTITIONS_SUMMARY__ и __TABLES_SUMMARY__.

  • Все операции UDF. Не нужно платить за операции создания, замены или вызова функций.

Wildcard-синтаксис

Wildcard-синтаксис позволяет выполнять запросы к нескольким таблицам, используя краткие операторы SQL. Wildcard-синтаксис доступен только в Standard SQL. Таблица с подстановочными знаками (wildcard) представляет собой объединение всех таблиц, соответствующих выражению с подстановочными знаками. Например, следующее предложение FROM использует выражение с подстановочными знаками table* для сопоставления всех таблиц в наборе данных test_dataset, которые начинаются со строки table:

FROM`bq.test_dataset.table*`

Запросы к таблице имеют следующие ограничения:

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

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

  • Запросы, содержащие операторы DML, не могут использовать wildcard-синтаксис в таблицах в качестве цели запроса. Например, wildcard-синтаксис для таблиц может использоваться в предложении FROM запроса UPDATE, но не может использоваться в качестве цели операции UPDATE.

Wildcard-синтаксис для таблиц полезен, когда набор данных содержит несколько таблиц с одинаковыми именами, которые имеют совместимые схемы. Обычно такие наборы данных содержат таблицы, каждая из которых представляет данные за один день, месяц или год. Такой синтаксис полезен для сегментированных таблиц (sharded tables) не путать с партиционированными таблицами.

Примеры использования:
Допустим, в BQ существуют набор данных test_dataset c таблицами, которые сегментированы по датам: test_table_20200101 test_table_20200102 ... test_table_20201231
Выборка всех записей за дату 2020-01-01:

select * from test_dataset.test_table_20200101

Выборка всех записей за месяц:

select * from test_dataset.test_table_202001*

Выборка всех записей за год:

select * from test_dataset.test_table_2020*

Выборка всех записей за весь период:

select * from test_dataset.test_table_*

Выборка всех записей из всего набора данных:

select * from test_dataset.*

Для ограничения запроса таким образом, чтобы он просматривал произвольный набор таблиц, можно использовать псевдостолбец _TABLE_SUFFIX в предложении WHERE. Псевдостолбец _TABLE_SUFFIX содержит значения, соответствующие подстановочному знаку *. Например, чтобы получить все данные за 1 и 5 января, можно выполнить следующий запрос:

select * from test_dataset.test_table_202001* where _TABLE_SUFFIX="01" and _TABLE_SUFFIX="05"

Партиционирование и шардирование таблиц

Партиционная таблица в BQ (partitioned table) таблица, которая разделяется на сегменты (секции) по определённому признаку.Таблицы BigQuery можно разбивать на разделы по следующим признакам:

  • Ingestion Time. Таблицы разбиваются на разделы в зависимости от времени загрузки или времени поступления данных, которые содержат дополнительные зарезервированные поля _PARTITIONTIME, _PARTITIONDATE, хранящие дату создания записи.

  • Date/timestamp/datetime. Таблицы разбиты на разделы на основе столбца с типом timestamp, date или datetime. Если таблица партиционирована по столбцу с типом DATE, вы можете создавать партиции с ежедневной, ежемесячной или ежегодной гранулярностью. Каждый раздел содержит диапазон значений, где начало диапазона это начало дня, месяца или года, а интервал диапазона составляет один день, месяц или год в зависимости от степени детализации разделения. Если таблица партиционирована по столбцам с типом TIMESTAMP или DATETIME, вы можете создавать разделы с любым типом гранулярности в единицах времени, включая HOUR.

  • Integer range. Таблицы разделены по целочисленному столбцу. BigQuery позволяет разбивать таблицы на разделы на основе определённого столбца INTEGER с указанием значений начала, конца и интервала. Запросы могут указывать фильтры предикатов на основе столбца секционирования, чтобы уменьшить объём сканируемых данных.

Шард-таблица в BQ (sharded table) совокупность таблиц, имеющих одну схему и сегментированных по датам. Другими словами, под шард-таблицами понимается разделение больших наборов данных на отдельные таблицы и добавление суффикса к имени каждой таблицы. Имена таблиц имеют шаблон tablename_YYMMDD, где YYMMDD шаблон даты. В отличие от партиционированных таблиц, шард-таблица не имеет колонки, по которой будет происходить сегментация данных. Обращение к шард-таблицам возможно с помощью синтаксиса wildcard-table. Шард-таблицы и запрос к ним с помощью оператора UNION могут имитировать партиционирование.

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

Кластеризация таблиц

Когда вы создаёте кластеризованную таблицу в BigQuery, данные таблицы автоматически сортируются на основе содержимого одного или нескольких столбцов в схеме таблицы. Указанные столбцы используются для размещения связанных данных. При кластеризации таблицы с использованием нескольких столбцов важен порядок указанных столбцов. Порядок указанных столбцов определяет порядок сортировки данных. Кластеризация может улучшить производительность определённых типов запросов, таких как запросы, использующие предложения фильтра, и запросы, которые объединяют данные. Когда данные записываются в кластеризованную таблицу, BigQuery сортирует данные, используя значения в столбцах кластеризации. Когда вы выполняете запрос, содержащий в фильтре данные на основе столбцов кластеризации, BigQuery использует отсортированные блоки, чтобы исключить сканирование ненужных данных. Вы можете не увидеть значительной разницы в производительности запросов между кластеризованной и некластеризованной таблицей, если размер таблицы или раздела меньше 1 ГБ.

Пример из жизни. Работа с GDPR

Нам пришлось столкнуться с задачей анонимизации данных по регламенту GDPR для Google Analytics (GA) в BigQuery. Задача заключалась в том, что каждый день в BigQuery импортировались данные из Google Analytics (GA). Поскольку в GA хранились персональные данные пользователей, для удалённых пользователей необходимо было очищать персональную информацию по регламенту GDPR. Данные, которые необходимо было анонимизировать, находились в поле с типом array. Аккаунт BigQuery, который нам предоставили, работал с ценовой моделью On-demand, в которой стоимость рассчитывалась из обработанных данных каждого запроса. Данные хранились в шард-таблицах. Google не рекомендует использовать шардированные таблицы и предлагает взамен партиционирование + кластеризацию, но, к сожалению, в Google Analytics (GA) это стандартная структура хранения данных. При экспорте данных из Google Analytics в BQ создаётся шард-таблица ga_sessions_, сегментированная по датам. В таблице находится порядка 16 полей, для нашей задачи необходимы были поля:

  • fullVisitorId (string) уникальный идентификатор посетителя GA (также известный как идентификатор клиента)

  • customDimensions (array) поле с типом array, содержит пользовательские данные, которые устанавливаются для каждого сеанса пользователя.

В поле customDimensions хранятся значения (идентификаторы), которые нам необходимо анонимизировать. Значения хранятся под определёнными индексами в массиве customDimensions.

Решение задачи

Мы создали в BQ таблицу opted_out_visitors для хранения пользователей, информацию о которых необходимо анонимизировать.

Схема таблицы:

[    {        "name": "fullVisitorId",        "type": "STRING",        "mode": "NULLABLE"    },    {        "name": "date",        "type": "STRING",        "mode": "NULLABLE"    },    {        "name": "customDimensions",        "type": "RECORD",        "mode": "REPEATED",        "fields": [            {                "name": "index",                "type": "INTEGER"            },            {                "name": "value",                "type": "STRING"            }        ]    }]

В данной таблице мы храним копию данных из ga_sessions_, которые подпадают под регламент GDPR.

При получении запроса на удаление пользователя в нашей системе мы находили в таблицах GA данные пользователя для анонимизации и добавляли значения в таблицу opted_out_visitors:

INSERT INTO `dataset`.opted_out_visitors (SELECT fullVisitorId, date, customDimensionsFROM `dataset`.`ga_sessions_*`, UNNEST(customDimensions) AS cdWHERE cd.index=11 and cd.value="1111111")

где cd.index=11 индекс массива customDimensions, в котором хранятся идентификаторы пользователя, а cd.value="1111111" идентификатор пользователя, данные которого необходимо почистить в таблицах GA. Собственно, в данной таблице мы имеем идентификатор пользователя в сеансе GA (fullVisitorId), данные пользователя (customDimensions) для анонимизации и дату, когда пользователь оставил за собой следы. После добавления данных в таблицу opted_out_visitors чистим значение, которое необходимо заменить.

UPDATE `dataset`.`opted_out_visitors`SET customDimensions = ARRAY(  SELECT (index, IF(index = 3, "GDPR", value))   FROM UNNEST(customDimensions))where 1=1

Осталось почистить значения в оригинальных таблицах GA. Для этого мы раз в 7 дней запускаем скрипт, который обновляет данные в ga_sessions для каждой даты в opted_out_visitors:

MERGE `dataset`.`ga_sessions_20200112` SUSING `dataset`.`opted_out_visitors` OON S.fullVisitorId = O.fullVisitorIdWHEN MATCHED and O.date='20200112' THENUPDATE SET S.customDimensions = O.customDimensions

После этого очищаем таблицу opted_out_visitors.

Многие читатели могут подумать, зачем так запариваться, создавать отдельную таблицу opted_out_visitors, хранить там идентификаторы из ga_sessions с анонимизированными данными, а потом всё это мержить раз в N дней. Дело в том, что каждая таблица ga_sessions занимает около 10 ГБ, и с каждым днём количество таблиц увеличивалось. Если бы мы выполняли анонимизацию данных каждый раз при поступлении запроса на удаление, мы получили бы огромные затраты в BigQuery. Но и с данным подходом нам не удалось добиться минимальных затрат. После анализа всех запросов мы выявили, что проблемным местом является запрос поиска анонимных данных и добавления в таблицу opted_out_visitors.

INSERT INTO `dataset`.opted_out_visitors (SELECT   fullVisitorId,   date,   customDimensionsFROM   `dataset`.`ga_sessions_*`,   UNNEST(customDimensions) AS cdWHERE cd.index=11 and cd.value="1111111")

В данном запросе мы обращаемся к таблице ga_sessions_ за весь период, откуда получаем данные из столбца customDimensions (напомним, что этот столбец имеет тип array, который может хранить в себе любой объём данных). В итоге один запрос весил около 40 ГБ, так как BigQuery сканировал все таблицы ga_sessions_ и искал информацию в столбце customDimensions. Таких запросов в день было 5080. Таким образом, меньше чем за день мы тратили весь бесплатный месячный трафик (1 ТБ).

Оптимизация

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

[    {        "name": "user_id",        "type": "STRING",        "mode": "REQUIRED",    },    {        "name": "anonymized_id",        "type": "STRING",        "mode": "REQUIRED",    }]

Каждый раз, когда к нам приходит запрос на удаления пользователя, в opted_out_users_id мы добавляем user_id и anonymized_id

INSERT INTO `dataset`.opted_out_users_id (user_id, anonymized_id) SELECT     user_id, anonymized_id FROM     (select '{user_id}' as user_id, '{anonymized_id}' as anonymized_id) WHERE     NOT (EXISTS (         SELECT 1         FROM `dataset`.opted_out_users_id         WHERE `dataset`.opted_out_users_id.user_id = '{user_id}'        )     )

Теперь при добавлении новой записи в opted_out_users_id мы тратим около 15 КБ, что значительно меньше, чем когда мы работали напрямую со столбцом customDimensions.Далее, раз в 7 дней нам необходимо запускать скрипт, который будет анонимизировать необходимые значения в ga_sessions_. Так как ga_sessions_ это шард-таблицы, сегментированные по датам, мы не можем обратиться к таблицам через wildcard-синтаксис ga_sessions_* в операторах UPDATE, INSERT, MERGE. Придётся найти даты, где удалённые пользователи были замечены, и далее обращаться напрямую к каждой таблице ga_sessions_{date}. Для этого перед анонимизацией данных мы находим все даты, где фигурируют удалённые пользователи.

SELECT ga.date,   ARRAY_AGG(DISTINCT oous.user_id) AS accountsFROM `dataset.opted_out_users_id` AS oousLEFT JOIN (  SELECT     `dataset.ga_sessions_*`.date, cd.index AS index,     cd.value AS value    FROM `dataset.ga_sessions_*`,        unnest(`dataset.ga_sessions_*`.customDimensions) AS cd  ) AS ga ON oous.user_id = ga.value AND ga.index = 3GROUP BY ga.date

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

UPDATE `dataset`.`ga_sessions_{date}` as gaSET customDimensions=ARRAY(  SELECT (   index,    CASE      WHEN index = {lookup_field} THEN      ac.anonymized_id      WHEN index in cleanup_fields THEN       null      else       value      end  )  FROM unnest(ga.customDimensions))FROM  `dataset`.`opted_out_users_id` as acWHERE ac.user_id=(  SELECT value   FROM unnest(ga.customDimensions) WHERE index=3)

В данном запросе для удалённых пользователей в столбце customDimensions производим замену user_id на anonymize_id, которые расположены в индексе с номером lookup_field, а для остальных индексов, которые расположены в cleanup_fields, чистим значения, устанавливая для них null. Запрос потребляет около 7 ГБ трафика, что также приемлемо для нас. В итоге в сумме все наши запросы не выходят за рамки бесплатного лимита 1 ТБ в месяц.

Итоги

Хочется сказать в конце, что BigQuery вполне достойное облачное хранилище данных. Для хранения небольшого количества данных можно уложиться в бесплатный лимит, но если ваши данные будут насчитывать терабайты и работать с данными вы будете часто, то и затраты будут высокими. С первого взгляда кажется, что 1 ТБ в месяц для запросов это очень много, но подводный камень кроется в том, что BigQuery считает все данные, которые были обработаны во время выполнения запроса. И если вы работаете с обычными таблицами и попытаетесь выполнить какое-либо усечение данных в виде добавления WHERE либо LIMIT, то с грустью говорим вам, что BigQuery израсходует такой же объём трафика, как и при обычном запросе SELECT FROM. Однако если грамотно построить структуру вашей БД, вы сможете колоссально сэкономить свой бюджет в BigQuery.

Наши рекомендации:

  • Избегайте SELECT *.
    Делайте запросы всегда только к тем полям, которые вам необходимы.

  • Избегайте в таблицах полей с типами данных record, array (repeated record).
    Запросы, в которых присутствуют данные столбцы, будут потреблять больше трафика, т. к. BigQuery придётся обработать все данные этого столбца.

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

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

  • Для подсчёта обработанных данных всегда используйте Cloud Console BigQuery.
    Когда вы вводите запрос в Cloud Console, валидатор запроса проверяет синтаксис запроса и предоставляет оценку количества прочитанных байтов. Эту оценку можно использовать для расчёта стоимости запроса в калькуляторе цен.

  • Используйте калькулятор для оценки стоимости хранения данных и выполнения запросов: https://cloud.google.com/products/calculator/.
    Для оценки стоимости запросов в калькуляторе необходимо ввести количество байтов, обрабатываемых запросом, в виде Б, КБ, МБ, ГБ, ТБ. Если запрос обрабатывает менее 1 ТБ, оценка составит 0 долларов, поскольку BigQuery предоставляет 1 ТБ в месяц бесплатно для обработки запросов по требованию. Аналогичные действия можно выполнить и для оценки хранения данных.

Подробнее..

Работа с dbt на базе Google BigQuery

11.02.2021 18:04:31 | Автор: admin

На днях смотрел вебинар OWOX, где Андрей Осипов (веб-аналитик, автор блога web-analytics.me и лектор Школы веб-аналитики Андрея Осипова) рассказал о своем опыте использования dbt. Говорил о том, кому будет полезен инструмент и какие проблемы решает, а самое главное как не свихнуться со сложной иерархией таблиц и быть уверенным, что все данные считаются корректно. Я решил расшифровать вебинар в статью, потому что так удобнее возвращаться к информации, а она тут, поверьте, того стоит.

Зачем нужен dbt

Зачем нужен еще один инструмент для управления SQL-запросами? Ведь у нас есть Google BigQuery, и вообще в Google Cloud много различных механизмов, которые могут решать задачи по формированию таблиц, например scheduled queries.

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

Но если мы говорим о реальном проекте, то все может выглядеть как на картинке ниже.

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

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

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

При такой сложной структуре стандартные механизмы управления (типа scheduled queries) не подходят по нескольким причинам:

  1. Зависимости. Каждый scheduled query нужно запускать в определенное время, то есть у вас должна быть четкая иерархия запуска расчета таблиц. Нельзя, чтобы результирующая таблица считалась раньше, чем исходная. К примеру, в 5 утра у вас формируется отчет. После этого происходит какой-то сбой, и только в 7 утра данные о нем попадают в исходную таблицу. В результате вы теряете данные за вчера и нужно пересчитывать весь проект. А если у вас десятка два-три запросов, то пересчет займет минут 40.

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

  3. Тестирование. Данные, которые попадают в исходные таблицы, не всегда корректны, а в Google BigQuery нет встроенных инструментов для их тестирования. Например, у вас была таблица с заказами. Потом в нее добавили рейтинг, который пользователи могут менять. Из-за этого могут дублироваться транзакции. То есть в таблице будет две записи с одинаковой транзакцией, но с разными timestamp и рейтингами.

  4. Много одинаковых кусков SQL. Когда у вас несколько финальных таблиц, которые генерируются из базовых, одни и те же агрегации происходят много раз. Это сильно увеличивает стоимость использования BigQuery. На нашем вебинаре Андрей Осипов поделился примером, как с помощью dbt ему удалось снизить стоимость использования GBQ в 20 раз для одного из проектов, с которым он работал. Только за счет того, что обращение к базовой таблице с событиями происходило всего один раз.

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

Что такое dbt (data build tool)

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

Как выглядит процесс обработки данных:

Схема из презентации dbt.

На схеме мы видим:

  1. Источники данных.

  2. Сервисы, которые достают данные из этих источников и складывают в хранилище. Это могут быть Cloud Functions, Cloud Run, OWOX BI Pipeline и др.

  3. Хранилище, куда мы складываем данные и где потом их нужно преобразовать: объединить с другими данными, проверить, валидировать.

  4. После обработки мы можем отправлять данные в инструменты визуализации, BI-системы или использовать как-либо еще.

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

Структура dbt

Фактически dbt состоит из двух сущностей: модель и файл конфигурации.

Модель это сам запрос, то есть отдельный файл, на базе которого будут формироваться view или table.

Модель (.sql) единица трансформации, выраженная SELECT-запросом.

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

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

Файл конфигурации (.yml) параметры, настройки, тесты, документация.

dbt CLI

dbt поставляется в двух версиях: консоль и cloud. То есть инструмент может быть как локальным, так и размещаться в Google Cloud и быть полноценным микросервисом.

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

Также у вас есть возможность привязать свой dbt проект к Cloud Source Repositories или GitHub. То есть фактически все будет вертеться вокруг вашего cloud-проекта, и сам dbt будет там работать.

Как работать с dbt консолью:

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

  • После этого используете команду git push для выгрузки содержимого локального репозитория в удаленный репозиторий. И сам dbt с вашими новыми моделями через Cloud Build билдятся в новый контейнер и запускаются.

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

dbt Cloud

Если использовать консоль для вас сложно или нецелесообразно, вы можете попробовать dbt Cloud. По сути это веб-интерфейс той же самой консоли. Простой сайт, на котором можно вносить правки в свои модели, добавлять макросы. Вы можете запускать как весь проект, так и отдельные модели. Здесь же хостится документация по проекту. Регистрация для первого пользователя бесплатна, для каждого следующего $50 в месяц.

Функционал dbt

Зависимости (Refs)

О них мы говорили в начале статьи у вас должна быть четкая иерархия запуска расчета таблиц. dbt позволяет указывать эти зависимости прямо внутри каждого запроса. На базе этих зависимостей, во-первых, происходит расчет подряд необходимых табличек, а во-вторых, строится прямой асинхронный граф (Directed Acyclic Graph).

Прямой асинхронный граф (Directed Acyclic Graph)

Это часть документации, которая также формируется самим dbt. Благодаря этому графу вы можете посмотреть, как именно формируются ваши таблицы. Этого, конечно, очень не хватает в Google BigQuery. Потому что, если в вашем проекте больше 2-3 датасетов с несколькими таблицами, довольно сложно разобраться, как они все формируются.

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

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

Шаблоны (Loops)

Вторая полезная вещь это использование Jinja. Это такой язык шаблонов. Шаблонизатор, в котором есть циклы, переменные и все остальное. Их можно указывать для похожих сущностей.

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

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

Переменные (Variables)

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

Макросы (Macros)

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

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

Пакеты макросов

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

Materializations

Еще одна полезная функция, которая значительно экономит ресурсы.

Допустим, вы не используете dbt. Когда вы обращаетесь в BigQuery к своей партиционной таблице, например делаете select * from [название вашей таблицы], то вы обращаетесь ко всему датасету. Если у вас немного трафика, GA 4 или стриминг OWOX BI настроены недавно, то вы обработаете небольшое количество данных. Если же у вас много данных и большие таблицы, то каждый такой запрос будет дорого стоить.

По факту инкрементальная модель dbt позволяет вам сначала удалять данные в формируемой таблице (например, по дате или по order_id), а потом записывать новые.

Например, в GA 4 данные за вчера, которые образовались в табличке events, еще не полностью готовы. Если вы посмотрите на логи, то вы увидите, что система перезатирает данные. Она формирует из таблицы intraday таблицу events и перезаписывает данные еще на два дня назад.

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

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

Тесты

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

Примеры тестов, которые можно проводить в dbt:

  • Not Null.

  • Unique.

  • Reference Integrity ссылочная целостность (например, customer_id в таблице orders соответствует id в таблице customers).

  • Соответствие списку допустимых значений.

  • Custom data tests.

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

Документация

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

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

DEV TEST PROD

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

Подключение Git

Вы можете подключить к своему dbt проекту любой Git, например GitHub или Google Cloud Source Repositories, и полноценно управлять всеми моделями, которые у вас есть.

Логгинг через вебхуки (Logging via webhooks)

Вы можете складывать результаты тестов и расчетов в какой-нибудь pop-up и потом отправлять через Google Cloud, куда вам надо. Или складывать их в отдельную таблицу GBQ и выводить визуализацию, как все посчиталось.

Как использовать dbt

dbt Сloud

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

Также здесь есть schedule, с помощью которого можно задать периодичность расчета данных.

Google Cloud Cloud Shell

Еще один вариант использования dbt. В Google Cloud есть такой инструмент, как Cloud Shell. Если вы его откроете, то фактически окажетесь внутри apenjin. То есть у вас есть возможность развернуть dbt не в доке, а прямо в apenjin.

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

Google Cloud Cloud Run

Схема работы с dbt, Google Cloud и Cloud Run выглядит примерно так:

  1. В Atom или другом редакторе вносим правки, делаем для новых правок отдельные бренчи.

  2. После этого коммитим изменения и пушим в Cloud репозиторий.

  3. По факту пуша через Cloud Build формируется новая версия нашего Cloud Run и запускается через Cloud Scheduler по необходимому расписанию.

  4. Как результат работы dbt, который находится в Cloud Run, все это рассчитывается в BigQuery, откуда идет уже в Data Studio.

  5. Логи можно складывать через pop-up в Telegram по определенным правилам например, пушить не все, а только какие-то важные изменения.

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

Подробнее..

Виртуальные машины А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 бесплатных продуктов доступны всегда. Подробнее поспециальной ссылке.

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

Подробнее..

Пишем Telegram Bota для оповещения о коммите в git репозитарий на базе Gitea и разворачиваем его в Google Cloud Platform

27.01.2021 20:23:33 | Автор: admin

Здравствуйте как и обещал в продолжение моей статьи о Автоматической публикации приложения в Google Play , рассмотрю в деталях процесс написания Telegram Bot`a для оповещения команды тестировщиков о выпуске новой версии.

Регистрация Bota в Telegram и получение ID

Просто напишите пользователю@BotFatherиследуйте его инструкциям.

Выполните последовательно следующий команды

/start/newbotbot_name
В итоге вы должны получить сообщение

Из этого сообщение нам понадобятся собственно

  • t.me/bot_name - Имя бота по которому мы будем добавлять его в каналы или писать в ЛС

  • token - это наш ключ для доступа к API

Подготовка проекта и подключение необходимых библиотек

Наш бот будет написан на Java и будет представлять из себя Spring Boot Web приложение, в качестве системы сборки будет использоваться maven

1) Создайте обычный Spring Boot проект, проще всего это сделать через встроенный конфигуратор в IntelliJ IDEA , либо используя Spring Initializr.

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

pom.xml
    <parent>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-parent</artifactId>        <version>2.1.6.RELEASE</version>        <relativePath/> <!-- lookup parent from repository -->    </parent>    <properties>        <java.version>1.8</java.version>    </properties>    <dependencies>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-test</artifactId>            <scope>test</scope>        </dependency>        <dependency>            <groupId>org.telegram</groupId>            <artifactId>telegrambots</artifactId>            <version>5.0.0</version>        </dependency>        <dependency>            <groupId>com.google.code.gson</groupId>            <artifactId>gson</artifactId>            <version>2.8.6</version>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-configuration-processor</artifactId>            <optional>true</optional>        </dependency>        <dependency>            <groupId>org.projectlombok</groupId>            <artifactId>lombok</artifactId>            <optional>true</optional>        </dependency>    </dependencies>    <build>        <plugins>            <plugin>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-maven-plugin</artifactId>            </plugin>        </plugins>    </build>
Минимальный проект будет иметь примерно такую структуру :

А теперь детальней по каждому классу :

BotConfig - Конфигурация подтягивающая настройки бота из application.properties
@Configuration@Data@PropertySource("classpath:application.properties")public class BotConfig {    // Имя бота заданное при регистрации    @Value("${botUserName}")    String botUserName;    // Токен полученный при регистрации    @Value("${token}")    String token;}
BotInitializer - Component регистрации/инициализации бота в системе Telegram
@Component@Slf4jpublic class BotInitializer {    @Autowired    Bot bot;    @EventListener({ContextRefreshedEvent.class})    public void Init() throws TelegramApiException {        TelegramBotsApi telegramBotsApi = new TelegramBotsApi(DefaultBotSession.class);        try {            telegramBotsApi.registerBot(bot);        } catch (TelegramApiRequestException e) {            log.error(exceptionStackTraceToString(e));        }    }}

Телеграм API должно быть зарегистрировано в системе и делать это нужно уже после поднятия контекста Spring, по этому вешаем слушатель на ContextRefreshedEvent

Bot - Сервис инкапсулирующий в себе реализацию TelegramLongPollingBot,
@Component@Slf4j/** * Касс является основным пулом взаимодействия с Telegram * получение, обработка, отправка сообщений */public class Bot extends TelegramLongPollingBot {    final    BotConfig config;    public Bot(BotConfig config) {        this.config = config;    }    public void onUpdateReceived(Update update) {        update.getUpdateId();        SendMessage.SendMessageBuilder builder =SendMessage.builder();        String messageText;        String chatId;        if (update.getMessage() != null) {            chatId = update.getMessage().getChatId().toString();            builder.chatId(chatId);            messageText = update.getMessage().getText();        } else {            chatId = update.getChannelPost().getChatId().toString();            builder.chatId(chatId);            messageText = update.getChannelPost().getText();        }        if (messageText.contains("/hello")) {            builder.text("Привет");            try {                execute(builder.build());            } catch (TelegramApiException e) {                log.debug(e.toString());            }        }        if (messageText.contains("/chartId")) {            builder.text("ID Канала : " + chatId);            try {                execute(builder.build());            } catch (TelegramApiException e) {                log.debug(e.toString());            }        }    }    public String getBotUsername() {        return config.getBotUserName();    }    public String getBotToken() {        return config.getToken();    }}

Данный класс представляет из себя основной функционал для взаимодействия с Telegram

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

WebHook - RestController обслуживающий API для реакции на события WebHook Gitea
@Slf4j@RestController@RequestMapping("/api/public/gitea")@RequiredArgsConstructor@PropertySource("classpath:application.properties")public class WebHook {    Bot bot;    // Канал в который будем слать уведомления    @Value("${chartId}")    String chartId;    // Секретный ключ который придёт в нутри JSON от Gitea,    // что бы левые люди не имели доступа к боту т.к. API публичное без авторизации    @Value("${secret}")    String secret;    @Autowired    public WebHook(Bot bot) {        this.bot = bot;    }    @PostMapping(value = "/webhook")    public ResponseEntity<?> webhook(@RequestBody String json){        Gson gson = new Gson();        GiteaWebHook giteaWebHook = null;        try {            giteaWebHook = gson.fromJson(json, GiteaWebHook.class);        } catch (JsonSyntaxException e) {            log.error(Utils.exceptionStackTraceToString(e));            return new ResponseEntity<>(Utils.exceptionStackTraceToString(e), HttpStatus.BAD_REQUEST);        }        if (validationWebHookContent(giteaWebHook)) {            SendMessage.SendMessageBuilder messageBuilder =SendMessage.builder();            messageBuilder.chatId(chartId);            messageBuilder.parseMode(ParseMode.HTML);            StringBuilder builder = new StringBuilder();            builder.append("<b>Проект</b> : " + giteaWebHook.getRepository().getName()+"\n");            for (Commit commit : giteaWebHook.getCommits()) {             builder.append("<b>Автор</b> : " + commit.getAuthor().getName()+"\n");             builder.append("<b>Комментарий</b> : " + commit.getMessage()+"\n");            }            builder.append("<a href=\"https://play.google.com/store/apps/details?id=URL_ВАШЕГО_ПРИЛАЖЕНИЯ\">Обновление будет доступно в Play Market через пару минут</a>\n");            messageBuilder.text(buildToCorrectString(builder));            try {                bot.execute(messageBuilder.build());            } catch (TelegramApiException e) {                log.error(Utils.exceptionStackTraceToString(e));                return new ResponseEntity<>(Utils.exceptionStackTraceToString(e), HttpStatus.INTERNAL_SERVER_ERROR);            }        } else return new ResponseEntity<>(HttpStatus.BAD_REQUEST);        HttpHeaders headers = new HttpHeaders();        headers.add("Content-Type", "application/json; charset=utf-8");        return new ResponseEntity<>(headers, HttpStatus.OK);    }    /**     * Проверка пришедших JSON данных на валидность     * @param giteaWebHook - GiteaWebHook     * @return true - если не null, PUSH в master, совпал секретный ключ     */    private boolean validationWebHookContent(GiteaWebHook giteaWebHook){        return giteaWebHook != null && // Если вообще что то есть               giteaWebHook.getRef().contains(giteaWebHook.getRepository().getDefaultBranch()) && // Есть был PUSH в /master               giteaWebHook.getSecret().equals(secret); // Если совпал секретный ключ    }    private String buildToCorrectString(StringBuilder builder){        return builder.toString()                .replace("_", "\\_")                .replace("*", "\\*")                .replace("[", "\\[")                .replace("`", "\\`")                .replace("&nbsp;", " ")                .replace("&frac", " ")                .replaceAll(" \\u003c","");    }}

Данный RestController обслуживает RestAPI с точкой входа http://you_ip:port/api/public/gitea/webhook , сюда наша система контроля версий Gitea будет делать PUSH запрос с JSON данными WebHook возникающего при различных событиях происходящих с вашим репозитарием.

TelegramBotGiteaApplication - Стартовый метод нашего Spring Boot проекта
@SpringBootApplication@AutoConfigurationPackagepublic class TelegramBotGiteaApplication extends SpringBootServletInitializer {    public static void main(String[] args) {        new SpringApplicationBuilder(TelegramBotGiteaApplication.class)                .run(args);    }}

Все те классы что вы наблюдаете в пакете Model , представляют сгенерированную модель GiteaWebHook по JSON-Schema взятому из оф документации по GiteaWebHookApi , удобнее всего это делать при помощи http://www.jsonschema2pojo.org/

Полный исходный код вы можете взять ЗДЕСЬ

Настройка Gitea для выполнения WebHook к нашему боту

Данная статья рассматривает вариант обслуживания API предоставляемое системой контроля версий Gitea но это не значит что вы не сможете сделать оповещение и без неё. Проявив некую долю усердия всё те-же WebHook можно реализовать через .git\hooks\post-update и curl , или некое API GitHub но эти реализации я доверяю вам, и здесь мы рассмотрим лишь вариант с Gitea

1) И так, перейдите в репозитарий вашего проекта и войдите в его Настройки в раздел Автоматическое обновление . Нажмите на кнопку Добавить Webhook , выберете вариант Gitea

2) В качестве URL обработчика укажите URL на котором у нас висит RestController http://you_ip:port/api/public/gitea/webhook

3) Тип содержимого - application/json

3) Секретный ключ - любой набор символов который мы в последующем внесём в наш application.properties

4) На какие события этот webhook должен срабатывать? - выберите PUSH

5) Галочку Активности оставьте включённой.

Всё это хорошо бот написан, Gitea настроена но нашему боту нужно где-то жить.

Публикация нашего бота в Google Cloud Platform, бесплатно

New customers get $300 in free credits to spend on Google Cloud. All customers get free usage of 20+ products.See offer details.

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

И так приступим, авторизуйтесь в Google Cloud Platform

1) В боковом меню перейдите в раздел Сompute Engine, и дождитесь его инициализации

2) В разделе Экземпляры ВМ, нажмите создать

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

Давайте зададим сразу правило Брандмауэра разрешающего трафик по порту 8080

Зайдите Cеть VPS - Брандмауэр

Создайте правило для порта 8080 по аналогии с 80 портом

Подключитесь к VM через SSH , непосредственно через браузер

Теперь мы может перейти к настройке нашей виртуальной машины

Для обновления информации об новейших версиях пакетов вводим

sudo apt update

Установим Java

sudo apt install default-jdk

Проверьте это выполнив

java - version

Если всё прошло хорошо вы должны наблюдать версию Java в консоли SSH

Теперь установим maven

sudo apt install maven

Сделаем clone репозитария с нашим ботом заготовкой

git clone https://legan.by/gitea/leganas/TelegramBotGiteaLesson.git

Сделайте необходимые манипуляции по настройке appliation.properties , укажите валидный bot_name и token

nano ./TelegramBotGiteaLesson/src/main/resources/application.properties

Зайдём в папку с нашим ботом и соберём его при помощи maven

cd TelegramBotGiteaLesson/mvn package

После того как maven соберёт наш проект

Бот полностью готов к запуску, выполните команду

java -jar ./target/telegrambotgitea-0.0.1-SNAPSHOT.jar

Используя внешний IP указанный в web консоли управления виртуальными машинами, проверьте его работоспособность открыв в браузере страницу http://YOU_IP:8080/

Если наш бот успешно подключился к Telegram мы можем написать ему проверочное сообщение в ЛС /hello , на что он должен ответить нам Привет

И так теперь у нас всё готово для того что бы добавить нашего бота в Telegram канал, дать ему права администратора (что бы он мог читать сообщения) и протестировать оповещение !

Добавил бота в канал и дав ему права , вы можете написать

/chartId

Теперь это ID можно добавить в application.properties и либо пересобрать проект , либо подкинуть этот файл рядом с jar. Внесите необходимые правки IP адреса в WebHook в настройках Gitea и опробуйте вашего бота.

У кого получилось вот так , тот молодец, о том как сделать jar сервисом писать уже не буду, уж очень много про это написано на хабре, а если не найдёте пишите в личку.

Надеюсь моё повествование было достаточно подробным что бы любой смог запустить свою зверушку. :)

Подробнее..
Категории: Git , Devops , Java , Telegram , Google cloud platform , Gtea

Пишем Telegram Bot для оповещения о коммите в git репозитарий на базе Gitea и разворачиваем его в Google Cloud Platform

27.01.2021 22:06:12 | Автор: admin

Здравствуйте как и обещал в продолжение моей статьи о Автоматической публикации приложения в Google Play , рассмотрю в деталях процесс написания Telegram Bot`a для оповещения команды тестировщиков о выпуске новой версии.

Регистрация Bota в Telegram и получение ID

Просто напишите пользователю@BotFatherиследуйте его инструкциям.

Выполните последовательно следующий команды

/start/newbotbot_name
В итоге вы должны получить сообщение

Из этого сообщение нам понадобятся собственно

  • t.me/bot_name - Имя бота по которому мы будем добавлять его в каналы или писать в ЛС

  • token - это наш ключ для доступа к API

Подготовка проекта и подключение необходимых библиотек

Наш бот будет написан на Java и будет представлять из себя Spring Boot Web приложение, в качестве системы сборки будет использоваться maven

1) Создайте обычный Spring Boot проект, проще всего это сделать через встроенный конфигуратор в IntelliJ IDEA , либо используя Spring Initializr.

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

pom.xml
    <parent>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-parent</artifactId>        <version>2.1.6.RELEASE</version>        <relativePath/> <!-- lookup parent from repository -->    </parent>    <properties>        <java.version>1.8</java.version>    </properties>    <dependencies>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-test</artifactId>            <scope>test</scope>        </dependency>        <dependency>            <groupId>org.telegram</groupId>            <artifactId>telegrambots</artifactId>            <version>5.0.0</version>        </dependency>        <dependency>            <groupId>com.google.code.gson</groupId>            <artifactId>gson</artifactId>            <version>2.8.6</version>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-configuration-processor</artifactId>            <optional>true</optional>        </dependency>        <dependency>            <groupId>org.projectlombok</groupId>            <artifactId>lombok</artifactId>            <optional>true</optional>        </dependency>    </dependencies>    <build>        <plugins>            <plugin>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-maven-plugin</artifactId>            </plugin>        </plugins>    </build>
Минимальный проект будет иметь примерно такую структуру :

А теперь детальней по каждому классу :

BotConfig - Конфигурация подтягивающая настройки бота из application.properties
@Configuration@Data@PropertySource("classpath:application.properties")public class BotConfig {    // Имя бота заданное при регистрации    @Value("${botUserName}")    String botUserName;    // Токен полученный при регистрации    @Value("${token}")    String token;}
BotInitializer - Component регистрации/инициализации бота в системе Telegram
@Component@Slf4jpublic class BotInitializer {    @Autowired    Bot bot;    @EventListener({ContextRefreshedEvent.class})    public void Init() throws TelegramApiException {        TelegramBotsApi telegramBotsApi = new TelegramBotsApi(DefaultBotSession.class);        try {            telegramBotsApi.registerBot(bot);        } catch (TelegramApiRequestException e) {            log.error(exceptionStackTraceToString(e));        }    }}

Телеграм API должно быть зарегистрировано в системе и делать это нужно уже после поднятия контекста Spring, по этому вешаем слушатель на ContextRefreshedEvent

Bot - Сервис инкапсулирующий в себе реализацию TelegramLongPollingBot,
@Component@Slf4j/** * Касс является основным пулом взаимодействия с Telegram * получение, обработка, отправка сообщений */public class Bot extends TelegramLongPollingBot {    final    BotConfig config;    public Bot(BotConfig config) {        this.config = config;    }    public void onUpdateReceived(Update update) {        update.getUpdateId();        SendMessage.SendMessageBuilder builder =SendMessage.builder();        String messageText;        String chatId;        if (update.getMessage() != null) {            chatId = update.getMessage().getChatId().toString();            builder.chatId(chatId);            messageText = update.getMessage().getText();        } else {            chatId = update.getChannelPost().getChatId().toString();            builder.chatId(chatId);            messageText = update.getChannelPost().getText();        }        if (messageText.contains("/hello")) {            builder.text("Привет");            try {                execute(builder.build());            } catch (TelegramApiException e) {                log.debug(e.toString());            }        }        if (messageText.contains("/chartId")) {            builder.text("ID Канала : " + chatId);            try {                execute(builder.build());            } catch (TelegramApiException e) {                log.debug(e.toString());            }        }    }    public String getBotUsername() {        return config.getBotUserName();    }    public String getBotToken() {        return config.getToken();    }}

Данный класс представляет из себя основной функционал для взаимодействия с Telegram

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

WebHook - RestController обслуживающий API для реакции на события WebHook Gitea
@Slf4j@RestController@RequestMapping("/api/public/gitea")@RequiredArgsConstructor@PropertySource("classpath:application.properties")public class WebHook {    Bot bot;    // Канал в который будем слать уведомления    @Value("${chartId}")    String chartId;    // Секретный ключ который придёт в нутри JSON от Gitea,    // что бы левые люди не имели доступа к боту т.к. API публичное без авторизации    @Value("${secret}")    String secret;    @Autowired    public WebHook(Bot bot) {        this.bot = bot;    }    @PostMapping(value = "/webhook")    public ResponseEntity<?> webhook(@RequestBody String json){        Gson gson = new Gson();        GiteaWebHook giteaWebHook = null;        try {            giteaWebHook = gson.fromJson(json, GiteaWebHook.class);        } catch (JsonSyntaxException e) {            log.error(Utils.exceptionStackTraceToString(e));            return new ResponseEntity<>(Utils.exceptionStackTraceToString(e), HttpStatus.BAD_REQUEST);        }        if (validationWebHookContent(giteaWebHook)) {            SendMessage.SendMessageBuilder messageBuilder =SendMessage.builder();            messageBuilder.chatId(chartId);            messageBuilder.parseMode(ParseMode.HTML);            StringBuilder builder = new StringBuilder();            builder.append("<b>Проект</b> : " + giteaWebHook.getRepository().getName()+"\n");            for (Commit commit : giteaWebHook.getCommits()) {             builder.append("<b>Автор</b> : " + commit.getAuthor().getName()+"\n");             builder.append("<b>Комментарий</b> : " + commit.getMessage()+"\n");            }            builder.append("<a href=\"https://play.google.com/store/apps/details?id=URL_ВАШЕГО_ПРИЛАЖЕНИЯ\">Обновление будет доступно в Play Market через пару минут</a>\n");            messageBuilder.text(buildToCorrectString(builder));            try {                bot.execute(messageBuilder.build());            } catch (TelegramApiException e) {                log.error(Utils.exceptionStackTraceToString(e));                return new ResponseEntity<>(Utils.exceptionStackTraceToString(e), HttpStatus.INTERNAL_SERVER_ERROR);            }        } else return new ResponseEntity<>(HttpStatus.BAD_REQUEST);        HttpHeaders headers = new HttpHeaders();        headers.add("Content-Type", "application/json; charset=utf-8");        return new ResponseEntity<>(headers, HttpStatus.OK);    }    /**     * Проверка пришедших JSON данных на валидность     * @param giteaWebHook - GiteaWebHook     * @return true - если не null, PUSH в master, совпал секретный ключ     */    private boolean validationWebHookContent(GiteaWebHook giteaWebHook){        return giteaWebHook != null && // Если вообще что то есть               giteaWebHook.getRef().contains(giteaWebHook.getRepository().getDefaultBranch()) && // Есть был PUSH в /master               giteaWebHook.getSecret().equals(secret); // Если совпал секретный ключ    }    private String buildToCorrectString(StringBuilder builder){        return builder.toString()                .replace("_", "\\_")                .replace("*", "\\*")                .replace("[", "\\[")                .replace("`", "\\`")                .replace("&nbsp;", " ")                .replace("&frac", " ")                .replaceAll(" \\u003c","");    }}

Данный RestController обслуживает RestAPI с точкой входа http://you_ip:port/api/public/gitea/webhook , сюда наша система контроля версий Gitea будет делать PUSH запрос с JSON данными WebHook возникающего при различных событиях происходящих с вашим репозитарием.

TelegramBotGiteaApplication - Стартовый метод нашего Spring Boot проекта
@SpringBootApplication@AutoConfigurationPackagepublic class TelegramBotGiteaApplication extends SpringBootServletInitializer {    public static void main(String[] args) {        new SpringApplicationBuilder(TelegramBotGiteaApplication.class)                .run(args);    }}

Все те классы что вы наблюдаете в пакете Model , представляют сгенерированную модель GiteaWebHook по JSON-Schema взятому из оф документации по GiteaWebHookApi , удобнее всего это делать при помощи http://www.jsonschema2pojo.org/

Полный исходный код вы можете взять ЗДЕСЬ

Настройка Gitea для выполнения WebHook к нашему боту

Данная статья рассматривает вариант обслуживания API предоставляемое системой контроля версий Gitea но это не значит что вы не сможете сделать оповещение и без неё. Проявив некую долю усердия всё те-же WebHook можно реализовать через .git\hooks\post-update и curl , или некое API GitHub но эти реализации я доверяю вам, и здесь мы рассмотрим лишь вариант с Gitea:

  1. Итак, перейдите в репозитарий вашего проекта и войдите в его Настройки в раздел Автоматическое обновление . Нажмите на кнопку Добавить Webhook , выберете вариант Gitea

  2. В качестве URL обработчика укажите URL на котором у нас висит RestController http://you_ip:port/api/public/gitea/webhook

  3. Тип содержимого - application/json

  4. Секретный ключ - любой набор символов который мы в последующем внесём в наш application.properties

  5. На какие события этот webhook должен срабатывать? - выберите PUSH

  6. Галочку Активности оставьте включённой.

Всё это хорошо бот написан, Gitea настроена но нашему боту нужно где-то жить.

Публикация нашего бота в Google Cloud Platform, бесплатно

New customers get $300 in free credits to spend on Google Cloud. All customers get free usage of 20+ products.See offer details.

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

И так приступим, авторизуйтесь в Google Cloud Platform

1) В боковом меню перейдите в раздел Сompute Engine, и дождитесь его инициализации

2) В разделе Экземпляры ВМ, нажмите создать

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

Давайте зададим сразу правило Брандмауэра разрешающего трафик по порту 8080

Зайдите Cеть VPS - Брандмауэр

Создайте правило для порта 8080 по аналогии с 80 портом

Подключитесь к VM через SSH , непосредственно через браузер

Теперь мы может перейти к настройке нашей виртуальной машины

Для обновления информации об новейших версиях пакетов вводим

sudo apt update

Установим Java

sudo apt install default-jdk

Проверьте это выполнив

java - version

Если всё прошло хорошо вы должны наблюдать версию Java в консоли SSH

Теперь установим maven

sudo apt install maven

Сделаем clone репозитария с нашим ботом заготовкой

git clone https://legan.by/gitea/leganas/TelegramBotGiteaLesson.git

Сделайте необходимые манипуляции по настройке appliation.properties , укажите валидный bot_name и token

nano ./TelegramBotGiteaLesson/src/main/resources/application.properties

Зайдём в папку с нашим ботом и соберём его при помощи maven

cd TelegramBotGiteaLesson/mvn package

После того как maven соберёт наш проект

Бот полностью готов к запуску, выполните команду

java -jar ./target/telegrambotgitea-0.0.1-SNAPSHOT.jar

Используя внешний IP указанный в web консоли управления виртуальными машинами, проверьте его работоспособность открыв в браузере страницу http://YOU_IP:8080/

Если наш бот успешно подключился к Telegram мы можем написать ему проверочное сообщение в ЛС /hello , на что он должен ответить нам Привет

И так теперь у нас всё готово для того что бы добавить нашего бота в Telegram канал, дать ему права администратора (что бы он мог читать сообщения) и протестировать оповещение !

Добавил бота в канал и дав ему права , вы можете написать

/chartId

Теперь это ID можно добавить в application.properties и либо пересобрать проект , либо подкинуть этот файл рядом с jar. Внесите необходимые правки IP адреса в WebHook в настройках Gitea и опробуйте вашего бота.

У кого получилось вот так , тот молодец, о том как сделать jar сервисом писать уже не буду, уж очень много про это написано на хабре, а если не найдёте пишите в личку.

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

Подробнее..
Категории: Git , Devops , Java , Telegram , Google cloud platform , Gtea

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

10.02.2021 10:11:22 | Автор: admin

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

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

Простая мотивирующая история с полезными ссылками.

Почему облачные технологии?

Ты присоединился к EPAM Anywhere в качестве DevOps инженера. Почему ты решил развиваться в облачных технологиях?

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

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

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

Первые шаги в облаке

Первой платформой, которую я изучал, была Amazon Web Services. Это был основной поставщик облачных услуг на рынке в то время. Когда я начал работать с ним, я обнаружил, что моих практических навыков недостаточно для реализации даже несложных функций, поскольку мои знания были в основном теоретическими. Однако постепенно я повышал свои навыки, занимаясь крупными проектами. Мое правило не сдаваться и продолжать попытки, потому что построение карьеры в ИТ это всегда непрерывное обучение и сотрудничество.

Часть сертификатов ты получил самостоятельно, а остальные через EPAM Global Certification, верно?

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

В результате я прошел сертификацию AWS Cloud Practitioner и AWS Developer (Associate) до работы в EPAM, потом, будучи в EPAM, успешно сдал экзамен на AWS DevOps Engineer (Professional).

Помимо программы сертификации AWS, я принял участие в программе сертификации Microsoft Azure для сотрудников EPAM и прошел четыре сертификации: Azure Fundamentals; Azure Developer (Associate) и после небольшого перерыва архитектор решений Azure (Azure Solutions Architect Expert). Недавно я сертифицировался на Azure Data Scientist Associate.

От сертификатов AWS и Microsoft Azure до Google Cloud

Почему ты решил получить сертификат Google Cloud?

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

Затем я прочитал историю успеха о нашем коллеге, который получил ряд профессиональных сертификатов GCP, благодаря чему попал на новый интересный проект. Думаю, это послужило толчком для меня, я подал заявку на ещё одну сертификацию GCP и получил сертификат GCP Cloud Engineer (Associate).

Но это еще не конец истории. Поскольку я был на волне самообразования, я также решил изучить Kubernetes и, наконец, сдал экзамен на Kubernetes Application Developer (CKAD).

Сколько сертификатов сейчас в твоём портфолио?

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

Что, по-твоему, является самой сложной частью процесса сертификации и как с ней справиться?

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

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

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

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

Секреты успеха: ключевые принципы, которые помогут получить желаемые сертификаты

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

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

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

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

  • Мотивация, основанная на понимании преимуществ, которые сертификация даст для профессионального роста.

  • Продуманный стратегический план развития вашей карьеры на предстоящий период: 5 лет, 3 года, 1 год или меньше.

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

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

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

Двигайтесь вперед и никогда не останавливайтесь на пути к своей мечте!

Подробнее..

Переход с 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. Он тоже отличается масштабируемостью и хорошей архитектурой.
Подробнее..

Создание документов на диске Google на базе событий в CRM-системах аmoCRM и Битрикс24

18.02.2021 12:05:10 | Автор: admin

Практический кейс о том, как разработать свой сценарий интеграции.

Появившиеся в 2006 году сервисы Google по работе с текстовыми документами (Google Docs) и таблицами (Google Sheets), дополненные 6 лет спустя возможностями работы с виртуальным диском (Google Drive), завоевали широкую любовь пользователей, лишив компанию Microsoft сложившейся десятилетиями монополии на работу с офисным программным обеспечением.

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

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

В базовом функционале CRM-систем интеграция с сервисами Google представлена лишь в Битрикс24 и предполагает создание пустого документа на базе диска с переходом в режим редактирования при последующем клике на него.

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

Для того, чтобы выполнить какое-то действие на Google диске своего аккаунта есть два подхода: вызвать соответствующий REST API метод или запустить написанный Google Script. Как показал наш опыт, REST API библиотека Google пока имеет гораздо более бедный набор возможностей по отношению к скриптам, например, с помощью метода create можно создать исключительно пустой документ без наполнения. Поэтому, универсальным является сейчас комбинированный подход, заключающийся в написании исполняемого скрипта, который будет вызываться извне с помощью API с определенным набором параметров.

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

Шаг 1. Создание скрипта

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

Сам script добавляется на диске точно также как мы добавляем обычный файл на него.

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

Шаг 2. Привязка скрипта к проекту Google Cloud Platform

После того как скрипт написан рекомендуем прогнать его, нажав кнопку Выполнить в редакторе. Далее вам необходимо создать проект на Google Cloud Platform. Наиболее простым вариантом для этого является нажатие кнопки Enable Google Script API по ссылке:https://developers.google.com/apps-script/api/quickstart/php.

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

Шаг 3. Публикация скрипта

Чтобы скрипт был доступен извне, его надо развернуть через кнопку начать развертывание.

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

Шаг 4. Написание PHP-обработчика

Для работы с API Google существует готовая библиотека, которую вы подключаете к своему проекту командой: composer require google/apiclient:^2.0

В файле с подключенной библиотекой вызываете функцию для подключения токена авторизации:

function getClient(){    $client = new Google_Client();    $client->setApplicationName('Google Apps Script API PHP Quickstart');    // перечисляем области действия токена через пробел    $client->setScopes("https://www.googleapis.com/auth/documents https://www.googleapis.com/auth/drive");    // файл credential.json, полученный от Google$client->setAuthConfig('credentials.json');    $client->setAccessType('offline');    $client->setPrompt('select_account consent');    // Формируемый файл token.json    $tokenPath = 'token.json';    if (file_exists($tokenPath)) {        $accessToken = json_decode(file_get_contents($tokenPath), true);        $client->setAccessToken($accessToken);    }    // Действие если токен просрочен    if ($client->isAccessTokenExpired()) {        if ($client->getRefreshToken()) {            $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());        } else {            $authUrl = $client->createAuthUrl();            printf("Open the following link in your browser:\n%s\n", $authUrl);            print 'Enter verification code: ';            $authCode = trim(fgets(STDIN));            $accessToken = $client->fetchAccessTokenWithAuthCode($authCode);            print_r($accessToken);            $client->setAccessToken($accessToken);                        if (array_key_exists('error', $accessToken)) {                throw new Exception(join(', ', $accessToken));            }        }        // Сохранение токена в файл        if (!file_exists(dirname($tokenPath))) {            mkdir(dirname($tokenPath), 0700, true);        }        file_put_contents($tokenPath, json_encode($client->getAccessToken()));    }    return $client;}

Файл с этой функцией должен быть изначально исполнен в командной строке ssh клиента php (имя файла).

При первом запуске на экране появится url, который вы открываете в своем браузере и дав необходимые разрешения копируете verification code из url ресурса приложения, который вы указали на шаге 1, вставляя его в командную строку. После этого система создает файл токена авторизации (token.json), сохраняя его в папке PHP-обработчика. Следует отметить,что данную операцию надо выполнить один раз.

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

// вызов ранее описанной функции для получения токена авторизации$client = getClient();$service = new Google_Service_Script($client);// код развернутого скрипта$scriptId = '***********************wKhTTdKL7ChremS5AkvzwlPJARnxqisW7TzDB ';$request = new Google_Service_Script_ExecutionRequest();// имя и параметры функции в рамках скрипта$request->setFunction('FillTemplate');$request->setParameters([$_REQUEST['customer'],$_REQUEST['link'],$_REQUEST['formsv'],$_REQUEST['socnet'],$_REQUEST['whatsi'],   $_REQUEST['ats'],$_REQUEST['pipeline'],$_REQUEST['outscope'],$_REQUEST['editor'],$_REQUEST['viewer']]);try {    // Make the API request.    $response = $service->scripts->run($scriptId, $request);    if ($response->getError()) {        // Обработчик ошибок        $error = $response->getError()['details'][0];        printf("Script error message: %s\n", $error['errorMessage']);        if (array_key_exists('scriptStackTraceElements', $error)) {            print "Script error stacktrace:\n";            foreach($error['scriptStackTraceElements'] as $trace) {                printf("\t%s: %d\n", $trace['function'], $trace['lineNumber']);            }        }    }     } catch (Exception $e) {    // Обработчик исключения    echo 'Caught exception: ', $e->getMessage(), "\n";}

Шаг 5. Вызов PHP-обработчика из CRM

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

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

При этом, в Битрикс24 вебхук может быть встроен в бизнес-процесс, получая в качестве своих Get-параметров данные из сделки, переменных и констант бизнес-процесса.

Итогом работы данного вебхука стали добавляемые документы в соответствующую папку Google Drive:

Существенным ограничением запусков обработчиков через вебхуки является предельно допустимая длина URL, в которой будут передаваться Get-параметры. Напомним, что она составляет 4 кб (или 2048 символов).

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

Подробнее..

Обработка оценок за тесты в Google Forms

13.02.2021 06:17:09 | Автор: admin

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

Одним из простейших способов организовать тестирование через Интернет является использование сервиса Google Forms. Чтобы превратить простой список вопросов в тест с проверкой ответов и баллами, необходимо войти в настройки Формы и включить режим Quiz.


Ответы можно просматривать в интерфейсе самой Формы во вкладке Responses. Кроме того, ответы можно выгрузить в таблицу Google Sheet. Таблица выглядит следующим образом:

Интерес представляет столбец Score. В нем в виде дроби представлена информация о набранных баллах и максимальном количестве баллов за тест. Сложность состоит в том, что физически в ячейке записано только число набранных баллов, а строка "/ 2" является частью Custom Number Format. Чрезвычайно удобная функция IMPORTRANGE(), позволяющая вставить заданный диапазон на другой лист или даже в другую таблицу, успешно копирует этот формат для каждой ячейки. А вот функция QUERY() - нет. Информация о максимальном количестве баллов за тест в некоторых случаях теряется.

Итак, пусть у нас есть три Формы: Test 1, Test 2 и Test 3. Первым вопросом в тестах идет "Full Name". По этому полю мы будем идентифицировать учащихся. Для трех тестов есть три таблицы с ответами: Test 1 (Responses), Test 2 (Responses), Test 3 (Responses). Первые три столбца в каждой таблице одинаковые: Timestamp, Score, Full Name. Далее идут ответы на вопросы теста, которые нам не понадобятся.

Создадим новый документ Googe Sheet. Назовем его, например, Grade Book. Нам понадобится по одному листу на каждый тест (T1, T2, T3), лист Source, чтобы собрать всё вместе, и лист Grade Book для сводной таблицы.

Листы в документе "Grade Book"Листы в документе "Grade Book"

Листы T1, T2, T3...

Импортируем на листы T1, T2, T3 первые три столбца из таблиц ответов. Для этого в ячейку A1 на каждом листе вставим формулу:

=IMPORTRANGE("https://docs.google.com/spreadsheets/d/1dee7GYwj1NgZfDNZJgLMVOcWRmPnvSAvg3KJ0ahqkmI","Form Responses 1!A2:C")

Где "https://..." - это URL таблицы "Test X (Responses)", который можно скопировать из адресной строки браузера, "Form Responses 1" - название Листа с результатами теста, "A2:C" - диапазон ячеек, который мы хотим скопировать (заголовок игнорируем).

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

=ArrayFormula(split(B1:B, "/"))

Теперь в колонке D хранится количество баллов за тест, а в колонке E - максимальное количество баллов за тест.

Лист "T1"Лист "T1"

Лист Source

Лист Source будет чем-то вроде таблицы базы данных, в которую мы соберем ответы на все тесты добавив ещё один столбец - идентификатор теста. Затем уже можно будет пересчитать баллы в оценки и немого причесать поле Full Name.

В ячейку A1 на Листе "Source" вставим формулу:

=QUERY({QUERY('T1'!A1:E, "SELECT 'T1', A, B, C, D, E WHERE A IS NOT NULL LABEL 'T1' ''");QUERY('T2'!A1:E, "SELECT 'T2', A, B, C, D, E WHERE A IS NOT NULL LABEL 'T2' ''");QUERY('T3'!A1:E, "SELECT 'T3', A, B, C, D, E WHERE A IS NOT NULL LABEL 'T3' ''")}, "SELECT * ")

Где T1, T2, T3 - названия Листов, куда мы импортировали данные из таблиц ответов, SELECT 'T1'... - это необходимо, чтобы добавить в каждую строку идентификатор теста.

В ячейку G1 на листе "Source" добавим формулу для пересчета баллов в оценки по пятибалльной шкале:

=ArrayFormula(E1:E/F1:F*5)

А в ячейку H1 добавим формулу, чтобы вырезать из Full Name только первое слово. По опыту студенты пишут свою фамилию каждый раз одинаково, а дальше пишут то имя, то имя и отчество, то инициалы. Чтобы связать несколько ответов одного студента вместе в моём случае оказалось достаточно вырезать фамилию.

=ArrayFormula(INDEX(SPLIT(D1:D, " "), 0, 1))

Лист "Source" будет выглядеть следующим образом:

Лист Grade Book

В ячейку A1 на листе "Grade Book" вставим следующую формулу:

=QUERY(Source!A1:H,"SELECT H, MAX(G) WHERE C IS NOT NULL GROUP BY H PIVOT A")

Где Source - лист, с которого брать данные, MAX(G) - максимальная оценка из всех попыток каждого студента сдать тест, PIVOT(A) задает столбец для колонок сводной таблицы, в нашем случае - идентификатор теста.

Вот и готова таблица с оценками:

Лист "Grade Book"Лист "Grade Book"

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

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

Подробнее..

Мой опыт с экзаменами GCP Associate, Architect, Network

18.02.2021 18:15:13 | Автор: admin

Весной 2020 года я решил приступить к изучению Google Cloud Platform: моя фирма является партнером Google и у нас есть некоторые решения на GCP.

Доступ к GCP. Возможно мало кто знает, но получить доступ к платформе может каждый, у кого есть gmail аккаунт. Нужно только подтвердить свою личность с помощью кредитной карты (сразу скажу что не все карты подходят, моя например карта Revolut не проходила). Многие советуют иметь другой аккаунт специально под нужды GCP, не знаю точно с чем это связано. После активации аккаунта вы получаете полный доступ к консоли (это Google так называет свое облачное окружение, CLI же, через который можно выполнять команды называется Cloud Shell) и кредит в валюте вашей страны в эквиваленте 300 доларов США.

Подготовка и процесс сдачи экзамена Associate Cloud Engineer. Основные требования к экзамену можно посмотреть на странице Google Cloud сертификации. Для подготовки к экзамену я использовал различные источники: книга Associate Cloud Engineer Study Guide автор Dan Sullivan в связке с практикой в GCP консоли; видео с ютуб канала ADV-IT о Google Cloud; платформа Qwiklabs с лабораторными работами. Сдавал экзамен в июне 2020 года, как раз когда снова открылись экзаменационные центры в Польше. Для сдачи экзамена нужно зарегестрироваться на сайте Kryterion и забронировать экзамен. Экзамен занимает 2 часа. В конце экзамена ты получаешь информацию PASS или FAIL, я экзамен сдал. Через несколько дней приходит на электронную почту письмо с доступом к сертификату.

Подготовка и процесс сдачи экзамена Professional Cloud Architect. Для подготовки использовал книгу Google Cloud Certified Professional Cloud Architect Study Guide автор Dan Sullivan. Также на платформе Qwiklabs моя фирма открыла мне доступ к учебным материалам. Данный экзамен содержит 4 кейса о разных фирмах, на основании которых есть вопросы на экзамене: EHR Healthcare, Helicopter Racing League, Mountkirk games, TerramEarth. Можно легко нагуглить разбор этих кейсов и попробовать создать инфраструктуру в GCP для лучшего понимания. Экзамен сдавал в ноябре 2020 года в экзаменационном центре. Экзамен длился 2 часа, экзамен благополучно сдал.

Подготовка и процесс сдачи экзамена Professional Cloud Network Engineer. К данному экзамену я готовился с помощью платформы Qwiklabs и курса Networking in Google Cloud Specialization на платформе Coursera. Данный экзамен я решил сдавать онлайн. Для сдачи онлайн необходимо чтобы микрофон и камера работали корректноб установить на компьютер програму и создать биометрический профиль (детальная информация об этом доступна на платформе Kryterion). Экзамен я зарегистрировал на начало февраля 2021 года. Перед сдачей экзамена нужно было выполнить несколь условий, которые подаются перед началом экзамена: убрать все со стола, отключить фаервол и антивирус на компьтере, позакрывать все окна браузера кроме окна со страницей экзамена, обеспечить хорошее интернет соединение. На странице Kryterion предупреждают о необходимости залогиниться за 10 минут до начала экзамена и не отключаться в течении 20 минут после начала, возможны задержки в работе со стороны проктора. У меня так и было, когда когда время уже было более 20 минут после начала появилось всплывающее окно с диалогом. Меня сначала попросили показать с помощью камеры ноутбука все стены и потолок. Потом попросили показать стол и все что под столом. После этого попросили с помощью зеркала или передней камеры телефона показать экран и клавиатуру ноутбука. В конце попросили снять очки и показать их со всех сторон перед камерой ноутбука. Я думаю для сдачи экзамена онлайн стоит иметь отдельную веб камеру чтобы избежать всех этих плясок с ноутбуком. После всех этих манипудяций был открыт доступ к экзамену. Экзамен длился 2 часа. Возможно я не был достаточно подготовлен к экзамену поэтому FAIL.

Общее впечатление о сертификации. На каждый экзамен прихидится 50 вопросов с одним или несколькими правильными ответами. Есть возможность отметить определенные вопросы если хочешь к ним позже вернуться и вообще есть возможность возвращаться к предыдущим вопросам. Хорошо ли это каждый решает сам, например одна моя знакомая принципиально не возвращается к предыдущим вопросам потому что так больше возможности передумать и выбрать неправильный ответ. Есть большое кольчество вопросов с подвохом, в которые нужно очень внимательно вчитываться и понимать под углом реалий гугла. Хотелось бы чтобы на экзамене были вопросы связанные с конфигурацией, где тебе через CLI нужно что-то проверить, сконфигурировать (как например на CISCO экзаменах), так экзамен мог бы быть поинтересней.

Некоторые ресурсы, которые могут быть полезны при изучении GCP:

Google Cloud Developer's Cheat Sheet с коротким обьяснением что есть что в GCP,

GCP CheatSheet с популярными командами,

Github репозиторий с очень подробной информацией о каждом из экзаменов.

Подробнее..

Категории

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

  • Имя: Макс
    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