Aws ecs fargate ResourceInitializationError: невозможно получить секреты или аутентификацию реестра
Я пытаюсь запустить частный репозиторий на платформе aws-ecs-fargate-1.4.0.
Для аутентификации в частном репозитории я следил за документами, и это работало хорошо.
Как-то после обновления существующей службы много раз она не запускает задачу и жалуется на ошибку, например
ResourceInitializationError: unable to pull secrets or registry auth: execution resource retrieval failed: unable to get registry auth from asm: service call has been retried 1 time(s): asm fetching secret from the service for <secretname>: RequestError: ...
Я не менял ecsTaskExecutionRole
и он содержит все необходимые политики для получения секретного значения.
- AmazonECSTaskExecutionRolePolicy
- CloudWatchFullAccess
- AmazonECSTaskExecutionRolePolicy
- GetSecretValue
- GetSSMParamters
35 ответов
Сотрудник AWS здесь.
То, что вы видите, связано с изменением работы сети между платформой Fargate версии 1.3.0 и платформой Fargate версии 1.4.0. В рамках перехода от использования Docker к использованию containerd мы также внесли некоторые изменения в работу сети. В версии 1.3.0 и ниже каждая задача Fargate получила два сетевых интерфейса:
- Один сетевой интерфейс использовался для трафика приложения из контейнера (ов) вашего приложения, а также для журналов и извлечения уровня изображения контейнера.
- Вторичный сетевой интерфейс использовался самой платформой Fargate для получения учетных данных ECR-аутентификации и получения секретов.
Однако у этого вторичного сетевого интерфейса были некоторые недостатки. Этот вторичный трафик не отображался в журналах потоков VPC. Кроме того, хотя большая часть трафика оставалась в клиентском VPC, вторичный сетевой интерфейс отправлял трафик за пределы вашего VPC. Ряд клиентов жаловались, что у них нет возможности указать элементы управления на уровне сети на этом дополнительном сетевом интерфейсе и на то, к чему он может подключаться.
Чтобы сделать сетевую модель менее запутанной и предоставить клиентам больший контроль, мы изменили в платформе Fargate версии 1.4.0 использование единого сетевого интерфейса и сохранение всего трафика внутри вашего VPC, даже трафика платформы Fargate. Трафик платформы Fargate для получения ECR-аутентификации и секретов задач теперь использует тот же сетевой интерфейс задачи, что и остальной трафик вашей задачи, и вы можете наблюдать за этим трафиком в журналах потоков VPC и контролировать этот трафик с помощью таблицы маршрутизации в вашем собственном AWS VPC. .
Однако благодаря этой расширенной возможности наблюдения и управления сетью платформы Fargate вы также берете на себя ответственность за то, чтобы в вашем VPC действительно был настроен сетевой путь, который позволяет задаче взаимодействовать с ECR и AWS Secrets Manager.
Есть несколько способов решить эту проблему:
- Запускать задачи в общедоступной подсети с общедоступным IP-адресом, чтобы они могли связываться с ECR и другими вспомогательными службами через интернет-шлюз.
- Запускать задачи в частной подсети с таблицей маршрутизации VPC, настроенной для маршрутизации исходящего трафика через шлюз NAT в общедоступной подсети. Таким образом, шлюз NAT может открыть соединение с ECR от имени задачи.
- Запускайте задачи в частной подсети и убедитесь, что в вашем VPC настроены конечные точки AWS PrivateLink для необходимых вам сервисов (ECR для аутентификации по запросу, S3 для слоев изображений и AWS Secrets Manager для секретов).
Вы можете узнать больше об этом изменении в этом официальном блоге, в разделе «Эластичный сетевой интерфейс задачи (ENI) теперь запускает дополнительные потоки трафика».
https://aws.amazon.com/blogs/containers/aws-fargate-launches-platform-version-1-4/
Я не совсем уверен в вашей настройке, но после того, как я отключил NAT-шлюзы, чтобы сэкономить немного долларов, у меня появилось очень похожее сообщение об ошибке на платформе aws-ecs-fargate-1.4.0:
Stopped reason: ResourceInitializationError: unable to pull secrets or registry auth: execution resource retrieval failed: unable to retrieve ecr registry auth: service call has been retried 1 time(s): RequestError: send request failed caused by: Post https://api.ecr....
Оказалось, что мне пришлось создать конечные точки VPC для этих имен служб:
- com.amazonaws.REGION.s3
- com.amazonaws.REGION.ecr.dkr
- com.amazonaws.REGION.ecr.api
- com.amazonaws.REGION.logs
- com.amazonaws.REGION.ssm
И мне пришлось перейти на платформу aws-ecs-fargate-1.3.0. После перехода на более раннюю версию образы Docker можно было извлечь из ECR, и развертывания снова прошли успешно.
Если вы используете секретный менеджер без NAT-шлюза, возможно, вам придется создать конечную точку VPC для com.amazonaws.REGION.secretsmanager
.
Эта ошибка может произойти, если вы используете общедоступную подсеть и выбираете «Не назначать общедоступный адрес» .
То же самое применимо, если у вас есть частная подсеть и нет интернет-шлюза или шлюза NAT в вашем VPC. Ему нужен путь в Интернет.
Это одинаковое поведение во всей экосистеме AWS. Было бы здорово, если бы в таких случаях AWS отображал большой баннер с предупреждением.
Обеспечьте подключение к Интернету через IGW
или NAT
и убедитесь, что общедоступный IP-адрес включен, если его IGW находится в конфигурации сети Fargate Task/Service.
{
"awsvpcConfiguration": {
"subnets": ["string", ...],
"securityGroups": ["string", ...],
"assignPublicIp": "ENABLED"|"DISABLED"
}
}
Эта ошибка возникает, когда агенту Fargate не удается создать или загрузить ресурсы, необходимые для запуска контейнера, или если задача принадлежит. Эта ошибка возникает только при использовании платформы версии 1.4 или более поздней, скорее всего, потому, что версия 1.4 использует Task ENI (который находится в вашем VPC) вместо Fargate ENI (который находится в VPC AWS). Я думаю, это может быть вызвано некоторой потребностью в дополнительных разрешениях IAM, необходимых для извлечения изображения из ECR. Вы используете какую-нибудь приватную ссылку? Если да, вы можете ознакомиться с политиками для конечной точки ECR.
Я попытаюсь воспроизвести это, но я предлагаю открыть заявку в службу поддержки с AWS, если вы можете, чтобы они могли внимательнее изучить ваши ресурсы и лучше предложить.
У меня возникла эта проблема после перевода моего файла Cloudformation в файл Terraform.
После борьбы я обнаружил, что мне не хватает исходящего правила в моей группе безопасности fargate. Действительно, AWS автоматически создает правило «РАЗРЕШИТЬ ВСЕ», но terraform отключает его. Вам нужно добавить в свой
aws_security_group
:
resource "aws_security_group" "example" {
# ... other configuration ...
egress = [
{
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
]
}
Вы можете проверить документ здесь .
Поскольку агент ECS в FARGATE версии 1.4.0 использует задачу ENI для получения информации, запрос к диспетчеру секретов будет проходить через этот eni.
Вы должны убедиться, что трафик к API секретного менеджера (secretsmanager.{Region}.amazonaws.com) открыт:
если ваша задача является частной, у вас должна быть либо конечная точка vpc (com.amazonaws.{region}.secretsmanager), либо шлюз NAT, а группа безопасности ENI задачи должна разрешать для нее исходящий трафик https.
если ваша задача является общедоступной, группа безопасности должна разрешить исходящий трафик https на внешний (или общедоступные cidrs AWS).
в моем случае я пробовал все вышеперечисленные решения, и ни одно из них не работало. это была очень простая ошибка, но она может оказаться полезной для других, если ни один из ответов не сработает для вас.
в
containerDefinition
Часть JSON-файла определения задачи должна быть в конце значения.
то есть в моем случае:
{
"containerDefinitions": [{
"secrets": [{
"name": "MY_SECRET",
"valueFrom": "arn:aws:secretsmanager:<region>:<aws_account_id>:secret:<sm_resource_name>:MY_SECRET"
}]
}]
}
правильный формат был:
{
"containerDefinitions": [{
"secrets": [{
"name": "MY_SECRET",
"valueFrom": "arn:aws:secretsmanager:<region>:<aws_account_id>:secret:<sm_resource_name>:MY_SECRET::"
}]
}]
}
обратите внимание на дополнительные
::
в конце правильное решение
valueFrom
.
Перейдите в раздел «Определения задач» > «Обновить определение задачи». В раскрывающемся списке «Роль задачи» выберите .
Вам нужно изменить это
ecsTaskExecutionRole
в настройках IAM включить следующие разрешения:
- SecretsManagerЧтениеЗапись
- CloudWatchFullAccess
- AmazonSSMFПолный доступ
- AmazonECSTaskExecutionRolePolicy
Затем создайте новое определение задачи, и оно должно работать.
Новая карта подключений VPC очень помогает в решении этой проблемы. Убедитесь, что в ваших общедоступных подсетях есть маршрут к интернет-шлюзу. Ваша конфигурация должна выглядеть примерно так:
Если это не так, вам придется изменить или добавить таблицу маршрутизации .
хотя бы одна подсеть может подключаться к интернет-шлюзу.
Это необходимо для того, чтобы ECS мог извлечь изображение из общедоступного URL-адреса.
Группе безопасности службы необходим исходящий доступ на порт 443 (для этого подойдет исходящий доступ на всех портах). Без этого он не может получить доступ к Secrets Manager.
Возможно, ваша проблема в том, что вы не назначили публичный IP-адрес своему кластеру.
включите его при создании задачи в кластере.
Автоматическое назначение общедоступного IP-адреса = TRUE
Я решил это, установив «Назначить общедоступный IP-адрес» = ВКЛЮЧЕНО в моем определении задания.
Сегодня это меня достаточно сильно обожгло, и я решил поделиться своим опытом, поскольку он отличается от большинства вышеперечисленных (ответ AWS Employee покрывает это технически, но не описывает проблему).
Если все следующее верно:
- Вы используете платформу 1.4.0 (или, предположительно, новее - на момент написания, 1.4.0 является последней)
- Вы находитесь в среде VPC
- Ваш VPC по « причинам » использует собственный DNS (то есть не на VPC_BASE + 2).
- По « причинам » вы не разрешаете весь исходящий трафик, поэтому вы устанавливаете правила выхода для своей группы безопасности задач.
И, следовательно, у вас есть конечные точки для всех вещей, тогда также должно выполняться следующее:
- Ваш доморощенный DNS должен будет правильно разрешать частные адреса конечных точек (например, используя VPC_BASE+2, но как это не имеет значения)
- Вам также необходимо убедиться, что в вашей группе безопасности есть правила, разрешающие DNS-трафик на ваш DNS-сервер (-ы) <- Этот меня сжег.
Чтобы добавить оскорбления к травме, та небольшая информация об ошибке, которую вы получаете от Fargate, на самом деле не указывает на то, что у вас проблема с DNS, и, естественно, ваш CloudTrails тоже не будет показывать ни черта, поскольку в конечном итоге ничего не попадает в API, чтобы начать с участием.
В основном это должно быть связано с ограничением исходящего трафика в ваших группах безопасности (в случае общедоступной подсети).
Открытие TCP-порта поможет вам решить эту проблему.
ResourceInitializationError: невозможно получить секреты или аутентификацию реестра: не удалось получить ресурс выполнения: невозможно получить аутентификацию реестра ECR
Как сделать «Запуск задач в частной подсети, в которой есть таблица маршрутизации VPC, настроенная на маршрутизацию исходящего трафика через шлюз NAT в общедоступной подсети. Таким образом, шлюз NAT может открыть соединение с ECR от имени задачи»:
Предположения этого решения:
- У вас есть образ докера в репозитории ECR
- У вас есть роль IAM с разрешениями AmazonECSTaskExecutionRolePolicy
- Вы также хотите, чтобы ваша задача использовала тот же IP-адрес. Я отметил это необязательным, если вам не нужна эта часть.
Решение:
- Создать новый кластер
- AWS > ECS > Кластеры > Создать кластер > Только сеть > установите флажок для создания VPC > Создать
- Создать новое определение задачи
- AWS > ECS > Определения задач > Создать новое определение задачи > Fargate
- Поле «Добавить контейнер» > «Изображение*» должно содержать URI изображения из ECR.
- AWS > ECS > Определения задач > Создать новое определение задачи > Fargate
- Создайте эластичный IP-адрес (НЕОБЯЗАТЕЛЬНО, ТОЛЬКО ЕСЛИ ВЫ ХОТИТЕ ПОСТОЯННЫЙ ВЫВОД IP, КАК ПРИ ИСПОЛЬЗОВАНИИ ПРОКСИ-СЛУЖБЫ)
- AWS > VPC > Эластичные IP-адреса > Выделить эластичный IP-адрес > Создать
- Внесите этот IP-адрес в белый список любого сервиса, к которому Фаргейт попытается получить доступ
- Создать NAT-шлюз
- AWS > VPC > Шлюзы NAT > Создать шлюз NAT
- Выберите автоматически созданную подсеть
- Тип подключения: общедоступный
- ^ Поскольку вы сделали его общедоступным в подсети, это означает «шлюз NAT в общедоступной подсети».
- (НЕОБЯЗАТЕЛЬНО) Выберите Elastic IP из раскрывающегося списка.
- AWS > VPC > Шлюзы NAT > Создать шлюз NAT
- Маршрутизация общедоступных подсетей для использования интернет-шлюза
- AWS> VPC> Таблицы маршрутов> найдите одну с общедоступными подсетями, автоматически созданными на шаге 1> щелкните идентификатор таблицы маршрутов> Изменить маршруты> Добавить маршрут> Пункт назначения — 0.0.0.0/0, Цель — igw-{internet-gateway-autocreated-в шаге-1}
- ^ Это то, что позволяет VPC вообще получать доступ к Интернету.
- Создать подсеть
- AWS> VPC> Subnets> Create subnet> выберите автоматически созданный VPC на шаге 1, для IPv4, если вы запутались, просто введите 10.0.0.0/24> Add new subnet
- Направьте вновь созданную подсеть (на шаге 6) для использования NAT
- AWS> VPC> Таблицы маршрутов> найдите одну с подсетью, созданную на шаге 6> щелкните идентификатор таблицы маршрутов> Изменить маршруты> Добавить маршрут> Пункт назначения: 0.0.0.0/0, Цель: nat-{nat-gateway-created-in- шаг-4}
- ^ Это то, что подразумевается под «частной подсетью, в которой есть таблица маршрутизации VPC, настроенная для маршрутизации исходящего трафика через шлюз NAT».
- Запустить задачу Fargate
- AWS > ECS > Кластеры > ваш кластер > Запустить новую задачу
- Тип запуска: Фаргейт
- Определение задачи: ваша задача
- Кластер: ваш кластер
- Кластер VPC: ваш VPC
- Подсеть: подсеть, созданная вами, а НЕ автоматически созданная.
- Автоматическое назначение общедоступного IP-адреса: это зависит от того, используете ли вы эластичный IP-адрес. Если вы это сделали, то это должно быть отключено. Если вы не выделили эластичный IP-адрес, то его следует включить.
- Запустить задачу
У меня была эта проблема, и в конце концов я разобрался с ней.
Мое решение ниже:
- Настройте ECS в частной подсети
- Добавить конечные точки AWS PrivateLink в VPC
Разместите здесь мой код CDK для справки. Я вставил ссылки на документацию в комментарии к функциям, чтобы вы могли лучше понять ее назначение.
Это EcsStack:
export class EcsStack extends Stack {
constructor(scope: cdk.App, id: string, props: EcsStackProps) {
super(scope, id, props);
this.createOrderServiceCluster(props.vpc);
}
private createOrderServiceCluster(serviceVpc:ec2.IVpc) {
const ecsClusterName = "EcsClusterOfOrderService";
const OrderServiceCluster = new ecs.Cluster(this, ecsClusterName, {
vpc: serviceVpc,
clusterName: ecsClusterName
});
// Now ApplicationLoadBalancedFargateService just pick a randeom private subnet.
// https://github.com/aws/aws-cdk/issues/8621
new ecs_patterns.ApplicationLoadBalancedFargateService(this, "FargateOfOrderService", {
cluster: OrderServiceCluster, // Required
cpu: 512, // Default is 256
desiredCount: 1, // Default is 1
taskImageOptions: {
image: ecs.ContainerImage.fromRegistry("12345.dkr.ecr.us-east-1.amazonaws.com/comics:user-service"),
taskRole: this.createEcsTaskRole(),
executionRole: this.createEcsExecutionRole(),
containerPort: 8080
},
memoryLimitMiB: 2048, // Default is 512
// creates a public-facing load balancer that we will be able to call
// from curl or our web browser. This load balancer will forward calls
// to our container on port 8080 running inside of our ECS service.
publicLoadBalancer: true // Default is false
});
}
/**
* This IAM role is the set of permissions provided to the ECS Service Team to execute ECS Tasks on your behalf.
* It is NOT the permissions your application will have while executing.
* https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_execution_IAM_role.html
* @private
*/
private createEcsExecutionRole() : iam.IRole {
const ecsExecutionRole = new iam.Role(this, 'EcsExecutionRole', {
//assumedBy: new iam.ServicePrincipal(ecsTasksServicePrincipal),
assumedBy: new iam.ServicePrincipal("ecs-tasks.amazonaws.com"),
roleName: "EcsExecutionRole",
});
ecsExecutionRole.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonEC2ContainerRegistryReadOnly'));
ecsExecutionRole.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('CloudWatchLogsFullAccess'));
return ecsExecutionRole;
}
/**
* Creates the IAM role (with all the required permissions) which will be used by the ECS tasks.
* https://docs.aws.amazon.com/AmazonECS/latest/developerguide/instance_IAM_role.html
* @private
*/
private createEcsTaskRole(): iam.IRole {
const ecsTaskRole = new iam.Role(this, 'OrderServiceEcsTaskRole', {
//assumedBy: new iam.ServicePrincipal(ecsTasksServicePrincipal),
assumedBy: new iam.ServicePrincipal("ecs-tasks.amazonaws.com"),
roleName: "OrderServiceEcsTaskRole",
});
ecsTaskRole.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonEC2ContainerRegistryReadOnly'));
ecsTaskRole.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('CloudWatchLogsFullAccess'));
ecsTaskRole.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonS3ReadOnlyAccess'));
return ecsTaskRole;
}
}
Это фрагмент кода VpcStack:
export class VpcStack extends Stack {
readonly coreVpc : ec2.Vpc;
constructor(scope: cdk.App, id: string) {
super(scope, id);
this.coreVpc = new ec2.Vpc(this, "CoreVpc", {
cidr: '10.0.0.0/16',
natGateways: 1,
enableDnsHostnames: true,
enableDnsSupport: true,
maxAzs: 3,
subnetConfiguration: [
{
cidrMask: 28,
name: 'Public',
subnetType: ec2.SubnetType.PUBLIC,
},
{
cidrMask: 24,
name: 'Private',
subnetType: ec2.SubnetType.PRIVATE,
}
]
});
this.setupInterfaceVpcEndpoints();
}
/**
* Builds VPC endpoints to access AWS services without using NAT Gateway.
* @private
*/
private setupInterfaceVpcEndpoints(): void {
// Allow ECS to pull Docker images without using NAT Gateway
// https://docs.aws.amazon.com/AmazonECR/latest/userguide/vpc-endpoints.html
this.addInterfaceEndpoint("ECRDockerEndpoint", ec2.InterfaceVpcEndpointAwsService.ECR_DOCKER);
this.addInterfaceEndpoint("ECREndpoint", ec2.InterfaceVpcEndpointAwsService.ECR);
this.addInterfaceEndpoint("SecretManagerEndpoint", ec2.InterfaceVpcEndpointAwsService.SECRETS_MANAGER);
this.addInterfaceEndpoint("CloudWatchEndpoint", ec2.InterfaceVpcEndpointAwsService.CLOUDWATCH);
this.addInterfaceEndpoint("CloudWatchLogsEndpoint", ec2.InterfaceVpcEndpointAwsService.CLOUDWATCH_LOGS);
this.addInterfaceEndpoint("CloudWatchEventsEndpoint", ec2.InterfaceVpcEndpointAwsService.CLOUDWATCH_EVENTS);
this.addInterfaceEndpoint("SSMEndpoint", ec2.InterfaceVpcEndpointAwsService.SSM);
}
private addInterfaceEndpoint(name: string, awsService: ec2.InterfaceVpcEndpointAwsService): void {
const endpoint: ec2.InterfaceVpcEndpoint = this.coreVpc.addInterfaceEndpoint(`${name}`, {
service: awsService
});
endpoint.connections.allowFrom(ec2.Peer.ipv4(this.coreVpc.vpcCidrBlock), endpoint.connections.defaultPort!);
}
}
У меня была такая же проблема с использованием Fargate в качестве типа запуска с версией платформы. 1.4.0
. В конце концов, поскольку я использовал общедоступные подсети, все, что мне нужно было сделать, это разрешить назначение общедоступного IP-адреса задачам, чтобы позволить задаче иметь доступ к исходящей сети для получения изображения.
Я получил подсказку, как решить эту проблему, когда попытался создать сервис с использованием версии платформы 1.3.0
и создание задачи не удалось из-за аналогичной, но, к счастью, задокументированной ошибки.
У меня такая же проблема, потому что я не включил публичный IP. После того, как я включил его, мой сервис был развернут без проблем.
Я решил аналогичную проблему, обновив правила в группе безопасности ECS Service. Ниже конфигурация правил.
Inbound Rules:
* HTTP TCP 80 0.0.0.0/0
Outbound Rules:
* All traffic All All 0.0.0.0/0
Если вы размещаете задачи в частной подсети, вам может потребоваться добавить правила для входящего и исходящего трафика, чтобы разрешить трафик в связанный ACL.
Для меня у меня есть VPC с общедоступными и частными подсетями и шлюзом nat между общедоступными и частными подсетями. Когда я пытался получить доступ к секретам, сервис должен был запускаться в частных подсетях. Секретное извлечение не работает в общедоступных подсетях, если вы не настроили конечные точки vpc. Отлично работает в частных подсетях с версией Fargate 1.4.
Спасибо за решения, у меня была та же проблема, и ответ правильный, что это происходит из-за различий в Fargate v1.3 и v1.4, поэтому это может быть немного беспокойно, но это работает. [1]: /questions/50676337/aws-ecs-fargate-resourceinitializationerror-nevozmozhno-poluchit-sekretyi-ili-au/61252448#61252448
для меня это было комбинацией того, что к моей роли IAM не была привязана политика secretmanagerreadwrite (спасибо Jinkko); И отсутствие общедоступного IP-адреса на вычислительном экземпляре (для доступа к репозиторию ECR)
После проверки всего на этой странице поддержки AWS: https://aws.amazon.com/premiumsupport/knowledge-center/ecs-unable-to-pull-secrets/ и других популярных ответов здесь, еще одна вещь, которую нужно проверить, это то, что ваш Секрет, который извлекается, действительно имеет установленное значение.
При использовании диспетчера секретов, если ваша задача ECS пытается получить секрет, который был создан , но не имеет установленного значения , вы также получите ошибку такого рода.
Установка значения секрета решит эту конкретную проблему.
Для меня проблема возникла после того, как я добавил свой собственный VPC и подсеть в соответствии с этим шаблоном https://github.com/thombergs/code-examples/blob/master/aws/cloudformation/ecs-in-two-public-subnets/network.yml
Но мне также пришлось добавить интернет-шлюз, чтобы он заработал. В конфигурации выше это сразу после конфигурации подсети.
ECS выдает ту же ошибку, когда в URI изображения есть опечатка, что странно... но может кому-то помочь. Наверняка съел пару моих часов. Ваше здоровье!
в
ecsTaskExecutionRole => ECS-SecretsManager-Permission policy
убедитесь, что ваш региональный секрет добавлен с правильным уровнем доступа. Иногда, если вы работаете с мультирегиональной установкой с секретом, созданным в одном регионе, а затем клонированным в другой регион , вам все равно нужно добавить его в ecsTaskExecutionRole => ECS-SecretsManager-Permission, чтобы сделать его доступным для вашей региональной ECS.