いちはじCDK第3回 VPCとサブネット①

やっと・・・

第3回ですね・・・(‘ω’)ふむっ
そろそろAWSっぽいことをやっていきたい…そんなことを思います。
まずは、基本のVPCとサブネットを作ってみようかなと・・・

ちょっと一言

VPCはやっぱ自分で作ったのが良い!って思うんですけど、私見として言わせてもらえるなら、特に何かサービスを提供して商売するような目的でなければ、「defaultVPCを使った方が良い」と感じました。

私もかつてVPC独自で作って色々試していたんですけど、例えばCloud9とかを使って作業するときとか、VPCが異なるとアクセスできなかったりするんですよね。
でどうするか?VPCエンドポイント使ってバイパス作ったりするわけですが…「いやー便利やなぁ」みたいに思っていたら、請求額がドンドン上がっていくわけです。
そう、VPCエンドポイントは存在するだけで、お金がかかるのです・・・
VPC自体はお金かかんないんですけどね!
個別に作ったVPCにもインターネットGW付けちゃえとか、そういうのもお金かかってきます。
なので、動作確認したり、なんだりするだけの人はdefaultVPCを使った方が何かと手間が省けるし、コストを低く抑えることができると思うんです!
で、結局私は、個人的に作ったVPCとか、エンドポイントとか、インターネットGWは全部けして、defaultVPCだけに集約しました!
今は月に1000円も行かない感じです。高いときは1万9000円くらい取られましたね。
私としては毎月とられるのは痛い出費でした・・・
(´・ω・)ん?ただ、お金かかった?って話?単なる愚痴書くなよ、稼ぎの方を増やせ・・・
・・・(;・∀・)それでは、本題にもどります・・・

構成図!

最初はやっぱり構成図でしょう!構成図が描きたいという人は、AWSがアイコン集を提供してくれてるので!GETして書いてみたら良いと思います。以下がリンクです。

で今回作るのは以下のような構成です!

作るリリソースは
・VPC×1
・パブリックなサブネット×2※2つのアベイラビリティゾーンにそれぞれ配置するためです。
・プライベートなサブネット×2※2つのアベイラビリティゾーンにそれぞれ配置するためです。
・ルートテーブル×2
・インターネットGW×1※お金かかります。
以上です!
(´_ゝ`)絵見たらわかるのでは?

ここで改めて・・・

ここで改めて方針です・・・作ったら「わーできたできたパチパチ(∩´∀`)∩」ってやって・・・
速攻消します!

では!CDK!L1のIFを調べよう!

 憂鬱な作業です・・・まずはファーストコンタクトとしてはGoogle先生に聞くですね。
「CfnVPC CDK」というキーワードで検索をかけます。

ヒット!(;・∀・)!
あとは、訳して・・・パラメータを調べていく・・・でもそこは割愛です!がこちらに整理しました。
パラメータ調べてて気が付いたのは、CfnVPC単独ではIPv6を定義できないので、CfnVPCCidrBlockを合わせて使わないといけない感じですね。
IPv4はIPアドレスの枯渇の問題から、AWSでも有料化されます。うーん…世知辛いな…枯渇するとかずっと前から言われてるけど結局枯渇しなくね?って感じますけどね…
でもこれからはIPv4を使うとお金取られると認識しておいた方が良いです。
なのでIPv6へ切り替えていくことが必要になってきます。
VPC作るときにはIPv6の定義方法も押さえておきたいところですね。

まずはVPCだけを作って感じを見る

ではVPCだけを作ってみましょう。やる事は、
・パラメータリストを作る。
・IFのデータ構成を作る。
・ラッパー関数を作る。
です。
パラメータリストとIFのデータ構成ですが、第2回で書いたようにpydanticというパッケージを使います。イメージです。↓

非常に簡単だと思うんですが、パラメータと、変数名を同じにしたら良いです。
ただ、同じでないと上手く被せてくれないのでそこは注意。ちょっと違っていても許してはくれないですね。yamlについては、読み方を知らないと少しとっつきにくいですかね・・・
これはググってもらって調べてもらえたら幸いです。(‘◇’)ゞ
(;・∀・)・・・おお放り投げましたな・・・

ここで少しIPアドレスの範囲についてお話しておきます。知ってるよ!って人は読み飛ばしてく下さい。
上の図で、10.0.0.0/16としてますが、範囲は10.0.0.1~10.0.255.254の65534個のIPアドレスが利用可能です。かなり多いような気もします。

