本記事で学べること
本記事は「AWSの環境構築で学ぶトラブルシューティング」シリーズの最終回となっています。
本シリーズは、実際に手を動かしながらWSの環境構築とその過程でトラブルが起こった場合の対処方法や問題の特定方法などを体系的に学べる内容になっています。また、トラブルシューティングのセクションでは、遭遇した問題の問題の特定方法や解決方法について解説します。
今回は、Part 1で手動で構築した内容をCloud Formationを使用して自動で構築できるようにします。自動で構築することは人の操作によるミスがないことや、誰でも構築を行えるようにできるため、作業効率や労働生産性を向上させることができます。
「AWSの環境構築で学ぶトラブルシューティング」シリーズはこちら
https://envader.plus/article/259
https://envader.plus/article/260
https://envader.plus/article/262
環境構築のゴール
本記事における、環境構築のゴールを以下の図にまとめました。Cloud Formationで環境構築し、VPC内のパブリックサブネットに配置したインスタンスにSSH接続することがゴールです。
今までの記事の片付け
Cloud Formationで環境を構築する際に、既存の環境が存在すると環境の作成が行えませんので、Part1~3で使用した環境を削除します。
既に環境を削除している場合はこちらのセクションは飛ばして構いません。
-
インスタンスの削除
作成した全てのインスタンスを選択し、インスタンスの状態 → 「インスタンスの終了」を選択し、削除します。
-
VPCの削除
作成した全てのVPCを選択し、アクション → 「VPCを削除」を選択し、削除します。
VPCを削除すると、VPCに紐付いたコンポーネント(セキュリティグループ、サブネット、インターネットゲートウェイなど)も削除されます。
前提知識の解説
Cloud FormationはYAMLと呼ばれるファイル(テンプレート)に構築内容を記載し、そのファイルを基に環境を構築します。まず、YAMLについて解説します。
YAMLとは
YAMLは、”YAML Ain’t Markup Language”の再帰的な呼称で「ヤムル」と発音されることが多いです。YAMLは主に設定ファイルやデータのシリアライズ(複数の並列データを直列化して送信すること)に使用され、その構文は人間が読みやすいことを目的としています。
-
YAML Ain’t Markup Language
”YAML Ain’t Markup Language”というフレーズは、YAMLはマークアップ言語ではなく、データを表現するための言語であることを示しています。
-
再帰的な呼称
再帰的な呼称とは、呼称自体がその略称を説明するために使われている単語を含んでいることを意味します。YAMLの場合、”YAML Ain’t Markup Language”のYAMLが、その定義の一部として再び使用されています。
-
YAMLの特徴
YAMLはデータを階層的に表現するのに適しており、インデントを使用してデータの構造を表現します。
YAMLファイルでインデントが揃っていない場合、正しく読み込まれず、エラーになります。そのためYAMLファイルを記述する際には、インデントを正確に行うことが重要です。
-
YAMLファイルの記述例
YAMLファイルの記述例は以下になります。
# これはコメントです person: name: John Doe age: 30 married: true children: - name: Jane Doe age: 10 - name: Doe Junior age: 7
この例では
person
というオブジェクトがどんな情報であるかを表現しています。person
の名前、年齢、婚姻に関する情報(フィールド)や、children
という配列があり、それぞれの子供についての情報が含まれています。コメントアウトは
#
で表現できます。複数行に渡るコメントアウトはできません。
テンプレートファイル
Cloud Formationで環境構築の基となるYAMLファイルはテンプレートファイルと呼びます。ローカルのどこでも良いので、YAMLファイルを作成します。今回ファイル名はnetworking-cf.yaml
として作成します。
以後、項目ごとにテンプレートファイルに記述する内容を記載していきますが、最後に全文載せますのでご安心ください。
記述する際にはインデントに注意する必要があります。YAMLのリンターを設定したVSCodeなどのエディター上で記述するのをおすすめします。
また、設定に関する説明は適宜コメントを挿入しますので参考にしてください。
1-1. フォーマットバージョンの指定
冒頭ではテンプレートのフォーマットバージョンを指定します。テンプレートファイルの説明の有無は任意です。
以後、Resources配下に作りたいリソースやテンプレートファイル内で一意の名前などを設定していきます。
# 2010-09-09: 2023年11月現在の時点で最新のバージョン
AWSTemplateFormatVersion: 2010-09-09
# このテンプレートファイルがどんなものであるかを記述する
Description: template file for cloud formation
# リソースの定義
Resources:
1-2. VPCの作成
VPCを作成します。
# VPCの作成
NetworkingVPC:
Type: AWS::EC2::VPC
Properties:
# CIDRブロックの指定
CidrBlock: 10.0.0.0/16
# DNSサポートの有効化
EnableDnsSupport: true
# DNSホスト名の有効化
EnableDnsHostnames: true
# 一意になるように名前をつける
Tags:
- Key: Name
Value: networking-vpc
1-3. サブネットの作成
定義したVPC内にサブネットを作成します。今までの演習ではパブリックサブネット、プライベートサブネットを3つずつ作成しましたが、今回は各サブネットは1つずつ作成します。
以下に!Ref
、GetAZs
が出てきますが、これらはCloud Formationの組み込み関数です。!Ref
、GetAZs
に関して以下の表にまとめました。
関数 | 説明 | 例 |
---|---|---|
!Ref | テンプレート内で定義されたリソースやパラメータを参照する。 | !Ref MySecurityGroup は、テンプレート内で定義された MySecurityGroup という名前のリソースを参照する。 |
GetAZs | 指定されたリージョンの利用可能なアベイラビリティゾーンのリストを返す。 | !GetAZs '' は、スタックがデプロイされているリージョンの全アベイラビリティゾーンを返す。 |
アベイラビリティーゾーンをハードコーディングするとリンターで弾かれるケースがあるのでGetAZs
関数を使用して定義します。
# パブリックサブネットの作成
NetworkingPublicSubnet:
Type: AWS::EC2::Subnet
Properties:
# VPCのIDを指定
VpcId: !Ref NetworkingVPC
# CIDRブロックの指定
CidrBlock: 10.0.1.0/24
# パブリックサブネットの場合はtrueにし、インターネットゲートウェイをアタッチする
MapPublicIpOnLaunch: true
# ハードコードを避けるために、!GetAZs ""を使用
# 現在のリージョンのAvailability Zoneのリストの最初のAvailability Zoneを選択
AvailabilityZone: !Select [0, !GetAZs ""]
Tags:
- Key: Name
Value: networking-public-subnet
# プライベートサブネットの作成
NetworkingPrivateSubnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref NetworkingVPC
CidrBlock: 10.0.4.0/24
# プライベートサブネットの場合はfalseにし、インターネットゲートウェイをアタッチしない
MapPublicIpOnLaunch: false
AvailabilityZone: !Select [0, !GetAZs ""]
Tags:
- Key: Name
Value: networking-private-subnet
1-4. インターネットゲートウェイ
パブリックサブネットに配置するインスタンスはインターネット接続できる必要があるので、インターネットゲートウェイを作成し、VPCにアタッチします。
# インターネットゲートウェイの作成
NetworkingInternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: networking-igw
# VPCにインターネットゲートウェイをアタッチ
AttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref NetworkingVPC
InternetGatewayId: !Ref NetworkingInternetGateway
1-5. ルートテーブル
パブリックサブネット、プライベートサブネット用のルートテーブルを作成し、作成したルートテーブルとサブネットを関連付け(紐付け)ます。
インスタンスにパブリックIPを自動で割り当てる場合はDeviceIndex
は0
に設定します。DeviceIndex
が0
というのは、インスタンスインスタンスにアタッチされる最初のネットワークインターフェースであることを意味します。
# パブリックルートテーブルの作成
NetworkingPublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref NetworkingVPC
Tags:
- Key: Name
Value: networking-public-route-table
# プライベートルートテーブルの作成
NetworkingPrivateRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref NetworkingVPC
Tags:
- Key: Name
Value: networking-private-route-table
# パブリックルートテーブルをパブリックサブネットに関連付け
NetworkingPublicSubnetRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref NetworkingPublicSubnet
RouteTableId: !Ref NetworkingPublicRouteTable
# プライベートルートテーブルをプライベートサブネットに関連付け
NetworkingPrivateSubnetRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref NetworkingPrivateSubnet
RouteTableId: !Ref NetworkingPrivateRouteTable
1-6. セキュリティグループ
インバウンドルールでは単一ポートを解放するので、ToPort
とFromPort
は同じポートを指定します。
アウトバウンドルールは全てのトラフィックの通信を許可します。
※学習目的のため、全てのトラフィックを受け入れる設定を行ていることをご留意ください。
# セキュリティグループ
# SSHとHTTPのアクセスを許可
NetworkingSG:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Enable SSH and HTTP access
VpcId: !Ref NetworkingVPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
SecurityGroupEgress:
- IpProtocol: tcp
FromPort: 0
ToPort: 65535
CidrIp: 0.0.0.0/0
1-7. インスタンス
インスタンスはUbuntu Server 22.04 LTS
で作成します。
キーペアは事前に作成しておく必要があります。既存のキーペアを使用するか、新たに作成し、そのキーペアの名前を指定します。
# インスタンスの作成
NetworkingEC2Public:
Type: AWS::EC2::Instance
Properties:
ImageId: ami-09a81b370b76de6a2
InstanceType: t2.micro
KeyName: networking-key
NetworkInterfaces:
# パブリックサブネットに関連付け
# パブリックサブネットに関連付ける場合は、AssociatePublicIpAddressをtrueにする(パブリックIPの自動割り当て)
- AssociatePublicIpAddress: true
DeviceIndex: 0
GroupSet:
- !Ref NetworkingSG
SubnetId: !Ref NetworkingPublicSubnet
Tags:
- Key: Name
Value: networking-ec2-public
Cloud Formationで環境構築
ここまで作成したテンプレートファイルを基に環境を構築します。Cloud Formationでは、1つのテンプレートファイルで作成できるリソース全体を1つのユニット(集まり)として管理し、それをスタックと呼びます。
スタックの作成
マネージメントコンソールからCloud Formationのページへいき、スタックの作成を選択します。(新しいスタックの作成(標準))
最低限設定する項目を以下にまとめました。
設定項目 | 選択項目 |
---|---|
テンプレートの準備 | テンプレートの準備 |
テンプレートの指定 | テンプレートファイルのアップロード |
スタック名 | networking-1-stack |
作成された環境の確認
スタックの状態がCREATE_IN_PROGRESS
からCREATE_COMPLETE
になったらスタックの作成が完了しています。各環境が問題なくされたか確認してください。
インスタンスにSSH接続する
作成されたインスタンスにSSH接続します。インスタンスの接続タブからSSH接続するためのコマンドをコピーし、実行します。(
# 接続場所に`networking-key.pem`があることを確認
$ ls
networking-key.pem ...
$ ssh -i "networking-key.pem" ubuntu@ec2-3-112-198-111.ap-northeast-1.compute.amazonaws.com
しばらく待っても接続できません。
トラブルシューティング
インスタンスにSSH接続できない問題がどこにあるのか確認します。考えられる原因としては以下の2点です。
- セキュリティグループでSSH接続を許可していない
- ルーティングの問題
1. セキュリティグループの確認
networking-1-ec2-public
のセキュリティタブから、セキュリティグループの設定を確認します。
SSHでは全てのトラフィックを許可しており、設定に問題はありません。
2. ルーティングの確認
SSHで接続を確立するためには、接続元と接続先の相互でパケットのやり取りができる必要があります。
networking-1-ec2-public
のネットワーキングタブから、サブネットのページへいき、サブネットのルートテーブルを確認します。
上記では、10.0.0.0/16
というルーティングが存在します。これはnetworking-1-vpc内のリソース(インスタンスやデータベースなど)が互いに通信する際のルーティング定義です。
外部のネットワーク(インターネットやSSH)との通信が必要な場合は、インターネットゲートウェイやNATゲートウェイなどの追加のルーティング設定が必要になります。
インターネットゲートウェイにルーティングの追加
テンプレートファイルのパブリックルートテーブルの定義の下に、以下を追加します。
# パブリックルートテーブルに、インターネットゲートウェイをルートとして追加
NetworkingPublicRoute:
Type: AWS::EC2::Route
DependsOn: AttachGateway
Properties:
DestinationCidrBlock: 0.0.0.0/0
RouteTableId: !Ref NetworkingPublicRouteTable
GatewayId: !Ref NetworkingInternetGateway
スタックの更新
テンプレートファイルに変更を加えた場合、スタックを削除して再作成する必要はありません。代わりに更新操作を行います。
作成したスタック(networking-1-stack)を選択し、更新をクリックします。
設定項目 | 選択項目 |
---|---|
テンプレートの準備 | 既存のテンプレートを置き換える |
テンプレートの指定 | テンプレートファイルのアップロード |
ルーティングの確認
追加したルーティングが反映されているか確認し、再度インスタンスにSSH接続します。
-
追加したルーティングの確認
-
インスタンスにSSH接続する
$ ssh -i "networking-key.pem" ubuntu@ec2-3-112-198-111.ap-northeast-1.compute.amazonaws.com ... Welcome to Ubuntu 22.04.3 LTS (GNU/Linux 6.2.0-1012-aws x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/advantage
今度はインスタンスにSSH接続することができました。
テンプレートファイルの全文
今回作成したテンプレートファイルの全文が以下です。
# 2010-09-09: 2023年11月現在の時点で最新のバージョン
AWSTemplateFormatVersion: 2010-09-09
# yamlファイルの説明
Description: template file for cloud formation
# リソースの定義
Resources:
# --------------------
# 1つ目のVPCの設定
# --------------------
# VPCの作成
NetworkingVPC:
Type: AWS::EC2::VPC
Properties:
# CIDRブロックの指定
CidrBlock: 10.0.0.0/16
# DNSサポートの有効化
EnableDnsSupport: true
# DNSホスト名の有効化
EnableDnsHostnames: true
# 一意になるように名前をつける
Tags:
- Key: Name
Value: networking-vpc
# パブリックサブネットの作成
NetworkingPublicSubnet:
Type: AWS::EC2::Subnet
Properties:
# VPCのIDを指定
VpcId: !Ref NetworkingVPC
# CIDRブロックの指定
CidrBlock: 10.0.1.0/24
# パブリックサブネットの場合はtrueにし、インターネットゲートウェイをアタッチする
MapPublicIpOnLaunch: true
# ハードコードを避けるために、!GetAZs ""を使用
# 現在のリージョンのAvailability Zoneのリストの最初のAvailability Zoneを選択
AvailabilityZone: !Select [0, !GetAZs ""]
Tags:
- Key: Name
Value: networking-public-subnet
# プライベートサブネットの作成
NetworkingPrivateSubnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref NetworkingVPC
CidrBlock: 10.0.4.0/24
# プライベートサブネットの場合はfalseにし、インターネットゲートウェイをアタッチしない
MapPublicIpOnLaunch: false
AvailabilityZone: !Select [0, !GetAZs ""]
Tags:
- Key: Name
Value: networking-private-subnet
# インターネットゲートウェイの作成
NetworkingInternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: networking-igw
# VPCにインターネットゲートウェイをアタッチ
AttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref NetworkingVPC
InternetGatewayId: !Ref NetworkingInternetGateway
# パブリックルートテーブルの作成
NetworkingPublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref NetworkingVPC
Tags:
- Key: Name
Value: networking-public-route-table
# パブリックルートテーブルに、インターネットゲートウェイをルートとして追加
NetworkingPublicRoute:
Type: AWS::EC2::Route
DependsOn: AttachGateway
Properties:
DestinationCidrBlock: 0.0.0.0/0
RouteTableId: !Ref NetworkingPublicRouteTable
GatewayId: !Ref NetworkingInternetGateway
# プライベートルートテーブルの作成
NetworkingPrivateRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref NetworkingVPC
Tags:
- Key: Name
Value: networking-private-route-table
# パブリックルートテーブルをパブリックサブネットに関連付け
NetworkingPublicSubnetRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref NetworkingPublicSubnet
RouteTableId: !Ref NetworkingPublicRouteTable
# プライベートルートテーブルをプライベートサブネットに関連付け
NetworkingPrivateSubnetRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref NetworkingPrivateSubnet
RouteTableId: !Ref NetworkingPrivateRouteTable
# セキュリティグループ
# SSHとHTTPのアクセスを許可
NetworkingSG:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Enable SSH and HTTP access
VpcId: !Ref NetworkingVPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
SecurityGroupEgress:
- IpProtocol: tcp
FromPort: 0
ToPort: 65535
CidrIp: 0.0.0.0/0
# インスタンスの作成
NetworkingEC2Public:
Type: AWS::EC2::Instance
Properties:
ImageId: ami-09a81b370b76de6a2
InstanceType: t2.micro
KeyName: networking-key
NetworkInterfaces:
# パブリックサブネットに関連付け
# パブリックサブネットに関連付ける場合は、AssociatePublicIpAddressをtrueにする(パブリックIPの自動割り当て)
- AssociatePublicIpAddress: true
DeviceIndex: 0
GroupSet:
- !Ref NetworkingSG
SubnetId: !Ref NetworkingPublicSubnet
Tags:
- Key: Name
Value: networking-ec2-public
本記事の片付け
Cloud Formationでは、テンプレートを基に作成した全ての環境は、スタックを削除するだけでまとめて削除されます。
Cloud Formationのページから作成したスタック(networking-1-stack
)を選択し、削除を選択し、スタックを削除します。
まとめ
今回はCloud Formationで環境構築の自動化を行いました。
環境構築の自動化は、ファイルを基に作成するので、環境構築の共有が簡単です。また、一度ファイルを定義すれば人的ミスを防ぐことができます。
本シリーズではAWSの環境構築とその過程でのトラブルシューティングの方法や問題の特定までの手順などに触れました。エラーに遭遇し、解決した数だけトラブルシューティングのレベルは上がります。是非手を動かして学習してみましょう。
【番外編】USBも知らなかった私が独学でプログラミングを勉強してGAFAに入社するまでの話
プログラミング塾に半年通えば、一人前になれると思っているあなた。それ、勘違いですよ。「なぜ間違いなの?」「正しい勉強法とは何なの?」ITを学び始める全ての人に知って欲しい。そう思って書きました。是非読んでみてください。
「フリーランスエンジニア」
近年やっと世間に浸透した言葉だ。ひと昔まえ、終身雇用は当たり前で、大企業に就職することは一種のステータスだった。しかし、そんな時代も終わり「優秀な人材は転職する」ことが当たり前の時代となる。フリーランスエンジニアに高価値が付く現在、ネットを見ると「未経験でも年収400万以上」などと書いてある。これに釣られて、多くの人がフリーランスになろうとITの世界に入ってきている。私もその中の1人だ。数年前、USBも知らない状態からITの世界に没入し、そこから約2年間、毎日勉学を行なった。他人の何十倍も努力した。そして、企業研修やIT塾で数多くの受講生の指導経験も得た。そこで私は、伸びるエンジニアとそうでないエンジニアをたくさん見てきた。そして、稼げるエンジニア、稼げないエンジニアを見てきた。
「成功する人とそうでない人の違いは何か?」
私が出した答えは、「量産型エンジニアか否か」である。今のエンジニア市場には、量産型エンジニアが溢れている!!ここでの量産型エンジニアの定義は以下の通りである。
比較的簡単に学習可能なWebフレームワーク(WordPress, Rails)やPython等の知識はあるが、ITの基本概念を理解していないため、単調な作業しかこなすことができないエンジニアのこと。
多くの人がフリーランスエンジニアを目指す時代に中途半端な知識や技術力でこの世界に飛び込むと返って過酷な労働条件で働くことになる。そこで、エンジニアを目指すあなたがどう学習していくべきかを私の経験を交えて書こうと思った。続きはこちらから、、、、
エンベーダー編集部
エンベーダーは、ITスクールRareTECHのインフラ学習教材として誕生しました。 「遊びながらインフラエンジニアへ」をコンセプトに、インフラへの学習ハードルを下げるツールとして運営されています。
関連記事
2020.02.25
完全未経験からエンジニアを目指す爆速勉強法
USBも知らなかった私が独学でプログラミングを勉強してGAFAに入社するまでの話
- キャリア・学習法
- エンジニア
2024.08.01
ECSのデプロイ戦略を比較 ブルー/グリーンとローリングアップデート
デプロイメント戦略は、アプリケーションの更新をスムーズかつ安全に行うための重要な手段です。適切な戦略を選ぶことで、ダウンタイムを最小限に抑え、ユーザーへの影響を軽減できます。本記事では、ECSで利用可能な2つの主要なデプロイメント戦略、ブルー/グリーンデプロイメントとローリングアップデートについて解説します。
- AWS
2024.04.28
CloudWatchにおける監視項目 絶対に押さえておくべきアラームとは?
この記事では、システム運用において必須であろうアラームについて解説していきます。
- AWS
2024.10.29
AWSでアプリケーションの可観測性を高めよう!CloudWatch LogsとX-Rayの活用法
ユーザー体験を向上させ、ビジネスへの影響を最小限に抑えるためには、可観測性の強化が重要です。
- AWS
- インフラエンジニア