AWS: миграция RTFM, часть #2: ручное создание инфраструктуры — AIM, S3, RDS и EBS

Автор: | 09/03/2016
 

aws-logo-square-02Продолжение.

Начало — в посте AWS: миграция RTFM, часть #1: ручное создание инфраструктуры — VPC, подсети, IGW, NAT GW, маршруты и EC2.

Далее мы создадим S3 корзины (для CDN и хранения логов), MariaDB RDS базу данных (для будущего WordPress на Zeus) и Elastic Block Storage — в котором будут храниться данные (файлы WordPress)  для подключения к Zeus.

Содержание этой части:

AIM

Добавим пользователя AIM, которому будет разрешено всё в будущей инфраструктуре — позже он будет использоваться при создании стека CloudFormation, а сейчас через него мы разрешим доступ к S3, RDS и так далее.

Создаём группу:

$ aws iam create-group --group-name rtfm_migrate
{
    "Group": {
        "Path": "/", 
        "CreateDate": "2016-08-29T14:12:58.061Z", 
        "GroupId": "AGPAIOKQIEB5VMNDRN4KE", 
        "Arn": "arn:aws:iam::264418146286:group/rtfm_migrate", 
        "GroupName": "rtfm_migrate"
    }
}

Пользователя:

$ aws iam create-user --user-name rtfm_migrate
{
    "User": {
        "UserName": "rtfm_migrate", 
        "Path": "/", 
        "CreateDate": "2016-08-29T14:15:05.952Z", 
        "UserId": "AIDAIJ54QWZEURLNSAP5E", 
        "Arn": "arn:aws:iam::264418146286:user/rtfm_migrate"
    }
}

Добавляем его в группу:

$ aws iam add-user-to-group --user-name rtfm_migrate --group-name rtfm_migrate

Проверяем:

$ aws iam get-group --group-name rtfm_migrate
{
    "Group": {
        "Path": "/", 
        "CreateDate": "2016-08-29T14:12:58Z", 
        "GroupId": "AGPAIOKQIEB5VMNDRN4KE", 
        "Arn": "arn:aws:iam::264418146286:group/rtfm_migrate", 
        "GroupName": "rtfm_migrate"
    }, 
    "Users": [
        {
            "UserName": "rtfm_migrate", 
            "Path": "/", 
            "CreateDate": "2016-08-29T14:15:05Z", 
            "UserId": "AIDAIJ54QWZEURLNSAP5E", 
            "Arn": "arn:aws:iam::264418146286:user/rtfm_migrate"
        }
    ]
}

Проверяем разрешенные политики пользователя:

$ aws iam list-user-policies --user-name rtfm_migrate
{
    "PolicyNames": []
}

Подключаем политику arn:aws:iam::aws:policy/AdministratorAccess — «всё и везде»:

$ aws iam attach-user-policy --user-name rtfm_migrate --policy-arn arn:aws:iam::aws:policy/AdministratorAccess

Проверяем:

$ aws iam list-attached-user-policies --user-name rtfm_migrate
{
    "AttachedPolicies": [
        {
            "PolicyName": "AdministratorAccess", 
            "PolicyArn": "arn:aws:iam::aws:policy/AdministratorAccess"
        }
    ]
}

S3

Потребуется как минимум три корзины — для бекапов, CloudFront CDN и логов.

Создаём их:

$ aws s3 mb s3://rtfmbackup
make_bucket: s3://rtfmbackup/
$ aws s3 mb s3://rtfmcdn
make_bucket: s3://rtfmcdn/
$ aws s3 mb s3://rtfmlogs
make_bucket: s3://rtfmlogs/

Проверяем:

$ aws s3api list-buckets --query '[Buckets[*]]' --output text | grep rtfm
2016-08-29T08:43:13.000Z        rtfmbackup
2016-08-29T08:43:20.000Z        rtfmcdn
2016-08-29T08:43:25.000Z        rtfmlogs

