Amazon EFSを用いたストレージの永続化

最終更新日: 2020年6月12日
R8 | R9

Amazon EFSの概要

Wagby でファイル型項目に登録したファイルは upload_dir フォルダ内に管理されます。またインポート・エクスポート操作では export フォルダにファイルを保存します。Amazon EC2 は仮想環境であるため、サービスを停止するとこれらのローカルファイルもすべて消失します。

この対応のため、Amazon EFS (Elastic File System) を使う方法を説明します。EFS は共有ストレージであり、サーバ (EC2) を停止したあとでも EFS に保存したファイルは維持されます。

IPv4 VPC とサブネットの作成

Amazon EFS を使うために、はじめに AWS CLI を用いて IPv4 VPC とサブネットを作成します。次のページを参考にします。

VPC, Subnet, Security Groupを作成する

Amazon Virtual Private Cloud (VPC) は AWS アカウント専用の仮想ネットワークです。VPC を利用すると、他の仮想ネットワークから論理的に切り離すことができます。VPC 作成のために次のコマンドを入力します。

C:\Wagby-8.1.2\ecs>aws ec2 create-vpc --cidr-block 10.0.0.0/16

コンソールに次のように表示されます。

{
    "Vpc": {
        "CidrBlock": "10.0.0.0/16",
        "DhcpOptionsId": "dopt-68fb1d0d",
        "State": "pending",
        "VpcId": "vpc-0208b3ab6a7cf8978",
        "OwnerId": "234318443261",
        "InstanceTenancy": "default",
        "Ipv6CidrBlockAssociationSet": [],
        "CidrBlockAssociationSet": [
            {
                "AssociationId": "vpc-cidr-assoc-0b3e2206fc8f926e6",
                "CidrBlock": "10.0.0.0/16",
                "CidrBlockState": {
                    "State": "associated"
                }
            }
        ],
        "IsDefault": false,
        "Tags": []
    }
}

続いて VPC の DNS解決を有効にします。これは後の工程でEFSをマウントするときにDNSの名前解決が必要なためです。

C:\Wagby-8.1.2\ecs>aws ec2 modify-vpc-attribute --enable-dns-hostnames --vpc-id vpc-0208b3ab6a7cf8978

サブネットの作成

この VPC 内に2つのサブネットを作成します。それぞれ cidr-block と availability-zone が異なります。

C:\Wagby-8.1.2\ecs>aws ec2 create-subnet --vpc-id vpc-0208b3ab6a7cf8978 --cidr-block 10.0.1.0/24 --availability-zone ap-northeast-1b

コンソールに次のように表示されます。

{
    "Subnet": {
        "AvailabilityZone": "ap-northeast-1b",
        "AvailabilityZoneId": "apne1-az4",
        "AvailableIpAddressCount": 251,
        "CidrBlock": "10.0.1.0/24",
        "DefaultForAz": false,
        "MapPublicIpOnLaunch": false,
        "State": "pending",
        "SubnetId": "subnet-0c4d1541a528c63ba",
        "VpcId": "vpc-0208b3ab6a7cf8978",
        "OwnerId": "234318443261",
        "AssignIpv6AddressOnCreation": false,
        "Ipv6CidrBlockAssociationSet": [],
        "SubnetArn": "arn:aws:ec2:ap-northeast-1:234318443261:subnet/subnet-0c4d1541a528c63ba"
    }
}

二つ目のサブネットを作成します。

C:\Wagby-8.1.2\ecs>aws ec2 create-subnet --vpc-id vpc-0208b3ab6a7cf8978 --cidr-block 10.0.0.0/24 --availability-zone ap-northeast-1c
{
    "Subnet": {
        "AvailabilityZone": "ap-northeast-1c",
        "AvailabilityZoneId": "apne1-az1",
        "AvailableIpAddressCount": 251,
        "CidrBlock": "10.0.0.0/24",
        "DefaultForAz": false,
        "MapPublicIpOnLaunch": false,
        "State": "pending",
        "SubnetId": "subnet-030085de17d83f973",
        "VpcId": "vpc-0208b3ab6a7cf8978",
        "OwnerId": "234318443261",
        "AssignIpv6AddressOnCreation": false,
        "Ipv6CidrBlockAssociationSet": [],
        "SubnetArn": "arn:aws:ec2:ap-northeast-1:234318443261:subnet/subnet-030085de17d83f973"
    }
}

