惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Know Your Adversary
Know Your Adversary
N
News and Events Feed by Topic
C
CXSECURITY Database RSS Feed - CXSecurity.com
P
Privacy & Cybersecurity Law Blog
P
Privacy International News Feed
Recent Announcements
Recent Announcements
T
Threatpost
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Last Week in AI
Last Week in AI
博客园 - 叶小钗
AWS News Blog
AWS News Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
Cyberwarzone
Cyberwarzone
月光博客
月光博客
The Cloudflare Blog
罗磊的独立博客
P
Palo Alto Networks Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园 - 聂微东
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
T
Tailwind CSS Blog
PCI Perspectives
PCI Perspectives
Forbes - Security
Forbes - Security
Latest news
Latest news
V
Visual Studio Blog
阮一峰的网络日志
阮一峰的网络日志
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
WordPress大学
WordPress大学
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
有赞技术团队
有赞技术团队
N
News and Events Feed by Topic
爱范儿
爱范儿
L
Lohrmann on Cybersecurity
Cisco Talos Blog
Cisco Talos Blog
I
Intezer
S
Secure Thoughts
Hacker News: Ask HN
Hacker News: Ask HN
C
CERT Recently Published Vulnerability Notes
TaoSecurity Blog
TaoSecurity Blog
博客园 - 司徒正美
Google DeepMind News
Google DeepMind News
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Google Online Security Blog
Google Online Security Blog
H
Hacker News: Front Page
Recent Commits to openclaw:main
Recent Commits to openclaw:main
V2EX - 技术
V2EX - 技术
Microsoft Azure Blog
Microsoft Azure Blog
O
OpenAI News
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Webroot Blog
Webroot Blog

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Как мы перестали толкать и начали тянуть(AWS ECR)
stroitskiy · 2026-06-20 · via Все публикации подряд на Хабре

Средний

7 мин

0

Вместо вступления

Хочу рассказать про несколько новых возможностей AWS Elastic Container Registry (ECR), о которых, как мне кажеться знают немного.

Когда мы только начали использовать ECR, это был совсем простой сервис: настроил репозиторий, положил туда образ - и забыл. Но каждый раз, возвращаясь к документации по очередному поводу, я обнаруживал, что функциональности там стало заметно больше, чем в прошлый раз. В какой-то момент этих «незамеченных» фич накопилось достаточно, чтобы пересобрать всю нашу схему хранения образов. Об этом и статья.

Инцидент

Наши сервисы спокойно жили в 20 регионах AWS - ровно до очередного инцидента в us-east-1. Подробную хронологию(да это было аж в 2021 году, как летит время!) можно почитать в официальном разборе AWS: https://aws.amazon.com/message/12721/. Если коротко: из-за сетевых проблем в ключевом регионе посыпалось много чего. Нас это почти не задело(мы же распределенные!) - кроме одного маленького нюанса: примерно на час ECR API перестал авторизовать запросы из всех регионов кроме us-east-1. А наши образы в тот момент хранились только в us-east-1.

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

Полистав документацию, мы включили Cross-Region Replication во всех регионах. Сработало? Да, надёжность выросла. Но вместе с ней мы получили три новые проблемы.

Гидра

У такого решения есть своя цена. В нашем случае она сложилась из трёх сложностей.

1. Синхронизация

Репозиторий-реплика появляется в регионе только после первого успешного пуша (replication event). То есть старые образы в новых регионах-репликах попросту недоступны, пока нет события типа push в главном репозитории.

Звучит безобидно, но по факту:

  • случайно удалили не тот образ - сам он не восстановится, и это простой в регионе(outage);

  • завели новый регион - он стоит пустой, пока мы не сделаем пуш свежего (или старого) образа в вышестоящий регион, и если нужен ролбек- откатываться некуда, ведь старых версий не было, и это тоже простой в регионе(outage);

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

2. Деньги

Репликация в 20 регионов - это стоимость хранения, умноженная на 20. А количество образов растёт практически экспоненциально.

В качестве лекарства Amazon предлагает lifecycle (cleanup) policy, но правила там довольно грубые: можно «хранить последние N образов» или «удалять всё старше X дней / без тегов» - и почти ничего сверх этого. Представьте: разработчики гоняют хотфикс, проблема решается не сразу - и вот в репозитории уже два десятка новых образов, причём с релизными тегами(проблема у них, понимаешь, воспроизводиться только на проде!). А дальше такая политика спокойно удаляет образ, который крутится в проде - просто потому, что ему не повезло оказаться 21-м по счёту и старше 14 дней.

