В продолжение/дополнение постов Prometheus: AWS EC2 service discovery и AWS: настройка VPC peering — пример настройки VPC peering в шаблонах стеков CloudFormation.
Идея следующая:
- создадим стек monitor — он будет имитировать стек мониторинга
- создадим стек application — он будет имитировать стек приложения
- application должен будет запросить пиринг с VPC из стека monitor, что бы Prometheus в стеке monitor смог использовать service discovery
ec2_sd_configsв стеке application
Документация — тут>>> и тут>>>.
Что бы сделать запрос на создание peering connection — надо найти VPC ID из стека monitor.
Для этого — добавим в Outputs шаблона monitor вывод VPC ID, а потом используем Fn::ImportValue в шаблоне application, что бы выполнить запрос на пиринг.
Используем существующий шаблон vpc_ec2_stack.json, копируем его:
[simterm]
$ cp ~/Work/RTFM/Github/setevoy-aws-templates/vpc_ec2_stack.json vpc_monitor_stack.json $ cp ~/Work/RTFM/Github/setevoy-aws-templates/vpc_ec2_stack.json vpc_application_stack.json
[/simterm]
Получившиеся в результате шаблоны доступны в Github:
- стек monitor —
vpc_peering_accepter.json - стек application —
vpc_peering_requester.json
Не забываем поменять блоки адресов для VPC в обоих шаблонах, что они не пересекались, иначе получим ошибку «VpcPeeringConnection failed to stabilize. State: [failed]» и «Failed due to incorrect VPC-ID, Account ID, or overlapping CIDR range«.
Например для стека monitor:
...
"VPCCIDRBlock": {
"Description": "VPC CidrBlock",
"Type": "String",
"Default": "10.0.0.0/16"
},
"PublicSubnetCIDR": {
"Description": "Public Subnet CIDR",
"Type": "String",
"Default": "10.0.1.0/24"
},
...
И для стека application:
...
"VPCCIDRBlock": {
"Description": "VPC CidrBlock",
"Type": "String",
"Default": "10.1.0.0/16"
},
"PublicSubnetCIDR": {
"Description": "Public Subnet CIDR",
"Type": "String",
"Default": "10.1.0.0/24"
},
...
Запрос на создание пиринга будет выполняться из стека application к стеку monitor.
Стек monitor будет «статичным», т.е. — он «уже есть» (сначала будет разворачиваться мониторинг, а потом к нему — добавляться стеки с приложениями), и его параметры известы, поэтому их мы будем передавать в создаваемые стеки приложений через параметры в шаблоне monitor.
Параметры же создаваемых стеков (application в данном случае) — неизвестны, поэтому их мы будем экспортировать в Outputs новых стеков, а потом эти значения использовать в Fn::ImportValue для стека monitor.
Перед тем, как начать — небольшая заметка по импортам и экспортам данных: при первой попытке создания стеков — у меня получилось залочить два стека так, что ни изменить, ни удалить их нельзя было. Проблема заключалась в том, что стек monitor экспортировал в Outputs свой VPC ID и свою подсеть, которые импортировались в стеке application. А стек application, в свою очередь, экспортировал свою подсеть и VpcPeeringConnectionId, которая импортировались в стеке monitor для создания маршрута. В результате — получилась взаминая связь между стеками, которая не позволяла удалить один из стеков, т.к. его данные использовались в другом. Подробнее про ограничения см. в документации Fn::ImportValue.
Содержание
AWS::EC2::VPCPeeringConnection
В шаблоне стека application добавляем параметр MonitorVPCID:
...
"MonitorVPCID": {
"Description": "Monitoring VPC ID to be used to request peering connection",
"Type": "String",
"Default": "vpc-00d98968"
},
...
Добавляем ресурс AWS::EC2::VPCPeeringConnection:
...
"VPCPeeringConnection": {
"Type": "AWS::EC2::VPCPeeringConnection",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"PeerVpcId": {
"Ref": "MonitorVPCID"
}
}
},
...
Стек monitor уже создан.
Создаём стек appliсation:
[simterm]
$ aws --profile btrm-mon cloudformation create-stack --stack-name application --template-body file://vpc_application_stack.json --disable-rollback
[/simterm]
Проверяем статус пиринга:
[simterm]
$ aws --profile btrm-mon ec2 describe-vpc-peering-connections --filters Name=vpc-peering-connection-id,Values=pcx-a8427bc1 --query '[VpcPeeringConnections[*].Status.Message]' --output text Active
[/simterm]
Т.к. обе VPC принадлежат одному пользователю — то запрос на пиринг принимается автоматически.
В панели управления:
Теперь надо обновить таблицы маршрутизации обоих стеков.
AWS::EC2::Route
Для этого потребуется:
- в стек monitor добавить параметр с именем стека application
- в стек monitor добавить ресурс
AWS::EC2::Route, который будет:- с помощью
Fn::ImportValueполучать значение дляDestinationCidrBlockиз стека application — его параметрPublicSubnetCIDR - с помощью
Fn::ImportValueполучатьVpcPeeringConnectionIdиз стека application — его ресурсVPCPeeringConnection
- с помощью
- в стек application добавить параметр с CIDR подсети (или всей VPC) стека monitor
- в стек application добавить в
Outputsэкспорт егоPublicSubnetCIDR, что бы его мог использовать стек monitor - в стек application добавить в
Outputsэкспорт егоVpcPeeringConnectionId - в стек application добавить ещё один ресурс
AWS::EC2::Route, который будет:- использоват параметр
DestinationCidrBlock, в котором указывается сеть стека monitor — егоPublicSubnetCIDR - использовать
VpcPeeringConnectionIdиз стекаmonitor— его ресурсVPCPeeringConnection
- использоват параметр
Route стека application
Сначала обновляем стек application — добавляем параметр с подсетью стека monitor:
...
"MonitorPublicSubnet": {
"Description": "Stack Name to be used to add routes",
"Type": "String",
"Default": "10.0.1.0/24"
},
...
И добавляем новый роут:
...
"PeeringRouteToMonitorStackSubnet": {
"Type": "AWS::EC2::Route",
"Properties": {
"RouteTableId": {
"Ref": "PublicRouteTable"
},
"DestinationCidrBlock": {
"Ref": "MonitorPublicSubnet"
},
"VpcPeeringConnectionId": {
"Ref": "VPCPeeringConnection"
}
}
},
...
Обновляем его Outputs, добавляем экспорт значений для импорта в стеке monitor — PublicSubnetCIDR и VPCPeeringConnectionID:
...
"PublicSubnetCIDR" : {
"Description" : "Own Subnet CIDR to be used in the monitor's stack route",
"Value" : {"Ref" : "PublicSubnetCIDR"},
"Export" : {
"Name" : {"Fn::Sub": "${AWS::StackName}-PublicSubnetCIDR" }
}
},
"VPCPeeringConnectionID" : {
"Description" : "VPD ID to a Peering connection with",
"Value" : {"Ref" : "VPCPeeringConnection"},
"Export" : {
"Name" : {"Fn::Sub": "${AWS::StackName}-VPCPeeringConnectionID" }
}
}
...
Обновляем стек:
[simterm]
$ aws --profile btrm-mon cloudformation update-stack --stack-name application --template-body file://vpc_application_stack.json
[/simterm]
Проверяем Outputs:
Проверяем маршруты:
Route стека monitor
Обновляем шаблон для стека monitor.
Добавляем параметр с именем стека, который будет подключаться (при доабвлении новых стеков с новыми приложениями — просто добавим новые параметры в стек monitor с их именами и новые ресурсы роутов):
...
"ApplicationRouteStackName": {
"Description": "Stack Name to be used to add routes",
"Type": "String",
"Default": "application"
},
...
Далее — ресурс AWS::EC2::Route будет аналогичен ресурсу стека application, но тут можем использовать cross-stack ссылки на Outputs стека application:
...
"PeeringRouteToApplicationSubnet": {
"Type": "AWS::EC2::Route",
"Properties": {
"RouteTableId": {
"Ref": "PublicRouteTable"
},
"DestinationCidrBlock": {
"Fn::ImportValue": {"Fn::Sub" : "${ApplicationRouteStackName}-PublicSubnetCIDR"}
},
"VpcPeeringConnectionId": {
"Fn::ImportValue": {"Fn::Sub" : "${ApplicationRouteStackName}-VPCPeeringConnectionID"}
}
}
},
...
Тут через Fn::ImportValue мы получаем значения PublicSubnetCIDR и VPCPeeringConnectionID из Outputs стека application.
Обновляем стек monitor:
[simterm]
$ aws --profile btrm-mon cloudformation update-stack --stack-name monitor --template-body file://vpc_monitor_stack.json
[/simterm]
Проверяем его маршруты:
Пробуем пинг с EC2 в стеке monitor к EC2 в стеке application, используя приватный IP:
[simterm]
$ ssh [email protected] -i setevoy-testing-ohio.pem 'ip a s eth0 | grep -w inet; ping -c 1 10.1.0.141' The authenticity of host '18.217.222.6 (18.217.222.6)' can't be established. ECDSA key fingerprint is SHA256:0L83Mz5D2DFGBrIzov7E7YLWwOvgZNCMycLLkgp7x20. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '18.217.222.6' (ECDSA) to the list of known hosts. inet 10.0.1.221/24 brd 10.0.1.255 scope global eth0 PING 10.1.0.141 (10.1.0.141) 56(84) bytes of data. 64 bytes from 10.1.0.141: icmp_seq=1 ttl=64 time=0.477 ms --- 10.1.0.141 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 0.477/0.477/0.477/0.000 ms
[/simterm]
И обратно — с EC2 в стеке application к EC2 в стеке monitor:
[simterm]
$ ssh [email protected] -i setevoy-testing-ohio.pem 'ip a s eth0 | grep -w inet; ping -c 1 10.0.1.221' The authenticity of host '18.219.246.166 (18.219.246.166)' can't be established. ECDSA key fingerprint is SHA256:Gnz/KbfZ1hw2p6eKuo4WuVFSstzkBRMgTFmNhD9c6uU. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '18.219.246.166' (ECDSA) to the list of known hosts. inet 10.1.0.141/24 brd 10.1.0.255 scope global eth0 PING 10.0.1.221 (10.0.1.221) 56(84) bytes of data. 64 bytes from 10.0.1.221: icmp_seq=1 ttl=64 time=0.408 ms --- 10.0.1.221 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 0.408/0.408/0.408/0.000 ms
[/simterm]
Готово.