ゲートウェイの作成

次のコマンドでゲートウェイを作成します。二つのサブネットをつなげます。

C:\Wagby-8.1.2\ecs>aws ec2 create-internet-gateway

コンソールに次のように表示されます。

{
    "InternetGateway": {
        "Attachments": [],
        "InternetGatewayId": "igw-07da73307252fc675",
        "Tags": []
    }
}

作成したゲートウェイを使って、サブネットをつなげます。vpc-id を指定します。

C:\Wagby-8.1.2\ecs>aws ec2 attach-internet-gateway --vpc-id vpc-0208b3ab6a7cf8978  --internet-gateway-id igw-07da73307252fc675

ルータの設定

最初にルートテーブルを用意します。

C:\Wagby-8.1.2\ecs>aws ec2 create-route-table --vpc-id vpc-0208b3ab6a7cf8978

コンソールに次のように表示されます。

{
    "RouteTable": {
        "Associations": [],
        "PropagatingVgws": [],
        "RouteTableId": "rtb-043eb3934e1d30b4c",
        "Routes": [
            {
                "DestinationCidrBlock": "10.0.0.0/16",
                "GatewayId": "local",
                "Origin": "CreateRouteTable",
                "State": "active"
            }
        ],
        "Tags": [],
        "VpcId": "vpc-0208b3ab6a7cf8978",
        "OwnerId": "234318443261"
    }
}

このルートテーブルにルート情報を追加します。

C:\Wagby-8.1.2\ecs>aws ec2 create-route --route-table-id rtb-043eb3934e1d30b4c --destination-cidr-block 0.0.0.0/0 --gateway-id igw-07da73307252fc675

コンソールに次のように表示されます。

{
    "Return": true
}

このルーティングテーブルにサブネット情報を設定します。

C:\Wagby-8.1.2\ecs>aws ec2 describe-subnets --filters "Name=vpc-id,Values=vpc-0208b3ab6a7cf8978" --query "Subnets[*].{ID:SubnetId,CIDR:CidrBlock}"

コンソールに次のように表示されます。

[
    {
        "ID": "subnet-0c4d1541a528c63ba",
        "CIDR": "10.0.1.0/24"
    },
    {
        "ID": "subnet-030085de17d83f973",
        "CIDR": "10.0.0.0/24"
    }
]

サブネットをルートテーブルに関連付けます。

C:\Wagby-8.1.2\ecs>aws ec2 associate-route-table  --subnet-id subnet-030085de17d83f973 --route-table-id rtb-043eb3934e1d30b4c

コンソールに次のように表示されます。

{
    "AssociationId": "rtbassoc-036c34c948b6163d6"
}

セキュリティ

社内ネットワーク環境から、この仮想ネットワークに接続するためのセキュリティ設定を行います。これにより ssh 接続が行えるようになります。

セキュリティグループを作成します。

C:\Wagby-8.1.2\ecs>aws ec2 create-security-group --group-name ecswagby-sg --description "Security group for ssh and http access" --vpc-id vpc-0208b3ab6a7cf8978

コンソールに次のように表示されます。

{
    "GroupId": "sg-0d6b4b276edf7d47c"
}

ここで、社内ネットワークの IP アドレスが 61.xx.yy.zz/32 とします。この接続を許可させるために次のコマンドを入力します。port番号22はsshです。

C:\Wagby-8.1.2\ecs>aws ec2 authorize-security-group-ingress --group-id sg-0d6b4b276edf7d47c --protocol tcp --port 22 --cidr 61.xx.yy.zz/32
C:\Wagby-8.1.2\ecs>aws ec2 authorize-security-group-ingress --group-id sg-0d6b4b276edf7d47c --protocol tcp --port 80 --cidr 0.0.0.0/0

