не удалось извлечь секреты или аутентификацию реестра: команда извлечения не удалась: : сигнал: убит

#amazon-web-services #amazon-cloudformation #amazon-ecs #aws-fargate

Вопрос:

Я провел весь день, пытаясь развернуть образ в Fargate, но постоянно сталкиваюсь со следующей ошибкой:

ResourceInitializationError: не удалось извлечь секреты или реестр аутентификация: ошибка команды извлечения: : сигнал: убит

Я использую следующий шаблон cloudformation (сокращенный):

 Parameters:
  VPC:
    Type: AWS::EC2::VPC::Id
    Description: VPC Id. VPC's private subnets must have a NAT Gateway to download container image.
  PublicSubnets:
    Description: Choose which public subnets the Load Balancer and ECS Service should be deployed to
    Type: List<AWS::EC2::Subnet::Id>
  IamCertificateArn:
    Type: String
    Description: The IAM Certificate Arn, which must exist in the same region
  Image:
    Type: String
    Description: Docker image. You can use images in the Docker Hub registry or specify other repositories (repository-url/image:tag).
  ContainerPort:
    Type: Number
    Description: Port on which the application listens within the docker container
    Default: 80
  LoadBalancerPort:
    Type: Number
    Default: 443
  RDSSecurityGroupId:
    Type: AWS::EC2::SecurityGroup::Id
    Description: Security Group of the RDS Instance
  HealthCheckPath:
    Type: String
    Description: The health check path starting with / e.g. /health
  HostedZoneName:
    Type: String
    Description: Domain name for your website (example.com.). Note it must end in a .
  HostedZoneID:
    Type: String
    Description: Hosted Zone Id

