3/5 - (2 голоса)

Старший инженер Bolt, поделился возможностью использовать инфраструктуру как код с AWS CDK на примере веб игры.

Образец архитектуры

Архитектура, изображенная ниже, достаточно точно представляет ресурсы, использованные для проекта веб-версию хорошо знакомой игры Snake (изображение 1):

Ключевые особенности:

  1. Это бессерверная архитектура: отсутствуют зарезервированные вычислительные мощности и отсутствуют расходы «вперед».
  2. Amazon API Gateway служит единственной точкой входа в приложение.
  3. Хранилище S3 используется для размещения статического веб-сайта и медиа-контента (в нашем случае самой игры).
  4. AWS Lambda используется как среда выполнения API.
  5. Dynamo DB сохраняет состояние системы (в данном случае это счет в игре).
  6. Ради простоты примера я должен обойти интеграцию с Cognito, которая в реальном решении была использована для идентификации пользователей.

Согласно схеме выше, репозиторий содержит три проекта:

/aws-snake 
/snake-API # node/express API 
/snake-client # игра на обычном JavaScript 
/snake-iac # проект AWS CDK

Оригинальный коммерческий проект построен на .NET Core, но для текущего образца я использую TypeScript по трем причинам:

  1. TypeScript выглядит чем-то средним между Java/C# и JavaScript.
  2. JavaScript-подобный синтаксис понимают почти повсеместно.
  3. Чтобы доказать, что CDK действительно работает независимо от выбранного языка программирования.

Начало работы с CDK

Старт работы с AWS CKD достаточно прост, вы можете либо следовать официальным инструкциям с начала работы, либо выполнить следующие шаги:

    • Создать аккаунт AWS .
    • Создать ключ доступа AWS .
    • Установить AWS CLI .
curl "https://awscli.amazonaws.com/AWSCLIV2.pkg" -o "AWSCLIV2.pkg"
sudo installer -pkg AWSCLIV2.pkg -target /
  • Конфигурировать AWS CLI, используя предварительно созданный ключ
    aws configure
  • Установить Node LTS .
    brew  install  node  # mac  
    sudo apt- get  install  nodejs  # debian
  • Установите AWS CDK toolkit.
    npm install -g aws-cdk
  • Установите целевую среду выполнения (в нашем случае TypeScript) .
    npm install -g typescript
  • Создать пустой CDK-проект.
    mkdir  test -iac  
    cd  test -iac 
    cdk init app --language typescript
  • Познакомьтесь с CDK командами.
    cdk  list  # Список всех стеков программы  
    cdk synthesize  # Синтезирует и печатае CloudFormation для текущего стека  
    cdk bootstrap  # Разворачивание стека инструментов CDK в среде AWS  
    cdk diff  # Сравнивает локальный стек с развернутым стеком и печатает разницу
    cdk deploy  # Развертывание стека в аккаунте AWS
    cdk destroy  # Уничтожить развернутый стек

Вот и все! Теперь вы знаете все необходимые команды CDK. Хотя в основном вы будете использовать только две:

cdk diff

и

cdk deploy

Настройка стека

Стек CloudFormation  — это коллекция ресурсов AWS, управляемых как одно целое, настраиваемое как шаблон JSON или YAML
По сути, AWS CDK дает обертку над стеком CloudFormation, что позволяет создать его, используя язык программирования общего назначения.

cdk init app

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

lib/snake-iac-stack.ts
import  *  as  cdk  from  '@aws-cdk/core' ;
  export  class  SnakeIacStack  extends  cdk . Stack  {
       constructor (scope: cdk.Construct, id: string, props?: cdk.StackProps) {  
        super (scope, id, props);      
// The pre that defines your stack goes here     
 } 
 }

Добавление нового ресурса к стеку – это просто создание нового экземпляра класса, например, чтобы создать S3 хранилище для хостинга нашей JavaScript игры мы просто добавляем следующие строки :

// pre that defines your stack goes here  
// Snake Web Client  
const snakeClient =  new  s3. Bucket ( this , nameIt( "website-s3" ), { 
	bucketName: nameIt( "website-s3" ), 
	versioned:  false , 
	publicReadAccess:  true , 
	websiteIndexDocument:  "index.html" , 
	removalPolicy: cdk. RemovalPolicy . DESTROY  // remove on stack destruction 
});

