[PYTHON] Automatisation de la construction de l'infrastructure avec CloudFromation + troposphère + AWS Lambda

J'ai essayé de créer un outil de création de modèle pour CloudFormation en utilisant la troposphère. De plus, en exécutant l'outil créé sur Lambda, j'ai essayé de créer un modèle simplement en plaçant la feuille de paramètres sur S3.

Le format JSON est difficile à écrire.

Récemment, j'ai eu l'opportunité de toucher CloudFormation dans mon entreprise. Je pense que le goulot d'étranglement dans l'utilisation de CloudFormation est le fichier au format JSON.

python


{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Description": "hogehoge",
    "Resources": {
        "test1": {
            "Properties": {
                "CidrBlock": "10.1.0.0/16",
                "EnableDnsHostnames": "true",
                "EnableDnsSupport": "true",
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": "test1"
                    }
                ]
            },
            "Type": "AWS::EC2::VPC"
        },
        "test2": {
            "Properties": {
                "CidrBlock": "10.2.0.0/16",
                "EnableDnsHostnames": "true",
                "EnableDnsSupport": "true",
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": "test2"
                    }
                ]
            },
            "Type": "AWS::EC2::VPC"
        }
    }
}

Le simple fait de créer deux VPC ressemble à ceci, donc je pense que c'est assez artisanal d'écrire ceci à la main.

Qu'est-ce que la troposphère

troposphere est un outil pour créer un tel fichier au format JSON en l'écrivant en Python. https://github.com/cloudtools/troposphere Le code ci-dessus peut également être écrit d'une manière facile à lire comme suit en l'écrivant en utilisant tropical.

python


import json
from troposphere import Tags,Template
from troposphere.ec2 import VPC
t = Template()
t.add_version("2010-09-09")
t.add_description("hogehoge")
t.add_resource(VPC(
              "test1",
              EnableDnsSupport="true",
              CidrBlock="10.1.0.0/16",
              EnableDnsHostnames="true",
              Tags=Tags(
                    Name="test1"
                    )
              )) 
t.add_resource(VPC(
              "test1",
              EnableDnsSupport="true",
              CidrBlock="10.2.0.0/16",
              EnableDnsHostnames="true",
              Tags=Tags(
                    Name="test2"
                    )
              ))
json_template = t.to_json()
print(json_template)                

L'utilisation de base est de décrire le nom et la description de la version avec add_version et add_description, puis d'ajouter plus de ressources à créer avec add_resource. Ce n'est pas beaucoup plus facile à lire, mais je pense que c'est un peu mieux que de l'écrire au format JSON. En outre, non seulement c'est plus facile à voir, mais le fait est que vous pouvez utiliser Python pour et si des instructions. Il est possible de décrire facilement une grande quantité de ressources en décrivant en passant plusieurs blocs CIDR et noms sous forme de tableau.

python


import json
from troposphere import Tags,Template
from troposphere.ec2 import VPC
t = Template()
t.add_version("2010-09-09")
t.add_description("hogehoge")
VPC_CidrBlockList = ["10.1.0.0/16","10.2.0.0/16"]
VPC_TagsNameList = ["test1","test2"]
for (Address,Tag_Name) in zip(VPC_CidrBlockList,VPC_TagNameList):
t.add_resource(VPC(
              Tag_Name,
              EnableDnsSupport="true",
              CidrBlock=Address,
              EnableDnsHostnames="true",
              Tags=Tags(
                    Name=Tag_Name
                    )
              )) 
json_template = t.to_json()
print(json_template)                

Apportez la valeur définie de l'extérieur.

À propos, dans l'état ci-dessus, les valeurs de réglage telles que le bloc CIDR et le nom seront écrites dans le script, mais cela est difficile à utiliser. Lisons les paramètres de l'extérieur et stockons-les dans un tableau afin qu'ils puissent être utilisés. Dans ce cas, deux types d'informations sont nécessaires en tant que paramètres (bloc CIDR, nom), créez donc une feuille de paramètres comme indiqué ci-dessous et enregistrez-la sous forme de fichier texte. 1ère ligne 10.1.0.0/16, 10.2.0.0/16 Test de 2e ligne1, test2

Après avoir créé un fichier texte, ouvrez et chargez d'abord ce fichier texte.

python


f = open('test.txt')
test = f.read()
f.close

Les données sont maintenant stockées dans le test. Cependant, dans cet état, la première ligne et la deuxième ligne ne sont pas séparées. Utilisez donc des lignes de fractionnement pour stocker chaque ligne sous forme de tableau.

python


test_list= test.splitlines()

Cela créera un tableau test_list avec chaque ligne comme élément. ["10.1.0.0/16,10.2.0.0/16","test1,test2"] De plus, ici, split est utilisé pour créer un tableau de chaque paramètre.

python


VPC_CidrBlockList = test_list[0].split(',')
VPC_TagNameList = test_list[1].split(',')

