By using AWS re:Post, you agree to the AWS re:Post Terms of Use

Not able to mount EFS volume, into ECS containers on EC2 launch type

0

Appreciate any help on mounting the EFS volume on ECS containers on EC2 launch type with cloud formation

EFS volume, which has 3 access points mounted on two public subnets /logs /media /static

task definition maps access points into, mounts points MountPoints:

        - SourceVolume: efs-volume-media
              ContainerPath: /app/media
            - SourceVolume: efs-volume-static
              ContainerPath: /app/static
            - SourceVolume: efs-volume-logs
              ContainerPath: /app/logs

but when ECS service registered, gets Errors as CannotCreateContainerError: Error response from daemon: failed to copy file info for /var/lib/ecs/volumes/ecs-my-ecs-task-106-efs-volume-media-b8e192d6b0c0c3fca301: failed to chown /var/lib/ecs/volumes/ecs-my-ecs-task-106-efs-volume-media-b8e192d6b0c0c3fc

I have set posix user uid(1001), guid, efs permissions, efs file policy, iam policy, security groups, mounting ecs cluster on same subnet of efs subnets etc. but seems to be permission issue but seems some experts could figure out the issue. Any insights is highly appreciated.

following templates used in cloud formation EFS template

AWSTemplateFormatVersion: 2010-09-09

Parameters:
  VpcId:
    Type: AWS::EC2::VPC::Id
    Description: VPC ID where the resources will be deployed
  SubnetIds:
    Type: List<AWS::EC2::Subnet::Id>
    Description: List of subnet IDs where EFS mount targets will be created
  FileSystemName:
    Type: String
    Description: Name of the EFS filesystem
  STATICROOT:
    Type: String
    Description:  Static files path
    AllowedPattern: '[a-zA-Z0-9_]*'  # This restricts to alphanumeric and underscore only
  MEDIAROOT:
    Type: String
    Description:  Media files path
    AllowedPattern: '[a-zA-Z0-9_]*'  # This restricts to alphanumeric and underscore only
  LOGS:
    Type: String
    Description:  LOGS path
  EFSSecurityGroupName: 
    Type: String
    Description: Security Group Name of EFS
  
     
