AWS Notes
5.6K subscribers
445 photos
42 videos
10 files
2.8K 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
Завести #external (internet-facing/#public) #LoadBalancer (#ELB/#ALB/#NLB) на расположенные в #private #subnet виртуалки никаких проблем нет. Просто указываем для него, как и положено, #DMZ #subnet (#public):

albExt:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Name: externalAlb
Scheme: internet-facing
Subnets: # DMZ if public
- !ImportValue subnetVpc4DmzA
- !ImportValue subnetVpc4DmzB
SecurityGroups:
- !Ref sgAlb


А виртуалкам, расположенным и в #private_subnet добавляем в #security_group правила полного доступа с данного балансера:

sgInstance:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !ImportValue vpc4
GroupDescription: Full access for ALB
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 0
ToPort: 65535
SourceSecurityGroupId: !Ref sgAlb
Description: All TCP trafic - only for ALB


#CloudFormation #templates
Для #ECS наконец появились образы на базе #AMILinux2 - ECS-Optimized Amazon Linux 2 AMI. Для автоматического получения добавляем '-2' в конце. Или скрипт для #CloudFormation #templates:

for region in $(aws ec2 describe-regions --region us-east-1 --query 'Regions[].[RegionName]' --output text | sort); \
do printf " ${region}:\n AmiId: \
$(aws ssm get-parameters --names /aws/service/ecs/optimized-ami/amazon-linux-2/recommended/image_id \
--query 'Parameters[0].[Value]' --output text --region $region)\n" ; done
#recommendation — для имён переменных в #CloudFormation #templates лучше не использовать имена переменных, начинающихся с имени стэка, т.к. в Physical ID добавляется имя стэка и возникает визуальная путаница (особенно при использовании #nested_stacks):
jdot-St1IAM-16Z64H1UDUQF3-jdotInstanceProfile-WJ74BPFLW925
#recommendation Используемая практика именования переменных в #CloudFormation #templates у самого Амазана весьма ущербная - параметры начинаются с маленькой буквы p, а ресурсы начинаются с маленькой r:
pDMZSubnetA
rDMZSubnetA