Корзина rtfmcdn будет использоваться для доступа к статичным файлам для всех, поэтому — проверяем права доступа:

$ aws s3api get-bucket-acl --bucket rtfmcdn
{
    "Owner": {
        "DisplayName": "user", 
        "ID": "a8e627b97012bf714c8308e668fe092628e6e69006499397b6cb8f337322a7b1"
    }, 
    "Grants": [
        {
            "Grantee": {
                "Type": "CanonicalUser", 
                "DisplayName": "user", 
                "ID": "a8e627b97012bf714c8308e668fe092628e6e69006499397b6cb8f337322a7b1"
            }, 
            "Permission": "FULL_CONTROL"
        }
    ]
}

Напомню — по умолчанию доступ к корзине (bucket-level permissions) и объектам в ней (object level) запрещён всем, кроме владельца:

$ aws s3 cp empty.html s3://rtfmcdn/
upload: ./empty.html to s3://rtfmcdn/empty.html
$ curl https://s3-eu-west-1.amazonaws.com/rtfmcdn/empty.html
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>74633A6F245429F9</RequestId><HostId>2wFrAHw1LF3+Ql9zEG4jOljyeBUcWZCdIWgxTBrIAeX7aJJ1BDwtOykUNq+VrfPG5rND6dHvBQc=</HostId></Error>

Сгенерировать policy можно с помощью AWS Policy Generator.

Сохраним в json:

$ cat s3_rtfm_cdn_policy.json
{
  "Id": "Policy1472461631550",
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Stmt1472461623419",
      "Action": [
        "s3:GetObject"
      ],
      "Effect": "Allow",
      "Resource": "arn:aws:s3:::rtdmcdn/*",
      "Principal": "*"
    }
  ]
}

И с помощью put-bucket-policy — добавляем правило:

$ aws s3api put-bucket-policy --bucket rtfmcdn --policy file://s3_rtfm_cdn_policy.json

Проверяем:

$ aws s3api get-bucket-policy --bucket rtfmcdn 
{
    "Policy": "{\"Version\":\"2012-10-17\",\"Id\":\"Policy1472461631550\",\"Statement\":[{\"Sid\":\"Stmt1472461623419\",\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":\"s3:GetObject\",\"Resource\":\"arn:aws:s3:::rtfmcdn/*\"}]}"
}
$ curl https://s3-eu-west-1.amazonaws.com/rtfmcdn/empty.html
This is empty file

Далее — генерируем политику доступа для корзин rtfmbackup и rtfmlogs, используя пользователя AIM, которого создали в начале, и вписываем в JSON-файл:

$ cat s3_rtfm_aim_policy.json
{
  "Id": "Policy1472480683447",
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Stmt1472480681830",
      "Action": "s3:*",
      "Effect": "Allow",
      "Resource": "arn:aws:s3:::rtfmbackup/*",
      "Principal": {
        "AWS": [
          "arn:aws:iam::264418146286:user/rtfm_migrate"
        ]
      }
    }
  ]
}

Добавляем к rtfmbackup и повторяем для logs (отредактировав строку "Resource"):

$ aws s3api put-bucket-policy --bucket rtfmbackup --policy file://s3_rtfm_aim_policy.json

Проверяем:

$ aws s3api get-bucket-policy --bucket rtfmbackup
{
    "Policy": "{\"Version\":\"2012-10-17\",\"Id\":\"Policy1472480683447\",\"Statement\":[{\"Sid\":\"Stmt1472480681830\",\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::264418146286:user/rtfm_migrate\"},\"Action\":\"s3:*\",\"Resource\":\"arn:aws:s3:::rtfmbackup/*\"}]}"
}
$ aws s3api get-bucket-policy --bucket rtfmlogs
{
    "Policy": "{\"Version\":\"2012-10-17\",\"Id\":\"Policy1472480683447\",\"Statement\":[{\"Sid\":\"Stmt1472480681830\",\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::264418146286:user/rtfm_migrate\"},\"Action\":\"s3:*\",\"Resource\":\"arn:aws:s3:::rtfmlogs/*\"}]}"
}