Неудивительно, что соответствующий запрос на фичу собрал в роадмапе AWS Containers больше 600 голосов. Правда, на реализацию у AWS ушло около пяти лет - почему так долго и почему именно в таком виде, судить не берусь. Нам же оставалось только упражняться в написании достаточно хитрых политик, а для критичных сервисов - и вовсе отключать их.

3. Автоматизация

И, наконец, ложка дёгтя для тех, кто живёт в IaC:

  • Terraform не может применить aws_ecr_lifecycle_policy к репозиторию, которого ещё нет в регионе-реплике.

  • А репозиторий-реплика, как мы помним, появляется только после первого пуша.

В итоге деплой нового сервиса распадается на зависимые шаги: terraform apply для репозитория и его реплик → запуск пайплайна и сборка+пуш билда → ожидание репликации → terraform apply для политик очистки. Костыль, конечно, всегда можно прикрутить - но мы любим избегать нестандартных практик там, где это возможно.

Решение: Декларативный принцип

И вот однажды, обсуждая совсем другую тему - задержки и лимиты при стягивании образов с Docker Hub, - мы снова вернулись к теме репликации и решили присмотреться к Pull-Through Cache.

Ранее эта фича работала только для публичных апстримов (Docker Hub, ECR Public и подобных), и для нашей задачи была бесполезна. Но в 2025 году появилась возможность использовать в качестве апстрима приватный ECR. И тут до нас дошло: вместо того чтобы заранее реплицировать образы во все 20 регионов, надо просто стягивать их по требованию. Это же классическая дилемма проектирования - Push model против Pull model, - правда, раньше нам нечем было эту дилему решить.

Идея была использовать сразу две новые фичи: Pull-Through Cache + Repository Creation Templates.

Пример реализации

1. Pull-Through Cache

Декларативный принцип в чистом виде: больше не нужно пушить всё и везде заранее. Если ноде в каком-то регионе понадобился образ - она его запрашивает, а ECR сам сходит в апстрим, заберёт образ и закэширует его локально. Никто ничего не реплицирует «на всякий случай».

Нам надо просто объяснить ECR в новом регионе (например, eu-central-1): что если кто-то просит образ из нашего приватного us-east-1 реестра - не надо отдавать 404, надо сходить в апстрим и забрать его.

resource "aws_ecr_pull_through_cache_rule" "main"
 {
  ecr_repository_prefix = "ROOT"
  upstream_registry_url = "111111111111.dkr.ecr.us-east-1.amazonaws.com"
}

После этого команда с другим регионом внутри адреса магически работает, даже если репозитория upstream-prod/my-service в eu-central-1 никогда не существовало.

docker pull 111111111111.dkr.ecr.eu-central-1.amazonaws.com/upstream-prod/my-service:v1

Под капотом вместо того чтобы сразу выдать вам ошибку, ECR проверяет свои настройки кэширования и видит правило которое говорит, что за любыми неизвестными образами надо идти в "111111111111.dkr.ecr.us-east-1.amazonaws.com". Причем это работает и с другими аккаунтами(но там понадобиться создать IAM-роль).
Например, если за билды отвечает отдельная команда и она все образы складывает в центральный регион своего аккаунта, то ваш сервис может с помощью этой фичи стянуть этот образ в свой аккаунт и регион.
Интересно, что указывая несуществующий адрес образа с eu-central-1 внутри мы просто говорим ECR, в каком регионе он должен обработать запрос, а не указываем конкретный адрес.

Есть и более продвинутые возможности - например, если один и тот же образ лежит в разных регистри (dockerhub, quay.io) и вы хотите на стороне деплоймента регулировать, откуда загрузить образ в регион, можно использовать ecr_repository_prefix, отличный от ROOT.

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

2. Repository Creation Templates

