Автоматизация развертывания инфраструктуры для приложений без серверов с помощью Terraform
Бессерверные вычисления изменили то, как команды создают и развертывают приложения, предлагая масштабируемость, ценообразование с оплатой за использование и снижение операционных накладных расходов. Однако запуск безсерверных приложений в производстве включает в себя гораздо больше, чем написание функционального кода. Вам нужно обеспечить и управлять десятками облачных ресурсов - шлюзами API, очередями, базами данных, ролями IAM, конфигурациями журналов и сетевыми компонентами - все из которых должны быть последовательно воспроизведены в средах разработки, постановки и производства. Ручные клики-опсы в консоли быстро становятся склонными к ошибкам и немасштабируемыми. Инфраструктура как инструменты кода (IaC) как Terraform решает эту проблему, позволяя вам определять каждую часть инфраструктуры в контролируемых версиями, читаемых человеком файлах конфигурации. В этой статье рассматривается, как использовать Terraform для автоматизации развертывания инфраструктуры для приложений без серверов, предоставляя конкретные примеры, лучшие практики и стратегии для управления сложностью в реальном мире.
Что такое терраформа?
Terraform - это инструмент IaC с открытым исходным кодом, созданный HashiCorp, который позволяет вам предоставлять и управлять инфраструктурой через несколько облачных провайдеров, используя декларативный язык конфигурации, известный как HCL (язык конфигурации HashiCorp). Вместо написания императивных скриптов, которые выполняют пошаговые команды, вы объявляете желаемое состояние своей инфраструктуры - какие ресурсы вы хотите, их свойства и как они относятся друг к другу - и Terraform определяет необходимые действия для достижения этого состояния.
В основе Terraform лежит план выполнения. Перед внесением каких-либо изменений Terraform сравнивает вашу конфигурацию с текущим состоянием инфраструктуры и производит подробный план того, что будет создано, обновлено или уничтожено. Этот план может быть пересмотрен (и, в трубопроводах CI/CD, одобрен) до его применения, давая вам безопасный цикл обратной связи, который предотвращает непреднамеренные изменения. Terraform также отслеживает ресурсы в файле состояния, который отображает конфигурацию на реальные облачные объекты. Этот файл состояния необходим для Terraform, чтобы знать, что он управляет и обнаруживать дрейф.
Terraform поддерживает сотни провайдеров, включая все основные облачные платформы (AWS, Azure, Google Cloud), а также сервисы SaaS, такие как Cloudflare, Datadog и GitHub. Для бессерверных приложений на AWS вы обычно используете поставщика AWS для определения функций Lambda, API Gateway REST API, таблиц DynamoDB, очередей SQS, потоков Kinesis, пулов пользователей Cognito и каждой политики IAM, которая связывает их вместе.
Почему бессерверные приложения нуждаются в инфраструктуре
Безсерверные приложения состоят из множества небольших, специально построенных сервисов, которые взаимодействуют асинхронно или синхронно. Типичная архитектура, управляемая событиями, может включать API Gateway, который принимает HTTP-запросы, функцию Lambda для их обработки, таблицу DynamoDB для хранения результатов и очередь SQS для буферной работы для второй функции Lambda. Создание этих ресурсов вручную утомительно и подвержено ошибкам, особенно по мере того, как ваша архитектура становится включать десятки функций и вспомогательных служб. Проблемы ручного управления включают:
- Непоследовательность: Различные среды (дев, постановка, пад) неизбежно расходятся при создании вручную.
- Никакой истории версий: Кто изменил пропускную способность DynamoDB? Когда? Почему? Без кода вы теряете возможность аудита.
- Кошмар отдыха: После катастрофы вам нужно будет перенастроить все с нуля, надеясь, что вы помните каждую настройку.
- Время впустую: Нажатие на консоль для каждого ресурса занимает часы, которые должны идти в логику приложения.
IaC решает эти проблемы, превращая инфраструктуру в программное обеспечение. Каждое изменение - это запрос на вытягивание. Каждая среда - это повторяемое развертывание. И вся ваша архитектура может быть снесена и перестроена за считанные минуты. Для приложений без серверов, где ценностное предложение - скорость и маневренность, IaC не является опциональным - это основа надежного производственного рабочего процесса.
Основные преимущества использования Terraform для Serverless
Хотя любой инструмент IaC может использоваться для управления безсерверной инфраструктурой, Terraform предлагает различные преимущества, которые хорошо согласуются с потребностями команд без сервера.
Полная автоматизация жизненного цикла
Terraform обрабатывает не только резервирование, но и обновление и уничтожение ресурсов. Когда вам нужно изменить размер памяти функции Lambda или атрибут TTL таблицы DynamoDB, вы просто обновляете конфигурацию и запускаете . Когда вы закончите с ресурсом, тот же код, который его создал, очистит его. Это особенно ценно в эфемерных средах — например, в предварительном просмотре развертываний для каждого запроса на вытягивание — где вы можете раскрутить полный стек без сервера и позже уничтожить его автоматически.
Декларативное управление зависимостью
Безсерверные архитектуры имеют сложные зависимости. Функция Lambda зависит от роли IAM, которая может зависеть от политики, которая может зависеть от таблицы DynamoDB ARN. Terraform строит график ресурсов из ваших деклараций и автоматически определяет правильный порядок операций. Он создает ресурсы до того, как они будут упомянуты, и ждет, когда зависимости станут доступными. Это освобождает вас от написания сценариев, подверженных ошибкам, которые последовательность командует вручную.
Многоэкологическая согласованность
Используя рабочие пространства Terraform или структуры каталогов, вы можете повторно использовать одну и ту же конфигурацию в нескольких средах с различными значениями переменных. Конфигурация функции Lambda может быть одинаковой для разработчиков, постановки и производства, за исключением переменных, специфичных для окружающей среды, таких как имена таблиц, уровни журналов или настройки VPC. Это гарантирует, что производственная инфраструктура - это именно то, что было протестировано в постановке.
Гранулярный государственный контроль
Управление состоянием является критической проблемой. Terraform позволяет хранить состояние удаленно в бэкэндах, таких как S3 (с блокировкой DynamoDB), Terraform Cloud или HashiCorp Consul. Удалённое состояние позволяет совместно работать с командой: несколько инженеров могут безопасно применять изменения в одной и той же инфраструктуре без конфликтов. Для команд без серверов, которые постоянно развертывают надежное управление состоянием, необходимо.
Начало работы с Terraform для бессерверного развертывания
Давайте пройдемся по настройке полного бессерверного приложения с использованием Terraform на AWS. Наш пример представит простой REST API через API Gateway, который запускает функцию Lambda, которая записывает данные в таблицу DynamoDB. Мы также рассмотрим необходимые разрешения IAM.
Предпосылки
- Установка Terraform (] Download)
- Учетная запись AWS с настроенными учетными данными (через переменные среды или )
- Node.js установлен (для компиляции кода Lambda)
Структура проекта
serverless-terraform/
├── main.tf
├── variables.tf
├── outputs.tf
├── lambda/
│ └── index.js
└── terraform.tfvars
1.Определить поставщика терраформ
В настройте поставщика AWS и укажите регион:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
backend "s3" {
bucket = "my-terraform-state-bucket"
key = "serverless-app/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "terraform-locks"
}
}
provider "aws" {
region = var.aws_region
}
2.Создать роль IAM для Lambda
data "aws_iam_policy_document" "lambda_assume_role" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["lambda.amazonaws.com"]
}
}
}
resource "aws_iam_role" "lambda_exec" {
name = "serverless-lambda-role"
assume_role_policy = data.aws_iam_policy_document.lambda_assume_role.json
}
resource "aws_iam_policy" "lambda_dynamodb_policy" {
name = "lambda-dynamodb-policy"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = ["dynamodb:PutItem", "dynamodb:GetItem", "dynamodb:UpdateItem"]
Effect = "Allow"
Resource = aws_dynamodb_table.items.arn
},
{
Action = ["logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents"]
Effect = "Allow"
Resource = "*"
}
]
})
}
resource "aws_iam_role_policy_attachment" "lambda_policy_attach" {
role = aws_iam_role.lambda_exec.name
policy_arn = aws_iam_policy.lambda_dynamodb_policy.arn
}
3. Развернуть таблицу DynamoDB
resource "aws_dynamodb_table" "items" {
name = "items"
billing_mode = "PAY_PER_REQUEST"
hash_key = "id"
attribute {
name = "id"
type = "S"
}
tags = {
Environment = var.environment
}
}
4.Упаковка и развертывание функции Ламбда
Во-первых, создайте простую функцию Lambda в :
exports.handler = async (event) => {
const AWS = require('aws-sdk');
const dynamodb = new AWS.DynamoDB.DocumentClient();
const id = event.pathParameters.id;
const params = {
TableName: process.env.TABLE_NAME,
Item: { id, timestamp: Date.now(), data: event.body }
};
await dynamodb.put(params).promise();
return {
statusCode: 200,
body: JSON.stringify({ id })
};
};
Затем в вашей конфигурации Terraform обратитесь к коду функции:
data "archive_file" "lambda_zip" {
type = "zip"
source_dir = "${path.module}/lambda"
output_path = "${path.module}/lambda_function_payload.zip"
}
resource "aws_lambda_function" "api_handler" {
filename = data.archive_file.lambda_zip.output_path
function_name = "serverless-api-handler"
role = aws_iam_role.lambda_exec.arn
handler = "index.handler"
runtime = "nodejs18.x"
source_code_hash = data.archive_file.lambda_zip.output_base64sha256
environment {
variables = {
TABLE_NAME = aws_dynamodb_table.items.name
}
}
}
5.Разоблачить Lambda через API Gateway
resource "aws_api_gateway_rest_api" "api" {
name = "serverless-api"
}
resource "aws_api_gateway_resource" "items" {
rest_api_id = aws_api_gateway_rest_api.api.id
parent_id = aws_api_gateway_rest_api.api.root_resource_id
path_part = "items"
}
resource "aws_api_gateway_resource" "item" {
rest_api_id = aws_api_gateway_rest_api.api.id
parent_id = aws_api_gateway_resource.items.id
path_part = "{id}"
}
resource "aws_api_gateway_method" "put_item" {
rest_api_id = aws_api_gateway_rest_api.api.id
resource_id = aws_api_gateway_resource.item.id
http_method = "PUT"
authorization = "NONE"
}
resource "aws_api_gateway_integration" "lambda" {
rest_api_id = aws_api_gateway_rest_api.api.id
resource_id = aws_api_gateway_resource.item.id
http_method = aws_api_gateway_method.put_item.http_method
integration_http_method = "POST"
type = "AWS_PROXY"
uri = aws_lambda_function.api_handler.invoke_arn
}
resource "aws_lambda_permission" "apigw" {
statement_id = "AllowExecutionFromAPIGateway"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.api_handler.function_name
principal = "apigateway.amazonaws.com"
source_arn = "${aws_api_gateway_rest_api.api.execution_arn}/*/*"
}
resource "aws_api_gateway_deployment" "prod" {
depends_on = [aws_api_gateway_integration.lambda]
rest_api_id = aws_api_gateway_rest_api.api.id
stage_name = "prod"
}
6. Определение результатов
, выставить конечную точку API:
output "api_endpoint" {
value = "${aws_api_gateway_deployment.prod.invoke_url}/items/"
}
7. Применяется
terraform init
terraform plan
terraform apply
После подачи заявки вы можете отправить запрос PUT в конечную точку с помощью корпуса JSON. Функция Lambda записывает данные в DynamoDB. Чтобы снести весь стек, запустите .
Структурирование Terraform Projects для Serverless
Реальные безсерверные приложения слишком велики для одного файла конфигурации. Принятие масштабируемой структуры проекта имеет решающее значение. Вот общие шаблоны:
Используйте модули для инкапсуляции многоразовых компонентов
Модули Terraform позволяют группировать ресурсы в логические единицы. Для бессерверных можно создавать модули для:
- Базовый функциональный модуль Lambda (с функцией IAM, базовыми разрешениями CloudWatch и дополнительной конфигурацией VPC)
- Модуль интеграции API Gateway + Lambda
- DynamoDB модуль таблицы со стандартизированными атрибутами и автомасштабированием
- Модуль очереди SQS с очередями из мертвой буквы
Модули могут храниться в вашем собственном репозитории Git или публиковаться в реестре Terraform. Они упрощают конфигурации, специфичные для окружающей среды: вы инстанцируете модуль с различными переменными в каждой среде.
Отдельные среды с директориями или рабочими пространствами
Существует два общих подхода к управлению окружающей средой:
- Директура по среде: Создавайте папки , , , каждая со своей и, возможно, .
- Terraform Workspaces: Используйте встроенную функцию рабочего пространства для создания именованных экземпляров одной и той же конфигурации. Рабочие пространства легче, но могут сбивать с толку при работе с несколькими командами.
Для большинства команд без серверов подход к каталогам более ясен, поскольку он делает границы среды явными в кодовой базе.
Удаленное состояние с блокировкой
Никогда не храните состояние локально для командных проектов. Используйте бэкэнд S3 с блокировкой DynamoDB. В корзине S3 хранится файл состояния, а DynamoDB обеспечивает блокировки согласованности, так что за один раз запускается только один . Пример конфигурации бэкэнда был показан ранее. Убедитесь, что ведро S3 и таблица DynamoDB созданы за пределами Terraform (загрузите их отдельным скриптом или используйте встроенное управление состоянием Terraform Cloud).
Управляйте секретами безопасно
Безсерверные приложения часто требуют секретов, таких как пароли базы данных, ключи API или токены подписи JWT. Никогда не кодируйте их в конфигурациях Terraform. Вместо этого используйте:
- AWS Secrets Manager или SSM Parameter Store, ссылаясь на источники данных или
- Vault-провайдер для получения динамических секретов
- Зашифрованные переменные файлы, относящиеся к среде (например, , с такими инструментами, как )
Лучшие практики автоматизации инфраструктуры с помощью Terraform
Чтобы максимизировать надежность и скорость команды, следуйте этим проверенным методам:
Версия Control Everything
Все конфигурации Terraform, включая модули, должны храниться в Git с содержательными сообщениями о совершении. Выпуски тегов и использование веток для изменений. Это обеспечивает полный контрольный след того, кто что и когда изменил.
Всегда планируйте и пересматривайте
В локальной разработке всегда запускайте до . В CI/CD требуется ручной шаг утверждения для развертывания производства. Terraform Cloud и Atlantis являются популярными инструментами, которые интегрируют рабочие процессы планирования/приложения в запросы на вытягивание.
Внедрение CI/CD для инфраструктуры
Относитесь к изменениям инфраструктуры, таким как изменения кода. Используйте трубопровод, который выполняет и на запросах на вытягивание, затем выполняет , а после слияния — запускает . Для безсерверных устройств вы можете запустить интеграционные тесты после подачи заявки, чтобы убедиться, что конечные точки API реагируют правильно.
для обнаружения дрейфа
Даже с CI/CD кто-то может вручную модифицировать ресурс через консоль. Регулярный график работает (например, ночью) для обнаружения дрейфа и оповещения команды. Инструменты, такие как обнаружение дрейфа Terraform Cloud, могут автоматизировать это.
Проверьте свои конфигурации Terraform
Код инфраструктуры юнит-тестирования возможен с помощью таких инструментов, как Terratest, библиотека Go, которая раскручивает реальные облачные ресурсы, проверяет их поведение и срывает их. Для безсерверных устройств вы можете развертывать стека в изолированных тестовых учетных записях, запускать HTTP-тесты против API и проверять содержимое DynamoDB. В то время как написание тестов Terratest является инвестицией, она рано улавливает тонкие ошибки конфигурации.
Использование политики в качестве кода
Определить правила соблюдения в масштабах всей организации с использованием HashiCorp Sentinel (облако) или агента по открытой политике. Например, потребовать, чтобы все функции Lambda включали отслеживание рентгеновских лучей или предотвращали публичные таблицы DynamoDB. Эти политики применяются в плановое время, что делает управление безопасностью и расходами систематическим.
Общие вызовы и решения
Государственная блокировка файлов и конфликты
Когда несколько членов команды работают одновременно, может произойти коррупция в государстве. Решение: всегда используйте бэкэнд, который поддерживает блокировку (S3 + DynamoDB) и никогда не запускайте непосредственно из параллельных ветвей. Используйте трубопроводы CI / CD для сериализации.
Обработка большого количества функций лямбды
Управление 50+ функциями Lambda в одной конфигурации становится громоздким. Решение: использовать или с картой определений функций. Еще лучше организовать функции в отдельные конфигурации Terraform, которые разделяют источники данных состояния. Например, центральная «основная» конфигурация экспортирует выходы (названия таблиц DynamoDB, URL-адреса очереди SQS), которые импортируют конфигурации функций вниз по потоку через .
Заказ зависимостей в сложных архитектурах
Хотя Terraform обрабатывает большинство зависимостей автоматически, круговые зависимости (например, две службы, которые ссылаются друг на друга ARN) могут вызвать проблемы. Решение: разорвать цикл, введя третий ресурс (например, центральную тему SNS) или использовать явные блоки . Для бессерверных, общая схема заключается в создании ролей и политик IAM отдельно от функций, чтобы избежать циклов.
Внесение изменений в код Lambda
Terraform предназначен для инфраструктуры, а не для постоянного развертывания кода приложения. Нажимание новых версий Lambda путем повторного применения Terraform каждый раз медленно и не идеально подходит для быстрого итерации кода. Решение: отделить развертывание инфраструктуры (созданное один раз в среду) от развертывания кода. Используйте трубопроводы CI / CD, которые обновляют код функции Lambda через AWS SDK или инструменты, такие как Serverless Framework, в то время как Terraform управляет окружающими ресурсами. Альтернативно, используйте источник данных Terraform с последовательным хэш-источником, чтобы только изменения в файле кода запускали новое развертывание.
Заключение
Автоматизация развертывания инфраструктуры с помощью Terraform обеспечивает ту же строгость для безсерверной инфраструктуры, которую команды программного обеспечения применяют к коду приложения. Определяя каждый ресурс в файлах HCL, контролируемых версиями, вы получаете повторяемые развертывания, безопасное управление изменениями и полный контроль аудита. Хорошо структурированный проект Terraform с модулями, удаленным состоянием и интеграцией CI / CD позволяет командам управлять сотнями функций Lambda, конечными точками API и хранилищами данных, не погружаясь во время ручного обеспечения или беспокоясь о дрейфе среды.
Поскольку безсерверные архитектуры продолжают расти в сложности - с управляемыми событиями рабочими процессами, ступенчатыми функциями и глобальной инфраструктурой, распределенной по нескольким регионам - важность надежного IaC только возрастает. Начиная с шаблонов и примеров в этой статье, вы можете построить основу, которая масштабируется с вашим приложением и вашей организацией. Авансовые инвестиции в автоматизацию вашей безсерверной инфраструктуры многократно окупаются за счет снижения ошибок, более быстрого развертывания и повышения уверенности в том, что ваша производственная среда соответствует тому, что вы протестировали.