Проверяем.

Добавляем файл:

$ aws s3 cp empty.html s3://rtfmbackup
upload: ./empty.html to s3://rtfmbackup/empty.html

Пытаемся его получить напрямую:

$ curl https://s3-eu-west-1.amazonaws.com/rtfmbackup/empty.html
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>27DE0EF704F9BFEC</RequestId><HostId>vqRepDmnPfVRrPmrhwFifgBHujVYBqGO/0fR8zmc7BUIY9rTvSw+CTJvYU56nszugIRdvhTGlWI=</HostId></Error>

И с помощью simulate-principal-policy:

$ aws iam simulate-principal-policy --policy-source-arn arn:aws:iam::264418146286:user/rtfm_migrate --action-names s3:GetObject --resource-arns arn:aws:s3:::rtfmbackup
{
    "EvaluationResults": [
        {
            "EvalDecision": "allowed", 
            "MissingContextValues": [], 
            "EvalActionName": "s3:GetObject", 
            "MatchedStatements": [
                {
                    "SourcePolicyId": "AdministratorAccess", 
                    "StartPosition": {
                        "Column": 17, 
                        "Line": 3
                    }, 
                    "EndPosition": {
                        "Column": 6, 
                        "Line": 8
                    }
                }
            ], 
            "EvalResourceName": "arn:aws:s3:::rtfmbackup"
        }
    ], 
    "IsTruncated": false
}

"EvalDecision": "allowed"  — ОК, права на доступ к корзине есть.

Получаем данные доступа для пользователя rtfm_migrate:

$ aws iam create-access-key --user-name rtfm_migrate
{
    "AccessKey": {
        "UserName": "rtfm_migrate", 
        "Status": "Active", 
        "CreateDate": "2016-08-29T15:48:43.463Z", 
        "SecretAccessKey": "lqA***5vA", 
        "AccessKeyId": "AKI***DXA"
    }
}

И проверяем с авторизацией при помощи s3cmd:

$ ./s3cmd get s3://rtfmbackup/empty.html empty.html
download: 's3://rtfmbackup/empty.html' -> 'empty.html'  [1 of 1]
 19 of 19   100% in    5s     3.44 B/s  done

MariaDB RDS

Следующий шаг — создание инстанса сервера баз данных MariaDB.

Хороший FAQ тут>>>.

Сравнение Amazon Aurora и MariaDB RDS есть вот тут>>>.

Для RDS потребуется создать DB subnet group с двумя подсетями в разных Availability Zones.

Процесс выгглядит так:

  1. создаём вторую подсеть;
  2. группируем RDS подсети;
  3. создаём секьюрити группу;
  4. создаём DB инстанс.

Создаём вторую приватную подсеть в отличной от первой приватной подсети Availability-зоне для Multi-AZ deployment.

Напомню конфигурацию сети, созданную в предыдущей части:

  • VPC: --vpc-id vpc-1cc04778
    • публичная сеть: subnet-04ae0d5c
    • приватная сеть: subnet-f7ae0daf

Проверяем текущую зону имеющейся приватной подсети:

$ aws ec2 describe-subnets --subnet-id subnet-f7ae0daf --query '[Subnets[*].AvailabilityZone]' --output text
eu-west-1b

Добавляем ещё одну, но в зоне eu-west-1a:

$ aws ec2 create-subnet --vpc-id vpc-1cc04778 --cidr-block 10.0.3.0/24 --availability-zone eu-west-1a
{
    "Subnet": {
        "VpcId": "vpc-1cc04778", 
        "CidrBlock": "10.0.3.0/24", 
        "State": "pending", 
        "AvailabilityZone": "eu-west-1a", 
        "SubnetId": "subnet-3b6df54d", 
        "AvailableIpAddressCount": 251
    }
}

