ぶろとよ

ネットワーク系クラウドエンジニア(AWS)の技術ブログ。自動化に興味があるためAWS CLIを勉強&アウトプット中。

AWS CloudShell:VPC基盤を作成する(VPC・サブネット・ルートテーブル等)

以前、PowerShellを使ってVPC~EC2インスタンスまでの作成記事を書いたのですが、、、、久しぶりに読み返してみたら量が多くてみづらい・・・。

blog.toyokky.com

最近はセキュリティの都合上、PowerShellにアクセスキーを入れてAWS CLIを利用するより、AWS CloudShellを利用することが多いため、上の記事の分割とCloudShell版への変更を行っていきます。


本記事では、AWS CloudShellを利用して以下のVPC系リソースを作成します。

リソース種別 AZ 個別情報 Name CIDR, その他
VPC - - blog-P1x-Vpc 192.168.128.0/17
サブネット 1a パブリック blog-P1a-Sub-Pub01 192.168.128.0/24
1a プライベート blog-P1a-Sub-Pri01 192.168.129.0/24
1c パブリック blog-P1c-Sub-Pub01 192.168.192.0/24
1c プライベート blog-P1c-Sub-Pri01 192.168.193.0/24
インターネットゲートウェイ - - blog-P1x-Igw -
ルートテーブル 1a パブリック blog-P1a-Rtb-Pub01 -
1a プライベート blog-P1a-Rtb-Pri01 -
1c パブリック blog-P1c-Rtb-Pub01 -
1c プライベート blog-P1c-Rtb-Pri01 -

※Nameの命名規則は自分ルール「AWSリソースの命名規則について」を使用します。
※サブネットはAZ毎にパブリックとプライベートを作成します。
※ルートテーブルもサブネットと同様、AZ毎にパブリックとプライベートを作成します。

目次

検証環境

  • 検証日: 2022/09/24
  • 実行環境
    • PC
      • Windows10 Home Ver21H1
        • Google Chrome: バージョン: 105.0.5195.127(Official Build) (64 ビット)
    • AWSマネジメントコンソール
      • AWS CloudShell
        • AWS CLI: aws-cli/2.7.33 Python/3.9.11 Linux/4.14.287-215.504.amzn2.x86_64 exec-env/CloudShell exe/x86_64.amzn.2 prompt/off

注意事項

  • 本記事の内容はAWS CloudShellで検証しています。
  • AWS CLIはバージョン2を使用しています(CloudShellのデフォルトがバージョン2)。
  • コマンド内の変数やパラメータやは検証で使用したものを記載しています。ご自身の環境に合わせ、書き換えて使用してください。
  • 個人で検証しているため実行結果に責任は持てません。必ずご自身でも検証してから使用してください。


1. AWS CloudShell

1.1. AWS CloudShellとは

AWS CloudShellは、AWSマネジメントコンソールからAWS CLI v2が利用できる機能です。
手元のPCからAWS CLIを利用する場合、手元のPCへAWS CLIをインストールして、IAMユーザーとアクセスキーを発行してAWS CLIへ設定するなどの作業がありますが、AWS CloudShellはブラウザ上で動くためそういった作業が不要です。
また、アクセスキーの流出も無いためセキュリティ的にも安全です。

1.2. メリット・デメリット(個人の感想)

あくまでも、私が思っているAWS CloudShellのメリット・デメリットですが、

■ メリット

  • AWSマネジメントコンソールにログインできれば使える
    • 操作権限はそのログインしたIAMユーザーの権限と同等
    • 新規顧客のAWS環境でも、直ぐにAWS CLIが利用できる
  • アクセスキーを発行しなくて良い
    • 流出の心配が無い
    • セキュリティ意識の低いメンバーへアクセスキーを発行する恐怖からの解放
  • AWS CloudShell ~ 手元PC 間でのファイル受け渡しも可能
  • 「--profile」オプションを使わなくて良い
    • 複数のAWS案件を持つ場合、手元PCで案件を分けるために「--profile」オプションを使っていた

■ デメリット

  • 使用した後に110日放置すると、ストレージ消すぞ!とメールが来て焦る
    • CloudShellにファイルを残さない運用をしていれば問題ない
    • 必要なファイルを残したい場合は一度CloudShellへログインすればOK
    • AWS側へ問い合わせた際、このメールの改善は検討している。と言っていた
  • 手元PCを使うよりもAWS CloudShell ~ 手元PC 間でのファイル受け渡しは面倒


