share facebook facebook twitter menu hatena pocket slack

2016.08.29 MON

AWS EC2 インスタンスの復旧(Auto Recovery)設定の落とし穴

WRITTEN BY 大住 孝之

AWS EC2 インスタンスには、 Status Checked Failed 発生時に自動的に復旧を試みる機能があります。
設定自体は正しく行えているように見えるのに、いざ異常発生時に復旧に失敗するケースに当たりました。

Action failed. Encountered error calling EC2 recover. (401: AWS was not able to validate the provided access credentials)

復旧に失敗した RecoveryAlarm は IAM Role を使用して CloudFormation で作成していましたが、作成(設定)自体は正常に行えていました。
結論としてはドキュメントに記載があるのですが、IAM Role で復旧アラームを作成している場合、復旧アクションは動作しません。

IAM ロール (たとえば、Amazon EC2 インスタンスプロファイル) を使用している場合は、アラームアクションを使用してインスタンスを停止、終了、または再起動することはできません。

尚、復旧(recover)アクションと同様に、 停止(stop)、終了(terminate)、再起動(reboot) を実行するアラームを作成できますが、 復旧(recover)とその他のアクションでは使用される実行権限が異なります。 (アラーム作成時の権限が使用されるのは 復旧(revocer) の場合のみ)

IAM ロールに基づいて、アラームアクションを使用してインスタンスを停止、終了、または再起動する場合は、EC2ActionsAccess ロールしか使用できません。他の IAM ロールはサポートされていません。別の IAM ロールを使用している場合は、インスタンスを停止、終了、または再起動できません。
AWS Security Token Service (AWS STS) を用いて許可された一時的な認証情報を使用している場合は、アラームアクションを用いて Amazon EC2 インスタンスを復旧することはできません。

ドキュメントの内容だけではわかり難かったので、実際に復旧アクションの挙動を確認してみました。

IAM 準備

IAM Role と IAM User での比較を行います。

IAM Role / IAM User

IAM Role と IAM User を準備します。今回はいずれも PowerUserAccess を付与しています。

  • IAM Role

20160816230225

  • IAM User

20160816230226

aws configure

デフォルトで IAM Role を使用し、profile=cfn で IAM User を使用できるよう設定します。

$ aws configure list
      Name                    Value             Type    Location
      ----                    -----             ----    --------
   profile                             None    None
access_key     ****************EFEA         iam-role
secret_key     ****************dE0o         iam-role
    region           ap-northeast-1      config-file    ~/.aws/config
$ cat ~/.aws/credentials
[default]
region = ap-northeast-1

[cfn]
aws_access_key_id = ****************VO2A
aws_secret_access_key = ************************************QPgI
region = ap-northeast-1

Cloud Formation テンプレート準備

EC2 + RecoveryAlarm のテンプレートを用意します。

  • ec2.json
{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Outputs": {
    "InstanceID" : {
      "Value" : { "Ref" : "Ec2Instance" }
    },
    "RecoveryAlarm" : {
      "Value" : { "Ref" : "RecoveryAlarm" }
    }
  },
  "Resources": {
    "Ec2Instance" : {
      "Type" : "AWS::EC2::Instance",
      "Properties" : {
        "ImageId" : "ami-374db956",
        "InstanceType" : "t2.micro",
        "BlockDeviceMappings" : [
          {
            "DeviceName": "/dev/xvda",
            "Ebs": {
              "VolumeType": "gp2",
              "VolumeSize": "8"
            }
          }
        ]
      }
    },
    "RecoveryAlarm": {
      "Type": "AWS::CloudWatch::Alarm",
      "Properties": {
        "Namespace": "AWS/EC2" ,
        "MetricName": "StatusCheckFailed",
        "Statistic": "Minimum",
        "Period": "60",
        "EvaluationPeriods": "5",
        "ComparisonOperator": "GreaterThanThreshold",
        "Threshold": "0",
        "AlarmActions": [ {"Fn::Join" : ["", ["arn:aws:automate:", { "Ref" : "AWS::Region" }, ":ec2:recover" ]]} ],
        "Dimensions": [{"Name": "InstanceId","Value": {"Ref": "Ec2Instance"}}]
      }
    }
  }
}

RecoveryAlarm の作成

IAM Role と IAM User それぞれで CreateStack を実行します。

# IAM Role
aws cloudformation create-stack \
  --stack-name ec2-recoveryalarm-role \
  --template-body file://ec2.json
# IAM User
aws cloudformation create-stack \
  --stack-name ec2-recoveryalarm-user \
  --template-body file://ec2.json \
  --profile cfn
  • IAM Role で作成したStack

20160816230228

  • IAM User で作成したStack

20160816230227

  • 作成したEC2インスタンス(Alarm付)

20160816230229

  • 作成したRecoveryAlarm

20160816230230

RecoveryAlarm の実行確認

作成した RecoveryAlarm の状態を ALARM に更新し、挙動を確認します。 (システムステータスチェックのエラーを意図的に起こすことはできません。

IAM Role で作成した RecoveryAlarm

$ aws cloudwatch set-alarm-state \
  --alarm-name "ec2-recoveryalarm-role-RecoveryAlarm-1SXN4O9QLTKH" \
  --state-value ALARM \
  --state-reason "Manual Update to ALARM"

401 エラーが発生し、Action が失敗します。

20160816230231

IAM User で作成したRecoveryAlarm

$ aws cloudwatch set-alarm-state \
  --alarm-name "ec2-recoveryalarm-user-RecoveryAlarm-1HG4YDX2YZ90H" \
  --state-value ALARM \
  --state-reason "Manual Update to ALARM"

IAM User で作成した場合は問題無く、 Action が正常に終了します。

20160816230232

RecoveryAlarm を再作成

IAM Role で作成し、401エラーとなった RecoveryAlarm を IAM User からの実行で作成し直します。

$ diff ec2.json ec2_update.json
30a31
>         "AlarmName": "ec2-recoveryalarm-role-RecoveryAlarm-renew",
$ aws cloudformation update-stack --stack-name ec2-recoveryalarm-role --template-body file://ec2_update.json --profile cfn
  • RecoveryAlarm の再作成(Delete/Update)
    20160816230233

IAM User で “再作成” した RecoveryAlarm

作成し直した RecoveryAlarm の実行確認をします。

$ aws cloudwatch set-alarm-state \
  --alarm-name "ec2-recoveryalarm-role-RecoveryAlarm-renew" \
  --state-value ALARM \
  --state-reason "Manual Update to ALARM"

IAM User で再作成した場合も、Action が正常に終了しました。
20160816230234

マネジメントコンソール上と、 describe-alarms で RecoveryAlarm を確認してみましたが、どの権限(IAM)で作成されたかの情報は保持していませんでした。
RecoveryAlarm を作成した際は実行確認を行い、権限エラーが発生しない事を確認しておいた方が良さそうです。

元記事はこちら

AWS EC2 インスタンスの復旧(Auto Recovery)設定の落とし穴

大住 孝之

構築運用担当。 個性的な面々の中で無個性という個性を打ち出していこうと画策中。

cloudpack

cloudpackは、Amazon EC2やAmazon S3をはじめとするAWSの各種プロダクトを利用する際の、導入・設計から運用保守を含んだフルマネージドのサービスを提供し、バックアップや24時間365日の監視/障害対応、技術的な問い合わせに対するサポートなどを行っております。
AWS上のインフラ構築およびAWSを活用したシステム開発など、案件のご相談はcloudpack.jpよりご連絡ください。