3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ひとりでkubernetesを中心にAdvent Calendar 2021

Day 15

コンテナ環境でのIMDSv2使用上の注意

Posted at

ec2のインスタンスメタデータを取得するのに使用する仕組みですが

2年くらい前にv2が出ていて、セキュリティが強化されたらしいです(以下IMDSv2)
このへんの具体的な話は記事もたくさんあるので今回は特に触れませんが、これが引き起こすちょっとした問題について書きます

問題が起きる環境

ec2に起動したコンテナで起きます
現代社会においてはかなり当てはまるかと思います

起きる問題

metadata取得に失敗します

上記のドキュメントにある通り、IMDSv2はまずtokenを取得して、そのtokenを使用してmetadataを取得します
ec2の設定がデフォルトの場合、そのtoken取得に失敗します

どういうことなのか

IMDSv2のPUTリクエストにはホップ制限がかけられており、デフォルトでこの値は1になっています
そこでこちらのドキュメントに注意事項として書いてありますが

コンテナ環境では、ホップ制限が 1 の場合、コンテナへの到達は余分なネットワークホップと見なされるため、IMDSv2 応答は返されません。

ということです

回避方法

これまた書いてある通り、ec2インスタンスのホップ制限を2にします

方法としては

awsコマンドで modify-instande-metaata-options を使用して変更する
https://docs.aws.amazon.com/cli/latest/reference/ec2/modify-instance-metadata-options.html

起動テンプレートのAdvanced detailsで指定する
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-launch-templates.html

などがあります

一応確認してみる

kubernetes環境で試しました

適当にcurlができるpodを作成します(今回はnetshoot https://github.com/nicolaka/netshoot を使用)

podが作られたnodeのインスタンスidを取得して、metadata-optionsを確認

$ aws ec2 modify-instance-metadata-options --instance-id i-xxxxxxxxxxxxxxxxx
{
    "InstanceId": "i-xxxxxxxxxxxxxxxxx",
    "InstanceMetadataOptions": {
        "State": "pending",
        "HttpTokens": "optional",
        "HttpPutResponseHopLimit": 1,
        "HttpEndpoint": "enabled",
        "HttpProtocolIpv6": "disabled"
    }
}

"HttpPutResponseHopLimit": 1 が確認できましたので、netshootのコンテナにログインし、curlでtokenを取得してみます

bash-5.1# curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"
curl: (56) Recv failure: Connection reset by peer

エラーになりました(エラーになるまで2分くらい待ちました)
HttpPutResponseHopLimitを2にします

$ aws ec2 modify-instance-metadata-options --instance-id i-xxxxxxxxxxxxxxxxx --http-put-response-hop-limit 2
{
    "InstanceId": "i-xxxxxxxxxxxxxxxxx",
    "InstanceMetadataOptions": {
        "State": "pending",
        "HttpTokens": "optional",
        "HttpPutResponseHopLimit": 2,
        "HttpEndpoint": "enabled",
        "HttpProtocolIpv6": "disabled"
    }
}

再びnetshootのコンテナからtoken取得を試みます

bash-5.1# curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"
AQXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX==

tokenが取得できました

確かにec2デフォルトのコンテナ環境ではIMDSv2でのtoken取得で問題があり、ホップ制限を変更することで回避できました

隠れた影響

aws-sdkはデフォルトでIMDSv2を使用していますので、IMDSv2は使ってないよ、という場合も影響を受けている場合があります
aws-sdkの場合は、最初IMDSv2で試して、失敗するとIMDSv1で取得するという流れになっているということなので、遅延が起きます

https://github.com/aws/aws-sdk-go/issues/2972
例えばaws-sdk-goの場合は大々的に遅れるようなのでこの問題には気付きやすいでしょう

https://github.com/aws/aws-sdk-php/issues/1908
aws-sdk-phpの場合は1秒とのことで、気付かないうちにパフォーマンスが悪化している、なんてことがあるかもしれません

3
0
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
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?