1.3. 使用方法

AWS CloudShellを利用するには、やりたい作業の操作権限を持ったIAMユーザでAWSマネジメントコンソールへログインして、画面右上の このマークを押すか、以下のURLへアクセスします。

AWS CloudShell [東京リージョン]
https://ap-northeast-1.console.aws.amazon.com/cloudshell/home?region=ap-northeast-1

※AWS CloudShell [東京リージョン]で作成したリソースは、東京リージョンへ作成されます。他のリージョンへ作成する場合は、そのリージョンからCloudShellへ入るか、「--region」オプションを使用してください。


1.4. 長文表示時のPager設定(less)をOFFにする

AWS CLI v2からPager設定(less)が有効になっているため、コマンド入力時に出力が途中で止まります。かなり煩わしいのでOFFにする方法です。

aws configure set cli_pager ""

戻す場合は以下のコマンドです。

aws configure set cli_pager "less"

less表示から抜けたい時は「q」キーです。
※Ctrl+Cで抜けるとバグるのは何なのだろうか・・・。


2. VPC

2.1. VPCの作成

# 変数の指定 ★環境に合わせて修正
vpc_name="blog-P1x-Vpc"
vpc_cidr="192.168.128.0/17"

# VPCの作成
aws ec2 create-vpc \
    --cidr-block ${vpc_cidr} \
    --tag-specifications "ResourceType=vpc, \
        Tags=[{Key=Name,Value=${vpc_name}}]"


2.2. VPCの確認

# すべて表示
aws ec2 describe-vpcs

# Nameタグを指定して表示
vpc_name="blog-P1x-Vpc"
aws ec2 describe-vpcs \
    --filters "Name=tag:Name,Values=${vpc_name}"


3. サブネット

3.1. サブネットの作成

# ■ 作成したVPCのIDを変数へ格納する(共通利用)
vpc_name="blog-P1x-Vpc"
vpc_id=`aws ec2 describe-vpcs \
    --filters "Name=tag:Name,Values=${vpc_name}" \
    --query "Vpcs[].VpcId" \
    --output text` \
    && echo ${vpc_id}


# -------------------------------------------
# ■ サブネット作成: AZ-1a パブリック
## 変数の指定 ★環境に合わせて修正
sub_name="blog-P1a-Sub-Pub01"
sub_cidr="192.168.128.0/24"
availability_zone="ap-northeast-1a"

## サブネットの作成
aws ec2 create-subnet \
    --vpc-id ${vpc_id} \
    --cidr-block ${sub_cidr} \
    --availability-zone ${availability_zone} \
    --tag-specifications "ResourceType=subnet, \
        Tags=[{Key=Name,Value=${sub_name}}]"

## パブリックなのでEC2作成時にパブリックIPが自動付与されるようにする

### 作成したサブネットのIDを変数へ格納する
sub_id=`aws ec2 describe-subnets \
    --filters "Name=tag:Name,Values=${sub_name}" \
    --query "Subnets[].SubnetId" \
    --output text` \
    && echo ${sub_id}

### GUIの「パブリック IPv4 アドレスを自動割り当て」を「いいえ→はい」にする作業
aws ec2 modify-subnet-attribute \
    --subnet-id ${sub_id} \
    --map-public-ip-on-launch


# -------------------------------------------
# ■ サブネット作成: AZ-1a プライベート
## 変数の指定 ★環境に合わせて修正
sub_name="blog-P1a-Sub-Pri01"
sub_cidr="192.168.129.0/24"
availability_zone="ap-northeast-1a"

## サブネットの作成
aws ec2 create-subnet \
    --vpc-id ${vpc_id} \
    --cidr-block ${sub_cidr} \
    --availability-zone ${availability_zone} \
    --tag-specifications "ResourceType=subnet, \
        Tags=[{Key=Name,Value=${sub_name}}]"


# -------------------------------------------
# ■ サブネット作成: AZ-1c パブリック
## 変数の指定 ★環境に合わせて修正
sub_name="blog-P1c-Sub-Pub01"
sub_cidr="192.168.192.0/24"
availability_zone="ap-northeast-1c"