Vous avez maintenant créé un tableau de paramètres. Si vous intégrez ces opérations et modifiez le script précédent, ce sera comme suit.

python


import json
from troposphere import Tags,Template
from troposphere.ec2 import VPC

f = open('test.txt')
test = f.read()
f.close
test_list= test.splitlines()
VPC_CidrBlockList = test_list[0].split(',')
VPC_TagNameList = test_list[1].split(',')

t = Template()
t.add_version("2010-09-09")
t.add_description("hogehoge")
for (Address,Tag_Name) in zip(VPC_CidrBlockList,VPC_TagNameList):
t.add_resource(VPC(
              Tag_Name,
              EnableDnsSupport="true",
              CidrBlock=Address,
              EnableDnsHostnames="true",
              Tags=Tags(
                    Name=Tag_Name
                    )
              )) 
json_template = t.to_json()
print(json_template)                

Vous pouvez désormais créer plusieurs VPC en fonction des paramètres répertoriés dans la feuille de paramètres.

Essayez d'utiliser AWS Lambda.

La partie de base de l'utilisation de Lambda reste la même, mais le processus d'acquisition de la feuille de paramètres du compartiment S3 et le processus de téléchargement du modèle créé dans le compartiment S3 ont été ajoutés.

python


# coding: utf-8

import json
import urllib
import boto3
from troposphere import Tags,Template
from troposphere.ec2 import VPC
from datetime import datetime

basename = datetime.now().strftime("%Y%m%d-%H%M%S")

print('Loading function')

s3 = boto3.resource('s3')

def lambda_handler(event, context):
        #print("Received event: " + json.dumps(event, indent=2))

        # Get the object from the event and show its content type
        bucket = event['Records'][0]['s3']['bucket']['name']
        key = urllib.unquote_plus(event['Records'][0]['s3']['object']['key']).decode('utf8')
        print ("buket:" + bucket)
        print ("key:" + key)
        obj = s3.Object(bucket,key)
        response= obj.get()
        body = response['Body'].read()
        body_list= body.splitlines()
        # u'Créer un VPC'
        VPC_CidrBlockList = body_list[0].split(',')
        VPC_TagNameList= body_list[1].split(',')

        t = Template()
        t.add_version("2010-09-09")
        t.add_description("hogehoge")
        for (Address,Tag_Name) in zip(VPC_CidrBlockList,VPC_TagNameList):
            t.add_resource(VPC(
                  Tag_Name,
                  EnableDnsSupport="true",
                  CidrBlock=Address,
                  EnableDnsHostnames="true",
                  Tags=Tags(
                        Name=Tag_Name
                  )
            )) 
        json_template = t.to_json()
        bucket = s3.Bucket('template_test')
        obj = bucket.Object('json-template-' + basename + ' .txt')
        response = obj.put(
                       Body=json_template.encode('utf-8'),
                       ContentEncoding='utf-8',
                       ContentType='text/plane'
                    )
        print(json_template)                

Vous pouvez également le définir de manière plus flexible en modifiant les éléments à définir en tant que variables (tels que "EnableDnsHostnames" dans VPC). De plus, si vous décrivez d'autres ressources de cette manière, vous pouvez créer automatiquement des modèles tels que des sous-réseaux et des groupes de sécurité ainsi que des VPC.

Recommended Posts

Automatisation de la construction de l'infrastructure avec CloudFromation + troposphère + AWS Lambda
PyTorch avec AWS Lambda [importation Lambda]
Construction de l'environnement Ruby avec AWS EC2
[AWS] Créer une API avec API Gateway + Lambda
Notifier HipChat avec AWS Lambda (Python)
[AWS] Utilisation de fichiers ini avec Lambda [Python]
Connectez-vous à s3 avec AWS Lambda Python
[AWS] Faites des choses de type SSI avec S3 / Lambda
Je viens de faire FizzBuzz avec AWS Lambda
[AWS SAM] Créer une API avec DynamoDB + Lambda + API Gateway
Grattage sans serveur régulier avec AWS lambda + scrapy Part 1.8
LINE BOT avec Python + AWS Lambda + API Gateway
Application sans serveur avec AWS SAM! (APIGATEWAY + Lambda (Python))
[AWS] Essayez de tracer API Gateway + Lambda avec X-Ray
J'ai essayé de connecter AWS Lambda à d'autres services
Pages HTML dynamiques créées avec AWS Lambda et Python
[AWS] Play with Step Functions (SAM + Lambda) Part.3 (Branch)
Déployer la fonction Python 3 avec Serverless Framework sur AWS Lambda
Créer une couche pour AWS Lambda Python dans Docker
[AWS] Play with Step Functions (SAM + Lambda) Part.1 (Basic)
Je veux AWS Lambda avec Python sur Mac!
Gérer la rétention des groupes de journaux Amazon CloudWatch avec AWS Lambda
Créez des tweets ordinaires comme une flotte avec AWS Lambda et Python
[AWS] Play with Step Functions (SAM + Lambda) Part.2 (Paramètres)