Mit allen verbunden Teil 1
This content is more than 4 years old and the cloud moves fast so some information may be slightly out of date.
Test Transit Gateway mit CloudFormation/taskCat (Teil 1) und kitchen/Inspec (Teil 2)
Test Transit Gateway mit taskCat und Inspec
Transit Gateway What is a Transit Gateway? - Amazon Virtual Private Cloud ist ein neuer AWS Service, der VPC Peering komplett ablösen kann. Zusätzlich kann damit auch ein “transitives” Peering gebaut werden.
Das heißt, anders als bei einer VPC Peering Verbindung, die immer nur zwei VPCs miteinander verbindet, werden hier alle Netze miteinander verbunden.
Das lohnt es sich genau zu testen! Diesen Test will ich hier möglichst vollautomatisiert aufbauen. Dafür brauche ich zwei BlogPosts. Dies ist Teil 1: Test von CloudFormation mit taskCat.
Es folgt später Teil 2: Test von Transit-Gateway Infrastruktur mit Inspec.
Die Versuchsanordnung
Test von CloudFormation mit taskCat
Für diese Test will ich drei VPCs miteinander verbinden. Für den Aufbau der VPCs nehme ich natürlich CloudFormation. Jetzt ist es wie häufig auch bei Transit Gateway so, dass der Dienst zuerst in Irland verfügbar war und später in Frankfurt. Die CloudFormation Templates sollen also in diesen beiden Regionen laufen. AWS nutzt selber [taskcat] um CloudFormation Templates in mehreren Regionen zu testen. Netter Nebeneffekt: TaskCat kann Cloudformation auch linten, so dass grobe Fehler schon vor dem Deployment gefunden werden.
Folgenden Ablauf will ich hier für den Test nehmen:
-
Erstellen der CloudFormation Templates
-
Konfiguration von taskCat
-
Syntax Check “linting”
-
Test der Templates in zwei Regionen
Erstellen der CloudFormations
Ich brauche drei VPCS. Der Einfachheit halber baue ich nur ein Subnet im VPC. Für Produktionsumgebungen ist das nur sehr selten eine gute Wahl, hier ist es die einfachste Variante.
-
VPC A Name: TransitGatewayDemoVPCA IP V4 CIDR Block: 10.0.1.0/24 Name: TransitGatewayDemoSubnetA
-
VPC B Name: TransitGatewayDemoVPCB IP V4 CIDR Block: 10.0.2.0/24 Name: TransitGatewayDemoSubnetB
-
VPC C Name: TransitGatewayDemoVPCC IP V4 CIDR Block: 10.0.3.0/24 Name: TransitGatewayDemoSubnetC
Jetzt will ich ja das Routing mit TransitGateway testen. Routenverfolgung mit traceroute
geht bei AWS nicht. Deswegen nehme ich kleine Instanzen mit einem Webserver. Dadurch kann man die Tests auch auf Testen von Security Groups ausweiten, wenn man das möchte. Die Security Group lässt - nur für diesen Test - ein Zugriff vom gesamten 10.0.0.0/16 Netz auf Port 80 zu. In den VPCs soll es also jeweils einen EC2 Instanz geben, die auf der IP 16 und Port 80 hört.
EC2 Instance:
- nginx
- Security Group “node” mit 80 frei für 10.0.0.0/16
- Name: TransitGatewayDemoSubnetAtoC
Das Template füttere ich mit Parametern für:
- einen Namen
- eine Cidr für das Netz
- einem ssh Key, falls ich doch eine manuellen Zugriff benötige
- eine IP für die Instanz
Eine kleines Detail für das AMI der Instanz:
Mappings:
AmazonLinuxAMI:
eu-west-1:
AMI: ami-08935252a36e25f85
eu-central-1:
AMI: ami-0cfbf4f6db41068ac
Hier muss ein Mapping erstellt werden, da die Templates ja ineu-central-1
und eu-west-1
laufen sollen. Die Templates sind in YAML CloudFormation geschrieben, so dass man die Lesbarkeit durch Kommentare verbessern kann: Z.B.
Resources:
#######
# VPC
####
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock:
Ref: Cidr
Tags:
- Key: Name
Value: !Sub VPC ${Name}
- Key: Project
Value: "demotransit"
Im UserData Bereich wird der Webserver konfiguriert:
UserData:
Fn::Base64: |
#!/bin/bash -xe
yum update -y
yum install -y httpd24
service httpd start
chkconfig httpd on
echo "Node A" >/var/www/html/index.html
taskCat Konfiguration
Nach Installation von taskCat (siehe taskcat) muss zuerst die Konfiguration erstellt werden. Für diese Demo sieht die Konfiguration folgendermaßen aus:
global:
owner: gglawe@tecracer.de
qsname: demo-transit-gateway
regions:
- eu-central-1
- eu-west-1
tests:
scenario-a:
parameter_input: debug_a.json
template_file: testa.yaml
scenario-b:
parameter_input: debug_b.json
template_file: testb.yaml
scenario-c:
parameter_input: debug_c.json
template_file: testc.yaml
In den Regionen wird eingestellt, für welche Regionen die CloudFormation Templates ausgeführt werden. In der tests: Sektion werden jeweils die Templates und die Parameter konfiguriert. taskCat kann dynamisch Werte ersetzen. Hier arbeiten wir mit statischen Parametern. Die Parameterdatei “debug_a.json” sieht z.B. so aus:
[
{
"ParameterKey": "Cidr",
"ParameterValue": "10.0.1.0/24"
},
{
"ParameterKey": "Name",
"ParameterValue": "Demo A"
},
{
"ParameterKey": "ip",
"ParameterValue": "10.0.1.16"
},
{
"ParameterKey": "key",
"ParameterValue": "default-lab-key"
}
]
Statische Parameter werden als Paar von ParameterKey und ParameterValue definiert. Eigentlich könnte man taskCat jetzt schon aufrufen, es gibt aber noch zwei Besonderheiten. Zur Zeit (Release 0.8.9) erwartet taskCat die Templates im Unterverzeichnis “templates”. Die Template und Parameter Dateien müssen also in eben diesem Unterverzeichnis liegen.
Die zweite Besonderheit ist das Projektverzeichnis und die Protokolldateien. Im Beispiel ist konfiguriert, das qsname “demo-transit-gateway” ist. Das heißt, dass taskCat diesen Namen als Verzeichnis erwartet, in dem es aufgerufen wird. Die Templates und Parameter liegen also in “demo-transit-gateway/templates”.
Die Protokolldateien werden automatisch in ../taskcat_outputs/
geschrieben. Idee dabei ist, dass die Testprotokolldateien nicht zum Projekt gehören denke ich.
“Syntax Check” Liniting
Nach der Konfiguration kann taskCat zum Linten aufgerufen werden: taskcat -c ci/taskcat.yml -l
. Findet das lining keine Fehler sieht die Ausgabe in etwa so aus:
[]
Ich hatte zu Anfang kein AllowedPattern
für die Cidr in den CloudFormation Parametern angegeben. Das wurde prompt angemahnt:
[ERROR ] :Lint detected issues for test scenario-a on template demo-transit-gateway/templates/testa.yaml:
[INFO ] : line 13 [W2509] [CIDR Parameters have allowed values] (AllowedPattern and/or AllowedValues for Parameter should be
specified at Parameters/Cidr. Example for AllowedPattern: "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-
5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$")
[ERROR ] :Li
Ein bisschen zu genau ist das Linting bei den numerischen Parametern innerhalb des Templates. Damit ist der erste Teil des Test für Cloudformation abgeschlossen.
Test Ausführbarkeit CloudFormation in mehreren Regionen
Bei dem Test der Cloudformation hat sich schnell gezeigt, dass die Verwendung von CloudFormation Exports keine gute Idee ist, da diese global sind. Das führt dazu dass, wenn es diesen Export bereits gibt, einen Fehler gibt. Das widerspricht der Anforderung, dass die Templates auch mehrfach in einer Region in einem Account ausgeführt werden können sollen. Ist die Ausführung dann fehlerfrei, sieht der Report so aus:
Die kompletten Logs können aus der Übersicht aufgerufen werden. Im Beispiel sieht das Log für scenario-a so aus :
-----------------------------------------------------------------------------
Region: eu-central-1
StackName: tCaT-tag-scenario-a-89b456d8
*****************************************************************************
ResourceStatusReason:
Stack launch was successful
*****************************************************************************
*****************************************************************************
Events:
TimeStamp ResourceStatus ResourceType LogicalResourceId ResourceStatusReason
-------------------------------- ------------------ ------------------------------------- ---------------------------------- ---------------------------
2018-12-11 21:03:38.313000+00:00 CREATE_COMPLETE AWS::CloudFormation::Stack tCaT-tag-scenario-a-89b456d8
2018-12-11 21:03:36.310000+00:00 CREATE_COMPLETE AWS::EC2::Instance MyEC2Instance
2018-12-11 21:03:19.798000+00:00 CREATE_COMPLETE AWS::EC2::SubnetRouteTableAssociation PublicSubnet1RouteTableAssociation
2018-12-11 21:03:18.756000+00:00 CREATE_COMPLETE AWS::EC2::Route DefaultPublicRoute
2018-12-11 21:03:04.381000+00:00 CREATE_IN_PROGRESS AWS::EC2::SubnetRouteTableAssociation PublicSubnet1RouteTableAssociation Resource creation Initiated
2018-12-11 21:03:04.323000+00:00 CREATE_IN_PROGRESS AWS::EC2::Instance MyEC2Instance Resource creation Initiated
2018-12-11 21:03:03.340000+00:00 CREATE_IN_PROGRESS AWS::EC2::Route DefaultPublicRoute Resource creation Initiated
2018-12-11 21:03:03.307000+00:00 CREATE_IN_PROGRESS AWS::EC2::SubnetRouteTableAssociation PublicSubnet1RouteTableAssociation
2018-12-11 21:03:03.171000+00:00 CREATE_IN_PROGRESS AWS::EC2::Instance MyEC2Instance
2018-12-11 21:03:02.642000+00:00 CREATE_IN_PROGRESS AWS::EC2::Route DefaultPublicRoute
2018-12-11 21:03:00.281000+00:00 CREATE_COMPLETE AWS::EC2::Subnet PublicSubnet1
2018-12-11 21:02:59.537000+00:00 CREATE_COMPLETE AWS::EC2::VPCGatewayAttachment InternetGatewayAttachment
2018-12-11 21:02:48.991000+00:00 CREATE_COMPLETE AWS::EC2::SecurityGroup NodeSecurityGroup
2018-12-11 21:02:48.123000+00:00 CREATE_IN_PROGRESS AWS::EC2::SecurityGroup NodeSecurityGroup Resource creation Initiated
2018-12-11 21:02:44.848000+00:00 CREATE_COMPLETE AWS::EC2::RouteTable PublicRouteTable
2018-12-11 21:02:44.110000+00:00 CREATE_IN_PROGRESS AWS::EC2::VPCGatewayAttachment InternetGatewayAttachment Resource creation Initiated
2018-12-11 21:02:44.041000+00:00 CREATE_IN_PROGRESS AWS::EC2::Subnet PublicSubnet1 Resource creation Initiated
2018-12-11 21:02:43.728000+00:00 CREATE_IN_PROGRESS AWS::EC2::VPCGatewayAttachment InternetGatewayAttachment
2018-12-11 21:02:43.632000+00:00 CREATE_IN_PROGRESS AWS::EC2::RouteTable PublicRouteTable Resource creation Initiated
2018-12-11 21:02:43.537000+00:00 CREATE_IN_PROGRESS AWS::EC2::Subnet PublicSubnet1
2018-12-11 21:02:43.472000+00:00 CREATE_IN_PROGRESS AWS::EC2::SecurityGroup NodeSecurityGroup
2018-12-11 21:02:43.222000+00:00 CREATE_IN_PROGRESS AWS::EC2::RouteTable PublicRouteTable
2018-12-11 21:02:40.675000+00:00 CREATE_COMPLETE AWS::EC2::VPC VPC
2018-12-11 21:02:39.810000+00:00 CREATE_COMPLETE AWS::EC2::InternetGateway InternetGateway
2018-12-11 21:02:24.131000+00:00 CREATE_IN_PROGRESS AWS::EC2::VPC VPC Resource creation Initiated
2018-12-11 21:02:23.806000+00:00 CREATE_IN_PROGRESS AWS::EC2::InternetGateway InternetGateway Resource creation Initiated
2018-12-11 21:02:23.665000+00:00 CREATE_IN_PROGRESS AWS::EC2::VPC VPC
2018-12-11 21:02:23.336000+00:00 CREATE_IN_PROGRESS AWS::EC2::InternetGateway InternetGateway
2018-12-11 21:02:20.035000+00:00 CREATE_IN_PROGRESS AWS::CloudFormation::Stack tCaT-tag-scenario-a-89b456d8 User Initiated
*****************************************************************************
-----------------------------------------------------------------------------
Tested on: Tuesday, 11. December 2018 10:05PM
-----------------------------------------------------------------------------
Fertig getestet können die Templates deployed werden. Ich nehme Cloudsaws zu Hilfe. Dieses Tool haben wir hier im Blog schon beschrieben.
Außerdem habe ich alle Schritte zusammen in ein Makefile gepackt, so dass das Deployment mit make deploy
durchgeführt wird. Das Makefile:
.DEFAULT_GOAL := help
stacka = demo-vpc-a
stackb = demo-vpc-b
stackc = demo-vpc-c
templatea = stacks/$(stacka)/template.yaml
templateb = stacks/$(stackb)/template.yaml
templatec = stacks/$(stackc)/template.yaml
region = eu-west-1
help:
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
copy:
cp $(templatea) templates/testa.yaml
cp $(templateb) templates/testb.yaml
cp $(templatec) templates/testc.yaml
deploy: ## Deploy stack
clouds -r $(region) update -c --events $(stackb) &
clouds -r $(region) update -c --events $(stackc) &
clouds -r $(region) update -c --events $(stacka)
delete: ## Delete Stack
clouds -r $(region) delete -f --events $(stacka) &
clouds -r $(region) delete -f --events $(stackb) &
clouds -r $(region) delete -f --events $(stackc) &
test-cfn: copy ## Integration Test: CloudFormation test in different regions with taskcat
taskcat -c ci/taskcat.yml
report-cfn-test: ## Show integration test report
open ../taskcat_outputs/index.html
lint-cfn: copy ## Linting of Template
taskcat -c ci/taskcat.yml -l
Eine Besonderheit beim Makefile ist es hier, dass mit make
oder mit make help
eine kleine Anleitung für die Schritte angezeigt wird. Das target “copy” sorgt dafür, dass die CloudFormation Templates, die Clouds-aws unter dem Verzeichnis “stacks” erwartet in das Verzeichnis “templates” kopiert wird, wo taskCat sie erwartet. Der Lifecycle der CloudFormation Entwicklung wird damit sehr einfach:
-
Edit Templates
-
make lint-cfn
, Templates editieren bis keine Fehler mehr auftreten -
make test-cfn
-
make report-cfn-test
um die Reportseite anzusehen -
Wenn keine Fehler mehr auftreten:
make deploy
Und damit habe ich meine drei Test VPCs mit Instanzen. Den kompletten Code gibt es in ein paar Wochen mit dem zweiten Teil zusammen.
Photo by John Carlisle on Unsplash
Linkliste