Но это еще не все!
У ленивого создания репозиториев есть свои недостатки: созданный Амазоном «на лету» репозиторий пустой - без шифрования, без тегов, без lifecycle-политик.
Repository Creation Templates закрывают этот пробел. Мы один раз описываем шаблон для префикса (например, upstream-prod/*) - и при первом же обращении по этому пути AWS не только создаёт репозиторий автоматически, но и сразу накатывает на него весь нужный конфиг. Настроил один раз - и забыл.
Теперь говорим AWS: «Каждый раз, когда Pull-Through Cache создаёт репозиторий с префиксом upstream-prod, примени к нему вот этот конфиг» - зашифруй ключом KMS, повесь тег ManagedBy и удаляй всё старше 14 дней.

resource "aws_ecr_repository_creation_template" "template" {
  prefix      = "upstream-prod"
  description = "Auto-config for pull-through cached repos"

  applied_for = ["PULL_THROUGH_CACHE"]   # Обязательный аргумент: к каким действиям применяется шаблон

  custom_role_arn = "arn:aws:iam::111111111111:role/ecr-template"

  encryption_configuration {
    encryption_type = "KMS"
    kms_key         = "arn:aws:kms:eu-central-1:111111111111:key/some-key-123"
  }

  resource_tags = {
    ManagedBy = "Me"
  }

  lifecycle_policy = jsonencode({
    rules = [{
      rulePriority = 1
      description  = "Dumb cleanup"
      selection = {
        tagStatus   = "any"
        countType   = "sinceImagePushed"
        countUnit   = "days"
        countNumber = 14
      }
      action = { type = "expire" }
    }]
  })
}

Внимательный читатель дочитавший до сюда скажет:
 — Падажите! А как это решает изначально описанную проблемму с одним центральным регионом? Да, теперь у вас есть образы и локально, но если в каком‑то регионе сервиса не было, а потом его запустили, то контейнеры уже и не стартанут, ведь регион с апстрим репозиторием отвалился!

Да, это правда, но во‑первых у нас теперь есть требуемые образы во всех регионах, и контейнеры могут скейлиться, а во вторых мы можем оперативно поменять апстрим в `aws_ecr_pull_through_cache_rule.main.upstream_registry_url` если регион прилег надолго, что кстати вот недавно случилось с регионом в ОАЭ(а у нас такой риск был помечен как очень маловероятный!).

Итог

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

  • Нужен образ в регионе Сан-Паулу? Просто docker pull. Disaster recovery из коробки: образы доступны везде, где они реально нужны, а не там, куда мы заранее догадались их положить.

  • Образ устарел? Политика тихо его удалит. И можно не бояться что продакшен сломаеться!

  • Образ снова понадобился через год? Снова docker pull - и он опять здесь.

  • Zero-touch management. Настроил шаблоны - и забыл; новые сервисы заводятся сами.

  • Платим только за то, что действительно используется в регионе (кэш), а не за копию всего архива × 20.

Больше никаких многократных terraform apply для каждого нового микросервиса в каждом из 20 регионов!

И, пожалуй, главный урок: иногда лучшее решение проблемы синхронизации - это избавиться от синхронизации!

Бонус для тех, кто дочитал:
Автор ужасный зануда, и ему нравится AWS ECR, но ещё больше ему нравится производительность команды AWS ECR. За год, который прошёл с момента написания черновика этой статьи, они выпустили ещё больше крутых фич, которые сделают многим жизнь с образами легче:

  • Archive storage class + архивирование по last-pull-time. Фича которую мы ждали очень долго, я упоминал по ссылке про ишью на GitHub, но реализовали они это через двойное правило сначала правило sinceImagePulled и архивация, потом sinceImageTransitioned и там уже можно указать expired. Они утверждали что метрика sinceImagePulled не надежна, потому они перестраховываються. Ещё нюанс: в архиве образ обязан пролежать минимум 90 дней, прежде чем его можно удалить, что тоже стоит денег.

  • Cross-repository layer sharing (blob mounting) - шаринг слоев между репозиториями, экономия денег.

  • CREATE_ON_PUSH - Автосоздание репозитория на push. Тоже может быть полезно, шаблоны в том числе применяются и на репозиторий созданный так.

  • Pull-through cache: синк referrers - теперь вместе с образом автоматически подтягиваются подписи, SBOM и attestations из апстрима

  • Managed image signing - управляемая подпись образов без своей инфраструктуры подписи

  • Pull-through для Chainguard - Chainguard-реестр как upstream

  • И всякие мелочи типа поддержки IPv6 и новые метрики для подсчета репозиториев и образов

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