AWS Notes
5.6K subscribers
444 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
Стэк для 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).
Большая часть материалов этого канала берётся из моих записей, что я веду уже почти десять лет в Google Datasheets. Когда-то это начиналось просто с возможности не зависеть от ОС и используемого устройства, но со временем это вылилось в стиль работы, который особенно актуален для #devops. Хочу поделиться выработанными за годы практиками, которые, думаю, особенно будут полезны #начинающим.

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

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

===
Правило КОПИПАСТА. Все команды выполняем только копированием из своего документа.
===

Что это значит? Предположим, что стоит задача поднять на виртуалке Jenkins LTS в Docker. Создаю документ (я буду подразумевать гуглошиты, но это не принципиально) в папке проекта, к которому относится такая задача.

Все команды пишу сначала в документ, после просто их копирую в терминал. Речь о главных командах, относящихся к настройке — всяческие ls и отладочные не в счёт.

У меня таких документов много, всё повторяется, потому, конечно же, этого можно было бы и не делать. Да и вообще, память у меня отличная. А что не вспомню – можно быстренько нагуглить. И вообще, зачем лишние телодвижения?!? Ответ см. в п.1. (правило копипаста).

Часто (читай – всегда) нужно гуглить, нагугленное вставляю в свой документ и только из него копирую в терминал.

Мало того – сразу добавляю комментарии. Это сейчас понятно, а через месяц – нет. Комментарии выделяю, чтобы после можно было быстро видеть структуру документа, кроме того, при накоплении информации на странице, быстро ориентироваться можно будет только именно по ним.

Если есть важный ответ на команду – добавляю его. Форматирую (в моноширинный), если большой, то уменьшаю шрифт.

Выделяю важные места в ответе. Выделяю важные ключики в команде. Выделяю цветом основные параметры. Разбиваю на логические части. В общем, делаю красиво – #как_для_себя.

===

Да, это занимает время. Без практики (и начинающим) — очень много времени. Однако суть данной рекомендации в том, что #это_работает.
Уже второй подход к этой (или похожей) задаче полностью окупает потраченное время. Накопленный материал, лично переработанный, а не просто увиденный в поиске – повышает вашу квалификацию.

Во многих случаях (и с обеспечением должного уровня безопасности) в ответах команд даже можно хранить важные credentials (на картинках и постах в канале они изменены – можете не стараться :) ) – из контекста понятно для чего они и легко искать.

Удобно шарить другим. При ответственном подходе – считай, готовая документация.

А при накоплении материала – тоже сможете завести свой канал.

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

#recomendation #best_practices #continuous_self_improvement
Некоторые #читы, полезные на местности (в виртуалке).

===
Получить список имеющихся (в нужном регионе) #KeyPair:

aws --region us-east-1 ec2 describe-key-pairs --query KeyPairs[].KeyName[]

===
Получить список #IAM ролей:

aws iam list-roles --query Roles[].Arn[]

===
Получить список юзеров:

aws iam list-users --query Users[].Arn[]

===
Получить детальный отчёт по правам юзеров:

aws iam get-account-authorization-details --query UserDetailList[]

#aws_cli
О вреде юзеров.

В грамотно спроектированном окружении нет (не должно быть) #IAM юзеров. Почему? Потому что у юзера есть #credentials и они должны быть где-то явно указаны (в отличие от роли, прикреплённой к инстансу).

Если у вас один аккаунт на всех и всё, значит все пользователи заходят через юзеров, что проблема в степени количества этих юзеров. Обязательно включайте MFA для всех юзеров. А лучше переходите на светлую сторону #multi_account_strategy + #SSO.

В легаси-проектах, где ПО не умеет роль (требует наличия AccessKeyId и SecretAccessKey) - приходится заводить юзера. Включайте ему минимальные права - ровно на то, что он должен делать.

