FargateからEFSを利用するための動きを確認したい場合に使える、最小限の構成設定を準備したので記載します。
Dockerイメージの準備
以下のようなシンプルなコンテナを作成します。
ECS上でFargateで動かして、時刻とホスト名を2カ所に追記で吐き出します。
/mounttarget
ではEFSを直接マウント、/accesspoint
はアクセスポイント経由でマウントします。
FROM debian:stable-slim RUN mkdir /accesspoint RUN mkdir /mounttarget CMD echo "$(date) $(hostname)" | tee -a /accesspoint/log.txt /mounttarget/log.txt
ECRに efs-test
という名前でPushしておきます。
Cloudformation適用
EFSの定義と、EFSを利用するECSクラスタとタスク定義を一気にデプロイします。
--- AWSTemplateFormatVersion: "2010-09-09" Description: Fargate Sample Tasks using EFS Parameters: ImageName: Type: String VpcId: Type: AWS::EC2::VPC::Id SubnetId: Type: AWS::EC2::Subnet::Id ClusterName: Type: String Default: MyEfsSampleCluster Resources: #--------------------------------- # EFS #--------------------------------- MyEFSSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: EFS Allowed Ports VpcId: !Ref VpcId SecurityGroupIngress: - IpProtocol: tcp FromPort: 2049 ToPort: 2049 CidrIp: 0.0.0.0/0 Tags: - Key: Name Value: MyEFSSecurityGroup MyEFSFileSystem: Type: AWS::EFS::FileSystem Properties: FileSystemTags: - Key: Name Value: my-efs-fs BackupPolicy: Status: ENABLED Encrypted: true LifecyclePolicies: - TransitionToIA: AFTER_30_DAYS PerformanceMode: generalPurpose MyEFSMountTarget: Type: AWS::EFS::MountTarget Properties: FileSystemId: !Ref MyEFSFileSystem SecurityGroups: - !Ref MyEFSSecurityGroup SubnetId: !Ref SubnetId MyEFSAccessPoint: Type: AWS::EFS::AccessPoint Properties: AccessPointTags: - Key: Name Value: my-accesspoint FileSystemId: !Ref MyEFSFileSystem PosixUser: Gid: "1000" Uid: "1000" RootDirectory: CreationInfo: OwnerGid: "1000" OwnerUid: "1000" Permissions: "0755" Path: /accesspoint #--------------------------------- # ECS #--------------------------------- MyECSCluster: Type: AWS::ECS::Cluster Properties: ClusterName: !Ref ClusterName CapacityProviders: - FARGATE DefaultCapacityProviderStrategy: - CapacityProvider: FARGATE Base: 1 Weight: 1 MyECSSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: EFS Allowed Ports VpcId: !Ref VpcId Tags: - Key: Name Value: ECSSecurityGroup MyECSTaskExecutionRole: Type: AWS::IAM::Role Properties: RoleName: !Sub "ECSTaskExecutionRole-${ClusterName}" Path: / AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: ecs-tasks.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy MyECSTaskRole: Type: AWS::IAM::Role Properties: RoleName: !Sub "ECSTaskRole-${ClusterName}" Path: / AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: ecs-tasks.amazonaws.com Action: sts:AssumeRole MyECSTaskDefinition: Type: AWS::ECS::TaskDefinition Properties: Family: efs-sample Cpu: 256 Memory: 512 NetworkMode: awsvpc ExecutionRoleArn: !Ref MyECSTaskExecutionRole TaskRoleArn: !Ref MyECSTaskRole RequiresCompatibilities: - FARGATE Volumes: - Name: efs-mount-target-vol EFSVolumeConfiguration: AuthorizationConfig: IAM: ENABLED FileSystemId: !Ref MyEFSFileSystem RootDirectory: / TransitEncryption: ENABLED - Name: efs-access-point-vol EFSVolumeConfiguration: AuthorizationConfig: AccessPointId: !Ref MyEFSAccessPoint IAM: ENABLED FileSystemId: !Ref MyEFSFileSystem TransitEncryption: ENABLED ContainerDefinitions: - Name: efs-sample Image: !Ref ImageName Essential: true User: 0 MountPoints: - ContainerPath: /mounttarget ReadOnly: False SourceVolume: efs-mount-target-vol - ContainerPath: /accesspoint ReadOnly: False SourceVolume: efs-access-point-vol DependsOn: MyEFSFileSystem ECSService: Type: AWS::ECS::Service Properties: DesiredCount: 0 NetworkConfiguration: AwsvpcConfiguration: AssignPublicIp: DISABLED SecurityGroups: - !Ref MyECSSecurityGroup Subnets: - !Ref SubnetId Cluster: !Ref MyECSCluster ServiceName: my-efs-sample-service TaskDefinition: !Ref MyECSTaskDefinition
パラメータを入れてCloudformationを適用します。
項目 | 説明 |
---|---|
スタックの名前 | 任意 |
ClusterName | 理由なければ変更しないで大丈夫です |
ImageName | ECRにPushしたイメージの名称を入れて下さい 例: 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/efs-test |
VpcId | FargateとEFSの動くVPC |
SubnetId | FargateとEFSのサブネット |
この際に以下のエラーが発生する場合があります。
Resource handler returned message: "Invalid request provided: CreateCluster Invalid Request: Unable to assume the service linked role. Please verify that the ECS service linked role exists. (Service: AmazonECS; Status Code: 400; Error Code:
その場合はこちらのコマンドでロールを作成してから再実行してください。
aws iam create-service-linked-role --aws-service-name ecs.amazonaws.com
動かしてみる
ECSクラスタの初期設定はタスク数を0としているので何も動きません。以下のようにタスク数を増やすとEFSにログを出力し始めます。
aws ecs update-service --cluster MyEfsSampleCluster \ --service my-efs-sample-service \ --desired-count 2
EFSの中身を見てみる
別のEC2(Linux)から中身を覗いてみます。
EFSのマウント
EFSの以下のボタンをクリックするとEFSのマウントコマンドが表示されます。
例えばヘルパーを使わない場合は以下のようなコマンドが表示されます。
sudo mount -t nfs4 -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport ${YOUR_EFS_ID}.efs.ap-northeast-1.amazonaws.com:/ efs
ヘルパーをインストールしておけば、シンプルなコマンドでマウントも可能です。
sudo yum install amazon-efs-utils sudo mount -t efs -o tls fs-0e20972e:/ efs
EFSの中身確認
今回はコンテナの最後に以下のコマンドを打ってログを出力していました。
echo "$(date) $(hostname)" | tee -a /accesspoint/log.txt /mounttarget/log.txt
${mount_dir}/log.txt
と ${mount_dir}/accesspoint/log.txt
にそれぞれ出力されているはずです。
中身見ると両方のログに同じ内容が出力されているのが確認できます。
$ head -n5 efs/log.txt Sun May 2 00:18:37 UTC 2021 ip-10-0-1-95.ap-northeast-1.compute.internal Sun May 2 00:18:40 UTC 2021 ip-10-0-1-172.ap-northeast-1.compute.internal Sun May 2 00:19:52 UTC 2021 ip-10-0-1-230.ap-northeast-1.compute.internal Sun May 2 00:20:01 UTC 2021 ip-10-0-1-215.ap-northeast-1.compute.internal Sun May 2 00:20:40 UTC 2021 ip-10-0-1-221.ap-northeast-1.compute.internal $ head -n5 efs/accesspoint/log.txt Sun May 2 00:18:37 UTC 2021 ip-10-0-1-95.ap-northeast-1.compute.internal Sun May 2 00:18:40 UTC 2021 ip-10-0-1-172.ap-northeast-1.compute.internal Sun May 2 00:19:52 UTC 2021 ip-10-0-1-230.ap-northeast-1.compute.internal Sun May 2 00:20:01 UTC 2021 ip-10-0-1-215.ap-northeast-1.compute.internal Sun May 2 00:20:40 UTC 2021 ip-10-0-1-221.ap-northeast-1.compute.internal
コンテナユーザをrootのままにしているので、MountTargetに出力された log.txt
も所有者IDが0(root)になっています。
$ ls -ln efs total 8 drwxr-xr-x 2 1000 1000 6144 May 1 09:48 accesspoint -rw-r--r-- 1 0 0 299 May 1 09:49 log.txt
AccessPoint経由の出力ではCloudformationで以下のように設定してあります。
MyEFSAccessPoint: Type: AWS::EFS::AccessPoint Properties: AccessPointTags: - Key: Name Value: my-accesspoint FileSystemId: !Ref MyEFSFileSystem PosixUser: Gid: "1000" Uid: "1000" RootDirectory: CreationInfo: OwnerGid: "1000" OwnerUid: "1000" Permissions: "0755" Path: /accesspoint
これが反映されたPermissionが設定されていることが確認できます。
$ ls -ln efs/accesspoint/ total 4 -rw-r--r-- 1 1000 1000 299 May 1 09:49 log.txt
掃除
Cloudformaitonのスタックの削除と、ECRからのイメージの削除をすれば完了です。