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
Добавление в #ECR возможности тэгировать репозитории может поломать ваши сценарии, т.к. в #IAM добавилось новое #policy 'ecr:ListTagsForResource':

... error getting ECR repository tags: AccessDeniedException: User: ... is not authorized to perform: ecr:ListTagsForResource ...
#ECR-репозиторий имеет ограничение в 1000 образов максимум. Когда у вас активный процесс разработки, то этот кажущийся большим лимит очень даже быстро достигается и вы получаете много удовольствия от упражнений по изучению логов под названием "ну вчера же работало".

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

Светлая мысль "с этим что-то нужно делать" помноженная на гугление в попытках что-то найти и отсортировать в AWS консоли по работе с ECR докер-образами — очень скоро приведёт вас в уныние. Не расстраивайтесь, это не вы верблюд - там действительно не работает пэйджер (фильтры применяются лишь к одной странице). Пусть вас успокаивает факт, что они страдают точно также.

В общем смысл следующий - нужно настроить ECR LifecyclePolicy. Пишем правила, какие тэги сколько живут и добавляем каждому репозиторию, в результате порядок будет поддерживаться автоматически.

Если репозиторий один, то можно и потыкать ручками, однако если десятки? Тогда используем для этого секретную менюшку Edit JSON (на картинке внизу), откуда можно скопировать натыканное и размножить для других репозиториев.

Тяжело разбираться без примеров, потому вот реально используемый вариант #LifecyclePolicy:

{
"rules": [
{
"action": {
"type": "expire"
},
"selection": {
"countType": "sinceImagePushed",
"countUnit": "days",
"countNumber": 180,
"tagStatus": "tagged",
"tagPrefixList": [
"develop"
]
},
"description": "clean 'develop*' after 180 days",
"rulePriority": 10
},
{
"action": {
"type": "expire"
},
"selection": {
"countType": "sinceImagePushed",
"countUnit": "days",
"countNumber": 180,
"tagStatus": "tagged",
"tagPrefixList": [
"feature"
]
},
"description": "clean 'feature*' after 180 days",
"rulePriority": 20
},
{
"action": {
"type": "expire"
},
"selection": {
"countType": "sinceImagePushed",
"countUnit": "days",
"countNumber": 180,
"tagStatus": "tagged",
"tagPrefixList": [
"hotfix"
]
},
"description": "clean 'hotfix*' after 180 days",
"rulePriority": 30
},
{
"action": {
"type": "expire"
},
"selection": {
"countType": "sinceImagePushed",
"countUnit": "days",
"countNumber": 1,
"tagStatus": "untagged"
},
"description": "clean Untagged after 1 day",
"rulePriority": 40
}
]
}
В дополнение к предыдущему посту по #ECR #LifecyclePolicy - в идеале такое должно быть автоматизировано с помощью #CloudFormation #templates.

Это не всегда реально: например, какой-то старый проект, нельзя пересоздать репозитории. Но если можно пересоздать - чтобы репозиторием рулил CloudFormation или для нового проекта, то это получается реально удобно. Создаём репозитории с помощью шаблона типа:

https://github.com/applerom/cloudformation-examples/blob/master/ecs/ecr-repo.yml

Как видно в шаблоне - LifecyclePolicy прописывается в чистом виде (JSON). Там же для удобства добавлен шаринг для других аккаунтов, что всегда требуется в случае #multi_account_strategy (если не нужен - просто комментируем). Всё легко кастомизируется под свои значения и любимые скрипты.

Если нужно быстро — просто ручками меняем шаблон и запускаем/обновляем стэк. В любом случае это правильней, чем тыкать через консоль, т.к. контролируемо: и через год, и даже не вы, а другой — сможет повторить процесс. В том числе такой подход позволяет выявить Drift — кто чего тут натыкал, пока вас не было.

#всё_под_контролем
Скопировать с ECR-репозитория в другой нельзя ("напрямую" - через какую-то апишку/команду), можно лишь спулить и запушить. Но пилят регион-репликацию:

https://github.com/aws/containers-roadmap/issues/140

Актуально для DR (Disaster Recovery) - ведь при падении региона может упасть и региональный #ECR (такого ещё не было, но это правильный подход).
​​Чтобы расшарить ECR репозиторий (только на чтение - лишь скачать) для всей организации (нужно заменить на свой aws:PrincipalOrgID):

