Пошаговый процесс написания шаблона для AWS CloudFormation, который создаёт VPC, подсети и инстансы для Docker Swarm-кластера.
Первая часть — AWS: VPC – EC2 в public и private подсетях, NAT и Internet Gateway.
Вторая часть: Docker: Docker Swarm кластер в AWS step-by-step.
Общие сведения по AWS CloudFormation — AWS: CloudFormation.
Готовый шаблон доступен тут>>>.
Содержание
VPC
Начнём с VPC:
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "AWS CloudFormation Template Docker Swarm cluster in VPC",
"Parameters" : {
"VPCCidrBlock" : {
"Description" : "VPC CIDR IP addresses block",
"Type" : "String",
"MinLength": "9",
"MaxLength": "18",
"Default": "11.0.0.0/16",
"AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
"ConstraintDescription": "must be a valid IP CIDR range of the form x.x.x.x/x."
}
},
"Resources" : {
"VPC" : {
"Type" : "AWS::EC2::VPC",
"Properties" : {
"CidrBlock" : { "Ref" : "VPCCidrBlock" },
"EnableDnsSupport" : "false",
"EnableDnsHostnames" : "false",
"Tags" : [ {"Key" : "Application", "Value" : { "Ref" : "AWS::StackId"} } ]
}
}
},
"Outputs" : {
"VPCCIDR" : {
"Value" : { "Fn::GetAtt" : ["VPC", "CidrBlock"] },
"Description" : "VPC CIDR IP addresses block"
}
}
}
Запускаем:
$ aws cloudformation create-stack --stack-name VPConly1 --template-body file:////home//setevoy//PycharmProjects//Swarm-cluster/VPC_alone.template
{
"StackId": "arn:aws:cloudformation:eu-west-1:264418146286:stack/VPConly1/c7cc9d40-6383-11e6-9d18-50faeb52a4d2"
}
Security Group
Для конфигурирования Security Group — добавим параметр, через который можно указать IP, с которого будет разрешён SSH к Мастеру:
...
"SSHLocation" : {
"Description" : " The IP address range that can be used to SSH to the EC2 instances",
"Type": "String",
"MinLength": "9",
"MaxLength": "18",
"Default": "0.0.0.0/0",
"AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
"ConstraintDescription": "must be a valid IP CIDR range of the form x.x.x.x/x."
}
...
Добавляем ресурс MasterSecurityGroup:
...
"MasterSecurityGroup" : {
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"VpcId" : { "Ref": "VPC"},
"GroupDescription" : "Enable HTTP access via port 80 and SSH access",
"SecurityGroupIngress" : [
{"IpProtocol" : "tcp", "FromPort" : "80", "ToPort" : "80", "CidrIp" : "0.0.0.0/0"},
{"IpProtocol" : "tcp", "FromPort" : "22", "ToPort" : "22", "CidrIp" : { "Ref" : "SSHLocation"}}
]
}
}
...
В котором мы открываем порт 22 для доступа с IP, переданного в параметре {"Ref" : "SSHLocation"}, и порт 80 — отовсюду.
Сохраняем, удаляем старый стек и создаём его заново (с другим именем, пока удаляется старый):
$ aws cloudformation delete-stack --stack-name VPConly1
$ aws cloudformation create-stack --stack-name VPConly2 --template-body file:////home//setevoy//PycharmProjects//Swarm-cluster/VPC_alone.template
{
"StackId": "arn:aws:cloudformation:eu-west-1:264418146286:stack/VPConly2/f63414a0-6384-11e6-8c8c-500c3cd570d2"
}
Проверим.
Находим описание всех созаднных в стеке ресурсов:
$ aws cloudformation list-stack-resources --stack-name VPConly2
{
"StackResourceSummaries": [
{
"ResourceType": "AWS::EC2::SecurityGroup",
"PhysicalResourceId": "VPConly2-MasterSecurityGroup-1TCMP3SIJOV5N",
"LastUpdatedTimestamp": "2016-08-16T07:42:39.218Z",
"ResourceStatus": "CREATE_COMPLETE",
"LogicalResourceId": "MasterSecurityGroup"
},
{
"ResourceType": "AWS::EC2::VPC",
"PhysicalResourceId": "vpc-72ab1516",
"LastUpdatedTimestamp": "2016-08-16T07:42:40.951Z",
"ResourceStatus": "CREATE_COMPLETE",
"LogicalResourceId": "VPC"
}
]
}
И по PhysicalResourceId группы безопасности — проверяем правила:
$ aws ec2 describe-security-groups --group-names VPConly2-MasterSecurityGroup-1TCMP3SIJOV5N --filters --query '[SecurityGroups[*].IpPermissions[*].{Port:FromPort,FromIP:IpRanges}]' --output text
80
FROMIP 0.0.0.0/0
22
FROMIP 0.0.0.0/0
Подсети
Далее — добавим две подсети — публичную 11.0.1.0/24, и приватную — 11.0.2.0/24. При этом — их блоки адресов надо иметь возможность переопределить во время создания стека, поэтому — вынесем их отдельными параметрами.
Добавляем два параметра для новых подсетей — PubNetCIDR и PrivNetCIDR:
...
"PubNetCIDR": {
"Description" : "The IP address range tin VPC block for Public subnet",
"Type": "String",
"Default": "11.0.1.0/24",
"AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
"ConstraintDescription": "must be a valid IP CIDR range of the form x.x.x.x/x."
},
"PrivNetCIDR": {
"Description" : "The IP address range tin VPC block for Private subnet",
"Type": "String",
"Default": "11.0.2.0/24",
"AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
"ConstraintDescription": "must be a valid IP CIDR range of the form x.x.x.x/x."
}
...
Теперь — два ресурса:
...
"PubSubnet" : {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": { "Ref": "VPC"},
"CidrBlock": { "Ref": "PubNetCIDR"},
"AvailabilityZone": { "Fn::Select" : [ "0", { "Fn::GetAZs" : "" } ]}
}
},
"PrivSubnet" : {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": { "Ref": "VPC"},
"CidrBlock": { "Ref": "PrivNetCIDR"},
"AvailabilityZone": { "Fn::Select" : [ "0", { "Fn::GetAZs" : "" } ]}
}
}
...
VpcId мы получим из значения, возвращаемого ресурсом VPC, CidrBlock — из определенных нами выше параметров, а AvailabilityZone — с помощью функции GetAZs.
Проверяем шаблон:
$ aws cloudformation validate-template --template-body file:////home//setevoy//PycharmProjects//Swarm-cluster/VPC_alone.template
{
"Description": "AWS CloudFormation Template Docker Swarm cluster in VPC",
"Parameters": [
{
"DefaultValue": "0.0.0.0/0",
"NoEcho": false,
"Description": "The IP address range that can be used to SSH to the EC2 instances",
"ParameterKey": "SSHLocation"
},
{
"DefaultValue": "11.0.2.0/24",
"NoEcho": false,
"Description": "The IP address range tin VPC block for Public subnet",
"ParameterKey": "PrivNetCIDR"
},
{
"DefaultValue": "11.0.1.0/24",
"NoEcho": false,
"Description": "The IP address range tin VPC block for Public subnet",
"ParameterKey": "PubNetCIDR"
},
{
"DefaultValue": "11.0.0.0/16",
"NoEcho": false,
"Description": "VPC CIDR IP addresses block",
"ParameterKey": "VPCCidrBlock"
}
]
}
Запускаем создание:
$ aws cloudformation delete-stack --stack-name VPConly2
$ aws cloudformation create-stack --stack-name VPConly3 --template-body file:////home//setevoy//PycharmProjects//Swarm-cluster/VPC_alone.template
{
"StackId": "arn:aws:cloudformation:eu-west-1:264418146286:stack/VPConly3/b3a9bf00-6392-11e6-9731-500c4233b6d2"
}
Проверяем созданные ресурсы:
$ aws cloudformation list-stack-resources --stack-name VPConly3
{
"StackResourceSummaries": [
{
"ResourceType": "AWS::EC2::SecurityGroup",
"PhysicalResourceId": "VPConly3-MasterSecurityGroup-QFU149RV4XM8",
"LastUpdatedTimestamp": "2016-08-16T09:21:01.300Z",
"ResourceStatus": "CREATE_COMPLETE",
"LogicalResourceId": "MasterSecurityGroup"
},
{
"ResourceType": "AWS::EC2::Subnet",
"PhysicalResourceId": "subnet-e39d0895",
"LastUpdatedTimestamp": "2016-08-16T09:21:26.706Z",
"ResourceStatus": "CREATE_COMPLETE",
"LogicalResourceId": "PrivSubnet"
},
{
"ResourceType": "AWS::EC2::Subnet",
"PhysicalResourceId": "subnet-e49d0892",
"LastUpdatedTimestamp": "2016-08-16T09:21:22.010Z",
"ResourceStatus": "CREATE_COMPLETE",
"LogicalResourceId": "PubSubnet"
},
{
"ResourceType": "AWS::EC2::VPC",
"PhysicalResourceId": "vpc-7f9a241b",
"LastUpdatedTimestamp": "2016-08-16T09:21:01.928Z",
"ResourceStatus": "CREATE_COMPLETE",
"LogicalResourceId": "VPC"
}
]
}
И созданные подсети:
$ aws ec2 describe-subnets --filters Name=vpc-id,Values=vpc-7f9a241b
{
"Subnets": [
{
"VpcId": "vpc-7f9a241b",
"Tags": [
{
"Value": "arn:aws:cloudformation:eu-west-1:264418146286:stack/VPConly3/b3a9bf00-6392-11e6-9731-500c4233b6d2",
"Key": "aws:cloudformation:stack-id"
},
{
"Value": "VPConly3",
"Key": "aws:cloudformation:stack-name"
},
{
"Value": "PubSubnet",
"Key": "aws:cloudformation:logical-id"
}
],
"CidrBlock": "11.0.1.0/24",
"MapPublicIpOnLaunch": false,
"DefaultForAz": false,
"State": "available",
"AvailabilityZone": "eu-west-1a",
"SubnetId": "subnet-e49d0892",
"AvailableIpAddressCount": 251
},
{
"VpcId": "vpc-7f9a241b",
"Tags": [
{
"Value": "arn:aws:cloudformation:eu-west-1:264418146286:stack/VPConly3/b3a9bf00-6392-11e6-9731-500c4233b6d2",
"Key": "aws:cloudformation:stack-id"
},
{
"Value": "PrivSubnet",
"Key": "aws:cloudformation:logical-id"
},
{
"Value": "VPConly3",
"Key": "aws:cloudformation:stack-name"
}
],
"CidrBlock": "11.0.2.0/24",
"MapPublicIpOnLaunch": false,
"DefaultForAz": false,
"State": "available",
"AvailabilityZone": "eu-west-1a",
"SubnetId": "subnet-e39d0895",
"AvailableIpAddressCount": 251
}
]
}
VPC Internet Gateway
Далее создаем VPC Internet Gateway.
В ресурсы добавляем:
...
"PubNetIGW" : {
"Type": "AWS::EC2::InternetGateway",
"Properties": {}
}
...
И подключение этого IGW к VPC по VpcID:
...
"AttachGateway" : {
"Type": "AWS::EC2::VPCGatewayAttachment",
"Properties": {
"VpcId": { "Ref": "VPC" },
"InternetGatewayId": { "Ref": "PubNetIGW" }
}
}
...
Запускаем:
$ aws cloudformation delete-stack --stack-name VPConly3
$ aws cloudformation create-stack --stack-name VPConly4 --template-body file:////home//setevoy//PycharmProjects//Swarm-cluster/VPC_alone.template
{
"StackId": "arn:aws:cloudformation:eu-west-1:264418146286:stack/VPConly4/f5034280-6394-11e6-8cff-500c42421e36"
}
После создания — проверяем по VPC ID:
$ aws ec2 describe-internet-gateways --filters Name=attachment.vpc-id,Values=vpc-9c9927f8
{
"InternetGateways": [
{
"Tags": [
{
"Value": "PubNetIGW",
"Key": "aws:cloudformation:logical-id"
},
{
"Value": "VPConly4",
"Key": "aws:cloudformation:stack-name"
},
{
"Value": "arn:aws:cloudformation:eu-west-1:264418146286:stack/VPConly4/f5034280-6394-11e6-8cff-500c42421e36",
"Key": "aws:cloudformation:stack-id"
}
],
"InternetGatewayId": "igw-f42d2091",
"Attachments": [
{
"State": "available",
"VpcId": "vpc-9c9927f8"
}
]
}
]
}
NAT Gateway и Elastic IP
Для NAT-инстанса нам потребуется публичный IP.
Добавляем ресурс для получения Elastic IP:
...
"NatEIP": {
"Type" : "AWS::EC2::EIP",
"Properties" : { "Domain" : "vpc" }
}
...
И создание реcурса NAT Gateway:
...
"NatGW": {
"Type" : "AWS::EC2::NatGateway",
"Properties" : {
"AllocationId" : { "Fn::GetAtt" : ["NatEIP", "AllocationId"]},
"SubnetId" : { "Ref": "PubSubnet"}
}
}
...
SubnetId мы получаем из ресурса PubSubnet (NAT инстанс будет в публичной сети), а AllocationId — через атрибут AllocationId ресурса NatEIP.
Запускаем:
$ aws cloudformation delete-stack --stack-name VPConly4
$ aws cloudformation create-stack --stack-name VPConly5 --template-body file:////home//setevoy//PycharmProjects//Swarm-cluster/VPC_alone.template
{
"StackId": "arn:aws:cloudformation:eu-west-1:264418146286:stack/VPConly5/7b518e20-6398-11e6-9a5d-50faeb59c0d2"
}
Route tables
Последним шагом в создании сети будет настройка маршрутизации из подсетей.
Публичная сеть — будет ходить через Internet Gateway PubNetIGW, а приватная — через NAT NatGW, который будет в публичной сети PubSubnet.
Для этого — создаём две таблицы маршрутизации:
...
"PublicRouteTable" : {
"Type" : "AWS::EC2::RouteTable",
"Properties" : {
"VpcId": { "Ref": "VPC" }
}
},
"PrivateRouteTable" : {
"Type" : "AWS::EC2::RouteTable",
"Properties" : {
"VpcId": { "Ref": "VPC" }
}
},
...
И добавляем в них правила. Правило для таблицы маршрутизации публичной сети — пускать трафик через созданный Internet Gataway, для приватной — всё через NAT Gateway:
...
"PublicRoute" : {
"Type": "AWS::EC2::Route",
"Properties": {
"RouteTableId": { "Ref": "PublicRouteTable" },
"DestinationCidrBlock": "0.0.0.0/0",
"GatewayId": { "Ref": "PubNetIGW" }
}
},
"PrivateRoute" : {
"Type": "AWS::EC2::Route",
"Properties": {
"RouteTableId": { "Ref": "PrivateRouteTable" },
"DestinationCidrBlock": "0.0.0.0/0",
"NatGatewayId": { "Ref": "NatGW" }
}
}
...
Таблицу мо-умолчанию, которая создаётся вместе с VPC — можно вообще не трогать.
Добавляем подключение этих таблиц маршрутизации к подсетям:
...
"PublicRouteAssociate": {
"Type" : "AWS::EC2::SubnetRouteTableAssociation",
"Properties" : {
"RouteTableId" : { "Ref": "PublicRouteTable"},
"SubnetId" : { "Ref": "PubSubnet"}
}
},
"PrivateRouteAssociate": {
"Type" : "AWS::EC2::SubnetRouteTableAssociation",
"Properties" : {
"RouteTableId" : { "Ref": "PrivateRouteTable"},
"SubnetId" : { "Ref": "PrivSubnet"}
}
}
...
Запускаем:
$ aws cloudformation delete-stack --stack-name VPConly5
$ aws cloudformation create-stack --stack-name VPConly6 --template-body file:////home//setevoy//PycharmProjects//Swarm-cluster/VPC_alone.template
{
"StackId": "arn:aws:cloudformation:eu-west-1:264418146286:stack/VPConly6/81f38640-639b-11e6-a87d-50faeb59c036"
}
Проверяем:
$ aws ec2 describe-route-tables --filters Name=vpc-id,Values=vpc-608f3104 --query '[RouteTables[*].[RouteTableId, Routes[*]]]'
[
[
[
"rtb-c5710ea1",
[
{
"GatewayId": "local",
"DestinationCidrBlock": "11.0.0.0/16",
"State": "active",
"Origin": "CreateRouteTable"
},
{
"Origin": "CreateRoute",
"DestinationCidrBlock": "0.0.0.0/0",
"NatGatewayId": "nat-03e3bc9d817d3ed1c",
"State": "active"
}
]
],
[
"rtb-c6710ea2",
[
{
"GatewayId": "local",
"DestinationCidrBlock": "11.0.0.0/16",
"State": "active",
"Origin": "CreateRouteTable"
},
{
"GatewayId": "igw-122b2677",
"DestinationCidrBlock": "0.0.0.0/0",
"State": "active",
"Origin": "CreateRoute"
}
]
],
[
"rtb-f9710e9d",
[
{
"GatewayId": "local",
"DestinationCidrBlock": "11.0.0.0/16",
"State": "active",
"Origin": "CreateRouteTable"
}
]
]
]
]
EC2
Теперь можно создавать инстансы EC2.
Нам потребуется: 2 ноды для мастер, 2 ноды для воркеров и 1 нода — для Consul.
Начнём с Master, остальные — по аналогии.
Добавляем параметр InstanceType для определения типа интанса:
...
"InstanceType" : {
"Description" : "Swarm hosts EC2 instance type",
"Type" : "String",
"Default" : "t2.nano",
"AllowedValues" : [ "t2.nano", "t2.micro", "t2.small" ],
"ConstraintDescription" : "must be a valid EC2 instance type."
}
...
Ресурс группы безопасности у нас уже есть:
...
"MasterSecurityGroup" : {
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"VpcId" : { "Ref": "VPC"},
"GroupDescription" : "Enable HTTP access via port 80 and SSH access",
"SecurityGroupIngress" : [
{"IpProtocol" : "tcp", "FromPort" : "80", "ToPort" : "80", "CidrIp" : "0.0.0.0/0"},
{"IpProtocol" : "tcp", "FromPort" : "22", "ToPort" : "22", "CidrIp" : { "Ref" : "SSHLocation"}}
]
}
},
...
Добавляем ресурс SwarmMaster0EIP для получения Public IP:
...
"SwarmMaster0EIP": {
"Type" : "AWS::EC2::EIP",
"Properties" : { "Domain" : "vpc" }
},
...
Сам EC2 инстанс:
...
"SwarmMaster0": {
"DependsOn" : "SwarmMaster0EIP",
"Type" : "AWS::EC2::Instance",
"Properties" : {
"Tags" : [ {"Key" : "Name", "Value" : "SwarmMaster0" } ],
"InstanceType" : { "Ref" : "InstanceType" },
"ImageId" : "ami-a7412ad4",
"AvailabilityZone": { "Fn::Select" : [ "0", { "Fn::GetAZs" : "" } ]},
"KeyName": "my-cluster",
"NetworkInterfaces" : [ {
"DeleteOnTermination": "true",
"DeviceIndex" : "0",
"SubnetId": {"Ref": "PubSubnet"},
"GroupSet": [ {"Ref": "MasterSecurityGroup"} ]
}]
}
},
...
И подключение EIP к этому EC2:
...
"SwarmMaster0AssociateEIP": {
"DependsOn" : "SwarmMaster0",
"Type": "AWS::EC2::EIPAssociation",
"Properties": {
"EIP": { "Ref": "SwarmMaster0EIP"},
"InstanceId": { "Ref": "SwarmMaster0"}
}
}
...
Запускаем:
$ aws cloudformation delete-stack --stack-name VPConly6
$ aws cloudformation create-stack --stack-name VPConly7 --template-body file:////home//setevoy//PycharmProjects//Swarm-cluster/VPC_alone.template
{
"StackId": "arn:aws:cloudformation:eu-west-1:264418146286:stack/VPConly8/38f73870-63c2-11e6-9b1a-50faeb542cd2"
}
Проверяем:
$ aws cloudformation describe-stack-events --stack-name VPConly7 --query '[StackEvents[8].[ResourceType,PhysicalResourceId,LogicalResourceId]]'
[
[
"AWS::EC2::Instance",
"i-4f768bc2",
"SwarmMaster0"
]
]
Пробуем SSH. находим IP инстанса:
$ aws ec2 describe-instances --instance-ids i-4f768bc2 --query '[Reservations[0].Instances[0].PublicIpAddress]' --output text 52.210.87.238
Проверяем:
$ telnet 52.210.87.238 22 Trying 52.210.87.238... Connected to 52.210.87.238. Escape character is '^]'. SSH-2.0-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2.7
Добавляем ещё один инстанс под второй мастер:
...
"SwarmMaster1EIP": {
"Type" : "AWS::EC2::EIP",
"Properties" : { "Domain" : "vpc" }
},
"SwarmMaster1": {
"DependsOn" : "SwarmMaster1EIP",
"Type" : "AWS::EC2::Instance",
"Properties" : {
"Tags" : [ {"Key" : "Name", "Value" : "SwarmMaster1" } ],
"InstanceType" : { "Ref" : "InstanceType" },
"ImageId" : "ami-a7412ad4",
"AvailabilityZone": { "Fn::Select" : [ "0", { "Fn::GetAZs" : "" } ]},
"KeyName": "my-cluster",
"NetworkInterfaces" : [ {
"DeleteOnTermination": "true",
"DeviceIndex" : "0",
"SubnetId": {"Ref": "PubSubnet"},
"GroupSet": [ {"Ref": "MasterSecurityGroup"} ]
}]
}
},
"SwarmMaster1AssociateEIP": {
"DependsOn" : "SwarmMaster1",
"Type": "AWS::EC2::EIPAssociation",
"Properties": {
"EIP": { "Ref": "SwarmMaster1EIP"},
"InstanceId": { "Ref": "SwarmMaster1"}
}
...
Для инстансов в приватной сети — создадим второй Security Group, в котором разрешено всем и всё:
...
"NodesSecurityGroup" : {
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"VpcId" : { "Ref" : "VPC" },
"GroupDescription" : "Enable SSH access via port 22",
"SecurityGroupIngress" : [ {
"IpProtocol": "tcp",
"FromPort": "0",
"ToPort": "65535",
"CidrIp": "0.0.0.0/0"
}
],
"SecurityGroupEgress": [
{
"IpProtocol": "tcp",
"FromPort": "0",
"ToPort": "65535",
"CidrIp": "0.0.0.0/0"
}
]
}
},
...
И три инстанса в приватной сети — под воркеры и Consul:
...
"SwarmNode0": {
"Type" : "AWS::EC2::Instance",
"Properties" : {
"Tags" : [ {"Key" : "Name", "Value" : "SwarmNode0" } ],
"InstanceType" : { "Ref" : "InstanceType" },
"ImageId" : "ami-a7412ad4",
"AvailabilityZone": { "Fn::Select" : [ "0", { "Fn::GetAZs" : "" } ]},
"KeyName": "my-cluster",
"NetworkInterfaces" : [ {
"DeleteOnTermination": "true",
"DeviceIndex" : "0",
"SubnetId": {"Ref": "PrivSubnet"},
"GroupSet": [ {"Ref": "NodesSecurityGroup"} ]
}]
}
},
"SwarmNode1": {
"Type" : "AWS::EC2::Instance",
"Properties" : {
"Tags" : [ {"Key" : "Name", "Value" : "SwarmNode1" } ],
"InstanceType" : { "Ref" : "InstanceType" },
"ImageId" : "ami-a7412ad4",
"AvailabilityZone": { "Fn::Select" : [ "0", { "Fn::GetAZs" : "" } ]},
"KeyName": "my-cluster",
"NetworkInterfaces" : [ {
"DeleteOnTermination": "true",
"DeviceIndex" : "0",
"SubnetId": {"Ref": "PrivSubnet"},
"GroupSet": [ {"Ref": "NodesSecurityGroup"} ]
}]
}
},
"Consul0": {
"Type" : "AWS::EC2::Instance",
"Properties" : {
"Tags" : [ {"Key" : "Name", "Value" : "Consul0" } ],
"InstanceType" : { "Ref" : "InstanceType" },
"ImageId" : "ami-a7412ad4",
"AvailabilityZone": { "Fn::Select" : [ "0", { "Fn::GetAZs" : "" } ]},
"KeyName": "my-cluster",
"NetworkInterfaces" : [ {
"DeleteOnTermination": "true",
"DeviceIndex" : "0",
"SubnetId": {"Ref": "PrivSubnet"},
"GroupSet": [ {"Ref": "NodesSecurityGroup"} ]
}]
}
}
...
Запускаем:
$ aws cloudformation create-stack --stack-name VPCfinalizing --template-body file:////home//setevoy//PycharmProjects//Swarm-cluster/VPC_alone.template
{
"StackId": "arn:aws:cloudformation:eu-west-1:264418146286:stack/VPCfinalizing/430ad7b0-63c5-11e6-ae9a-50a686326636"
}
Готово, проверяем:
$ ssh [email protected] -i ~/Temp/aws_cluster_prod/my-cluster.pem The authenticity of host '52.50.104.231 (52.50.104.231)' can't be established. ECDSA key fingerprint is 92:1c:8d:b9:d8:97:07:33:7e:81:c2:fb:d1:6e:2c:70. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '52.50.104.231' (ECDSA) to the list of known hosts. Welcome to Ubuntu 14.04.5 LTS (GNU/Linux 3.13.0-93-generic x86_64) ... ubuntu@ip-11-0-1-121:~$
Проверяем машину из приватной сети, например — Consul0:
ubuntu@ip-11-0-1-121:~$ telnet 11.0.2.110 22 Trying 11.0.2.110... Connected to 11.0.2.110. Escape character is '^]'. SSH-2.0-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2.7
Что можно улучшить:
- добавить
outputs; - вынести создание EC2 в отдельный шаблон, и подключить его через AWS CloudFormation Template Snippets;
- вынести
ImageIdиKeyNameв параметры.






