起動時に初期化するアプリケーションを起動する

AWSBeginner
オンラインで実践に進む

はじめに

稼働中のインスタンスも、アプリケーションが正しく初期化されて初めて役立ちます。Terraform で準備済みのアプリケーション AMI を読み取り、用意されたネットワーク内に EC2 インスタンスを起動して、User Data を通じてアプリケーションを設定します。

Terraform の変数とリソース参照、パブリックサブネットのルーティング、セキュリティグループ、EC2 起動の基礎を理解していることを前提とします。この新しい環境には、AMI、キーペア、ネットワーク、独立した参照用アプリケーションが用意されています。自分のアプリケーションインスタンスを作成し、削除します。

認定試験との関連

認定資格 試験のタスク 演習内容
Cloud Practitioner (CLF-C02) Task 3.1 Infrastructure as Code で初期化済みの EC2 アプリケーションを構築し、AWS CLI でデプロイ後の状態を確認します。

実験の概要

概念の概要:Terraform が既存の AMI を読み取り、EC2 インスタンスを作成し、アプリケーションの応答を変更する User Data を渡します。

AMI を読み取ってアプリケーションを起動する

このステップでは、準備済みの AMI、ネットワークの入力、User Data を Terraform の EC2 リソースに組み合わせ、初期化されたアプリケーションの応答を検証します。

Terminal と AWS View を開きます。参照用サーバーはすでに稼働しています。アプリケーション用ネットワークは準備できていますが、application-server はまだ存在しません。この実験では、以前の実験の VM やリソースを再利用しません。

作業ディレクトリに移動し、準備済みの入力値を確認します。

cd /home/labex/project/application-launch
cat terraform.tfvars.json

これらの値は、用意された AMI、サブネット、セキュリティグループを識別します。ネットワークは、起動時のパブリック IP 割り当て、インターネットへのルート、アプリケーションポート 8081 での User クライアントの許可をすでに備えています。Terraform はこのコースの環境向けに準備済みで、個人の認証情報は不要です。

独立した AWS クエリで、用意されたアプリケーションイメージを探します。AMI はインスタンス作成時に使うイメージを表します。既存の AMI を読み取っても、新しいイメージは作成されません。

aws ec2 \
  describe-images \
  --filters Name=name,Values=report-server-ubuntu-2204 \
  --query 'Images[].{Image:ImageId,Name:Name,Architecture:Architecture}'

名前は report-server-ubuntu-2204、アーキテクチャは x86_64 で、ID は入力 ami_id と一致します。Terraform のデータソースは既存のオブジェクトを読み取り、リソースはオブジェクトのライフサイクルを管理します。この AMI を data.aws_ami.application で読み取り、aws_instance.application でインスタンスを作成します。

application.tf を作成します。引用符付きの区切り語を使う外側のヒアドキュメントは、シェル展開せずに HCL を書き込みます。HCL 内の ${...} は Terraform 式を展開し、jsonencode はメッセージを有効な JSON に変換します。新しいゲストで User Data が実行されると、内側の引用符付き CONFIG ヒアドキュメントが、その JSON を準備済みアプリケーションの設定に書き込みます。

cat > application.tf <<'HCL'
data "aws_ami" "application" {
  most_recent = true
  filter {
    name   = "image-id"
    values = [var.ami_id]
  }
}

resource "aws_instance" "application" {
  ami                    = data.aws_ami.application.id
  instance_type          = "t3.micro"
  key_name               = "report-key"
  subnet_id              = var.subnet_id
  vpc_security_group_ids = [var.security_group_id]

  user_data_replace_on_change = true
  user_data = <<-SCRIPT
    #!/bin/bash
    set -eu
    cat > /etc/report-app/config.json <<'CONFIG'
    ${jsonencode({ message = var.message })}
    CONFIG
  SCRIPT

  tags = {
    Name = "application-server"
  }
}

output "instance_id" {
  value = aws_instance.application.id
}

output "image_id" {
  value = data.aws_ami.application.id
}
HCL

