LoginSignup
10
0

More than 1 year has passed since last update.

CloudFormationを最近触り始めた私がAWS CDKを使ってEC2作成まで挑戦します

前提条件

以下インストールされていること
Python3
aws cli
aws cdk

app作成

以下を参考にapp作成していきます

$ mkdir cdk-app
$ cd cdk-app

$ cdk init app --language python

$ source .venv/bin/activate
$ python -m pip install -r requirements.txt
$ cdk bootstrap

成功するとこんな感じにファイルができます

$ ls -a
.           .venv           cdk_app         tests
..          README.md       requirements-dev.txt
.git            app.py          requirements.txt
.gitignore      cdk.json        source.bat

実装

どこに処理を書いていけばいいんじゃ.....?

生成されたファイルの中に「cdk_app_stack.py」というファイルがありました
どうやらここに処理を書いていくようです

$ cd cdk_app/
$ ls -a
.           ..          __init__.py     cdk_app_stack.py
$ cat cdk_app_stack.py
from aws_cdk import (
    # Duration,
    Stack,
    # aws_sqs as sqs,
)
from constructs import Construct

class CdkAppStack(Stack):

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

        # The code that defines your stack goes here

        # example resource
        # queue = sqs.Queue(
        #     self, "CdkAppQueue",
        #     visibility_timeout=Duration.seconds(300),
        # )

VPC作成

さっそくVPCとサブネットの部分を実装していきます

from aws_cdk import (
    # Duration,
    aws_ec2 as ec2,
    Stack,
)
from constructs import Construct

class CdkAppStack(Stack):

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

        # Create VPC
        vpc = ec2.Vpc(
            self,
            id="vpc",
            cidr="10.0.0.0/16",
            nat_gateways=0, # NatGatewayを作成しない指定
            # Create Private Subnet
            subnet_configuration=[
                ec2.SubnetConfiguration(
                    name="subnet",
                    subnet_type=ec2.SubnetType.PUBLIC,
                    cidr_mask=24
                )
            ]
        )

以下を実行することで実装した内容が正しく動くのかチェックできるのと、作成するリソースの内容が見れます

$ cdk diff

作成されるリソース

〜〜〜省略〜〜〜

Resources
[+] AWS::EC2::VPC vpc vpcA2121C38 
[+] AWS::EC2::Subnet vpc/subnetSubnet1/Subnet vpcsubnetSubnet1SubnetED4FAF75 
[+] AWS::EC2::RouteTable vpc/subnetSubnet1/RouteTable vpcsubnetSubnet1RouteTable540CA842 
[+] AWS::EC2::SubnetRouteTableAssociation vpc/subnetSubnet1/RouteTableAssociation vpcsubnetSubnet1RouteTableAssociation8AB5D956 
[+] AWS::EC2::Route vpc/subnetSubnet1/DefaultRoute vpcsubnetSubnet1DefaultRoute693F9670 
[+] AWS::EC2::Subnet vpc/subnetSubnet2/Subnet vpcsubnetSubnet2Subnet1FDD234B 
[+] AWS::EC2::RouteTable vpc/subnetSubnet2/RouteTable vpcsubnetSubnet2RouteTable76DD52F4 
[+] AWS::EC2::SubnetRouteTableAssociation vpc/subnetSubnet2/RouteTableAssociation vpcsubnetSubnet2RouteTableAssociationE50AAA12 
[+] AWS::EC2::Route vpc/subnetSubnet2/DefaultRoute vpcsubnetSubnet2DefaultRouteD284164C 
[+] AWS::EC2::InternetGateway vpc/IGW vpcIGWE57CBDCA 
[+] AWS::EC2::VPCGatewayAttachment vpc/VPCGW vpcVPCGW7984C166 

〜〜〜省略〜〜〜

ではデプロイしてみましょう

$ cdk deploy

VPCとサブネットが作成されてました!

VPC作成.png

サブネット作成.png

ルートテーブルやインターネットゲートウェイも作られてました!
ここはCloudFormationだと書かないと作られないので楽ですね
(自分で作ることもできそうです)

EC2作成

セキュリティグループもあわせて実装します

from aws_cdk import (
    # Duration,
    aws_ec2 as ec2,
    Stack,
)
from constructs import Construct

