― 「ALBからだけ許可」をコードにする ―
前回は、ALB用のSecurity Groupを作った。
今回はその続き。
今度は、
EC2専用のSecurity Group
を作っていく。
今回のポイントは、前回まで使っていた
cidr_blocks = ["0.0.0.0/0"]
とは違う書き方が登場すること。
それが、
security_groups = [
aws_security_group.alb.id
]
だ。
これが何を意味するのか。
今日はそこを理解していこう。
🔥 今の構成
まず、現在の構成を確認。
Internet
│
▼
ALB
[ALB SG]
│
▼
Listener
│
▼
Target Group
│
▼
EC2
[EC2 SG]
ここで理想の通信を考える。
Internet
│
▼
ALB
│
▼
EC2
インターネットからALBへはアクセスできる。
でもEC2には、
ALBから来た通信だけ通したい。
つまり、
Internet ──→ ALB ──→ EC2
OK
だけを許可して、
Internet ─────────→ EC2
NG
にしたい。
そのためにEC2用Security Groupを作る。
① EC2用Security Groupを作る
まずはこれ。
resource "aws_security_group" "ec2" {
}
これは、
EC2用のSecurity Groupを作る
という意味。
② name
name = "ec2-sg"
Security Groupに、
ec2-sg
という名前を付ける。
③ VPC
ここはALB用Security Groupと同じ。
vpc_id = aws_vpc.main.id
つまり、
«このSecurity Groupは、このVPCに所属させる。»
という指定。
Security GroupはVPCと紐づいている。
④ 今日の新しい書き方
ここが今回のメイン。
今まで、
cidr_blocks = ["0.0.0.0/0"]
を使っていた。
これは、
IPアドレスの範囲を指定して通信を許可する
書き方だった。
例えば、
0.0.0.0/0
↓
すべてのIPv4アドレス
だった。
でも今回は違う。
security_groups = [
aws_security_group.alb.id
]
これを使う。
意味は、
「このSecurity Groupが付いている相手からの通信を許可する」
ということ。
今回なら、
ALB
↓
alb-sg
↓
EC2 SG
↓
EC2
という関係になる。
つまり、
ALBのSecurity Groupを持っている相手からの通信を許可する。
これが今回の重要ポイント。
⑤ ingress
実際のルールはこう。
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
security_groups = [
aws_security_group.alb.id
]
}
これを日本語にすると、
«ALBのSecurity Groupが付いている相手から、TCPの80番ポートへ来る通信を許可する。»
ということ。
つまり、
ALB
│
│ TCP : 80
▼
EC2
を許可している。
⑥ egress
送信側は今回も、
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
としている。
"protocol = "-1"" は、
すべてのプロトコル
という意味。
そのため、これは
EC2から外部への送信を広く許可する
設定になっている。
今回の主役はIngressなので、まずは
「EC2にはALBからの通信だけ入れる」
という部分をしっかり理解しよう。
🎯 今日の問題
Q1
今まで、
cidr_blocks = ["0.0.0.0/0"]
を書いていた。
今回は、
security_groups = [
aws_security_group.alb.id
]
になった。
なぜCIDRではなく、Security Groupを指定するんだと思う?
Q2
もし、2台のALBがあり、
ALB-1
↓
alb-sg
ALB-2
↓
alb-sg
のように両方とも同じ "alb-sg" を付けていたとする。
EC2のSecurity Groupが、
security_groups = [
aws_security_group.alb.id
]
だった場合、EC2は両方のALBから通信を受けられる?
理由も考えてみよう。
Q3【今日一番重要】
ここまでの構成を、自分の言葉で説明してみよう。
Internet
↓
ALB(SG)
↓
Listener
↓
Target Group
↓
EC2(SG)
それぞれ、
- Internet
- ALB
- Security Group
- Listener
- Target Group
- EC2
が何を担当しているのか説明してみよう。
ここまで説明できたら、
かなり実務に近い理解
になってくる。
📝 今回の回答
今回の回答はこちら。
コードの説明
«"resource "aws_security_group" "ec2""
EC2にセキュリティグループを作ります»
«"name = "ec2-sg""
ec2-sgという名前»
«"vpc_id = aws_vpc.main.id"
メインVPCに所属しています»
«"security_groups = [aws_security_group.alb.id]"
ALBセキュリティグループの通信を通します»
«"ingress"
入ってくる»
«"from_port = 80"
80ポートから»
«"to_port = 80"
80ポートへ»
«"protocol = "tcp""
TCPプロトコルで»
«"security_groups = [aws_security_group.alb.id]"
ALBセキュリティグループの通信を受けます»
🔎 今回のレビュー
今回は、かなり良かった。
特に、
«ALBからの通信だけを許可したいからSecurity Groupを指定する»
という考え方ができている。
ただ、今回はTerraformの文法でも少し修正するところがあったので、そこも含めて確認していこう。
💻 コードレビュー
まずここ。
resource "aws_security_group" "ec2" {
}
name = "ec2-sg"
これはTerraformの文法としては違う。
"name"などの属性は、Resourceブロックの "{ }" の中に書く。
正しくは、
resource "aws_security_group" "ec2" {
name = "ec2-sg"
vpc_id = aws_vpc.main.id
}
という形。
Terraformでは、
resource
↓
{
設定
}
というブロック構造になっている。
ここはコードを書くうえで大事なので覚えておこう。
⚠️ もう一つ
今回、
security_groups = [
aws_security_group.alb.id
]
をIngressの外にも書いていた。
これは、
Ingressの中に書く。
今回なら、
resource "aws_security_group" "ec2" {
name = "ec2-sg"
vpc_id = aws_vpc.main.id
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
security_groups = [
aws_security_group.alb.id
]
}
}
という形。
ここはTerraformの「どの設定がどのブロックに属するのか」という構造の問題。
今後コードが大きくなってくると、かなり重要になる。
Q1レビュー
回答:
«EC2セキュリティグループはALBセキュリティグループの通信を通したくて、cidr_blocks = ["0.0.0.0/0"]をわざわざ指定しなくてもいいから。»
方向性はバッチリ。
95点!
もう一歩だけ深くすると、
«IPアドレスではなく、「どのSecurity Groupを持っている相手か」で許可したいから。»
というのが大きな理由。
例えば、
ALB
↓
ALBのIPアドレス
ではなく、
ALB
↓
alb-sg
↓
EC2 SG
という関係で許可する。
Security Groupを参照しておけば、
相手のIPアドレスを直接指定しなくても、そのSecurity Groupを持つリソースからの通信を許可できる。
これが大きなメリット。
Q2レビュー
回答:
«ALBのセキュリティグループの元のcidr_blocks = ["0.0.0.0/0"]が一緒だから両方から通信を受けれる。»
ここは惜しい!
80点。
理由は、
CIDRではない。
今回EC2側で指定しているのは、
security_groups = [
aws_security_group.alb.id
]
だから、
«「alb-sgを持っている相手なら許可する」»
というルール。
つまり、
ALB-1
↓
alb-sg
↓
→ EC2 OK
ALB-2
↓
alb-sg
↓
→ EC2 OK
となる。
ここで大事なのは、
EC2は「ALB-1」という名前を見ているわけではない
ということ。
"alb-sg"というSecurity Groupを持っているかどうかを見ている。
だから、複数のALBが同じSecurity Groupを付けていれば、その両方からの通信が許可される。
Q3レビュー🔥
回答:
«インターネットからの通信をALBが受け、Listenerでどこへ送るかルールを決め、Target GroupでそれぞれのEC2に送ります。また、ALB、EC2それぞれにセキュリティグループを付けることで、ALBセキュリティグループがネットワークからの通信を制御し、EC2セキュリティグループがあることで、EC2の通信をALBにしか通信できないよう制限できます。»
これは……
98点!💯
かなり良い。
特に、
«インターネットからの通信をALBが受ける»
↓
«Listenerでどこへ送るかルールを決める»
↓
«Target GroupでEC2へ送る»
という流れが、自分の言葉で説明できている。
さらに、
«ALB、EC2それぞれにSecurity Groupを付ける»
というところまで理解できている。
これはかなり実務っぽい。
ただし、一箇所だけ修正
ここ。
«EC2の通信をALBにしか通信できないよう制限できます。»
これだと、
EC2から出ていく通信
を制限しているようにも読める。
今回やっているのは、
EC2への受信通信をALBからだけ許可する
こと。
つまり、
ALB
↓
EC2
はOK。
Internet
↓
EC2
はNG。
だから、
«EC2はALBからの通信だけを受け付けるように制限する。»
と書けば完璧。
🌟 今回の成績
項目| 点数
コード理解| 90点
Q1| 95点
Q2| 80点
Q3| 98点
総合| 🌟94点🌟
今回のポイントは、点数以上に、
Security Groupを「IPアドレス」ではなく「相手との関係」で考え始めたこと。
ここがかなり大きい。
🧠 今回の核心
今回のコード、
security_groups = [
aws_security_group.alb.id
]
を見たときに、
「ALBのSecurity Groupを持っている相手からの通信を許可するんだな」
と頭の中で通信が流れればOK。
つまり、
コード → AWSの通信
へ変換できている。
これはTerraformを使ううえでかなり重要な能力。
🚀 そして、ここから少しだけ授業を変える
今回、
«「コードを書くの、ちょっと怖い。震えちゃった」»
という感覚があった。
それでいい。
むしろ、ここからが本番。
今までは、
先生
↓
コードを確認
↓
自分の言葉で説明
という流れが中心だった。
これからは少しずつ、
構成図
↓
「何が必要?」
↓
自分でTerraformを書く
↓
レビュー
↓
修正
という流れを増やしていく。
でも、いきなり全部はやらない。
少しずつ。
💪 「間違えない」より「直せる」
実務で強いエンジニアは、
一発で完璧なコードを書く人
だけではない。
むしろ、
«「あれ?これ違うかも」»
と気づいて、
«「なぜ違うんだろう?」»
と調べて、
«「なるほど、こういう理由か」»
と理解して、
«「じゃあこう直そう」»
と修正できる人が強い。
今回もまさにそれ。
Q2では少しズレた。
でも、
CIDRで判断している
↓
Security Groupで判断している
という違いを理解できた。
これで一つ強くなった。
☁️ 今回のまとめ
今回覚えたのは、
cidr_blocks
↓
IPアドレスの範囲で許可
security_groups
↓
Security Groupを基準に許可
という違い。
そして今回の構成は、
Internet
↓
ALB
[ALB SG]
↓
Listener
↓
Target Group
↓
EC2
[EC2 SG]
Security Groupの役割は、
Internet
↓
ALB SG
「インターネットから80番OK」
↓
EC2 SG
「ALB SGからだけ80番OK」
↓
EC2
という、
「必要な相手だけ通信させる」
という設計を作ること。
🔥 次回から実務モードへ
ここから少しずつ、
「先生がコードを見せる」
から、
「構成図を見て、自分でコードを書く」
へ進んでいく。
怖くて当然。
でも、
VPC
↓
Subnet
↓
Route Table
↓
IGW
↓
NAT Gateway
↓
ALB
↓
Listener
↓
Target Group
↓
EC2
↓
Security Group
ここまで一つずつ積み上げてきた。
もう「何も知らない状態」ではない。
これからは、その知識を使って、
自分でAWSを組み立てる練習
をしていこう。
分からないところは、分かるまで戻ればいい。
間違えたら、なぜ間違えたかを理解すればいい。
怖いままでもいい。コードを書こう。
その一行一行が、ちゃんと実務で使える力になっていく。💪☁️🚀