AWS CDK Python boto3でEC2の構築をしてみた

はじめに

今回はAWS CDKでEC2の構築を行いたいと思います。AWS CDKはコードでリソースの操作ができるIacツールです。様々なプログラミング言語をサポートしているので、使い慣れた言語を利用することで学習コストを抑えることができます。今回はPython boto3を使って構築していきます。

コードでリソースの操作をするのは最初はとっつきにくいですが、一度構築してしまえば、何度も同じ環境をコマンド一つで再現することができます。

例えば、本番環境と検証環境で同じ環境を用意したいというニーズがあった場合。コンソールからポチポチ画面を操作して同じ環境を構築するのは骨の折れる作業です。また、人が作業する以上ミスが発生するリスクがあります。Iacを導入することで確実に同じ環境を構築することができミスも削減できます。

作成するリソースの構成図

サブネット1つにEC2を1台たてるシンプルな構成で構築していきたいと思います。

boto3.drawio.png

実装

それでは実際にコードを書いて実装してみます。以下のコードで構成図通りの環境を構築することができます。

1ec2.py2#boto3インポート3import boto34#インスタンスの作成5ec2 = boto3.client('ec2')67#vpc作成8vpc = ec2.create_vpc(9    CidrBlock = '192.0.0.0/24',10    TagSpecifications=[11        {               12                        'ResourceType': 'vpc',13                       'Tags': [14                {15                    'Key': 'Name',16                    'Value': 'boto3-test-vpc'17                },18            ]19        }20    ]21    22)2324vpcId = vpc['Vpc']['VpcId']25#サブネット作成26publicSubnet1 = ec2.create_subnet(27    AvailabilityZone = 'ap-northeast-1a',28    CidrBlock = '192.0.0.0/28',29    VpcId = vpcId30)31publicSubnet1Id = publicSubnet1['Subnet']['SubnetId']3233#インターネットゲートウェイの作成34igw = ec2.create_internet_gateway(35    TagSpecifications=[36        {               37                        'ResourceType': 'internet-gateway',38                       'Tags': [39                {40                    'Key': 'Name',41                    'Value': 'boto3-test-igw'42                },43            ]44        }45    ]46)4748igwId = igw['InternetGateway']['InternetGatewayId']4950#インターネットゲートウェイをvpcにアタッチ51ec2.attach_internet_gateway(52    InternetGatewayId= igwId,53    VpcId =vpcId54)5556#ルートテーブルの作成57routeTable = ec2.create_route_table(58    VpcId = vpcId,59    TagSpecifications=[60        {               61                        'ResourceType': 'route-table',62                       'Tags': [63                {64                    'Key': 'Name',65                    'Value': 'boto3-test-route-table'66                },67            ]68        }69    ]70)71routeTableId = routeTable['RouteTable']['RouteTableId']7273route1 = ec2.create_route(74    DestinationCidrBlock= '0.0.0.0/0',75    GatewayId= igwId,76    RouteTableId= routeTableId77)78#サブネットとルートテーブルの紐づけ79ec2.associate_route_table(80    RouteTableId = routeTableId,81    SubnetId = publicSubnet1Id,82)8384#セキュリティグループの作成85securityGroup = ec2.create_security_group(86    Description='test-boto3',87    GroupName='boto3-test',88    VpcId= vpcId,89)90sgId = securityGroup['GroupId']9192#sshの設定93authorizeSsh =  ec2.authorize_security_group_ingress(94    GroupId = sgId,95      IpPermissions=[96        {97            'FromPort': 22,98            'IpProtocol': 'tcp',99            'IpRanges': [100                {101                    'CidrIp': 'myip',102                    'Description': 'SSH access from the office',103                },104            ],105            'ToPort': 22,106        },107    ],108109)110111#キーペアの作成112keyName = "boto3-test"113114keyPair = ec2.create_key_pair(115    KeyName=keyName,116    KeyFormat="ppk"117)118119#キーペアのファイルを作成する120keyData = keyPair['KeyMaterial']121#with命令でfileオブジェクトの生成、書き込み専用(ファイルが存在しなければ新規作成)122with open(keyName + ".ppk",mode='w') as f:123    f.write(keyData)124125#ec2インスタンスの起動126instance1 = ec2.run_instances(127    ImageId="ami-05a56ce08feadf9c4",128    MinCount=1,129    MaxCount=1,130    InstanceType="t2.micro",131    KeyName=keyName,132    SecurityGroupIds=[sgId],133    SubnetId=publicSubnet1Id,134    TagSpecifications=[135        {136            'ResourceType': 'instance',137            'Tags': [138                {139                    'Key': "Name",140                    'Value': "boto3"141                },142            ]143        }144    ]145)

