以前の記事ではTerraformを用いてAzureに料金の割安なSpotインスタンスを構築する方法を掲載しましたが、今回はAWS版です。
ちゃんと覚えていました!
えらい!
今回もインドのムンバイリージョンで作業しています。
本記事は2024年7月6日(日本時間)時点のAWSのムンバイリージョンのEC2の料金に関して言及しています。
Spotインスタンスの基本的な概念をわかりやすくするために具体的な金額を出しておりますが、実際の皆様の課金金額は本記事記載の金額に合致しない場合がありますのでご注意ください。
AWSのSpotインスタンスのコード
コードは簡単ですが、考え方がAzureよりも少し難しいです。
Linux(Amazon Linux 2023)とWindows Server 2022の2台のEC2をSpotインスタンスで構築するコードです。
変数設定
# ---------------------------
# Variables - 変数設定
# ---------------------------
# region
# ap-northeast-1 東京リージョン
# ap-south-1 ムンバイリージョン
variable "region" {
default = "ap-south-1"
}
# 環境種別(本番:prd,ステージング:stg,開発:dev)
variable "env_type" {
default = "dev"
}
# システム名
variable "sys_name" {
default = "test_lb_dns"
}
# availability_zone
variable "availability_zone" {
type = object({
a = string
b = string #ムンバイリージョンで利用
c = string
})
default = {
a = "ap-south-1a" # ムンバイ(インド)のアベイラビリティゾーン
b = "ap-south-1b" # ムンバイ(インド)のアベイラビリティゾーン
c = "ap-south-1c" # ムンバイ(インド)のアベイラビリティゾーン
}
}
# ------------------------------
# Web Server と Application Load Balancer用VPC作成
# ------------------------------
# vpc address
variable "vpc_address_pre" {
default = "10.0."
}
variable "vpc_address_suf" {
default = "0.0/23"
}
# private subnet suffix address01
variable "private_address_suf01" {
default = "1.0/26"
}
# private subnet suffix address02
variable "private_address_suf02" {
default = "1.64/26"
}
# private subnet suffix address03
variable "private_address_suf03" {
default = "1.128/26"
}
# public subnet suffix address01
variable "public_address_suf01" {
default = "0.0/24"
}
# EC2のインスタンスタイプ
variable "ec2_instance_type" {
default = "t2.micro"
}
# VPC Endpoint
variable "vpc_endpoints" {
type = list(any)
default = ["ssm", "ssmmessages", "ec2messages"]
}
IPがどうのこう、SSMがどうのこうの書いてますが無視してください。
このvarriable.tf
で大事なのは最後から2ブロック目のEC2のインスタンスタイプ
とコメントしてある部分で指定しているt2.micro
というインスタンスタイプです。
このインスタンプタイプで以下のec2.tf
でLinuxのEC2を構築しています。
EC2.tf
# ---------------------------
# EC2作成
# ---------------------------
# Amazon Linux 2023 の最新版AMIを取得
data "aws_ssm_parameter" "al2023-ami-kernel-default-x86_64" {
name = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64"
}
# ---------------------------
# 必要台数のEC2を作成
# ---------------------------
# Linux
resource "aws_spot_instance_request" "ec2_app01" { #spot_priceを設定する
spot_price = "0.0047"
ami = data.aws_ssm_parameter.al2023-ami-kernel-default-x86_64.value
instance_type = var.ec2_instance_type
availability_zone = var.availability_zone.a
vpc_security_group_ids = [aws_security_group.sg_ec2_app01.id]
subnet_id = aws_subnet.sn_public_1a.id
associate_public_ip_address = "true"
iam_instance_profile = aws_iam_instance_profile.instance_prof.name
root_block_device {
volume_size = 30 # GB
volume_type = "gp3" # 汎用SSD
encrypted = false
tags = {
Snapshot = "false"
}
}
tags = {
Name = "${var.env_type}-${var.sys_name}-ec2-app01"
}
# NAT Gateway構築後にEC2を構築するパラメーター→Route Table設定後に変更、App01はNAT Gateway構築後でもコケないが、App02と03がコケるため構成変更。(EC2構築前にNAT Gatewayが無いとヒアドキュメント内のdnfコマンドでこける)
depends_on = [
aws_route_table_association.associate_rt_sn_public_1a
]
}
# クライアントPC相当のWindows Serverマシンを構築
# ---------------------------
# Windowsマシン用のKey pair作成
# ---------------------------
variable "key_name" {
default = "kp-ec2-01"
}
variable "key_path" {
default = "適当なディレクトリ"
}
# 秘密鍵のアルゴリズム設定
resource "tls_private_key" "kp-ec2-01" {
algorithm = "RSA"
rsa_bits = 2048
}
# クライアントPCにKey pair(秘密鍵と公開鍵)を作成
# - Windowsの場合はフォルダを"\\"で区切る(エスケープする必要がある)
# - [terraform apply] 実行後はクライアントPCの公開鍵は自動削除される
locals {
public_key_file = "${var.key_path}\\${var.key_name}.id_rsa.pub"
private_key_file = "${var.key_path}\\${var.key_name}.id_rsa"
}
resource "local_file" "kp_ec2_01_pem" {
filename = "${local.private_key_file}"
content = "${tls_private_key.kp-ec2-01.private_key_pem}"
}
# 上記で作成した公開鍵をAWSのKey pairにインポート
resource "aws_key_pair" "kp_ec2_01" {
key_name = "${var.key_name}"
public_key = "${tls_private_key.kp-ec2-01.public_key_openssh}"
}
# ---------------------------
# クライアント相当のEC2を作成
# ---------------------------
#20240523時点のAMI
#Microsoft Windows Server 2022 Base:ami-0f346136f3b372267
#Microsoft Windows Server 2019 Base:ami-01bd28d73d0053a15
#Microsoft Windows Server 2016 Base:ami-063d3d00f8a97a6d1
resource "aws_spot_instance_request" "ec2_client01" { #spot_priceを設定する
spot_price = "0.14"
ami = "ami-0f346136f3b372267" #Microsoft Windows Server 2022 Base
instance_type = "m4.large"
availability_zone = var.availability_zone.a
vpc_security_group_ids = [aws_security_group.sg_ec2_client01.id]
subnet_id = aws_subnet.sn_public_1a.id
associate_public_ip_address = "true"
key_name = "${var.key_name}"
iam_instance_profile = aws_iam_instance_profile.instance_prof.name
root_block_device {
volume_size = 100 # GB
volume_type = "gp3" # 汎用SSD
encrypted = false
tags = {
Snapshot = "false"
}
}
tags = {
Name = "${var.env_type}-${var.sys_name}-ec2-client01"
}
}
以上です。
勿論ほかにもVPC.tfやsecurity_group.tfがありますが、今回は割愛します。
このec2.tf
で2台のEC2を構築しており、上から順にLinux、2台目がWindowsです。
EC2の指定を普通のEC2だとaws_instance
となるところがaws_spot_instance_request
となります。
・・・
・・・そうなんですよ・・・
あくまでrequest
なんですよ・・・
requestって何に対するrequestなの?
はい。
AWSの基盤に対して、
「今このインスタンスタイプで、このリージョンでこの条件でSpotインスタンス使って良いかい?」
というリクエスト(要望)です。
で、ここで言っている条件がaws_spot_instance_request
を使うことによって有効になるオプションで指定します。
有効になるオプションで何を指定するの?
はい。
コードを見てお気づきだと思いますが、わざとわかりやすくaws_spot_instance_request
の直下に記載しています。
spot_price
です。
詳細を説明します。
spot_priceについて
お金の話なので、具体的な数字(金額)を用いて説明した方がわかりやすいので、金額を出します。
まずは1台目のLinuxから標準料金を見てみましょう。
AWS Pricing Calcuratorで算出します。
画像が大きくなっちゃいますが必要な情報を一目でわかるようにするため、このようなサイズになってしまいました。
必要な情報は赤枠で囲っていますが、まとめると以下の通りです。
項目 | 設定値 |
---|---|
リージョン | ムンバイ |
OS | Linux |
インスタンス | t2.micro |
他にも手ナンシーやワークロードという項目もありますが、基本的にはこれらの項目でEC2の1時間当たりの金額が決定します。
画像にある通り、この条件だと1時間当たり0.0124USDかかります。
次にSpotインスタンスの料金です。
Spotインスタンスの価格を5分おきに更新してくれるAWSの公式サイトです。
https://aws.amazon.com/jp/ec2/spot/pricing/
ここでも標準料金と同一スペックである以下の表
項目 | 設定値 |
---|---|
リージョン | ムンバイ |
OS | Linux |
インスタンス | t2.micro |
と同じスペックで見積もると、1時間当たり0.0047USDです。
約38%の料金で利用することが可能です。
これをTerraformのコードで表現すると
resource "aws_spot_instance_request" "ec2_app01" {
spot_price = "0.0047"
になります。
aws_spot_instance_request
でSpotインスタンスの利用Request(要望)を出し、ムンバイリージョンでt2.microを利用した場合1時間当たりのコストを0.0047USDにしてくれ、という金額の指定をspot_price
で行う、という理屈です。
いかがでしょうか?
少しわかりづらいですね。
こちらのオプションはあくまでオプション、必須ではないのですが、これを指定しないと標準料金でEC2を利用することになるため実質指定しないとSpotインスタンスの旨味はありません。
spot_priceをめっちゃ安く指定するとどうなるの?
試してみました。
Requestが蹴られるので、EC2の構築ができません。
Terraform上は特にエラーメッセージも出ませんが、AWSコンソールにログインしてみると安い価格を要望したEC2は影も形も見当たりません。
いかがでしょうか?
金額をしっかりと指定できることは強みですが、毎回時価であるSpotインスタンスの価格を調べて指定するのは少し面倒だなと感じました。
この辺はお金が絡んでいるのでAzureと比較して甲乙つけがたいですが、しっかりと自分で金額管理、いくらの単価でEC2が動作しているのか管理したい場合はAWSのTerraformのコードが向いていると思いますし、とりあえず(いくらかはわからないが標準料金よりは安く)VMを使いたいんだ、簡単に安く使いたいんだ、という方はAzureの金額指定の無い自動選択のコードが向いていると思います。
確認
はい。
すみません。
確認が漏れておりましたね。
どうぞご覧ください。
Linux
Windows
どちらも赤枠内の通りSpotインスタンスで構築されています。
これでAWSでもお財布にやさしくガンガン検証できますね!
本日はここまで。