Для некоторых ситуаций, например, доступ в #CodeCommit по SSH или в #ES вне #VPC - тоже требуется наличие юзера. Всё это издержки Амазона (фу, как не стыдно), не придумавшего пока, как реализовать это без юзеров.

Во всех остальных случаях - никаких юзеров. Помните, хороший юзер - это роль.

#recomendation
62-users-on-project.gif
94.2 KB
Когда увидел, что на проекте 62 юзера.
Чтобы запустить #aws_cli команду для другого аккаунта, нужно сначала добавить в ~/.aws/config профиль типа:

[profile devops-codecommit]
role_arn = arn:aws:iam::123456789012:role/codecommit-role
credential_source = Ec2InstanceMetadata


Параметры:
devops-codecommit - просто имя профиля
role_arn - роль в аккаунте, куда нужно переключиться
credential_source = Ec2InstanceMetadata означает, что #IAM из роли инстанса

У codecommit-role должны быть права на переключение "sts:AssumeRole" и остальное нужное (в данном примере - доступ в #CodeCommit).

Теперь для просмотра репозиториев в другом аккаунте отработает следующая команда:

aws codecommit list-repositories --profile devops-codecommit

Т.е. благодаря флажку --profile происходит переключение в роль нужного аккаунта.

https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-role.html
Доступ в #CodeCommit (git репозиторий) можно получить не только через привычные логин-пароль (https) и ключ (ssh), но и с помощью IAM роли. Это удобно и безопасно, т.к. нет #credentials (лишь прикреплённая к инстансу роль). В качестве адреса репозитория при этом используется https-вариант.

Когда CodeCommit-репозиторий в том же аккаунте, то всё работает очевидно. Однако что делать, если согласно #multi_account_strategy какое-то test-окружение, поднятое в своём test-аккаунте, должно загрузить репозиторий из репозитория, расположенного в (другом) devops-аккаунте?

Тут потребуется подправить настройки credential.helper - чтобы #git сам переключался в нужный аккаунт.

git config --global credential.helper '!aws codecommit --profile devops-codecommit credential-helper $@'

То есть для этого используем описанный в предыдущем посте метод.

Вот полный пример кода для #user_data с загрузкой git из другого аккаунта:
## Setup Git for CodeCommit
mkdir /root/.aws
AWS_CONFIG=/root/.aws/config

echo "[profile devops-codecommit]" > $AWS_CONFIG
echo "credential_source = Ec2InstanceMetadata" >> $AWS_CONFIG
echo "role_arn = ${CodeCommitRoleArn}" >> $AWS_CONFIG

export HOME=/root
git config --global credential.helper '!aws codecommit --profile devops-codecommit credential-helper $@'
git config --global credential.UseHttpPath true

## get repos from CodeCommit
HTTPS_GIT=https://git-codecommit.us-east-1.amazonaws.com/v1/repos
git clone -b ${ProjectBranch} --quiet $HTTPS_GIT/${ProjectName} $DOCKERPROJECT_DIR &> /dev/null


https://docs.aws.amazon.com/codecommit/latest/userguide/auth-and-access-control.html
Если в #user_data переменных нужно получить #ImportValue параметры, то используется следующая конструкция:
UserData:
Fn::Base64: !Sub
- |
#!/bin/bash -x
## ...
echo "role_arn = ${CodeCommitRoleArn}" >> $AWS_CONFIG
## ...
#### end of UserData
- AwsAccountDevops: !ImportValue AwsAccountDevops
CodeCommitRoleArn: !ImportValue CodeCommitRoleArn


Т.е. передаём в Fn::Base64: !Sub массив, где сначала сам код, а потом список используемых в нём переменных (именно в таком порядке - код, затем переменные).
#single_account vs #multi_account_strategy

Споры о преимуществах той или иной стратегии ("всё/все в одном" или #мультиаккаунт) бессмысленны. Не буду хохмить про то, что они очень часто ведутся между теми, кто уже давно ест апельсины и теми, кто никогда их не пробовал, но не одобряет. Если максимально коротко - у каждого способа есть набор очевидных и неочевидных плюсов и минусов, однако #multi_account_strategy — суть современный способ работы современного проекта, а потому ориентироваться нужно именно на него.

Объять столь большую и радикально отличающуюся тему быстро невозможно, потому буду разбирать поэтапно, усложняя и объясняя по ходу.

===
Минимальная схема
===

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

По принципу разбиения схему можно назвать "мухи и котлеты". Всё, что не относится к поднимаемым окружениям - это условный Devops аккаунт. Окружения dev-stg-prod (test, etc) поднимаются единым образом, т.е. условно из одного шаблона и лишь с разными настройками.

Окружения живут в своих VPC и соединяются с Management VPC с помощью VPC peering. Доступ к закрытым ресурсам (без внешних айпишников) происходит через промежуточный Bastion инстанс.

Всё необходимое для поднятия окружений, различные ресурсы и настройки - всё лежит в Devops аккаунте, куда может иметь доступ лишь девопс, а разработчики ходят в dev-окружение и им выделяется доступ (временно, для деплоя) в stage-prod-etc.

Это (относительно) просто в реализации и поддержке, схема удовлетворяет требованиям различных #compliance (например, #NIST) и наверняка подойдёт для многих проектов, особенно тех, кто хочет начать использовать мультиаккаунты.
С учётом AWS #Organizations минимальная схема принимает вид, где есть мастер (root) аккаунт (помеченный ранее как #devops) и подаккаунты с окружениями.

Некоторые AWS сервисы до сих пор рассчитаны на работу именно из мастер-аккаунта, в том числе поэтому реализовывать #мультиаккаунт по такой схеме проще всего.
Минимальная схема не является рекомендованной, т.к. поднятие ресурсов в мастер-аккаунте не есть #best_practices. Согласно оным мастер-аккаунт должен быть пустым и страшно защищённым.

Правда пока сам Амазон не способствует такой реализации - отдельные сервисы (#CloudTrail, #Config, #SSO и др.) до сих пор завязаны некоторым своим функционалом на использование именно мастера. В результате для соблюдения архитектурной чистоты приходится плодить костыли и с нетерпением ждать, когда же эти косяки будут исправлены.

Однако делать нужно правильно, несмотря на некоторые текущие моменты. Как минимум знать и стремиться.

Здесь и далее всё будет подразумевать использование AWS #Organizations, что и есть реализация #multi_account_strategy.

===
Рекомендуемая схема
===

В рекомендуемой схеме мастер аккаунт пустой (с поправкой на то, что пока ещё требует запуска в нём) - как минимум, никакие виртуалки в нём точно не запускаем, а наш #devops становится суб-аккаунтом и смещается по иерархии ниже.

Для различных функций, в том числе связанных со всей организацией, некоторая часть мух из предыдущей "мухо-котлетной" схемы выделяются в отдельный аккаунт с расплывчатым названием Secure. Туда переезжают ключи шифрования, домены (только регистрации, а не Hosted zones), бэкапы, #CloudTrail-логи и прочие сущности с особой важностью для организации в целом.

Современные фичи Амазона изменяют некоторые архитектурные элементы.

• Bastion выбрасываем - появление #SSM #Session_Manager закрывает его функционал.

• Для #VPC_peering используем #Transit_Gateway.

• В Devops-аккаунте добаляется #Shared_VPC, которая используется для окружений без жёстких требований по безопасности (условно dev-test), хотя, в принципе, можно и для всех окружений.

Также в Devops-аккаунте появился #Jenkins как CI-инструмент - это может быть любой другой вам привычный (я же использую Jenkins, как говорил Портос, потому, что я использую Jenkins).
Дальнейшее усложнение AWS #Organizations происходит по мере увеличения количества проектов, команд, требований и т.д.

===
Расширенная схема
===

• Общие ресурсы (ECR, снэпшоты, AMI и др.) вместе с #Shared_VPC выделяются в Shared аккаунт.

• Централизованный мониторинг и логи (ELK/Prometheus/Grafana/Sentry и т.д.) занимают свой аккаунт Monitoring (логи прода могут отправляться туда же или в отдельные - тут чисто условно).

• Бэкапы переезжают в DR (Disaster Recovery) аккаунты своих проектов.

• Наборы окружений dev-test-stg-prod-dr объединяются в #OU (Organization Units) для возможности применения к ним групповых SCP политик (объединение может быть и как Dev OU, DR OU etc - тоже чисто условно).

• Если ваша контора хочет целиком переехать в AWS, то выделяется отдельный аккаунт Organization для "организационных" вещей (название не самое удачное, речь об организации-фирме-компании, где, видимо, вы работаете :) ) — AD (Active Directory) для юзеров (самих работников), используемые для #SSO как единой точки входа, а также финансы, биллинги и прочие бухгалтерии, которые совсем не про код - всё будет там.

Процесс детализации #multi_account_strategy можно продолжать дальше - например, добавить OU для #HIPAA и прочих #compliance, где посредством #SCP будут отрабатывать их требования. Многие используеют Sandbox и/или личные аккаунты для разработчиков. И так далее и тому подобное — основные типы уже были перечислены и это уже лишь детали.
Не все йогурты одинаково полезны, а потому с Managed #IAM политиками нужно быть на чеку (амазоновцы не парятся и ставят "с запасом" - многие имеют излишние права).
Чтобы знать врага в лицо, добрые люди собрали коллекцию IAM Managed политик и ведут историю их изменений:

https://github.com/SummitRoute/aws_managed_policies/tree/master/policies
В пандан к предыдущему посту - заслуживающая внимания утилита для вычисления минимально нужных #IAM привилегий посредством сравнения имеющихся политик у юзера/роли и тех, что реально запрашиваются через AWS API (определяется с помощью #CloudTrail логов).

Может особенно может быть полезной для адептов #single_account, где такое весьма актуально в каждодневной борьбе с желающими урвать себе прав и побольше.

С помощью утилиты CloudTracker можно чётко контролировать используемое: кто не оценил вашу доброту - отобрать лишнее, а всем остальным выдавать доступ строго по талонам.

https://github.com/duo-labs/cloudtracker
При создании #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.
Ещё один ресурс для возможности сравнения EC2 инстансов - с некоторыми претензиями на мобильную версию:

https://cloudbanshee.com/ec2

Кстати, кто активно пользуется https://ec2instances.info и кому чего-то там не хватает — может вполне такое сделать сам:

https://github.com/powdahound/ec2instances.info

#info #comparison
Если у вас годами себе мирно жили тучи файлов на #s3 и вдруг выясняется, что по #compliance причинам теперь их всех нужно зашифровать либо по требованиями аудита требуется всем проставить (переставить) тэги или ещё какая-то глобально-массовая напасть — для всех таких работ теперь есть нативный инструмент #s3_batch_operations:

https://aws.amazon.com/blogs/aws/new-amazon-s3-batch-operations/
Просто оставлю это здесь - интересная утилита, реализующая traffic mirroring:

https://github.com/buger/goreplay

Кому интересно, чуть расшифрую (не про Амазон).

Тестирование почти всегда проводится какими-то искусственными паттернами, которые должны при это дать некую гарантию, что на проде при реальной нагрузке оно не поломается. А метод traffic mirroring (или shadow traffic) дублирует реальный трафик, пришедший на прод в нужное вам (тестовое) окружение.

Это очень круто - иметь возможность тестировать "живым" трафиком. Модная тема, особенно легко реализуемая с помощью #kubernetes, так что советую как минимум знать про это - сие есть следующая инкарнация подходов Blue/Green или Canary Deployment.
Безопасности пост.