Фон
В этой статье описывается весь процесс разработки приложения, основанного на технологии без серверов AWS. Инфраструктура построена с использованием Server Server Framework и Terraform. Основной модуль системы представляет собой временную задачу, которая выполняется один раз в день: задача получает набор данных о ценах фонда ETF через Tushare и после обработки генерирует текст торговых сигналов и хранит его в ведре S3. После этого сообщение отправляется в тему AWS SNS, а пользователи, подписанные на тему, получат предупреждение по электронной почте. На веб -странице системы есть портал подписки по электронной почте пользователя, и вы также можете получить доступ к повседневной истории торговых сигналов.
Эта статья охватывает следующее:
- Создайте изображение Docker, чтобы выполнить основную службу.
- Следующие услуги по инфраструктуре AWS необходимы для создания основных услуг с Terraform.
- Установите репозиторий ECR.
- Установите кластер ECS с помощью FARGATE.
- Установите задачи FARGATE.
- Установите задачи по времени CloudWatch.
- Установите IAM разрешения.
- Настройка тем SNS.
- Настройка сети VPC.
- Следующие службы инфраструктуры AWS, необходимые для создания услуг API и веб -сайта с использованием Framework без сервера.
- Настройте функции Lambda.
- Установите шлюз API.
- Настройка маршрута53.
- Настройка CloudFront.
- Настройка сертификатов TLS.
- Настройка ведра S3.
- Настройка облачной информации.
Окончательный результат доступен по адресу: Онлайн -версия Анкет
Исходный код доступен по адресу: Код репозиторий Анкет
Технологический стек выглядит следующим образом:
Предварительные условия
Вам нужно сначала зарегистрироваться для следующей учетной записи:
Жизненный опыт
Архитектура приложения Эволюция История1
- Монолитное применение (монолитное): небольшие приложения, подходящие для стартапов; хорошая производительность.
- Сервис-ориентированный (SOA): крупные приложения, подходящие для сложного предприятия.
- Микросервисы (микросервисы): сложные эластичные масштабируемые приложения для опытных команд.
- Serverless (Serverless): низкая стоимость, подходит для фоновых задач; Также подходит для приложений с большим количеством клиентов и приложений, которые быстро растут и необходимы бесконечно масштабировать.
Без сервера
Создайте и запустите приложения, не задумываясь о серверах 2
Без сервера вычислений, или без серверов для краткости, является моделью выполнения, в которой облачный провайдер (AWS, Azure или Google Cloud) отвечает за выполнение куска кода путем динамического распределения ресурсов и зарядки только за ресурсы, используемые для запуска кода. Код обычно работает в контейнере без сохранения состояния и может быть запускается различными событиями, включая HTTP -запросы, события базы данных, службы очереди, оповещения мониторинга, загрузки файлов, события планирования (задачи CRON) и многое другое. Код, который отправляется в облачный провайдер для выполнения, обычно находится в форме функции, и, таким образом, вычисления без сервера иногда называют «функцией как служба» или FAAS. 3
Преимущества
- Нет затрат на управление сервером
- Гибкое масштабирование
- Оплата за время выполнения услуг
- Автономная высокая доступность и устойчивость к разлому
Недостатки
- Плохое холодное начало производительности
- Сложный мониторинг и отладка
- Зависимость от поставщиков облака
DevOps
Это панорама инструментов DevOps, и я использовал лишь небольшую часть из них в этом процессе разработки приложения, даже без процесса тестирования. Конечно, применение этих инструментов также должно рассмотреть фактическую ситуацию проекта, гибкое приложение.
Архитектура приложения
Приложение разделено на три основных модуля:
- Основная услуга: фоновые задачи временного времени, предоставление функции получения данных о ценах фондов, анализа и генерации торговых сигналов и отправки электронных писем.
- Сервис API: предоставляет API темы подписки.
- Интернет: предоставляет страницу входной темы подписки и просмотреть исторические записи сигналов торговли.
Реализация кодирования
Так как вы будете использовать различные облачные сервисы AWS, чтобы узнать о них, посмотрите на эту статью Услуги AWS объяснены Анкет
Структура кода
. ├── api # api service │ ├── serverless.yml │ └── sns.js # lambda function ├── core # core service │ ├── Dockerfile │ ├── Infrastructure │ │ └── tf-fargate │ │ ├── cloudwatch.tf │ │ ├── ecr.tf │ │ ├── ecs.tf │ │ ├── iam.tf │ │ ├── main.tf │ │ ├── output.tf │ │ ├── sns.tf │ │ ├── tasks │ │ │ └── task_definition.json │ │ ├── variables.tf │ │ └── vpc.tf │ ├── Makefile # CLI entry │ ├── requirements.txt │ └── src │ ├── fund.txt │ └── main.py # fargate task └── web # web service ├── binaryMimeTypes.js ├── client │ ├── assets │ │ └── styles │ │ └── global.less │ ├── components │ │ └── navbar.vue │ ├── layouts │ │ └── default.vue │ ├── pages │ │ └── index.vue │ └── plugins │ └── iview.js ├── index.js ├── nuxt.config.js ├── nuxt.js # lambda function ├── package-lock.json ├── package.json ├── secrets_example.json ├── serverless.yml └── yarn.lock
Основной сервис
Основной сервис проходит через AWS Fargate, который лучше подходит, чем Lambda для выполнения длинных фоновых задач. Основной сервис разрабатывается в Python, и для того, чтобы его запустили в среде AWS ECS, сначала построено изображение Docker, а затем выдвигается в репозиторий AWS ECR.
Docker Image
FROM python:3.8-slim-buster USER root WORKDIR /tmp # for source RUN rm /bin/sh && ln -s /bin/bash /bin/sh # for compile RUN apt-get update \ && apt-get install -y wget \ && apt-get install -y build-essential \ && rm -rf /var/lib/apt/lists/* # for TA-Lib RUN pip install numpy && \ wget http://prdownloads.sourceforge.net/ta-lib/ta-lib-0.4.0-src.tar.gz && \ tar -xvzf ta-lib-0.4.0-src.tar.gz && \ cd ta-lib/ && \ ./configure --prefix=/usr && \ make && \ make install RUN rm -R ta-lib ta-lib-0.4.0-src.tar.gz # set the working directory in the container WORKDIR /code # copy the dependencies file to the working directory COPY requirements.txt . # install dependencies RUN pip3 install -r requirements.txt # copy the content of the local src directory to the working directory COPY src/ . # command to run on container start CMD [ "python", "./main.py" ]
Здесь следует помнить о выборе базового изображения, обычно мы используем альпийскую версию при выборе изображения Python. Тем не менее, альпийская версия требует большого количества компиляции при установке некоторых локальных двоичных пакетов, и эта компиляция будет столкнуться с различными ошибками, поэтому я наконец выбрал версию Buster, которая основана на Ubuntu. Если вы хотите узнать об этом больше, см. Эта статья 《Использование Alpine может сделать Python Docker строить на 50 × медленнее 》 。
После получения токена API для Tushare вам нужно запустить Docker на местном уровне.
docker build -t invest-alchemy/core . # Build docker run -t -i -e TUSHARE_API_TOKEN=xxxx invest-alchemy/core # Local Run
Затем репозиторий ECR создается в AWS, а затем изображения локально построены в ECR для использования задачами ECS.
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin replace_with_your_ecr_addr.dkr.ecr.us-east-1.amazonaws.com # Login ECR docker build -t invest-alchemy/core . # Local Build docker tag invest-alchemy/core:latest replace_with_your_ecr_addr.dkr.ecr.us-east-1.amazonaws.com/invest-alchemy/core:latest # Add Tag docker push replace_with_your_ecr_addr.dkr.ecr.us-east-1.amazonaws.com/invest-alchemy/core:latest # Push to Remote Repo
Инфраструктура как код
Следующим шагом является создание необходимой инфраструктуры (ECS/IAM/SNS/VPC/CloudWatch) через Terraform. Основная ссылка для этой части — это 《Планирование заданий без сервера с помощью AWS Fargate 》 。
ECR/ECS/Задача
Подробнее см. Смотрите исходный код, обратите внимание, что установите емкость_проворовидера
к Fargate_spot
может значительное снижение затрат.
Cloudwatch
Подробнее см. Смотрите исходный код, обратите внимание, что ecs_target
/ network_configuration
может использовать сеть VPC по умолчанию, обязательно установите assign_public_ip
к истинный
В противном случае задача контейнера не сможет получить доступ к внешней сети.
VPC
Используйте сеть VPC по умолчанию AWS. AWS Fargate может работать в нескольких сетевых режимах; Самый простой, публичный режим подсети выбирается здесь.
Для других сцен см. 《Шаблоны облачныхформ для развертывания AWS Fargate》 Анкет
Для дальнейшего изучения вы можете прочитать эту статью 《 Fargate Networking 101》 Анкет
Я
######################### Role used by the container regulates what AWS services the task has access to, e.g. your application is using a DynamoDB, then the task role must give the task access to Dynamo. resource "aws_iam_role" "ecs_service_role" { name = "${var.project}_ecs_service_role_${var.env}" assume_role_policy = "${data.aws_iam_policy_document.ecs_service_assume_role_policy.json}" } resource "aws_iam_role_policy" "ecs_service_policy" { name = "${var.project}_ecs_service_role_policy_${var.env}" policy = "${data.aws_iam_policy_document.ecs_service_policy.json}" role = "${aws_iam_role.ecs_service_role.id}" } data "aws_iam_policy_document" "ecs_service_policy" { statement { effect = "Allow" resources = ["*"] actions = [ "iam:ListPolicies", "iam:GetPolicyVersion" ] } } data "aws_iam_policy_document" "ecs_service_assume_role_policy" { statement { actions = ["sts:AssumeRole"] principals { type = "Service" identifiers = ["ecs-tasks.amazonaws.com"] } } } resource "aws_iam_role_policy_attachment" "ecs_service_role_policy_attachment" { role = aws_iam_role.ecs_service_role.name policy_arn = "arn:aws:iam::aws:policy/AWSLambdaFullAccess" # https://gist.github.com/gene1wood/55b358748be3c314f956 } ######################### Role used by the container enables the service to e.g. pull the image from ECR, spin up or deregister tasks etc resource "aws_iam_role" "ecs_task_execution_role" { name = "${var.project}_ecs_task_execution_role_${var.env}" assume_role_policy = <
Здесь определены три роли.
- ECS_SERVICE_ROLE: привилегии приложения контейнеров, такие как основная служба, необходимо для того, чтобы продвигать данные в S3 и SNS, вам необходимо иметь соответствующие привилегии для этой роли.
- ECS_TASK_EXCUTION_ROLE: Например, разрешение на выполнение задач ECS, если ECS должен вытащить изображения из ECR, ему необходимо иметь разрешение на доступ к ECR.
- ECS_EVENTS_ROLE: Задача задачи CloudWatch, например, задачи времени, необходимо для выполнения задач ECS, вам необходимо иметь разрешение
Amazonec2containerServiceEventsrole
роль.
Секреты приложения
Приложения всегда должны полагаться на некоторую конфиденциальную информацию, такую как различные токены API. Основной сервис зависит от токена Tushare API, поэтому его необходимо вводить через Terraform. Здесь я имею в виду это 《 Комплексное руководство по управлению секретами в вашем коде Terraform》 .
В статье представлены эти способы управления конфиденциальной информацией.
- Переменные среды
- Зашифрованные файлы (AWS KMS)
- Ключевой репозиторий (AWS Secrets Manager)
Первые переменные среды — самый простой, а следующие два имеют определенную стоимость использования, поскольку ключевые требования безопасности не высоки, здесь используется первый простой способ.
Сначала определите переменные.
variable "TUSHARE_API_TOKEN" { description = "Tushare API Token from .env" type = string }
Затем введите эту переменную среды в определение ECS.
data "template_file" "task" { template = "${file("./Infrastructure/tf-fargate/tasks/task_definition.json")}" vars = { project = "${var.project}" aws_region = "${var.aws_region}" ecr_image_uri = "${var.ecr_image_uri}" TUSHARE_API_TOKEN = "${var.TUSHARE_API_TOKEN}" # 注入变量 } }
Наконец, введите эту переменную в контейнер в task_definition.json
Анкет
"environment": [{"name": "TUSHARE_API_TOKEN", "value": "${TUSHARE_API_TOKEN}"}]
Этот ключ должен быть введен каждый раз, когда вносятся изменения, чтобы ключ не просочился в репозиторий кода.
Сделайте сценарий сборки
################ Config ######################## S3_BUCKET ?= invest-alchemy AWS_REGION ?= us-east-1 ENV ?= dev ECR := 745121664662.dkr.ecr.us-east-1.amazonaws.com/invest-alchemy-core-ecr-dev # ECR Repository Example: 123456789012.dkr.ecr.eu-west-1.amazonaws.com/{project_name}-ecr-{env} ################################################ ################ Artifacts Bucket ############## artifacts: @echo "Creation of artifacts bucket" @aws s3 mb s3://$(S3_BUCKET) @aws s3api put-bucket-encryption --bucket $(S3_BUCKET) \ --server-side-encryption-configuration \ '{"Rules": [{"ApplyServerSideEncryptionByDefault": {"SSEAlgorithm": "AES256"}}]}' @aws s3api put-bucket-versioning --bucket $(S3_BUCKET) --versioning-configuration Status=Enabled ################################################ build-docker: @echo "run aws ecr get-login --region $(AWS_REGION) first" @docker build -t $(PROJECT) . @docker tag $(PROJECT) $(ECR) @docker push $(ECR) ################ Terraform ##################### init: @. .env @terraform init \ -backend-config="bucket=$(S3_BUCKET)" \ -backend-config="key=$(PROJECT)/terraform.tfstate" \ ./Infrastructure/tf-fargate/ validate: @terraform validate ./Infrastructure/tf-fargate/ plan: @terraform plan \ -var="env=$(ENV)" \ -var="project=$(PROJECT)" \ -var="description=$(DESCRIPTION)" \ -var="aws_region=$(AWS_REGION)" \ -var="artifacts_bucket=$(S3_BUCKET)" \ ./Infrastructure/tf-fargate/ apply: @terraform apply \ -var="env=$(ENV)" \ -var="project=$(PROJECT)" \ -var="description=$(DESCRIPTION)" \ -compact-warnings ./Infrastructure/tf-fargate/ destroy: @read -p "Are you sure that you want to destroy: '$(PROJECT)-$(ENV)-$(AWS_REGION)'? [yes/N]: " sure && [ $${sure:-N} = 'yes' ] @terraform destroy ./Infrastructure/tf-fargate/
Первый исполнение Сделать докер
Чтобы построить изображение и загрузить его в ECR, затем выполнить Сделать init
Для инициализации Terraform, затем выполнить Сделать проверку и составить план
Чтобы убедиться, что нет проблем с конфигурацией инфраструктуры. Если нет проблем, запустите применить
Чтобы построить реальную инфраструктуру.
Рабочий процесс
Если в системном коде есть изменения, можно повторить следующий процесс.
- Изменить код
Сделайте сборку
применить
Сервис API
Служба API имеет только один API для подписки на темы SNS, который используется, чтобы помочь пользователям подписаться на темы, предоставленные Core Service.
Без сервера Framework
service: api app: invest-alchemy org: madawei2699 provider: name: aws role: arn:aws:iam::745121664662:role/invest-alchemy-lambda runtime: nodejs12.x stage: dev region: us-east-1 functions: subscribe_sns: handler: sns.subscribe_sns memorySize: 128 description: Subscribe sns topic. environment: snsTopicArn: arn:aws:sns:us-east-1:745121664662:trade-signal-topic events: - http: path: subscribe method: post cors: true integration: LAMBDA
Функция indifbibe_sns определена здесь, и мы реализуем ее с помощью JavaScript, исходный код доступен по адресу sns.js , так что мы не рассмотрим это здесь.
Обратите внимание, что код должен определить тему SNS, поэтому он должен иметь разрешение на роль подписки на SNS, что мы указываем в конфигурации без сервера как ARN: AWS: IAM:: 745121664662: Роль/Инвест-Алхей-Ламбда
, который имеет разрешение подписываться на SNS с дополнительными политиками Awslambdabasicexecutionrole
и Amazonsnsfullaccess
Анкет
Код, выполненный в Lambda, может быть импортирован непосредственно в AWS SDK без необходимости его установки, и нет необходимости устанавливать учетные данные AWS, поскольку функция выполняется с разрешениями, прикрепленными к роли напрямую.
Веб —
Веб-интерфейс предоставляет пользователи, доступные для пользователей для подписки на подписку по электронной почте. Vue.js и Nuxt.js используются в этом модуле для создания веб-страниц на стороне сервера. Я в основном ссылаюсь на эту статью AWS | VUE NUXT SSR Анкет
service: web app: invest-alchemy org: madawei2699 provider: name: aws runtime: nodejs12.x stage: ${self:custom.secrets.NODE_ENV} region: us-east-1 environment: NODE_ENV: ${self:custom.secrets.NODE_ENV} functions: nuxt: handler: index.nuxt memorySize: 256 events: - http: path: / method: any cors: true - http: path: /{proxy+} method: any cors: true plugins: - serverless-apigw-binary - serverless-domain-manager - serverless-offline custom: secrets: ${file(secrets.json)} apigwBinary: types: - '*/*' customDomain: domainName: ${self:custom.secrets.DOMAIN} basePath: '' stage: ${self:custom.secrets.NODE_ENV} createRoute53Record: true
Обратите внимание, что шлюз интегрирует пользовательские доменные имена и сертификаты TLS: вам нужно сначала настроить доменное имя в AWS Route53, а затем подать заявку на получение сертификата TLS в диспетчере сертификатов AWS, см. Статью, упомянутую выше для подробного процесса.
Как только заявление на сертификат будет успешным, вы можете выполнить sls create_domain
Чтобы создать информацию DNS для доменного имени.
Наконец -то беги NPM запустить развертывание
развернуть в AWS. Если вы хотите отладить локально, вы можете запустить NPM запустить Start-Server
Анкет
Отладка/логирование
Выберите службу CloudWatch в консоли AWS, чтобы просмотреть группу журналов и найти проблему, анализируя связанные журналы. Если журналы не генерируются, вы также можете увидеть, генерируются ли временные события, просмотрев журналы в Cloudtrail
Анкет
Проблемы, которые требуют внимания
Без сервера затрат
Одним из основных преимуществ без серверов является то, что он оплачивается как вы, что дешевле, чем покупка отдельных VPS для поставленных задач или с низким трафиком. Он также имеет чрезвычайно высокую доступность и упругую масштабируемость, что невозможно при одном VPS.
Чтобы проанализировать стоимость, вы можете использовать платежную услугу AWS. Службы выставления счетов, которые мы используем (за исключением некоторых услуг, которые имеют незначительные выставления счетов по системе, такой как S3/VPC/CloudFront и т. Д.) Включите
- API Gateway: 1 долл. США за 1 миллион запросов.
- ECS Spot Fargate: 0,01289974 за VCPU/час и 0,00141649 долл. США за ГБ памяти/час.
- Lambda: $ 0,0000002083 на 128 млн ОЗУ/100 мс.
- SNS: 2 доллара за 100 000 толчков по электронной почте.
Все вышеперечисленное основано на Восточном регионе США.
Из набора журнала CloudWatch мы знаем, что время выполнения Lambda на запрос составляет 1200 мс за прогон API и веб -службы; Основной сервис работает 3 минуты в день. Стоимость Lambda составляет: 200000 * 1200/100 * 0,000000002083 = 0,5 долл. США; Стоимость ECS составляет 3 * 30/60 * (0.01289974 + 0.00141649) + 0.00141649) = $0.02. API -шлюз стоит 200000/1000000 = 0,2 долл. США; SNS, предполагая, что 1000 человек подписываются на электронную почту, составляет 1000 * 30/100000 = 0,3 долл. США.
Тогда ежемесячная стоимость составляет: 0,5 + 0,02 + 0,2 + 0,3 = 1,02 долл. США. Возьми VULTR VPS
Например, самая дешевая конфигурация с 1 VCPU + 512 МБ конфигурация составляет 2,50 долл. США в месяц, и это не включает стоимость отправки электронных писем.
Холод начинается
Задачи на время фонового времени не чувствительны к временю начала, если вы очень обеспокоены временем начала, может постоянно нагреваться некоторыми задачами с времени, но это также приведет к более высоким затратам. Для получения дополнительной информации, пожалуйста, обратитесь к этой статье 《Решение без сервера Холод начинается с передового инструмента》 。
Цена VPC
Большинство служб VPC не взимаются, кроме VPN/NAT Gateway/Endpoints (шлюз бесплатный/Интерфейс взимается), в то время как конечные точки интерфейса заряжаются очень дорого и должны быть остановлены как можно больше, когда они не нужны, и вам нужно удалить связанные службы AWS, чтобы прекратить зарядку.
Обратите внимание, что конечные точки взимаются на основе доступных зон, поэтому, если конечная точка создается с 6 доступными зонами, она будет заряжена в 6 раз больше.
Чтение материалов
использованная литература
https://rubygarage.org/blog/monolith-soa-microservices-serverless ↩
https://serverless-stack.com/chapters/zh/what-is-serverless.html ↩
Оригинал: «https://dev.to/aws-builders/adventures-in-serverless-application-development-f7g»