それではコードの解説をしていきます。

1ec2.py23# boto3インポート  45import boto3

まずはライブラリをインポートします。

1ec2.py23# インスタンスの作成  45ec2 = boto3.client('ec2')

EC2サービスへのクライアントインターフェースを作成しています。これにより、EC2インスタンスに関連する操作をプログラムから行うことができます。

VPCの作成

1ec2.py23# vpc作成  45vpc = ec2.create_vpc(  6    CidrBlock = '192.0.0.0/24',  7    TagSpecifications=[  8        {  9            'ResourceType': 'vpc',  10            'Tags': [  11                {  12                    'Key': 'Name',  13                    'Value': 'boto3-test-vpc'  14                },  15            ]  16        }  17    ]  18)

新しいVPC(Virtual Private Cloud)を作成しています。CIDRブロックとして192.0.0.0/24をしていします。このVPCはNameタグをboto3-test-vpcとして設定します。

1ec2.py2vpcId = vpc['Vpc']['VpcId']

boto3のclientは戻り値としてdict型を返します。上記のコードでVPC IDを取得しています。

サブネットの作成

1ec2.py23# サブネット作成  45publicSubnet1 = ec2.create_subnet(  6    AvailabilityZone = 'ap-northeast-1a',  7    CidrBlock = '192.0.0.0/28',  8    VpcId = vpcId  9)

作成したVPC内に新しいサブネットを作成しています。このサブネットはアベイラビリティーゾーンap-northeast-1a(東京リージョンのAZ)に配置され、CIDRブロックとしては192.0.0.0/28が割り当てられています。先ほど取得したVPCIDを指定します。

1ec2.py2publicSubnet1Id = publicSubnet1['Subnet']['SubnetId']

作成したサブネットからサブネットIDを取得しています。

インターネットゲートウェイの作成

1ec2.py23# インターネットゲートウェイの作成  45igw = ec2.create_internet_gateway(  6    TagSpecifications=[  7        {  8            'ResourceType': 'internet-gateway',  9            'Tags': [  10                {  11                    'Key': 'Name',  12                    'Value': 'boto3-test-igw'  13                },  14            ]  15        }  16    ]  17)

インターネットゲートウェイを作成し、Nameタグでboto3-test-igwと命名しています。

1ec2.py2igwId = igw['InternetGateway']['InternetGatewayId']

作成したインターネットゲートウェイからIDを取得しています。

1ec2.py23# インターネットゲートウェイをvpcにアタッチ  45ec2.attach_internet_gateway(  6    InternetGatewayId= igwId,  7    VpcId =vpcId  8)

VPCに対してインターネットゲートウェイをアタッチ(接続)しています。これにより、VPC内のインスタンスがインターネットと通信できるようになります。

ルートテーブルの作成

1ec2.py23# ルートテーブルの作成  45routeTable = ec2.create_route_table(  6    VpcId = vpcId,  7    TagSpecifications=[  8        {  9            'ResourceType': 'route-table',  10            'Tags': [  11                {  12                    'Key': 'Name',  13                    'Value': 'boto3-test-route-table'  14                },  15            ]  16        }  17    ]  18)

新しいルートテーブルを作成し、Nameタグでboto3-test-route-tableと命名しています。

1ec2.py2routeTableId = routeTable['RouteTable']['RouteTableId']

作成したルートテーブルからIDを取得しています。

1ec2.py2route1 = ec2.create_route(  3    DestinationCidrBlock= '0.0.0.0/0',  4    GatewayId= igwId,  5    RouteTableId= routeTableId  6)