class CdkAppStack(Stack):

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

        # Create VPC
        vpc = ec2.Vpc(
            self,
            id="vpc",
            cidr="10.0.0.0/16",
            nat_gateways=0, # NatGatewayを作成しない指定
            # Create Private Subnet
            subnet_configuration=[
                ec2.SubnetConfiguration(
                    name="subnet",
                    subnet_type=ec2.SubnetType.PUBLIC,
                    cidr_mask=24
                )
            ]
        )

        # Create SecurityGroup
        security_group = ec2.SecurityGroup(
            self,
            id="ec2-sg",
            vpc=vpc,
            allow_all_outbound=True,
            security_group_name="ec2-sg"
        )

        # Add Ingress Rule
        security_group.add_ingress_rule(
            peer=ec2.Peer.ipv4("**********/32"),
            connection=ec2.Port.tcp(22),
            description="allow ssh access"
        )

        # Create EC2
        ec2_instance = ec2.Instance(
            self,
            id="ec2-instance",
            instance_type=ec2.InstanceType.of(
                ec2.InstanceClass.BURSTABLE2,
                ec2.InstanceSize.MICRO
            ),
            machine_image=ec2.AmazonLinuxImage(),
            vpc=vpc,
            vpc_subnets=ec2.SubnetSelection(
                subnet_type=ec2.SubnetType.PUBLIC
            ),
            instance_name="ec2-instance",
            security_group=security_group
        )

できたので再度diff...

$ cdk diff

ちゃんと差分のみ表示してくれますね!
とても見やすいです!

IAM Statement Changes
┌───┬──────────────────────────────┬────────┬────────────────┬──────────────────────────────┬───────────┐
│   │ Resource                     │ Effect │ Action         │ Principal                    │ Condition │
├───┼──────────────────────────────┼────────┼────────────────┼──────────────────────────────┼───────────┤
│ + │ ${ec2-instance/InstanceRole. │ Allow  │ sts:AssumeRole │ Service:ec2.${AWS::URLSuffix │           │
│   │ Arn}                         │        │                │ }                            │           │
└───┴──────────────────────────────┴────────┴────────────────┴──────────────────────────────┴───────────┘
Security Group Changes
┌───┬───────────────────┬─────┬────────────┬────────────────────┐
│   │ Group             │ Dir │ Protocol   │ Peer               │
├───┼───────────────────┼─────┼────────────┼────────────────────┤
│ + │ ${ec2-sg.GroupId} │ In  │ TCP 22     │ **********/32 │
│ + │ ${ec2-sg.GroupId} │ Out │ Everything │ Everyone (IPv4)    │
└───┴───────────────────┴─────┴────────────┴────────────────────┘
(NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299)

Parameters
[+] Parameter SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter SsmParameterValueawsserviceamiamazonlinuxlatestamznamihvmx8664gp2C96584B6F00A464EAD1953AFF4B05118Parameter: {"Type":"AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>","Default":"/aws/service/ami-amazon-linux-latest/amzn-ami-hvm-x86_64-gp2"}

Resources
[+] AWS::EC2::SecurityGroup ec2-sg ec2sg81ADD929 
[+] AWS::IAM::Role ec2-instance/InstanceRole ec2instanceInstanceRoleCA97C688 
[+] AWS::IAM::InstanceProfile ec2-instance/InstanceProfile ec2instanceInstanceProfile9BCE9015 
[+] AWS::EC2::Instance ec2-instance ec2instance42082E81 

そしてデプロイ

$ cdk deploy

EC2作成されてました!

EC2.png

メソッド化

せっかくyamlでなくPythonで書いているので、プログラムみたいにしたい!
ということでメソッドを作ってみます

        def create_ec2(self, id, vpc, security_group):
        return ec2.Instance(
            self,
            id=id,
            instance_type=ec2.InstanceType.of(
                ec2.InstanceClass.BURSTABLE2,
                ec2.InstanceSize.MICRO
            ),
            machine_image=ec2.AmazonLinuxImage(),
            vpc=vpc,
            vpc_subnets=ec2.SubnetSelection(
                subnet_type=ec2.SubnetType.PUBLIC
            ),
            instance_name=id,
            security_group=security_group
        )

単純ですがEC2を作成するメソッドを作成しました

idを変えて呼び出す
このidの部分がCloudFormationでいうResourcesIdの部分なので同じ値は指定できません

        # EC2インスタンスを作成
        ec2_instance = self.create_ec2("ec2-instance", vpc, security_group)
        ec2_instance2 = self.create_ec2("ec2-instance2", vpc, security_group)

これでデプロイしてみると.....

EC2_2.png

2つ作成されてました!
素敵ですね!!

スタック削除

一通り試せたので次はスタックの削除をしてみます
削除するときはdestroyコマンドです

$ cdk destroy

消す前にスタック名の確認をしてくれるので精神的に安心ですw

Are you sure you want to delete: CdkAppStack (y/n)? 

最初に作成したVPCまで削除されてました

感想

CDKで実行するとターミナル上で見れる情報が多く、コマンド実行してからの不安が軽減された感じがしました

あとやっぱりメソッド化できるのがいいですね!
CloudFormationだとどうしても冗長化したソースになってしまい読みづらくなってしまうので、、、

今後構築する案件ではCDK使って行きたいなととても感じました

以上

Tips

公式サンプル

app作成

10
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
0