Добавляем теги:

$ aws ec2 create-tags --resources subnet-3b6df54d --tags Key=Name,Value=rtfm_migrate_priv_net2

С помощью create-db-subnet-group создаём группу подсетей:

$ aws rds create-db-subnet-group --db-subnet-group-name rtfmdbs --db-subnet-group-description "RTFM MariaDB instance" --subnet-ids subnet-f7ae0daf subnet-3b6df54d
{
    "DBSubnetGroup": {
        "Subnets": [
            {
                "SubnetStatus": "Active", 
                "SubnetIdentifier": "subnet-f7ae0daf", 
                "SubnetAvailabilityZone": {
                    "Name": "eu-west-1b"
                }
            }, 
            {
                "SubnetStatus": "Active", 
                "SubnetIdentifier": "subnet-3b6df54d", 
                "SubnetAvailabilityZone": {
                    "Name": "eu-west-1a"
                }
            }
        ], 
        "DBSubnetGroupName": "rtfmdbs", 
        "VpcId": "vpc-1cc04778", 
        "DBSubnetGroupDescription": "RTFM MariaDB instance", 
        "SubnetGroupStatus": "Complete"
    }
}

VPC Security Group

DB security group controls access to a DB instance that is not in a VPC, a VPC security group controls access to a DB instance (or other AWS instances) inside a VPC, and an EC2 security group controls access to an EC2 instance.

Одна VPC Security Group уже имеется:

$ aws ec2 describe-security-groups --filters Name=vpc-id,Values=vpc-1cc04778 --query '[SecurityGroups[*].GroupId]' --output text
sg-914e7ef6

Текущие правила в ней:

$ aws ec2 describe-security-groups --group-ids sg-914e7ef6 --query '[SecurityGroups[*].IpPermissions[*].{FromPort:FromPort,IpRanges:IpRanges}]' --output text
80
IPRANGES        0.0.0.0/0
None
22
IPRANGES        194.***.***.0/24
443
IPRANGES        0.0.0.0/0

Создаём новую группу, в которой разрешим доступ из приватной подсети, которая используется для EC2-инстанса Zeus:

$ aws ec2 create-security-group --group-name rtfm_rds_rivate --description "RTFM RDS DB access" --vpc-id vpc-1cc04778
{
    "GroupId": "sg-80d3d2e7"
}

Добавляем правило для доступа к RDS из приватной посети для Zeus:

$ aws ec2 authorize-security-group-ingress --group-id sg-80d3d2e7 --protocol tcp --port 3306 --cidr 10.0.2.0/24

Создание RDS

Описание типов DB инстансов тут>>>.

Выбираем Burst. Хорошее сравнение Burstable vs. Fixed Performance есть тут>>>.

Создаём с помощью create-db-instance:

$ aws rds create-db-instance --db-instance-identifier rtfm-mariadb-1 --db-instance-class db.t2.small --engine mariadb --master-username setevoy --master-user-password p@ssw0rd --vpc-security-group-ids sg-80d3d2e7 --db-subnet-group-name rtfmdbs --multi-az --no-publicly-accessible --allocated-storage 5

Проверяем:

