【AWS】TerraformでVPC構築からEC2を動作させてみた#3(EC2構築)
もう年が終わりますね。
私は退職前ということもあり、年納めの日は有給をいただきました(納会に参加できるわけがない)
大掃除も飽きてきたので前回の続きをしていきたいと思います
何をやるか
- 先日の記事と同様に下記構成を
Terraform
で構築していきたいと思います。 - 今日はパブリックサブネットとプライベートサブネットにそれぞれ1つずつ立てる
EC2
の構築です。
予備知識
毎度、めちゃくちゃ大雑把ですがメモレベルの予備知識
EC2とは
- 従量課金制で利用することができる仮想ササーバー
- 利用する仮想サーバの単位を
インスタンス
とか言ったりする
- 利用する仮想サーバの単位を
- OSは
AMI(Amazon Machine Image)
から選択して起動するためOSより上のレイヤーを自分で構築していくことになる
インスタンスタイプと世代
- GPU搭載だとかインスタンスの用途別に
インスタンスファミリー
という形で分類されている - さらにインスタンスタイプの中でも何代目とかで別れている
- 利用するインスタンスタイプと世代が決まったら、ハードウェアのリソース(メモリだとかストレージだとか)を指定してインスタンスタイプが決まる
t2.nano t2: 汎用ファミリーと世代(tシリーズの2世代目) nano: インスタンスの容量
AMI
- EC2で利用されるOSのディスクイメージ
- 自分で構築したインスタンスをAMIとして保存することもできる
- Thidr PartyのAMIを売られているため、そちらを利用することも可能。(LastlineのAMI使ってみたいなー)
公式では、下記のように記載されているが要はEC2インスタンスの元となるテンプレートと捉えていいのではないでしょうか
Amazon マシンイメージ(AMI)は、ソフトウェア構成(オペレーティングシステム、アプリケーションサーバー、アプリケーションなど)を記録したテンプレートです。 AMI から、クラウドで仮想サーバーとして実行される AMI のコピーであるインスタンスを起動します。 AMI には次が含まれています。
インスタンスのルートボリュームのテンプレート(オペレーティングシステム、アプリケーションサーバー、アプリケーションなど)
EC2の利用形態(どのような形でお金を払うか)
前述の通り、EC2は利用時間に応じてお金がかかる`従量課金`の仕組みなのですが、通常とは異なる利用形態もあります。
リザーブドインスタンス
- 利用期間が長期利用を前提とした利用形態
- 通常利用よりも割引されて利用することができる
- 期間中にインスタンスファミリー、OSが変更できる
コンパーティブル
と変更ができないスタンダード
がある - もちろん
スタンダード
の方が割引率が高くなる
スポットインスタンス
- AWSさん側では、リソース不足に陥らないために多めに予備分を含めたリソースを蓄えている
- 予備分のリソースが余剰となった際に、インスタンスに値段をつけて入札式で払い出す
- 自分の入札価格が最高入札で有る限り、通常利用よりもコストを抑えてEC2インスタンスが利用できる
EC2が利用するストレージについて
- EC2インスタンスが直接利用するストレージには
EBS
とインスタンスストア
がある - 大雑把な違いしか分かりませんが、 EBSは不揮発性(インスタンスを止めても電源は失われない)に対して、インスタンスストアは揮発性(インスタンスストアを止めると消える)
- インスタンスストアは一時データを保持するためのストレージと捉えればいいかも
EBS(Elastic Block Storage)
- 名前の通り、
ブロック型のストレージ
になります - EC2インスタンスとネットワーク接続されている
仮想ストレージ
的な位置付けになる - ストレージのサイズと性能で料金が変わってくる
インスタンスストア
- 物理ホストに内蔵されたディスクストレージ
- インスタンスを再起動すると物理ホストが切り替わるため、データは消えてしまう
Terraformの実装
設計方針
パブリックサブネットのEC2インスタンスは下記をコード化する
- インスタンス起動時に
httpd
のインストールとサービスの開始を行う KeyPair
は作成済みを使う
プライベートサブネットのインスタンスは下記をコード化する
コードの実装
共通操作
variable
を使って他モジュールとか起動時に受け取る変数を定義vpc_security*
と*_subnet
は他モジュールの出力値から受け取る変数
aws_key_pair
でEC2インスタンスに接続するKey Pairを作成data resource
を使って最新版のAmazon LinuxのAMIを取得
variable "instance_type" {} variable "key_name" {} variable "vpc_security_group_web" {} variable "vpc_security_group_db" {} variable "vpc_security_group_ssh" {} variable "public_subnet" {} variable "private_subnet" {} ########################################### # Resouce (Create Key Pair) # ########################################### locals { public_key_file = "./ec2/${var.key_name}.pub" } resource "aws_key_pair" "instance_ssh_key_pairs" { key_name = "${var.key_name}" public_key = "${file(local.public_key_file)}" } ########################################### # Data Resource(Get most recent AMI image)# ########################################### data "aws_ami" "recent_amazon_linux_2" { most_recent = true owners = ["amazon"] filter { name = "architecture" values = ["x86_64"] } filter { name = "root-device-type" values = ["ebs"] } filter { name = "name" values = ["amzn2-ami-hvm-2.0.????????.?-x86_64-gp2"] } filter { name = "virtualization-type" values = ["hvm"] } filter { name = "block-device-mapping.volume-type" values = ["gp2"] } }
パブリックサブネット側のEC2インスタンス
tfファイル
aws_instance
を使ってEC2インスタンスを作成するami
にはdata resource
から取得したAMIのidを代入するkey_name
は上で作成したキーペアを指定するvpc_security_groups
でセキュリティグループに所属させる- 前回の記事で作成した
web-sg
とssh-sg
に参加
- 前回の記事で作成した
subne_id
で作成済みのサブネットに構築する- EC2でグローバルIPをアサインする
associate_public_ip_addres
があるらしいけどサブネット作成時にグローバルIPアドレスの割り当てはすでに設定ずみのため省略
- EC2でグローバルIPをアサインする
user_data
でインスタンス起動後に実行するコマンドを定義
########################################### # Resource(Create Web Server) # ########################################### resource "aws_instance" "public_subnet_instance" { ami = "${data.aws_ami.recent_amazon_linux_2.image_id}" instance_type = "${var.instance_type}" key_name = "${aws_key_pair.instance_ssh_key_pairs.id}" vpc_security_group_ids = ["${var.vpc_security_group_web}", "${var.vpc_security_group_ssh}"] subnet_id = "${var.public_subnet}" private_ip = "10.0.1.10" tags = { Name = "Test Public Web Server" } user_data = "${file("./ec2/httpd.sh")}" }
httpd.sh
- ただ
httpd
をインストールして起動しているだけのズボラ設定
# !/bin/bash yum install -y httpd systemctl start httpd.service
プライベートサブネット側のEC2インスタンス
tfファイル
- Webサーバと設定内容はほぼ同等
- 所属するセキュリティグループだとかサブネットが異なるぐらい
########################################### # Resource(Create DB Server) # ########################################### resource "aws_instance" "private_subnet_instance" { ami = "${data.aws_ami.recent_amazon_linux_2.image_id}" instance_type = "${var.instance_type}" key_name = "${aws_key_pair.instance_ssh_key_pairs.id}" vpc_security_group_ids = ["${var.vpc_security_group_db}", "${var.vpc_security_group_ssh}"] subnet_id = "${var.private_subnet}" private_ip = "10.0.2.10" tags = { Name = "Test Private DB Server" } user_data = "${file("./ec2/db.sh")}" }
db.sh
- mysqlを起動させるだけ
- 今回は
nmap
を使ってポートが開いているか最後に確認する程度
- 今回は
# !/bin/bash yum -y install -y mariadb-server systemctl start mariadb.servcice
出力値
########################################### # Public Instance # ########################################### output "public_instance_ip_address" { value = "${aws_instance.public_subnet_instance.public_ip}" } output "public_instance_id" { value = "${aws_instance.public_subnet_instance.id}" } ########################################### # Private Instance # ########################################### output "private_instance_id" { value = "${aws_instance.private_subnet_instance.id}" } ########################################### # Key # ########################################### output "key_pair" { value = "${aws_key_pair.instance_ssh_key_pairs.key_name}" }
呼び出し元のtfファイル
module_ec2_instance
で各種変数を代入しているvpc*
と*_subnet
の変数は、他モジュールで作成したリソースの出力値を代入
provider "aws" { region = "${var.region}" profile = "${var.profile}" } module "module_vpc" { source = "./vpc" } module "module_security_group" { source = "./sg" vpc_id = "${module.module_vpc.vpc_id}" } module "module_ec2_instance" { source = "./ec2" instance_type = "t3.micro" key_name = "terraform-test" vpc_security_group_web = "${module.module_security_group.web_sg_id}" vpc_security_group_db = "${module.module_security_group.db_sg_id}" vpc_security_group_ssh = "${module.module_security_group.ssh_sg_id}" public_subnet = "${module.module_vpc.public_subnet_id}" private_subnet = "${module.module_vpc.private_subnet_id}" } output "nat_gateway_ip_address" { value = "${module.module_vpc.nat_gateway_ip}" } output "ec2_public_instance_ip" { value = "${module.module_ec2_instance.public_instance_ip_address}" } output "ec2_public_instance_id" { value = "${module.module_ec2_instance.public_instance_id}" } output "ec2_private_instance_id" { value = "${module.module_ec2_instance.private_instance_id}" } output "ec2_ssh_key_pair_name" { value = "${module.module_ec2_instance.key_pair}" }
実行結果
terraform plan
からterraform apply
を実行し、必要な情報が出力されていることを確認
(省略) Outputs: ec2_private_instance_id = (インスタンスID) ec2_public_instance_id = (インスタンスID) ec2_public_instance_ip = (EC2のパブリックIPアドレス) ec2_ssh_key_pair_name = terraform-test nat_gateway_ip_address = (NAT GatewauのパブリックIPアドレス)
shinoAir% ssh ec2-user@[IPアドレス] -i ~/.ssh/terraform-test The authenticity of host '[IPアドレス]' can't be established. ECDSA key fingerprint is SHA256:***********. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '[IPアドレス]' (ECDSA) to the list of known hosts. __| __|_ ) _| ( / Amazon Linux AMI ___|\___|___| https://aws.amazon.com/amazon-linux-ami/2018.03-release-notes/ 16 package(s) needed for security, out of 32 available Run "sudo yum update" to apply all updates.
- Webサーバが動作できているようです。
waragaishinoAir% curl 52.194.254.19 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> (省略)
shinoAir% ssh ec2-user@[NATゲートウェイ] -i ~/.ssh/terraform-test ssh: connect to host [NATゲートウェイ] port 22: Operation timed out
- ということで、パブリックサブネット側のEC2を踏み台にして接続できるようにセキュリティグループを1つ追加してリトライ
- 先ほどの
ssh-sg
は、パブリックサブネット専用に変更
- 先ほどの
[ec2-user@ip-10-0-1-10 ~]$ ssh -i ~/.ssh/terraform-test ec2-user@10.0.2.10 The authenticity of host '10.0.2.10 (10.0.2.10)' can't be established. ECDSA key fingerprint is SHA256:****************. ECDSA key fingerprint is MD5:*********. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '10.0.2.10' (ECDSA) to the list of known hosts. __| __|_ ) _| ( / Amazon Linux AMI ___|\___|___| https://aws.amazon.com/amazon-linux-ami/2018.03-release-notes/
- プライベートサブネット側の
3306/tcp
が開いているかプライベート側から確認- 文字化けしてるけど、接続はできているっぽいですね
[ec2-user@ip-10-0-1-10 ~]$ nc 10.0.2.10 3306 R 5.5.64-MariaDBueySq^bQ� �P|Bp2C<BxU}9mysql_native_password ^C
諸々確認できたので、今回作成したリソースは`terraform destory`で削除しておわり!!
まとめ
- 今回でとりあえず1シリーズは終了です。
- VPC
- セキュリティグループ
EC2
次は
RDS
とかS3
を使って、シンプルな構成をもう一度作成していきたいと思います
蛇足
今週は4回トレーニングにいけました。ど素人の重さしか挙げれていないです。
火曜日(三頭、二頭)
- トライセプスエクステンション 30KG 10回 3セット
- ディップス 10回 3セット
- プレスダウン 21.5kg 10回 3セット
- ランニング 30分
木曜日(胸)
- ベンチプレス 60kg 10回 3セット
- インクラインベンチプレス 40kg 8回 3セット
- ダンベルインクライン 12kg 10回 3セット
- ケーブルクロスオーバ 16kg 10回 3セット
- ランニング 40分
金曜日(脚、肩)
- スクワット 60kg 10回 3セット
- レッグプレス 90kg 10回 3セット
- レッグカール 35kg 10回 3セット
- レッグエクステンション 60kg 10回 3セット
- ダンベルショルダープレス 14kg 10回 3セット
- サイドレイズ 8kg 10回 3セット
- ランニング 40分
- 坂道ウォーキング 10分
日曜日(予定, 背中)
- デッドリフト 60kg 10回 3セット
- ベントオーバーロウ 35kg 10回 3セット
- ラットプルダウン 42kg 10回 3セット
- 懸垂 6~7回 ?セット
- ランニング 40分