AWS Notes
5.61K subscribers
493 photos
43 videos
10 files
2.87K links
AWS Notes — Amazon Web Services Educational and Information Channel

Chat: https://xn--r1a.website/aws_notes_chat

Contacts: @apple_rom, https://www.linkedin.com/in/roman-siewko/
Download Telegram
Последовательность блоков в #CloudFormation #templates можно менять (сначала ресурсы или даже вывод, остальное ниже):

Outputs:
 ecrRepository:
  Value: !Ref ecrRepository
Resources:
 ecrRepository: 
  Type: AWS::ECR::Repository
  Properties: 
   RepositoryName: !Ref RepositoryName
Parameters:
 RepositoryName:
  Type: String
  Description: Name of ECR repository
  Default: some-repo
Description: ECR repository
Соединение элементов строки в CloudFormation

Собрать в кучу строчку в CloudFormation шаблоне можно разными способами.

Стандартный с помощью !Join, например,

ContainerName: !Join ['-', ['service', !Ref MsName]]

Однако то же самое можно сделать с помощью !Sub:

ContainerName: !Sub 'service-${MsName}'

То есть с !Sub олучается короче, иногда существенно короче. Потому такой подход весьма популярен.

Однако длина не единственный показатель удобности и потому, когда вы после дебажите шаблон, все эти важные параметры сливаются на мониторе в строку (ведь это строка) и их не видно на фоне других. В то время как в случае !Join чётко видны логические составляющие - все переменные, из которых будет собрана строка.

Так что я использую !Join - длиннее, но разборчивей.

Кстати, многие забывают, что у !Sub кроме "обычной" возможности просто вставлять параметры из шаблона, есть возможность подставлять их через свои переменные, организуя сложные выборки с !ImportValue и т.п. Например, вот здесь встречается такая конструкция:

ResourceId: !Sub
- 'service/${Cluster}/${Service}'
- Cluster: {'Fn::ImportValue': !Sub '${ParentClusterStack}-Cluster'}
Service: !GetAtt 'Service.Name

Чтобы собрать строчку, мы внутри её делаем две свои "локальные" переменные Cluster и Service (которые указывают после строки как массив) и уже в них делаем ещё какие-то действия.

В "солидной" версии это (не точный аналог - просто очень похожее из реального кода) будет длинным, но очевидным:

ResourceId: !Join ['', ['service/', !ImportValue ecsClusterMs, '/', !GetAtt [ecsService, 'Name']]]

Всё видно и понятно. Как минимум мне.

#CloudFormation #templates
Отличный источник примеров работы с #CloudFormation #templates (а также #Terraform и #aws_cli) плюс прямые ссылки на документацию, официальные блоги, всяческие безопасности и различные #best_practices:

https://asecure.cloud/

Однозначно в закладки.

#security #info
Beanstalk + ALB + CloudFormation

По умолчанию в Elastic Beanstalk создаётся ALB, если делать это через консоль:

By default, Elastic Beanstalk creates an Application Load Balancer for your environment when you enable load balancing with the Elastic Beanstalk console or the EB CLI.

А через CloudFormation - с классическим ELB! (Здравствуй, логика.) Из-за этого в документации не найти примеров кода для создания Beanstalk в CloudFormation.

Cервис старый и все примеры в интернете обычно лишь для классического (старого) ELB. И документация из-за старости и сложности (под капотом) сервиса, весьма неочевидна.

Вот главная ссылка, что всегда требуется при создании шаблона для Beanstalk:

https://docs.amazonaws.cn/en_us/elasticbeanstalk/latest/dg/command-options-general.html

А вот пример кода, как заставить создать Beanstalk + ALB через CloudFormation:

- Namespace:  aws:elasticbeanstalk:environment
OptionName: LoadBalancerType
Value: application
- Namespace: aws:elbv2:listener:443
OptionName: Protocol
Value: HTTPS
- Namespace: aws:elbv2:listener:443
OptionName: SSLCertificateArns
Value: !Ref AcmCertificateArn
- Namespace: aws:elbv2:listener:443
OptionName: DefaultProcess
Value: default
- Namespace: aws:elbv2:loadbalancer
OptionName: SecurityGroups
Value: !ImportValue sgVpc4Web
- Namespace: aws:elasticbeanstalk:environment:process:default
OptionName: Port
Value: !Ref InstancePort
- Namespace: aws:elasticbeanstalk:environment:process:default
OptionName: Protocol
Value: HTTP
- Namespace: aws:elasticbeanstalk:environment:process:default
OptionName: StickinessEnabled
Value: true
- Namespace: aws:elasticbeanstalk:environment:process:default
OptionName: HealthCheckPath
Value: !Ref HealthCheckPath

Переменные нужно поменять на свои, главная оставить LoadBalancerType - application.

#Beanstalk #CloudFormation #templates
ECS task + init container

Часто нужно, чтобы ECS task-а сначала была проиниацилизирована, а уже потом стартовал сервис. Пример, как такое можно сделать с помощью CloudFormation:

https://github.com/applerom/cloudformation-examples/blob/master/ecs/task-with-init-container.yaml

Код из рабочего конфига, но отредактирован (длинный, выброшено не относящееся к делу), чисто к тому, как такое можно сделать. В нём будут интересны следующие строчки.

ecsTaskWithInit:
Type: AWS::ECS::TaskDefinition
Properties:

...
   ContainerDefinitions:
- Name: !Ref StdNameInit
Image: !Ref DockerImage
Essential: false

...
     Command:
- sh
- '-c'
- !Sub |
cd /home/my/app \
&& ./setup.py migrate --noinput \
&& ./setup.py rebuild_index --noinput

...
   - Name:      !Ref StdName
Image: !Ref DockerImage
Essential: true
Links:
- !Ref StdNameInit
Environment:

...

Поднимаем task-у с двумя контейнерами - один будет для инициализации, а другой уже стартует сервис (это может быть один и тот же образ, лишь с разными переменными, как в данном случае).

Контейнер для инициализации отрабатывает первым и умирает, потому ставим ему:

Essential: false

Он должен выполнить какую-то команду(-ы), запускаем следующим способом:

Command:
- sh
- '-c'
- !Sub |
cd /home/my/app \
&& ./setup.py migrate --noinput \
&& ./setup.py rebuild_index --noinput


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

Links:
- !Ref StdNameInit


И ставим главному контейнеру:

Essential: true

Так можно регулировать последовательность запуска и инициализировать что-то перед работой основного сервиса.

#CloudFormation #templates #examples