$ aws rds describe-db-instances --db-instance-identifier rtfm-mariadb-1
{
    "DBInstances": [
        {
            "PubliclyAccessible": false,
            "MasterUsername": "setevoy",
            "MonitoringInterval": 0,
            "LicenseModel": "general-public-license",
            "VpcSecurityGroups": [
                {
                    "Status": "active",
                    "VpcSecurityGroupId": "sg-80d3d2e7"
                }
            ],
            "InstanceCreateTime": "2016-09-03T09:37:15.501Z",
            "CopyTagsToSnapshot": false,
            "OptionGroupMemberships": [
                {
                    "Status": "in-sync", 
                    "OptionGroupName": "default:mariadb-10-0"
                }
            ], 
            "PendingModifiedValues": {
                "MultiAZ": true
            }, 
            "Engine": "mariadb", 
            "MultiAZ": false, 
            "DBSecurityGroups": [], 
            "DBParameterGroups": [
                {
                    "DBParameterGroupName": "default.mariadb10.0", 
                    "ParameterApplyStatus": "in-sync"
                }
            ], 
            "AutoMinorVersionUpgrade": true, 
            "PreferredBackupWindow": "02:18-02:48", 
            "DBSubnetGroup": {
                "Subnets": [
                    {
                        "SubnetStatus": "Active", 
                        "SubnetIdentifier": "subnet-f7ae0daf", 
                        "SubnetAvailabilityZone": {
                            "Name": "eu-west-1b"
                        }
                    }, 
                    {
                        "SubnetStatus": "Active", 
                        "SubnetIdentifier": "subnet-3b6df54d", 
                        "SubnetAvailabilityZone": {
                            "Name": "eu-west-1a"
                        }
                    }
                ], 
                "DBSubnetGroupName": "rtfmdbs", 
                "VpcId": "vpc-1cc04778", 
                "DBSubnetGroupDescription": "RTFM MariaDB instance", 
                "SubnetGroupStatus": "Complete"
            }, 
            "ReadReplicaDBInstanceIdentifiers": [], 
            "AllocatedStorage": 5, 
            "BackupRetentionPeriod": 1, 
            "PreferredMaintenanceWindow": "mon:22:19-mon:22:49", 
            "Endpoint": {
                "HostedZoneId": "Z29XKXDKYMONMX", 
                "Port": 3306, 
                "Address": "rtfm-mariadb-1.chcmj9clr1dt.eu-west-1.rds.amazonaws.com"
            }, 
            "DBInstanceStatus": "modifying", 
            "EngineVersion": "10.0.24", 
            "AvailabilityZone": "eu-west-1b", 
            "StorageType": "standard", 
            "DbiResourceId": "db-XSFKEBVS6OJ7QUJJYPUHYM4W3M", 
            "CACertificateIdentifier": "rds-ca-2015", 
            "StorageEncrypted": false, 
            "DBInstanceClass": "db.t2.small", 
            "DbInstancePort": 0, 
            "DBInstanceIdentifier": "rtfm-mariadb-1"
        }
    ]
}

Пробуем подключиться с рабочей машины:

$ telnet rtfm-mariadb-1.chcmj9clr1dt.eu-west-1.rds.amazonaws.com 3306
Trying 10.0.2.221...

ОК, разрешение имени происходит по внутреннему IP 10.0.2.221 — снаружи доступа нет.

Подключаемся на Bastion, и пробуем с него (публичная подсеть):

$ ssh root@52.31.64.42 -i ~/.ssh/rtfm_migrate.pem
# bash
bash-4.3# telnet rtfm-mariadb-1.chcmj9clr1dt.eu-west-1.rds.amazonaws.com 3306
Trying 10.0.2.221...

ОК, теперь с Bastion — на Zeus:

bash-4.3# ssh core@10.0.2.101 -i .ssh/rtfm_migrate.pem 
CoreOS stable (1068.9.0)
Last login: Sat Sep  3 09:43:12 2016 from 10.0.1.243
core@ip-10-0-2-101 ~ $ 

Устанавливаем telnet (привык я к нему).

Запускаем Toolbox/Fedora:

core@ip-10-0-2-101 ~ $ /usr/bin/toolbox
latest: Pulling from library/fedora
2bf01635e2a0: Pull complete 
Digest: sha256:64a02df6aac27d1200c2572fe4b9949f1970d05f74d367ce4af994ba5dc3669e
Status: Downloaded newer image for fedora:latest
core-fedora-latest
Spawning container core-fedora-latest on /var/lib/toolbox/core-fedora-latest.
Press ^] three times within 1s to kill container.
[root@ip-10-0-2-101 ~]# dnf install telnet -y