## サブネットの作成
aws ec2 create-subnet \
    --vpc-id ${vpc_id} \
    --cidr-block ${sub_cidr} \
    --availability-zone ${availability_zone} \
    --tag-specifications "ResourceType=subnet, \
        Tags=[{Key=Name,Value=${sub_name}}]"

## パブリックなのでEC2作成時にパブリックIPが自動付与されるようにする

### 作成したサブネットのIDを変数へ格納する
sub_id=`aws ec2 describe-subnets \
    --filters "Name=tag:Name,Values=${sub_name}" \
    --query "Subnets[].SubnetId" \
    --output text` \
    && echo ${sub_id}

### GUIの「パブリック IPv4 アドレスを自動割り当て」を「いいえ→はい」にする作業
aws ec2 modify-subnet-attribute \
    --subnet-id ${sub_id} \
    --map-public-ip-on-launch


# -------------------------------------------
# ■ サブネット作成: AZ-1c プライベート
## 変数の指定 ★環境に合わせて修正
sub_name="blog-P1c-Sub-Pri01"
sub_cidr="192.168.193.0/24"
availability_zone="ap-northeast-1c"

## サブネットの作成
aws ec2 create-subnet \
    --vpc-id ${vpc_id} \
    --cidr-block ${sub_cidr} \
    --availability-zone ${availability_zone} \
    --tag-specifications "ResourceType=subnet, \
        Tags=[{Key=Name,Value=${sub_name}}]"


3.2. サブネットの確認

# すべて表示
aws ec2 describe-subnets

# Nameタグを指定して表示
sub_name="blog-P1a-Sub-Pub01"
aws ec2 describe-subnets \
    --filters "Name=tag:Name,Values=${sub_name}"


4. インターネットゲートウェイ

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

# 変数の指定 ★環境に合わせて修正
igw_name="blog-P1x-Igw"

# インターネットゲートウェイの作成
aws ec2 create-internet-gateway \
    --tag-specifications "ResourceType=internet-gateway, \
        Tags=[{Key=Name,Value=${igw_name}}]"


4.2. インターネットゲートウェイとVPCの関連付け

# 作成したVPCのIDを変数へ格納する
vpc_name="blog-P1x-Vpc"
vpc_id=`aws ec2 describe-vpcs \
    --filters "Name=tag:Name,Values=${vpc_name}" \
    --query "Vpcs[].VpcId" \
    --output text` \
    && echo ${vpc_id}

# 作成したインターネットゲートウェイのIDを変数へ格納する
igw_name="blog-P1x-Igw"
igw_id=`aws ec2 describe-internet-gateways \
    --filters "Name=tag:Name,Values=${igw_name}" \
    --query "InternetGateways[].InternetGatewayId" \
    --output text` \
    && echo ${igw_id}

# インターネットゲートウェイとVPCを関連付ける
aws ec2 attach-internet-gateway \
    --vpc-id ${vpc_id} \
    --internet-gateway-id ${igw_id}


4.3. インターネットゲートウェイの確認

# すべて表示
aws ec2 describe-internet-gateways

# Nameタグを指定して表示
igw_name="blog-P1x-Igw"
aws ec2 describe-internet-gateways \
    --filters "Name=tag:Name,Values=${igw_name}"


5. ルートテーブル

5.1. ルートテーブルの作成

# ■ 作成したVPCのIDを変数へ格納する(共通利用)
vpc_name="blog-P1x-Vpc"
vpc_id=`aws ec2 describe-vpcs \
    --filters "Name=tag:Name,Values=${vpc_name}" \
    --query "Vpcs[].VpcId" \
    --output text` \
    && echo ${vpc_id}


# -------------------------------------------
# ■ ルートテーブル作成: AZ-1a パブリック
## 変数の指定 ★環境に合わせて修正
rtb_name="blog-P1a-Rtb-Pub01"

aws ec2 create-route-table \
    --vpc-id ${vpc_id} \
    --tag-specifications "ResourceType=route-table, \
        Tags=[{Key=Name,Value=${rtb_name}}]"

#"# -------------------------------------------
# ■ ルートテーブル作成: AZ-1a プライベート
rtb_name="blog-P1a-Rtb-Pri01"