さらに新しいVPCを作りたいです!ってなったときは、10.1.0.0/16と2つ目の数字を増やすと良いです。
で、更にもう一つVPCを増やしたいってときは・・・お解りかと思うけど、10.2.0.0/16と2つ目の数字をさらに増やしていく感じで番号帯を作っていくと良いと思います。(番号帯が重複しないように増やせます。)

で、65534個もいらんがなって人は、10.0.0.0/24で、10.0.0.1~10.0.0.254の254個の番号帯使ったら良いかと思います。この場合は3つ目の数字を増やしてく感じですね!
10.0.1.0/24(10.0.1.1~10.0.1.254)
10.0.2.0/24(10.0.2.1~10.0.2.254)
・・・

余談はこれでおしまいです。
おつぎは、CfnVPCのラッパー関数について少し説明します。
CfnVPCのラッパー関数は以下になります。
core/myconstructs/ec2/myvpc.py

from aws_cdk.aws_ec2 import CfnVPC

from core.basetypes.myec2 import MyVPCIF
from core.myconstructs.mytags import MyTags


def MyVpc(self: any, myif: MyVPCIF) -> CfnVPC:
    tags = MyTags(myif.tags)
    rsc = CfnVPC(
        self,
        myif.construct_id,
        cidr_block=myif.cidr_block,
        enable_dns_hostnames=myif.enable_dns_hostnames,
        enable_dns_support=myif.enable_dns_support,
        instance_tenancy=myif.instance_tenancy,
        ipv4_ipam_pool_id=myif.ipv4_ipam_pool_id,
        ipv4_netmask_length=myif.ipv4_netmask_length,
        tags=tags,
    )
    return rsc

myifという変数が先ほど作ったIFデータ構成です。後は単純にCfnVPCのパラメータに設定してあげてるだけです。
tagsだけは、別途関数を用意してそちらで先に設定してから、結果を設定するような、ちょっと特殊なことしていますが・・・これもそれほど難しくはないんじゃないかなと思います。

で、実際にリソース(VPC、サブネット)を作っていくコードですが、VPC、サブネットのリソースを一つのStackにまとめてコードを書いていきたいと思います。
対象のソース名を「first_vpc_stack.py」とします。
内容は以下になります。

01:from aws_cdk import Stack
02:from constructs import Construct
03:
04:from core.myconstructs.ec2.myvpc import MyVpc
05:from core.servicetypes.first_vpc_types import FirstVpcTypes
06:
07:
08:class FirstVpcStack(Stack):
09:    def __init__(
10:        self, scope: Construct, construct_id: str, myif: FirstVpcTypes, **kwargs
11:    ) -> None:
12:        super().__init__(scope, construct_id, **kwargs)
13:        # VPC
14:        vpfif = myif.firstvpc.vpcs["firstvpc"]
15:        firstvpc = MyVpc(self, myif=vpfif)

短くて理解しやすくできていると思います。
14行目はパラメータリストのVPCのIFに関連する部分を取得しています。
パラメータリストはyaml形式で以下のように記載してあり、この部分を「firstvpc.vpcs[‘firstvpc’]」と指定して以下の赤字の部分を取ってきます。

firstvpc:
  vpcs:
    firstvpc:
      construct_id: "firstvpc"
      cidr_block: "10.0.0.0/16"
      enable_dns_hostnames: True
      enable_dns_support: True
      instance_tenancy: "default"
      tags:
        vpctag1: "vpctag1-value"
        vpctag2: "vpctag2-value"

15行目で、取って来たパラメータリストを、そのままラッパー関数に渡しています。

firstvpc=MyVpc(self,myif=vpfif)

コードはそんなに難解ではないかなと思います。

では、最後にメインのapp.pyです。こちらには、パラメータリストを読み込んで、IFデータ構成に被せるという処理を記載します。
ちとbeforeとafterで書きますね。
まずはbeforeは第1回の空プロジェクトから以下になります。

#!/usr/bin/env python3
import os

from aws_cdk import App,Environment
from cdk_core_project.cdk_core_project_stack import CdkCoreProjectStack

app = App()
env = Environment(account='123456789012', region='ap-northeast-1')
CdkCoreProjectStack(app,"CdkCoreProjectStack",env=env)
app.synth()

