1
0

以前の記事ではTerraformを用いてAzureに料金の割安なSpotインスタンスを構築する方法を掲載しましたが、今回はAWS版です。
ちゃんと覚えていました!
えらい!
今回もインドのムンバイリージョンで作業しています。

本記事は2024年7月6日(日本時間)時点のAWSのムンバイリージョンのEC2の料金に関して言及しています。
Spotインスタンスの基本的な概念をわかりやすくするために具体的な金額を出しておりますが、実際の皆様の課金金額は本記事記載の金額に合致しない場合がありますのでご注意ください。

AWSのSpotインスタンスのコード

コードは簡単ですが、考え方がAzureよりも少し難しいです。
Linux(Amazon Linux 2023)とWindows Server 2022の2台のEC2をSpotインスタンスで構築するコードです。

変数設定

varriable.tf
# ---------------------------
# 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.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で算出します。
image.png
画像が大きくなっちゃいますが必要な情報を一目でわかるようにするため、このようなサイズになってしまいました。
必要な情報は赤枠で囲っていますが、まとめると以下の通りです。

項目 設定値
リージョン ムンバイ
OS Linux
インスタンス t2.micro

他にも手ナンシーやワークロードという項目もありますが、基本的にはこれらの項目でEC2の1時間当たりの金額が決定します。
画像にある通り、この条件だと1時間当たり0.0124USDかかります。

次にSpotインスタンスの料金です。
Spotインスタンスの価格を5分おきに更新してくれるAWSの公式サイトです。
https://aws.amazon.com/jp/ec2/spot/pricing/
image.png
ここでも標準料金と同一スペックである以下の表

項目 設定値
リージョン ムンバイ
OS Linux
インスタンス t2.micro

と同じスペックで見積もると、1時間当たり0.0047USDです。
約38%の料金で利用することが可能です。

これをTerraformのコードで表現すると

ec2(抜粋).tf
 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
image.png
Windows
image.png

どちらも赤枠内の通りSpotインスタンスで構築されています。

これでAWSでもお財布にやさしくガンガン検証できますね!

本日はここまで。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0