Resources:
  TaskDefinition:
    Type: AWS::ECS::TaskDefinition
    DependsOn: 
      - LogGroup
      - TaskExecutionRole
    Properties:
      Family: !Join ["", [!Ref "AWS::StackName", TaskDefinition]]
      NetworkMode: awsvpc
      RequiresCompatibilities:
        - FARGATE
      Cpu: 512
      Memory: 1GB
      ExecutionRoleArn: !Ref TaskExecutionRole
      TaskRoleArn: !Ref TaskExecutionRole
      ContainerDefinitions:
        - Name: !Ref "AWS::StackName"
          Image: !Ref Image
          PortMappings:
            - ContainerPort: !Ref ContainerPort
          LogConfiguration:
            LogDriver: awslogs
            Options:
              awslogs-region: !Ref AWS::Region
              awslogs-group: !Ref LogGroup
              awslogs-stream-prefix:
                !Join ["", [!Ref "AWS::StackName", -ecs-app]]
          Command: ["./app -f config.toml"]

  Cluster:
    Type: AWS::ECS::Cluster
    Properties:
      ClusterName: !Join ["", [!Ref "AWS::StackName", "-", "Cluster"]]

  Service:
    Type: AWS::ECS::Service
    DependsOn:
      - ListenerHTTPS
    Properties:
      ServiceName: !Join ["", [!Ref "AWS::StackName", "-", "Service"]]
      Cluster: !Ref Cluster
      TaskDefinition: !Ref TaskDefinition
      DeploymentConfiguration:
        MinimumHealthyPercent: 100
        MaximumPercent: 200
      DesiredCount: 1
      HealthCheckGracePeriodSeconds: 30
      LaunchType: FARGATE
      NetworkConfiguration:
        AwsvpcConfiguration:
          AssignPublicIp: ENABLED
          Subnets: !Ref PublicSubnets
          SecurityGroups:
            - !Ref ContainerSecurityGroup
      LoadBalancers:
        - ContainerName: !Ref AWS::StackName
          ContainerPort: !Ref ContainerPort
          TargetGroupArn: !Ref TargetGroup

  # API Load Balancer

  TargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      HealthCheckIntervalSeconds: 30
      HealthCheckPath: !Ref HealthCheckPath
      HealthCheckTimeoutSeconds: 10
      UnhealthyThresholdCount: 2
      HealthyThresholdCount: 2
      Name: !Join ["", [!Ref AWS::StackName, "-", "TrgtGrp"]]
      Port: !Ref ContainerPort
      Protocol: HTTP
      TargetGroupAttributes:
        - Key: deregistration_delay.timeout_seconds
          Value: 60 # default is 300
      TargetType: ip
      VpcId: !Ref VPC

  LoadBalancer:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Name: !Join ["", [!Ref AWS::StackName, "-", "ELB"]]
      Scheme: internet-facing
      SecurityGroups: 
        - !Ref LoadBalancerSecurityGroup
      Subnets: !Ref PublicSubnets

  ListenerHTTPS:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      DefaultActions:
        - TargetGroupArn: !Ref TargetGroup
          Type: forward
      LoadBalancerArn: !Ref LoadBalancer
      Port: !Ref LoadBalancerPort
      Protocol: HTTPS
      Certificates:
        - CertificateArn: !Ref IamCertificateArn
  
  TaskExecutionRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
              - ec2.amazonaws.com
              - ecs.amazonaws.com
              - ecs-tasks.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Policies:
        - PolicyDocument: {
            "Version": "2012-10-17",
            "Statement": [
            {
              "Effect": "Allow",
              "Action": [
                "s3:GetObject"
              ],
              "Resource": [
                "arn:aws:s3:::config.toml"
              ]
            }
            ]
          }
          PolicyName: !Join ["", [!Ref "AWS::StackName", "-", "DownloadConfigFromS3Policy"]]
        - PolicyDocument: {
            "Version": "2012-10-17",
            "Statement": [
            {
              "Effect": "Allow",
              "Action": [
                "ecr:GetAuthorizationToken",
                "ecr:BatchCheckLayerAvailability",
                "cr:GetDownloadUrlForLayer",
                "ecr:BatchGetImage"
              ],
              "Resource": "*"
            }
            ]
          }
          PolicyName: !Join ["", [!Ref "AWS::StackName", "-", "PullImagePolicy"]]
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
        - arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role


  VPCEndpointECRAPI:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      VpcEndpointType: Interface
      SecurityGroupIds:
        - !Ref PrivateLinkSecurityGroup
      ServiceName: !Join ["", ["com.amazonaws.", !Ref "AWS::Region", ".ecr.api"]]
      SubnetIds: !Ref PublicSubnets
      VpcId: !Ref VPC

  VPCEndpointECRDKR:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      VpcEndpointType: Interface
      SecurityGroupIds:
        - !Ref PrivateLinkSecurityGroup
      ServiceName: !Join ["", ["com.amazonaws.", !Ref "AWS::Region", ".ecr.dkr"]]
      SubnetIds: !Ref PublicSubnets
      VpcId: !Ref VPC

  VPCEndpointLogs:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      VpcEndpointType: Interface
      SecurityGroupIds:
        - !Ref PrivateLinkSecurityGroup
      ServiceName: !Join ["", ["com.amazonaws.", !Ref "AWS::Region", ".logs"]]
      SubnetIds: !Ref PublicSubnets
      VpcId: !Ref VPC

  VPCEndpointS3:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      VpcEndpointType: Interface
      SecurityGroupIds:
        - !Ref PrivateLinkSecurityGroup
      ServiceName: !Join ["", ["com.amazonaws.", !Ref "AWS::Region", ".s3"]]
      SubnetIds: !Ref PublicSubnets
      VpcId: !Ref VPC
  
  VPCEndpointSSM:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      VpcEndpointType: Interface
      SecurityGroupIds:
        - !Ref PrivateLinkSecurityGroup
      ServiceName: !Join ["", ["com.amazonaws.", !Ref "AWS::Region", ".ssm"]]
      SubnetIds: !Ref PublicSubnets
      VpcId: !Ref VPC

  # Security Groups

  LoadBalancerSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Load balancer security group
      GroupName: !Join ["", [!Ref "AWS::StackName", "-", "LoadBalancerSecurityGroup"]]
      Tags:
        - Key: ProjectName
          Value: !Ref "AWS::StackName"
      VpcId: !Ref VPC

  LoadBalancerInboundRuleHTTP:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !Ref LoadBalancerSecurityGroup
      IpProtocol: tcp
      FromPort: 80
      ToPort: 80
      CidrIp: 0.0.0.0/0
  
  LoadBalancerOutboundRuleHTTP:
    Type: AWS::EC2::SecurityGroupEgress
    Properties:
      GroupId: !Ref LoadBalancerSecurityGroup
      IpProtocol: tcp
      FromPort: 80
      ToPort: 80
      CidrIp: 0.0.0.0/0
  
  LoadBalancerInboundRuleHTTPS:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !Ref LoadBalancerSecurityGroup
      IpProtocol: tcp
      FromPort: 443
      ToPort: 443
      CidrIp: 0.0.0.0/0
  
  LoadBalancerOutboundRuleHTTPS:
    Type: AWS::EC2::SecurityGroupEgress
    Properties:
      GroupId: !Ref LoadBalancerSecurityGroup
      IpProtocol: tcp
      FromPort: 443
      ToPort: 443
      CidrIp: 0.0.0.0/0
  
  LoadBalancerInboundRuleContainer:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !Ref LoadBalancerSecurityGroup
      IpProtocol: tcp
      FromPort: !Ref ContainerPort
      ToPort: !Ref ContainerPort
      SourceSecurityGroupId: !GetAtt ContainerSecurityGroup.GroupId
  
  LoadBalancerOutboundRuleContainer:
    Type: AWS::EC2::SecurityGroupEgress
    Properties:
      GroupId: !Ref LoadBalancerSecurityGroup
      IpProtocol: tcp
      FromPort: !Ref ContainerPort
      ToPort: !Ref ContainerPort
      DestinationSecurityGroupId: !GetAtt ContainerSecurityGroup.GroupId

  ContainerSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Accepts traffic from and to load balancer
      GroupName: !Join ["", [!Ref "AWS::StackName", "-", "ContainerSecurityGroup"]]
      Tags:
        - Key: ProjectName
          Value: !Ref "AWS::StackName"
      VpcId: !Ref VPC
      
  ContainerInboundRuleHTTP:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !Ref ContainerSecurityGroup
      IpProtocol: tcp
      FromPort: !Ref ContainerPort
      ToPort: !Ref ContainerPort
      SourceSecurityGroupId: !GetAtt LoadBalancerSecurityGroup.GroupId
  
  ContainerOutboundRuleHTTP:
    Type: AWS::EC2::SecurityGroupEgress
    Properties:
      GroupId: !Ref ContainerSecurityGroup
      IpProtocol: tcp
      FromPort: !Ref ContainerPort
      ToPort: !Ref ContainerPort
      DestinationSecurityGroupId: !GetAtt LoadBalancerSecurityGroup.GroupId

  ContainerInboundRuleRDS:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !Ref ContainerSecurityGroup
      IpProtocol: tcp
      FromPort: 5432
      ToPort: 5432
      SourceSecurityGroupId: !Ref RDSSecurityGroupId
    
  ContainerInboundRuleRDS:
    Type: AWS::EC2::SecurityGroupEgress
    Properties:
      GroupId: !Ref ContainerSecurityGroup
      IpProtocol: tcp
      FromPort: 5432
      ToPort: 5432
      DestinationSecurityGroupId: !Ref RDSSecurityGroupId
  
  PrivateLinkSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties: 
      GroupName: PrivateLink-SecurityGroup
      GroupDescription: PrivateLink-SecurityGroup
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: 0.0.0.0/0 #should be cidrip of vpc
      VpcId: !Ref VPC
 