{
 "Version": "2008-10-17",
 "Statement": [
  {
   "Sid": "Organization ReadOnly access",
   "Effect": "Allow",
   "Principal": "*",
   "Action": [
    "ecr:BatchCheckLayerAvailability",
    "ecr:BatchGetImage",
    "ecr:GetDownloadUrlForLayer"
   ],
   "Condition": {
    "StringEquals": {
     "aws:PrincipalOrgID": "o-gs1bsr375"
    }
   }
  }
 ]
}

Данные правила (download only) применяются для других аккаунтов, а для аккаунта, где расположен ECR - регулируется с помощью IAM, которыми можно поставить нужные права (в том числе на upload).

#ECR
​​Когда нужно сделать ECR публичным:

https://github.com/monken/aws-ecr-public

#ECR
​​Если есть строгие правила at-rest шифрования всего используемого, то для Amazon ECR можно использовать свои KMS-ключи (customer master keys):

https://docs.aws.amazon.com/AmazonECR/latest/userguide/encryption-at-rest.html

Если не включать KMS (см. картинку) — шифрование всё равно будет, но лишь серверное (как SSE-S3).

Если включить KMS, но не поставить вторую галку, то будут использоваться дефолтные ключи Амазона (AWS-managed).

Если все галки — нужно будет указать свой ключ для KMS CMK.

Последний вариант добавит пару копеек к стоимости за использование KMS запросов, однако позволит пользоваться ECR из других аккаунтов.

Иначе, если при этом нужно шарить докер-образы из ECR в разные аккаунты — не включайте KMS encryption. Т.е. "средний вариант" (первая галка без второй) — лучше не использовать совсем.

#ECR #KMS
Helm + ECR

Для стандартизации процессов в Kubernetes окружениях, использующих Helm для деплоя сервисов удобно иметь и чарты в виде докер-образов. Такая возможность на текущий момент в Helm доступна лишь в экспериментальном режиме:

export HELM_EXPERIMENTAL_OCI=1

В докер-реестрах других провайдеров такая поддержка уже была раньше, наконец, с сентября 2020-го года она есть и в ECR:

https://docs.aws.amazon.com/AmazonECR/latest/userguide/push-oci-artifact.html

Настроим переменные:

ECR_AWS_ID=123456789012
ECR_REGION=eu-central-1
CHART_DIR=my-chart
REPO_NAME=helm-repo
IMAGE_TAG=build-1

HELM_REGISTRY=${ECR_AWS_ID}.dkr.ecr.${ECR_REGION}.amazonaws.com
HELM_ECR_ADDRESS=${HELM_REGISTRY}/${REPO_NAME}:${IMAGE_TAG}

Сохраняем чарт:

helm chart save ${CHART_DIR} ${HELM_ECR_ADDRESS}

Логинимся Хелмом в реестр (aws-cli version 2):

aws ecr get-login-password --region ${ECR_REGION} | helm registry login --username AWS --password-stdin ${HELM_REGISTRY}

Пушим чарт в ECR:

helm chart push ${HELM_ECR_ADDRESS}

Спулить чарт из ECR:

helm chart pull ${HELM_ECR_ADDRESS}

Распаковать чарт в текущую папку:

helm chart export ${HELM_ECR_ADDRESS}

Распаковать чарт в нужную папку (останется изначально имеющаяся вложенность):

helm chart export ${HELM_ECR_ADDRESS} --destination some-dir

#ECR #Helm
​​ECR Scan Reporter:

https://blog.compose-x.io/posts/automated-ecr-scans-reports-with-ecr-scan-reporter/index.html

ECR Scan Reports being a built-in feature of AWS ECR, which is free, uses Clair, and publishes to EventsBridges events when scans are in progress, failed or complete, we have a very easy integration that allows us to capture and feed into AWS Lambda (or other services).
Also, EventsBridge allowing us to create cronjobs like executions (previously into AWS CloudWatch Events) we could trigger a scan for all the images of all our repositories on a regular basis to ensure that we keep up with the images we previously published.

#ECR #security
Выборочная репликация ECR репозиториев:

https://aws.amazon.com/blogs/containers/using-amazon-ecr-replication-rules-to-optimize-your-application-delivery-process/

Репликация ECR появилась ещё год назад, но была малоприменима, т.к. можно было реплицировать лишь сразу все репозитории в регионе оптом.

И вот теперь, наконец, её можно реально использовать — можно выбирать не только отдельный репозиторий, но и задать маску для билдов, которые будут реплицироваться!

В общем, реально востребованная вещь, многие костыли и велосипеды для различных Disaster Recovery сценариев можно будет выбросить.

#ECR
Кэш для ECR:

https://aws.amazon.com/blogs/aws/announcing-pull-through-cache-repositories-for-amazon-elastic-container-registry/