インスタンスは、コピーしたイメージ ID ではなく AMI データソースを参照します。用意されたサブネットとグループの入力が、インスタンスを準備済みネットワークに接続します。User Data は初回起動時に実行され、アプリケーションを設定します。対話的なログインコマンドではありません。入力 message のデフォルト値は Terraform report application です。user_data_replace_on_change により、後で起動設定を変更すると明示的に置き換えが行われます。このリリース時の動作は、後の実験で扱います。

初期化し、整形して検証します。

terraform init
terraform fmt
terraform validate

init が Incomplete lock file information for providers と表示した場合は、他のプラットフォーム向けのチェックサムについての説明です。この準備済み VM は linux_amd64 を使用します。初期化と検証が成功したら続行してください。

プランを確認します。用意された AMI を読み取り、EC2 インスタンスを 1 つ作成することを提案します。参照用サーバーを置き換えたり、新しい AMI を作成したりしてはいけません。

terraform plan

適用し、確認を求められたら yes を入力します。

terraform apply

作成後のインスタンス ID とイメージ ID を保存して表示します。

INSTANCE_ID=$(terraform output -raw instance_id)
echo "$INSTANCE_ID"
IMAGE_ID=$(terraform output -raw image_id)
echo "$IMAGE_ID"

インスタンスを独立して照会します。稼働状態、イメージ、サブネット、セキュリティグループを、準備済みの入力と照合してください。

aws ec2 \
  describe-instances \
  --instance-ids "$INSTANCE_ID" \
  --query 'Reservations[].Instances[].{ID:InstanceId,State:State.Name,Image:ImageId,Subnet:SubnetId,Groups:SecurityGroups[].GroupId,PublicIP:PublicIpAddress}'

AWS View で application-server、User · 198.51.100.10、Application · 8081 を選択し、Send request をクリックします。Connected · 200 と Terraform report application が表示されるはずです。実際のアプリケーションの応答は、起動設定がワークロードに反映されたことを示します。running だけでは、この結果を確認したことにはなりません。

初期化されたアプリケーションが、準備済みのネットワークを通じて応答しています。

確認画面の例:AWS View に、稼働中のアプリケーションと、初期化後の実際のメッセージが表示されています。リソース ID とアドレスは VM ごとに異なります。

Terraform の対応付けを確認し、収束していることを確かめます。

terraform state list
terraform plan

状態には AMI データソースとインスタンスリソースが含まれ、プランは No changes. と表示します。

インスタンスを削除して用意されたインフラストラクチャを保持する

このステップでは、元のイメージ、準備済みネットワーク、参照用アプリケーションを保持しながら、Terraform が管理するアプリケーションインスタンスだけを削除します。

データソースは、読み取るイメージを所有していません。VPC、サブネット、ルート、セキュリティグループ、キーペアも、この状態の管理対象外として用意されたものです。承認する前に削除範囲を確認します。

terraform plan -destroy

削除対象は管理対象のインスタンス 1 つのはずです。次に削除を実行し、yes を入力します。

terraform destroy

同じインスタンス ID を照会します。状態は terminated になるはずです。リクエストの失敗は、終了の証拠にはなりません。

aws ec2 \
  describe-instances \
  --instance-ids "$INSTANCE_ID" \
  --query 'Reservations[].Instances[].{ID:InstanceId,State:State.Name}'

準備済みのイメージは、元の ID のまま存在していなければなりません。

aws ec2 \
  describe-images \
  --image-ids "$IMAGE_ID" \
  --query 'Images[].{Image:ImageId,Name:Name}'

残っている状態を確認します。

terraform state list

管理対象のアプリケーションリソースは存在しないはずです。AWS View では、終了したインスタンスは、稼働中の対象として選択できなくなります。reference-server、送信元 User、ポート 8081 を選択して、リクエストを送信します。応答は引き続き Connected · 200 と Reference application でなければなりません。

HCL ファイルは確認用に保持してください。設定が残っているため、後で通常のプランを実行すると新しいインスタンスが提案されますが、削除操作が失敗したという意味ではありません。

まとめ

AMI データソースと EC2 リソースを区別し、用意されたネットワークの入力を接続して、User Data でアプリケーションを初期化し、実際の応答を検証しました。変更のないプランを確認し、イメージ、ネットワーク、参照用アプリケーションを保持しながら、管理対象のインスタンスだけを削除しました。