
はじめに
CloudFormationがよくわからんという人
この記事は下記記事の続きの記事です。
「CloudFormationの基本的な文法を知りたい」「CloudFormationの使い方がわからん」といった場合は、↑の記事を読むことをおすすめする。
EC2とかVPCとかサブネットがよくわからんという人
こんな場合はこっちの記事を読むと良い。
- EC2やVPCやサブネットがよくわからない
- EC2はわかるけどなんでVPCやサブネットが必要なのかわからない
この記事の対象者
CloudFormationの基本的な文法や、やEC2, VPC, サブネットについては理解しているが、EC2インスタンスを立てるのにどうやって書いていったらいいのかわからーんという人。
CloudFormationでEC2サーバー2台の構成を建てる
AWSで何かサービスを建てる時、最も簡単なのは「EC2インスタンスを1台建てて、そこでアプリケーションを動かす」構成だ。これをCloudFormationで構成しようと思う。*1
CloudFormationとは?(わかっていれば読まなくて良い)
AWSのサーバー構成を記述すると、その通りにサーバーを建ててくれるというものだ。例えば「Webサーバーが1台でポート80を開ける。CPUのスペックはこんなもん。DBサーバーが1台あってWebサーバーからのMySQL接続だけを許可」といったことが記述できる。
CloudFormationを利用しなくても、WebのUIでボタンを押していけばサーバーを建てること自体は可能だ。しかし、「もう一回同じ構成を作ってくれ」と言われた場合に *2、は大変だ。しかしCloidFormationならAnsibleの用に設定ファイルを流し込むだけて全く同じ構成のものが作れる。これがCloudFormationを利用するメリットである。
構築してみる
今回は development.yml として、Dev環境を構築するというシナリオで行う。
VPCを作成する
VPCを作るだけならすごく簡単なので、まずはVPCを構築してみる。 [AWSをはじめてみる2 - CloudFormationでのプロビジョニング・構成管理 - 猫でもわかるWebプログラミング の方も、VPCの作成を題材にしているので参考にしてもらいたい。
AWSTemplateFormatVersion: '2010-09-09'
Description: "Create dvelopment environment"
Resources:
DevelopmentVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
Tags:
- Key: Name
Value: Development-VPC
今後は、Resources 以下のみ書いていくので注意してもらいたい。
DevelopmentVPC:と書き始める。ここの名前は何でもいいが、他と被らない名前にする必要があるので、今回はDevelopmentVPCとしたProperties以下の VPC の設定を書いていく
CidrBlock
CIDRというのは x.x.x.x/16 のような書き方のこと。このVPCで利用するIPの範囲を指定する。10.0.0.0/16 は 10.0.0.0 〜 10.0.255.255 の範囲を利用することを示す。*3 ふつうはVPCを /16 にしてサブネットを /24 とかにするので、それに習って今回は /16 とした。((サーバーの台数によってはIPが足りなくなったりするので適宜いい感じに設定してあげてください。わからなければ思考停止で /16 でいいと思います。))
Tags
Tags:
- Key: Name
Value: Development-VPC
高こう定するとここのNameのところに Development-VPC と表示される。付けなくても良いのだが、Webのコンソールから見た時かなり見づらいので、設定したほうが良い。完全にWebの見た目だけのための設定なので好きに設定して良い。この設定に限らない話だが、日本語を使うとAWSのWeb上で文字化けするので英語を推奨する。

ここまででVPCの作成は終わりなので、一度CloudFormationを流してみて正しくVPCができていることを確認するとよい。次回以降は「スタックの更新」を行えば差分だけが適用されるし、「スタックの削除」を行えば今回作ったVPC, EC2などはすべて削除できるので、切りの良いところまでできたら流してみて文法ミスがないかなどをチェックしてほしい。*4
インターネットゲートウェイの設置
VPCを作成したらインターネットゲートウェイを設置してやる必要がある。VPC内に設置されたEC2インスタンスはインターネットゲートウェイを経由しなければインターネットにアクセスできない。逆に外からVPC内にアクセスする場合もインターネットゲートウェイを通る。インターネットゲートウェイの主な役割はVPC内外でのアドレス変換である。 *5
このインターネットゲートウェイは結構複雑だ。長いので適宜コメントで補足しているので見てほしい。以下の設定が書かれている。
- Gatewayを作成
- GatewayをVPCに配置
- ルートテーブルを作成。ルートテーブルとは「VPCの中から外に出る場合はGatewayを通ってアドレス変換してね」というのを記述するものである。
- ルートテーブルの内容を設定
# VPC内とインターネットをつなぐGatewayを作成
DevelopmentInternatGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: Development-VPC-Gateway
# GatewayをVPCに配置する
# Gateway作成とは別に配置の設定が必要となる
AttachDevelopmentGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
# VpcIdで指定されたVPCに、InternetGatewayIdで指定されたGatewayを配置する
VpcId: !Ref DevelopmentVPC
InternetGatewayId: !Ref DevelopmentInternatGateway
# ルートテーブルを作成
DevelopmentRouteTable:
Type: AWS::EC2::RouteTable
# このようにDependsOnを書くと、AttachGatewayが完了してから
# ルートテーブルが作成される。
# Proertiesの中でDevelopmentVPCを参照しているので、
# DevelopmentVPCが作られたあとに実行されることは保証されているが、
# AttachされているかどうかはわからないのでDependsOnで明記する必要がある
DependsOn: AttachDevelopmentGateway
Properties:
VpcId: !Ref DevelopmentVPC
Tags:
- Key: Name
Value: Development-RouteTable
# ルートテーブルの設定
DevelopmentGatewayRoute:
Type: AWS::EC2::Route
DependsOn: AttachGateway
Properties:
# VPC内から外へのすべての通信はInternetGatewayを通るようにする設定を
# DevelopmentRouteTable に入れる。
RouteTableId: !Ref DevelopmentRouteTable
# 0.0.0.0/0 はすべてのIPを表す(VPC内のアドレスは除く)
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref AsadaigakuDevInternetGateway
ちょっと複雑だったがこれでVPCの中とインターネットが接続できるようになった。これを行わないと、VPC内のサーバーはインターネットにアクセスできないし、*6 外から中にhttpでアクセスしたりSSHしたりすることもできない。
サブネットの作成
サブネットの作成はVPCと同じでシンプルだ。
# ユーザー(開発者)がインターネット経由でアクセスできるサブネット
DevelopmentPublicSubnet:
Type: AWS::EC2::Subnet
DependsOn: AttachGateway
Properties:
CidrBlock: 10.0.1.0/24
MapPublicIpOnLaunch: true
VpcId: !Ref DevelopmentVPC
Tags:
- Key: Name
Value: Development-Public-VPC
ここまで読めたならもうこれは読めるだろう。IPアドレス帯としては 10.0.1.0 〜 10.0.1.255 をこのサブネット用のものとして定義する。((これも先程のVPCと同様、特にこだわりがなければ /24 で良いだろう))
DevelopmentPublicSubnet という名前をつけているが、これはインターネットからポート80または443でアクセスできるという意味で付けていますので、 DevelopmentWebServerSubnet でもなんでも、なんかいい感じの名前を付けてください。
EC2インスタンスしか作らない場合、サブネットの意義はあまり感じられませんが、EC2インスタンスを作成する際にサブネットは必要になるので、作る必要があります。
セキュリティグループの作成
セキュリティグループはEC2インスタンスに設定するセキュリティの設定です。「ここからここへはポート22のアクセスを許可」などの情報を書きます。
SSH用セキュリティグループの作成
まずは「SSH可能とするEC2インスタンスに設定するためのセキュリティグループ」を作成します。
# 開発環境EC2インスタンスにSSHするためのセキュリティグループ
DevelopmentSSHSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !Ref DevelopmentVPC
GroupDescription: Enable SSH
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
これももう読んでもらえればだいたい分かるかと思いますが、ポート22に来たtpcのアクセスを、アクセスもとがどこかにかかわらず常に許可する設定です。 VpcId が設定されていますが、これは別にPC内部のすべてのインスタンスのポート22への接続を許可する わけではありません 。このセキュリティグループをEC2インスタンスに付与すると、そのインスタンスへのSSH接続が可能になります。
GroupDescription は必須要素なので注意してください。
HTTP/HTTPS用セキュリティグループの作成
上記とほぼ同様です
# Webアプリケーションにアクセスできるようにするセキュリティグループ
# VPNからのアクセスのみ許可する
DevelopmentWebSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Enable web traffic to Instance
VpcId: !Ref DevelopmentVPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
- IpProtocol: tcp
FromPort: 443
ToPort: 443
EC2インスタンスを立てる
ようやくEC2インスタンスを建てられます。
DevelopmentWeb:
Type : AWS::EC2::Instance
Properties:
# Amazon Linux 2
ImageId: ami-0f9ae750e8274075b
InstanceType: t2.micro
SubnetId: !Ref DevelopmentPublicSubnet
SecurityGroupIds:
- !Ref DevelopmentSshSecurityGroup
- !Ref DevelopmentWebSecurityGroup
KeyName: sakamoto
Tags:
- Key: Name
Value:Development-Web
これももう見たらわかるかと思います。EC2について全然わからん!って人は下記の記事を見ながら一度EC2インスタンスを立ててみるといいと思います。
ImageIdはAMIってやつです。OSみたいなものです。KeyNameは初期設定されるSSH用のキーの名前です。AMIやキー、インスタンスタイプについては↑のブログを呼んでみるといいです。
他は見ての通り、先ほど作成したサブネットやセキュリティグループを設定します。CloudFormationでスタックを作成してみたら、EC2のコンソールからIPを調べてSSH接続してみましょう。Keyが正しく設定されていれば
ssh ec2-user@<IP Address>
で接続できるかと思います。
ポート80も空いていますが、まだWebアプリケーションが動いていないので、接続しようとしてもなにも応答はありません。
さいごに
RDSだったり、Elastic IPだったりDNSだったりプロビジョニングだったり、まだいろいろやるべきことはありますのですが、長くなったので次回以降にします。
*1:EC2を利用する際にセットでRDSを使うことが多いが、RDSは結構複雑なので、次回以降で扱う
*2:例えばOSのバージョンを上げたいのでインスタンスを作り直したい、サーバー台数を増やしたいのでもう一台同じ設定で建てたい、といった状況が考えられる
*3:CIDRの読み方については簡単なのでググって調べてほしい
*4:yamlにミスがある場合はCloudFormationが流れる前にエラーが表示される。yamlにミスは無いが設定内容にミスがあったりする場合は、更新中にエラーがでてロールバックされたり、更新されたものの思い通りに設定できていなかったりするので注意してみてほしい。
*5:詳しくはNATでググってほしい。長くなるので細かくは説明しない
*6:インターネットにアクセスできないと、yumのようなコマンドは動かない