暗号化したEBSルートボリュームを持つインスタンスを、Lambdaを使って自動起動させようとした時にハマった箇所があったのであったのでまとめました。
EBSルートボリュームの暗号化
以下の記事にありますように現在、EBSではインスタンスのルートボリュームの暗号化がサポートされています。
http://aws.typepad.com/aws_japan/2015/12/new-encrypted-ebs-boot-volumes.html
今回はこのルートボリューム暗号化を施したインスタンスの自動起動を行う際にハマった点について書きます。
インスタンスの起動失敗
今回AWS Lambdaを用いてインスタンスの起動自動化を図ろうとしていました。
使用したスクリプトはAMIバックアップを取るLambdaファンクション(python)を元に作成した、以下のインスタンス起動バッチです。
ストップと合わせてGitHubにも置いてあります。
https://github.com/tatsuo48/Hello-world/tree/master/LambdaFunctions
# !/usr/bin/python
# -*- coding: utf-8 -*-
import json
import boto3
import pprint
TAG_KEY_AUTO_START = 'auto-start'
print('Loading function')
pp = pprint.PrettyPrinter(indent=4)
# 関数名 : lambda_handler
def lambda_handler(event, context):
print("Received event: " + json.dumps(event, indent=2))
ec2_client = boto3.client('ec2')
ret = execute_start_instance(ec2_client)
print 'Start instance success(%s).' % (ret)
return 0
raise Exception('Something went wrong')
# 関数名 : execute_start_instance
# 戻り値 : 実行結果
# 引数 : ec2_client
# : ec2_resource
# 機能 : インスタンスを起動する。
def execute_start_instance(ec2_client):
response = ec2_client.describe_instances()
result = None
for ec2_group in response['Reservations']:
for instance_info in ec2_group['Instances']:
ret = is_target(instance_info)
if (ret == False):
continue
instance_id = instance_info.get('InstanceId')
response = ec2_client.start_instances(InstanceIds=[instance_id,])
print response
result = True
return result
# 関数名 : is_target
# 戻り値 : 起動要否
# 引数 : instance_info <dict>
# 機能 : 起動要否を判定する
def is_target(instance_info):
val = get_tag_value(
instance_info,
TAG_KEY_AUTO_START
)
if val is None:
return False
return True
# 関数名 : get_tag_value
# 戻り値 : タグ値(当該キーに合致するものがなければNone)
# 引数 : instance_info <dict>
# : key <str>
# 機能 : インスタンス情報から指定キーのタグ値を取得する
def get_tag_value(instance_info, key):
tags = instance_info.get('Tags')
if tags == None:
return None
for tag in tags:
if not (key == tag['Key']):
continue
tag_value = tag['Value']
if tag_value == "true":
return True
return None
しかし、何度Lambdaファンクションを実行しても、以下のような正しいレスポンスが返っているのにインスタンスは起動しませんでした。。。。
{u'StartingInstances': [{u'InstanceId': 'インスタンスID', u'CurrentState': {u'Code': 0, u'Name': 'pending'}, u'PreviousState': {u'Code': 80, u'Name': 'stopped'}}], 'ResponseMetadata': {'HTTPStatusCode': 200, 'RequestId': 'kkksfh084k-l9hh-8iy6-hshs4-ipsug88w9hwh'}}
原因:実行ロールの権限不足
色々調べましたが原因はとても単純なことでした。
KMS(Key Management Service)の実行許可が抜けていたのです。。
今回、私はデフォルトのキーではなく自分で暗号化キーを作成して使っていました。
その場合、該当の暗号化キーの「キーユーザ」もしくは実行ロールのポリシーにてキーの利用を許可する必要がありました。
暗号化キーの「キーユーザ」に設定する場合は以下のようにGUIで設定できます。
実行ロールのポリシーだったらこんな風に。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1236596007000",
"Effect": "Allow",
"Action": [
"kms:*"
],
"Resource": [
"作成したキーのARN"
]
}
]
}
終わりに
原因は至極当然で当たり前なんですが普段使わない機能だとそこまでたどり着くのにも苦労します。
これからも業務内外問わず触れていない機能に触れるようにしなければなーと思いました。