インフラ屋のAWSはじめた日記─GUIを捨てよ

第4回ネットワークを構築するんだ! 今日は

ネットワークを構築したい

今日はこの間からずっと気になっていたVPCというのを使ってネットワークを構築していきたいと思っている。

まず、今日構築したいのはこんなシンプルなものだ。

画像

グローバルIPが振られて、外からアクセスできるようなネットワークを1つと、外からはアクセスできないネットワークを1つ作りたい。

イメージとしては外からアクセスできるWebサーバと、外からはアクセスできないデータベースサーバをそれぞれ置けるような、ちょっと意味がありそうでだれでもすぐに思いつきそうなネットワーク構成。これを構築すると決めた。

AWSがどんなものかわからないからか、何をしたらいいのかわからなくなることが多い。だから先にやりたいことを見つけてやり方を探すようにしようと思った。

VPCの作成

VPCはクラウド上で仮想のネットワーク環境を構築するためのサービスらしい。そして、VPCというひとつのくくりの中にSubnetを作ることができるらしい。

とりあえず、VPCを作ることにする。びっくりしたのは、VPCはaws vpc ~ ではなくて、aws ec2であるということ。おそらく昔はec2の1機能だったのだろうと勝手に想像してみた。

$ aws ec2 create-vpc --cidr-block 172.16.0.0/16
{
    "Vpc": {
        "InstanceTenancy": "default",
        "State": "pending",
        "VpcId": "vpc-6ece0d0b",
        "CidrBlock": "172.16.0.0/16",
        "DhcpOptionsId": "dopt-c83421aa"
    }
} 

Stateがpendingということは、しばらく待つ必要があるっていうのはもう慣れっこで、確認のために1分くらいおいてdescribe-vpcsする。

$ aws ec2 describe-vpcs
{
    "Vpcs": [
        {
            "VpcId": "vpc-6ece0d0b",
            "InstanceTenancy": "default",
            "State": "available",
            "DhcpOptionsId": "dopt-c83421aa",
            "CidrBlock": "172.16.0.0/16",
            "IsDefault": false
        },
        {
           -略-
        }
    ]
}

State がavailableになっているのを確認した。

画像

今はこのようなVPCができている状態だと思われる。

ただ、VPCを作っただけではEC2をそこに起動することはできないようだ。Subnetというのを作る必要がある。

Subnetの作成

当初の予定どおり、グローバルのネットワークとローカルのネットワークの2つを作る。最初VPCでそれぞれ作るものと考えていたけれど、Subnetというので作れそうな気もしてきたので、こちらでやってみる。こちらもvpcではなくec2のサブコマンドのcreate-subnetでやれる。前回やったCLIの補完がだいぶ楽にしてくれているのが実感できる。もうドキュメントを見なくてもターミナルだけで探すことができている。

$ aws ec2 create-subnet --vpc-id vpc-6ece0d0b --cidr-block 172.16.64.0/24
{
    "Subnet": {
        "VpcId": "vpc-6ece0d0b",
        "CidrBlock": "172.16.64.0/24",
        "State": "pending",
        "AvailabilityZone": "ap-northeast-1c",
        "SubnetId": "subnet-5b1cf402",
        "AvailableIpAddressCount": 251
    }
}
$ aws ec2 create-subnet --vpc-id vpc-6ece0d0b --cidr-block 172.16.32.0/24
{
    "Subnet": {
        "VpcId": "vpc-6ece0d0b",
        "CidrBlock": "172.16.32.0/24",
        "State": "pending",
        "AvailabilityZone": "ap-northeast-1c",
        "SubnetId": "subnet-5d1cf404",
        "AvailableIpAddressCount": 251
    }
}

このようにvpcのIDとCIDRブロックを指定してSubnetを作成した。今回はグローバルにアクセスできるものとできないものとの2つのネットワークを作りたいから2つ作ったけど、この段階では区別はついていないように見える。

画像

たぶん、今作った状態はこんな感じなんだろうけど、このサブネット間の通信とか、インターネットへの接続とかどうなっているのか、よくわからなかった。