И через MySQL-клиент:

# dnf install mysql
[root@ip-10-0-2-101 ~]# mysql -h rtfm-mariadb-1.chcmj9clr1dt.eu-west-1.rds.amazonaws.com -u setevoy -p
Enter password: 
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 23
Server version: 10.0.24-MariaDB MariaDB Server

Copyright (c) 2000, 2016, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| innodb             |
| mysql              |
| performance_schema |
+--------------------+

RDS готова к использованию.

EBS

Добавляем EBS для подключения к Zeus.

Общая информация по созданию EBSтут>>>, типы разделов — тут>>>.

Создаём с помощью create-volume в той же зоне, что и EC2 Zeus:

$ aws ec2 create-volume --size 10 --region eu-west-1 --availability-zone eu-west-1b --volume-type gp2
{
    "AvailabilityZone": "eu-west-1b", 
    "Encrypted": false, 
    "VolumeType": "gp2", 
    "VolumeId": "vol-098cdfb8", 
    "State": "creating", 
    "Iops": 100, 
    "SnapshotId": "", 
    "CreateTime": "2016-09-03T10:23:20.304Z", 
    "Size": 10
}

Добавляем теги:

$ aws ec2 create-tags --resources vol-098cdfb8 --tags Key=Name,Value=rtfm_migrate_zeus_vol_1

Проверяем текущие устройства на Zeus:

core@ip-10-0-2-101 ~ $ lsblk 
NAME    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
xvda    202:0    0    8G  0 disk 
|-xvda1 202:1    0  128M  0 part /boot
|-xvda2 202:2    0    2M  0 part 
|-xvda3 202:3    0    1G  0 part /usr
|-xvda4 202:4    0    1G  0 part 
|-xvda6 202:6    0  128M  0 part /usr/share/oem
|-xvda7 202:7    0   64M  0 part 
`-xvda9 202:9    0  5.7G  0 part /

Далее, с помощью attach-volume — подключаем его к Zeus:

$ aws ec2 attach-volume --volume-id vol-098cdfb8 --instance-id i-0113158d --device /dev/xvdc
{
    "AttachTime": "2016-09-03T10:25:56.589Z", 
    "InstanceId": "i-0113158d", 
    "VolumeId": "vol-098cdfb8", 
    "State": "attaching", 
    "Device": "/dev/xvdc"
}

На CoreOS проверяем:

core@ip-10-0-2-101 ~ $ lsblk 
NAME    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
xvda    202:0    0    8G  0 disk 
|-xvda1 202:1    0  128M  0 part /boot
|-xvda2 202:2    0    2M  0 part 
|-xvda3 202:3    0    1G  0 part /usr
|-xvda4 202:4    0    1G  0 part 
|-xvda6 202:6    0  128M  0 part /usr/share/oem
|-xvda7 202:7    0   64M  0 part 
`-xvda9 202:9    0  5.7G  0 part /
xvdc    202:32   0   10G  0 disk

И через fdisk:

ip-10-0-2-101 core # fdisk -l
Disk /dev/xvda: 8 GiB, 8589934592 bytes, 16777216 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 8398C29B-7038-48BA-9E57-F36900F47EAA

Device       Start      End  Sectors  Size Type
/dev/xvda1    4096   266239   262144  128M EFI System
/dev/xvda2  266240   270335     4096    2M BIOS boot
/dev/xvda3  270336  2367487  2097152    1G unknown
/dev/xvda4 2367488  4464639  2097152    1G unknown
/dev/xvda6 4464640  4726783   262144  128M Linux filesystem
/dev/xvda7 4726784  4857855   131072   64M unknown
/dev/xvda9 4857856 16777182 11919327  5.7G unknown