aws ec2 create-route-table \
    --vpc-id ${vpc_id} \
    --tag-specifications "ResourceType=route-table, \
        Tags=[{Key=Name,Value=${rtb_name}}]"

# -------------------------------------------
# ■ ルートテーブル作成: AZ-1c パブリック
## 変数の指定 ★環境に合わせて修正
rtb_name="blog-P1c-Rtb-Pub01"

aws ec2 create-route-table \
    --vpc-id ${vpc_id} \
    --tag-specifications "ResourceType=route-table, \
        Tags=[{Key=Name,Value=${rtb_name}}]"

#"# -------------------------------------------
# ■ ルートテーブル作成: AZ-1c プライベート
rtb_name="blog-P1c-Rtb-Pri01"

aws ec2 create-route-table \
    --vpc-id ${vpc_id} \
    --tag-specifications "ResourceType=route-table, \
        Tags=[{Key=Name,Value=${rtb_name}}]"


5.2. ルートテーブルとサブネットの関連付け

関連付けの組み合わせは以下です。
※ルートテーブルの構成要素にAZの指定はありませんが、サブネットのAZと合わせます。将来的にNATゲートウェイやTransit Gatewayを使う場合など、AZ毎に分けておいた方が利点があると思うからです。

AZ 用途 ルートテーブル サブネット
1a パブリック blog-P1a-Rtb-Pub01 blog-P1a-Sub-Pub01
1a プライベート blog-P1a-Rtb-Pri01 blog-P1a-Sub-Pri01
1c パブリック blog-P1c-Rtb-Pub01 blog-P1c-Sub-Pub01
1c プライベート blog-P1c-Rtb-Pri01 blog-P1c-Sub-Pri01

本手順をAWS CLIで行う際の注意点
1つのルートテーブルへ2つ以上のサブネットを関連付けする場合、関連付けコマンドassociate-route-tableはサブネット数分の実行が必要です。1回のコマンド実行で同時に2つは付けられない。

また、関連付け対象のサブネットがDefaultルートテーブルに紐付いている必要があります。他のルートテーブルへ明示的に関連付けしているサブネットは別の方法で付け替えますが、方法が面倒になるためGUIで付け替えたほうが楽です。


# -------------------------------------------
# ■ 関連付け: AZ-1a パブリック
## ルートテーブルのIDを変数へ格納する
rtb_name="blog-P1a-Rtb-Pub01"
rtb_id=`aws ec2 describe-route-tables \
    --filters "Name=tag:Name,Values=${rtb_name}" \
    --query "RouteTables[].RouteTableId" \
    --output text` \
    && echo ${rtb_id}

## サブネットのIDを変数へ格納する
sub_name="blog-P1a-Sub-Pub01"
sub_id=`aws ec2 describe-subnets \
    --filters "Name=tag:Name,Values=${sub_name}" \
    --query "Subnets[].SubnetId" \
    --output text` \
    && echo ${sub_id}

## ルートテーブルとサブネットの関連付け
aws ec2 associate-route-table \
    --route-table-id ${rtb_id} \
    --subnet-id ${sub_id}

# -------------------------------------------
# ■ 関連付け: AZ-1a プライベート
## ルートテーブルのIDを変数へ格納する
rtb_name="blog-P1a-Rtb-Pri01"
rtb_id=`aws ec2 describe-route-tables \
    --filters "Name=tag:Name,Values=${rtb_name}" \
    --query "RouteTables[].RouteTableId" \
    --output text` \
    && echo ${rtb_id}

## サブネットのIDを変数へ格納する
sub_name="blog-P1a-Sub-Pri01"
sub_id=`aws ec2 describe-subnets \
    --filters "Name=tag:Name,Values=${sub_name}" \
    --query "Subnets[].SubnetId" \
    --output text` \
    && echo ${sub_id}

## ルートテーブルとサブネットの関連付け
aws ec2 associate-route-table \
    --route-table-id ${rtb_id} \
    --subnet-id ${sub_id}

# -------------------------------------------
# ■ 関連付け: AZ-1c パブリック
## ルートテーブルのIDを変数へ格納する
rtb_name="blog-P1c-Rtb-Pub01"
rtb_id=`aws ec2 describe-route-tables \
    --filters "Name=tag:Name,Values=${rtb_name}" \
    --query "RouteTables[].RouteTableId" \
    --output text` \
    && echo ${rtb_id}