EC2を起動して疎通の確認をしたかったけれど、EC2にSSHで接続することもできなかった。というか、グローバルのIPアドレスが与えられていない。

おそらく、Subnetはスイッチみたいな状態で存在していて、ルータには接続されていないんじゃないかと思った。EC2を起動すればスイッチには接続されて、同一スイッチ内でなら通信できるけど、それ以外とは通信できない。そんな状態だと想像している。

そういえば、Subnetを作った時にふと気づいた事がある。AWSにはAvailability Zoneという概念があるらしい。Availability Zoneという概念は、Regionと呼ばれる地域単位での区切りの中で、さらにデータセンターを分けたような考え方で、同じ東京のリージョンでも数十km離れた場所にあって、データセンターの障害に対応できる仕組みになっているらしい。

せっかくなので、複数のAvailability Zoneを利用したネットワーク構成をしてみようと思う。

Availability Zone

Subnetを作成する時に--availability-zone オプションを指定するとAvailability Zoneを指定してSubnetを作る事ができそうだ。マジでコマンドの補完便利すぎる。

さっき作ったやつはap-northeast-1cとなっていたので、今度はap-northeast-1bを指定しようとしたけれど

A client error (InvalidParameterValue) occurred when calling the CreateSubnet
operation: Value (ap-northeast-1b) for parameter availabilityZone is invalid. 
Subnets can currently only be created in the following availability zones: 
ap-northeast-1c, ap-northeast-1a.

と出て、1aか1cしか使えないらしい。1bというのはないのかもしれない。

$ aws ec2 create-subnet --vpc-id vpc-6ece0d0b --cidr-block 172.16.128.0/24 --availability-zone ap-northeast-1a
{
    "Subnet": {
        "VpcId": "vpc-6ece0d0b",
        "CidrBlock": "172.16.128.0/24",
        "State": "pending",
        "AvailabilityZone": "ap-northeast-1a",
        "SubnetId": "subnet-ea0fd89d",
        "AvailableIpAddressCount": 251
    }
}
$ aws ec2 create-subnet --vpc-id vpc-6ece0d0b --cidr-block 172.16.160.0/24 --availability-zone ap-northeast-1a
{
    "Subnet": {
        "VpcId": "vpc-6ece0d0b",
        "CidrBlock": "172.16.160.0/24",
        "State": "pending",
        "AvailabilityZone": "ap-northeast-1a",
        "SubnetId": "subnet-d40fd8a3",
        "AvailableIpAddressCount": 251
    }
}

ap-northeast-1aにもSubnetを作ってみた。

今はきっとこの図のようになっているはずだ。

画像

なっているはずだけれども、EC2を立ち上げても、SSHで接続できないので、確認できないのが悔しいところ。

ルーティング

いい加減にEC2にSSHで接続できないので、やっていて虚しさを覚えはじめた。というか、合っているのかどうかが確認のできない試行錯誤って意味あるんだろうか。

そろそろ本気でEC2に接続できるように原因を考えていく。なんとなくだけど、ルーティングとかその辺りの設定が必要なんじゃないかって気がしている。というのも、さっき補完でそれっぽいのを見てるからだったりする。

$ aws ec2 create-[TAB]

この時にcreate-internet-gatewayがあるのを見ていて、実は気になっていた。今日何回も言うけど、補完はマジで便利。

Internet Gateway

というわけで、とりあえず、Internet Gatewayを作ってみる。

$ aws ec2 create-internet-gateway
{
    "InternetGateway": {
        "Tags": [],
        "InternetGatewayId": "igw-da14fdbf",
        "Attachments": []
    }
}

結構あっさりと作る事ができた。作るときにvpc-idを指定するのかと思ったけど、指定するオプションがなかったのが、ものすごく不安だ。もしかしたら、VPCと全く関係ない機能だったのかもしれない。とりあえず、他のinternet-gatewayのコマンドを探してみる。

$ aws ec2 help |grep internet
       o attach-internet-gateway
       o create-internet-gateway
       o delete-internet-gateway
       o describe-internet-gateways
       o detach-internet-gateway