続いてafter

#!/usr/bin/env python3
import os

from aws_cdk import App,Environment
from core.utils.configread import configread
from core.servicetypes.first_vpc_types import FirstVpcTypes
from core.first_vpc_stack import FirstVpcStack


app = App()
tmpif=FirstVpcTypes(**configread("core/parameters/first_vpc_params.yaml"))
env=Environment(region=tmpif.common.region,account=tmpif.common.account)
FirstVpcStack(app,"FirstVpcStack",myif=tmpif,env=env)
app.synth()

赤字のところがパラメータリストの読み込み箇所です。
青字が変更箇所です。ベタ書きしてた部分をパラメータリストから取得て設定するように変更してます。
configreadは、yamlファイルを読み込んでくれる関数です。
ここでは、yamlというパッケージと、jinja2というパッケージを使って実現してます。
yamlファイルから読み込んでIFデータ構成に簡単に被せてくれます。
この辺は、主題がCDKなので細かい説明は割愛します。

説明を省いている部分も多々ありますので、全体像はここで公開してます。

synth準備

全体的なコードは上記のGITから取得してください。
まず、新たに使用するパッケージを環境に追加します。
第1回から比べるとrequirements.txtに赤字の部分を追加します。

aws-cdk-lib==2.155.0
constructs>=10.0.0,<11.0.0
pyyaml==6.0.1
pydantic==2.5.3
jinja2==3.1.4

では、これらをインストールして、環境のアップデートをします。
最初は、プロジェクトのディレクトリ下(cdk_core_projectの下)に移動して、仮想環境を有効にします。以下はWindows Power Shellの例です。その他の環境は第1回を見て下さい。

> .venv\Scripts\Activate.ps1

で環境変数が有効にできたら以下のコマンドを実施です。
アップデートでなくて、ここで初めて環境作る人は以下を実施してからupdateを実施になります。

> pip install -r requirements.txt
> pip install -r requirements-dev.txt

既に上記を実施済みの場合は、以下のみ実施です。

> pip install --upgrade -r requirements.txt

これでsynth準備完了です。

synthする

synthは、pythonコードの確認と、cdkがCloudFormationの形式に変換された結果の確認ができます。
まず、synthが成功しないとdeployできないですね。(deployしてもエラーになります。)
では実施してみましょう。

> cdk synth

実行結果を以下です。

(.venv) PS E:\works\cdkstady\cdk-core-project-tmp> cdk synth
Resources:
  firstvpc4F2EE15C:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsHostnames: true
      EnableDnsSupport: true
      InstanceTenancy: default
      Tags:
        - Key: vpctag1
          Value: vpctag1-value
        - Key: vpctag2
          Value: vpctag2-value
    Metadata:
      aws:cdk:path: FirstVpcStack/firstvpc/firstvpc
  CDKMetadata:
    Type: AWS::CDK::Metadata
    Properties:
      Analytics: v2:deflate64:H4sIAAAAAAAA/zPSMzQ11TNQTCwv1k1OydbNyUzSqw4uSUzO1kksL45PTTbSc07LCwtw1nFOywtKLc4vLUpOrdUJqCzJyM/TN9YzNNIzVcwqzszULSrNK8nMTdULgtAANba5u1kAAAA=
    Metadata:
      aws:cdk:path: FirstVpcStack/CDKMetadata/Default
Parameters:
  BootstrapVersion:
    Type: AWS::SSM::Parameter::Value<String>
    Default: /cdk-bootstrap/hnb659fds/version
    Description: Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]

デ!プロイ!

初めてのデプロイです。デプロイの前にまだ一度もやってない人は、を実施する必要あります。
これは、AWSアカウントに対して1回やればよいのかと思います。

> cdk bootstrap

上手く行ったら、続いてdeployをやる前にdiffをやりましょう!初めてなんで作られるリソースが全部出てくるはず!

> cdk diff

で結果は以下の通り

cdk diff
Stack FirstVpcStack
Parameters
[+] Parameter BootstrapVersion BootstrapVersion: {"Type":"AWS::SSM::Parameter::Value<String>","Default":"/cdk-bootstrap/hnb659fds/version","Description":"Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]"}

Resources
[+] AWS::EC2::VPC firstvpc/firstvpc firstvpc4F2EE15C


✨  Number of stacks with differences: 1