ロードバランサの作成

これまで作成した VPC、サブネット、セキュリティグループを使ってロードバランサを作成します。

C:\Wagby-8.1.2\ecs>aws elbv2 create-load-balancer --name ecswagbylb --subnets subnet-0c4d1541a528c63ba subnet-030085de17d83f973 --security-groups sg-0d6b4b276edf7d47c

コンソールに次のように表示されます。

{
    "LoadBalancers": [
        {
            "LoadBalancerArn": "arn:aws:elasticloadbalancing:ap-northeast-1:234318443261:loadbalancer/app/ecswagbylb/fab7fdfdf1fe36f6",
            "DNSName": "ecswagbylb-1355833343.ap-northeast-1.elb.amazonaws.com",
            "CanonicalHostedZoneId": "Z14GRHDCWA56QT",
            "CreatedTime": "2018-12-12T05:44:34.550Z",
            "LoadBalancerName": "ecswagbylb",
            "Scheme": "internet-facing",
            "VpcId": "vpc-0208b3ab6a7cf8978",
            "State": {
                "Code": "provisioning"
            },
            "Type": "application",
            "AvailabilityZones": [
                {
                    "ZoneName": "ap-northeast-1c",
                    "SubnetId": "subnet-030085de17d83f973"
                },
                {
                    "ZoneName": "ap-northeast-1b",
                    "SubnetId": "subnet-0c4d1541a528c63ba"
                }
            ],
            "SecurityGroups": [
                "sg-0d6b4b276edf7d47c"
            ],
            "IpAddressType": "ipv4"
        }
    ]
}

ターゲットグループの作成

次にターゲットグループを作成します。(ターゲットグループは前ページで説明済みのため、ここでは割愛します。)

C:\Wagby-8.1.2\ecs>aws elbv2 create-target-group --name ecswagby-targets --protocol HTTP --port 80 --health-check-path /wagby/logonPage.do --vpc-id vpc-0208b3ab6a7cf8978

次のようなメッセージが表示されます。

{
    "TargetGroups": [
        {
            "TargetGroupArn": "arn:aws:elasticloadbalancing:ap-northeast-1:234318443261:targetgroup/ecswagby-targets/a78a33bfd2d3de6b",
            "TargetGroupName": "ecswagby-targets",
            "Protocol": "HTTP",
            "Port": 80,
            "VpcId": "vpc-0208b3ab6a7cf8978",
            "HealthCheckProtocol": "HTTP",
            "HealthCheckPort": "traffic-port",
            "HealthCheckEnabled": true,
            "HealthCheckIntervalSeconds": 30,
            "HealthCheckTimeoutSeconds": 5,
            "HealthyThresholdCount": 5,
            "UnhealthyThresholdCount": 2,
            "HealthCheckPath": "/wagby/logonPage.do",
            "Matcher": {
                "HttpCode": "200"
            },
            "TargetType": "instance"
        }
    ]
}

リスナの作成

続いてリスナを作成します。(リスナは前ページで説明済みのため、ここでは割愛します。)

C:\Wagby-8.1.2\ecs>aws elbv2 create-listener --load-balancer-arn "arn:aws:elasticloadbalancing:ap-northeast-1:234318443261:loadbalancer/app/ecswagbylb/fab7fdfdf1fe36f6" --protocol HTTP --port 80 --default-actions Type=forward,TargetGroupArn=arn:aws:elasticloadbalancing:ap-northeast-1:234318443261:targetgroup/ecswagby-targets/a78a33bfd2d3de6b

次のようなメッセージが表示されます。

{
    "Listeners": [
        {
            "ListenerArn": "arn:aws:elasticloadbalancing:ap-northeast-1:234318443261:listener/app/ecswagbylb/fab7fdfdf1fe36f6/8b4fcc80e3e1b13f",
            "LoadBalancerArn": "arn:aws:elasticloadbalancing:ap-northeast-1:234318443261:loadbalancer/app/ecswagbylb/fab7fdfdf1fe36f6",
            "Port": 80,
            "Protocol": "HTTP",
            "DefaultActions": [
                {
                    "Type": "forward",
                    "TargetGroupArn": "arn:aws:elasticloadbalancing:ap-northeast-1:234318443261:targetgroup/ecswagby-targets/a78a33bfd2d3de6b"
                }
            ]
        }
    ]
}