ほう。attach-internet-gatewayというのがある。コレにvpc-idを指定するオプションがあれば、おそらく合っているはず。

$ aws ec2 attach-internet-gateway --vpc-id vpc-6ece0d0b --internet-gateway-id igw-da14fdbf

あった。vpc-idを指定する事ができた。これでVPCにinternet gatewayをアタッチすることができた。

画像

ここまでできたところで、たぶん、だけれども接続できるようにはなっていない。

Route Table

さっきなんとなくやったけど、案外使えるなと思ったのが

$ aws ec2 help |grep *****

これで目星をつけた名前で探すとなんとなくそれっぽいのを見つけられるってこと。

今回もルーティングについて何かないかなと探してみる。もう補完とこの方法でドキュメント見なくても、いろいろできるような気がしている。今日だってまだドキュメントを一度も見ていない。この日記を書くためのエディタと、ターミナルしか立ち上げていない。

$ aws ec2 help |grep route
       o associate-route-table
       o create-route
       o create-route-table
       o create-vpn-connection-route
       o delete-route
       o delete-route-table
       o delete-vpn-connection-route
       o describe-route-tables
       o disable-vgw-route-propagation
       o disassociate-route-table
       o enable-vgw-route-propagation
       o replace-route
       o replace-route-table-association

ほら、あった。たぶんcreate-route-tableだ。けど、いきなりcreate-route-tableをするような事はしない。まずはdescribeからやってみる。もしかしたら、勝手に作られている可能性もあるから。

$ aws ec2 describe-route-tables
{
    "RouteTables": [
        ?略? 
        {
            "Associations": [
                {
                    "RouteTableAssociationId": "rtbassoc-fffa2e9a",
                    "Main": true,
                    "RouteTableId": "rtb-c33df4a6"
                }
            ],
            "RouteTableId": "rtb-c33df4a6",
            "VpcId": "vpc-6ece0d0b",
            "PropagatingVgws": [],
            "Tags": [],
            "Routes": [
                {
                    "GatewayId": "local",
                    "DestinationCidrBlock": "172.16.0.0/16",
                    "State": "active",
                    "Origin": "CreateRouteTable"
                }
            ]
        }
    ]
}

describe-route-tableで見てみると、やっぱりあった。今回作ったvpc以外にももう1つVPCがあるらしく、そっちの方にくっついているRoute Tableと今回作ったVPCにくっついているRoute Tableがあることが確認できた。

Route Tableがあるのであればそこに外に出て行くような設定をしてあげれば良いはず。たぶんだけれど、create-routeがそういうコマンドなんだと思う。もし、Internet GatewayのIDとRoute TableのIDを指定するようなオプションがあれば間違いないと思っていいだろう。

補完があれば、その確認もすぐできる。今回何度目かわからないけど、補完はマジで最高だ。

$ aws ec2 create-route --gateway-id igw-da14fdbf --route-table-id rtb-c33df4a6 --destination-cidr-block 0.0.0.0/0

やはりオプションがあったから、すぐに実行してみる。destination-cidr-blockというのがあるので、もうほぼ間違いないだろうと思う。

$ aws ec2 describe-route-tables --route-table-ids rtb-c33df4a6
{
    "RouteTables": [
        {
            "Associations": [
                {
                    "RouteTableAssociationId": "rtbassoc-fffa2e9a",
                    "Main": true,
                    "RouteTableId": "rtb-c33df4a6"
                }
            ],
            "RouteTableId": "rtb-c33df4a6",
            "VpcId": "vpc-6ece0d0b",
            "PropagatingVgws": [],
            "Tags": [],
            "Routes": [
                {
                    "GatewayId": "local",
                    "DestinationCidrBlock": "172.16.0.0/16",
                    "State": "active",
                    "Origin": "CreateRouteTable"
                },
                {
                    "GatewayId": "igw-da14fdbf",
                    "DestinationCidrBlock": "0.0.0.0/0",
                    "State": "active",
                    "Origin": "CreateRoute"
                }
            ]
        }
    ]
}

