[PYTHON] J'ai essayé AWS CDK!

Introduction un peu longue

À propos de cet article

Récemment, je n'ai pas écrit beaucoup d'articles «J'ai essayé». En effet, les sites Web officiels sont si vastes que vous ne faites que tracer les sites Web officiels.

** Cette fois, je connaissais AWS CDK et j'ai été profondément ému, donc je vais l'écrire tel quel. ** **

Qu'est-ce que CDK?

Il sera cité sur le site officiel à la fois, mais vous pouvez créer des ressources AWS dans un langage de programmation familier sans utiliser CloudFormation ou Teraform! !! ** C'est maintenant! C'est trop maintenant! !! ** **

Le kit de développement AWS Cloud (AWS CDK) est un cadre de développement logiciel open source pour la modélisation et le provisionnement de ressources d'application cloud à l'aide de langages de programmation familiers.

https://aws.amazon.com/jp/cdk/

Comment as-tu su

Dans les informations fournies par les membres de l'équipe lors des activités d'acquisition technique en interne, l'AWS CDK a été brièvement mentionnée.
Au début, je n'en connaissais pas l'existence et je pensais à quelque chose comme une erreur dans le SDK AWS.

Je ne vais pas y entrer car cela s'écarte du sujet principal, mais les informations qui circulent sont très utiles! Je recommande vivement de le lire. https://tomomano.gitlab.io/intro-aws/

## Que mentionner dans cet article CDK a beaucoup d'exemples. https://github.com/aws-samples/aws-cdk-examples

Cette fois, je vais suivre le processus de création d'un nouveau VPC à l'aide de Python et de provisionnement d'ALB et d'EC2. https://github.com/aws-samples/aws-cdk-examples/tree/master/python/new-vpc-alb-asg-mysql Ce serait bien si l'exemple pouvait être versé dans votre environnement tel quel, mais je ne pense pas que ce soit le cas. (Parce que le CIDR du VPC est déjà attribué et qu'il peut entrer en collision) ** Par conséquent, avec quelle partie de l'exemple est-il pratique de jouer? Je voudrais expliquer principalement dans cette perspective. ** **

Enfin le sujet principal

J'entrerai enfin dans le sujet principal ici.

Conditions préalables

Bien sûr, vous avez besoin d'un compte AWS. (Cette zone est omise comme prévu) Et diverses installations sont nécessaires. Puisque vous pouvez créer un environnement en complétant l'atelier, il suffit d'avoir Hello, CDK!, Nous vous recommandons donc fortement de le faire. https://cdkworkshop.com/

Tout d'abord, versons l'exemple avec les modifications minimales! (1er tour)