クラスタの作成

ここまでの設定を使ってクラスタを作成し、実行できることを確認してみます。
VPC、サブネット、セキュリティグループ、ロードバランサ、ターゲットグループはこれまでの設定を使います。

C:\Wagby-8.1.2\ecs>ecs-cli up --keypair YOURKEY --capability-iam --size 1 --instance-type t2.medium --cluster-config ecswagbycluster --security-group sg-0d6b4b276edf7d47c --subnets subnet-0c4d1541a528c63ba,subnet-030085de17d83f973 --vpc vpc-0208b3ab6a7cf8978

コマンドを実行すると次のようなメッセージが表示されます。

INFO[0000] Using recommended Amazon Linux 2 AMI with ECS Agent 1.22.0 and Docker version 18.06.1-ce
INFO[0001] Created cluster                               cluster=ecswagbycluster region=ap-northeast-1
INFO[0001] Waiting for your cluster resources to be created...
INFO[0001] Cloudformation stack status                   stackStatus=CREATE_IN_PROGRESS
INFO[0062] Cloudformation stack status                   stackStatus=CREATE_IN_PROGRESS
INFO[0123] Cloudformation stack status                   stackStatus=CREATE_IN_PROGRESS
INFO[0184] Cloudformation stack status                   stackStatus=CREATE_IN_PROGRESS
Cluster creation succeeded.

サービスを起動します。

C:\Wagby-8.1.2\ecs>ecs-cli compose service up  --cluster-config ecswagbycluster --target-group-arn "arn:aws:elasticloadbalancing:ap-northeast-1:234318443261:targetgroup/ecswagby-targets/a78a33bfd2d3de6b"  --container-name tomcat --container-port 8080
INFO[0000] Using ECS task definition                     TaskDefinition="ecs:9"
INFO[0000] Created an ECS service                        service=ecs taskDefinition="ecs:9"
INFO[0001] Updated ECS service successfully              desiredCount=1 serviceName=ecs
INFO[0031] Service status                                desiredCount=1 runningCount=1 serviceName=ecs
INFO[0031] ECS Service has reached a stable state        desiredCount=1 runningCount=1 serviceName=ecs

Web ブラウザの URL にロードバランサのホスト名に対応するURLにアクセスし、表示されることを確認します。

http://ecswagbylb-1355833343.ap-northeast-1.elb.amazonaws.com/wagby/

Amazon EFS を使う

ここまでで Amazon EFS を使う準備が整いました。ここからの説明は次のページを参考にします。

VPC ID とセキュリティグループはそれぞれ次のようになっているものとします。(実際には環境によって異なるので読み替えてください。)

VPC IDvpc-0208b3ab6a7cf8978
セキュリティグループecswagby-sg(sg-0d6b4b276edf7d47c)

Amazon EFS ファイルシステムのセキュリティグループを作成する

次のコマンドを実行します。

C:\Wagby-8.1.2\ecs>aws ec2 create-security-group --group-name ecswagby-efsaccess-sg --description "Security group for EFS access" --vpc-id vpc-0208b3ab6a7cf8978
{
    "GroupId": "sg-0f8deea37c13e8c2f"
}

このセキュリティグループは、すべてのプロトコルによる接続を許可するものとします。

C:\Wagby-8.1.2\ecs>aws ec2 authorize-security-group-ingress --group-id sg-0f8deea37c13e8c2f --protocol all --source-group sg-0d6b4b276edf7d47c

Amazon EFS ファイルシステムを作成する

ファイルシステムを作成します。次のコマンドを実行します。

C:\Wagby-8.1.2\ecs>aws efs create-file-system --creation-token ecswagby-tomcat-fs

次のようなメッセージが表示されます。