指定した後のdescribe-route-tablesを見てみる。さっきとRoutesの部分が変わっているのでわかりやすい。たぶんこれで、外との通信ができるはずだ。

試してみると、ついに接続ができた。ここまで長かった。

ネットワークに接続されたサーバにSSHで接続できることがこんなに嬉しいとは思わなかった。

しかしひとつ問題が発生した。ローカルでデータベースとかを置きたいなと思っていたネットワークにも直接SSHで接続できてしまっている。これじゃダメだ。グローバルのIPアドレスを与えなきゃいいのかもしれないけれど、ネットワーク的に接続されている状態はそもそも嫌だ。

なんとかして、切り離したい。たぶんイメージだけど、今はこんな事になっているはず。

画像

このRouterのルーティングテーブルを書き換えれば、なんとかなると思う。

とりあえず、何かヒントを探すために、再びroute関係で何ができるのかを見てみることにした。

$ aws ec2 help |grep route

associate-route-table???

なんかこれ怪しい気がする。オプションを見てみると--route-table-idと--subnet-idの2つがある。これはたぶんSubnetごとにRoute Tableを変更することができそうな予感。

理想としてはこうなれば良いんじゃないかと思う。

画像

というわけで、まずはもう1つRoute Tableを作成する。

$ aws ec2 create-route-table --vpc-id vpc-6ece0d0b
{
    "RouteTable": {
        "Associations": [],
        "RouteTableId": "rtb-7335fc16",
        "VpcId": "vpc-6ece0d0b",
        "PropagatingVgws": [],
        "Tags": [],
        "Routes": [
            {
                "GatewayId": "local",
                "DestinationCidrBlock": "172.16.0.0/16",
                "State": "active",
                "Origin": "CreateRouteTable"
            }
        ]
    }
}

作った時にはdestination 172.16.0.0/16に対してlocalというgatewayにルーティングされているのがわかるので、もしかしたら、ここにassociateすれば良いんじゃないかという事が想像できる。なんか、最近は表示されているものからだいぶAWSを理解できるようになってきている気がする。

$ aws ec2 associate-route-table --subnet-id subnet-d40fd8a3 --route-table-id rtb-7335fc16
{
    "AssociationId": "rtbassoc-d1e236b4"
}
$ aws ec2 associate-route-table --subnet-id subnet-5b1cf402 --route-table-id rtb-7335fc16
{
    "AssociationId": "rtbassoc-dce236b9"
}

このコマンドを投入した直後には、今までSSHで接続されていたものが切断された。

いい感じだ。思っていた通りの動きをしてくれた。

グローバルのネットワークにいる、EC2からローカルにいるネットワークに対しては、しっかりpingが届いていた(Security GroupでICMPは許可済み⁠⁠。

[ec2-user@ip-172-16-32-219 $ ping 172.16.64.232
PING 172.16.64.232 (172.16.64.232) 56(84) bytes of data.
64 bytes from 172.16.64.232: icmp_seq=1 ttl=64 time=0.466 ms
64 bytes from 172.16.64.232: icmp_seq=2 ttl=64 time=1.55 ms
64 bytes from 172.16.64.232: icmp_seq=3 ttl=64 time=0.431 ms
^C
--- 172.16.64.232 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2405ms
rtt min/avg/max/mdev = 0.431/0.817/1.554/0.521 ms

これで当初思い描いていた、ネットワークが構築できた。

やりたいことを先に思い浮かべたら大体のことはAWSでできそうな気がするけど、やり方とか、概念がわからない。正直このあたり教えてくれる人がいたらすぐできるとは思うけど、CLIのhelpとかタブを押して出てくるオプションとかで推測しながら概念を勝手に理解していくのはなんだか楽しい。Linuxを初めて触った時の感覚が蘇ってきて、つい夜更かししてしまう。


なんだかそれらしくなってきた、とあるインフラエンジニア。クラウドを触るのが楽しそうだ。いよいよこの連載も後半です。次回は2月更新です、お楽しみに。

AWSの仕事ができるようになる、トレーニングプログラム

http://tr.pasonatech.co.jp/wpaws01

おすすめ記事

記事・ニュース一覧