En guise de procédure approximative, clonez l'exemple mentionné ci-dessus et utilisez new-vpc-alb-asg-mysql de Python. Changeons un peu l'exemple et versons-le en premier. (C'est le premier tour. Il y aura un deuxième tour plus tard)

clone J'ai oublié de l'écrire, mais j'utilise Ubuntu 18.04. Pour le matériel d'étude, nous creusons des sous-répertoires pour chaque thème dans un répertoire appelé pratique. Alors, clonez-le sous ~ / practice / cdk /. (Veuillez changer cette zone en bonne)

$ git clone https://github.com/aws-samples/aws-cdk-examples.git

En conséquence, le subordonné new-vpc-alb-asg-mysql de Python devient comme suit.

$ tree
.
├── app.py
├── cdk.json
├── cdk_vpc_ec2
│   ├── cdk_ec2_stack.py
│   ├── cdk_rds_stack.py
│   └── cdk_vpc_stack.py
├── img_demo_cdk_vpc.png
├── README.md
├── requirements.txt
├── setup.py
└── user_data
    └── user_data.sh

2 directories, 10 files

Modification et exécution de fichiers

Tout d'abord, apportez les modifications minimales et versez-les réellement. Le fichier à modifier est

est. Je suis désolé que ce soit difficile à comprendre, mais les commentaires japonais dans le code source ont été faits par moi, alors veuillez vous y référer.

Puisqu'il sera long, le contenu de la modification de fichier sera réduit.

Cliquez ici pour plus de détails.
Changer avant

cdk_vpc_stack.py (avant changement)


from aws_cdk import core
import aws_cdk.aws_ec2 as ec2


class CdkVpcStack(core.Stack):

    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        # The code that defines your stack goes here

        self.vpc = ec2.Vpc(self, "VPC",
                           max_azs=2,
                           cidr="10.10.0.0/16", #Le CIDR est écrit de manière fixe!
                           # configuration will create 3 groups in 2 AZs = 6 subnets.
                           subnet_configuration=[ec2.SubnetConfiguration(
                               subnet_type=ec2.SubnetType.PUBLIC,
                               name="Public",
                               cidr_mask=24
                           ), ec2.SubnetConfiguration(
                               subnet_type=ec2.SubnetType.PRIVATE,
                               name="Private",
                               cidr_mask=24
                           ), ec2.SubnetConfiguration(
                               subnet_type=ec2.SubnetType.ISOLATED,
                               name="DB",
                               cidr_mask=24
                           )
                           ],
                           # nat_gateway_provider=ec2.NatProvider.gateway(),
                           nat_gateways=2,
                           )
        core.CfnOutput(self, "Output",
                       value=self.vpc.vpc_id)

Le CIDR de VPC est 10.10.0.0/16. Si cela vous convient, vous pouvez l'exécuter tel quel, mais dans mon cas, j'ai dû le changer, donc je le changerai. De plus, comme il n'est pas facile à utiliser s'il est écrit en ligne, j'ai décidé de le couper en tant que variable.

Après le changement

cdk_vpc_stack.py (après changement)


from aws_cdk import core
import aws_cdk.aws_ec2 as ec2


vpc_cidr = "x.x.x.x/16" #Définissez le CIDR en tant que variable et réécrivez-le avec une valeur arbitraire.

class CdkVpcStack(core.Stack):

    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        # The code that defines your stack goes here

        self.vpc = ec2.Vpc(self, "VPC",
                           max_azs=2,
                           cidr=vpc_cidr,  #Changé pour utiliser des variables
                           # configuration will create 3 groups in 2 AZs = 6 subnets.
                           subnet_configuration=[ec2.SubnetConfiguration(
                               subnet_type=ec2.SubnetType.PUBLIC,
                               name="Public",
                               cidr_mask=24
                           ), ec2.SubnetConfiguration(
                               subnet_type=ec2.SubnetType.PRIVATE,
                               name="Private",
                               cidr_mask=24
                           ), ec2.SubnetConfiguration(
                               subnet_type=ec2.SubnetType.ISOLATED,
                               name="DB",
                               cidr_mask=24
                           )
                           ],
                           # nat_gateway_provider=ec2.NatProvider.gateway(),
                           nat_gateways=2,
                           )
        core.CfnOutput(self, "Output",
                       value=self.vpc.vpc_id)

Vient ensuite EC2. (En bref, modifiez le nom_clé de la paire de clés.)

Changer avant

cdk_ec2_stack.py (avant changement)


from aws_cdk import core
import aws_cdk.aws_ec2 as ec2
import aws_cdk.aws_elasticloadbalancingv2 as elb
import aws_cdk.aws_autoscaling as autoscaling

ec2_type = "t2.micro"
key_name = "id_rsa"  # Setup key_name for EC2 instance login 
linux_ami = ec2.AmazonLinuxImage(generation=ec2.AmazonLinuxGeneration.AMAZON_LINUX,
                                 edition=ec2.AmazonLinuxEdition.STANDARD,
                                 virtualization=ec2.AmazonLinuxVirt.HVM,
                                 storage=ec2.AmazonLinuxStorage.GENERAL_PURPOSE
                                 )  # Indicate your AMI, no need a specific id in the region
with open("./user_data/user_data.sh") as f:
    user_data = f.read()


class CdkEc2Stack(core.Stack):

    def __init__(self, scope: core.Construct, id: str, vpc, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        # Create Bastion
        bastion = ec2.BastionHostLinux(self, "myBastion",
                                       vpc=vpc,
                                       subnet_selection=ec2.SubnetSelection(
                                           subnet_type=ec2.SubnetType.PUBLIC),
                                       instance_name="myBastionHostLinux",
                                       instance_type=ec2.InstanceType(instance_type_identifier="t2.micro"))
        
        # Setup key_name for EC2 instance login if you don't use Session Manager
        # bastion.instance.instance.add_property_override("KeyName", key_name)

        bastion.connections.allow_from_any_ipv4(
            ec2.Port.tcp(22), "Internet access SSH")

        # Create ALB
        alb = elb.ApplicationLoadBalancer(self, "myALB",
                                          vpc=vpc,
                                          internet_facing=True,
                                          load_balancer_name="myALB"
                                          )
        alb.connections.allow_from_any_ipv4(
            ec2.Port.tcp(80), "Internet access ALB 80")
        listener = alb.add_listener("my80",
                                    port=80,
                                    open=True)

        # Create Autoscaling Group with fixed 2*EC2 hosts
        self.asg = autoscaling.AutoScalingGroup(self, "myASG",
                                                vpc=vpc,
                                                vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PRIVATE),
                                                instance_type=ec2.InstanceType(instance_type_identifier=ec2_type),
                                                machine_image=linux_ami,
                                                key_name=key_name,
                                                user_data=ec2.UserData.custom(user_data),
                                                desired_capacity=2,
                                                min_capacity=2,
                                                max_capacity=2,
                                                # block_devices=[
                                                #     autoscaling.BlockDevice(
                                                #         device_name="/dev/xvda",
                                                #         volume=autoscaling.BlockDeviceVolume.ebs(
                                                #             volume_type=autoscaling.EbsDeviceVolumeType.GP2,
                                                #             volume_size=12,
                                                #             delete_on_termination=True
                                                #         )),
                                                #     autoscaling.BlockDevice(
                                                #         device_name="/dev/sdb",
                                                #         volume=autoscaling.BlockDeviceVolume.ebs(
                                                #             volume_size=20)
                                                #         # 20GB, with default volume_type gp2
                                                #     )
                                                # ]
                                                )

        self.asg.connections.allow_from(alb, ec2.Port.tcp(80), "ALB access 80 port of EC2 in Autoscaling Group")
        listener.add_targets("addTargetGroup",
                             port=80,
                             targets=[self.asg])

        core.CfnOutput(self, "Output",
                       value=alb.load_balancer_dns_name)

Après le changement

python:python:cdk_ec2_stack.py (après changement)


from aws_cdk import core
import aws_cdk.aws_ec2 as ec2
import aws_cdk.aws_elasticloadbalancingv2 as elb
import aws_cdk.aws_autoscaling as autoscaling

ec2_type = "t2.micro"
key_name = "hogehoge" #Changez pour la paire de clés préparée à l'avance.
linux_ami = ec2.AmazonLinuxImage(generation=ec2.AmazonLinuxGeneration.AMAZON_LINUX,
                                 edition=ec2.AmazonLinuxEdition.STANDARD,
                                 virtualization=ec2.AmazonLinuxVirt.HVM,
                                 storage=ec2.AmazonLinuxStorage.GENERAL_PURPOSE
                                 )  # Indicate your AMI, no need a specific id in the region
with open("./user_data/user_data.sh") as f:
    user_data = f.read()

#À partir de ce moment, la publication sera supprimée.

Verser!

Merci pour l'attente. Pour le moment, créons une ressource dans cet état.

#Réglez venv.
$ cd ~/practice/cdk/aws-cdk-examples/python/new-vpc-alb-asg-mysql
$ python3 -m venv .env
$ source .env/bin/activate

#Installation de bibliothèques dépendantes
$ pip install -r requirements.txt

#Entrez la commande CDK pour générer un modèle CloudFormation.
$ cdk ls
cdk-vpc
cdk-ec2
cdk-rds

$ cdk synth
Successfully synthesized to /home/****/practice/cdk/aws-cdk-examples/python/new-vpc-alb-asg-mysql/cdk.out

Un répertoire appelé cdk.out sera créé et des modèles CloudFormation y seront créés. (Au fait, le modèle était json ... n'est-ce pas yaml?)

$ cdk bootstrap

$ cdk deploy cdk-vpc #Cela prendra un certain temps. (comme ci-dessus)
$ cdk deploy cdk-ec2
$ cdk deploy cdk-rds

La pile CloudFormation est terminée et la ressource souhaitée est finalement terminée. Puisqu'il n'est pas possible de tous les lister, seul le sous-réseau sera associé à la vue de la console de gestion. [TBD] Collez l'image.

Problèmes à ce stade

Ceux-ci seront résolus dans le deuxième tour. Alors je l'ai fait, mais je vais supprimer la ressource facilement!

Supprimer la ressource

#Je l'ai effacé dans l'ordre inverse de celui où je l'ai fait. Il a disparu proprement. (Comme prévu, la pile CloudFormation sera supprimée)
$ cdk destroy cdk-rds
$ cdk destroy cdk-ec2
$ cdk destroy cdk-vpc


Faites une pause (écrivez quelque chose d'une importance inattendue)

Par exemple, un sous-réseau privé 「cdk-vpc/VPC/PrivateSubnet1」 Vous pouvez le faire avec le nom.

Vous pouvez utiliser / (barre oblique) dans le nom de la ressource! ?? C'était frais. L'endroit où Kebab Case (-Tsunagi) et Camel Case sont mélangés est ludique.

Comment le nom de la ressource est-il déterminé? En parlant de cela (les détails doivent être confirmés) 最初のcdk-vpcの部分は、app.py Puisque ce qui suit est spécifié dans, cela semble être décidé par cela.

app.py (extrait seulement en partie)


vpc_stack = CdkVpcStack(app, "cdk-vpc")
ec2_stack = CdkEc2Stack(app, "cdk-ec2",
                        vpc=vpc_stack.vpc)
rds_stack = CdkRdsStack(app, "cdk-rds",
                        vpc=vpc_stack.vpc,
                        asg_security_groups=ec2_stack.asg.connections.security_groups)

Par conséquent, pour le deuxième tour, je voudrais changer la partie cdk- à une valeur légèrement plus significative. Cette fois (bien que pas très significatif) je vais essayer akira-test-cdk-.

Passons au deuxième tour! !! Let's et al!

2e tour

Changements au deuxième tour

Remplacez le nom de la ressource par akira-test-cdk-begin

app.py


#!/usr/bin/env python3

from aws_cdk import core

from cdk_vpc_ec2.cdk_vpc_stack import CdkVpcStack
from cdk_vpc_ec2.cdk_ec2_stack import CdkEc2Stack
from cdk_vpc_ec2.cdk_rds_stack import CdkRdsStack

app = core.App()

vpc_stack = CdkVpcStack(app, "akira-test-cdk-vpc")
ec2_stack = CdkEc2Stack(app, "akira-test-cdk-ec2",
                        vpc=vpc_stack.vpc)
rds_stack = CdkRdsStack(app, "akira-test-cdk-rds",
                        vpc=vpc_stack.vpc,
                        asg_security_groups=ec2_stack.asg.connections.security_groups)

app.synth()

Attribuer une paire de clés à Bastion et restreindre l'adresse IP entrante du groupe de sécurité et utiliser le port 8080

Chacun est un pseudonyme, veuillez donc le lire comme vous le souhaitez.

cdk_ec2_stack.py


from aws_cdk import core
import aws_cdk.aws_ec2 as ec2
import aws_cdk.aws_elasticloadbalancingv2 as elb
import aws_cdk.aws_autoscaling as autoscaling

ec2_type = "t2.micro"
key_name = "hogehoge" #Changez pour la paire de clés préparée à l'avance.
linux_ami = ec2.AmazonLinuxImage(generation=ec2.AmazonLinuxGeneration.AMAZON_LINUX_2, #Passer à Amazon Linux 2
                                 edition=ec2.AmazonLinuxEdition.STANDARD,
                                 virtualization=ec2.AmazonLinuxVirt.HVM,
                                 storage=ec2.AmazonLinuxStorage.GENERAL_PURPOSE
                                 )  # Indicate your AMI, no need a specific id in the region
with open("./user_data/user_data.sh") as f:
    user_data = f.read()


class CdkEc2Stack(core.Stack):

    def __init__(self, scope: core.Construct, id: str, vpc, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        # Create Bastion
        bastion = ec2.BastionHostLinux(self, "myBastion",
                                       vpc=vpc,
                                       subnet_selection=ec2.SubnetSelection(
                                           subnet_type=ec2.SubnetType.PUBLIC),
                                       instance_name="myBastionHostLinux",
                                       instance_type=ec2.InstanceType(instance_type_identifier="t2.micro"))
        
        # Setup key_name for EC2 instance login if you don't use Session Manager
        #Décommentez ici et enregistrez la paire de clés
        bastion.instance.instance.add_property_override("KeyName", key_name)

        #Affiner l'adresse IP source
        # bastion.connections.allow_from_any_ipv4(
        bastion.connections.allow_from(ec2.Peer.ipv4("x.x.x.x/32"), #IP source ici!
            ec2.Port.tcp(22), "Internet access SSH")

        # Create ALB
        alb = elb.ApplicationLoadBalancer(self, "myALB",
                                          vpc=vpc,
                                          internet_facing=True,
                                          load_balancer_name="myALB"
                                          )
        alb.connections.allow_from_any_ipv4(
            ec2.Port.tcp(80), "Internet access ALB 80")
        listener = alb.add_listener("my80",
                                    port=80,
                                    open=True)

        # Create Autoscaling Group with fixed 2*EC2 hosts
        self.asg = autoscaling.AutoScalingGroup(self, "myASG",
                                                vpc=vpc,
                                                vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PRIVATE),
                                                instance_type=ec2.InstanceType(instance_type_identifier=ec2_type),
                                                machine_image=linux_ami,
                                                key_name=key_name,
                                                user_data=ec2.UserData.custom(user_data),
                                                desired_capacity=2,
                                                min_capacity=2,
                                                max_capacity=2,
volume_type=autoscaling.EbsDeviceVolumeType.GP2,
                                                )

        self.asg.connections.allow_from(alb, ec2.Port.tcp(8080), "ALB access 8080 port of EC2 in Autoscaling Group")
        listener.add_targets("addTargetGroup",
                             port=8080, # 80 ->Changer pour 8080
                             targets=[self.asg])

        core.CfnOutput(self, "Output",
                       value=alb.load_balancer_dns_name)


Modifier user_data

user_data.sh


#!/bin/bash
sudo yum update -y
sudo yum install -y java-11-amazon-corretto-headless
sudo yum install -y maven
# sudo yum -y install httpd php
# sudo chkconfig httpd on
# sudo service httpd start

Au lieu de créer un RDS, exécutons une application de test de fumée indépendante de DB pour le moment!

Pour le moment, exécutez l'application Spring Boot sur EC2. (Je suis désolé d'être épuisé et l'explication est compliquée ici ... Eh bien, ce n'est pas le sujet principal.)

HelloController.java


package com.example.demo;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @GetMapping("/")
    public String hello() {
        return "Hello, Spring boot with AWS CDK";
    }
}

** Étant donné que le groupe de sécurité lié à l'EC2 de l'application n'accepte que l'accès depuis ALB, il n'est pas possible pour le moment d'effectuer un ssh de Bastion vers l'EC2 de l'application. Par conséquent, modifiez le SecurityGroup et modifiez-le manuellement pour accepter ssh de Bastion. ** **

[TODO] L'explication ici est trop compliquée, alors je vais le faire un peu plus ...

#Apportez le pot à EC2 avec SCP etc.

#commencer
$ java -jar demo-0.0.1-SNAPSHOT.jar

#Atteignez le point de terminaison à la suite du déploiement d'ec2.

Impressions

CloudFormation a l'impression que c'est un peu délicat lorsque le responsable de l'application crée un environnement AWS. CDK est un langage de programmation populaire qui l'enveloppe, donnant l'impression que le code d'infrastructure est ainsi plus facile à lire. J'ai utilisé Python cette fois, mais je voulais aussi l'essayer dans d'autres langues.

Les spécifications de l'API se trouvent ci-dessous. https://docs.aws.amazon.com/cdk/api/latest/python/modules.html

Recommended Posts

J'ai essayé AWS CDK!
J'ai essayé AWS Iot
J'ai essayé d'utiliser AWS Chalice
J'ai essayé de gratter
J'ai essayé PyQ
J'ai essayé AutoKeras
J'ai essayé le moulin à papier
J'ai essayé django-slack
J'ai essayé Django
J'ai essayé spleeter
J'ai essayé cgo
J'ai essayé d'utiliser paramétré
J'ai essayé d'utiliser argparse
J'ai essayé d'utiliser l'API Detect Labels d'AWS Rekognition
J'ai essayé d'utiliser la mimesis
J'ai essayé d'utiliser anytree
J'ai essayé d'exécuter pymc
J'ai essayé le spoofing ARP
J'ai essayé d'utiliser aiomysql
J'ai essayé Python> autopep8
J'ai essayé d'utiliser coturn
J'ai essayé d'utiliser Pipenv
J'ai essayé d'utiliser matplotlib
J'ai essayé d'utiliser "Anvil".
J'ai essayé d'utiliser Hubot
J'ai essayé d'utiliser ESPCN
J'ai essayé PyCaret2.0 (pycaret-nightly)
J'ai essayé d'utiliser openpyxl
J'ai essayé d'utiliser Ipython
J'ai essayé de déboguer.
J'ai essayé d'utiliser PyCaret
J'ai essayé d'utiliser cron
J'ai essayé la mapview de Kivy
J'ai essayé d'utiliser ngrok
J'ai essayé d'utiliser face_recognition
J'ai essayé d'utiliser Jupyter
J'ai essayé de connecter AWS Lambda à d'autres services
J'ai essayé de déplacer EfficientDet
J'ai essayé la programmation shell
J'ai essayé d'utiliser doctest
J'ai essayé Python> décorateur
J'ai essayé d'exécuter TensorFlow
J'ai essayé Auto Gluon
J'ai essayé d'utiliser du folium
J'ai essayé d'utiliser jinja2
J'ai essayé l'optimisation bayésienne!
J'ai touché AWS Chalice
J'ai essayé de créer un service de raccourcissement d'url sans serveur avec AWS CDK
J'ai essayé d'utiliser du folium
J'ai essayé d'utiliser la fenêtre de temps
Quand j'ai essayé de créer un VPC avec AWS CDK mais que je n'ai pas pu le faire
J'ai fait une analyse émotionnelle d'Amazon Comprehend avec l'AWS CLI.
J'ai essayé d'obtenir une AMI en utilisant AWS Lambda
AWS Lambda prend désormais en charge Python, je l'ai donc essayé
[Introduction à AWS] J'ai essayé de jouer avec la conversion voix-texte ♪
J'ai essayé les réseaux d'itération de valeur