{
    "OwnerId": "234318443261",
    "CreationToken": "ecswagby-tomcat-fs",
    "FileSystemId": "fs-e971adc8",
    "CreationTime": 1544602819.0,
    "LifeCycleState": "creating",
    "NumberOfMountTargets": 0,
    "SizeInBytes": {
        "Value": 0
    },
    "PerformanceMode": "generalPurpose",
    "Encrypted": false,
    "ThroughputMode": "bursting"
}

それぞれのサブネットに対してマウントします。

C:\Wagby-8.1.2\ecs>aws efs create-mount-target --file-system-id fs-e971adc8 --subnet-id subnet-0c4d1541a528c63ba --security-groups sg-0f8deea37c13e8c2f
{
    "OwnerId": "234318443261",
    "MountTargetId": "fsmt-0a56a02b",
    "FileSystemId": "fs-e971adc8",
    "SubnetId": "subnet-0c4d1541a528c63ba",
    "LifeCycleState": "creating",
    "IpAddress": "10.0.1.234",
    "NetworkInterfaceId": "eni-0c8328395beb4bea0"
}
C:\Wagby-8.1.2\ecs>aws efs create-mount-target --file-system-id fs-e971adc8 --subnet-id subnet-030085de17d83f973 --security-groups sg-0f8deea37c13e8c2f
{
    "OwnerId": "234318443261",
    "MountTargetId": "fsmt-1356a032",
    "FileSystemId": "fs-e971adc8",
    "SubnetId": "subnet-030085de17d83f973",
    "LifeCycleState": "creating",
    "IpAddress": "10.0.0.14",
    "NetworkInterfaceId": "eni-0b9e65a268de68512"
}

EC2インスタンスにssh接続する

まず実行中のEC2インスタンスのIPアドレスを取得します。

C:\Wagby-8.1.2\ecs>aws ec2 describe-instances  --query "Reservations[].Instances[].PublicIpAddress"

次のように IP アドレスがわかります。(この値はダミーです。)

[
    "52.194.212.182"
]
または「ec2 > インスタンス」画面で、ECSが実行されているインスタンスを選択し、「IPv4 パブリック IP」に書かれているIPアドレスを確認するという方法も利用できます。

ssh コマンドでログオンします。

$ ssh -i .ssh/YOURKEY ec2-user@52.194.212.182

ここで .ssh/YOURKEY は登録したssh鍵に対応する秘密鍵です。また ssh コマンド(プログラム)は別途、用意する必要があります。

Windows OS の場合、Cygwin をインストールすると ssh が含まれています。または ssh クライアントとして、PuTTY といったアプリケーションをインストールしてもよいでしょう。

ssh を実行すると、例えば次のようなメッセージが表示されます。