インターネットへのルート(全てのトラフィックを0.0.0.0/0でキャッチしてインターネットゲートウェイへと流すためのルール)をルートテーブルに追加しています。

1ec2.py23# サブネットとルートテーブルの紐づけ  45ec2.associate_route_table(  6    RouteTableId = routeTableId,  7    SubnetId = publicSubnet1Id,  8)

ルートテーブルをサブネットに関連付けています。これによりサブネット内のインスタンスが作成したルートテーブルを利用してインターネットに出ることが可能になります。

セキュリティグループの作成

1ec2.py23# セキュリティグループの作成  45securityGroup = ec2.create_security_group(  6    Description='test-boto3',  7    GroupName='boto3-test',  8    VpcId= vpcId,  9)

新しいセキュリティグループを作成しています。インスタンスに適用されるファイアウォールです。

1ec2.py2sgId = securityGroup['GroupId']

作成したセキュリティグループからIDを取得します。

1ec2.py23# sshの設定  45authorizeSsh =  ec2.authorize_security_group_ingress(  6    GroupId = sgId,  7    IpPermissions=[  8        {  9            'FromPort': 22,  10            'IpProtocol': 'tcp',  11            'IpRanges': [  12                {  13                    'CidrIp': 'myip',  14                    'Description': 'SSH access from the office',  15                },  16            ],  17            'ToPort': 22,  18        },  19    ],  20)

セキュリティグループのインバウンドルールを設定しており、指定のIPアドレス(myipからのSSH(ポート22)接続を許可しています。ここは自身の環境のIPアドレスを設定してください。

キーペアの作成

1ec2.py23# キーペアの作成  45keyName = "boto3-test"  67keyPair = ec2.create_key_pair(  8    KeyName=keyName,  9    KeyFormat="ppk"  10)

キーペアを作成します。フォーマットはppk(PuTTY用のフォーマット)をしていします。これによりプライベートキーが生成され、セキュリティで保護された方法でインスタンスに接続する際に使用します。

1ec2.py2keyData = keyPair['KeyMaterial']

生成したキーペアから実際のキー情報を取得しています。

1ec2.py23# キーペアのファイルを作成する  45# with命令でfileオブジェクトの生成、書き込み専用(ファイルが存在しなければ新規作成)  67with open(keyName + ".ppk", mode='w') as f:  8    f.write(keyData)

プライベートキーをファイルとして保存しています。このファイルはSSHログインに使用します。ファイル名は先ほど設定したキーペア名に.ppk拡張子をつけたものです。

EC2インスタンスの起動

1ec2.py23# ec2インスタンスの起動  45instance1 = ec2.run_instances(  6    ImageId="ami-05a56ce08feadf9c4",  7    MinCount=1,  8    MaxCount=1,  9    InstanceType="t2.micro",  10    KeyName=keyName,  11    SecurityGroupIds=[sgId],  12    SubnetId=publicSubnet1Id,  13    TagSpecifications=[  14        {  15            'ResourceType': 'instance',  16            'Tags': [  17                {  18                    'Key': "Name",  19                    'Value': "boto3"  20                },  21            ]  22        }  23    ]  24)

最後に、EC2インスタンスを起動します。使用するAMIはAmazon Linux2023を指定しています。、インスタンスタイプ、キーペア、セキュリティグループ、サブネットを指定し、最低1つ、最高1つのインスタンスを起動するように設定します。インスタンスにはboto3という名前タグを設定しました。

おわりに

今回はEC2インスタンス1台を起動するという簡単なものでしたがカスタマイズしていくことで独自のニーズに合わせたインフラの構築が可能です。ご活用いただけたら幸いです。

===

ナレッジコミュニケーションでは「Musubite」というエンジニア同士のカジュアルトークサービスを利用しています。

生成 AI 技術を使ったプロジェクトに携わるメンバーと直接話せるサービスですので興味がある方は是非利用を検討してください!

今後もクラウド AI の最新情報を皆さんに届けていきたいと思います。お楽しみに。

この記事を書いた人

aws-recipe-user