Resources:
  MyEFSSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: EFS Security Group
      GroupName: !Ref EFSSecurityGroupName
      VpcId: !Ref VpcId
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 2049  # NFS port used by EFS
          ToPort: 2049
          CidrIp: 0.0.0.0/0  # Adjust CIDR block based on your security requirements
      
          # SourceSecurityGroupId: <ContainerHostSecurityGroup ID>  # ContainerHostSecurityGroup ID
      SecurityGroupEgress:  # Outbound rules
        - IpProtocol: tcp
          FromPort: 0  # Allow all ports for outbound
          ToPort: 65535  # Allow all ports for outbound
          CidrIp: 0.0.0.0/0  # Allow outbound traffic to anywhere
      Tags:
        - Key: Name
          Value: !Ref EFSSecurityGroupName

  FileSystemResource:
    Type: 'AWS::EFS::FileSystem'
    Properties:
      BackupPolicy:
        Status: ENABLED
      Encrypted: false
      LifecyclePolicies:
        - TransitionToIA: AFTER_30_DAYS
        - TransitionToPrimaryStorageClass: AFTER_1_ACCESS
      FileSystemTags:
        - Key: Name
          Value: !Ref FileSystemName
      
      FileSystemPolicy:  # Add this to enable EFS IAM authorization
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal: "*"
            Action:
              - elasticfilesystem:ClientMount
              - elasticfilesystem:ClientWrite
              - elasticfilesystem:DescribeMountTargets
              - elasticfilesystem:ClientRootAccess
            Resource: "*"
      PerformanceMode: generalPurpose
      
  MountTargetResource1:
    Type: AWS::EFS::MountTarget
    Properties:
      FileSystemId: !Ref FileSystemResource
      SubnetId: !Select [0, !Ref SubnetIds]  # First subnet in provided list
      SecurityGroups:
        - !GetAtt MyEFSSecurityGroup.GroupId

  MountTargetResource2:
    Type: AWS::EFS::MountTarget
    Properties:
      FileSystemId: !Ref FileSystemResource
      SubnetId: !Select [1, !Ref SubnetIds]  # Second subnet in provided list
      SecurityGroups:
        - !GetAtt MyEFSSecurityGroup.GroupId


  AccessPointLogs:
    Type: 'AWS::EFS::AccessPoint'
    Properties:
      FileSystemId: !Ref FileSystemResource
      PosixUser:
        Uid: "1001"
        Gid: "1001"
      RootDirectory:
        CreationInfo:
          OwnerUid: "1001"
          OwnerGid: "1001"
          Permissions: "0755"
        Path: !Sub "/${LOGS}"

  AccessPointStatic:
    Type: 'AWS::EFS::AccessPoint'
    Properties:
      FileSystemId: !Ref FileSystemResource
      PosixUser:
        Uid: "1001"
        Gid: "101"
      RootDirectory:
        CreationInfo:
          OwnerUid: "1001"
          OwnerGid: "1001"
          Permissions: "0755"
        Path: !Sub "/${STATICROOT}"

  AccessPointMedia:
    Type: 'AWS::EFS::AccessPoint'
    Properties:
      FileSystemId: !Ref FileSystemResource
      PosixUser:
        Uid: "1001"
        Gid: "1001"
      RootDirectory:
        CreationInfo:
          OwnerUid: "1001"
          OwnerGid: "1001"
          Permissions: "0755"
        Path: !Sub "/${MEDIAROOT}"

................................................................................................................................ Task definition template

AWSTemplateFormatVersion: 2010-09-09
Description: Create a task definition for django container.

Parameters:
  AwsDefaultRegion:
    Type: String
    Description: "Aws Region"
  AwsAccessKey:
    Type: String
    Description: "Aws Access key ID"
  AwsSecretKey:
    Type: String
    Description: "Aws Secret Key"
  ProductionDBInstanceRDSEndpoint:
    Type: String
    Description: "EndpointName of ProductionDB RDS instance"
  ProductionDBInstanceRDSPort:
    Type: Number
    Description: "Port number of RDS Production instance"
  ProductionDBName:
    Type: String
    Description: "Name of the production database"
  ProductionDBUsername:
    Type: String
    Description: Username for the production database
  ProductionDBPassword:
    Type: String
    NoEcho: true
    Description: Password for the production database
  TestDBInstanceRDSEndpoint:
    Type: String
    Description: "EndpointName of TestDB RDS instance"
  TestDBInstanceRDSPort:
    Type: Number
    Description: "Port number of RDS Test instance"
  TestDBName:
    Type: String
    Description: "Name of the test database"
  TestDBUsername:
    Type: String
    Description: Username for the test database
  TestDBPassword:
    Type: String
    NoEcho: true
    Description: Password for the test database
  StaticRoot:
    Type: String
    Description: Static file folder
  MediaRoot:
    Type: String
    Description: Media file folder
  Logs:
    Type: String
    Description: Logs folder
  FileSystemId:
    Type: String
    Description: EFS file system id
  AccessPointIdMedia:
    Type: String
    Description: Media files access point in EFS
  AccessPointIdStatic:
    Type: String
    Description: Static files access point in EFS
  AccessPointIdLogs:
    Type: String
    Description: Logs files access point in EFS
  RedisHost:
    Type: String
    Description: Redis host name
  RedisPort:
    Type: Number
    Description: Redis host port
  RedisDb:
    Type: String
    Description: Redis db
  DisableRedisCache:
    Type: String
    Description: Redis db
  RedisPassword:
    Type: String
    Description: Redis password
  LogstashHost:
    Type: String
    Description: Logstash host name
  LogstashPort:
    Type: Number
    Description: Logstash port
  SslCertPathLogstash:
    Type: String
    Description: Logstash ssl cert path
  SslCertLogstash:
    Type: String
    Description: Logstash ssl cert in base64
  DisableElkStackLogging:
    Type: String
    Description: Disable ELK Stack
  DockerImageUrl:
    Type: String
    Description: Docker image URL
  LogGroupNameEcs:
    Type: String
    Description: Log Group Name
  LogRetentionInDays:
    Type: Number
    Description: Log Rention days
  TaskDefinitionName:
    Type: String
    Description: Task definition Name
  SecretKey:
    Type: String
    Description: Secret Key