Обратите внимание, что очень важно установить всеобщую конвенцию именования для всех ресурсов, например:

<environment>-<project>-<resource>

Для этого мы используем следующую вспомогательную функцию:

const  envName =  'test' ; 
const  nameIt =  ( name: string ) =>  ` ${envName} -snake- ${name} ` .toLowerCase(); 

Сочетание ресурсов

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

// API Gateway  
const snakeClientIntegration =  new  integration. HttpProxyIntegration ( { 
	method: gate. HttpMethod . ПОЛУЧИТЬ , 
    url: snakeClientBucket.bucketWebsiteUrl, 
}); 
const httpApi=  new  gate. HttpApi ( this , nameIt( "Api-GateWay" ), { 
    apiName: nameIt( "Api-GateWay" ), 
    defaultIntegration: snakeClientIntegration, 
});

Далее мы можем установить маршруты API таким же образом:

const apiGateway =  new  gate. HttpApi ( this , nameIt( "Api-GateWay" ), { 
   // ... // 
}); 
// Snake API  
const apiLambda =  new  lambda. Function ( this , nameIt( "api-lambda" ), { 
   // ... // 
}); 
const snakeApiIntegration =  новая  интеграция. LambdaProxyIntegration ({ 
	handler: apiLambda,  // api integration 
}); 
apiGateway.addRoutes({  // api route  
	path:  "/api/{proxy+}" , 
	methods: [gate. HttpMethod . ANY ], 
	integration: snakeApiIntegration 
}); 
apiGateway.addRoutes({  // swagger route  
	path:  "/swagger/{proxy+}" , 
	methods: [gate. HttpMethod . GET ], 
	integration: snakeApiIntegration 
});

То же касается управления контролем доступа, предоставления доступа к базе данных для компонента API:

// Persistence layer  
const table =  new  dynamodb. Table ( this , nameIt( 'DynamoDb - Table '), { 
	 // ... // 
}); 
 
table.grantReadWriteData(apiLambda); // give api access to dynamo DB table 

Для завершения образца конфигурации стека обратитесь в  репозиторий проекта

Просмотр стека

Во-первых, вы можете найти стеки CloudFormation в веб-консоли AWS (изображение 2):

Изображение 2. Стеки CloudFormation в консоли AWS
Во-вторых, тот же список стеков можно получить, выполнив следующую команду в терминале:

aws cloudformation list-stacks

Обработка дрейфа конфигурации

К сожалению, это слабое место как AWS CDK так и CloudFormation, поскольку обнаружение и обработка дрейфа конфигурации пока отсутствуют «out of the box» (см. открытый вопрос ).
Обработка дрейфа конфигурации возможна, но не тривиальна (см. статью ).
Поэтому я бы предложил начать с предотвращения возможности внесения несанкционированных изменений в конфигурацию.
В идеале все изменения в инфраструктуру должны вноситься программно, от имени отдельной учетной записи, используемой исключительно CDK приложением.
Этот подход также может быть автоматизирован (см. открытый вопрос ).

CI/CD

AWS CDK может быть легко интегрирован в процедуры непрерывной доставки (continuous delivery). Для этого образца используются GitHub Actions, тогда как для оригинального проекта мы использовали Azure DevOps, отличия не существенны.
Образец конфигурации CI/CD состоит из двух важных элементов:

  1. Скрипт для компиляции развернутых пакетов (./build.sh)
  2. Настройка GitHub Workflow в виде YAML файла, описывающего доставление в несколько сред (test, prod) с подтверждением администратора (/.github/workflows/ci-cd.yml)

Полученный результат доставки отображен ниже (изображение 3):
Изображение 3. Результат доставки GitHub Workflow
Обратитесь к руководству CI/CD в Readme.MD для настройки.

Вывод

AWS CDK создал прецедент для DevOps практики будущего, а текущая разработка Terraform CDK доказывает существование широкой заинтересованности в использовании языков общего назначения для реализации «инфраструктуры как кода».
Этот подход делает дисциплину непрерывного доставки доступнее, позволяет разработчикам быть вовлеченными в поддержку инфраструктуры, а также использовать существующие инструменты контроля качества как статический анализ, или даже модульные тесты.