The authenticity of host '52.194.212.182 (52.194.212.182)' can't be established.
ECDSA key fingerprint is SHA256:XX...
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '52.194.212.182' (ECDSA) to the list of known hosts.
Enter passphrase for key '.ssh/YOURKEY':
   __|  __|  __|
   _|  (   \__ \   Amazon Linux 2 (ECS Optimized)
 ____|\___|____/
For documentation, visit http://aws.amazon.com/documentation/ecs
No packages needed for security; 9 packages available
Run "sudo yum update" to apply all updates.
[ec2-user@ip-10-0-1-166 ~]$

Amazon EFS ファイルシステムを使用する

ssh でログオンしたコンソール上で、この仮想OS(実行中のコンテナインスタンス)が Amazon EFS ファイルシステムを使用するように設定します。具体的なコマンド入力例を示します。

この設定はクラスタを作り直した場合は再度、行う必要があります。
[ec2-user@ip-10-0-1-166 ~]$ sudo mkdir /efs
[ec2-user@ip-10-0-1-166 ~]$ sudo yum install -y nfs-utils
Loaded plugins: priorities, update-motd, upgrade-helper
...
Complete!
[ec2-user@ip-10-0-1-166 ~]$ sudo mount -t nfs4 -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2 fs-e971adc8.efs.ap-northeast-1.amazonaws.com:/ /efs
[ec2-user@ip-10-0-1-166 ~]$ mount | grep efs
fs-e971adc8.efs.ap-northeast-1.amazonaws.com:/ on /efs type nfs4 (rw,relatime,vers=4.1,rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=10.0.1.166,local_lock=none,addr=10.0.1.234)
[ec2-user@ip-10-0-1-166 ~]$ sudo cp /etc/fstab /etc/fstab.bak
[ec2-user@ip-10-0-1-166 ~]$ echo 'fs-e971adc8.efs.ap-northeast-1.amazonaws.com:/ /efs  nfs4 nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2 0 0' | sudo tee -a /etc/fstab
fs-e971adc8.efs.ap-northeast-1.amazonaws.com:/ /efs  nfs4 nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2 0 0
[ec2-user@ip-10-0-1-166 ~]$ sudo mount -a
[ec2-user@ip-10-0-1-166 ~]$ sudo service ecs stop
Redirecting to /bin/systemctl stop ecs.service
[ec2-user@ip-10-0-1-166 ~]$ sudo service docker restart
Redirecting to /bin/systemctl restart docker.service
[ec2-user@ip-10-0-1-166 ~]$ sudo service ecs start
Redirecting to /bin/systemctl start ecs.service

ecs/docker-compose.ymlの編集

ecs/docker-compose.ymlを修正して、VolumeをEFSに保存するように設定します。具体的には ecs/docker-compose.yml に volume を指定します。

version: '3'
services:
  tomcat:
    image: 234318443261.dkr.ecr.ap-northeast-1.amazonaws.com/wagbyapp
    ports:
      - "80:8080"
    environment:
      DB: "hsqldb"
      INIT_DB: "true"
    volumes:
      - /efs/upload_dir:/usr/local/upload_dir
      - /efs/export:/usr/local/export
    logging:
      driver: awslogs
      options:
        awslogs-group: ecswagby
        awslogs-region: ap-northeast-1
        awslogs-stream-prefix: tomcat

編集後、サービスを再起動します。

C:\Wagby-8.1.2\ecs>ecs-cli compose service up  --cluster-config ecswagbycluster --target-group-arn "arn:aws:elasticloadbalancing:ap-northeast-1:234318443261:targetgroup/ecswagby-targets/a78a33bfd2d3de6b"  --container-name tomcat --container-port 8080

次のようなメッセージが表示されます。

INFO[0000] Using ECS task definition                     TaskDefinition="ecs:10"
WARN[0000] You cannot update the load balancer configuration on an existing service.  serviceName=ecs
INFO[0000] Updated the ECS service with a new task definition. Old containers will be stopped automatically, and replaced with new ones  desiredCount=1 serviceName=ecs taskDefinition="ecs:10"
INFO[0031] Service status                                desiredCount=1 runningCount=1 serviceName=ecs
INFO[0031] (service ecs) has started 1 tasks: (task 12b03f76-0b6c-46f1-8317-8f66b6033cc6).  timestamp="2018-12-12 09:08:13 +0000 UTC"
INFO[0031] ECS Service has reached a stable state        desiredCount=1 runningCount=1 serviceName=ecs

動作の確認

ロードバランサのホスト名に対応するURLにアクセスし、表示されることを確認します。

http://ecswagbylb-1355833343.ap-northeast-1.elb.amazonaws.com/wagby/

エクスポートファイル

アプリケーションにログオンします。インポート・エクスポート画面にてエクスポートを行なってみます。/efs/export/にファイルが作成されることを確認してください。

[ec2-user@ip-10-0-1-166 ~]$ ls /efs/export/
data_20181212180925.zip

帳票テンプレートの登録

帳票テンプレートのデータを新規登録し、テンプレートファイルに適当なファイルを指定して登録してみます。/efs/upload_dirにファイルが保存されることを確認してください。

[ec2-user@ip-10-0-1-166 ~]$ sudo find /efs/upload_dir/
/efs/upload_dir/
/efs/upload_dir/jfcreporttemplate
/efs/upload_dir/jfcreporttemplate/__multi4753612593004669550.tmp