## サブネットのIDを変数へ格納する
sub_name="blog-P1c-Sub-Pub01"
sub_id=`aws ec2 describe-subnets \
    --filters "Name=tag:Name,Values=${sub_name}" \
    --query "Subnets[].SubnetId" \
    --output text` \
    && echo ${sub_id}

## ルートテーブルとサブネットの関連付け
aws ec2 associate-route-table \
    --route-table-id ${rtb_id} \
    --subnet-id ${sub_id}

# -------------------------------------------
# ■ 関連付け: AZ-1c プライベート
## ルートテーブルのIDを変数へ格納する
rtb_name="blog-P1c-Rtb-Pri01"
rtb_id=`aws ec2 describe-route-tables \
    --filters "Name=tag:Name,Values=${rtb_name}" \
    --query "RouteTables[].RouteTableId" \
    --output text` \
    && echo ${rtb_id}

## サブネットのIDを変数へ格納する
sub_name="blog-P1c-Sub-Pri01"
sub_id=`aws ec2 describe-subnets \
    --filters "Name=tag:Name,Values=${sub_name}" \
    --query "Subnets[].SubnetId" \
    --output text` \
    && echo ${sub_id}

## ルートテーブルとサブネットの関連付け
aws ec2 associate-route-table \
    --route-table-id ${rtb_id} \
    --subnet-id ${sub_id}


5.3. ルートテーブルへルート情報を追加する

本構成で追加するルートは、以下の2本です。
パブリックサブネットがインターネットへ出られるように、デフォルトルートを書きます。

AZ 用途 ルートテーブル 宛先ネットワーク ターゲット(NextHop)
1a パブリック blog-P1a-Rtb-Pub01 0.0.0.0/0 InternetGateway: blog-P1x-Igw
1c パブリック blog-P1c-Rtb-Pub01 0.0.0.0/0 InternetGateway: blog-P1x-Igw


# -------------------------------------------
# ■ ルート追加: AZ-1a パブリック
## ルートテーブルのIDを変数へ格納する
rtb_name="blog-P1a-Rtb-Pub01"
rtb_id=`aws ec2 describe-route-tables \
    --filters "Name=tag:Name,Values=${rtb_name}" \
    --query "RouteTables[].RouteTableId" \
    --output text` \
    && echo ${rtb_id}

## 作成したインターネットゲートウェイのIDを変数へ格納する
igw_name="blog-P1x-Igw"
igw_id=`aws ec2 describe-internet-gateways \
    --filters "Name=tag:Name,Values=${igw_name}" \
    --query "InternetGateways[].InternetGatewayId" \
    --output text` \
    && echo ${igw_id}

# ルートテーブルへルート情報を追加する
dest_cidr="0.0.0.0/0"

aws ec2 create-route \
    --route-table-id ${rtb_id} \
    --gateway-id ${igw_id} \
    --destination-cidr-block ${dest_cidr}


# -------------------------------------------
# ■ ルート追加: AZ-1c パブリック
## ルートテーブルのIDを変数へ格納する
rtb_name="blog-P1c-Rtb-Pub01"
rtb_id=`aws ec2 describe-route-tables \
    --filters "Name=tag:Name,Values=${rtb_name}" \
    --query "RouteTables[].RouteTableId" \
    --output text` \
    && echo ${rtb_id}

## 作成したインターネットゲートウェイのIDを変数へ格納する
igw_name="blog-P1x-Igw"
igw_id=`aws ec2 describe-internet-gateways \
    --filters "Name=tag:Name,Values=${igw_name}" \
    --query "InternetGateways[].InternetGatewayId" \
    --output text` \
    && echo ${igw_id}

# ルートテーブルへルート情報を追加する
dest_cidr="0.0.0.0/0"

aws ec2 create-route \
    --route-table-id ${rtb_id} \
    --gateway-id ${igw_id} \
    --destination-cidr-block ${dest_cidr}


5.4. ルートテーブルの確認

# すべて表示
aws ec2 describe-route-tables

# Nameタグを指定して表示
rtb_name="blog-P1a-Rtb-Pub01"
aws ec2 describe-route-tables \
    --filters "Name=tag:Name,Values=${rtb_name}"