Настройка CI/CD для AWS Lambda с CodePipeline и SAM CLI
Приветствую! Сегодня я расскажу вам, как настроить CI/CD для AWS Lambda с использованием AWS CodePipeline и AWS SAM CLI. Если вы хотите автоматизировать процесс деплоя серверлесс-приложений и избавиться от рутины, то эта статья для вас.
Что нам понадобится
Перед началом работы убедитесь, что у вас есть:
AWS Account: доступ к облачным сервисам AWS.
AWS CLI: инструмент командной строки для взаимодействия с AWS.
AWS SAM CLI: утилита для разработки и деплоя серверлесс-приложений.
AWS CodePipeline: сервис для создания CI/CD пайплайнов.
AWS CodeBuild: для сборки и тестирования вашего кода.
GitHub или AWS CodeCommit: репозиторий для хранения исходного кода.
S3 Bucket: хранилище для артефактов сборки.
Настройка окружения
После всех установок необходимо настроить AWS CLI, чтобы он мог взаимодействовать с вашим аккаунтом AWS:
aws configure
Вам будет предложено ввести:
AWS Access Key ID и AWS Secret Access Key: их можно получить в AWS Console в разделе IAM → Users → [Ваш пользователь] → Security credentials.
Default region name: указываем регион, в котором будут развёрнуты ресурсы (например,
us-east-1
).Default output format: обычно ставят
json
.
Создание серверлесс-приложения
Теперь создадим простое серверлесс-приложение, которое будем деплоить.
Запустим команду инициализации:
sam init --runtime python3.8 --name my-lambda-app --app-template hello-world
--runtime python3.8
: выбираем язык и версию.--name my-lambda-app
: имя нашего проекта.--app-template hello-world
: используем шаблон «Hello World».
В результате появится структура проекта с базовой Lambda-функцией.
Дерево проекта будет выглядеть так:
my-lambda-app/
├── README.md
├── events/
│ └── event.json
├── hello_world/
│ ├── app.py
│ └── requirements.txt
├── template.yaml
└── tests/
└── unit/
└── test_handler.py
app.py
: содержит код Lambda-функции.template.yaml
: описывает инфраструктуру и конфигурацию для AWS.tests/
: содержит тесты для нашей функции.
Файл template.yaml
является шаблоном CloudFormation и определяет ресурсы, которые будут созданы в AWS. Папка tests/
содержит тесты.
В файле hello_world/app.py
находится простой обработчик:
import json
def lambda_handler(event, context):
message = "Hello, World!"
return {
'statusCode': 200,
'body': json.dumps({'message': message})
}
Эта функция возвращает простой JSON с сообщением.
Локальное тестирование функции
Прежде чем деплоить функцию, убедимся, что она работает локально.
Переходим в корневой каталог проекта и установим необходимые зависимости:
pip install -r hello_world/requirements.txt
Если requirements.txt
пуст, значит дополнительных пакетов не требуется.
SAM CLI позволяет запускать функцию локально, имитируя API Gateway:
sam local start-api
Вы увидите сообщение, что сервер запущен на http://127.0.0.1:3000/hello
.
Открываем новый терминал и выполняем запрос:
curl http://127.0.0.1:3000/hello
Вы должны получить ответ:
{"message": "Hello, World!"}
Это означает, что функция работает корректно и готова к деплою.
Подготовка к деплою
Перед тем как настроить CI/CD, нужно подготовить инфраструктуру для деплоя.
AWS SAM использует S3 для хранения артефактов сборки. Создадим бакет:
aws s3 mb s3://my-lambda-artifacts-bucket
Важно заменить my-lambda-artifacts-bucket
на уникальное имя бакета.
S3 бакет необходим для хранения упакованного кода функции, который затем используется при деплое с помощью CloudFormation.
Соберём приложение и подготовим его к деплою:
sam package \
--output-template-file packaged.yaml \
--s3-bucket my-lambda-artifacts-bucket
sam package
: упаковывает ваш код и загружает его в S3, обновляя ссылки в шаблоне.--output-template-file
: файл, в который будет записан обновлённый шаблон CloudFormation.--s3-bucket
: бакет, куда будут загружены артефакты.
Эта команда подготавливает всё необходимое для деплоя и генерирует обновлённый шаблон, который указывает на артефакты в S3.
Можно проверить деплой вручную, чтобы убедиться, что всё работает:
sam deploy \
--template-file packaged.yaml \
--stack-name my-lambda-stack \
--capabilities CAPABILITY_IAM
sam deploy
: выполняет деплой вашего приложения в AWS.--stack-name
: имя стека CloudFormation, который будет создан или обновлён.--capabilities
: подтверждаем создание IAM ролей, необходимых для работы функции.
После успешного деплоя вы получите URL для вызова функции. Попробуйте вызвать её и убедитесь, что она работает как ожидается.
Настройка репозитория
Для автоматизации нужен репозиторий, где будет храниться код.
В корне проекта инициализируем репозиторий:
git init
git add .
git commit -m "Initial commit"
Это позволяет отслеживать изменения в коде и интегрировать систему контроля версий с CI/CD пайплайном.
Создадим новый репозиторий на GitHub и свяжем его с локальным:
git remote add origin https://github.com/yourusername/my-lambda-app.git
git push -u origin master
Теперь код доступен в удалённом репозитории, и можно настроить автоматизацию на основе изменений в нём.
Настройка CodeBuild
CodeBuild будет отвечать за сборку и тестирование приложения.
Создадим файл buildspec.yml
в корне проекта со следующим содержанием:
version: 0.2
phases:
install:
runtime-versions:
python: 3.8
commands:
- pip install aws-sam-cli
pre_build:
commands:
- pip install -r hello_world/requirements.txt
- pip install -r tests/requirements.txt
- python -m pytest tests/unit -v
- sam validate --template template.yaml
build:
commands:
- sam build
post_build:
commands:
- sam package --s3-bucket my-lambda-artifacts-bucket --output-template-file packaged.yaml
artifacts:
files:
- packaged.yaml
В файле tests/unit/test_handler.py
добавляем:
import json
from hello_world import app
def test_lambda_handler():
event = {}
context = {}
response = app.lambda_handler(event, context)
data = json.loads(response['body'])
assert response['statusCode'] == 200
assert data['message'] == 'Hello, World!'
Это простой тест, который проверяет корректность ответа функции.
Создадим файл tests/requirements.txt
и добавим:
pytest
Это необходимо для установки pytest
на этапе сборки.
Настройка CodePipeline
Теперь настроим сам пайплайн, который будет автоматизировать процесс от коммита до деплоя.
Переходим в консоль AWS CodePipeline и создаём новый пайплайн.
Шаги настройки:
Pipeline settings:
Add source stage:
Source provider: GitHub.
Connect to GitHub: предоставляем доступ AWS к вашему репозиторию.
Repository: выбираем репозиторий
my-lambda-app
.Branch:
master
.
Add build stage:
Add deploy stage:
Deploy provider: AWS CloudFormation.
Action mode: Create or update a stack.
Stack name:
my-lambda-stack
.Template:
packaged.yaml
.Capabilities: отметьте
CAPABILITY_IAM
.
После настройки пайплайна сохраняем его.
Сделаем изменение в коде, например, обновим сообщение в функции:
def lambda_handler(event, context):
message = "Hello, AWS Lambda!"
return {
'statusCode': 200,
'body': json.dumps({'message': message})
}
Закоммитим и запушим изменения:
git add .
git commit -m "Updated message"
git push origin master
Переходим в CodePipeline и убеждаемся, что пайплайн автоматически запустился и прошёл все этапы.
Управление конфигурацией и секретами
Для управления настройками и секретами рекомендуется использовать переменные окружения и сервисы AWS.
Обновим template.yaml
, чтобы передавать переменные окружения в функции:
Globals:
Function:
Environment:
Variables:
STAGE: !Ref Stage
Parameters:
Stage:
Type: String
Default: dev
В коде функции можно получить переменную STAGE
:
import os
def lambda_handler(event, context):
stage = os.environ.get('STAGE', 'dev')
message = f"Hello from {stage} stage!"
return {
'statusCode': 200,
'body': json.dumps({'message': message})
}
Теперь используем AWS Systems Manager Parameter Store для хранения секретов и конфиденциальных данных.
aws ssm put-parameter --name "/myapp/secret" --value "mysecretvalue" --type SecureString
Доступ к параметру в коде:
import boto3
def get_secret():
ssm = boto3.client('ssm')
parameter = ssm.get_parameter(Name='/myapp/secret', WithDecryption=True)
return parameter['Parameter']['Value']
Роль Lambda должна иметь права на ssm:GetParameter
. Это можно сделать, добавив соответствующую политику к роли функции.
Мониторинг и логирование
Важно иметь возможность отслеживать работу функции и быстро находить ошибки.
В начале файла app.py
добавим:
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
Внутри функции используем:
def lambda_handler(event, context):
logger.info('Received event: %s', event)
# Основная логика
Это позволит записывать логи, которые можно просматривать в AWS CloudWatch.
Обновим template.yaml
, чтобы включить X-Ray:
Globals:
Function:
Tracing: Active
AWS X-Ray позволяет собирать данные о производительности функции, создавать трассировки и визуализировать поток данных через приложение.
Обработка ошибок
Оборачивайте важные части кода в блоки try-except
для отлова исключений:
Globals:
Function:
Environment:
Variables:
STAGE: !Ref Stage
Parameters:
Stage:
Type: String
Default: dev
Это позволит записать ошибку в логи и, при необходимости, повторно вызвать функцию.
В template.yaml
добавьте параметры повторного вызова:
import os
def lambda_handler(event, context):
stage = os.environ.get('STAGE', 'dev')
message = f"Hello from {stage} stage!"
return {
'statusCode': 200,
'body': json.dumps({'message': message})
}
Это позволит автоматом повторять выполнение функции в случае ошибок.
Заключение
Если у вас возникли вопросы или вы хотите поделиться своим опытом, пишите в комментариях.
Сегодня в 20:00 пройдет открытый урок «Mock интервью на позицию Cloud Solution Architect» — поговорим, как уверенно пройти все этапы интервью. Если актуально — записывайтесь на урок на странице курса «Cloud Solution Architecture».