出してみた感じ…「んー?」なんかよくわからんですね・・・
そんでもってデプロイしてみましょう~これはちょっと時間かかりますね。

> cdk deploy
> cdk deploy

✨  Synthesis time: 7.19s

FirstVpcStack:  start: Building a2abef6ce7920a7739e747ff0ae0f0ae04a6f3deb94e5f6f28872bbb19ccfa8d:123456789099-ap-northeast-1
FirstVpcStack:  success: Built a2abef6ce7920a7739e747ff0ae0f0ae04a6f3deb94e5f6f28872bbb19ccfa8d:123456789099-ap-northeast-1
FirstVpcStack:  start: Publishing a2abef6ce7920a7739e747ff0ae0f0ae04a6f3deb94e5f6f28872bbb19ccfa8d:123456789099-ap-northeast-1
FirstVpcStack:  success: Published a2abef6ce7920a7739e747ff0ae0f0ae04a6f3deb94e5f6f28872bbb19ccfa8d:123456789099-ap-northeast-1
FirstVpcStack: deploying... [1/1]
FirstVpcStack: creating CloudFormation changeset...
FirstVpcStack | 0/3 | 22:04:16 | REVIEW_IN_PROGRESS   | AWS::CloudFormation::Stack | FirstVpcStack User Initiated
FirstVpcStack | 0/3 | 22:04:22 | CREATE_IN_PROGRESS   | AWS::CloudFormation::Stack | FirstVpcStack User Initiated
FirstVpcStack | 0/3 | 22:04:25 | CREATE_IN_PROGRESS   | AWS::EC2::VPC      | firstvpc/firstvpc (firstvpc4F2EE15C)
FirstVpcStack | 0/3 | 22:04:25 | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata)
FirstVpcStack | 0/3 | 22:04:26 | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) Resource creation Initiated
FirstVpcStack | 1/3 | 22:04:26 | CREATE_COMPLETE      | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata)
FirstVpcStack | 1/3 | 22:04:26 | CREATE_IN_PROGRESS   | AWS::EC2::VPC      | firstvpc/firstvpc (firstvpc4F2EE15C) Resource creation Initiated
FirstVpcStack | 2/3 | 22:04:37 | CREATE_COMPLETE      | AWS::EC2::VPC      | firstvpc/firstvpc (firstvpc4F2EE15C) 
FirstVpcStack | 3/3 | 22:04:38 | CREATE_COMPLETE      | AWS::CloudFormation::Stack | FirstVpcStack

 ✅  FirstVpcStack

✨  Deployment time: 26.3s

Stack ARN:
arn:aws:cloudformation:ap-northeast-1:123456789099:stack/FirstVpcStack/7e07ccf0-83e3-11ef-b0b1-0ae15d915465✨  Total time: 33.48s

終わったらAWSコンソールからできたリソースを確認しましょう。
まずはVPC

(‘ω’)ノクリックすると拡大するよ!
下の奴が作ったものですね。これ作るとネットワークACLとかルートテーブルが自動的にできちゃうんですね…知らなかった…あとNameがないの気に入らないな~
もう一つCloudFormationでリソースができるのでそっちも確認!

(‘ω’)ノクリックすると拡大するよ!
なんやかんやで、CDKがリソース削除できなくて何やら環境がおかしくなったときは、こいつを抹消するときありますんで!一応チェックです。

destroy

作ったら壊す!これが世の常です!
で自動でできちゃった、ネットワークACLとかルートテーブルも消えるのかはきちんと確認しとかないとだめですね。ではdestroyです。

> cdk destroy
Are you sure you want to delete: FirstVpcStack (y/n)? y
FirstVpcStack: destroying... [1/1]

 ✅  FirstVpcStack: destroyed

かなりすぐ終わりましたね・・・
上手く消えたようです。メデタシメデタシ・・・
ちょっといくつか課題がでてしまったので、その辺を次回改善ですね。
・Nameはつけられないのか?
・ネットワークACLや、ルートテーブルのカスタマイズできるの?
ってあたりになります。
(´・ω・)あれ?この回だけで終わるはずでは?
・・・無理でしたね・・・( ;∀;)

最後に上記でも書いてますが、公開先のGITはこちらです。
と言う訳で「いちはじCDK第4回 VPCとサブネット②編」に続きます~

コメント

タイトルとURLをコピーしました