Поиск по сайту:

Как автоматизировать безопасное развертывание Lambda из Git


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

Как работает CI/CD для Lambda

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

CodePipeline запускается автоматически всякий раз, когда обнаруживает изменения в системе управления версиями, и отправляет изменения в CodeBuild (или Jenkins) для сборки. Этот шаг является необязательным, и вы можете не использовать его для Lambda, но если вы используете что-то вроде TypeScript, вам понадобится этот этап. После сборки изменения передаются в CodeDeploy, который занимается развертыванием.

CodeDeploy автоматически обновит ваши функции Lambda и отправит новую версию. Чтобы сделать процесс развертывания более плавным, он может постепенно перемещать трафик с помощью псевдонима, пока 100% трафика не будет направлено на новую функцию.

Для фактического развертывания CodeDeploy использует бессерверную модель приложений AWS (SAM). SAM — это расширение CloudFormation, сервиса «инфраструктура как код». По сути, это шаблон понятного человеку языка сериализации данных (YAML), который используется для обработки всей конфигурации, связанной с развертыванием функций Lambda и их предварительных требований, и является жизненно важной частью возможности развертывания с использованием только кода.

Настройка системы управления версиями

Этот шаг довольно прост. Вы захотите создать новый каталог проекта для хранения всего вашего кода и инициализировать его с помощью Git. Шаблон SAM будет помещен в корень этого каталога с именем template.yml. Каждая функция будет находиться в своей папке, корнем которой будет index.js. Это четко разделяет все и упрощает управление

ProjectDirectory
  |--template.yml
  |--Function
  |   |--index.js
  |--AnotherFunction
      |--index.js

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

Написание шаблона SAM

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

Базовый шаблон выглядит примерно так:

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: An AWS Serverless Specification template describing your function
Resources:
  HelloWorld:
    Type: AWS::Serverless::Function
    Properties:
      Handler:  HelloWorld/index.handler
      Runtime: nodejs8.10

Это регистрирует один ресурс, функцию Lambda, которая работает на NodeJS и имеет обработчик в HelloWorld/index.js.

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

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: An AWS Serverless Specification template describing your function
Resources:
  HelloWorld:
    Type: AWS::Serverless::Function
    Properties:
      Handler:  HelloWorld/index.handler
      Runtime: nodejs8.10
      Events:
        HelloWorldApi:
          Type: Api
          Properties:
            Path: /helloworld
            Method: GET
  HelloWorldPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName:
        Fn::GetAtt:
        - HelloWorld
        - Arn
      Principal: apigateway.amazonaws.com
      SourceArn:
        Fn::Sub: arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:*/*/*/*

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

Получив рабочий шаблон, вы можете протестировать развертывание, установив интерфейс командной строки SAM:

pip install aws-sam-cli

Затем вы упакуете свой проект и сохраните артефакты в корзине S3:

sam package 
--template-file template.yml 
--output-template-file package.yml 
--s3-bucket bucket-name

И вы вручную запустите развертывание:

sam deploy 
--template-file package.yml 
--stack-name sam-hello-world 
--capabilities CAPABILITY_IAM

Если все заработало правильно, вы должны увидеть новый стек CloudFormation и приложение на Lambda с вашими функциями.

Упаковка и развертывание проекта с помощью CodePipeline

Этот этап необязателен, даже если вы не работаете с компилируемым языком. Используя шаблон SAM, CodeBuild будет использоваться здесь для обработки упаковки проекта во что-то, что можно очень легко развернуть с помощью CodeDeploy. При желании перед упаковкой можно запустить другие команды, например npm run build и npm install.

Во-первых, вам понадобится исполнительная роль, способная обрабатывать обновления CloudFormation. Откройте консоль управления IAM, чтобы добавить новую роль. Выберите CloudFormation в качестве ресурса, который будет использовать эту роль, а затем прикрепите политику разрешений AWSLambdaExecute.

Сохраните роль, откройте ее и прикрепите следующую встроенную политику:

{
    "Statement": [
        {
            "Action": [
                "apigateway:*",
                "codedeploy:*",
                "lambda:*",
                "cloudformation:CreateChangeSet",
                "iam:GetRole",
                "iam:CreateRole",
                "iam:DeleteRole",
                "iam:PutRolePolicy",
                "iam:AttachRolePolicy",
                "iam:DeleteRolePolicy",
                "iam:DetachRolePolicy",
                "iam:PassRole",
                "s3:GetObject",
                "s3:GetObjectVersion",
                "s3:GetBucketVersioning"
            ],
            "Resource": "*",
            "Effect": "Allow"
        }
    ],
    "Version": "2012-10-17"
}

Создайте новый конвейер из консоли CodePipeline. Выберите настройки по умолчанию для создания новой сервисной роли. Это будет настроено автоматически.

Для этапа управления версиями выберите тип системы управления версиями, репозиторий и ветку выпуска.

На этапе сборки вам нужно создать новый проект в CodeBuild. Конфигурация по умолчанию подходит, просто выберите Amazon Linux 2 в качестве операционной системы для сборки и выберите стандартную среду выполнения и стандартный образ.

Главное, что вам понадобится для codePipeline, — это ваш файл buildspec.yml, расположенный в корне каталога вашего проекта. Это настраивает CodeBuild с командами, которые необходимо запустить. Следующая конфигурация представляет собой пример, который устанавливает TypeScript, все пакеты NPM, запускает npm run build, а затем упаковывает все для CloudFormation.

version: 0.2
phases:
    install:
        runtime-versions:
            nodejs: 10
        commands:
            - npm install -g typescript
    build:
        commands:
            - echo Build started on `date`
            - npm install time
            - npm run build
            - export BUCKET=typescript-lambda
            - aws cloudformation package --template-file template.yml --s3-bucket $BUCKET --output-template-file outputtemplate.yml
artifacts:
    type: zip
    files:
        - template.yml
        - outputtemplate.yml

Возможно, вам придется изменить это в соответствии с вашим проектом.

Как только это будет сделано, вы можете настроить последний этап. Однако вместо того, чтобы использовать CodeDeploy, мы будем использовать CloudFormation для непосредственного обновления вещей, так как вся упаковка в любом случае происходила на этапе сборки. Выберите «CloudFormation» в качестве поставщика развертывания и установите режим действия «Создать или заменить набор изменений». Введите новое имя и измените имя набора.

Для шаблона выберите «BuildArtifact» и введите outputtemplate.yml из предыдущего шага. Добавьте «Capability IAM» к возможностям и выберите роль службы, которую вы создали вручную ранее.

Нажмите «Создать», и ваш конвейер должен работать без ошибок. Однако этап CloudFormation создает набор изменений, что похоже на предварительный просмотр изменений. Чтобы фактически развернуть изменения, нам нужно выполнить набор изменений.

Нажмите «Изменить» на созданном конвейере. В разделе Развернуть нажмите Изменить и нажмите Добавить группу действий после уже созданного действия. Если вы создадите новое действие перед этим, оно не сработает.

Выберите «CloudFormation» в качестве провайдера. Выберите «BuildArtifact» в качестве входного артефакта. Для режима действия и имени набора изменений введите те же значения, которые вы создали для первого действия развертывания.

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

Если вы получаете ошибки, их довольно легко отследить, так как вы можете нажать «Подробнее» рядом с сообщением об ошибке в CodePipeline. Скорее всего, это либо неудачная сборка, либо неполный шаблон SAM, либо недостаточные разрешения для CodeBuild или CloudFormation.

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