Disk /dev/xvdc: 10 GiB, 10737418240 bytes, 20971520 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

Подключение раздела на CoreOS вообще отдельная тема, быстро можно посмотреть тут>>> и тут>>>.

Проверяем текущую файловую систему:

ip-10-0-2-101 core # df -T /dev/xvda6
Filesystem     Type 1K-blocks  Used Available Use% Mounted on
/dev/xvda6     ext4    110576    64    101340   1% /usr/share/oem

Форматируем новый раздел:

ip-10-0-2-101 core # mkfs.ext4 -L rtfm_migrate_zeus_vol_1 /dev/xvdc  
mke2fs 1.42.13 (17-May-2015)
Creating filesystem with 2621440 4k blocks and 655360 inodes
Filesystem UUID: 74497db2-b63e-446b-9183-b88a6da3b67b
Superblock backups stored on blocks: 
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done

В каталоге /etc/systemd/system создаём systemd юнит для монтирования раздела — /etc/systemd/system/data-www.mount:

#cloud-config

coreos:
  units:
    - name: data-www.mount
      command: start
      content: |
        [Mount]
        What=/dev/xvdc
        Where=/data/www
        Type=ext4

Проверяем текущие точки монтирования:

ip-10-0-2-101 core # mount | grep xvd
/dev/xvda9 on / type ext4 (rw,relatime,seclabel,data=ordered)
/dev/xvda3 on /usr type ext4 (ro,relatime,seclabel,block_validity,delalloc,barrier,user_xattr,acl)
/dev/xvda6 on /usr/share/oem type ext4 (rw,nodev,relatime,seclabel,commit=600,data=ordered)
/dev/xvda1 on /boot type vfat (rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,errors=remount-ro)

Монтируем новый диск:

# systemctl start data-www.mount
# systemctl status data-www.mount
● data-www.mount - /data/www
   Loaded: loaded (/etc/systemd/system/data-www.mount; bad; vendor preset: disabled)
   Active: active (mounted) since Sat 2016-09-03 10:46:58 UTC; 5s ago
    Where: /data/www
     What: /dev/xvdc
  Process: 1261 ExecMount=/bin/mount /dev/xvdc /data/www -t ext4 (code=exited, status=0/SUCCESS)
    Tasks: 0
   Memory: 108.0K
      CPU: 5ms

Sep 03 10:46:58 ip-10-0-2-101.eu-west-1.compute.internal systemd[1]: Mounting /data/www...
Sep 03 10:46:58 ip-10-0-2-101.eu-west-1.compute.internal systemd[1]: Mounted /data/www.

И ещё раз проверяем:

ip-10-0-2-101 core # mount | grep xvd
/dev/xvda9 on / type ext4 (rw,relatime,seclabel,data=ordered)
/dev/xvda3 on /usr type ext4 (ro,relatime,seclabel,block_validity,delalloc,barrier,user_xattr,acl)
/dev/xvda6 on /usr/share/oem type ext4 (rw,nodev,relatime,seclabel,commit=600,data=ordered)
/dev/xvda1 on /boot type vfat (rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,errors=remount-ro)
/dev/xvdc on /data/www type ext4 (rw,relatime,seclabel,data=ordered)
ip-10-0-2-101 core # ls -l /data/www/
total 16
drwx------. 2 root root 16384 Sep  3 10:39 lost+found

Готово.

Ссылки по теме

Tutorial: Create an Amazon VPC for Use with an Amazon RDS DB Instance

Scenarios for Accessing a DB Instance in a VPC

Tutorial: Create an Amazon VPC for Use with an Amazon RDS DB Instance

Simple Stateful Services with CoreOS and AWS

Running CoreOS on EC2

Using Cloud-Config in CoreOS

Using IAM Policy Conditions for Fine-Grained Access Control

Writing IAM Policies: How to Grant Access to an Amazon S3 Bucket

AWS: CloudFront – описание, примеры