如何让我的 ECS 任务提取我的 ECR 映像

如何让我的 ECS 任务提取我的 ECR 映像

我正在尝试创建 ECS 任务并能够访问和提取 ECR,但出现错误。我该如何解决这个问题?

原始错误:

Cannotpullcontainererror: pull image manifest has been retried 1 time(s): failed to resolve ref {accId}.dkr.ecr.us-east-1.amazonaws.com/test-container:latest: {accId}.dkr.ecr.us-east-1.amazonaws.com/test-container:latest: not found

AWSTemplateFormatVersion:'2010-09-09' 描述:'ECS 服务、集群和 ECR'

Resources:
  # ECR repository
  EcrRepository:
    Type: 'AWS::ECR::Repository'
    Properties:
      RepositoryName: 'test-container'
  # ECS cluster
  EcsCluster:
    Type: 'AWS::ECS::Cluster'
    Properties:
      ClusterName: 'test'
  # IAM role for ECS task
  EcsTaskRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: 'Allow'
            Principal:
              Service:
                - 'ecs-tasks.amazonaws.com'
            Action:
              - 'sts:AssumeRole'
      Path: '/'
      Policies:
        - PolicyName: 'test_task_policy'
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: 'Allow'
                Action:
                  - 'ecr:*'
                Resource: '*'
              - Effect: 'Allow'
                Action:
                  - 'logs:CreateLogGroup'
                  - 'logs:CreateLogStream'
                  - 'logs:PutLogEvents'
                Resource: 'arn:aws:logs:*:*:*'
              - Effect: 'Allow'
                Action:
                  - 'lambda:InvokeFunction'
                  - 'lambda:GetFunction'
                Resource: '*'
              - Effect: 'Allow'
                Action:
                  - 'ec2:CreateNetworkInterface'
                  - 'ec2:DescribeNetworkInterfaces'
                  - 'ec2:DeleteNetworkInterface'
                Resource: '*'

  # ECS task definition
  EcsTaskDefinition:
    Type: 'AWS::ECS::TaskDefinition'
    Properties:
      Family: 'test'
      Memory: 512
      Cpu: 256
      ContainerDefinitions:
        - Name: 'test_container'
          Image: !Join [ "", [ !Ref "AWS::AccountId", ".dkr.ecr.", !Ref "AWS::Region", ".amazonaws.com/", !Ref EcrRepository, "" ] ]
          PortMappings:
            - ContainerPort: 80
          Environment:
            - Name: 'ENV_VAR_1'
              Value: 'value1'
          Essential: true
          LogConfiguration:
            LogDriver: awslogs
            Options:
              awslogs-group: !Join [ '', [ '/ecs/', !Ref AWS::StackName ] ]
              awslogs-region: !Ref AWS::Region
              awslogs-stream-prefix: ecs
              awslogs-create-group: true
      TaskRoleArn: !GetAtt EcsTaskRole.Arn
      ExecutionRoleArn: !GetAtt TestExecutionRole.Arn
      NetworkMode: awsvpc
      RequiresCompatibilities:
        - FARGATE

  # ECS service
  EcsService:
    Type: 'AWS::ECS::Service'
    Properties:
      ServiceName: 'test_svc'
      Cluster: !Ref EcsCluster
      DesiredCount: 1
      TaskDefinition: !Ref EcsTaskDefinition
      LaunchType: 'FARGATE'
      NetworkConfiguration:
        AwsvpcConfiguration:
          AssignPublicIp: ENABLED
          SecurityGroups:
            - !Ref TestSG
          Subnets:
            - !Ref TestSubnet

  TestExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: TestExecutionRole
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action:
              - 'sts:AssumeRole'
            Principal:
              Service:
                - 'ecs-tasks.amazonaws.com'
      Policies:
        - PolicyName: EcsTaskExecutionPolicy
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - 'ec2:*'
                  - 'ecs:*'
                  - 'logs:*'
                  - 'ecr:*'
                Resource: '*'

  # Network
  TestVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsSupport: true
      EnableDnsHostnames: true
  TestSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref TestVPC
      CidrBlock: 10.0.0.0/24
      MapPublicIpOnLaunch: true

  TestSG:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Security group for my ECS task
      VpcId: !Ref TestVPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0

  RouteTable:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref TestVPC

  InternetGateway:
    Type: "AWS::EC2::InternetGateway"

  VPCGatewayAttachment:
    Type: "AWS::EC2::VPCGatewayAttachment"
    Properties:
      VpcId: !Ref TestVPC
      InternetGatewayId: !Ref InternetGateway

  InternetRoute:
    Type: "AWS::EC2::Route"
    Properties:
      DestinationCidrBlock: "0.0.0.0/0"
      GatewayId: !Ref InternetGateway
      RouteTableId: !Ref RouteTable

  SubnetARouteTableAssociation:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      RouteTableId: !Ref RouteTable
      SubnetId: !Ref TestSubnet

答案1

上次我遇到这样的错误是因为 ECS 没有到 ECR 的路由。这可以是互联网路由或 ECR VPC 端点。如果容器位于私有子网中,您可以使用 NAT 网关(昂贵)或 VPC 端点(较便宜)。

从记忆中看,事情似乎是这样运作的:ECS 启动您的任务以及图像的 URL,容器必须获取图像来引导自身。容器位于您的 VPC/子网上,这就是为什么它需要一条通往 ECR 的路由。

答案2

您的问题在于:

  TestSG:
    Type: AWS::EC2::SecurityGroup
    Properties:
    GroupDescription: Security group for my ECS task
    VpcId: !Ref TestVPC
    SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: 80
        ToPort: 80
        CidrIp: 0.0.0.0/0

您的 ECS 任务的安全组应允许出站流量到 ECR。最简单的方法是允许所有流量到 0.0.0./0(流量通过互联网)。您也可以使用 VPC 端点到 ECR,但仍需要在安全组中添加出站规则(文档:https://docs.aws.amazon.com/AmazonECR/latest/userguide/vpc-endpoints.html

相关内容