Resources:
  
 

  # Base task execution role
  MyTaskExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: MyEcsTaskExecutionRole
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Principal:
              Service: [ecs-tasks.amazonaws.com]
            Action: ['sts:AssumeRole']
            Condition:
              ArnLike:
                aws:SourceArn: !Sub arn:aws:ecs:${AWS::Region}:${AWS::AccountId}:*
              StringEquals:
                aws:SourceAccount: !Ref AWS::AccountId
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy

  # Grant additional ability to access Elastic File System
  TaskAccessToEFS:
    Type: AWS::IAM::Policy
    Properties:
      Roles:
        - !Ref MyTaskExecutionRole
      PolicyName: AccessSecret
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Action:
              - elasticfilesystem:ClientMount
              - elasticfilesystem:ClientWrite
              - elasticfilesystem:DescribeMountTargets
              - elasticfilesystem:DescribeFileSystems
              - elasticfilesystem:ClientRootAccess
            Resource: '*'


  TaskAccessToLOGS:
    Type: AWS::IAM::Policy
    Properties:
      Roles:
        - !Ref MyTaskExecutionRole
      PolicyName: ECSLogPolicy
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Action:
              - logs:CreateLogGroup
              - logs:CreateLogStream
              - logs:PutLogEvents
            Resource:
              - !GetAtt LogGroup.Arn

  
  ECSTaskDefinition:
    Type: AWS::ECS::TaskDefinition
    Properties:
      # TaskRoleArn: arn:aws:iam::030863198243:role/ecsTaskExecutionRole
      # ExecutionRoleArn: arn:aws:iam::030863198243:role/ecsTaskExecutionRole
      TaskRoleArn: !GetAtt MyTaskExecutionRole.Arn
      ExecutionRoleArn: !GetAtt MyTaskExecutionRole.Arn
      NetworkMode: bridge
      
     
      RequiresCompatibilities:
        - EC2  # Change this to EC2 for EC2 launch type
      Family: !Ref TaskDefinitionName
      Cpu: "512"
      Memory: "1024"
      ContainerDefinitions:
        - Name: django
          Image: !Ref DockerImageUrl
          Essential: true
          PortMappings:
            - Name: "8000"
              ContainerPort: 8000
              HostPort: 8000
              Protocol: tcp
              AppProtocol: http
          LinuxParameters:
            InitProcessEnabled: true
          MountPoints:
            - SourceVolume: efs-volume-media
              ContainerPath: /app/media
            - SourceVolume: efs-volume-static
              ContainerPath: /app/static
            - SourceVolume: efs-volume-logs
              ContainerPath: /app/logs
          LogConfiguration:
            LogDriver: awslogs
            Options:
              mode: non-blocking
              max-buffer-size: 25m
              awslogs-group: LogGroup
              awslogs-region: !Ref AwsDefaultRegion
              awslogs-create-group: "true"
              awslogs-stream-prefix: efs-task
          Environment:
            - Name: AWS_DEFAULT_REGION
              Value: !Ref AwsDefaultRegion
            - Name: AWS_ACCESS_KEY_ID
              Value: !Ref AwsAccessKey
            - Name: AWS_SECRET_ACCESS_KEY
              Value: !Ref AwsSecretKey
            - Name: DB_HOST
              Value: !Ref ProductionDBInstanceRDSEndpoint             
            - Name: DB_PORT
              Value: !Ref ProductionDBInstanceRDSPort
            - Name: DB_NAME
              Value: !Ref ProductionDBName
            - Name: DB_USER
              Value: !Ref ProductionDBUsername
            - Name: DB_PASSWORD
              Value: !Ref ProductionDBPassword
            - Name: DB_TEST_HOST
              Value: !Ref TestDBInstanceRDSEndpoint
            - Name: DB_TEST_PORT
              Value: !Ref TestDBInstanceRDSPort
            - Name: DB_TEST_NAME
              Value: !Ref TestDBName
            - Name: DB_TEST_USERNAME
              Value: !Ref TestDBUsername
            - Name: DB_TEST_PASSWORD
              Value: !Ref TestDBPassword
            - Name: STATIC_ROOT
              Value: !Ref StaticRoot
            - Name: MEDIA_ROOT
              Value: !Ref MediaRoot
            - Name: LOGS
              Value: !Ref Logs
            - Name: REDIS_HOST
              Value: !Ref RedisHost
            - Name: REDIS_PORT
              Value: !Ref RedisPort
            - Name: REDIS_PASSWORD
              Value: !Ref RedisPassword
            - Name: REDIS_DB
              Value: !Ref RedisDb
            - Name: DISABLE_REDIS_CACHE
              Value: !Ref DisableRedisCache
            - Name: LOGSTASH_HOST
              Value: !Ref LogstashHost
            - Name: LOGSTASH_PORT
              Value: !Ref LogstashPort
            - Name: SSL_CERT_PATH_LOGSTASH
              Value: !Ref SslCertPathLogstash
            - Name: SSL_CERT_LOGSTASH
              Value: !Ref SslCertLogstash
            - Name: DISABLE_ELK_STACK_LOGGING
              Value: !Ref DisableElkStackLogging
            - Name: SECRET_KEY
              Value: !Ref SecretKey
      
      Volumes:
        - Name: efs-volume-media
          EFSVolumeConfiguration:
            FilesystemId: !Ref FileSystemId
            RootDirectory: /
            TransitEncryption: ENABLED
            AuthorizationConfig:
              AccessPointId: !Ref AccessPointIdMedia

        - Name: efs-volume-static
          EFSVolumeConfiguration:
            FilesystemId: !Ref FileSystemId
            RootDirectory: /
            TransitEncryption: ENABLED
            AuthorizationConfig:
              AccessPointId: !Ref AccessPointIdStatic
        
        - Name: efs-volume-logs
          EFSVolumeConfiguration:
            FilesystemId: !Ref FileSystemId
            RootDirectory: /
            TransitEncryption: ENABLED
            AuthorizationConfig:
              AccessPointId: !Ref AccessPointIdLogs
            
  LogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Ref LogGroupNameEcs
      RetentionInDays: !Ref LogRetentionInDays  # Modify retention period as needed

............................................................................................................

Dockerfile has

# Create a new user with specific UID/GID
RUN groupadd --gid 1001 myappuser \
&& useradd --uid 1001 --gid 1001 --shell /bin/bash --create-home myappuser

# Create directories for media, static, and logs
# Create directories for media, static, and logs
RUN mkdir -p /app/media /app/static /app/logs  && \
    chown -R 0:1001 /app/media /app/static /app/logs  && \
    chmod -R 775 /app/media /app/static /app/logs
asked 5 months ago202 views
1 Answer
0

Hi,

I think the issue could be related to EFS Access Point Permissions, please refer this article What are common EFS access point configurations? if it has been setup as intended.

Alternatively, could you please cross verify if your cloud-formation is as per this this article? I would suggest try it step by step using the console, as mentioned.

Thanks, Rama

profile pictureAWS
EXPERT
answered 5 months ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions