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

Aws

Погружение в Serverless. По следам протокола S3

30.03.2021 10:05:43 | Автор: admin

Продолжаем беседовать с разработчиками экосистемы сервисов Serverless. В прошлый раз Глеб Борисов рассказал о возможностях и перспективах функций в Yandex.Cloud, сегодня Данил Ошеров погрузит нас в мир бессерверных систем и сервис Object Storage.

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

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

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

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

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

Рынок созрел. Бизнес готов доверить свои данные облачным хранилищам. Если бы на месте Amazon оказалась Google, взорвав рынок своим протоколом, то мы бы сейчас пользовались им.

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

Мы предоставляем S3-совместимый протокол, чтобы клиентам было максимально удобно как мигрировать к нам, так и использовать уже готовый инструментарий: всевозможные консольные утилиты, готовые приложения, написанные программы. Но в любой момент клиенты могут просто переключиться на использование Yandex Object Storage, и всё также будет работать. Это большой плюс.

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

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

Да, мы не должны себя ограничивать. Сейчас рынок максимально сфокусирован на S3-совместимых решениях. Это нормально, поэтому мы никоим образом не отказываемся от него, а продолжаем развивать нашу совместимость. Мы фокусируемся сейчас именно на поддержке S3-совместимого решения, но при этом всегда держим в голове и в планах развитие собственного протокола, собственных SDK. Но это вопрос будущего.

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

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

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

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

Получается, на входе существует какой-то прокси, который разделяет эти данные в момент записи?

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

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

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

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

Инфраструктуры Яндекса и Yandex.Cloud независимые, учения Яндекса никак не влияют на работоспособность сервисов Yandex.Cloud. Это важный момент.

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

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

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

Правильно я понимаю, что на S3 как на базовом элементе инфраструктуры внутри Яндекса и Yandex.Cloud построено огромное количество других сервисов, отвечающих за работу других публичных услуг?

Да, объектное хранилище использует огромное количество сервисов. Причем сервис Object Storage, предоставляемый как услуга платформы Yandex.Cloud, построен на тех же технологиях, что и хранилище для внутренней инфраструктуры. Это не раздельные решения, специально написанные для облака или специально написанные для Яндекса, а единая система объектного хранения с независимыми инсталляциями, но одинаковым технологическим стеком.

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

Технологические решения в области S3 полностью переиспользуются в виде отдельной инсталляции?

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

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

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

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

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

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

То есть скорость доступа к холодным данным ниже, чем к горячим?

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

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

Как это работает есть стандартные решения?

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

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

Меня еще волнует вопрос внезапной пиковой нагрузки. Допустим, видео или картинка завирусилась или на сайт совершена DDoS-атака.

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

На чем сейчас написана реализация S3?

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

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

А когда вообще в Яндексе появился S3?

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

Насколько Object Storage в Yandex.Cloud отличается от реализации S3 в Amazon?

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

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

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

P.S.

Самый простой и понятный сценарий, который может использовать любой хаброжитель в своих целях, раздача статического контента с Object Storage, например статического сайта. Это может стать основой вашего Serverless-приложения. О подробностях и нюансах разработки в этой экосистеме можно узнать в сообществе Serverless в Telegram: Yandex Serverless Ecosystem.

На осенней конференции Yandex Scale был анонсирован free tier для сервисов экосистемы бессерверных вычислений. Это специальные тарифы для Serverless-сервисов с уровнем нетарифицируемого использования. Например, для Yandex Object Storage каждый месяц не тарифицируются первые 100 000 операций GET, HEAD и первые 10 000 операций PUT, POST. Более подробно об условиях читайте в разделе.

Подробнее..
Категории: Интервью , S3 , Aws , Yandex.cloud , Serverless

Перевод Улучшаем производительность Java-микросервиса парой простых приемов

10.03.2021 18:12:48 | Автор: admin

Привет, Хабр. Для будущих студентов курса "Highload Architect" подготовили перевод материала.

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


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

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

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

Что будем использовать

Мы будем использовать два микросервиса:

  • External-service (внешний сервис): "реальный" микросервис, доступный по HTTP.

  • Facade-service (фасад): микросервис, который будет читать данные из external-service и отправлять результат клиентам. Будем оптимизировать этот сервис.

Что нам нужно

  • Java 8

  • Jmeter 5.3

  • Java IDE

  • Gradle 6.6.1

Исходный код

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

External service

Сервис был создан с помощью Spring Initializer. В нем один контроллер, имитирующий нагрузку:

@RestController public class ExternalController {   @GetMapping(/external-data/{time})  public ExternalData getData(@PathVariable Long time){  try {  Thread.sleep(time);  } catch (InterruptedException e) {  // do nothing  }  return new ExternalData(time);  } }

Запустите ExternalServiceApplication. Сервис должен быть доступен по адресу https://localhost:8543/external-data/300 .

Facade service

Этот сервис также был создан с помощью Spring Initializer. В нем два основных класса: ExternalService и ExternalServiceClient.

Класс ExternalService читает данные из сервиса External Service с помощью externalServiceClient и вычисляет сумму.

@Service public class ExternalService {   @Autowired  private ExternalServiceClient externalServiceClient;   public ResultData load(List<Long> times) {  Long start = System.currentTimeMillis();  LongSummaryStatistics statistics = times  .parallelStream()  .map(time -> externalServiceClient.load(time).getTime())  .collect(Collectors.summarizingLong(Long::longValue));  Long end = System.currentTimeMillis();  return new ResultData(statistics, (end  start));  } }

Для чтения данных из external service класс ExternalServiceClient использует библиотеку openfeign. Реализация HTTP-клиента на основе OKHttp выглядит следующим образом:

@FeignClient( name = external-service, url = ${external-service.url}, configuration = ServiceConfiguration.class) public interface ExternalServiceClient {   @RequestMapping(  method = RequestMethod.GET,  value = /external- data/{time},  consumes = application/json)  Data load(@PathVariable(time) Long time); }

Запустите класс FacadeServiceApplication и перейдите на http://localhost:8080/data/1,500,920,20000.

Ответ будет следующим:

{  statistics: {  count: 4,  sum: 1621,  min: 1,  max: 920,  average: 405.25  },  spentTime: 1183 }

Подготовка к тестированию производительности

Запустите Jmeter 5.3.1 и откройте файл perfomance-testing.jmx в корне проекта.

Конфигурация теста:

Нагрузочный тест будем проводить по следующему URL-адресу: http://localhost:8080/data/1,500,920,200

Перейдите в Jmeter и запустите тест.

Первый запуск Jmeter

Сервер стал недоступен. Это связано с тем, что в ExternalService мы использовали parallelStream(). Stream API для параллельной обработки данных использует ForkJoinPool. А по умолчанию параллелизм ForkJoinPool рассчитывается на основе количества доступных процессоров. В моем случае их три. Для операций ввода-вывода это узкое место. Итак, давайте увеличим параллелизм ForkJoinPool до 1000.

-Djava.util.concurrent.ForkJoinPool.common.parallelism=1000

И запустим Jmeter еще раз.

Второй запуск Jmeter

Как вы видите, пропускная способность (throughput) увеличилась с 6 до 26 запросов в секунду. Это хороший результат. Кроме того, сервис работает стабильно без ошибок. Но тем не менее среднее время (average time) составляет 9 секунд. У меня есть предположение, что это связано с затратами на создание HTTP-соединение. Давайте добавим пул соединений:

@Configuration public class ServiceConfiguration {      @Bean  public OkHttpClient client()  throws IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException, NoSuchProviderException {     okhttp3.OkHttpClient client = new okhttp3.OkHttpClient.Builder()  .sslSocketFactory(sslContext.getSocketFactory(), trustManager)  .hostnameVerifier((s, sslSession) -> true)  .connectionPool(new ConnectionPool(2000, 10, TimeUnit.SECONDS))  .build();   OkHttpClient okHttpClient = new OkHttpClient(client);   return okHttpClient;  }

Таким образом, приложение может поддерживать до 2000 HTTP-соединений в пуле в течение 10 секунд.

Третий запуск Jmeter

Пропускная способность улучшилась почти в три раза: с 26 до 71 запросов в секунду.

В целом пропускная способность улучшилась в 10 раз: с 6 до 71 запросов / сек, но мы видим, что максимальное время запроса (maximum time) составляет 7 секунд. Это много и влияет как на общую производительность, так и на задержку в UI.

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

server.tomcat.accept-count=80server.tomcat.max-connections=80 server.tomcat.max-threads=160

Приложение будет отклонять запросы на подключение и отвечать ошибкой "Connection refused" (отказ соединения) всем клиентам, как только количество подключений достигнет 160.

Четвертый запуск Jmeter

Теперь максимальное время составляет меньше пяти секунд и число запросов увеличилось с 71 до 94 запросов в секунду. Процент ошибок ожидаемо увеличился до 29%. Это все ошибки "Connection refused".

Заключение

В этой статье мы продемонстрировали реальный сценарий повышения производительности в 15 раз с 6 до 94 запросов / сек без каких-либо сложных изменений кода. Кроме того, упомянутые выше шаги позволяют снизить стоимость инфраструктуры, такой как AWS. Возможно, для вашего следующего проекта вам стоит подумать об использовании микросервисов. Хотя одна из тенденций последних лет переход к бессерверной архитектуре, но вы должны всё взвесить при переходе к такой архитектуре.

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


Узнать подробнее о курсе "Highload Architect".

Смотреть открытый вебинар по теме Репликация как паттерн горизонтального масштабирования хранилищ.

Подробнее..

Cypress и его место в нашей тестовой пирамиде

18.05.2021 08:17:48 | Автор: admin

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

Введение в Cypress

Если отбросить капитанское определение, что Cypress это JavaScript-фреймворк для тестирования, то важно отметить, что при работе с ним мы видим на экране браузер. Он не обязательно открыт, он может быть headless, но он есть, и он открывает особое приложение самого Cypress, которое состоит из нескольких фреймов: в одном фрейме открывается продукт, который мы тестируем, в другом фрейме запускаются тесты. Код тестов пишется на JavaScript, поэтому они могут выполняться непосредственно в браузере ведь это нативный для него язык.

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

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

Нет Selenium WebDriver

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

Selenium WebDriver это third-party сервис на Java, который обращается к браузеру по WebDriver протоколу. Это накладывает ограничения на работу с браузером в рамках протокола. Сетевое взаимодействие также вносит свой вклад во время выполнения тестов.

Изначально Selenium был создан не специально для тестов, а как общий инструмент автоматизации для браузера. Cypress, в отличие от него, сфокусирован на решении конкретной задачи, а именно, на создании end-to-end (е2е) тестов для интерфейса web-приложений.

Все в одном

Cypress не нужно собирать из кусочков он принес все достаточно современные "батарейки" с собой:

  • Синтаксис BDD (унаследовано из Mocha): describe(), context(), it().
    А также хуки: before(), beforeEach().
    Использовать такой DSL привычно для тех, кто уже писал юнит-тесты на JavaScript.

  • Библиотека ассертов (унаследовано из Chai). Например:
    expect(name).to.not.equal("Jane") ожидание того, что элемент не существует это не то же самое, что ожидание неудачи при проверке существования элемента. Если элемента нет, то это хорошо, это не нужно перепроверять, а нужно идти дальше.
    Такую задачу должен решать тестовый фреймворк, и этого нам очень не хватало в старой самописной библиотеке, при использовании которой многое ложится на плечи разработчика теста.

  • Перехват, отслеживание (spy) и подмена (mock) запросов браузера к бэкенду.

Development experience

Главное преимущество Cypress это отличный development experience. Написать первый тест для своего проекта (неважно, на каком языке написан сам проект) можно минут за 10. Потребуется добавить одну зависимость в package.json (npm install cypress), прочитать документацию про то, куда складывать файлы (cypress/integration/login.spec.js), и написать код в 5 строчек:

describe('Login', () => {it('should log in with credentials', () => {cy.visit('/login');cy.get('[name=login_name]').type(Cypress.env('login'));cy.get('[name=passwd]').type(Cypress.env('password'));cy.get('[name=send]').click();cy.get('.main-header').should('be.visible');});});

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

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

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

Одна из Best Practices говорит, что не нужно никогда писать таймаут типа "подождать 2 секунды". Абсолютно все таймауты должны ждать чего-то осязаемого, например, окончания Ajax-запроса. Можно подписаться на событие, которое случается в коде продукта. Например, когда нам через веб-сокет прилетает событие с бэкенда, то срабатывает определенный listener на фронтенде.

Вся документация Cypress и Best Practices находятся на одном сайте docs.cypress.io хотелось бы отдельно отметить высокое качество этой документации, а также мастер классов, которые команда разработки Cypress проводит и публикует в открытом доступе.

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

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

Тестовая пирамида

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

Как бы то ни было, к нам это не относится у нас несколько тысяч PHPUnit-тестов с покрытием около 12% строк кода.

В то же время у нас есть еще несколько тысяч е2е-тестов с Selenium, которые проверяют все возможные конфигурации продукта, занимают кучу времени (подмножество, запускаемое на каждый коммит, мы смогли оптимизировать до 40-60 минут), имеют довольно слабый уровень доверия (с вероятностью 30-40% тесты упадут, хотя коммит не содержит причины этого падения) и покрывают около 30% строк кода.

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

Наш подход к написанию тестов

Проект, о котором идет речь, это контрольная панель Plesk. Она предоставляет пользователям интерфейс для управления хостингом веб сайтов. Функциональность панели доступна не только через UI, но и через API и CLI, которые используются для автоматизации.

Мы начали с того, что сделали следующие предположения:

  • Тесты на Cypress относятся чисто к UI. Мы не относим сюда тесты, у которых шаги выполняются через API или CLI.

  • Мы не проводим никакой дополнительной валидации, кроме той, что выполняется средствами UI. Например, если мы проверяем создание домена, то мы не отправляем запросы для проверки Web-сервера или DNS, мы считаем тест пройденным, если в UI появилось сообщение на зеленом фоне о том, что домен создан успешно. Такой подход избавляет нас от предварительной подготовки и написания тестовых сценариев.

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

Наш опыт работы с Cypress в сочетании с официальными рекомендациями привел нас к использованию следующего набора практик:

Сбрасывать состояние продукта

Мы сбрасываем состояние продукта до исходного перед запуском каждого набора тестов (Cypress рекомендует делать это перед запуском каждого теста, но мы используем облегченный вариант). Мы создаем дамп базы данных и восстанавливаем его перед прогоном каждого набора тестов (test suite / spec). Это занимает порядка 5 секунд.

before(cy.resetInstance);//=> test_helper --reset-instance//=> cat /var/lib/psa/dumps/snapshot.sql | mysql

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

Использовать фикстуры

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

cy.setupData(subscription).as('subscription');//=> test_helper --setup-data < {domains: [{ id: 1, name: "example.com" }]}

Такие объекты не будут выполнять полноценные пользовательские сценарии, но для тестирования UI их будет достаточно.

Использовать прямые URL

Мы не используем навигацию и попадаем в нужные места UI по прямым URL-ам. Мы вызываем свою специальную команду login, которая создает сессию, а затем переходим прямо на нужную страницу.

beforeEach(() => {cy.login();cy.visit('/admin/my-profile/');});

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

Фронтенд без бэкенда

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

const lastChecked = 'Jan 29, 2021 04:42 PM';cy.intercept('POST', '/admin/home/check-for-updates', {status: 'success',lastChecked,newVersion: null,whatsNewUrl: null,}).as('checkForUpdates');cy.get('[data-name="checkForUpdates"]').click();cy.wait('@checkForUpdates');cy.get('[data-name="lastCheckedDate"]').should('contain', lastChecked);

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

Стабильность тестов

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

Дожидаться выполнения Ajax-запроса

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

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

cy.intercept('POST', '/admin/customer/create').as('customerCreate');cy.get('[name=send]').click();cy.wait('@customerCreate');cy.get('.msg-box.msg-info').should('be.visible');

Дожидаться исчезновения индикатора загрузки

Кое-где в нашем интерфейсе фоновые операции, например, обновление списка, сопровождаются анимированным индикатором загрузки ("крутилкой"). Именно на таких страницах после окончания Ajax-запроса случается ошибка "element has been detached from the DOM" при попытке Cypress кликнуть на элементы списка. Поэтому мы добавляем после Ajax-запроса дополнительную строку, которая проверяет, что индикатор загрузки не виден.

cy.get('.ajax-loading').should('not.be.visible');

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

Ajax-запросы после окончания теста

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

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

В качестве workaround можно переходить на пустую страницу, чтобы браузер сбрасывал все активные Ajax-запросы. Для этого добавляем в support/index.js

afterEach(() => {cy.window().then(win => {win.location.href = 'about:blank';});});

Первые результаты

За 3 человеко-месяца (3 итерации) мы получили следующие результаты:

  • 335 тестов на Cypress (разбиты на 84 спеки)

  • Пайплайн полностью выполняется за 35-40 минут, из которых сами тесты занимают 20 минут

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

  • Уровень доверия выше 95% (то есть вероятность flaky падения ниже 5%)

  • Покрытие интерфейса 35% (ниже расскажу подробнее)

Пайплайн для запуска тестов

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

Как и для большинства наших задач, пайплайн запускается в Jenkins и хранится в Jenkinsfile вместе с кодом проекта.

Линейный пайплайн

В первом заходе получился простой линейный пайплайн.

Мы запускаем Docker-контейнер с Plesk в фоновом режиме и ждем, когда он будет доступен в локальной сети. Потом запускаем другой контейнер с Cypress и кодом тестов, он подключается к Plesk и выполняет все тесты, а мы ждем его завершения (не делаем detach).

Мы запускали тесты на машине с 12 ядрами, которая используется у нас для сборки Plesk и ряда его служб. В течении рабочего дня у нас бывает до 20-30 сборок. В результате Load Average достигал 20, и многие соседние процессы "вставали". Мы добавили ограничение на количество исполняемых сборок до 3-5. Но и этого оказалось недостаточно, соседи по железу продолжали жаловаться на нагрузку.

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

Пайплайн с параллельными шагами

Чтобы как-то ускорить процесс, мы решили воспользоваться Jenkins EC2 Fleet plugin, который предоставляет Jenkins slave ноду по требованию из Autoscaling Group в AWS и уничтожает неактивные ноды после некоторого простоя. Такой подход позволяет тратить деньги на аренду ресурсов только тогда, когда они необходимы.

Переход на spot-инстансы позволил нам существенно сэкономить: вместо $150 в месяц за ondemand c5.xlarge, мы стали тратить около $60 за c5.xlarge и более мощные c5.2xlarge.

А главное, мы можем делать столько одновременных запусков, сколько нам нужно.

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

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

Пайплайн с параллельными тестами

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

cypress run --spec $(find 'cypress/integration' -type f -name '*.js' | awk '(NR - ${RUNNER}) % ${TOTAL_RUNNERS} == 0' | tr '\n' ',')

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

В итоге мы укладываемся в приемлемые 35-40 минут для всего пайплайна, а время одной пачки тестов занимает примерно 20 минут.

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

Измерение URL coverage

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

Для анализа тестового покрытия UI мы решили воспользоваться продуктовой аналитикой и сравнить данные, полученные от тестовых инсталляций, с данными от реальных пользователей. У нас уже был сервис, аналогичный Google Analytics, для сбора пользовательских метрик, а тестовые данные складывались отдельно и никем не использовались. Из множества метрик мы отфильтровали события о посещенных URL-ах (страницах) продукта, начали сохранять эти данные в удобном для нас виде в базу данных и составлять отчет по посещенным адресам.

По полученным данным, за счет всего автоматического и ручного тестирования внутри компании мы покрываем около 60% URL-ов, которые посещают реальные пользователи в течении месяца. Наши старые тесты покрывают около 25%, а новые тесты на Cypress уже достигли 35%.

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

Следующие шаги

Ускорить сборку Docker

Одна из проблем, над которой мы хотим поработать ускорение сборки контейнеров Docker. Как уже было сказано выше, мы создаем временный сервер в AWS (slave node) для каждой сборки Docker, и эта сборка на данный момент занимает в среднем 8 минут. Но поскольку каждый временный сервер новый, то мы совершенно не используем преимущества кэширования, а хотелось бы ими воспользоваться. Поэтому сейчас мы исследуем возможность использования BuildKit. Альтернативными решениями могут стать Kaniko или AWS CodeBuild.

Сократить количество е2е тестов

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

Основная идея: перенести все UI-тесты в Cypress, а в старом фреймворке оставить только CLI-тесты с детальными проверками. Поэтому для каждого UI-теста из старого фреймворка мы делаем следующее:

  1. Заменяем UI-шаги на CLI (если это возможно).

  2. Удаляем, если уже есть аналогичный тест с CLI.

  3. Если проверка возможна только через UI уносим ее в Cypress.

Например, при создании домена проверяется то, что он резолвится, и что на нем работают определенные скрипты. Эти проверки останутся только для создания домена через CLI. А тест на UI в Cypress будет проверять только появление сообщения о создании домена.

В результате мы избавимся от дублирования тестовых сценариев, сократим нагрузку на сервера с Selenium и в перспективе совсем от них избавимся, когда тестирование UI будет делать только Cypress.

Заключение

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

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

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

Подробнее..

Монтируем видео на облачном сервере в AWS

01.05.2021 20:09:31 | Автор: admin

Мой рабочий компьютер - Macbook Air 2020 (Intel), и его вполне хватает для написания кода и прочих задач. Однако, когда потребовалось смонтировать небольшой видеоролик, выяснилось что мощи моего ноута катастрофически не хватает, и я стал искать варианты.

Что я пытался сделать

Я не занимаюсь профессиональным монтажом видео, и впервые уткнулся в эту тему пытаясь сделать вот такой небольшой демонстрационный ролик для Teamplify (с озвучкой помог Мэтт, наш учитель английского):

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

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

  2. Записать это единым куском практически невозможно - то замешкаешься где-то, то ошибешься, то интернет подтупит;

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

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

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

Монтаж видео требует ресурсов

Мои попытки работать с видео на Macbook Air были похожи на мучение. Оказалось, что After Effects любит побольше памяти, и моих 16ГБ явно не хватало. Ноутбучный проц и слабая видюха также не улучшали картину. Превью в After Effects работало с сильными лагами. Финальный рендер трехминутного ролика занимал 3 часа (!!).

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

Что нам может предложить AWS?

Мне он предложил примерно следующее:

  • Регион eu-north-1 (Стокгольм), пинг до меня ~30мс (я живу в Вильнюсе), до Москвы чуть побольше, но тоже неплохо - около 40мс;

  • Сервер g4dn.2xlarge - 8 ядер, 32ГБ, Nvidia Tesla T4, 225 GB NVMe SSD;

  • Образ винды с дровами от Nvidia;

  • Цену в $1.166 в час. И это кстати еще одна причина выбрать Стокгольм, ибо во Франкфурте на ~12% дороже.

Разумеется, можно взять и побольше, и поменьше. На момент написания статьи цены в Стокгольме такие (инстансы с Nvidia Tesla T4, на винде):

Подготовка к работе

Для коннекта к серверу я использовал Microsoft Remote Desktop. Сначала я думал, что мне потребуются какие-то специальные клиенты, рассчитанные на стриминг видео, но оказалось что и обычный Remote Desktop неплохо справляется, никаких особенных лагов я не замечал.

Остается решить вопрос с диском и доставкой исходников на него. Тут амазона предлагает нам два варианта - EBS и Instance Store. Отличаются они следующим:

  • EBS - подключаемый сетевой диск, по надежности примерно как RAID 1. Такой диск в вашем сервере обязательно будет как основной, по умолчанию он небольшого размера (достаточного чтобы влезла операционка), но вы можете при желании его расширить. Данные на EBS сохраняются и после выключения сервера. Платите вы за такой диск постоянно, даже если сервер выключен, в размере $0.0836 за ГБ в месяц (в версии gp3, burstable IOPS). У EBS есть разные варианты по производительности. Можно купить гарантированную производительность, но тогда она может влететь в копеечку, или же можно остаться на стандартном gp3, который основан на модели burstable IOPS. Когда диск простаивает, у вас накапливаются кредиты на IO, а когда он активно используется - они расходуются. Подробнее можно почитать в доках.

  • Instance store - так называемый эфемерный диск, который может идти в комплекте к некоторым типам инстансов. В частности, к g4dn.2xlarge прилагается 225 GB NVMe SSD. Он быстрый, производительность ничем не ограничена, однако данные на нем полностью пропадают при выключении сервера (при перезагрузке - остаются).

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

Когда диск готов, нужно как-то доставить на него исходники. Я использую для этого pCloud (аналог Dropbox), который установлен и на моем ноуте, и на облачном сервере. При старте сервера на нем запускается небольшой батничек, который инициализирует расшаренную папку pCloud (для исходников и результатов) и заодно создает папку для кеша After Effects:

mkdir Z:\"Teamplify Videos"mkdir Z:\"AE Cache"

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

Как возможную альтернативу Dropbox / pCloud можно еще рассмотреть что-то вроде ownCloud с хранилищем на S3. Если исходники будут выкачиваться из S3 в том же AWS регионе, что и ваш сервер, то это должно быть очень быстро, что может иметь значение при большом размере исходников.

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

И как это все работает?

Да вроде неплохо. Превью в After Effects нормальное, без лагов. Поскольку пинг до сервера хороший, работа на нем почти не отличается от работы с настольным компьютером. Рендер того ролика, который у меня на ноуте выполнялся три часа, на g4dn.2xlarge делается за 13-17 минут. День работы на таком сервере обходится в несколько долларов.

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

Подробнее..

Почему в AWS все так сложно с прайсом и правами? Как избежать политических блокировок и защитить данные в облаке?

10.03.2021 14:15:34 | Автор: admin


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


Спикер вебинара Александр Волочнев (Developer Advocate в DataStax Inc.) и Всеволод Севастьянов (TechLead в vene.io) ответили на вопросы о прайсе и правах в AWS, рассказали, как защитить данные и в каких ситуациях лучше выбрать российских облачных провайдеров.


Зачем Openstack от %anyvendor% если есть открытая ванильная версия, разрабатываемая огромным количеством талантливых разработчиков?


Всеволод Севастьянов: Вопрос классный, если уточнить, что такое Openstack, так как есть 15 компаний, которые контрибьютят своих разработчиков на разработку непосредственно самого Openstack (HP, IBM и др.). И то, что они себе устанавливают, это по сути есть Openstack для их клауда с какими-то обертками, свистелками от непосредственно самих вендоров. Что выбирать для себя? Вопрос. Если вы берете Openstack, чтобы поставить на свои сервера, берите Openstack, если вам ничего сверху не надо. Если вы будете работать с HP-шными железками или с вещами, которые они вам предоставляют для облачных вычислений, для нейросетей или для коннекшена к облаку самого HP, берите HP-шный Openstack.


Александр Волочнев: Тут я должен сделать шаг в сторону и сказать, что не все знают, что такое Openstack, у нас вебинар для начинающих разработчиков. Openstack это возможность самому сделать свое собственное облако, то есть это такая система управления всяким железом и всем остальным, где с одной стороны сидите вы сами и запихиваете новые сервера, а с другой стороны люди пользуются этим как облаком. Обычно это для больших компаний актуально, где есть отдел, который делает все то же самое, что делает AWS, и есть отдел, который это все обеспечивает. То есть это такое домашнее облако, и есть несколько его поставщиков. Хороший вопрос, на который сложно однозначно ответить. Это как есть Linux Kernel, есть Ubuntu. Несколько холиварная тема, которую я пока что закрываю.


Почему в AWS все так сложно с прайсом? Сложно понять, сколько в итоге будет стоить проект?


Александр: Сложно, потому что AWS это система, которую инженеры создавали для инженеров. А когда инженеры берутся разрабатывать какую-то систему, они думают о том, чтобы все было технически правильно, а не просто. Большой проект иногда бывает проще разработать и внедрить, чем просчитать. Потому что AWS пошло по пути сверхточного вычисления, плюс у каждого сервиса есть отдельные классы, например, у сервиса хранения Simple Storage есть несколько классов хранения файлов. На одном классе хранения файлов у вас файлы будут храниться чуть подороже, но с вас не будут браться деньги, когда их кто-то скачивает, на других классах файлы будут храниться подешевле, но с вас будут браться деньги, когда их кто-то скачивает, причем первые 100 Гб с вас будут брать одну сумму, последующие 100 Гб с вас будут брать другую сумму. При этом, чтобы окончательно всех запутать, есть еще Intelligent Tiering, когда у вас файлы будут прыгать между слоями в зависимости тот того, как будет вам выгоднее, по мнению AWS.


И это я только про хранение файлов говорю в одной конкретной корзине. Если мы говорим про AWS Lambda, бессерверные приложения, там тоже красиво, потому что отдельно считается время, отдельно считаются запуски и отдельно считается потребление памяти в Гб/мс. На самом деле они хотели как лучше. Они хотели предоставить вам оплату потребления только того, что вы действительно потребили. Но поскольку они отдельно считают коннекшены, отдельно потребление, отдельно то-се, пятое-десятое Когда считаете какой-то проект, во-первых, посчитайте, что тарифицируется. Надо учитывать нюансы. Если вы, например, храните маленький файл в их AWS S3 Glacier, ледник служба длительного хранения файлов на магнитных лентах, самое дешевое хранилище, но не самое быстрое, надо учитывать, что там минимальный размер файла считается 100 с чем-то Кб, то есть надо учитывать, что если вы туда положили файл в 1 Кб, платить вы будете как за 100 Кб. Много нюансов, обсчет сложный. Это характерно для продуктов, разработанных инженерами для инженеров.


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


Всеволод: Я могу добавить? В защиту AWS хочу сказать, что там данные потребления непосредственно трафика, ресурсов и т.д. берутся с физического сервера. И этот физический сервер может отвечать за несколько типов данных, и этих серверов может быть много, они могут быть объединены в датацентр или колокейшн, разделены по зонам, вы это все используете, все это надо собрать и в конце дня вам доставить. Это непростая задача сама по себе. То есть причины для задержек есть, и они достаточно объективны. Никто не хочет нажиться на бедных разработчиках.


Как избежать чека в $1000, когда ожидаешь максимум $100-200, и при этом не остаться с заблокированным сервисом в час-пик?


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


Александр: У автоскейлинга всегда можно задать верхнюю границу. Теперь мой вариант ответа. Во-первых, все, что сказал Всеволод. Во-вторых, проблема общая, все приходят с этими вопросами. Как избежать чека? Нужно понимать, что вы потребляете, где у вас точки расходов, потому что есть, например, условно бесплатные сервисы. И во всех точках расходов можно задать верхний предел масштабирования. Вы используете AutoScaling groups? Ну, пожалуйста, можно задать максимальное количество серверов, после которого вы согласны падать.


Создавая AutoScaling group, вы задаете минимальное и максимальное значение. Не ставьте там 100 серверов, поставьте 20, если у вас маленький сервис и вы напрямую не монетизируетесь с пришедших клиентов, и то же самое возможно для всех остальных сервисов. Ставьте ограничения, ставьте лимиты. Это вполне себе работает.


Почему так сложно управлять правами доступа в AWS (IAM)? (Прописывание policy вручную, boundary и т.д.)


Александр: Я сначала отвечу на вопрос почему, а потом на вопрос как. Представьте себе на одной стороне отрезка самокат, а на другой самолет, Boieng 777 или что-то подобное. Самокат прост и интуитивно понятен. Вы можете с первого раза встать на него, поехать и через несколько минут с ним справиться, а пару раз набив шишки уже делать какие-то трюки. Порог вхождения низкий, возможности низкие. Вы не можете на самокат посадить себя, своего пьяного друга и два ведра грибов из леса. Мощность низкая, простое управление.


Мы начинаем говорить про мощные системы. Identity and Access Management для тех, кто может быть не знает, это система управления правами доступа в AWS, очень мощная. Она позволяет вам генерировать такие правила, что пользователю Васе разрешено будет использование такого-то сервиса с редактированием при, не знаю, восходящей фазе луны в три часа ночи после крика петуха, но не будет доступно все остальное время, и т.д. Любая мощная система не может быть простой. Это закон природы. Из хороших новостей. Да, порог вхождения высокий, но когда привыкаешь, все становится хорошо. И все эти штуки нужные, хорошие и правильные.


Boundaries в начале можно не использовать. Для небольших проектов они не критичны. Начинайте с простого. В целом описание правил и политики доступа в IAM это очень классная вещь. Ее здорово настраивать. Сложные системы не могут быть с низким порогом вхождения.


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


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


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


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


Александр: Биллинг любой системы сложнее велосипеда будет отставать, потому что это чертовски сложно. Есть возможность сделать биллинг быстрым. Но ценой потребления ресурсов с вашего сервера. То есть биллинг у вас будет риал-тайм, а сервер будет работать медленнее. Вы точно этого хотите? Всегда есть риск, что выйдет чек в тысячи долларов. Есть. Так вы границы задавайте. Все. Ставьте ограничение, кеширование, тротлинг на API Gateway.


Всеволод: Справедливости ради стоит отметить, что найти эти AutoScaling groups с первого раза сложно, плюс они по умолчанию настроены очень широко.


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


Как подстраховаться от политической блокировки в облаке, и насколько оправдано стремление к гибридному облаку?


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


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


Насколько оправдано стремление к гибридному облаку?


Александр: Очень зависит от вашего проекта. Гибридное облако это когда часть проекта у вас запущена в AWS, а часть проекта запущена в вашем собственном датацентре. И они взаимодействуют друг с другом. Насколько это оправдано? Для небольших и средних проектов, я бы сказал, это не оправдано чаще всего. Для больших проектов это может быть оправдано, так как это может быть оптимальным способом уменьшения расходов. Все зависит от вашего юзкейса. Если вы хотите создать максимальную доступность и пережить падение облака, такое тоже возможно. Но это очень сложно, и для этого нужны очень хорошие спецы. То есть снова для большинства проектов это будет неактуальным. Проще, конечно, одно чистое облако. Любые интеграции буду всегда сложнее.


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


Александр: CAPEX (capital expences, капитальные расходы) подразумевается, что когда компания покупает новые сервера, она тратит много денег, ставит сервера себе как основные средства. И есть OPEX (operational expences), которые относятся к аренде, и если вы целиком в облаке, у вас все расходы на инфраструктуру являются операционными, и они списываются по-другому. Для некоторых компаний это может быть очень важно с точки зрения бухгалтерии и налогообложения.


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


Александр: Как говорят AWS и, полагаю, Azure тоже: Security is a shared responsibility. Безопасность это разделенная ответственность. Имеется ввиду, что часть безопасности организовывает облако, но как бы они ни старались, если вы со своей стороны о безопасности не позаботились, они вам ничем помочь не смогут. То есть это общая ответственность. Хотите безопасность, изучайте, как организовать безопасность.


И второй момент надо понимать, что с GCP, с Amazon работают очень серьезные американские правительственные компании, у которых сверх строгие требования по шифрованию и хранению данных. И облака регулярно проходят всевозможные виды аудитов, чтобы подтвердить, что у них есть все необходимое: все виды изоляции, все защиты, шифрования и сертификаты все вообще, что может только потребоваться. И для совсем Advanced-кейсов можно использовать Outpost, то есть можно разворачивать инфраструктуру AWS на базе вашего собственного железа.


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


Я рекомендую организовывать бастионы, то есть некоторые сервера-прокси, точки входа, изолировать базу данных внутри кластеров, настраивать сервисы Kubernetes так, чтобы они не отвечали ни на что, кроме white-listed IP или white-listed services, ну, и так далее, потому что это большой топик.


Что вы думаете насчет отечественных cloud-провайдеров, Yandex, Selectel? Просто ваше мнение и опыт использования, если есть.


Александр: Здесь все просто. У меня есть небольшое участие в разработке одного из околооблачных поставщиков в России, опыта использования нет, потому что я почти сразу после этого переехал из России и ни про Yandex, ни про Selectel не могу рассказывать.


Всеволод: Последний раз, когда я изучал этот рынок, помимо Яндекса и MCS все остальные провайдеры использовали в некотором смысле openstack-решения. И у них были очень классные решения поверх openstack и очень классный менеджмент. В целом если вы держите бизнес в России, наверное, имеет смысл. У Амазона, например, нет региона Россия.


Александр: Да, у GCP, по-моему, тоже. Если вы держите данные ваших пользователей в России, то Yandex и Selectel могут быть для вас хорошим выбором.


После вашего курса смогу ли я запустить свой проект (небольшой) в AWS c пониманием дела? Смогу использовать нужные абстракции и т. д.?


Александр: Да, безусловно, он для этого и разработан. Я прицеплю сюда еще вопрос ниже: У меня уже есть AWS-SAA01, стоит ли покупать курс Слёрм. Насколько он будет мне полезен? Один из ценных моментов курса возможность задать вопрос и быть услышанным. У Амазона с этим сложно, как правило, такой возможности нет. Я готов взаимодействовать и отвечать на вопросы.


Если вы хотите использовать какие-то сложные вещи, про них мы, может быть, в курсе и не говорим. Например, Амазон предоставляет роскошнейшие возможности для machine learning, у них там все автоматизировано, интегрировано, вообще супер. И это в облаке вообще огонь. Но про это мы не рассказываем в базовом курсе, потому что где базовый курс, а где machine learning? Если вы планируете использовать Fargate, про него мы не рассказываем в базовом курсе, но все стандартные вещи: EC2, S3, AutoScaling, базы данных, Serverly, Lambda, API Gateway, инфраструктура как код, которая помогает вам управлять вашим проектом, и т. д. это все есть.


Почему в России большинство компаний все еще косо смотрит на облака (в пользу in-house инфраструктуры) при всех их преимуществах? Когда ожидать сдвига в мышлении?


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


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


Сколько требуется времени для получения опыта или равноценного сертификата, который требуют работодатели для Cloud DevOps Engineer?


Александр: Во-первых, я не знаю, каких сертификатов требуют работодатели для Cloud DevOps Engineer. Если говорить про стандартные младшие позиции, если вы не претендуете на Senior Cloud DevOps, то у меня лично подготовка и сертифицирование для GCP заняла ровно месяц. Мне надо было перенести опыт архитектуры и разработки с AWS на GCP. Но это было много работы, я серьезно по много часов в день вкладывался. Что касается младших должностей, мне кажется, в качестве сайд-проекта базовую сертификацию в направлении Сloud DevOps нужно делать тоже за месяц. Если заниматься этим по паре-тройке часов в день, то это возможно. Это дело интересное и очень неплохо оплачивается в очень многих компаниях.


IAAS не всегда решает вопрос рабочих мест. Есть ли альтернативные способы реализации виртуальных рабочих мест кроме RDS (не гибко) и VDS (дорого)?


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


Amazon Outpost. Зачем и как применять?


Александр: Это классная возможность, когда вы можете поднять свой собственный ЦОД, и вы можете запустить весь софт AWS на вашей стороне, и вы будете использовать его как полностью интегрированный в инфраструктуру Амазон, но при этом это будет ваше железо, которое стоит у вас и которое охраняется вами, обеспечивается электричеством вами и т. д. Вот что такое Amazon Outpost. Зачем и как применять? Как применять не расскажу, потому что до сих пор не приходилось, это очень специфичный кейс. У меня нет опыта с Outpost никакого, просто никогда не было необходимости. Зачем? В некоторых ситуациях есть супер-строгие требования по аудиту, системам безопасности и т. д. то есть только у вас должны храниться данные и никуда они не должны попадать, с точки зрения аудита.


Какова разница между курсами Слёрма и AWS training?


Александр: Со своей стороны скажу вот что: AWS я больше изучал на практике и отдельно знакомился с некоторыми курсами, которые у них есть. С точки зрения организации обучения, мне очень понравился Google Cloud Platform. Он вперед на милю от AWS с точки зрения организации процесса, материалов для подготовки и т. д. Первая разница между курсами Слёрм и AWS: AWS на английском. Если у вас плохой английский, Слёрм здесь однозначно будет лучшим выбором. У AWS есть тренинги практически на любую тему. Не всегда полные, не всегда хорошие, но они есть. У Слёрм на данный момент есть только один курс по AWS. Это базовый курс, который закрывает все основные юзкейсы и самые наиболее часто используемые сервисы. Но если вам нужен какой-нибудь хитровывернутый кейс, то этого может не оказаться в нашем курсе, опять-таки, курс называется базовый. И последнее Слёрм обеспечивает определенную поддержку: можно написать, можно сказать, что в практике написано вот так, у меня так не получается, что пошло не так? В AWS Training писать будет некому.


На сколько порядков отличается цена за единицу ресурсов облака для Netflix и стартапа?


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


Где границы между разумным использованием Iaas, PaaS, SaaS?


Александр: Все зависит от того, как много у вас специалистов в этой отрасли, насколько у вас хватает мощностей. Первое правило аутсторса: аутсорсить то, что для вас не принципиально, то, на чем вы не зарабатываете деньги, что не является ключом вашей бизнес-модели. Если вы делаете что-то, что не является для вас принципиальным, это склоняет вас ближе к SaaS. Saas и PaaS очень близки. Вы разрабатываете бессерверное приложение: у вас база данных будет SaaSом, а приложение ваше будет запущено на PaaSе. Я про это рассказываю в восьмом модуле курса. Если у вас много крутейших специалистов, вы Apple, и вы хотите иметь полный контроль над всем железом, то вы ближе к IaaSу или к on-premices собственному датацентру.

Подробнее..

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Подробнее..

Перевод Terraform в AWS несколько аккаунтов и другие хитрости

19.03.2021 08:14:45 | Автор: admin


В этой статье поговорим о нюансах использования Terraform от HashiCorp, в частности о том, как использовать Terraform при управлении несколькими аккаунтами Amazon Web Services (так делают все чаще из-за размера организации или предпочтений команды DevOps). По сути, AWS сами намекают клиентам, что неплохо было бы использовать несколько аккаунтов, и недавно даже выпустили для этого несколько сервисов.


Зачем нужно несколько аккаунтов AWS?


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


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


На практике крупные организации из-за своих размеров уже используют несколько аккаунтов AWS, но эти аккаунты никак не связаны. Это серьезно усложняет жизнь отделам закупок на каждый аккаунт AWS нужен отдельный счет, причем организация может группировать счета в соответствии со своими внутренними правилами или нормативными требованиями. Чтобы упростить работу, можно использовать AWS Organizations для управления иерархией аккаунтов и объединения счетов по группам. Недавно AWS представили AWS Control Tower для подготовки новых аккаунтов с предустановленным набором ресурсов и централизованным управлением всеми аккаунтами.


Новый тренд


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


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


Этот тренд влияет на Инфраструктуру как код (IaC) например, при использовании Terraform. Инструменты IaC обычно по умолчанию привязаны к одному аккаунту AWS. С самого начала в Terraform могло быть несколько так называемых провайдеров в одном скрипте, чтобы получать доступ к нескольким аккаунтам AWS или даже других облачных вендоров.


Инфраструктура как код с несколькими аккаунтами


Управление ресурсами в разных аккаунтах


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


По умолчанию блок провайдера AWS работает в аккаунте, данные которого использовались для подключения к AWS API. Например, если вы используете идентификатор ключа доступа/секретный ключ доступа определенного пользователя AWS, Terraform будет ссылаться на аккаунт этого пользователя. Код Terraform:


provider aws {region = us-east-1}

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


provider aws {  region = us-east-1  assume_role {    role_arn = arn:aws:iam::123456789012:role/iac  }}

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


Промежуточная роль для доступа к третьему аккаунту


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



Рис. 1. Схема промежуточной роли для доступа к финальному аккаунту AWS


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


Другие продвинутые стратегии Terraform


Несколько стейтов


Если ресурсов относительно много, можно разделить скрипты Terraform на несколько стейтов особенно при использовании continuous deployment (CD). Управление всеми ресурсами в одном стейте имеет недостатки:


  • Каждый раз, когда мы вносим даже незначительные изменения, мы боимся, что Terraform затронет базовые ресурсы, которые трогать не надо.
  • Ошибочные изменения в базовых ресурсах, примененные вслепую в рамках continuous deployment, могут иметь плачевные последствия.
  • Разрешения IAM, которые нужны для выполнения скрипта Terraform, будут затрагивать самые разные задачи. Их будет больше, чем требуется для CD.
  • На применение изменений нужно очень много времени, потому что Terraform будет собирать стейт всех ресурсов, которыми управляет стейт, даже если в большинстве из них ничего не поменялось.
  • Если при деплойменте произойдет сбой, последствия могут быть обширными.

Обычно базовые ресурсы редко меняются. Речь идет о VPC, подсетях, Transit Gateways, VPN, базах данных RDS и балансировщиках нагрузки. Эти ресурсы принадлежат базовому стейту, который почти не меняется, а если и меняется, то руками человека.


Некоторые ресурсы, наоборот, меняются постоянно. Это инстансы EC2, автоскейлинг группы, сервисы в ECS и EKS. Обычно такие ресурсы деплоятся (или обновляются) через пайплайны CD и помещаются в другой стейт, отдельно от базовых ресурсов. Этот отдельный набор скриптов Terraform будет управлять лишь небольшой, быстро меняющейся группой ресурсов, и вам потребуется гораздо меньше разрешений. Такое разделение стейтов Terraform идеально подойдет для автоматизированных деплоев.


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


Модули


Terraform упрощает разбивку кода IaC на модули. Просто поместите код в другой каталог и используйте директиву module:


provider aws {region = us-east-1}module mymodule {source = ./modules/my_modulevariable1 = value1variable2 = value2}

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


Модули Terraform позволяют соблюдать принцип DRY (Dont Repeat Yourself не повторяйся). Но все равно остается шаблонный код (определения в бэкенде и вызовы к самим модулям), который нельзя поместить в модуль.


Окружения


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


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


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


Заключение


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


С помощью советов в этой статье можно создать аккуратный код Terraform в соответствии с принципами DRY.

Подробнее..

Перевод Реализуем бессерверный API с AWS Gateway и Lambda

01.04.2021 16:06:37 | Автор: admin


Без API не обходится ни одно веб-приложение. Для их разработки используются разные методы. Сейчас, например, набирает популярность бессерверный подход он экономичный, масштабируемый и относительно простой. Как ведущий провайдер бессерверных вычислений Amazon Web Services (AWS) вносит огромный вклад в бессерверную разработку. Здесь мы обсудим общие концепции реализации API с помощью AWS Lambda и других сервисов AWS.


Почему именно AWS Lambda?


AWS Lambda это сервис AWS, который отвечает за выполнение определенных функций в ответ на триггеры, то есть события в приложении. Это могут быть HTTP-вызовы, события в других сервисах AWS, например S3, Kinesis или SNS, или повторяющиеся запланированные события. Функции выполняются в эфемерных контейнерах, подготовкой и масштабированием которых занимается AWS, так что разработчики избавлены от хлопот, связанных с инфраструктурой.


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


Роль API Gateway


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


HTTP API


API Gateway включает множество функций и интеграций. В какой-то момент в Amazon поняли, что разработчикам, которые используют бессерверные вычисления, обычно не нужно столько всего. Скорее, они предпочли бы в целом упростить процесс реализации. Наверное, поэтому в конце 2019 года AWS объявили о новых HTTP API, облегченной версии API Gateway, которая существенно упрощает разработку, повышает производительность и снижает расходы для бессерверных API. Несмотря на свою простоту, HTTP API поддерживают такие важные фичи, как настройка CORS для всех конечных точек, интеграция JWT, кастомные домены и соединения с VPC.


Принципы бессерверных API


Чтобы разобраться с главными принципами реализации бессерверных API, рассмотрим лаконичный пример простого приложения виртуальной доски, состоящий из двух конечных точек: POST для записи сообщений и GET для извлечения трех последних сообщений. Рассмотрим и другие возможные функции (параметры пути, CORS и авторизаторы), но постараемся не усложнять финальную реализацию.


AWS DynamoDB


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


AWS Serverless Application Model


Для реализации вам понадобится аккаунт AWS, а также установленный и настроенный фреймворк AWS Serverless Application Model (SAM). SAM это инструмент для создания, обновления и администрирования бессерверных приложений и всех ресурсов, которые нужны ему для работы. С AWS SAM мы не создаем каждый сервис вручную на веб-консоли мы просто описываем все, что нам нужно, в специальном файле шаблона.
После установки CLI переходим в нужный каталог и выполняем команду:


$ sam init -r nodejs12.x -n whiteboard
Инициализация нового проекта


Выбираем первую опцию и нажимаем Quick Start from Scratch (Быстрый запуск с нуля). Создается каталог нашей доски с минимумом установочных файлов.


Определяем необходимые ресурсы


Сначала открываем файл template.yml и удаляем все, что находится под разделом Resources. Прежде чем перейти к самому API, создаем дополнительные ресурсы. Определяем таблицу DynamoDB, где будут храниться сообщения:


Resources:  BoardMessagesTable:      Type: AWS::DynamoDB::Table      Properties:        TableName: board-messages-table        AttributeDefinitions:          - AttributeName: partKey            AttributeType: S          - AttributeName: createdAt            AttributeType: N        KeySchema:          - AttributeName: partKey            KeyType: HASH          - AttributeName: createdAt            KeyType: RANGE        ProvisionedThroughput:          ReadCapacityUnits: 5          WriteCapacityUnits: 5

Объявление таблицы DynamoDB


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


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


BoardHttpApi:    Type: AWS::Serverless::HttpApi    Properties:      StageName: Test      CorsConfiguration: True

Объявление HTTP API


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


Определяем функции обработчиков API


Наконец, определив все API, давайте объявим две функции, связанные с конкретными конечными точками.


PostMessageFunction:      Type: AWS::Serverless::Function      Properties:        Handler: src/handlers/postMessage.handler        Runtime: nodejs12.x        MemorySize: 128        Timeout: 5        Events:          PostMessage:            Type: HttpApi            Properties:              ApiId: !Ref BoardHttpApi              Method: POST              Path: /messages        Policies:          - AmazonDynamoDBFullAccess  GetMessagesFunction:      Type: AWS::Serverless::Function      Properties:        Handler: src/handlers/getMessages.handler        Runtime: nodejs12.x        MemorySize: 128        Timeout: 5        Events:          GetMessages:            Type: HttpApi            Properties:              ApiId: !Ref BoardHttpApi              Method: GET              Path: /messages        Policies:          - AmazonDynamoDBFullAccess

Объявление обработчиков для запросов POST и GET


Тут все понятно: две функции, одна из которых будет вызываться при запросе POST к пути /messages, а другая при запросе GET к тому же пути. У обеих функций есть ограничения на 128 МБ оперативки и пятисекундный таймаут. Код функций находится в файлах postMessage.js и getMessage.js в каталоге /src/handlers/. Создадим их прямо сейчас. (Мы предоставили полный доступ к DynamoDB в разделе Policies каждой функции, чтобы упросить код. В реальном проекте доступ нужно будет настроить более тонко).


Написание функций


Идем в каталог /src/handlers и создаем файлы со следующим содержимым:


postMessage.js


const AWS = require('aws-sdk');const dynamodb = new AWS.DynamoDB();exports.handler = async (event) => {  const { body } = event;  try {    const { author, text } = JSON.parse(body);    if (!author || !text) {      return {        statusCode: 403,        body: 'author and text are required!'      }    }    await dynamodb.putItem({      TableName: 'board-messages-table',      Item: {        msgId: { S: 'board' },        author: { S: author },        text: { S: text },        createdAt: { N: String(Date.now()) } // still expects string!      }    }).promise();    return {       statusCode: 200,       body: 'Message posted on board!',    }  } catch (err) {    return {       statusCode: 500,       body: 'Something went wrong :(',    }  }};

Код обработчика запросов POST


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


getMessages.js


const AWS = require('aws-sdk');const dynamodb = new AWS.DynamoDB();exports.handler = async () => {  try {    const result = await dynamodb.query({      TableName: 'board-messages-table',      KeyConditionExpression: 'partKey = :partKey',      ScanIndexForward: false,      Limit: 3,      ExpressionAttributeValues: {':partKey': { S: 'board'}}    }).promise();    return {      statusCode: 200,      headers: {        'Content-Type': 'application/json',      },      body: JSON.stringify(result.Items),    }  } catch (err) {    console.log(err);    return {      statusCode: 500,      body: 'Something went wrong :(',    }  }};

Код обработчика запросов GET


В этой функции мы сначала получаем записи, у которых partKey равен board, потом задаем для ScanIndexForward значение false, чтобы последние сообщения отображались сверху, и наконец с помощью свойства Limit указываем, что хотим увидеть только три сообщения.


Развёртывание


Деплоить с AWS SAM легко достаточно одной команды с несколькими введенными значениями. Переходим в root-каталог проекта и выполняем команду:


$ sam deploy --guided

Команда развертывания


Нас попросят ввести имя приложения и выбрать регион AWS, а еще подтвердить несколько действий:



Указание и подтверждение параметров


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



Список создаваемых ресурсов их статусы


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



URL для конечной точки root API


Тестируем API


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


curl -d '{"author":"name", "text":"Message text"}' -H "Content-Type: application/json" -X POST https://your-api-id.execute-api.your-region.amazonaws.com/test/messages

Выполнение запроса POST в curl


Отправляем несколько запросов с разными сообщениями. Если все нормально, в консоли отобразится Message posted on board! (Сообщение опубликовано на доске) без ошибок.


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


curl https://your-api-id.execute-api.your-region.amazonaws.com/test/messages

Выполнение запроса GET в curl


Вот и все. Мы создали простой HTTP API с AWS Lambda и AWS SAM. Конечно, в реальном проекте нужно будет больше функций и конфигураций, но принцип будет тот же: определяем ресурсы, определяем конфигурации, пишем код и запускаем деплой.


Подключение мониторинга Thundra


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


Можно подключить мониторинг Thundra к только что созданным функциям Lambda (см. краткое руководство). После подключения Thundra вам нужно будет инструментировать функции Lambda postMessage и getMessages, чтобы просмотреть подробную информацию о каждом вызове и получить общую картину приложения.


Выбираем функции в списке, нажимаем сначала кнопку Instrument, а затем OK.



Подтверждение инструментирования функции Lambda


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



Сведения об одном вызове


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


Стоит ли использовать HTTP API?


С помощью HTTP API с AWS Lambda можно создавать высокопроизводительные и экономичные API. Хоть это и облегченная версия API Gateway REST API, она обладает всем необходимым функционалом и покрывает 90% нужд разработчиков. HTTP API не поддерживают некоторые полезные функции, вроде кэширования, валидации схем и трансформации ответов.


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

Подробнее..

Recovery mode DevOps автоматизация инфраструктуры на примере Terraform, docker, bash, prometheus exporters, Gitlab и WireGuard

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

Всем привет.

Есть такие люди, которые работают с облачной инфраструктурой и не используют автоматизацию, потому что это долго, нужно вникать, а им надо фичи пилить. Накликали что-то там в UI, подключились по ssh, поставили всякого с помощью apt и т.д. и конфигурационные файлы ещё вручную поменяли. Документации конечно же написать времени не хватило или в ней много разных хитрых шагов и повторить настройку этой инфраструктуры в точности уже нельзя или очень сложно, а сервисы крутятся в проде. А потом человек забыл что и как делал в точности или вообще уволился.

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

К слову, крайне рекомендую для автоматизации много чего, но в особенности облачных провайдеров вроде AWS / GCP / Azure и т.д. использовать именно Terraform, т.к. это достаточно зрелый инструмент, у него большое сообщество и кроме всего прочего он поддерживает автоматизацию далеко не только каких-то облачных провайдеров, но и практически всего у чего есть API. К тому же инструмент open source и при желании можно реализовать что угодно самостоятельно. Для таких облаков, как AWS не рекомендую пытаться реализовывать автоматизации с помощью чистого питона и запросов к AWS API с помощью cli или Cloudformation.

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

Для тех, кто совсем не знаком с Terraform упомяну, что если в одну папку положить несколько файлов с расширением .tf и запустить Terraform в этой папке, то Terraform прочитает и использует код из всех файлов, а не только одного. Это в том числе позволяет разбивать один большой main.tf файл с кучей ресурсов на какие-то удобные вам логические блоки.

Итак, например, встала задача развернуть vpn серверы WireGuard на базе Ubuntu 20.04 в нескольких регионах + немного мониторинга. Поддержка WireGuard сейчас есть в ядре linux, но дополнительные инструменты, которые можно поставить отдельно облегчают жизнь, поэтому поставим и их.

Весь код модуля выложен здесь.

Также этот модуль опубликован в реестре модулей здесь.

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

Итак, создаются необходимые для работы iam политики, роль и т.п.

Используем elastic ip, отдельный для сервера в каждом регионе, которые нужно прописать в dns для того, чтобы пользователь мог использовать единое имя для подключения к vpn серверу. Планировал использовать geo dns route53, чтобы при местоположении пользователя в оперделённом регионе ему бы отдавался ip vpn сервера в его регионе, но т.к. на этом проекте route53 пока не используется, то создание записей в нём пока не автоматизировал.

Создаются security groups с правилами, которые позволяют подключиться к vpn серверу извне по udp (Wireguard работает только по udp) + ssh + несколько портов для prometheus exporter'ов.

Создаётся собственно сервер / ec2 машина, но не просто отдельно стоящая, а входящая в auto scaling group, в данном примере в единственном варианте. Это сделано для того, чтобы если с сервером что-то не так, то Амазон автоматом пересоздаст его. Self healing.

Позже немного допилив конфигурацию и добавив в неё load balancer можно добиться того, для чего auto scaling groups отлично подходят: при повышенной нагрузке на какой-то из ресурсов сервера, например на cpu, можно реализовать автоматическое создание дополнительных vpn серверов, а соответственно при падении нагрузки уменьшать их количество.

Этот модуль можно использовать просто с Terraform, но лучше использовать Terragrunt, который позволяет делать некоторые удобные вещи и местами реализовывать концепцию Keep your Terraform code DRY, например параметризуя некоторые вещи в backend блоке, чего сам Terraform пока не умеет. Terraform хранит состояние инфраструктуры в специальном файле и принято хранить его не локально, а, чаще всего, в S3 бакете. Также, если вы работаете с этим кодом не в одиночку, то принято хранить локи в Dynamodb, чтобы случайно не применить какое-то изменение инфраструктуры несогласованно и не поломать всё.

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

С помощью файла terragrunt.hcl в корне репозитория (https://github.com/vainkop/terraform-aws-wireguard/blob/master/example/terragrunt.hcl) я могу, например, задать место для хранения state для всех поддиректорий, а потом ссылаться на этот файл в других terragrunt.hcl с помощью функции find_in_parent_folders() https://github.com/vainkop/terraform-aws-wireguard/blob/master/example/us-east-1/terragrunt.hcl#L2

При этом key, т.е. файл, где будет храниться состояние инфраструктуры в конкретном регионе будет храниться отдельно, что достигается с помощью функции path_relative_to_include() https://github.com/vainkop/terraform-aws-wireguard/blob/master/example/terragrunt.hcl#L11

Также я реализовал хранение/чтение переменных в yaml формате, что мне кажется более удобочитаемым с помощью функции yamldecode(file(...)) https://github.com/vainkop/terraform-aws-wireguard/blob/master/example/eu-central-1/terragrunt.hcl#L9

Вот так выглядит пример передаваемых в модуль уникальных параметров (конечно YOUR_... нужно заменить на реальные значения): https://github.com/vainkop/terraform-aws-wireguard/blob/master/example/us-east-1/values.yaml

Иногда удобно реализовать использование имени папки в качестве параметра, например в приведённом примере это мог бы быть параметр region и реализуется это с помощью, например, функций basename(get_terragrunt_dir()) и задавать его в values.yaml не пришлось бы, но по определённым причинам решил этого не делать.

В итоге в вашем приватном репозитории код из которого применяете либо вы, либо какой-то ci cd runner может лежать только содержимое похожее на мою папку example, т.е. только terragrunt.hcl и yaml файлы с параметрами, а модуль можно использовать как публичный и хорошо поддерживаемый, так и написать свой. Это позволяет отдать "пользователям" только задание параметров в yaml и в принципе ничего не знать про Terraform код.

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

Для того, чтобы изменения в коде open source модулей, как впрочем и в частных, не повлияли на работу вашей автоматизации принято фиксировать версии используемых модулей, например в моём коде это сделано с помощью source = "github.com/vainkop/terraform-aws-wireguard?ref=v1.2.0" здесь https://github.com/vainkop/terraform-aws-wireguard/blob/master/example/eu-central-1/terragrunt.hcl#L6

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

Например я реализовал cloud-init скрипт, который осуществляет предварительную установку и настройку софта на свежеразвёрнутый сервер и делает это каждый раз, когда сервер пересоздаётся в auto scaling group, что очень удобно: https://github.com/vainkop/terraform-aws-wireguard/blob/master/templates/user-data.txt

Ближе к концу скрипта устанавливается 2 prometheus exporter'а, которые позволяют как мониторить метрики самой ec2 машины, так и базовые метрики самого WireGuard, на основании которых можно построить удобные Dashboards и соответственно определённые alerts и т.п.

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

Также привожу пример кода из .gitlab-ci.yml и Dockerfile где можно увидеть какие команды используются для применения всего этого хозяйства с помощью Gitlab runner'а и какой docker контейнер можно использовать для этого runner'а.

$ cat .gitlab-ci.ymlstages:  - build  - plan  - apply  - destroyvariables:  GIT_DEPTH: 1.aws_configure: &aws_configure  before_script:    - aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID    - aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY    - aws configure set default.region $AWS_DEFAULT_REGIONbuild-terraform:  image: docker:19.03.15  services:    - docker:19.03.15-dind  stage: build  variables:    DOCKER_TLS_CERTDIR: ""    DOCKER_HOST: tcp://docker:2375    DOCKER_DRIVER: overlay2    TERRAFORM_VERSION: "0.13.6"    TERRAGRUNT_VERSION: "v0.28.9"  before_script:    - printenv    - docker info    - echo $CI_REGISTRY_PASSWORD | docker login $CI_REGISTRY -u $CI_REGISTRY_USER --password-stdin  script:    - cd docker    - docker build --build-arg TERRAFORM_VERSION=$TERRAFORM_VERSION --build-arg TERRAGRUNT_VERSION=$TERRAGRUNT_VERSION -t $CI_REGISTRY_IMAGE:$TERRAFORM_VERSION .    - docker push $CI_REGISTRY_IMAGE:$TERRAFORM_VERSION  rules:    - changes:        - docker/*plan-us-east-1:  image:    name: registry.gitlab.com/vainkop/terraform:0.13.6    entrypoint: [""]  stage: plan  <<: *aws_configure  script:    - cd wireguard/us-east-1    - terragrunt run-all plan --terragrunt-non-interactive -out $CI_PROJECT_DIR/wireguard/us-east-1/tfplan-$CI_COMMIT_SHA  artifacts:    paths:    - $CI_PROJECT_DIR/wireguard/us-east-1/tfplan-$CI_COMMIT_SHA    expire_in: 1 month  rules:    - changes:        - wireguard/us-east-1/*      allow_failure: trueplan-eu-central-1:  image:    name: registry.gitlab.com/vainkop/terraform:0.13.6    entrypoint: [""]  stage: plan  <<: *aws_configure  script:    - cd wireguard/eu-central-1    - terragrunt run-all plan --terragrunt-non-interactive -out $CI_PROJECT_DIR/wireguard/eu-central-1/tfplan-$CI_COMMIT_SHA  artifacts:    paths:    - $CI_PROJECT_DIR/wireguard/eu-central-1/tfplan-$CI_COMMIT_SHA    expire_in: 1 month  rules:    - changes:        - wireguard/eu-central-1/*      allow_failure: trueapply-us-east-1:  image:    name: registry.gitlab.com/vainkop/terraform:0.13.6    entrypoint: [""]  stage: apply  <<: *aws_configure  script:    - cd wireguard/us-east-1    - terragrunt run-all apply --terragrunt-non-interactive -auto-approve $CI_PROJECT_DIR/wireguard/us-east-1/tfplan-$CI_COMMIT_SHA  rules:    - changes:        - wireguard/us-east-1/*      when: manual      allow_failure: trueapply-eu-central-1:  image:    name: registry.gitlab.com/vainkop/terraform:0.13.6    entrypoint: [""]  stage: apply  <<: *aws_configure  script:    - cd wireguard/eu-central-1    - terragrunt run-all apply --terragrunt-non-interactive -auto-approve $CI_PROJECT_DIR/wireguard/eu-central-1/tfplan-$CI_COMMIT_SHA  rules:    - changes:        - wireguard/eu-central-1/*      when: manual      allow_failure: truedestroy-us-east-1:  image:    name: registry.gitlab.com/vainkop/terraform:0.13.6    entrypoint: [""]  stage: destroy  <<: *aws_configure  script:    - cd wireguard/us-east-1    - terragrunt run-all destroy --terragrunt-non-interactive -auto-approve  rules:    - changes:        - wireguard/us-east-1/*      when: manual      allow_failure: truedestroy-eu-central-1:  image:    name: registry.gitlab.com/vainkop/terraform:0.13.6    entrypoint: [""]  stage: destroy  <<: *aws_configure  script:    - cd wireguard/eu-central-1    - terragrunt run-all destroy --terragrunt-non-interactive -auto-approve  rules:    - changes:        - wireguard/eu-central-1/*      when: manual      allow_failure: true
$ cat docker/DockerfileFROM ubuntu:20.04USER rootARG DEBIAN_FRONTEND=noninteractiveARG TERRAFORM_VERSIONENV TERRAFORM_VERSION=$TERRAFORM_VERSIONARG TERRAGRUNT_VERSIONENV TERRAGRUNT_VERSION=$TERRAGRUNT_VERSIONRUN set -x && \    apt-get update && \    apt-get install -y \    apt-transport-https \    ca-certificates \    build-essential \    software-properties-common \    unzip \    net-tools \    wget \    curl \    python3 \    python3-dev \    python3-pip \    jq \    gettext-base \    git && \    rm -rf /var/lib/apt/lists/*RUN set -x && \    apt-key adv --keyserver keyserver.ubuntu.com --recv-keys CC86BB64 && \    add-apt-repository ppa:rmescandon/yq && \    apt update && \    apt install -y yq && \    rm -rf /var/lib/apt/lists/*RUN set -x && \    pip3 install -U --no-cache-dir setuptools shyamlRUN set -x && \    ln -sf /usr/bin/python3 /usr/bin/python && ln -sf /usr/bin/pip3 /usr/bin/pipRUN set -x && \    curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" && \    unzip awscliv2.zip && \    rm awscliv2.zip && \    ./aws/installRUN set -x && \    cd /tmp && \    curl -O https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip && \    unzip terraform_${TERRAFORM_VERSION}_linux_amd64.zip -d /usr/local/bin && \    chmod +x /usr/local/bin/terraform && \    rm /tmp/terraform_${TERRAFORM_VERSION}_linux_amd64.zipRUN set -x && \    wget "https://github.com/gruntwork-io/terragrunt/releases/download/${TERRAGRUNT_VERSION}/terragrunt_linux_amd64" && \    mv terragrunt_linux_amd64 /usr/local/bin/terragrunt && \    chmod +x /usr/local/bin/terragruntRUN set -x && \    curl --version && \    envsubst --version && \    python --version && \    pip --version && \    shyaml --version && \    jq -V && \    yq -V && \    aws --version && \    terraform --version && \    terragrunt --versionENTRYPOINT ["/bin/bash", "-c"]

За код не ругайте, написал за несколько часов и решил поделиться.

Если есть конкретные замечания/предложения, то готов их выслушать либо в комментариях, либо в личке, например, в телеграм: @vainkop

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

Подробнее..

GitOps Определение дрейфа вашей инфраструктуры Terraform Terragrunt

18.03.2021 14:16:42 | Автор: admin

Всем привет.

Дисклеймер: сказу скажу, что пишу статью по-ходу дела, "код" в ней рабочий, но не претендует на какие-либо best practices, поэтому не придирайтесь :) Цель статьи: донести до интересующейся русскоязычной части населения общие принципы, возможно разбудить интерес поразбираться самостоятельно и сделать что-то гораздо лучше и интереснее. Итак поехали!

Допустим Вы работаете с Terraform / Terragrunt (второе здесь непринципиально, но лучше изучайте, если ещё не используете) и автоматизируете инфраструктуру, например, в AWS (но совершенно необязательно AWS). Инфраструктура в коде репозитория, разворачивается из него же, казалось бы вот оно GitOps счастье :)

Всё идёт хорошо, пока какой-то пользователь не поменял что-то руками через консоль / UI и конечно забыл об этом кому-либо сказать. А то и сделал что-то нехорошее намеренно. И вот он ваш дрейф: код и инфраструктура больше не совпадают! :(

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

Как обычно, есть много различных путей добиться желаемого. Например, недавно на горизонте появилась неплохо развивающаяся утилита https://github.com/cloudskiff/driftctl , которая может даже больше, чем предложу Вашему вниманию чуть ниже я, но на момент написания статьи driftctl как минимум не поддерживает работу с aws provider v2, а также не умеет в multi region, что делает его использование невозможным в большинстве серьёзных проектов. Но ребята обещают доделать её через месяц-два.

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

1) создаём pipeline, который или по расписанию (в Gitlab можно воспользоваться Pipeline schedules) или по кругу будет делать terraform plan

2) при нахождении дрейфа (diff в плане) pipeline будет, например, отправлять сообщение с его содержанием в Slack.

Аналогично можно реализовать и, например, создание issue в любом из используемых вами репозиториев, где поддерживается их создание через api и любое другое действие, например apply, который вернёт инфраструктуру к её эталонному состоянию. Или всё-таки импортировать изменение в state, если оно действительно необходимо.

Допустим есть репозиторий содержащий код для вашей live инфраструктуры, т.е. код, которому она должна соответствовать и откуда она и была развёрнута с такой структурой:

account_1/ eu-central-1  dev   eks    terragrunt.hcl    values.yaml   s3-bucket       terragrunt.hcl       values.yaml  prod   eks    terragrunt.hcl    values.yaml   s3-bucket       terragrunt.hcl       values.yaml  staging      eks       terragrunt.hcl       values.yaml      s3-bucket          terragrunt.hcl          values.yaml us-east-1  dev   eks    terragrunt.hcl    values.yaml   s3-bucket       terragrunt.hcl       values.yaml  prod   eks    terragrunt.hcl    values.yaml   s3-bucket       terragrunt.hcl       values.yaml  staging      eks       terragrunt.hcl       values.yaml      s3-bucket          terragrunt.hcl          values.yaml terragrunt.hcl

В приведённом выше примере в папке account_1 находятся 2 папки: us-east-1 и eu-central-1 , по имени регионов AWS. Иногда удобно организовать структуру именно так и тогда имена папок можно использовать как значение для передачи в модуль с помощью Terragrunt функции/й, например, таких "${basename(get_terragrunt_dir())}"

Аналогичная логика с папками имеющими в названии окружение и далее идут названия самих компонентов, которых в этом примере 2: eks и s3-bucket

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

<account_name>/<region>/<environment>/<component>/*

Т.е. "в общих чертах" */*/*/<component>/*

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

Не забудьте подключить Incoming WebHooks в Slack и записать полученный Webhook URL. Делается это так: https://api.slack.com/messaging/webhooks

Тогда вот такой скрипт может выполнять требуемое планирование в pipeline и отправку в Slack diff'а при его нахождении:

#!/bin/bashROOT_DIR=$(pwd)plan () {  echo -e "$(date +'%H-%M-%S %d-%m-%Y') $F"  CURRENT_DIR=$(pwd)  PLAN=$CURRENT_DIR/plan.tfplan  terragrunt run-all plan --terragrunt-non-interactive -lock=false -detailed-exitcode -out=$PLAN 2>/dev/null || ec=$?    case $ec in    0) echo "No Changes Found"; exit 0;;    1) printf '%s\n' "Command exited with non-zero"; exit 1;;    2) echo "Changes Found! Reporting!";          MESSAGE=$(terragrunt show -no-color ${PLAN} | sed "s/\"/'/g");    # let's replace the double quotes from the diff with single as double quotes "break" the payload       curl -X POST --data-urlencode "payload={\"channel\": \"#your-slack-channel-here\", \"username\": \"webhookbot\", \"text\": \"DRIFT DETECTED!!!\n ${MESSAGE}\", \"icon_emoji\": \":ghost:\"}" https://hooks.slack.com/services/YOUR/WEBHOOK/URL_HERE;;  esac}N="$(($(grep -c ^processor /proc/cpuinfo)*4))"    # any number suitable for your situation goes herefor F in */*/*/s3-bucket/*; do  ((i=i%N)); ((i++==0)) && wait    # let's run only N jobs in parallel to speed up the process  cd $ROOT_DIR  cd $F  plan &    # send the job to background to start the new onedone

Меняем что-нибудь руками, запускаем pipeline или ждём его выполнения и радуемся :)

На этом на сегодня всё!

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

P.S. имхо проект https://github.com/cloudskiff/driftctl мне лично кажется действительно полезным и решающим правильную задачу и хороших аналогов ему нет, так что прошу поддержать ребят, а по-возможности внести свою лепту ибо open source.

Всем хорошего настроения!

Подробнее..

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

10.06.2021 18:12:02 | Автор: admin

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

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

Примечание.SAP Concur использует AWS EKS, но рассматриваемые здесь концепции также применимы к Google GKE, Azure AKS и любым другим реализациям Kubernetes от облачных провайдеров.

Готовность к эксплуатации в рабочей среде

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

$ eksctl create cluster

Совсем другое дело, если нужно получить кластер Kubernetes, готовый к эксплуатации в рабочей среде production-ready Понятие production-ready может толковаться по-разному, но в SAP Concur используются следующие четыре этапа для создания и предоставления кластеров Kubernetes, готовых к эксплуатации в рабочей среде.

Четыре этапа сборки

  • Предварительное тестирование.Перечень простых тестов целевой среды AWS, которые проверяют соответствие всем необходимым требованиям до начала сборки кластера. Например, проверяются доступные IP-адреса в подсетях, экспортируемые параметры для AWS, параметры SSM или другие переменные.

  • Уровень управления EKS и группа узлов.Непосредственно сборка кластера AWS EKS с подключением рабочих узлов.

  • Установка дополнений.Добавим в кластер любимую приправу. :) По желанию можно установить такие дополнения, как Istio, Logging Integration, Autoscaler и пр.

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

Склеиваем все вместе

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

В результате мы нашли семейство решений Argo, в частности инструменты Argo Events и Argo Workflows. Они оба запускаются в Kubernetes как CRD и полагаются на декларативную концепцию YAML, как и множество других развертываний Kubernetes.

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

Кластер K8s, готовый к эксплуатации в рабочей среде. Создан с помощью Argo WorkflowsКластер K8s, готовый к эксплуатации в рабочей среде. Создан с помощью Argo Workflows

Поэтапная реализация процесса в Argo Workflows

Argo Workflows это движок рабочих процессов с открытым кодом и нативной поддержкой контейнеров, предназначенный для оркестрации параллельных заданий в среде Kubernetes. Argo Workflows реализован как Kubernetes CRD.

Примечание.Если вы знакомы с K8s YAML, обещаю, что вы разберетесь.

Давайте посмотрим, как все эти четыре этапа сборки могут выглядеть в Argo Workflows.

1. Предварительное тестирование

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

Мы пишем тесты на фреймворке BATS. Написать предварительный тест в BATS очень просто:

#!/usr/bin/env bats@test More than 100 available IP addresses in subnet MySubnet {AvailableIpAddressCount=$(aws ec2 describe-subnets --subnet-ids MySubnet | jq -r .Subnets[0].AvailableIpAddressCount) [ ${AvailableIpAddressCount} -gt 100 ]}

Параллельный запуск приведенного выше тестового файла BATS (avail-ip-addresses.bats) вместе с тремя другими вымышленными тестами BATS через Argo Workflows выглядит следующим образом:

 name: preflight-tests  templateRef:     name: argo-templates    template: generic-template  arguments:    parameters:     name: command      value: {{item}}  withItems:   bats /tests/preflight/accnt-name-export.bats   bats /tests/preflight/avail-ip-addresses.bats   bats /tests/preflight/dhcp.bats   bats /tests/preflight/subnet-export.bats

2. Уровень управления EKS и группа узлов

Уровень управления EKS и группа узлов с зависимостямиУровень управления EKS и группа узлов с зависимостями

Для построения кластера EKS можно использовать любой удобный инструмент. Например, eksctl, CloudFormation или Terraform. Двухэтапное построение базового кластера EKS с зависимостями в Argo Workflows с помощью шаблонов CloudFormation (eks-controlplane.yaml и eks-nodegroup.yaml) реализуется следующим образом.

 name: eks-controlplane  dependencies: [preflight-tests]  templateRef:     name: argo-templates    template: generic-template arguments:   parameters:    name: command     value: |       aws cloudformation deploy \       --stack-name {{workflow.parameters.CLUSTER_NAME}} \       --template-file /eks-core/eks-controlplane.yaml \       --capabilities CAPABILITY_IAM- name: eks-nodegroup  dependencies: [eks-controlplane]  templateRef:     name: argo-templates    template: generic-template  arguments:    parameters:     name: command      value: |        aws cloudformation deploy \        --stack-name {{workflow.parameters.CLUSTER_NAME}}-nodegroup \        --template-file /eks-core/eks-nodegroup.yaml \        --capabilities CAPABILITY_IAM

3. Установка дополнений

Параллельная установка дополнений с зависимостямиПараллельная установка дополнений с зависимостями

Для установки дополнений можно применить kubectl, helm, kustomize или их комбинацию. Например, установка дополнения metrics-server с шаблоном helm и kubectl, при условии что запрошена установка metrics-server, может выглядеть в Argo Workflows следующим образом.

 name: metrics-server  dependencies: [eks-nodegroup]  templateRef:     name: argo-templates    template: generic-template  when: {{workflow.parameters.METRICS-SERVER}} != none  arguments:    parameters:     name: command      value: |        helm template /addons/{{workflow.parameters.METRICS-SERVER}}/ \        --name metrics-server \        --namespace kube-system \        --set global.registry={{workflow.parameters.CONTAINER_HUB}} | \        kubectl apply -f -

4. Валидация кластера

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

Для валидации дополнений мы применяем BATS-библиотеку DETIK, которая заметно упрощает написание тестов для K8s.

#!/usr/bin/env batsload lib/utilsload lib/detikDETIK_CLIENT_NAME=kubectlDETIK_CLIENT_NAMESPACE="kube-system"@test verify the deployment metrics-server {  run verify there are 2 pods named metrics-server [ $status -eq 0 ]  run verify there is 1 service named metrics-server [ $status -eq 0 ]  run try at most 5 times every 30s to find 2 pods named metrics-server with status being running [ $status -eq 0 ]  run try at most 5 times every 30s to get pods named metrics-server and verify that status is running [ $status -eq 0 ]}

Запуск приведенного выше тестового файла BATS DETIK (metrics-server.bats), при условии что установлено дополнение metrics-server, можно реализовать в Argo Workflows так:

 name: test-metrics-server  dependencies: [metrics-server]  templateRef:    name: worker-containers    template: addons-tests-template  when: {{workflow.parameters.METRICS-SERVER}} != none  arguments:    parameters:     name: command      value: |        bats /addons/test/metrics-server.bats

Только представьте, сколько еще можно сюда подключить тестов. Нужны тесты Sonobuoy, Popeye или Fairwinds Polaris? Просто подключите их через Argo Workflows!

К этому моменту у вас должен получиться полнофункциональный, готовый к эксплуатации в рабочей среде кластер AWS EKS с установленным дополнением metrics-server. Все тесты пройдены, кластер можно принимать в работу. Дело сделано!

Но мы еще не прощаемся самое интересное я оставил напоследок.

Шаблоны рабочих процессов

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

Argo Events

Argo Events это событийно-ориентированный фреймворк для Kubernetes, который позволяет инициировать объекты K8s, Argo Workflows, бессерверные рабочие нагрузки и другие операции на основе различных триггеров, таких как веб-хуки, события в S3, расписания, очереди сообщений, Google Cloud Pub/Sub, SNS, SQS и пр.

Сборка кластера запускается посредством API-вызова (Argo Events) с использованием полезной нагрузки из JSON. Кроме того, каждый из четырех этапов сборки (WorkflowTemplates) имеет собственную конечную точку API. Операторы Kubernetes (тоесть люди) получают явные преимущества:

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

  • Хотите собрать голый кластер EKS? Вызывайте API eks-core (control-plane и nodegroup).

  • Хотите установить или переустановить дополнения в существующем кластере EKS? Вызывайте API дополнений.

  • Кластер начал чудить и вам нужно быстро его протестировать? Вызывайте API тестирования.

Возможности Argo

Решения Argo Events и Argo Workflows предлагают широкий функционал прямо из коробки, не нагружая вас лишней работой.

Вот семь самых востребованных функций:

  • Параллелизм

  • Зависимости

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

  • Условия

  • Поддержка S3

  • Шаблоны рабочих процессов

  • Параметры сенсоров событий

Заключение

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


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

Подробнее..

CloudWatch и Lambda, или Как я перестал бояться и полюбил AWS

23.04.2021 14:18:12 | Автор: admin

Облачные провайдеры это реактор, где вместо обогащённого урана используется твой кошелёк. В позапрошлом году наша компания начала активно применять облака и мы в полной мере ощутили это на себе: несколько команд разрабатывали отдельные продукты, и для большинства тестов запускались виртуальные мощности в AWS. Мы с коллегами получили сертификаты от Amazon, и это, вместе с наглядностью происходящего, Free Tier и Soft Limitами, создавало ложное чувство спокойствия за свой бюджет. А когда этому чувству поддаёшься, получаешь локальный Чернобыль.

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

Почему настройка оповещений это плацебо

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

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

Как взять под контроль облачный ядерный реактор

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

Я решил, что нужно где-то разместить логику реагирования и дёргать за различные API в облаке. Проще всего это сделать в AWS Lambda, так как Serverless может работать бесплатно, логика реагирования оформляется как на NodeJS, так и на Python, а простота API-вызовов из облака и ролевая модель доступа сокращают время на тестирование такого решения.

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

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

Какие есть инструменты для контроля трат на AWS

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

  • Cost Explorer даёт подробную разбивку по сервисам, но единственное, что он показывает, это сколько аккаунт уже успел потратить. Ничего не знает про запущенные в данный момент виртуальные мощности, но с его помощью можно оптимизировать траты.

  • Budgets внутри Cost Explorer. С сентября 2020 г. он научился определять Usage в часах, но всё ещё не даёт ответа, как идентифицировать забытые сущности.

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

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

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

Накопление данных Lambda + S3

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

Для упрощения тестирования и читаемости кода разобьём задачу между несколькими Lambda:

  • отдельно собираем информацию по запущенным инстансам;

  • решаем, какие инстансы заслуживают выключения, а какие нет;

  • выключаем ненужные инстансы.

Оркестратором простой цепочки Lambda я сделал Step Functions, который может запускаться по расписанию из CloudWatch.

Пример решения

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

Что тут происходит?

Каждые 5 минут CloudWatch отправляет заготовленный вызов в Step Functions, который управляет последовательным запуском четырёх Lambda-функций. Каждая Lambda-функция исполняет код на JavaScript (версии Node.js 10.x), использует сервисы EC2, Config или S3, и завершает свою работу передачей JSON в следующую Lambda. Исполнение скрипта завершается записью логов в CloudWatch Logs.

Как это работает?

CloudWatch Event > Step Function > 4 Lambda functions > CloudWatch Logs

  1. Get List of Working Instances получает список работающих инстансов и передает его через JSON в следующую Lambda-функцию

  2. Update Budget Usage делает много вещей, но главное обновляет данные файла в S3-хранилище.

  3. Terminate Instances выключает инстансы, которые превышают бюджет или нас не устраивают.

Как устанавливать?

После размещения кода и настройки ролей в Lambda-функциях необходимо составить схему работы через Step Functions, а также привязать событие CloudWatch Event Rule, которое будет запускать систему каждые 5 минут.

Как бы я подошёл к этой проблеме сейчас

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

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

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

Подробнее..

Облачные Gateway API зачем нужны подобные сервисы и чем они отличаются у разных платформ

19.05.2021 16:06:46 | Автор: admin

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

Похоже, мы окружены значит, придётся разбираться. Что такое API, на Хабре уже рассказывали, а я предлагаю рассмотреть поподробнее реализацию API Gateway на облачных платформах.

Зачем вообще нужны Gateway API

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

Представьте себе: у вас есть интернет-магазин по продаже реплик молота Тора. Для удобства пользователя имеется как сайт под десктоп и мобильные устройства, так и приложения для Android и iPhone, которые взаимодействуют с сервером через REST API.

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

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

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

Например возможность повторного использования компонентов, упрощение бэкенда приложения, обеспечение доступа к статическим веб-страницам и документам, удобная проверка авторизации и подбор оптимального для каждого типа клиента API как это делает Netflix API Gateway.

Что такое облачные API Gateway

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

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

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

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

Как облачные API Gateway облегчают жизнь

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

Для чего разработчики вообще выбирают облачные API Gateway?

  • Чтобы сократить время разработки API Gateway создаётся в несколько кликов, а интеграция с облачными сервисами выбранной платформы занимает пару минут.

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

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

  • Чтобы отлаживать API встроенными средствами меньше головной боли.

  • Чтобы генерировать клиентские SDK.

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

  • Чтобы контролировать доступ к API и управлять его жизненным циклом от создания до публикации.

  • Чтобы уведомление приходило от сервиса, а не от разозлённого клиента, если что-то идёт не так.

  • Чтобы настраивать авторизацию удобным методом с помощью средств Lambda или токенов OAuth.

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

  • Чтобы платить только за количество запросов в месяц или пользоваться сервисами бесплатно, если не выходить за рамки определённой цифры.

Как используют облачные API Gateway

Виртуальная доска

Простое приложение, состоящее из двух конечных точек POST для записи сообщений и GET для извлечения трёх последних сообщений. Реализовано с помощью AWS Gateway, AWS DynamoDB, AWS Serverless Application Model и Lambda.

Голосовой сервиc

Рецепт сервиса записи к врачу и регистрации в поликлинике, разработанный коммуникационной платформой Voximplant и Yandex.Cloud.

Бот для телеграма

Запуск бота на Python внутри одного из облачных сервисов, а именно Yandex.Cloud.

Трекер пульсометрии

Один из вариантов решения для сбора данных пульсовой оксиметрии для нескольких пользователей, отслеживания этих данных и обмена ими. Фронт написан на VueJS, бэкенд реализован с применением Amazon API Gateway.

Статический сайт в облаке

Пошаговая инструкция по деплою статического сайта в облако, прикрутке к нему сертификата Lets Encrypt, домена второго уровня и настройке API-шлюза в системе Yandex.Cloud.

Блог

И снова приложение на микросервисах реализация клиентской части на VueJS, взаимодействие настроено через REST API и gRPC, а в качестве базы данных используется MongoDB.

Реализация на разных облачных платформах

Сервис API Gateway предлагают несколько облачных платформ и все они предоставляют более-менее схожий пакет услуг. Так в чём же разница?

Azure API Management

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

Amazon API Gateway

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

Документация включает подробные инструкции от развёртывания RESTful API при создании бессерверного веб-приложения до работы с HTTP API, поэтому не придётся искать примеры по всей Сети, чтобы разобраться.

Особенности:

  • Создание API RESTful при помощи API HTTP или API REST.

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

  • Частная интеграция с AWS ELB и AWS Cloud Map.

  • Ключи API для сторонних разработчиков.

  • Генерирование клиентских SDK на многих языках, включая JavaScript, iOS и Android.

  • Внедрение подписи четвёртой версии для API REST и API WebSocket при авторизации и проверке запросов API к другим сервисам AWS API Gateway.

  • Авторизация с помощью AWS Lambda.

  • Amazon API Gateway можно пользоваться бесплатно целый год пока ваши потребности не превышают один миллион вызовов API, полученных для API REST, один миллион вызовов API, полученных для API HTTP, и один миллион сообщений и 750 000 минут подключения для API WebSocket в месяц.

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

Oracle API Gateway

Сервис Oracle API Gateway стал доступен любому пользователю в конце 2019 года и уже пытается активно конкурировать с Amazon API Gateway. Получится ли у него отвоевать хотя бы часть аудитории у AWS, нам только предстоит увидеть а сравнивать всегда интереснее на собственном опыте. Почитать про создание своего Gateway API можно вот в этой статье.

Особенности платформы:

  • RESTful API в комбинации с Oracle Functions, а также возможностями Kubernetes и Compute.

  • Каждая служба в облачной инфраструктуре Oracle интегрируется с IAM для аутентификации и авторизации (консоль, SDK или CLI и REST API).

  • Интеграция с системой управления доступом Oracle Cloud Infrastructure.

  • Бесплатный период длительностью в тридцать дней, чтобы опробовать возможности широкого спектра сервисов Oracle Cloud, в том числе к Databases, Analytics, Compute, Container Engine for Kubernetes и т. д.

  • Платформа Oracle Cloud позиционирует себя как более экономичное решение, чем AWS, и в качестве примера упоминает, что соотношение цены и производительности в 2 раза выше, а стоимость исходящей пропускной способности составляет только 1/4 от стоимости у AWS.

Google API Gateway

Сервис перешёл на стадию публичного бета-тестирования 18 сентября 2020 года, так что пока о нём известно довольно мало и тем интереснее пронаблюдать за его развитием.Сейчас Google API Gateway позволяет управлять API других сервисов облачной платформы Cloud Functions, Cloud Run, App Enginе, Compute Engine и Google Kubernetes Engine. Настроить работу с Cloud Run, к примеру, можно всего за несколько минут.

Особенности:

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

  • До 2 миллионов запросов в месяц бесплатно.

  • Наличие пробной версии. Google Cloud предоставляет виртуальный кредит в размере 300 долларов, который необходимо потратить в течение последующих трёх месяцев. После окончания бесплатного периода оплата не начинает взиматься автоматически на платный тариф необходимо перейти вручную.

SberCloud API Gateway

SberCloud API Gateway использует наработки Huawei, а информации об особенностях применении в Сети можно найти немного, но здесь вам поможет Хабр: после недавнего хакатона один из участников рассказал о впечатлениях от SberCloud и сравнил функциональность с более известным AWS.

Особенности:

  • Доступ к облачным продуктам для физических лиц возможен только с помощью входа/регистрации через Сбер ID.

  • Управление квотами и регулирование запросов пользователей.

  • Встроенный инструмент отладки.

  • Визуализированная панель мониторинга API.

  • Создание каналов VPC для доступа к бэкенд-сервисам в сети VPC и управления нагрузкой путём отправки API-запросов на различные серверы.

  • Цифровая подпись, которая вступает в силу только после привязки к API.

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

  • Возможность монетизации API.

Yandex API Gateway

23 сентября 2020 года к четырём сервисам платформы Yandex.Cloud прибавились ещё два Yandex API Gateway и база данных Yandex Database в режиме Serverless.

Yandex API Gateway интегрирован с другими сервисами платформы, благодаря чему возможна отправка HTTP-запросов с помощью функций Yandex Cloud Functions, доступ к статическим данным осуществляется Yandex Object Storage напрямую из хранилища, а запуск произвольных HTTP-сервисов в облаке возможен с помощью Yandex Managed Service for Kubernetes. Так что спектр применения широк к примеру, внутри облака можно запустить приложение на Express.js.

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

Особенности:

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

  • Поддержка OpenAPI 3.0.

  • Обработка запросов только по протоколу HTTPS. Сервис автоматически перенаправляет все запросы к API-шлюзам по протоколу HTTP на их HTTPS-версии.

  • Интеграция с системой управления доменами сервиса Certificate Manager. Для обеспечения TLS-соединения используется привязанный к домену сертификат.

  • Система квот и лимитов. Максимальный размер спецификации 3,5 МБ. Количество API-шлюзов в одном облаке 10, но, в отличие от максимального размера спецификации, меняется по запросу в техническую поддержку.

Тарификация по количеству запросов к созданным API-шлюзам и исходящему трафику. При этом запросы к API-шлюзам до 100 000 запросов в месяц не тарифицируются. Как, кстати, и входящий трафик, а также передача данных между сервисами Yandex.Cloud. Больше подробностей можно узнать в сообществе Serverless в Telegram:Yandex Serverless Ecosystem. Мы регулярно встречаемся в виртуальном пространстве и похоже созревает потребность в очной встрече.

Подробнее..

Подборка телеграм-каналов для DevOps инженеров

13.03.2021 14:14:35 | Автор: admin

Приветствую, братцы!

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

Подборка телеграм-каналов и чатов:

Вакансии

Devops Jobs - Вакансии и резюме

Jobs for Devs & Ops - Вакансии для инженеров и разработчиков

Новостные каналы

Mops DevOps - Kubernetes, DevOps, SRE и многое другое

DevOps Deflope News - Новостной канал

Записки админа - Linux и администрировании серверов

k8s (in)security - Канал о (не)безопасности Kubernetes

Мир IT c Антоном Павленко - IT новости, статьи и видео

Конференции

DevOpsConf Channel - Информационный канал профессиональной конференции по эксплуатации и devops DevOpsConf Russia

Meetup Moscow - анонсы конференций

Инструменты DevOps

terraform_ru - Русскоязычный чат Hashicorp Terraform

pro_ansible- Чат для взаимопомощи по Ansible

Docker_ru- Русскоговорящее сообщество по экосистеме Docker (чат)

RU.Docker - Официальное Русское Сообщество (чат)

ru_gitlab- Русскоговорящая группа по GitLab

ru_jenkins- Русскоговорящая группа по Jenkins

Инфраструктура

Kubernetes- Общаемся на темы, посвященные Kubernetes, конфигурации и возможностям

istio_ru - Чат про Mervice Mesh в целом и Istio в частности

Вокруг Kubernetes в Mail.ru Group митапы по Kubernetes, DevOps, открытым технологиям в Mail.ru Group и немного проKubernetes как сервис

Envoy Proxy- Делимся опытом, экспертизой, советами и фэйлами :)

nginx_ru - Сообщество пользователей nginx, новости, обсуждения конфигураций

SDS и Кластерные FS - Обсуждаем Software-defined storage, кластерные файловые системы, блочные хранилища, стратегии построения хранилища и все что с ними связанно (Linstor, DRBD, ZFS, LVM, Ceph, GlusterFS, Lustre, MooseFS, LizardFS, mdadm, S3, iSCSI, NFS, OrangeFS, OCFS, GFS2)

Грефневая Кафка (pro.kafka)- Здесь топят за Кафку (Apache Kafka )

pro.kafka- Чат для добросовестных господ и дам, посвящённый Apache Kafka

DBA- Общаемся и обсуждаем темы, посвященные DBA, PostgreSQL, Redis, MongoDB, MySQL...

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

AWS_ru- Чат про Amazon Web Services

AWS notes- Канал про Amazon Web Services

Yandex.Cloud - Новости от команды платформы Yandex.Cloud

IT-журнал Завтра облачно - Блог команды Mail.ru Cloud Solutions (MCS)

Мониторинг и сбор логов

VictoriaMetrics_ru - Чат для обсуждения VictoriaMetrics

Церковь метрик- Канал про Метрики. Метрики. Метрики.

ru_logs - ElasticSearch, Graylog, Mtail, rsyslog и все такое прочее

Мониторим ИТ- Канал о мониторинге ИТ-инфраструктуры и приложений

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

Подробнее..
Категории: Kubernetes , Gitlab , Devops , Nginx , Docker , Monitoring , Istio , Telegram , Aws , Envoy

Развертывание приложений Django

11.04.2021 20:17:45 | Автор: admin

Введение

После того, как мы закончили разработку веб-приложения, оно должно быть размещено на хосте, чтобы общественность могла получить доступ к нему из любого места. Мы посмотрим, как развернуть и разместить приложение на экземпляре AWS EC2, используя Nginx в качестве веб-сервера и Gunicorn в качестве WSGI.

AWS EC2

Amazon Elastic Compute Cloud (Amazon EC2) - это веб-сервис, обеспечивающий масштабируемость вычислительных мощностей в облаке. Мы устанавливаем и размещаем наши веб-приложения на экземпляре EC2 после выбора AMI (OS) по нашему усмотрению. Подробнее об этом мы поговорим в следующих разделах.

NGINX

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

GUNICORN

Gunicorn - это серверная реализация интерфейса шлюза Web Server Gateway Interface (WSGI), который обычно используется для запуска веб-приложений Python.

WSGI - используется для переадресации запроса с веб-сервера на Python бэкэнд.

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

Развертывание приложения

Мы запустим EC2 экземпляр на AWS, для этого войдите в консоль aws.

  • Выберите EC2 из всех сервисов

  • Выберите запуск New instance и выберите Ubuntu из списка.

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

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

Подключение к Экземпляру

Мы можем подключиться к экземпляру, используя опцию 'connect' в консоли (или с помощью putty или любого другого подобного инструмента ). После подключения запустите следующие команды

sudo apt-get update

Установите python , pip и django

sudo apt install pythonsudo apt install python3-pippip3 install django

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

cd  /home/ubuntu/  mkdir Projectcd Projectmkdir ProjectNamecd ProjectName

Теперь мы поместим наш код по следующему пути.
/home/ubuntu/Project/ProjectName

GitHub

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

  • Перейдите в только что созданную папку (/home/ubuntu/Project/ProjectName/)

  • git clone <repository-url>

Это клонирует репозиторий в папку, и в следующий раз мы сможем просто вытащить изменения с помощью git pull.

Settings.py Файл.

Мы должны внести некоторые изменения в settings.py в нашем проекте.

  • Вставьте свои секретные ключи и пароли в переменные окружения

  • Установить Debug = False

  • Добавте Ваш домейн в ALLOWED_HOSTS

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))STATIC_ROOT = os.path.join(BASE_DIR, static)

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

manage.py makemigrationsmanage.py migratemanage.py collectstatic

Установка Nginx

Для установки Nginx выполните команду

 sudo apt install nginx

Есть конфигурационный файл с именем по умолчанию в /etc/nginx/sites-enabled/, который имеет базовую настройку для NGINX, мы отредактируем этот файл.

sudo vi default

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

мы добавим proxy_pass http://0.0.0.0:9000 и укажем путь к нашей статической папке, добавив путь внутри каталога /static/, как указано выше. Убедитесь, что вы собрали все статические файлы в общую папку, запустив команду

manage.py collectstatic

Теперь запустите сервер nginx

sudo service nginx start             #to start nginxsudo service nginx stop              #to stop nginxsudo service nginx restart           #to restart nginx

Установка Gunicorn

pip install gunicorn

Убедитесь, что Вы находитесь в папке проекта, например: /home/ubuntu/Project, и запустите следующую команду, чтобы запустить gunicorn

gunicorn ProjectName.wsgi:application- -bind 0.0.0.0:9000

Теперь, когда мы установили и настроили nginx и gunicorn, к нашему приложению можно получить доступ через DNS экземпляра ec2.

Подробнее..
Категории: Python , Nginx , Python3 , Django , Aws , Gunicorn

Перевод Оптимизируем затраты с помощью AWS Cost Explorer

15.04.2021 14:13:15 | Автор: admin

У Amazon Web Services отличный бесплатный пакет:хороший набор сервисов и щедрая раздача кредитов для разработчиков. Я был уверен: проблем с оплатой моего окружения не будет, поэтому о расходах не беспокоился. Мое приложение на 100% serverless, и я всегда укладывался в уровень бесплатного использования, так что просто игнорировал вопрос оплаты. В какой-то момент я расслабился и потерял бдительность.

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

AWS Cost Explorer

Сервис AWS Billing dashboard хорошо подходит для оплаты счетов и показывает график прогноза счетов за текущий месяц. Но этот сервис едва ли претендует на звание лучшего в AWS. Месячный прогноз часто врет, поэтому лучше игнорировать его вовсе.

Помимо Billing Dashboard, соседний Cost Explorer. Он предоставляет очень хорошую детализацию и возможность прогнозирования. Кроме просмотра стандартной разбивки потребления в AWS, можно писать код под Cost Explorer, извлекая много ценной информации. И мне это дело зашло.

Используя Cost Explorer, я смог заранее определить уязвимые места и исправить их задолго до того, как с меня начнут списывать за них деньги. Еще раз спасибо AWS.

Пользовательский интерфейс

Прежде чем начать работать, надо познакомиться со стандартным видом консоли Billing Dashboard. Нужно сначала включить её, что будет стоить денег. Лучше сделать это заранее, чтобы потом не было мучительно больно. У кого много остатку, тот не боится недостатку!

Пользовательский интерфейс интуитивно понятный: здесь мы можем получать подробные отчеты по дням / услуге; или сгруппированные по времени / региону / услуге и множеством других способов.

Это мой график потраченного за последние несколько месяцев.

Отчеты

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

Бюджеты

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

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

Обнаружение аномалий

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

Cost Explorer API

Стандартный вид консоли управления меня устраивает но только для эпизодического ознакомления. Для того, чтобы получить нечто большее, AWS предоставляет отличный API. Репозиторий AWS Samples Github дает нам наглядный пример доступа к API Cost Explorer.

Мой код основан на этом примере, и позволяет разработать собственный отчет для Cost Explorera.

Код Lambda функции

import osimport sys# Required to load modules from vendored subfolder (for clean development env)sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), "./vendored"))import boto3import datetimeimport loggingimport pandas as pd#For datefrom dateutil.relativedelta import relativedelta#For emailfrom email.mime.application import MIMEApplicationfrom email.mime.multipart import MIMEMultipartfrom email.mime.text import MIMETextfrom email.utils import COMMASPACE, formatdateSES_REGION="ap-south-1"CURRENT_MONTH = True#Default exclude support, as for Enterprise Support#as support billing is finalised later in month so skews trends    INC_SUPPORT = os.environ.get('INC_SUPPORT')if INC_SUPPORT == "true":    INC_SUPPORT = Trueelse:    INC_SUPPORT = FalseTAG_VALUE_FILTER = os.environ.get('TAG_VALUE_FILTER') or '*'TAG_KEY = os.environ.get('TAG_KEY')class CostExplorer:    """Retrieves BillingInfo checks from CostExplorer API    >>> costexplorer = CostExplorer()    >>> costexplorer.addReport(GroupBy=[{"Type": "DIMENSION","Key": "SERVICE"}])    >>> costexplorer.generateExcel()    """        def __init__(self, CurrentMonth=False):        #Array of reports ready to be output to Excel.        self.reports = []        self.client = boto3.client('ce', region_name='us-east-1')        # self.end = datetime.date.today().replace(day=1)        self.riend = datetime.date.today()        self.end = self.riend        # Default is last 12 months        self.start = (datetime.date.today() - relativedelta(months=+12)).replace(day=1) #1st day of month 12 months ago        self.ristart = (datetime.date.today() - relativedelta(months=+11)).replace(day=1) #1st day of month 11 months ago        self.sixmonth = (datetime.date.today() - relativedelta(months=+6)).replace(day=1) #1st day of month 6 months ago, so RI util has savings values        self.accounts = {}    def addRiReport(self, Name='RICoverage', Savings=False, PaymentOption='PARTIAL_UPFRONT', Service='Amazon Elastic Compute Cloud - Compute'): #Call with Savings True to get Utilization report in dollar savings        type = 'chart' #other option table        if Name == "RICoverage":            results = []            response = self.client.get_reservation_coverage(                TimePeriod={                    'Start': self.ristart.isoformat(),                    'End': self.riend.isoformat()                },                Granularity='MONTHLY'            )            results.extend(response['CoveragesByTime'])            while 'nextToken' in response:                nextToken = response['nextToken']                response = self.client.get_reservation_coverage(                    TimePeriod={                        'Start': self.ristart.isoformat(),                        'End': self.riend.isoformat()                    },                    Granularity='MONTHLY',                    NextPageToken=nextToken                )                results.extend(response['CoveragesByTime'])                if 'nextToken' in response:                    nextToken = response['nextToken']                else:                    nextToken = False            rows = []            for v in results:                row = {'date':v['TimePeriod']['Start']}                row.update({'Coverage%':float(v['Total']['CoverageHours']['CoverageHoursPercentage'])})                rows.append(row)              df = pd.DataFrame(rows)            df.set_index("date", inplace= True)            df = df.fillna(0.0)            df = df.T        elif Name in ['RIUtilization','RIUtilizationSavings']:            #Only Six month to support savings            results = []            response = self.client.get_reservation_utilization(                TimePeriod={                    'Start': self.sixmonth.isoformat(),                    'End': self.riend.isoformat()                },                Granularity='MONTHLY'            )            results.extend(response['UtilizationsByTime'])            while 'nextToken' in response:                nextToken = response['nextToken']                response = self.client.get_reservation_utilization(                    TimePeriod={                        'Start': self.sixmonth.isoformat(),                        'End': self.riend.isoformat()                    },                    Granularity='MONTHLY',                    NextPageToken=nextToken                )                results.extend(response['UtilizationsByTime'])                if 'nextToken' in response:                    nextToken = response['nextToken']                else:                    nextToken = False            rows = []            if results:                for v in results:                    row = {'date':v['TimePeriod']['Start']}                    if Savings:                        row.update({'Savings$':float(v['Total']['NetRISavings'])})                    else:                        row.update({'Utilization%':float(v['Total']['UtilizationPercentage'])})                    rows.append(row)                  df = pd.DataFrame(rows)                df.set_index("date", inplace= True)                df = df.fillna(0.0)                df = df.T                type = 'chart'            else:                df = pd.DataFrame(rows)                type = 'table' #Dont try chart empty result        elif Name == 'RIRecommendation':            results = []            response = self.client.get_reservation_purchase_recommendation(                #AccountId='string', May use for Linked view                LookbackPeriodInDays='SIXTY_DAYS',                TermInYears='ONE_YEAR',                PaymentOption=PaymentOption,                Service=Service            )            results.extend(response['Recommendations'])            while 'nextToken' in response:                nextToken = response['nextToken']                response = self.client.get_reservation_purchase_recommendation(                    #AccountId='string', May use for Linked view                    LookbackPeriodInDays='SIXTY_DAYS',                    TermInYears='ONE_YEAR',                    PaymentOption=PaymentOption,                    Service=Service,                    NextPageToken=nextToken                )                results.extend(response['Recommendations'])                if 'nextToken' in response:                    nextToken = response['nextToken']                else:                    nextToken = False            rows = []            for i in results:                for v in i['RecommendationDetails']:                    row = v['InstanceDetails'][list(v['InstanceDetails'].keys())[0]]                    row['Recommended']=v['RecommendedNumberOfInstancesToPurchase']                    row['Minimum']=v['MinimumNumberOfInstancesUsedPerHour']                    row['Maximum']=v['MaximumNumberOfInstancesUsedPerHour']                    row['Savings']=v['EstimatedMonthlySavingsAmount']                    row['OnDemand']=v['EstimatedMonthlyOnDemandCost']                    row['BreakEvenIn']=v['EstimatedBreakEvenInMonths']                    row['UpfrontCost']=v['UpfrontCost']                    row['MonthlyCost']=v['RecurringStandardMonthlyCost']                    rows.append(row)              df = pd.DataFrame(rows)            df = df.fillna(0.0)            type = 'table' #Dont try chart this        self.reports.append({'Name':Name,'Data':df, 'Type':type})    def addReport(self, Name="Default",GroupBy=[{"Type": "DIMENSION","Key": "SERVICE"},],     Style='Total', NoCredits=True, CreditsOnly=False, RefundOnly=False, UpfrontOnly=False, IncSupport=False):        type = 'chart' #other option table        results = []        if not NoCredits:            response = self.client.get_cost_and_usage(                TimePeriod={                    'Start': self.start.isoformat(),                    'End': self.end.isoformat()                },                Granularity='MONTHLY',                Metrics=[                    'UnblendedCost',                ],                GroupBy=GroupBy            )        else:            Filter = {"And": []}            Dimensions={"Not": {"Dimensions": {"Key": "RECORD_TYPE","Values": ["Credit", "Refund", "Upfront", "Support"]}}}            if INC_SUPPORT or IncSupport: #If global set for including support, we dont exclude it                Dimensions={"Not": {"Dimensions": {"Key": "RECORD_TYPE","Values": ["Credit", "Refund", "Upfront"]}}}            if CreditsOnly:                Dimensions={"Dimensions": {"Key": "RECORD_TYPE","Values": ["Credit",]}}            if RefundOnly:                Dimensions={"Dimensions": {"Key": "RECORD_TYPE","Values": ["Refund",]}}            if UpfrontOnly:                Dimensions={"Dimensions": {"Key": "RECORD_TYPE","Values": ["Upfront",]}}            tagValues = None            if TAG_KEY:                tagValues = self.client.get_tags(                    SearchString=TAG_VALUE_FILTER,                    TimePeriod = {                        'Start': self.start.isoformat(),                        'End': datetime.date.today().isoformat()                    },                    TagKey=TAG_KEY                )            if tagValues:                Filter["And"].append(Dimensions)                if len(tagValues["Tags"]) > 0:                    Tags = {"Tags": {"Key": TAG_KEY, "Values": tagValues["Tags"]}}                    Filter["And"].append(Tags)            else:                Filter = Dimensions.copy()            response = self.client.get_cost_and_usage(                TimePeriod={                    'Start': self.start.isoformat(),                    'End': self.end.isoformat()                },                Granularity='MONTHLY',                Metrics=[                    'UnblendedCost',                ],                GroupBy=GroupBy,                Filter=Filter            )        if response:            results.extend(response['ResultsByTime'])            while 'nextToken' in response:                nextToken = response['nextToken']                response = self.client.get_cost_and_usage(                    TimePeriod={                        'Start': self.start.isoformat(),                        'End': self.end.isoformat()                    },                    Granularity='MONTHLY',                    Metrics=[                        'UnblendedCost',                    ],                    GroupBy=GroupBy,                    NextPageToken=nextToken                )                results.extend(response['ResultsByTime'])                if 'nextToken' in response:                    nextToken = response['nextToken']                else:                    nextToken = False        rows = []        sort = ''        for v in results:            row = {'date':v['TimePeriod']['Start']}            sort = v['TimePeriod']['Start']            for i in v['Groups']:                key = i['Keys'][0]                if key in self.accounts:                    key = self.accounts[key][ACCOUNT_LABEL]                row.update({key:float(i['Metrics']['UnblendedCost']['Amount'])})             if not v['Groups']:                row.update({'Total':float(v['Total']['UnblendedCost']['Amount'])})            rows.append(row)          df = pd.DataFrame(rows)        df.set_index("date", inplace= True)        df = df.fillna(0.0)        if Style == 'Change':            dfc = df.copy()            lastindex = None            for index, row in df.iterrows():                if lastindex:                    for i in row.index:                        try:                            df.at[index,i] = dfc.at[index,i] - dfc.at[lastindex,i]                        except:                            logging.exception("Error")                            df.at[index,i] = 0                lastindex = index        df = df.T        df = df.sort_values(sort, ascending=False)        self.reports.append({'Name':Name,'Data':df, 'Type':type})    def generateExcel(self):        # Create a Pandas Excel writer using XlsxWriter as the engine.\        os.chdir('/tmp')        writer = pd.ExcelWriter('cost_explorer_report.xlsx', engine='xlsxwriter')        workbook = writer.book        for report in self.reports:            print(report['Name'],report['Type'])            report['Data'].to_excel(writer, sheet_name=report['Name'])            worksheet = writer.sheets[report['Name']]            if report['Type'] == 'chart':                # Create a chart object.                chart = workbook.add_chart({'type': 'column', 'subtype': 'stacked'})                chartend=13                for row_num in range(1, len(report['Data']) + 1):                    chart.add_series({                        'name':       [report['Name'], row_num, 0],                        'categories': [report['Name'], 0, 1, 0, chartend],                        'values':     [report['Name'], row_num, 1, row_num, chartend],                    })                chart.set_y_axis({'label_position': 'low'})                chart.set_x_axis({'label_position': 'low'})                worksheet.insert_chart('O2', chart, {'x_scale': 2.0, 'y_scale': 2.0})        writer.save()        #Time to deliver the file to S3        if os.environ.get('S3_BUCKET'):            s3 = boto3.client('s3')            s3.upload_file("cost_explorer_report.xlsx", os.environ.get('S3_BUCKET'), "cost_explorer_report.xlsx")        if os.environ.get('SES_SEND'):            #Email logic            msg = MIMEMultipart()            msg['From'] = os.environ.get('SES_FROM')            msg['To'] = COMMASPACE.join(os.environ.get('SES_SEND').split(","))            msg['Date'] = formatdate(localtime=True)            msg['Subject'] = "Cost Explorer Report"            text = "Find your Cost Explorer report attached\n\n"            msg.attach(MIMEText(text))            with open("cost_explorer_report.xlsx", "rb") as fil:                part = MIMEApplication(                    fil.read(),                    Name="cost_explorer_report.xlsx"                )            part['Content-Disposition'] = 'attachment; filename="%s"' % "cost_explorer_report.xlsx"            msg.attach(part)            #SES Sending            ses = boto3.client('ses', region_name=SES_REGION)            result = ses.send_raw_email(                Source=msg['From'],                Destinations=os.environ.get('SES_SEND').split(","),                RawMessage={'Data': msg.as_string()}            )     def lambda_handler(event, context):    costexplorer = CostExplorer(CurrentMonth=False)    #Default addReport has filter to remove Support / Credits / Refunds / UpfrontRI    #Overall Billing Reports    costexplorer.addReport(Name="Total", GroupBy=[],Style='Total',IncSupport=True)    costexplorer.addReport(Name="TotalChange", GroupBy=[],Style='Change')    costexplorer.addReport(Name="TotalInclCredits", GroupBy=[],Style='Total',NoCredits=False,IncSupport=True)    costexplorer.addReport(Name="TotalInclCreditsChange", GroupBy=[],Style='Change',NoCredits=False)    costexplorer.addReport(Name="Credits", GroupBy=[],Style='Total',CreditsOnly=True)    costexplorer.addReport(Name="Refunds", GroupBy=[],Style='Total',RefundOnly=True)    costexplorer.addReport(Name="RIUpfront", GroupBy=[],Style='Total',UpfrontOnly=True)    #GroupBy Reports    costexplorer.addReport(Name="Services", GroupBy=[{"Type": "DIMENSION","Key": "SERVICE"}],Style='Total',IncSupport=True)    costexplorer.addReport(Name="ServicesChange", GroupBy=[{"Type": "DIMENSION","Key": "SERVICE"}],Style='Change')    costexplorer.addReport(Name="Accounts", GroupBy=[{"Type": "DIMENSION","Key": "LINKED_ACCOUNT"}],Style='Total')    costexplorer.addReport(Name="AccountsChange", GroupBy=[{"Type": "DIMENSION","Key": "LINKED_ACCOUNT"}],Style='Change')    costexplorer.addReport(Name="Regions", GroupBy=[{"Type": "DIMENSION","Key": "REGION"}],Style='Total')    costexplorer.addReport(Name="RegionsChange", GroupBy=[{"Type": "DIMENSION","Key": "REGION"}],Style='Change')    if os.environ.get('COST_TAGS'): #Support for multiple/different Cost Allocation tags        for tagkey in os.environ.get('COST_TAGS').split(','):            tabname = tagkey.replace(":",".") #Remove special chars from Excel tabname            costexplorer.addReport(Name="{}".format(tabname)[:31], GroupBy=[{"Type": "TAG","Key": tagkey}],Style='Total')            costexplorer.addReport(Name="Change-{}".format(tabname)[:31], GroupBy=[{"Type": "TAG","Key": tagkey}],Style='Change')    #RI Reports    costexplorer.addRiReport(Name="RICoverage")    costexplorer.addRiReport(Name="RIUtilization")    costexplorer.addRiReport(Name="RIUtilizationSavings", Savings=True)    costexplorer.addRiReport(Name="RIRecommendation") #Service supported value(s): Amazon Elastic Compute Cloud - Compute, Amazon Relational Database Service    costexplorer.generateExcel()    return "Report Generated"

IAM Role

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

Базовая политика Lambda

{    "Version": "2012-10-17",    "Statement": [        {            "Effect": "Allow",            "Action": [                "logs:CreateLogGroup",                "logs:CreateLogStream",                "logs:PutLogEvents"            ],            "Resource": "*"        }    ]}

Разрешение для записи отчетов в S3 бакет

{    "Version": "2012-10-17",    "Statement": [        {            "Sid": "VisualEditor0",            "Effect": "Allow",            "Action": [                "s3:PutObject",                "s3:GetObject"            ],            "Resource": "arn:aws:s3:::account.admin/*"        }    ]}

Simple Email Service

{    "Version": "2012-10-17",    "Statement": [        {            "Sid": "VisualEditor0",            "Effect": "Allow",            "Action": [                "ses:SendEmail",                "ses:SendRawEmail"            ],            "Resource": "*"        }    ]}

Cost Explorer

{    "Version": "2012-10-17",    "Statement": [        {            "Sid": "VisualEditor0",            "Effect": "Allow",            "Action": "ce:*",            "Resource": "*"        }    ]}

Запуск на Event Bridge

Наконец, мы настраиваем регулярный запуск нашей Lambda функции на Event Bridge, например, 5 числа каждого месяца. В результате работы всех настроек я буду получать email с прикрепленным XLS-отчетом. Также можно настраивать срабатывание еженедельно и даже на определенные дни недели, при необходимости.

Подробнее..

Сам себе DevOps строим cloud-only CI для веб приложения

22.05.2021 18:12:52 | Автор: admin

Привет, Хабр! Сегодня мы немного поговорим о DevOps и самоорганизации на примере одного из наших проектов.

Начнем с фразы, с которой не соглашается добрая половина разработчиков в индустрии: "каждый разработчик должен быть сам себе DevOps". Кто-то считает, что этим должен заниматься отдельно выделенный человек, чтобы у разработчика оставалась забота только о качестве кода. А кому-то свойственно думать о конвейере доставки кода в той же степени, как и о самом коде. Я же считаю, что в современных реалиях рынка и избытке инструментов/знаний разработчик должен уметь настроить и обслуживать конвейер быстрой и предсказуемой доставки артефакта в нужную ему среду. В отличие от мобильных разработчиков, для которых вопросы инфраструктуры и доставки приложения в большей степени решены самим вендором (Google и Apple), backend и web разработчики должны если не владеть, то хотя бы интересоваться практиками доставки кода.

И речь не идет о настройке каких-то больших и громоздких билд-систем, для которых обычно приносится в жертвую целая штатная единица. Нет. DevOps - не человек, а система ежедневных маленьких привычек, основанных на самоорганизации. Понятие, взрастающее снизу вверх, а не сверху или в бок. И если вы, как разработчик, смогли ускорить поток артефактов (любимое американцами понятие "Value Stream") на небольшой процент, то поздравляем - это уже DevOps way. Рекомендуем прочесть книгу "DevOps Handbook" by Gene Kim - лучшая книга для понимания этого концепта (ссылка в конце статьи).

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

Кто

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

  • 3 фронтенд разработчика с кучей пулл реквестов в день

  • 2 тестировщика, бастующие за улучшение QX (QA experience)

Что

Клиентское и администраторское web-приложения на Angular 9.0, собираемые из одного репозитория.

Где

Моя команда известна как ярый адепт продуктов Atlassian, поэтому вся экосистема нашего проекта живет в "австралийских облаках":

  • задачи и релизы в Jira

  • код в Bitbucket

  • CI в Bitbucket Pipelines

  • подробная документация в Confluence.

Наша команда использует стандартный план Bitbucket за $4/чел, включающий в себя 1500 минут сборки в Bitbucket Pipelines. О нем в сегодняшней статье и пойдет речь. Принцип работы и синтаксис настройки на 90 процентов похожи на Gitlab CI, поэтому любому пользователю Gitlab вся схема работы будет максимально понятной.

Сама система интернет банкинга разбита на микросервисы и работает в контейнерах на серверах Банка. Но в этой статье речь будет идти не о контейнерах, хотя настройка CI с помощью Docker-образов звучит очевидным.

Немного контекста

Первые наши шаги в DevOps и конкретно в улучшении QX (QA experience) мы начали задолго до этого в проектах мобильных приложений. Мы интегрировали между собой Jira, Bitbucket и сервис Bitrise.io во всех наших пулл-реквестах, что позволило иметь на выходе конкретный билд на каждый коммит по конкретной задаче. Для наглядности: тестировщик понимал, что пулл реквест 30 выдает билд приложения 170, в которой нужно тестировать Jira-задачу 500. Если вкратце описать процесс пулл-реквестов, то обязательными требованиями к слиянию пулл-реквеста являются

  • Зеленый билд на последнем коммите

  • Добро от разработчика-ревьюера

  • Добро от тестировщика

Если один из этих шагов давал красный свет, то пулл-реквест проходит все шаги заново.
Такой процесс позволяет нам обеспечить высокое качество кода и продукта в стабильной ветке репозитория. Мы с высокой долей уверенности можем релизить приложение, собранное с master (мы начали работать по trunk-based development и поэтому master наша стабильная ветка).

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

Подобного механизма пулл-реквестов никогда не существовало в web приложениях. Мы всегда делали приемку задач после слияния пулл-реквестов в стабильную ветку, из-за чего каждый третий коммит в ней был дефектным. Настроить такой же процесс приема пулл реквестов, как в мобилке, было для нас очевидным шагом. Сделать CI окружение для web приложения на инфраструктуре Банка было для нас слишком долгой историей, потому что хотелось настроить и поехать очень быстро. А все, кто работал с большими банками, почувствовал "скорость" продвижения задач по железу. Все процессы, что мы опишем в этой статье, мы планируем воссоздать в инфраструктуре банка с помощью оркестратора (Kubernetes или OpenShift, на усмотрение заказчика), но это уже другая история. В тот момент нам нужно было как можно быстрее начать работать правильно.

Первый очевидный вопрос: куда доставлять? Мы начали присматриваться к разным вариантам: Heroku, AWS, Netlify, Surge итд. В итоге остановились на использовании AWS S3. Для тех, кто думал, что S3 это всего лишь файловое хранилище - S3 может работать как сайт и его можно привязать к доменному имени. Подробнее об этом можно прочитать на страничке AWS.

Так почему же AWS?

  • Доступная цена. При всей репутации AWS как дорогой экосистемы, ежемесячные счета за S3 выходят в среднем 2 доллара при следующих метриках:

    • Новых ПР в день ~ 2

    • Пайплайнов в день ~ 12

    • Кол-во единовременно существующих бакетов ~ 5

    • Средний размер бакета = 13 Mb

  • У AWS отличный API и CLI. у "Surge" и других легковесных сервисов хостинга не настолько качественный и полноценный тулинг, как у Amazon AWS. Надо отметить, что CLI и документация Heroku не уступает Амазону, но высокий на наш взгляд порог вхождения и специфика работы Heroku Dynos заставили нас отойти от его выбора.

  • У команды уже был опыт работы с продуктами AWS.

Можно было бы настроить весь этот процесс в контейнерах в самом Amazon, но это повлечет за собой запуск EC2 машин. Даже с использованием Docker Hub вместо Elastic Container Registry, прогноз затрат вываливался у нас за $100 в месяц. В конечном итоге у нас получилась именно та схема работы с пулл-реквестами, которую мы представляли себе в самом начале. Но давайте проанализируем каждую ступень нашей эволюции и посмотрим на принятые решения.

Уровень 1: создание S3 бакета

Мы начали с того, что создали по одному выделенному S3 bucket для хостинга клиентского и админского приложений. Настроили конфигурацию сборки нашего проекта (bitbucket-pipelines.yml), чтобы он собирал приложения (html/css/js/img) и заливал их в соответствующий S3 bucket. В начале был использован AWS CLI, но, как оказалось, Bitbucket предоставляет набор готовых официальных Pipes (аналог Github actions), среди которых оказался Pipe для выгрузки файлов в S3 bucket. В итоге: тестировщик имеет сайт, на котором он может проверить реализацию задачи пулл-реквеста с постоянной условной ссылкой web.s3-website.ap-northeast-2.amazonaws.com.

Обязательным предварительным шагом при создании бакета через консоль AWS является включение опции "Enable static hosting" в настройках бакета. Без этой опции bucket является просто файловым хранилищем.

- step:      name: Build and deploy webadmin PR version into AWS for QA      caches:        - node      script:        # начальная конфигурация        - apk update && apk add git        - npm install        # сборка        - npm run build:admin        - cd dist/admin        # загрузка в S3        - pipe: atlassian/aws-s3-deploy:0.2.4          variables:            AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID            AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY            AWS_DEFAULT_REGION: $AWS_DEFAULT_REGION            S3_BUCKET: $S3_WEBADMIN_BUCKET_NAME            DELETE_FLAG: 'true'            LOCAL_PATH: $(pwd)            ACL: 'public-read'

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

Оценка:

  • за старания - четверка

  • за QX - двойка

Уровень 2: выделение S3 bucket под каждого автора

В ответ на обратную связь от тестировщиков командой было решено выделить по одному S3 bucket на каждого фронтенд разработчика. В нашем проекте были разработчики Манар, Миша - следовательно были созданы условные S3 бакеты jsn-web-manar и jsn-web-michael. В bitbucket-pipelines.yml в step для пулл-реквестов была добавлена логика определения конечного S3 бакета в зависимости от PR автора.

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

  1. Гонка пулл-реквестов одного автора. Если один и тот же разработчик создаст 3 параллельных пулл-реквеста, то все они вызовут запуск пайплайна сборки. Мы не можем точно знать, какой из пайплайнов закончится быстрее. Команде, в частности тестировщику, без использования консоли Chrome сложно понять, какой из пулл-реквестов сейчас развернут на S3 бакете разработчика Михаила.

  2. Появление нового автора. В наших репозиториях создавать пулл-реквест может любой член команды, поэтому эта схема сломалась ровно в тот момент, когда ПР создал кто-то, кроме фронтенд-разработчиков. По нашей тривиальной логике определения бакета его запущенный пайплайн "угонит" S3 бакет одного из разработчиков. В итоге другой тестировщик может потерять version-under-test сайт прям в момент тестирования.

  3. Смена никнейма. Наши разработчики забавы ради любят менять свои git author name время от времени. Для нас это никогда не являлось проблемой до того, как мы применили логику с бакетами на каждого автора. К сожалению, Bitbucket Pipelines из коробки не предоставляют возможности определения автора по его Jira account, поэтому в логике присвоения бакета пришлось оперировать стандартным commit git author. Как вы и сами догадались, при смене имени с "Manar Kurmanov" на "Dark Lord" повторилась ситуация из пункта 2 - был угнан бакет другого разработчика.

С этой шаткой схемой команда прожила еще несколько месяцев.

Оценка:

  • за старания - четверка

  • за QX - тройка

Уровень 3: добавление штампа авторства в web приложение

Команда решила проблему гонки пулл-реквестов добавлением пояснительного текста в footer сайта:

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

Фрагмент из bitbucket-pipelines.yml

- step:    name: Build PR version    caches:      - node    script:      # initial configuration      - apk update && apk add git      - npm install      # preparing site footer text      - TIMESTAMP_FILE="./src/app/some/folder/copyright.timestamp.html"      - GIT_AUTHOR=$(git log -n 1 --format=format:'%an')      - PR_URL="$BITBUCKET_GIT_HTTP_ORIGIN/pull-requests/$BITBUCKET_PR_ID"      - BRANCH_TEXT="PR branch <a href=\\"$PR_URL\\">$BITBUCKET_BRANCH</a><br>"      - echo $BRANCH_TEXT >> $TIMESTAMP_FILE      - echo "Author $GIT_AUTHOR<br>" >> $TIMESTAMP_FILE      - echo "Built at $(TZ=UTC-6 date '+%d-%m-%Y %H:%M') <br>" >> $TIMESTAMP_FILE      - echo "</small>" >> $TIMESTAMP_FILE      - cat $TIMESTAMP_FILE > src/app/target/folder/copyright.component.html      # building artefacts      - npm run build    artifacts:      paths:        # кеширование артефактов для следующего Build Step         - dist/web/**

Казалось бы, +100 к QX, куда еще прозрачнее. Но поставьте себя на место тестировщика в ежедневной работе и вы поймете еще одно скрытое неудобство. Допустим, что разработчик создал 3 параллельных пулл-реквеста и тестировщик проверил сайт на S3 бакете. Что он должен делать дальше? Тестировщику не очевидно, что он находится в ситуации очереди ПР-ок на один и тот же S3 бакет. После он должен зайти в странице Pipelines, найти нужную ветку и сделать ручной Rerun.

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

Оценка:

  • за старания - четверка

  • за QX - тройка с плюсом

Уровень 4: динамичные бакеты под каждый пулл реквест

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

  • Каждый пулл реквест должен породить свой отдельный S3 бакет и задеплоить сайт туда.

  • Нужно, чтобы в комментарий к пулл-реквесту писалась ссылка на этот бакет при каждом новом билде.

  • Автоматика должна уметь подчищать за собой неиспользуемые бакеты

Для реализации этих требований не хватало стандартных Bitbucket Pipes, поэтому нужно было писать кастомные скрипты для взаимодействия с AWS S3. К счастью Bitbucket Pipelines, как и многие CI системы, является cloud-first и предоставляет возможность запускать свои пайплайны на базе любого публичного Docker образа. Мы использовали официальный образ aws-cli, включающий в себя AWS CLI и все базовые утилиты командной строки (curl, sed, xargs).

Ниже фрагмент из bitbucket-pipelines.yml по загрузке статики сайта в динамический бакет. NOTE: в скрипте используются ключи и секреты из учетной записи AWS S3, их можно сгенерировать по официальной инструкции.

- step:    name: Deploy PR version into AWS bucket for QA    image:      name: amazon/aws-cli    script:      # 1. Настройка сессии в aws cli с помощью ключей      - aws configure set aws_access_key_id=$AWS_ACCESS_KEY_ID aws_secret_access_key=$AWS_SECRET_ACCESS_KEY      # 2. определяем название для динамического бакета      - export BUCKET_NAME=web-pullrequest-$BITBUCKET_PR_ID      # 3. если в AWS нету бакета с таким названием, создаем его с нужными флагами      - if [ -z $(aws s3 ls | grep $BUCKET_NAME) ]; then aws s3api create-bucket --bucket $BUCKET_NAME --acl public-read --region ap-northeast-2 --create-bucket-configuration LocationConstraint=ap-northeast-2; fi      # 4. задаем это бакету настройку статичного хостинга      - aws s3api put-bucket-website --website-configuration "{\\"ErrorDocument\\":{\\"Key\\":\\"error.html\\"},\\"IndexDocument\\":{\\"Suffix\\":\\"index.html\\"}}" --bucket $BUCKET_NAME      # 5. очищаем содержимое бакета      - aws s3 rm s3://$BUCKET_NAME --recursive       # 5. заливаем в него собранные html/css/js      - aws s3 cp dist/web s3://$BUCKET_NAME --acl public-read --recursive      # 6. Пишем коммент со ссылкой от имени сервисной учетки в нужный пулл реквест      - export PR_API_URL=https://api.bitbucket.org/2.0/repositories/$BITBUCKET_REPO_FULL_NAME/pullrequests/$BITBUCKET_PR_ID/comments      - export BUCKET_PUBLIC_URL=http://$BUCKET_NAME.s3-website.ap-northeast-2.amazonaws.com      - curl $PR_API_URL -u $CI_BB_USERNAME:$CI_BB_APP_PASSWORD --request POST --header 'Content-Type:application/json' --data "{\\"content\\":{\\"raw\\":\\"[http://$BUCKET_NAME.s3-website.ap-northeast-2.amazonaws.com](http://personeltest.ru/away/$BUCKET_NAME.s3-website.ap-northeast-2.amazonaws.com)\\"}}"

В качестве автора комментарий в пулл реквест мы использовали нашу сервисную учетную запись для CI с использованием App-specific password. В этой статье от Atlassian можно узнать, как создать такой пароль.

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

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

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

- step:    name: Remove dangling s3 buckets left after PR merges    image:        name: amazon/aws-cli    script:      # 1. Запросить список 10 последних MERGED пулл реквестов      - export API_URL="<https://api.bitbucket.org/2.0/repositories/$BITBUCKET_REPO_FULL_NAME/pullrequests?state=MERGED>"      - curl "$API_URL" -u $CI_BB_USERNAME:$CI_BB_APP_PASSWORD > pr_list.json      # 2. выделить бакеты, соответствующие спец-формату       - aws s3 ls | grep -o '[a-zA-Z\\-]\\+pullrequest\\-[0-9]\\+' > buckets.txt- set +e      # очистить все бакеты с номер ПР-ок, которые уже MERGED      # (AWS API требует очистки бакета перед его полным удалением)      - echo "$(cat pr_list.json | grep -o '"id":\\s[0-9]\\+')" | sed 's/[^0-9]//g' | xargs -I{} grep {} buckets.txt | xargs -I{} aws s3 rm s3://{} --recursive      # удалить все бакеты с номер ПР-ок, которые уже MERGED      - echo "$(cat pr_list.json | grep -o '"id":\\s[0-9]\\+')" | sed 's/[^0-9]//g' | xargs -I{} grep {} buckets.txt | xargs -I{} aws s3api delete-bucket --bucket {}

Оценка:

  • За старания пятерочка

  • за QX - четверка с плюсом. Почему не пять? Потому что на своей шкуре мы поняли, что улучшение любого X (QX, DevX, HX) - это бесконечный процесс

Технические ремарки

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

#1: По поводу CORS

Так как API запросы совершаются с одного хоста (.amazonaws.com) на другой хост (*.somebank.com), по умолчанию они будут блокироваться браузером из-за настроек CORS (cross origin resource sharing) сервера. Если вкратце, то браузер позволяет отправлять запросы только из того же хоста, откуда сайт был запрошен. Для примера, API на api.server.com будет принимать запросы только с сайта server.com. При попытке сделать GET запрос с сайта another.com браузер сначала совершит "pre-flight" запрос на сервер и поймет, что сервер строго выдерживает правило "same-origin-policy".

Для того, чтобы запросы со статичного сайта S3 бакета проходили в ваш API, вы должны добавить хост бакета в серверные настройки Headers.

Access-Control-Allow-Origin: <http://bucket.s3-website.amazonaws.com># илиAccess-Control-Allow-Origin: *

Во всех популярных фреймворках есть поддержка управления Cross Origin.

#2: По поводу расходов

В уровне 4 в скрипте присутствует строка очистки содержимого бакета:

aws s3 rm s3://$BUCKET_NAME --recursive 

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

Если этого не делать, то размер бакета будет увеличиваться пропорционально кол-ву пайплайнов на 1 ПР. В масштабах 3 разработчиков это экономит нам пару центов, но в масштабе десяток разработчиков и долгих ПР - это десятки долларов. Мы считаем, что это полезное упражнение как минимум с точки зрения практики владения AWS API.

ВАЖНО! Если в вашем проекте будет использоваться долгоживущий S3 bucket и вы будете использовать официальный aws-s3-deploy pipe, то убедитесь, что вы используете DELETE_FLAG. Этот флаг очищает bucket перед очередной выгрузкой файлов. Во время уровня #1 наша команда об этом флаге не знала в течение 2 месяцев и узнала только после обнаружения нескольких тысяч файлов в одном бакете. Поэтому парочку десяток американских долларов было сожжено во имя наших познаний.

# вызов пайпа загрузки файлов в S3 с флагом DELETE_FLAG- pipe: atlassian/aws-s3-deploy:0.2.4    variables:      AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID      AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY      AWS_DEFAULT_REGION: $AWS_DEFAULT_REGION      S3_BUCKET: $S3_WEBADMIN_BUCKET_NAME      DELETE_FLAG: 'true' # не забыть этот флаг      LOCAL_PATH: $(pwd)      ACL: 'public-read'

Вывод

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

Финальную версию bitbucket-pipelines.yml можно посмотреть в github репозитории.

Материалы к прочтению

Подробнее..
Категории: S3 , Angular , Devops , Frontend , Amazon web services , Aws , Cicd , Pipelines , Bitbucket

Выбор оптимальной платформы для веб приложения

29.03.2021 10:21:19 | Автор: admin

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

Проблемы внедрения

Как уже упоминалось выше, запустить веб-приложение можно на разных платформах. Можно на собственных серверах компании, можно использовать Shared Hosting провайдеров, можно приобрести VPS/VDS хостинг, например, у DigitalOcean, а можно для размещения вашего веб-приложения использовать облачную инфраструктуру от интернет гигантов -Amazon Web Services (AWS), Google Cloud, Microsoft Azure и так далее. Существуют также и специально ориентированные на хостинг веб-приложений решения вроде Pantheon или WP Engine.

Множество возможных решений вызывает головную боль у новичка. Что выбрать? Что дешевле? Что надежнее? Где лучше техподдержка? Где больше возможностей и где лучше перспектива роста? Давайте рассмотрим плюсы и минусы каждого из вариантов.

Dedicated server

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

Shared Hosting

Если вы решили использовать Shared Hosting, то со стоимостью необходимых затрат наоборот, все хорошо. Это, пожалуй, самое дешевое решение. К тому же часто дополнительно вы получаете бесплатные доменные имена. Ваш сервер настроен и в общем-то не требует специальных технических знаний для использования. Все обслуживается и администрируется службой поддержки сервис провайдера. Но при этом вы крайне ограничены в добавлении и конфигурировании дополнительных возможностей для вашего проекта. Более того, производительность и стабильность вашего веб-приложения может серьезно пострадать из за внезапных и значительных потоков трафика ипотребления ресурсов сервера соседними сайтами и веб-приложениями. А таких прожорливых соседей у вас может быть несколько сотен! Оперативности технической поддержки при таком количестве клиентов скорее всего не следует ожидать. Кроме того, остро стоит вопрос безопасности shared hosting-а, ведь если хотя бы один из сайтов или веб-приложений будет взломан злоумышленниками, скорее всего они сумеют получить доступ и к ресурсам других проектов на этом сервере. По этим и другим причинам рынок shared hosting стагнирует в последние годы.

VPS Hosting

Одно из самых популярных решений. У многих на слуху компания DigitalOcean со своими популярными предложениями. Виртуальные приватные сервера дороже, чем Shared Hosting, на за эту разницу в цене вы получаете выделенные только для вас ресурсы на сервере, соседи по серверу не влияют на производительность вашего веб-приложения, конфигурируемость очень высокая поскольку вы имеете полный root доступ к вашей системе и тем самым имеете полное право навыполнение всех без исключения операций. Удобно вертикально масштабировать ваш VPS вручную и с даунтаймом. Достаточно остановить VPS, добавить ресурсов и снова запустить. С физическим сервером такое не пройдет. Но опять же, помимо достаточно ощутимой цены,тут требуется высокая квалификация и серьезные технические знания по управлению серверами. По сути, нужны специалисты такого же уровня, как и для управления физическими серверами, разница только в том, что нет проблем с hardware (не нужен план замен, закупок, монтажа и тому подобное), но инфраструктурно всё то же самое. Поэтому и для VPS hosting нужны высококвалифицированные администраторы.Чтобы сконфигурировать рабочее окружение для вашего веб-приложения и поддерживать его, вам потребуется немало времени.

Managed Hosting

Вариант хостинга, когда для вас запускают конкретное веб приложение, дают вам административный доступ в него, но непосредственное управление сервером осуществляется не вами. Таким образом, вы ограничены только вашим приложением. Управлять вы можете только тем, что оно позволяет делать в своих рамках. А поскольку таких как вы много на физическом сервере, то возникают все те же проблемы, которые характерны для Shared hosting -нестабильность объёма фактически доступных ресурсов, медленный ответ техподдержки и так далее.

Clouds

Давайте тут остановимся подробнее. Динамика роста популярности облачных решений в последние годы впечатляет. Аналитическая компания Gartner оценила объем мирового рынка публичных облачных сервисов в $242,7 млрд по итогам 2019 года. В 2021 году глобальный рынок внедрения облачных технологий превысит в общей сложности $306 млрд по данным той жеGartner. Решения на базе облачных технологий выбирают для себя компании и организации независимо от своего размера. Каждый находит в них для себя что-то свое, но общие преимущества облачных решений очевидны:

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

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

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

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

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

Но при всех преимуществах облачных технологий, в процессе их внедрения в работу компании, неизменно возникает проблема высокого порога вхождения. Она заключается в сложности выбора облачной архитектуры. Например, непросто выбрать подходящий для вашего проекта AWS stack, который обеспечивал бы все потребности и его стоимость не выходила бы за рамки бюджета. Вообще, если мы говорить об AWS, то его можно представить себе в виде некого конструктора, изкоторого вы можете сделать много разного - главное уметь это делать. Организацию хостинга веб-приложения с помощью AWS порой сравнивают со сборкой компьютера (по сравнению с покупкой готового - заказа хостинга у провайдера):EC2-это материнская плата и память. Онпозволяет запускать instance на базе образа операционной системы.EBS-это как диск. Вы можете сказать: сделай мне диск размером в 45 гигабайт и подключи его к такому-то instance (созданный "диск" будет называться volume). В результате в вашей системе появляется новое устройство, которое вы можете монтировать, форматировать и работать с ним. Все, что было записано на него, сохраняется независимо от жизни instance.S3-это как внешнее хранилище. Туда можно сохранять большие файлы и хранить их там вечно. А есть еще сервисы для логирования, мониторинга, баз данных, DNS и множество других. Как собрать из этого набора комплектующих именно тот "компьютер", или AWS stack, который обеспечит оптимальную работу вашего приложения и при этом не переплатить?Новичку в облачных технологиях непонятно, какую конкретно схему AWS stack использовать, какие выбрать сервисы и компоненты, как их соединять между собой. Оценить сложность выбора можно по вот этой схемеCNCF Cloud Native Landscape.

Усложняет задачу выбора и тот факт, что для использования AWS Cost Forecast или калькулятора для расчета расходов от пользователя требуются специфические знания и навыки. Кроме того, весьма сложно создать описания процессов, структуры и необходимых скриптов. Все это требует наличия высококвалифицированных специалистов, глубоко разбирающихся в облачных технологиях Amazon, Google или Microsoft.

В общем, главный минус хостинга в облаках - он сложный.

App-specificproviders

Если рассматривать услуги App-specific providers, которые рассчитаны в первую очередь на разработчиков, то широко известными примерами таких сервисов являются Google AppEngine, VMWare Pivotal Cloud Foundry, Heroku, Pantheon и другие. Такиесервисы представляют наборы готовых компонентов для создания приложений, а также фреймворки для управления платформой. В данном случае компонентами будут являться сервисы баз данных, репозитории, инструменты автоматизированного деплоя, мониторинга, среды тестирования и тому подобные сервисы.

Уровень входа в эти сервисы ниже, чем в облачные, но тем не менее, для развертывания хостинга вашего приложения на таких системах, какHeroku или Pantheon требуется написание специального манифеста,разрабатывать и отлаживать который для новичков очень непросто.Недостатки напоминают таковые у Managed hosting - ты имеешь только то, что тебе дают. При этом часто чего-то не додают, например, нужную конкретную версию компонента. Кроме того, неудобны ценовые планы - вы либоне помещаетесь в план, либо платите за большие ресурсы, чем потребляет ваш проект. В итоге часто получается так, что в процессе роста ваше приложение начинает обходиться слишком дорого, но так как вы уже адаптировали его для конкретного PaaS, перейти на какое-то другое решение вам уже сложно.Но при этом у App-specific providers нет проблемы выбора и соединения множества компонентов, как у AWS или других облачных провайдеров.

Предлагаемое решение

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

  • AWS account

  • GIT account

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

Кастомизация и отличия от конкурентов

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

Масштабируемость

В отличие от решений масштабируемости, которые предлагают сервис провайдеры,WSP предоставляет возможность использовать autoscaling, или, иначе говоря, горизонтальнуюмасштабируемость. Autoscaling легко настраивается в зависимости от потребностей работы вашего приложения. Учитывая, что вы платите только за фактически используемые ресурсы, autoscaling становится очень выгодным решением. Если нагрузка снижается, избыточные серверные мощности высвобождаются, соответственно вы платите меньше.

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

Наскриншоте нижехорошо видно, как просто это можно настроить:

Мониторинг и логи

Настройка систем мониторинга и логирования крайне нетривиальная задача в AWS. В WSP логирование с помощью ELK stack (Elasticsearch, Logstash, Kibana) и мониторинг с использованием Prometheus или Grafana настраиваются и подключаютсяпредельно просто. То есть, ониподключаются автоматически к каждому приложению,если при регистрацииAWS аккаунта к WSP было выбрано использование этой функциональности. В то же время вы всегда можете отключить мониторинг и логи, например, для экономии. И наоброт, включить их, когда они потребуются.

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

Управление затратами

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

Технические домены с сертификатами

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

Автоматическое развертывание баз данных в Amazon RDS

WSP может автоматически разворачивать экземпляр базы данных типа PostgreSQL, MySQL или MariaDB для вашего приложения в Amazon RDS. Это настраивается непосредственно в "Environment settings" вашго приложения:

Zero downtime

Если в процессе работы с вашим приложением WSP производит развертывание новой версии приложения или откат на предыдущую версию, сессия работы переключается с текущей на новую версию приложения совершенно незаметно для вас. Реализован полный Zero Downtime для таких случаев.

One more thing!

  • Lift&Shift. Особенное внимание в разработке и концепции WSP уделяется тому, что вам совершенно не нужно как-то адаптировать и переделывать ваше приложение для его работы в облаке. С помощью WSP оно будет работать без каких то дополнительных усилий для его адаптации.

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

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

  • Все используемые в продукте компоненты стандартные. Эти компоненты- признанный мировой стандарт индустрии, имеют открытый исходный код и бесплатны.Никакие проприетарные компоненты не используются. Например, для pipeline в WSP используется Tekton.

  • Все секретные данные, такие, например, как пароли, логины и т.д. шифруются.

  • Поддерживается непрерывное развертывание (Continuous Deployment (CD)). То есть, платформа может автоматически собирать и разворачивать приложение по коммиту в GIT репозитории.

  • В настоящее время в качестве поддержки концепции "Infrastructure as a code" WSP может считывать параметры приложения из специальных файлов из git-репозитория, то есть кроме задания параметров приложения из UI возможно задавать параметры в файле.

Планы дальнейшего развития

В настоящее время WSP работает только с облачной инфрастуктурой Amazon. В дальнейшем планируется расширить этот список облачными сервисами Google, Microsoft Azure и DigitalOcean. Для тех потребителей, кто использует инфрастуктуру на базе Kubernetes также планируется поддержка.

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

Заключение

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

Проект находится еще в очень ранней стадии развития. Фаза активной разработки продолжается. В настоящее время команда Pleskуже использует WSP для наших собственных сервисов. Если вы хотите попробовать WSP, посмотреть, подходит ли он для вас, повлиять на развитие проекта путём обратной связи, поделиться вашими сценариями использования - welcome to closed alpha. Присоединиться можноздесь.

Подробнее..

И еще разок про Serverless

15.03.2021 14:07:31 | Автор: admin
Логотип AWS Lambda (ну или Half Life, я так и не понял)Логотип AWS Lambda (ну или Half Life, я так и не понял)

С публичного релиза AWS Lambda прошло ни много ни мало 6 с лишним лет. Реактивные функции, реагирующие на события, не только позволили по-другому смотреть на архитектуру систем и приложений, но и породили новый buzzword Serverless.

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

Мой пост будет опираться на технологии, разработанные в компании AWS, но тезисы из него применимы как к другим облачным провайдерам (GCP, Azure), так и к "домашним" имплементациям (OpenFaaS).


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

  • Сначала я "демистифицирую" понятие Serverless, отделив его от реактивных функций Lambda,

  • Затем я пройдусь по архитектуре Lambda

  • И закончу этот пост рядом рекомендаций по разработке и сопровождению Serverless приложений.

В дальнейшем я буду использовать sls для обозначения Serverless. Я очень ленивый.

Lambda != Serverless, Lambda in Serverless == True

Горе павшим жертвами сладких речей адвокатов и евангелистов! "Вам не нужно будет управлять парком машин!", "Вы сможете развернуть свое приложение за считанные секунды!", "С помощью sls эффективность вашей разработки возрастет в разы!", - это и многое другое пытаются втолкнуть мне толпы героев и евангелистов AWS, но я познал суть.

Видите ли, риторика "мне не нужно думать об инфраструктуре" обречена на провал. Разве код работает в воздухе? Разве он не нуждается в сети? Разве мне нужно заботиться об инфраструктуре, если у меня есть Kubernetes, и я просто объявляю в нем сущности?

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

Fail cheap - вот, что конкурентно "продает" sls. Чтобы проверить тезис, мне не нужно так много ресурсов, как понадобилось бы чтобы развернуть небольшой кластер из виртуалок или контейнеров. Скорость здесь - не решающий фактор. В 2021-ом году, что Lambda функция, что таблица DynamoDB, что контейнер в ECS/EKS, что экземпляр EC2 - все это запускается в считанные минуты, если не секунды.

Скрытое послание 1

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

Что такое Serverless

AWS предоставляет огромный набор сервисов для построение систем различной степени нагрузки и тяжести, часть из которых имеет бирку sls - очереди и потоковая обработка (SQS, Kinesis), нотификации (SES, SNS), интеграции (EventBridge, Step Functions), хранилище (S3), базы данных (DynamoDB), работа с данными (Glue, Athena). Если вы смотрели мое выступление на HighLoad++, вы помните, как именно я отличаю sls от "обычных" сервисов. Sls создает для вас отдельный уровень абстракции, снимая с вас операционную нагрузку по работе с сервисом (на самом деле нет - теперь вам надо учить новую технологию/подход).

Взять к примеру базы данных DynamoDB - сама СУБД уже есть! В ваше пользование предоставляется таблица с ее "пропускной способностью" (WCU/RCU), индексы и прочие фичи. В случае с сервисом ETL Glue вас не допускают к работе с самим движком ETL - вместо этого вы объявлете схему трансформации данных, указываете источник и пункт назначения данных, а так же описываете задачу. Все остальное находится вне вашего ведения и управления, чтобы вы себе лишний раз ногу не отстрелили (если очень хотите отстрелить - поднимайте свое на виртуалках ЕС2).

Отличие будет в биллинге. Если в случае с базами RDS и задачами ECS Fargate где оплата идет поминутно (или посекундно?), с sls вы платите за объем (сколько гигабайт "весят" данные в S3) и утилизацию (запросы и трафик).

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

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

Ничего сложного, верно? Основное непонимание связано как раз с отсутствием простой истины в умах: sls - это абстракция над PaaS, которая тарифицируется по-другому.

Отсюда и сложности с sls приложениями. Sls приложение - не только набор Lambda функций за API GW. Sls приложение состоит только из sls сервисов.

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

Архитектура AWS Lambda

Родоначальница sls подхода вызвала в своей время немало шума, ведь ее релиз пришелся на то же время, что и буря вокруг Docker и рождение Kubernetes. За простотой Lambda функций (далее - Функция) стоит определенная хитрость, ведь мысль о том, что "просто нужно написать код и запустить" вызывает недоверие.

На самом же деле Функции несколько сложнее, чем звучат из сладких уст многочисленных sls евангелистов и героев, (и порождают не меньше сложностей, но об этом позже). Архитектура Функции состоит из 3 частей: Источник События (Triggering Event); внутренности AWS Lambda - runtime, deployment package (логика с зависимостями), слои (layers) и "дополнение" (extensions); точка назначения Функции (если имеется) - корзина S3, таблица DynamoDB, очередь SQS и т.д.

Картинка посвящается Ване Моисееву - моему другу и любителю иконок AWSКартинка посвящается Ване Моисееву - моему другу и любителю иконок AWS

В довесок к этому идут еще мониторинг, трассировка запроса и многие прелести, например Lambda Permission - а именно "разрешение" какому-то внешнему ресурсу (генератору событий) запускать Функции, передавая им полезную нагрузку (Событие).

Что происходит под капотом Lambda - история куда сложнее, и лучше послушать о ней из первоисточника.

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

Как жить с Lambda

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

  1. Локальная разработка и отладка

  2. Архитектура sls приложений

  3. Организация кодовой базы

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

  5. Эксплуатация (логирование, мониторинг, трассировка)

  6. Безопасность

Звучит сложно? Ну передавайте от меня привет тем, кто говорил, что sls это легко.

1. Локальная разработка и отладка

Стоит первым пунктом потому, что с этого все и начинается. AWS завез прекрасный инструмент под названием Serverless Application Model или SAM.

SAM представляет собой два компонента: интерфейс командной строки aws-sam-cli (ставится как через brew так и через pip) и шаблон (сильно упрощенный CloudFormation).

Для отладки Функции нужно объявить ее в шаблоне. Затем можно будет вызывать ее двумя способами: sam local invokeили sam local start-api(для Функций, отвечающих на вызовы API GW).

Если вы впервые видите SAM, то проще всего запустить один из quick start шаблонов, заботливо приготовленных для вас инженерами AWS.

$ sam initWhich template source would you like to use?1 - AWS Quick Start Templates2 - Custom Template LocationChoice: 1What package type would you like to use?1 - Zip (artifact is a zip uploaded to S3)2 - Image (artifact is an image uploaded to an ECR image repository)Package type: 1Which runtime would you like to use?1 - nodejs12.x2 - python3.83 - ruby2.74 - go1.x5 - java116 - dotnetcore3.17 - nodejs10.x8 - python3.79 - python3.610 - python2.711 - ruby2.512 - java8.al213 - java814 - dotnetcore2.1Runtime: 2Project name [sam-app]:Cloning app templates from https://github.com/aws/aws-sam-cli-app-templatesAWS quick start application templates:1 - Hello World Example2 - EventBridge Hello World3 - EventBridge App from scratch (100+ Event Schemas)4 - Step Functions Sample App (Stock Trader)5 - Elastic File System Sample AppTemplate selection: 1    -----------------------    Generating application:    -----------------------    Name: sam-app    Runtime: python3.8    Dependency Manager: pip    Application Template: hello-world    Output Directory: .    Next steps can be found in the README file at ./sam-app/README.md

Пройдя в sam-appможно вызвать функцию локально (первый запуск займет некоторое время, образ Lambda runtime нужно скачать):

$ sam local invoke HelloWorldFunctionInvoking app.lambda_handler (python3.8)Image was not found.Building image.......................................Skip pulling image and use local one: amazon/aws-sam-cli-emulation-image-python3.8:rapid-1.15.0.Mounting /Users/karentovmasyan/Development/Personal/dummy_project/sam-app/hello_world as /var/task:ro,delegated inside runtime containerSTART RequestId: e7036160-e11c-440a-b089-8099b1e0d500 Version: $LATESTEND RequestId: e7036160-e11c-440a-b089-8099b1e0d500REPORT RequestId: e7036160-e11c-440a-b089-8099b1e0d500Init Duration: 0.29 msDuration: 114.08 msBilled Duration: 200 msMemory Size: 128 MBMax Memory Used: 128 MB{"statusCode": 200, "body": "{\"message\": \"hello world\"}"}%

А установив плагин для JetBrain IDE или VS Code можно использовать и полноценный отладчик, чтобы узнать, где конкретно входящий JSON неправильно обрабатывается!

2. Архитектура sls приложений

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

Давайте представим некий market-service для биржи, который имплементирует API GET /markets. Вызовы на этот API вернут нам список текущих рынков, базовых валют, по прямому запросу - тикер.

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

GET /marketsGET /markets/baseGET /markets/ticker?pair=USD-RUB

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

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

# GET /markets{  # some params...  "resource": "/markets",  "path": "/markets",  "headers": #...  "queryStringParameters": null,  # etc...}# GET /markets/ticker?pair=USD-RUB{  # some params...  "resource": "/markets/ticker",  "path": "/markets/ticker",  "queryStringParameters": {  "pair": "USD-RUB"}} 

Мы можем осуществить проверку пути/ресурса и в зависимости от этого реализовать логику одной функции. Что-то навроде:

def get_markets():  passdef get_ticker(pair):  passdef handler(event, context):  path = event.get('path')  if path == '/markets':    return get_markets()  elif path == '/markets/ticker':    return get_ticker(event.get('queryStringParameters').get('pair'))

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

  1. Тарификация Функции идет по времени выполнения и мы тратим драгоценное время на избыточный control flow.

  2. Если Функция должна "ходить" в несколько мест (S3, DynamoDB и прочие API AWS), то мы даем ей опасно большое количество разрешений.

  3. Проблемы масштабируемости: нам нужно масштабировать GET /markets/ticker, но вот GET /marketsдорогой, и нам хотелось бы применить к нему throttling, что в условиях одной функции сделать невозможно.

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

И каждая функция будет иметь свою ограниченную область применения. Это порождает другую проблему - как нам организовать управление повторяемым кодом и кодовую базу в принципе?

3. Организация кодовой базы

Подход выше открывает 2 проблемы: управление общим кодом (что если 90% кода в Функциях одинаковые? Где моя бритва?!) и организация репозитория.

Раньше чтобы запаковать Функцию с зависимостями, нужно было создавать специальный deployment package и загружать его на S3. Что вручную, что с SAM это представляет собой следующее:

$ pip install -t . -r requirements.txt$ zip -r lambda.zip .$ aws s3 cp lambda.zip s3://bucket_name/

И если с внешними зависимостями еще можно как-то жить, то с внутренними возникает вопрос. А в "многофункциональном" sls приложении наверняка найдется одна или две библиотеки, которые делят между собой все функции.

Для компилируемых языков проблема не такая неприятная, управление зависимостями пройдет на стадии сборки. Для интерепретируемых языков, таких как Python, JavaScript и Ruby, проблема решается с помощью слоев (Lambda Layers). Слои Функций работают по схожему принципу со слоями контейнерных образов и предоставляют собой отдельное хранилище, монтируемое к runtime'у Функции.

Таким образом, проект можно организовать следующим образом:

$ tree -L 2. README.md  requirements.txt src # исходный код  lambda # handler'ы приложения  lib # общие библиотеки template.yaml tests venv

В шаблоне SAM можно указать директорию, чтобы создать нужный слой:

Resources:  Layer:    Type: AWS::Serverless::LayerVersion    Properties:      CompatibleRuntimes:          - python3.6          - python3.7          - python3.8          - python3.9      ContentUri: 'src/lib'

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

Resources:  MarketsGet:    Type: AWS::Serverless::Function    Properties:      CodeUri: src/lambda/markets/get      Handler: markets_get.handler      Layers:        - !Ref Layer      Events:        ApiEvent:          Type: Api          Properties:            Path: /markets            RestApiId: !Ref Api            Method: get

Возникает вопрос: "А что делать, если в одном репозитории мне нужны разные версии зависимостей?" С помощью Слоев эта проблема не решается. Самое правильное - собрать, упаковать и положить зависимость в репозиторий. В случае с Python - Pip server.

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

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

Что CloudFormation, что Terraform обладают возможностью объявлять ресурсы в облаке от Amazon, но объявление sls ресурсов может стать очень муторным процессом в виду гибкости и тонкой настройки.

SAM хорош тем, что создает абстракцию над CloudFormation для упрощенного объявления ресурсов sls приложений. В свою очередь Антон Бабенко сделал похожий инструмент для TF. Выбирать между одним или вторым я не буду (в тусовке амазонщиков у меня уже есть репутация "хейтера" Terraform), а разбор отличий заслуживает отдельной статьи.

Все еще живой Serverless framework тоже управляет жизненным циклом sls приложений (сам я с ним не работал, так что на ваш страх и риск).

Ну и вишенка на торте и вершина айсберга Хайпа - Cloud Development Kit или CDK. В отличие от выше описанных инструментов CDK объявляет инфраструктуру с использованием высокоуровневых языков программирования (TypeScript, JavaScript, Python, C#, Java), код которых компилируется ("синтезируется") в шаблон CloudFormation. Похожую историю имплементировали и ребята из HashiCorp, назвав ее cdktf.

Архитектура CDK/cdktf сама по себе сложная, но это не выступает барьером, который даже неопытные инженеры-облачники не в состоянии предолодеть. В сети полно материалов, как блогов, так и self-paced workshop, лекций, CDK day - их море.

Скрытое послание 2

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

В остальном развертывание sls приложений ничем не отличается от развертывания других приложений на AWS - у вас имеется цепочка поставки (pipeline), которая прогоняет тесты, пакует ресурсы и раскатывает их по различным регионам и аккаунтам. Делаете вы это с помощью sam deployили terraform apply- не так уж и важно.

5. Эксплуатация

С внутренними метриками и логами Функций проблем нет - они сами собой складываются в CloudWatch (разумеется, если вы не забыли прописать нужные политики в роли).

Отладить простейшую CRUD-функцию тоже много ума не надо. Прилетел JSON в Функцию, с ним что-то произошло, выхлоп лег куда-то. Если что-то в этом потоке пошло не так, достаточно локально отладить Функцию с помощью того же SAM CLI, приложив к ней багообразующий event.

Другое дело, если Функций много и работают они в каком-то долгом транзакционном процессе, наппример Step Functions. Отлавливать логи по времени, как прилетел злосчастный запрос, который не смог корректно обработать - то еще приключение, и разработчик может потратить неприемлемо много времени, чтобы найти баг.

На помощь придет инструмент observability от AWS под названием X-Ray. X-Ray является сервисом трассировки, он тесно интегрирован в sls экосистему. Достаточно включить поддержку X-Ray в Функции, и каждому запросу начнет присваиваться нужный идентификатор.

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

6. Безопасность

С очевидными вещами разбираться не будем. Всем известны такие базовые паттерны безопасности, как шифрование (at-rest, in-transit) и контроль сетевого периметра c помощью NACL и Security Groups.

У каждой Функции должна быть своя IAM роль. И по лучшим практикам безопасности каждая роль должна следовать least-privilege principle - то есть не даем больше прав, чем минимально нужно для работы приложения.

Иными словами, если наша Функция выполняет операцию dynamodb:PutItem, как минимум странно давать роли разрешение dynamodb:*(разрешаем все действия по отношению к DynamoDB). Так же странно видеть Resource: "*", в то время как работа идет в отношении одной таблицы.

Поэтому первое правило безопасности в sls приложениях - минимум прав. Потратье время и изучите как работает AWS IAM, и какие трюки там есть для тонкого управления доступом.

Скрытое послание 3

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

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

Бояться тут надо не того, что кто-то взломает Функцию и изнутри нее будет делать всякие глупости (такая вероятность есть, но это тема другой статьи), но того, что роль Функции кто-то может assume, т.е. "принять на себя". Именно таким образом взломали Capital One: не взломали сервер, а просто получили ARN роли, через которую получили STS ключ, секрет и токен. Потому что кто-то ошибся в поле Principal. Стыд!


Вроде ничего не забыл? Я не ожидаю, что после прочтения вы сразу побежите писать Lambda функции и хвастаться стремительно сокращаюимся парком EC2 машин. Ниже я прилагаю ссылки, которые позволят вам двигаться дальше в изучении Serverless и Lambda в частности:

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

Подробнее..
Категории: Lambda , Amazon web services , Aws , Cloudnative , Serverless

Перевод Как выглядит обычная 100-но бессерверная архитектура в AWS Lambda

11.05.2021 10:09:42 | Автор: admin

Когда мы говорим о бессерверной архитектуре, мы обычно выходим далеко за рамки модели функция как услуга (FaaS), одной из реализаций которой являются функции AWS Lambda.

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

Как же будет выглядеть такого рода архитектура в интернет-проекте?

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

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

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

Мы рекомендуем полномасштабный переход на AWS Lambda c использованием событийных микросервисов, написанных на TypeScript

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

Amazon Web Services

Конкурентный рынок облачных технологий весьма насыщен: AWS, GCP, Azure, IBM Cloud, Alibaba Cloud каждая из этих компаний предлагает свое замечательное решение и развивается беспрецедентно высокими темпами.

Бен Эллерби (Ben Ellerby) сравнил трех крупнейших облачных провайдеров в этой статье: мы отдали предпочтение решениям AWS. С точки зрения бессерверных технологий они оказались самыми продвинутыми. Именно решения AWS позволяют нам максимально приблизиться к полностью бессерверной архитектуре. Чтобы это проиллюстрировать, в следующей части статьи мы подробно рассмотрим каждый из AWS-сервисов, входящих в состав наших архитектурных блоков.

Node.js с использованием TypeScript

JavaScript это один из самых популярных языков программирования в мире, с огромным сообществом разработчиков (посмотрите статистику на GitHub). Мир бессерверных вычислений не сильно выпадает из этой статистики. Например,по данным Datadog, 39% всех развернутых сегодня систем AWS Lambda работает на JavaScript, хоть Python и лидирует с 47%. TypeScript делает еще один шаг вперед и добавляет к JavaScript еще один замечательный уровень защиты. И наконец, JavaScript отлично работает в AWS Lambda с подавляющим большинством сценариев использования!

Serverless Framework

Именно в этом фреймворке по большей части реализуется практика IaC (инфраструктура как код) поверхCloudFormation. Задав функцию AWS Lambda, которая будет реагировать на HTTP-событие, Serverless Framework автоматически развернет связанный ресурс API-шлюза, а также соответствующий маршрут вместе с новой функцией AWS Lambda. Затем, когда будет достигнута предельная емкость фреймворка и нам понадобится более сложная конфигурация сервисов, мы сможем легко добавить CloudFormation.

C гордостью сообщаем: команда Theodo настолько уверовала в Serverless Framework, что решиластать официальным партнером фреймворка!

Узкоспециализированные функции AWS Lambda

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

разделение на микросервисы

Чтобы не заставлять команды разработчиков толкаться и мешать друг другу, не раздувать файлы package.json и serverless.yml до немыслимых размеров (кстати, в CloudFormation довольно щедрое ограничение на число ресурсов 500), не тратить много времени на развертывание CloudFormation, а также лучше ориентироваться в базе кода и четко разграничивать ответственность между функциями AWS Lambda, мы устанавливаем границы и разделяем проект на отдельные микросервисы.Бен Эллерби написал здесь о полезной методологии мозгового штурма под названием EventBridge Storming, которая как раз и помогает определить эти границы.

В нашем монорепозитории: 1 микросервис = 1 стек CloudFormation = 1 файл serverless.yml + 1 файл package.json. Кроме того, микросервисы управляют своими собственными сущностями данных и не предоставляют их в общее пользование другим микросервисам.

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

взаимодействие на языке событий

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

Для каждого типа функций требуется особая бессерверная архитектура с конкретным набором AWS-сервисов

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

Фронтенд (разработка)

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

Amplify это сразу несколько полезных вещей: инструмент CLI, инструмент IaC, SDK, а также набор UI-компонентов. Мы используем при разработке фронтенда JS SDK, чтобы ускорить интеграцию с ресурсами (например, Cognito для аутентификации), развернутыми при помощи других инструментов IaC, таких как Serverless Framework.

Хостинг сайтов

Большинство современных веб-сайтов это одностраничные приложения (Single Page Applications, SPA). Это полнофункциональные динамические приложения, упакованные в единый набор статических файлов, которые загружает пользовательский браузер, когда он впервые обращается к URL-адресу. В среде AWS мы размещаем эти файлы на файловом хранилищеS3и предоставляем к нему доступ через CDN-сетьCloudFront.

Тем не менее тенденция явно склоняется в пользу SSR-сайтов, использующих отрисовку на стороне сервера, как в случае технологии Next.js. Для настройки SSR-сайта в бессерверной инфраструктуре мы используемLambda@Edgeвнутри CloudFront. Это позволяет реализовать отрисовку на стороне сервера, располагая функции AWS Lambda как можно ближе к конечным пользователям. Чтобы погрузиться в тему, прочитайтеэту статью.

Домен и сертификат

Разумеется, для нашего сайта мы не можем довольствоваться необработанным автоматически сгенерированным S3-адресом, поэтому мы формируем сертификаты и привязываем их к CloudFront с помощьюCertificate Manager, а затем для управления доменами используемRoute 53.

Бизнес-API

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

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

DynamoDB это огромная отдельная тема, и вэтой статьеРоб Кронин (Rob Cronin) дает обнадеживающий комментарий о классических проблемах, связанных с широко известной базой данных NoSQL.

Асинхронные задачи

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

Обработка отказов играет решающую роль в распределенной асинхронной системе. Поэтому в случае асинхронных Lambda-функций мы используем DLQ очередь недоставленных сообщений и передаем окончательное сообщение об отказе сначала в службу уведомленийSNS (Simple Notification Service), а затем в службу очередейSQS (Simple Queue Service). Сейчас нам приходится поступать так, потому что на данный момент невозможно привязать SQS напрямую к DLQ-очереди Lambda-функций.

Передача пуш-сообщений от бэкенда к фронтенду

В асинхронном режиме фронтенд уже не может ограничиваться показом иконки загрузчика в ожидании XHR-ответа. Нужны состояния ожидания и передача пуш-данных от бэкенда. Для этого мы используем API WebSocket от нашего API-шлюза, который поддерживает постоянное соединение WebSocket и запускает Lambda-функции, только когда приходят сообщения. Я написалстатьюдля глубокого погружения в тему. Там я рассказал, почему мы выбрали WebSocket, а не другие решения и как лучше еговнедрять.

Загрузка файлов

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

Пользователи и аутентификация

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

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

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

Машина состояний

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

Мы объявляем машину состояний через CloudFormation включая любые последующие шаги и состояния, все ожидаемые либо неожиданные результаты и назначаем этим шагам некие стандартные действия (например, wait или choice) либо Lambda-функцию (выбираем изподдерживаемых интеграций). Затем мы можем в реальном времени, используя интерфейс AWS, следить за работой машины (на основе логов). На каждом из этих шагов мы можем задать обработку повторных и неудачных попыток. Бен Эллерби более подробно описал сервис в этой статье.

Чтобы привести более конкретный пример, предположим, что мы хотим реализовать email-рассылку помощью SaaS и убедиться, что все сообщения были высланы адресатам.

  • Шаг 1 Lambda: дает SaaS указание выполнить email-рассылку и получает в ответ идентификатор рассылки.

  • Шаг 2 Task Token Lambda: получает callback-токен от Step Function, связывает его с идентификатором рассылки, а затем ждет обратного вызова от SaaS.

  • Шаг 3 (внепотока) Lambda: вызывается перехватчиком из SaaS при изменении статуса рассылки (ожидание, архивация, неудача, успех) и возобновляет поток по статусу кампании, используя соответствующий callback-токен.

  • Шаг 4 выбор: в зависимости от статуса, если рассылка еще не была успешно выполнена, вернуться к шагу 2.

  • Шаг 5 (заключительный) Lambda: обновляет данные о пользователях после рассылки.

В этой статье хорошо объяснено, как работают токены Task Token.

Безопасность

Управление идентификацией и доступом (Identity & Access Management, IAM) эта система нужна для того, чтобы филигранно управлять всеми AWS-доступами со стороны разработчиков, конвейеров CI/CD, а также сервисов AWS, которые обращаются друг к другу. Поначалу это может выглядеть пугающе, однако преимущество тут в широких возможностях тонкой настройки. Они позволяют нам хорошо продумать и детализировать любое действие, которое мы хотим разрешить конкретному потребителю. Это означает, что каждый уровень нашей инфраструктуры защищен по умолчанию.Бен Эллерби выступал на ServerlessDays Nashville на эту тему.

Что касается данных повышенной секретности, таких как API-ключ SaaS, то мы безопасно храним их вSystems Manager (в Parameter Store). Запрашиваем мы эти данные из наших файлов в Serverless Framework или в CloudFormation или даже напрямую из исходного кода (при помощи соответствующего SDK). Полезно упомянуть, что системаSecrets Managerвыполняет аналогичные действия. Такжев данном случае полезен сервисKey Management Service (KMS) он помогает нам управлять ключами шифрования.

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

Мониторинг

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

Мы не прекращаем поиск альтернативных вариантов.X-Ray, например, комплексно отслеживает весь путь запросов в рамках нашей распределенной системы, а затем красочно отображает его в динамике. Иногда, правда, он сбивается со следа, поскольку пока еще не поддерживает некоторые сервисы, такие как EventBridge (а это как раз центральный элемент нашей архитектуры). Еще один сервис,ServiceLens, развертывается поверх X-Ray и CloudWatch и выглядит потрясающе. Есть также ряд перспективных внешних (с точки зрения AWS) решений: Thundra, Epsagon, Lumigo. Однако мы еще не успели в полной мере их опробовать.

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

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

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

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

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

Я, безусловно, продолжу работать над всеми этими темами, поэтому, если вам интересно,напишите мне в твиттер.

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

П.С. От переводчика

Присоединяйтесь к сообществу Serverless в Telegram:Yandex Serverless Ecosystem. Мы регулярно встречаемся в виртуальном пространстве и похоже созревает потребность в очной встрече.

Подробнее..
Категории: Aws , Serverless , Faas

Категории

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

  • Имя: Макс
    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