Пошаговый процесс написания шаблона для 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
в параметры.