Ущербность выявляется, когда выходишь за пределы одного стэка (особенно явно в #nested_stacks) — приходится переименовывать "бывшие" в одном стэке ресурсы в параметры в другом, что приводит при такой схеме к смене имени и сильно затрудняет сопровождение, а также плодит ошибки при переиспользование кода.

За многие годы я пришёл к другой схеме именования - параметры и ресурсы (если их нужно передавать) имеют одинаковые имена, лишь только добавляется правило, что все ресурсы начинаютс с маленькой буквы, а параметры с большой.

Кроме того, в имени ресурса почти всегда принципиально видеть тип, потому пример выше преобразуется в:
SubnetDmzA
subnetDmzA


Сначала кажется, что это как раз добавит путаницу, но очень скоро станет понятно, что обычно совпадающие имена (лишь начинающиеся с разной буквы) встречаются редко (обычно при создании бакетов или юзеров, где передаётся их имя), а возможность поиска по всему проекту(-ам) для последующего оптового переименования в случае надобности - крайне удобна.
Пример реализации #bucket_policy для нескольких #OriginAccessIdentity в одном #s3 бакете.

policyBucketFiles:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref bucketFiles
PolicyDocument:
Statement:
- Sid: Access for Cloudfront-files
Effect: Allow
Principal:
CanonicalUser: !GetAtt [originAccessIdentityBucketFiles, 'S3CanonicalUserId']
Action:
- 's3:GetObject'
Resource:
- !Join ['',['arn:aws:s3:::', !Ref bucketFiles, '/files/*']]
- !Join ['',['arn:aws:s3:::', !Ref bucketFiles, '/files_public/*']]
- Sid: Access for SwitchOver Cloudfront-files
Effect: Allow
Principal:
CanonicalUser: !Ref CanonicalUserFilesSwitchOver
Action:
- 's3:GetObject'
Resource:
- !Join ['',['arn:aws:s3:::', !Ref bucketFiles, '/files/*']]
- !Join ['',['arn:aws:s3:::', !Ref bucketFiles, '/files_public/*']]
- Sid: Access for replication account
Effect: Allow
Principal:
AWS: !Join ['',['arn:aws:iam::', !Ref AccountReplication, ':root']]
Action:
- 's3:*'
Resource:
- !Join ['',['arn:aws:s3:::', !Ref bucketFiles ]]
- !Join ['',['arn:aws:s3:::', !Ref bucketFiles, '/*']]

#CloudFormation #templates #examples
Использование секции #Rules в #CloudFormation #templates для дополнительной валидации входных параметров (например, чтобы проверить, что один параметр равен другому).

https://www.cloudar.be/awsblog/undocumented-feature-using-template-constraint-rules-in-cloudformation/

Rules:
ValidateEqual:
Assertions:
- AssertDescription: Both parameters must be the same
Assert:
"Fn::Equals":
- !Ref CanBeAnything
- !Ref MustBeTheSame


Работает лишь в консоли, но для случаев её использования может быть крайне удобным.
В блоке #Outputs #CloudFormation #templates нельзя сделать:

dns1:
Value: !GetAtt [
!If [ IsPrivate, esDomainVpc, esDomainPublic ], 'DomainEndpoint']

т.к. в #GetAtt нельзя использовать функции. Потому нужно использовать обратную конструкцию:

Value: !If [ IsPrivate, !GetAtt [esDomainVpc, 'DomainEndpoint'], !GetAtt [esDomain, 'DomainEndpoint'] ]
Стэк для VPC peering должен быть в том же регионе (cross-region появился в конце 2017), где находится VpcId:

peerManagementVpc4:
Type: 'AWS::EC2::VPCPeeringConnection'
Properties:
VpcId: !Ref VpcManagement
PeerVpcId: !Ref Vpc4
PeerOwnerId: !Ref AwsAccountVpc4
PeerRoleArn: !Ref RoleInVpc4

т.к. #CloudFormation ищет VpcId именно в этом регионе (аккаунте), а в шаблоне (т.е. в самом CloudFormation #templates) нет возможности задать регион (как минимум - пока).

В результате при попытке это сделать через шаблон будет #error:
VpcPeeringConnection failed to stabilize

А потому #cross_region #vpc_peering пока можно сделать лишь вручную через консоль (где есть возможность задать #aws_region).
При создании #security_group в #CloudFormation #templates не забывайте (не ленитесь) прописать Description в ингрессах (в каждом) — сами себе скажете спасибо в будущем, не говоря уже про других.

sgInstance:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !ImportValue vpc4
GroupDescription: Std Security Group
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 0
ToPort: 65535
SourceSecurityGroupId: !Ref sgAlb
Description: All TCP trafic - only for ALB
- IpProtocol: tcp
FromPort: 9100
ToPort: 9100
CidrIp: 10.0.0.0/8
Description: node-exporter
- IpProtocol: tcp
FromPort: 8080
ToPort: 8080
CidrIp: 10.0.0.0/8
Description: cadvisor
Поддержка Secrets в Environment для #Fargate появилась в конце 2018-го года (версия Fargate 1.3), но на текущий момент в документации есть только следующее. Получается, это можно реализовать и в #CloudFormation #templates, однако документация, как обычно, отстаёт и хромает, хотя это уже работает.

Предположим, что нужно поднять какой-то Fargate контейнер, создать для него #SSM_Parameters, которые прокидываются в докер Environment, чтобы после можно было поменять нужный параметр без пересоздания всего стэка (для применения, естественно, потребуется пересоздание таски).

Главная часть кода для имплементации такого будет следующая:
...
ssmparamDbEndpoint:
Type: AWS::SSM::Parameter
Properties:
Name: !Ref ParamNameDbEndpoint
Type: String
Value: !Ref DbEndpoint
Description: SSM Parameter for DB endpoint
...
fargateTask:
Type: AWS::ECS::TaskDefinition
Properties:
ContainerDefinitions:
- Name: !Ref ServiceName
Image: !Ref DockerImage
Essential: true
Secrets:
- Name: WORDPRESS_DB_HOST
ValueFrom: !Join ['',['arn:aws:ssm:', !Ref 'AWS::Region', ':', !Ref 'AWS::AccountId', ':parameter/', !Ref ParamNameDbEndpoint]]
- Name: WORDPRESS_DB_USER
ValueFrom: !Join ['',['arn:aws:ssm:', !Ref 'AWS::Region', ':', !Ref 'AWS::AccountId', ':parameter/', !Ref ParamNameDbUser]]
- Name: WORDPRESS_DB_PASSWORD
ValueFrom: !Join ['',['arn:aws:ssm:', !Ref 'AWS::Region', ':', !Ref 'AWS::AccountId', ':parameter/', !Ref ParamNameDbPassword]]
Environment:
- Name: WORDPRESS_DB_NAME
Value: wp-db
...


Т.е. добавляется блок Secrets, куда значения из #ParameterStore попадают благодаря такой конструкции:

arn:aws:ssm:YOUR_AWS_REGION:YOUR_AWS_ACCOUNT:parameter/PARAMETER_NAME

Полный (рабочий) пример тут.

На текущий момент параметры из блока Secrets не отображаются в AWS Console (см. картинку внизу - она из примера), однако точно работают (можно попробовать пример). Хотя с некоторыми регионами могут быть вопросы - точно работает (проверено) для Virginia и Ireland.