Переход в облако. Практическое руководство по организации облачных вычислений для ученых и IT-специалистов
.pdf
ГЛАВА 6
Бакет: nasa-experiment
4: Загрузка результатов
1: Получение кода ПО Classificator
Данные NASA Earth (API)
Экземпляр EC2
3:Обработка данных
2:Получение данных по месяцам
Рис. 6.2 Архитектура высокого уровня и рабочий процесс для эксперимента
с классификацией месяцев по облачности
•Предварительные требования:
—Этот шаг предполагает, что в AWS корректно созданы необходимое виртуальное частное облако (VPC) и подсеть (более подробную информацию о том, как настроить VPC и подсеть, можно найти в официальной документации85). В данном примере созданная подсеть получает идентификатор subnet-1a2b3c4e.
—Для доступа к экземпляру через SSH может потребоваться действи-
тельная/созданная пара ключей. Создать ее можно в консоли AWS (UI): EC2 Manager Key Pairs Create Key Pair). В данном примере
парой ключей будет nasa-experiment.
—Создается бакет S3: это можно сделать в консоли AWS (UI) в разделе S3 Create Bucket. Код classificator.py расположен в бакете с от-
крытым доступом, чтобы его можно было загрузить из экземпляра.
Этот скрипт вызовет экземпляр t2.micro под управлением Amazon Linux (ami-047bb4163c506cd98) в подсети subnet-1a2b3c4e, доступ к которой осуществляется через SSH с использованием ключа nasa-experiment86.
85Amazon (2019) AWS VPC documentation. https://docs.aws.amazon.com/vpc/index.html. По состоянию на 10 апреля 2019 г.
86Обратите внимание: этот код значительно упрощен в иллюстративных целях и подлежит оптимизации, например введению аргументов вместо констант в многопроцессные запросы.
81
ПЕРЕХОД В ОБЛАКО
Первая часть кода создает на AWS базовую инфраструктуру, состоящую из одного экземпляра из предлагаемого бесплатного уровня. Это простой сценарий командной оболочки, который использует интерфейс командной строки AWS87.
#!/ bin /bash
# AMI — идентификатор для Amazon Linux
aws ec2 run–instances ––region eu–west-1 ––image–id ami-047 bb4163c506cd98 ––count 1 ––instance–type t2.micro ––key–name nasa
— experiment ––subnet–id subnet-1a2b3c4e ––instance–initiated– shutdown–behavior terminate ––user–data file://${PWD}/scripts/boot.sh
Содержимое загрузочного скрипта “boot.sh”, устанавливающего зависимости и запускающего код моделирования, таково88:
#!/ bin /bash yum update –y
amazon–linux–extras install python3 pip install numpy boto
# Получение кода скрипта классификатора из общедоступного URL (в данном случае тот же бакет)
curl https://s3-eu–west-1.amazonaws.com/nasa–experiment/classifier.py –o /tmp/ classifier.py
chmod +x /tmp/ classifier .py /tmp/ classifier .py
# Вычисления и выгрузка завершены: экземпляр прерывает работу shutdown –h now
Основные этапы моделирования таковы:
•Получить данные об облачности в течение месяца из API NASA.
87Описание этапов установки можно найти здесь: https://docs.aws.amazon.com/cli/latest/ userguide/installing.html.
88Обратите внимание: как упоминалось ранее, код классификатора должен быть общедоступным по URL-адресу, в который свертывается скрипт.
82
ГЛАВА 6
•Учитывая эти данные, рассчитать средний показатель за месяц и наиболее типичный для этого месяца день.
•Загрузить результат в объект AWS S3.
•Отправить пользователю сообщение об успешном завершении операции.
Наконец, вот как будет выглядеть код classificator.py:
import json import numpy import os import requests import tempfile import boto import boto.s3
from calendar import monthrange from datetime import datetime from boto.s3.key import Key
# Константы: ключи API и секретные ключи доступа
NASA_API_KEY = “NASA_API_KEY”
AWS_ACCESS_KEY_ID = ’XXX’
AWS_SECRET_ACCESS_KEY = ’YYY’
S3_BUCKET = ’MY_EXPERIMENT_BUCKET’
# Константы: дата в формате ГГГГ–ММ
DATE = «2016–07»
# Константы: долгота и широта
LON = «–7.8987052»
LAT = “42.3384207”
class S3(object):
def __init__ (self):
self ._conn = boto.connect_s3(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)
83
ПЕРЕХОД В ОБЛАКО
self ._bucket = self ._conn. create_bucket (
S3_BUCKET, location=boto.s3.connection.Location.DEFAULT)
def upload(self, source_file, target_file): k = Key(self ._bucket)
k.key = target_file
k. set_contents_from_filename (source_file)
class Month(object):
def __init__ (self, longitude, latitude, date, api_key): self. _longitude = longitude
self. _latitude = latitude self. _date = date
self ._api_key = api_key
self. _baseurl = “https://api. nasa.gov/ planetary / earth /imagery/” self ._req = requests
# День месяца
self ._monthdata = {}
def _getData(self):
year, month = self. _date. split (’–’)
mrange = monthrange(int(year), int (month))
print(“> Receiving data from API … “)
for day in range(1, mrange[1] + 1):
day_date = “{}–{}”.format(self. _date, day) day_url = “{base}?lon={lon}&lat={lat}
&date={date}&cloud_score=True &api_key={api_key}”.format(base=self. _baseurl, lon=self. _longitude, lat =self. _latitude, date=day_date, api_key=self ._api_key)
84
ГЛАВА 6
#Оптимизация может заключаться в том, чтобы делать меньше запросов к API (ближайший день от API).
#а также с целью использования многопроцессорного пула для
#параллельных запросов
day_data = self ._req. get (day_url) day_data_json = day_data. json () response_date = datetime. strptime (
day_data_json[’ date ’], ’%Y–%m–%dT%H:%M:%S’) response_simple_date = “{}–{}–{}”.format(
response_date. year, response_date.month, response_date. day)
# Добавление данных только в случае, если их еще нет if response_simple_date not in self ._monthdata:
self ._monthdata[response_simple_date] = day_data_json
def _getAverageDay(self):
self ._getAverageCloudScore() closest_average_day = ’ ’ average_distance = 1
for day in self ._monthdata: day_avg_distance = numpy.absolute(
self ._monthdata[day][’ cloud_score ’] — self. _average_cloud_score)
if (day_avg_distance < average_distance):
# Помечаем этот день как наиболее близкий к среднему значению average_distance = day_avg_distance
closest_average_day = day
self. _closest_average_day = closest_average_day self ._writeTempFile()
def _getAverageCloudScore(self): cloud_scores = []
for day in self ._monthdata:
cloud_scores.append(self ._monthdata[day][’ cloud_score ’])
85
ПЕРЕХОД В ОБЛАКО
self. _average_cloud_score = numpy.mean(cloud_scores)
def _writeTempFile(self):
new_file, filename = tempfile.mkstemp() print(“> Writing local temp file:%s”% filename) os. write (new_file, json.dumps(
self ._monthdata[self. _closest_average_day])) os. close (new_file)
def _writeOutput(self): print(“ “)
print(“> Month Average Cloud Score for%s:%s”% (DATE, self. _average_cloud_score))
print(“> Average Day Date (YYYY–MM–DD):%s (avg.:%s)”% (self. _closest_average_day, self ._monthdata[self.
_closest_average_day][’ cloud_score ’]))
def process (self): self ._getData ()
self ._getAverageDay() self. _writeOutput () self ._uploadS3()
if __name__ == “__main__”:
month = Month(LON, LAT, DATE, NASA_API_KEY)
# Обработка данных за месяц month.process ()
Г Л А В А 7
Бессерверные
эксперименты в облаке
7.1. Саша пересматривает эксперимент
Потратив некоторое время на проведение небольшого эксперимента в облаке с помощью EC2, т. е. прибегнув к классическому подходу, Саша понял, что подход оказался слишком сложным. Привлекательное решение этой проблемы предлагают бессерверные вычисления. Как мы поняли из раздела 3.6, существует ряд примеров применения бессерверных технологий в области научных исследований. Саша решает изучить, может ли такой вариант упростить код, настройку и процесс моделирования, выполняемый его командой. Давайте рассмотрим, что такое бессерверные вычисления и как они могут упростить реализацию облачных.
7.2. Бессерверный подход
Функция как услуга (FaaS), или бессерверные вычисления89, — это относительно новая модель в рамках облачной парадигмы, в которой ПО работает в крайне абстрагированной и ограниченной среде, а разработчик совсем мало контролирует процесс, взамен получая автоматизированную и автономную инфраструктуру. Бессерверные вычислительные платформы
89Baldini I. et al (2017) Serverless computing: current trends and open problems. Research advances in cloud computing. Springer, Singapore, pp 1–20. https://doi.org/10.1007/978– 981–10–5026–8_1.
87
ПЕРЕХОД В ОБЛАКО
отличаются по степени абстракции от тех платформ, которые оставляют за разработчиками некоторую степень контроля, например App Engine от Google, где можно выбрать тип машины и установить сторонние пакеты, до таких FaaS, как AWS Lambda, среда выполнения которой полностью определяется AWS, и разработчику приходится адаптировать свой код к ограничениям.
Создание или переделка решения для FaaS90 требует переосмысления некоторых аспектов, например, того, как запускать функцию и как передавать данные; бессерверные вычисления не подходят для решения любой проблемы, но весьма выгодны для реализаций определенного типа. Если Саше действительно нужен контроль над собственными ресурсами, например операциями ввода-вывода, или если его проект обладает специфическими или индивидуальными требованиями, такими, например, как обязательное наличие функции пользовательской библиотеки, то бессерверные вычисления не будут наилучшим решением. Однако, если Сашино ПО достаточно универсально, если в нем используется основной язык со стандартными числовыми модулями, то бессерверные решения могут оказаться оптимальными.
7.2.1. За и против
За
•Упрощенный рабочий процесс: это преимущество не только определяет, но и оправдывает использование бессерверных вычислений вместо любой другой облачной службы. Поставщик облачных решений располагает необходимым опытом для поддержания инфраструктуры, а значит разработчик может сосредоточиться на генерировании и внедрении ПО.
•Лучший контроль над затратами: в сфере бессерверных вычислений, как правило, придерживаются схемы оплаты по факту использования, при которой поставщик взимает плату только за конкретные использованные ресурсы на более детальном уровне, чем в случае с любым другим облачным сервисом.
90Hong S. (2018) Go Serverless: securing cloud via serverless design patterns. In: 10th USENIX workshop on hot topics in cloud computing (HotCloud 18), Boston.
88
ГЛАВА 7
Против
•Сложность с точки зрения больших задач HPC91: выделение большого объема ресурсов требует планирования с участием поставщика облачных услуг; в противном случае может возникнуть ситуация, при которой, например, мощность процессора, необходимая для работы приложения, окажется недоступна.
•Чем выше уровень абстракции, тем ниже уровень контроля: иллюстрацией может служить ситуация, при которой Сашино ПО пострадает от недостаточной производительности из-за использования неправильных ресурсов. Как мы помним, Саша не контролирует многие из них: ресурсы выделяет поставщик, и они могут не подходить для решения Сашиной проблемы.
•Специфичный код: в некоторых случаях Сашиному приложению может потребоваться индивидуальный код, доступный только у конкретных поставщиков, т. е. нестандартный код, ведущий в некоторой степени к привязке к одному поставщику. Кроме того, Саше нужно знать, возможен ли рефакторинг кода ресурсов с целью запуска в бессерверной среде.
7.3. Пример: Классификатор месяцев. Бессерверная версия
Пересмотрев эксперимент с классификатором, описанный в предыдущей главе, и проанализировав текущую ситуацию с развитием технологии и тенденций в сфере облачных вычислений, Саша решает, что его классификатор станет отличным проектом для бессерверной реализации, и вот по каким причинам:
•Исследователям не придется учитывать некоторые требования и зависимости, такие как экземпляры EC2 или VPC.
91Kleppmann M. (2017) Designing data-intensive applications, Chapter 8. O’Reilly, Sebastopol; Montes D. et al (2017) Views on the potential of Cloud computing and IaaS/HPCaaS for meteorology and climatology. In: EMS Annual Meeting Abstracts (EMS2017), Vienna, vol 14, p 639.
89
4: Загрузка результатов
ПЕРЕХОД В ОБЛАКО
•Код (Python 3) является стандартным и относительно простым.
•Дополнительные расходы, связанные с инфраструктурой, будут сокращены благодаря использованию вычислительных ресурсов строго по мере необходимости.
Вданном случае Саша располагает финансированием для GCP, поэтому выбирает Google Cloud Functions92. Вот некоторые детали:
•Поставщик облачных услуг: предположим, что в данном случае это GCP.
•Технологии:
— Язык программирования и библиотеки: Python 3 и NumPy.
— Сторонние API: Earth data API NASA.
— Облачные технологии/сервисы: Google Cloud Functions и Google Cloud Storage (GCS).
Высокоуровневая архитектура и рабочий процесс представлены на рис. 7.1.
•Предварительные требования:
—Действительные учетные данные (учетная запись службы) с разрешением на управление как облачными функциями, так и облачным хранилищем. Самый простой способ получить учетные данные — использовать Google Cloud SDK93 и аутентифицировать текущий сеанс с помощью следующей команды, чтобы предоставить ссылку для открытия и проверки сеанса:
$ gcloud auth login
—Создать бакет GCS. Сделать это можно, выполнив следующую команду:
$ gcloud mb gs:// MY_EXPERIMENT_BUCKET
92Google (2019) Google cloud functions. https://cloud.google.com/functions/docs/concepts/ python-runtime. По состоянию на 10 мая 2019 г.
93Google (2019) Cloud SDK. https://cloud.google.com/sdk/. По состоянию на 10 мая 2019 г.
90
