LoginSignup
2
1

More than 3 years have passed since last update.

なにもしてないのにEC2インスタンスが壊れた

Last updated at Posted at 2020-12-16
1 / 28

この記事について

DMMグループ Advent Calendar 2020 の 17日目の投稿記事となります
https://qiita.com/advent-calendar/2020/dmm

また、発表に向けた記事のため、スライドモードでの回覧を推奨しています。


自己紹介

名前 : 松田 弘樹
入社 : 2015年5月入社の6年目
担当 : バックエンド、インフラ担当
趣味 : 乗馬🐎 全乗協の5級ライセンス取得しました。  


想定読者

  • IaC (Terraformなど)の概要を理解している人
  • CI/CDによる、自動デプロイの概要を理解している人
  • AWSのEC2インスタンスを構築したことがある人

発端

通常の運用で

ある日、Terraformにて構築済みのEC2インスタンスから、作業のために mysqlコマンドで接続をしてみると
mysql: command not found
というエラーコードが返却された


発端

!?

数日前まで、使えていたコマンドが使えなくなっていること示すをエラーが返却された。
histroyを確認してみると、実行したコマンド履歴が一切無い。つまり、EC2インスタンスが初期化されている。

自分「(構築後にインフラので変更していないはずなのに)何もしていないのに壊れた」


発端

というわけで

本記事では私が遭遇した なにもしてないのにEC2インスタンスが壊れた について、ストーリ仕立てでお話をしていきます。

最後にまとめがあるので、忙しい人はそちらへどうぞ


状況整理

まずは事象と影響範囲の確認から

事象

Terraformのtfstateで管理さている、EC2インスタンスが初期化された。

影響範囲

他のTerraform管理のインフラ要素に影響はなし。


環境について

概要をざっくり説明

インフラ構成管理

基本と、Terraformを利用し、インフラ構成をコードで管理している


環境について

Terraformコードを管理するリポジトリは2種類

  • inf: VPC、サブネット、ネットワーク定義など管理。デプロイは手動適用。
  • app: アプリ特有の定義管理。WEBサーバ、RDB定義など。EC2もここで管理。デプロイはCI/CDに組み込まれ自動適用。

環境について

CI/CDフロー

利用しているツール類は次の通り。

  • GithubEnterprise (ソースコードのリポジトリ管理)
  • CircleCI (Docker Build、コンテナ上での単体テスト、Terraformのapply、Docker ImageのPUSH)
  • AWS ECR (Docker Image用リポジトリ)
  • AWS ECS (コンテナの実行環境)

上から順番に連携するフローとなっている


調査

ここからは調査です。
可能性のありそうな仮設をたてながら、検証を繰り返していきました。


調査

仮設1 手動で、メンバーか削除した可能性

一番わかり易いのは、誰かが手動でEC2を作り直したことです。
しかし、メンバーに確認をとってみましたが、該当者がいないため、この説否定されました


調査

仮設2 tfstateの状態が破損し、作り直した可能性

何かの理由でstateファイルが破損したことでEC2インスタンスがterraform管理から外れ、
新しくTerraform管理とするため作り直された可能性を考えました。

tfstateファイルの状態確認のため、手動で Terraform plan を実行しました。
結果、エラーなく正常に動作し、tfstateファイルは正しく機能しているため、この説は否定されました


調査

仮設3 TerraformのEC2の記述が修正されて、EC2が再構築した可能性

EC2インスタンスを管理しているtfファイルの直近の修正履歴を確認しましたが、直近ではtfファイルは修正されていませんでした。
症状発生時には編集されていないため、この説は否定されました


調査

他にどんな原因が考えられるかと仮設をかんがえていたなかで、調査をお願いしていたメンバーから新たな情報をいただく

新く判明した情報

CloudTrail上のイベントにおいて、Terraform実行ユーザが、EC2インスタンス対して Terminateinstance を複数回、実行していることが判明。

image.png
同様に。EC2インスタンスが作成されているイベントも確認。


調査

上記の情報より、原因がTerraformが怪しいとの絞り込みができたので新たな仮設が浮かぶ。

仮設4 Terraformにおいて、意図せずEC2が再構築した可能性

EC2の何かしらのリソースが動的取得しており、その部分が更新されるたびにEC2インスタンスが再構築されるのではないか。


調査

というわけで、EC2関連の記載について細かく見ていきました。

当時のソース

AMI情報をaws_amifilter で絞り込んだあと、aws_instanceに指定する流れとなっています。

# AMI情報を取得
data "aws_ami" "amazon_linux" { 
  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-*"]
  }

  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }

  filter {
    name   = "block-device-mapping.volume-type"
    values = ["gp2"]
  } 
}

# AMIのIDを指定して構築
resource "aws_instance" "rds_access_ec2" {
  ami = data.aws_ami.amazon_linux.id
  instance_type = "t2.micro" 
}

調査

aws_ami のパラメータをひとつづつ確認していると、怪しい記述を発見しました。

怪しい部分

most_recent - (Optional) If more than one result is returned, use the most recent AMI. 
most_recent-(オプション)複数の結果が返される場合は、最新のAMIを使用します。

これだ!!!!!!!!!!!!!!!
原因が特定できました。


原因

CDCDの自動デプロイフローにおいて、EC2のAMIを動的に取得しており、デプロイのたびに最新版のAMIを取得して、更新がある場合はEC2再構築を行うため。

発生時のフロー

  1. GithubEnterpirseに、コードをpushする。
  2. 連携しているCircleCIで、push検知してCI/CDが起動する。
  3. デプロイ処理のなかで、毎回最新のAMIイメージを取得する。
  4. AMIイメージが更新されている場合、古いEC2インスタンスを削除し、新しいAMIイメージでEC2インスタンスを作成する。

このため、直接のEC2の定義部分のtfファイルの修正なくとも、EC2インスタンスが新しいものに差し替わってしまったのです。


対応

原因がわかったので対応をしていきましょう。

案1

EC2インスタンスの再作成を許容する。
EC2インスタンスの更新のたびに、コマンドが消失しないように、aws_instanceuser_dataに必要なインストールコマンドを定義しておく。

resource "aws_instance" "rds_access_ec2" {
  user_data = <<EOF
    #!/bin/bash
    sudo yum install -y mysql-community-client
  EOF
}

欠点は、ローカルにおいたファイルなどが消えてしまうことです。


対応

案2

AMIの値を固定値に変更する。
更新したい場合は、AMIの値を修正する運用とする。

resource "aws_instance" "rds_access_ec2" {
  # 固定値に修正
  ami = "ami-00f045aed21a55240"
}

欠点は、手動運用の手間が増えることとなります。


対応

どちらの案も欠点があるので、要件などと照らし合わせて判断すればいいかなと思います。


まとめ

次の環境の場合は、意図せずにリソースが更新されることがあるので注意しましょう。

  • インフラの構成を、Terraformなどでコード管理している
  • デプロイが、手動ではなく自動でデプロイする
  • リソースを動的に取得している部分がある

Special Thanks

調査に協力してくれた @moroishisan


宣伝

弊社ではエンジニアを積極募集中です!
https://dmm-corp.com/recruit/

個人あてに、カジュアルにお話が聞きたいかたもどうぞ!


引用

Data Source: aws_ami
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami


ご視聴ありがとうございました

2
1
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
2
1