Kontakt: +49 511 59095 – 942

Mit allen verbunden Teil 1

Thumbnail

Test Transit Gateway mit CloudFormation/taskCat (Teil 1) und kitchen/Inspec (Teil 2)

Zu 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:

1) Erstellen der CloudFormation Templates

2) Konfiguration von taskCat

3) Syntax Check “linting”

4) 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.

1) VPC A Name: TransitGatewayDemoVPCA IP V4 CIDR Block: 10.0.1.0/24 Name: TransitGatewayDemoSubnetA

2) VPC B Name: TransitGatewayDemoVPCB IP V4 CIDR Block: 10.0.2.0/24 Name: TransitGatewayDemoSubnetB

3) 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:

  1. Edit Templates

  2. make lint-cfn, Templates editieren bis keine Fehler mehr auftreten

  3. make test-cfn

  4. make report-cfn-test um die Reportseite anzusehen

  5. 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


Teilen