Я рассмотрел несколько вопросов в StackOverflow и на форумах aws. Я могу подтвердить:

  • у VPC включен DNS
  • Назначение общедоступных IP-адресов включено на Fargate
  • Частные подсети не используются
  • Хранилище ECR является частным
  • Я не храню никаких секретов в секретном менеджере

Я перепробовал все виды политик TaskExecutionPolicies, предоставляющих полный доступ к ECS, но все равно получаю ту же ошибку.

Честно говоря, я не знаю, что еще попробовать. Был бы очень признателен за некоторую помощь в этом вопросе.

Комментарии:

1. Ваш код неполон. TargetGroup и ListenerHTTPS не определены. Так что трудно строить догадки.

2. @Marcin: Спасибо за ваш комментарий. Я добавил их определения к вопросу

Ответ №1:

Ваша проблема связана с неправильным ContainerSecurityGroup . Он разрешает только исходящие подключения к вашему ALB. Таким образом, он не может получить ваши изображения. Я бы добавил следующее правило:

   ContainerOutboundAll:
    Type: AWS::EC2::SecurityGroupEgress
    Properties:
      GroupId: !Ref ContainerSecurityGroup
      IpProtocol: tcp
      FromPort: 0
      ToPort: 65535
      CidrIp: 0.0.0.0/0  
 

Это позволит использовать весь исходящий трафик, побуждая done к ECR. Вы можете дополнительно поиграть с ним, разрешив доступ только к конечным точкам интерфейса VPC, если хотите.

Пожалуйста, обратите внимание: ContainerOutboundAll это должно устранить вашу текущую ошибку. Ваш шаблон длинный и сложный, и у него может быть больше проблем, которые пока не очевидны. Если да, то новый вопрос был бы лучше для этих вопросов (если таковые имеются).

Комментарии:

1. Спасибо! Это решило проблему. Да, есть и другие проблемы, но я разберусь с ними или задам вопрос. Очень ценю вашу помощь 🙂

2. @W. K. S Нет проблем. Рад, что вы смогли пройти мимо текущего выпуска.