【小ネタ】TerraformでSSMセッションマネージャー接続エラー、原因はAMI選択ミス
歴史シミュレーションゲーム好きのくろすけです!
検証環境として Terraform で VPC 内に EC2 を立て、SSM セッションマネージャーで接続しようとしたところ、接続できない事象に遭遇しました。
結論として、AMI の取得方法(data "aws_ami" のフィルタ指定)が原因でした。
数日前はこのテンプレートで問題なく、EC2への接続ができていたため何か変更したかな?という違和感がありました。
ただ大抵はネットワークが原因であることが多かったため、今回もネットワークだろうという思い込みで解決まで時間をかけてしまいました。
失敗談として残しておこうと思います。
構成
今回作成した検証環境の構成は下記になります。

再現
解決までの一連の流れを再現していきます。
1. Terraform テンプレート
下記がエラー発生時の Terraform テンプレートです。
VPC においてカスタムモジュールを使用していますが、本題から逸れますので解説は割愛します。
main.tf
################################################################################
# Data Sources #
################################################################################
data "aws_caller_identity" "current" {}
data "aws_region" "current" {}
################################################################################
# VPC #
################################################################################
module "vpc" {
source = "../../modules/vpc"
name = "${var.project_name}-${var.env}-vpc"
cidr_block = var.vpc_cidr_block
igw_name = "${var.project_name}-${var.env}-igw"
subnets = {
"public_a" = {
name = "${var.project_name}-${var.env}-subnet-publ-a"
cidr_block = var.public_subnets.a.cidr_block
availability_zone = "ap-northeast-1a"
route_tables = ["public"]
network_acl = "public"
},
"protected_a" = {
name = "${var.project_name}-${var.env}-subnet-prot-a"
cidr_block = var.protected_subnets.a.cidr_block
availability_zone = "ap-northeast-1a"
route_tables = ["protected_a"]
network_acl = "protected"
}
}
route_tables = {
"public" = {
name = "${var.project_name}-${var.env}-rtb-publ",
use_internet_gateway = true,
},
"protected_a" = {
name = "${var.project_name}-${var.env}-rtb-prot-a",
nat_gateway = "ngw_a"
}
}
nat_gateways = {
"ngw_a" = {
name = "${var.project_name}-${var.env}-ngw-a"
subnet_id = "public_a"
}
}
network_acls = {
"public" = {
name = "${var.project_name}-${var.env}-nacl-publ"
ingress = [
{
rule_no = 100
protocol = "-1"
action = "allow"
cidr_block = "0.0.0.0/0"
from_port = 0
to_port = 0
}
]
egress = [
{
rule_no = 100
protocol = "-1"
action = "allow"
cidr_block = "0.0.0.0/0"
from_port = 0
to_port = 0
}
]
},
"protected" = {
name = "${var.project_name}-${var.env}-nacl-prot"
ingress = [
{
rule_no = 100
protocol = "-1"
action = "allow"
cidr_block = "0.0.0.0/0"
from_port = 0
to_port = 0
}
]
egress = [
{
rule_no = 100
protocol = "-1"
action = "allow"
cidr_block = "0.0.0.0/0"
from_port = 0
to_port = 0
}
]
}
}
security_groups = {
"sg_ec2" = {
name = "${var.project_name}-${var.env}-sg-ec2"
description = "Security group for EC2"
egress = [
{
description = "All outbound traffic"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
]
}
}
}
################################################################################
# EC2 #
################################################################################
data "aws_ami" "amazon_linux_2023" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-*-x86_64"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}
# EC2用のIAMロール(モジュール使用)
module "ec2_iam_role" {
source = "terraform-aws-modules/iam/aws//modules/iam-role"
version = "~> 6.4"
name = "${var.project_name}-${var.env}-role-ec2"
use_name_prefix = false
create_instance_profile = true
# Trust policy(EC2が引き受けるロール)
trust_policy_permissions = {
EC2AssumeRole = {
actions = ["sts:AssumeRole"]
principals = [
{
type = "Service"
identifiers = ["ec2.amazonaws.com"]
}
]
}
}
# マネージドポリシー(SSM接続用)
policies = {
AmazonSSMManagedInstanceCore = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}
tags = {
Name = "${var.project_name}-${var.env}-role-ec2"
}
}
# EC2インスタンス
module "ec2" {
source = "terraform-aws-modules/ec2-instance/aws"
version = "~> 6.2"
name = "${var.project_name}-${var.env}-ec2"
ami = data.aws_ami.amazon_linux_2023.id
instance_type = "t3.micro"
subnet_id = module.vpc.subnets["protected_a"].id
vpc_security_group_ids = [module.vpc.security_groups["sg_ec2"].id]
create_security_group = false
iam_instance_profile = module.ec2_iam_role.instance_profile_name
# EBSボリューム設定
root_block_device = {
volume_type = "gp3"
volume_size = 8
encrypted = true
}
tags = {
Name = "${var.project_name}-${var.env}-ec2"
}
}
2. SSMエージェントのステータスエラー確認
構築が完了し EC2 にログインしようとしたところ...

SSM エージェントのステータスエラーが表示されました。
それぞれのステータスは下記のエンドポイントと疎通できているかを表しています。
Ping statusssm.<region>.amazonaws.comec2messages.<region>.amazonaws.com
Session Manager connection statusssmmessages.<region>.amazonaws.com
そのため、この時点ではネットワーク的な問題か、SSMエージェントの問題か双方の可能性を考慮するべきでした。
3. 原因特定
ネットワークの問題だと思っていましたが、数日前はこのテンプレートで問題がなかったことを思い出し同一VPC内で手動でEC2を起動してみました。
すると、ステータスエラーもなく接続成功しました。
ここで EC2 の問題だと気付きます。
そこで改めて接続できない EC2 の詳細を確認したところ、AMIが al2023-ami-minimal-2023.10.20260216.1-kernel-6.1-x86_64 であることに気付きました。
このイメージを使用したことがなかったため知りませんでしたが、SSMエージェントが事前インストールされていないことが原因でした。
根本的には下記の Terraform テンプレートのAMI取得時のフィルターの問題です。
...
data "aws_ami" "amazon_linux_2023" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-*-x86_64"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}
...
余談ですが実際にコンソールで検索してみると、こんな感じにヒットしました。

4. 解決
ということで、SSM のパブリックパラメータから最新イメージを取得する方法に変更して、問題なく接続できるようになりました!
...
data "aws_ssm_parameter" "amazon_linux_2023_ami" {
name = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64"
}
...
あとがき
自分の場合、これまでネットワークの設定に不備がある場合が多く、今回もネットワークだろうと決めつけていたために原因の特定に時間をかけてしまいました...
もし同様の事象に遭遇した方の参考になれば幸いです。
以上、くろすけでした!








