Розгортаємо контейнер з приватного реєстру ghcr.io в Amazon ECS
У кожного настає такий момент, коли вам потрібно розгорнути контейнер з приватного репозиторію на ECS. Документація від Amazon не є взірцем зрозумілості, тому я підготував для вас (в першу чергу для себе) опис того, що для цього потрібно зробити.
Передумови
Контейнер в ghcr.io
Для початку, вам потрібно завантажити контейнер на GitHub Container Registry. Це може бути як публічний, так і приватний репозиторій.
Входите в GitHub і переходите на сторінку репозиторію, в якому знаходиться ваш контейнер. В розділі Packages обираєте артефакт, який є створеним раніше контейнером.
Для доступу до вашого реєстру вам знадобиться токен доступу Private Access Token. Для створення PAT перейдіть в налаштування вашого облікового запису.
Внизу сторінки оберіть Developer settings
Далі, виберіть Personal access tokens/Tokens (classic)/Generate new token (classic).
або, перейдіть за цим посиланням для створення PAT — https://github.com/settings/tokens/new.
Додайте за потреби Примітку, оберіть час дії токена (через скільки днів він перестане бути валідним), та вкажіть потрібні права доступу – в цьому випадку нам потрібно лише мати права на отримання пакетів (read:packages — Download packages from GitHub Package Registry). Внизу сторінки натисніть кнопку Generate token.
Після цього ви побачите сторінку з вашим новим токеном. Скопіюйте його та збережіть у безпечному місці. Ми будемо його використовувати для доступу до реєстру.
ECS
У вас має бути налаштований обліковий запис в AWS, за бажанням локально встановлений AWS CLI та Amazon ECS CLI. Якщо ви не бажаєте встановлювати їх локально, ви можете використовувати AWS CloudShell.
Створення CMK в AWS KMS
Для початку, нам потрібно створити CMK (Customer Master Key) та аліасу для нього в AWS KMS. CMK використовується AWS Secret Manager для шифрування конвертів, даних які містять чутливу інформацію. Аліас виступає як назва для вашого CMK, її простіше запамʼятати та використовувати ніж сам ідентифікатор ключа. Також ви можете використовувати аліас у вашому коді. Ви можете змінювати ключ у майбутньому (на інший), залишаючи аліас незмінним.
aws kms create-key --query KeyMetadata.Arn --output text
у відповідь ви отримаєте ідентифікатор вашого ключа, у вигляді Amazon Resource Name (ARN) наприклад:
arn:aws:kms:eu-central-1:123456789012:key/abc123de-4567-89fa-0bcd-efgh12345678
Тепер ми створимо аліас для нашого ключа:
aws kms create-alias \
--alias-name alias/ecs-ghcr \
--target-key-id arn:aws:kms:eu-central-1:123456789012:key/abc123de-4567-89fa-0bcd-efgh12345678
Якщо ви не налаштовували собі локально AWS CLI, ви можете скористатись CloudShell та виконувати всі команди в командному рядку там.
Створення CMK ви можете зробити в Консолі AWS, перейшовши в AWS KMS та натиснувши кнопку Create key.
ARN CMK вам знадобиться при створенні документа політики довіри на наступному кроці.
Створення Secret в AWS Secrets Manager
На цьому етапі нам потрібно створити Secret, який буде містити ваш логін на пароль (код доступу) зашифровані за допомогою CMK для витягування образу вашого контейнера з приватного реєстру.
aws secretsmanager create-secret \
--name ghcr_io_pat \
--description "Secret to get packages from ghcr.io" \
--kms-key-id alias/ecs-ghcr \
--secret-string '{"username":"your_nickname", "password":"ghp_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"}'
У відповідь ви маєте отримати наступне:
{
"ARN": "arn:aws:secretsmanager:eu-central-1:123456789012:secret:ghcr_io_pat-abcdEF",
"Name": "ghcr_io_pat",
"VersionId": "4b43b832-df4c-48b3-b59a-bb18287e6c15"
}
ARN секрету повинен бути у виводі ☝️ попередньої команди – поле ARN. Вам потрібно буде посилатися на цей ARN під час створення документа політики довіри на наступному кроці.
Створення ролі в IAM для виконання завдання
У випадку наявності у вас ролі ecsTaskExecutionRole
можете пропустити цей крок.
Спочатку вам потрібно буде створити документ політики довіри, щоб вказати виконавця, який візьме на себе роль, що в цьому випадку є ECS task:
cat << EOF > ecs-trust-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ecs-tasks.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
Створимо роль скориставшись AWS CLI та файлом ecs-trust-policy.json
з описом ролі.
aws iam create-role \
--role-name ecsTaskExecutionRole \
--assume-role-policy-document file://ecs-trust-policy.json
Щоб додати основні дозволи до інших ресурсів сервісів AWS, які необхідні для запуску завдань Amazon ECS, прикріпіть політику ролі виконання завдань AWS ECS до новоствореної ролі:
aws iam attach-role-policy \
--role-name ecsTaskExecutionRole \
--policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
Тепер створимо документ політики дозволів, який дозволяє завданню ECS розшифрувати та отримати секрет, створений в AWS Secrets Manager.
cat << EOF > ecs-secret-permission.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"kms:Decrypt",
"secretsmanager:GetSecretValue"
],
"Resource": [
"arn:aws:secretsmanager:eu-central-1:123456789012:secret:ghcr_io_pat-abcdEF",
"arn:aws:kms:eu-central-1:123456789012:key/abc123de-4567-89fa-0bcd-efgh12345678"
]
}
]
}
EOF
☝️ вкажіть свої Secret та CMK в значення "Resource": [ <Secret>, <CMK> ]
.
Нарешті, додайте інтегровану політику дозволів, яка дозволить вашій задачі отримувати імʼя користувача та пароль до ghcr.io з AWS Secrets Manager. Зверніть увагу, що ви посилаєтеся на документ політики дозволів, створений на попередньому кроці. Змініть шлях до теки за необхідності, щоб визначити правильне розташування файлу:
aws iam put-role-policy \
--role-name ecsTaskExecutionRole \
--policy-name ECS-SecretsManager-Permission \
--policy-document file://ecs-secret-permission.json
Налаштування ECS CLI (необовʼязково)
Інструмент командного рядка для Amazon ECS (ESC CLI) надає команди для спрощення створення кластера Amazon ECS та AWS ресурсів, необхідних для його налаштування. Після встановлення ECS CLI ви можете додатково налаштувати ваші AWS облікові дані в іменованому профілі ECS. Профілі зберігаються в файлі ~/.ecs/credentials
.
ecs-cli configure profile \
--access-key <AWS_ACCESS_KEY_ID> \
--secret-key <AWS_SECRET_ACCESS_KEY> \
--profile-name <PROFILE_NAME>
Ви також можете вказати стандартний профіль який використовувати для всіх команд ECS CLI:
ecs-cli configure profile default --profile-name <PROFILE_NAME>
Якщо ви не налаштовуєте профіль ECS або не встановлюєте змінні середовища, буде використано стандартний профіль AWS. Значення ключа доступу та секретного ключа доступу можна переглянути в AWS Management Console.
Ви можете додатково налаштувати назву кластера ECS, тип запуску та регіон AWS для використання з ECS CLI за допомогою команди ecs-cli configure
. Значення змінної <LAUNCH_TYPE>
можна встановити у FARGATE
або EC2
.
ecs-cli configure \
--cluster <CLUSTER_NAME> \
--default-launch-type <LAUNCH_TYPE> \
--config-name <CONFIG_NAME> \
--region <AWS_REGION>
Ці значення також можна визначити або перевизначити за допомогою прапорців команд, зазначених у наступних кроках.
Створення кластера Amazon ECS
Створимо кластер Amazon ECS за допомогою команди ecs-cli up
, вказавши назву кластера, регіон AWS (наприклад, eu-central-1
) та FARGATE
як тип запуску:
ecs-cli up \
--cluster <CLUSTER_NAME> \
--region eu-central-1 \
--launch-type FARGATE \
Використовуючи тип запуску FARGATE, ми використовуємо AWS Fargate для управління обчислювальними ресурсами від нашого імені, щоб нам не потрібно було вказувати власні екземпляри контейнера EC2. Типово ECS CLI також запустить стек AWS CloudFormation для створення нового VPC з прикріпленим Інтернет-шлюзом, 2 загальнодоступними підмережами та групою безпеки. Ви також можете вказати власні ресурси, використовуючи прапорці в команді вище.
Налаштування групи безпеки
Після успішного створення кластера ECS ви повинні побачити ідентифікатори VPC та підмережі, що відображаються в терміналі. Далі отримайте опис JSON новоствореної групи безпеки та занотуйте ідентифікатор групи безпеки або GroupId
. Замініть змінну <VPC_ID>
на ідентифікатор новоствореного VPC.
aws ec2 describe-security-groups \
--filters Name=vpc-id,Values=<VPC_ID> \
--region eu-central-1
У відповідь ви маєте отримати подібний вивід:
{
"SecurityGroups": [
{
"Description": "default VPC security group",
"GroupName": "default",
"IpPermissions": [
{
"IpProtocol": "-1",
"IpRanges": [],
"Ipv6Ranges": [],
"PrefixListIds": [],
"UserIdGroupPairs": [
{
"GroupId": "sg-04512c8a7bff9b34e",
"UserId": "123456789012"
}
]
},
…
],
…
}
]
}
Додайте правило для вхідного трафіку до групи безпеки, що дозволяє HTTP-трафік з будь-якої адреси IPv4. Замініть змінну <SG_ID>
на GroupId
, отриману на попередньому кроці. Це вхідне правило дозволить вам підтвердити, що ваш сервер працює у вашому завданні та що образ з приватного реєстру було успішно отримано з GHCR.
aws ec2 authorize-security-group-ingress \
--group-id <SG_ID> \
--protocol tcp \
--port 8080 \
--cidr 0.0.0.0/0 \
--region eu-central-1
Створення Service Amazon ECS
Service Amazon ECS дозволяє одночасно запускати та підтримувати кілька екземплярів визначення завдання. ECS CLI дозволяє створити Service за допомогою файлу Docker compose. Створіть наступний файл docker-compose.yml
, який визначає контейнер, який надає порт 8080 для вхідного трафіку на сервер. Щоб посилатися на образ, який зберігається у вашому приватному реєстрі у GHCR, замініть змінну <USER_NAME>
на ваше імʼя користувача GitHub, змінну <REPO_NAME>
на імʼя вашого приватного репозиторію та змінну <TAG_NAME>
на теґ, який ви використовували.
cat << EOF > docker-compose.yml
version: "3"
services:
web:
image: ghcr.io/<USER_NAME>/<REPO_NAME>:<TAG_NAME>
ports:
- 8080:8080
EOF
Так, якщо ви спробуєте розгорнути образ з прикладу на початку, значення змінної image
буде наступним — ghcr.io/andygol/switch2osm-mkdocs:main
.
Вам також потрібно буде створити наступний файл ecs-params.yml
, щоб вказати додаткові параметри для вашого Service, специфічні для Amazon ECS. Зауважте, що поле services
нижче відповідає полю services
у файлі Docker Compose вище, що відповідає назві контейнера для запуску. Коли ECS CLI створює визначення завдання з файлу docker-compose.yml
, поля web
будуть обʼєднані в визначення контейнера ECS, включаючи образ контейнера, який він буде використовувати, та облікові дані сховища GHCR, які йому знадобляться для доступу до нього. Замініть змінну <SECRET_ARN>
на ARN секрету AWS Secrets Manager, який ви створили раніше. Замініть змінні <SUB_1_ID>
, <SUB_2_ID>
та <SG_ID
> ідентифікаторами 2 загальнодоступних підмереж та групи безпеки, які були створені разом з кластером ECS.
cat << EOF > ecs-params.yml
version: 1
task_definition:
task_execution_role: ecsTaskExecutionRole
ecs_network_mode: awsvpc
task_size:
mem_limit: 0.5GB
cpu_limit: 256
services:
web:
repository_credentials:
credentials_parameter: "<SECRET_ARN>"
run_params:
network_configuration:
awsvpc_configuration:
subnets:
- "<SUB_1_ID>"
- "<SUB_2_ID>"
security_groups:
- "<SG_ID>"
assign_public_ip: ENABLED
EOF
Далі створіть Service ECS зі свого файлу compose за допомогою команди ecs-cli compose service up
. Ця команда шукатиме ваші файли docker-compose.yml
та ecs-params.yml
у поточній теці. Замініть змінну <CLUSTER_NAME>
на імʼя вашого кластера ECS та змінну <PROJECT_NAME>
на бажану назву вашого Service ECS.
ecs-cli compose \
--project-name <PROJECT_NAME> \
--cluster <CLUSTER_NAME> \
service up \
--launch-type FARGATE
Майте трохи часу на розгортання вашого Service ECS. Тепер ви можете перевірити стан вашого Service ECS за допомогою команди ecs-cli ps
.
ecs-cli compose \
--project-name <PROJECT_NAME> \
--cluster <CLUSTER_NAME> \
service ps
Перейшовши до IP-адреси, зазначеної на порту 8080, ви зможете переглянути головну сторінку нашого проєкту, підтверджуючи, що ваше завдання змогло успішно витягнути образ контейнера з реєстру GHCR, використовуючи ваші облікові дані для автентифікації.
Очищення
Припиніть роботу вашого Service ECS за допомогою команди ecs-cli compose service down
.
ecs-cli compose \
--project-name <PROJECT_NAME> \
--cluster <CLUSTER_NAME> \
service down
Видаліть стек AWS CloudFormation, який був створений ecs-cli up
, та пов’язані з ним ресурси за допомогою команди ecs-cli down
:
ecs-cli down --cluster <CLUSTER_NAME>