EC2にroleを渡せなくてトラブった話

EC2にroleを渡せなくてトラブった話:

javascript SDKで、次のような流れの処理を書こうとしていたのですが、EC2の起動時にRoleが渡せなくて週末の夜が潰れてしまったので、似たようなことをする方向けにメモしておきます。

  • 一時的にRoleを作成
  • EC2インスタンスを起動
  • UserDataで渡したスクリプト内でゴニョゴニョする
  • Roleを削除
コードは次のような感じになります。

PolicyArnには起動するEC2に許可したいポリシーのArnが入っていて、ec2Paramにはインスタンス起動時に必要な他のパラメータが全部入っていると考えてください。

const AssumeRolePolicyDocument = JSON.stringify({ 
  Version: "2012-10-17", 
  Statement: { 
    Effect: "Allow", 
    Principal: { Service: "ec2.amazonaws.com" }, 
    Action: "sts:AssumeRole" 
  } 
}); 
const iam = new AWS.IAM() 
await iam.createRole({ RoleName, AssumeRolePolicyDocument }).promise(); 
await iam.attachRolePolicy({ RoleName, PolicyArn}).promise(); 
const InstanceProfileName = RoleName; 
await iam.createInstanceProfile({ InstanceProfileName }).promise(); 
await iam.addRoleToInstanceProfile({ InstanceProfileName, RoleName }).promise(); 
 
const ec2 = new AWS.EC2(); 
ec2Param.IamInstanceProfile={ Name: InstanceProfileName }; 
await ec2.runInstances(ec2Param).promise(); 
特に問題の無いコードに見えますが、これだとrunInstancesで InvalidParameterValue: Value (****) for parameter iamInstanceProfile.name is invalid. Invalid IAM Instance Profile name と言われて起動しません。

waitForでinstanceProfileExistsを待ってからrunInstancesを呼んでも状況は変わらず、どうしたもんかと悩んでいたんですがAWS forumの古い記事に答えが書いてありました(この方はRuby sdkでやっていたようです)

https://forums.aws.amazon.com/thread.jspa?threadID=107077

Many of the AWS APIs are eventually consistent. While the API call responds right away, it can take a variable amount of time before that resource is ready. In this case, the IAM instance profile is not available for use outside IAM yet.
つまり、IAM側で有効になっててもEC2側からは未だ見えない可能性があるよ!!ってことですね。

このフォーラムでは、ちょっと待ったらOKだったよ!みたいな話になってますが、こっちを使ってrunInstancesに成功するまで頑張ってもらった方が良さそうです。

https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Request.html#retry-event

色々ハードコーディングしていますが、こんな感じのコードで、Instance Profile name絡みでエラーが出たら、3000ミリ秒の間隔を空けて、10回リトライします。

let retryCount = 0; 
const result = await ec2.runInstances(ec2Param) 
  .on("retry", (res)=>{ 
    if (retryCount < 10 && res.error.code === "InvalidParameterValue" && res.error.message.endsWith("Invalid IAM Instance Profile name")) { 
      res.error.retryable = true; 
      res.error.retryDelay = 3000; 
      ++retryCount; 
    } 
  }) 
  .promise(); 
クリエイティブ・コモンズ・ライセンス
この記事は クリエイティブ・コモンズ 表示 4.0 国際 ライセンスの下に提供されています。

コメント

このブログの人気の投稿

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2021-04-30 23:37:32 RSSフィード2021-04-30 23:00 分まとめ(42件)

投稿時間:2023-02-05 02:09:04 RSSフィード2023-02-05 02:00 分まとめ(9件)