Теперь можно пулить образы из публичных репозиториев (без авторизации) используя для этого свои приватные ECR. Амазон сам автоматически будет синхронизировать тэги в приватном репозитории с теми, что находятся в публичном источнике.

Ещё один набор велосипедных Лямбд, подтягивающих опенсорсные образы из внешних репозиториев можно заменить на нативный функционал.

#ECR
🆕 Container Image Signing for ECR with AWS Signer:

https://aws.amazon.com/blogs/containers/announcing-container-image-signing-with-aws-signer-and-amazon-eks/

▫️ Using the Notation client with the AWS Signer plugin, you can implement a simple client-based workflow for signing and verifying your container images.
▫️ Using the Kyverno-Notation-AWS Signer solution, you can validate container images in Kubernetes.

#ECR #Signer #EKS
🔥5
​​ECR + OCI v1.1 = добавляем любой файл к образу в ECR

0️⃣ Историческая справка

OCI 1.0 появился в далёком 2017-м. Поддержка OCI 1.0 появилась в ECR в 2020-м:

https://aws.amazon.com/blogs/containers/oci-artifact-support-in-amazon-ecr/

Это позволило добавлять Helm чарты сразу к запушенному в ECR образу.

Релиз OCI v1.1 вышел в начале 2024 г. и теперь он поддерживается ECR:

https://aws.amazon.com/about-aws/whats-new/2024/06/amazon-ecr-oci-image-distribution-version-1-1/

Релиз 1.1 позволяет стандартизированно, без костылей с созданием кучи спамовских тэгов, добавить нужное к любому образу.

Документация по поводу работы с OCI в AWS на момент написания крайне ограниченная:

https://docs.aws.amazon.com/AmazonECR/latest/userguide/images.html

Поэтому в качестве примера добавим к sbom.json и readme.md к образу в ECR. Я буду для этого использовать AWS CloudShell.


1️⃣ Ставим и настраиваем oras:

https://oras.land/docs/installation/

На момент написания CloudShell по-прежнему на Intel (ужас какой), у кого ARM — нужно будет поменять в ссылке скрипта на arm64.

⚠️ Без amazon-ecr-credential-helper он даст ошибку:

Error: basic credential not found

Ставим под вашу систему, в случае CloudShell это обычное:

sudo yum install amazon-ecr-credential-helper

⚠️ Без файла ~/.docker/config.json также будет ошибка:

Error: failed to decode config file at /home/cloudshell-user/.docker/config.json: invalid config format: EOF

Создаём, если такого не было:

mkdir ~/.docker
cat >> ~/.docker/config.json << EOF
{
"credsStore": "ecr-login"
}
EOF

Если уже был, то просто добавляем строчку:

{
"credsStore": "ecr-login",
"auths": {
...


2️⃣ Просмотр файлов у образа в ECR

oras discover 0123456789012.dkr.ecr.us-east-1.amazonaws.com/myrepo:mytag

Получим что-то типа:

0123456789012.dkr.ecr.us-east-1.amazonaws.com/myrepo@sha256:54408c668558c601e7fb564a912343af3edfe5f4f5a1922086a8be87d8f74923

То есть ничего нет.


3️⃣ Добавляем файлы к образу в ECR

oras attach 0123456789012.dkr.ecr.us-east-1.amazonaws.com/myrepo:mytag --artifact-type my/sbom ./sbom.json:application/json

oras attach 0123456789012.dkr.ecr.us-east-1.amazonaws.com/myrepo:mytag --artifact-type my/readme ./readme.md:text/markdown


4️⃣ Смотрим снова

(на картинке)


5️⃣ Получаем файлы из ECR

Сначала нужен digest файла:

oras discover --artifact-type 'my/readme' 0123456789012.dkr.ecr.us-east-1.amazonaws.com/myrepo:mytag --format json | jq -r ".manifests[0].digest"

Теперь получаем сам файл в папку myfiles:

oras pull 0123456789012.dkr.ecr.us-east-1.amazonaws.com/myrepo@sha256:bdd414443ed04e69a09a9eab979d5e3950197341cc8c81a8d9001431685b571f --output myfiles


Итого: хорошая вещь, можно напихать всякого полезного в CI/CD пайплайны на каждый образ, пользуемся.

#ECR
🔥6👍4❤‍🔥1
​​S3 как container registry вместо ECR — в 5-8 раз быстрее и в 4 раза дешевле!

https://ochagavia.nl/blog/using-s3-as-a-container-registry/

#S3 #ECR
🤔44👍8🤪2