katekichiのゆるブログ

普段の作業メモや日常の出来事とか

zappaが想定しないAWSアカウントにデプロイされて焦った話し

世間は、最近サーバレスが盛んで業務でlambdaを使用するメンバも増えてきましたが自分は なかなか使う機会がなかったのですが、PyConJPで弊社ブースを出すに当たってなにか展示物を作る 必要があったので、ZappaGitHub - Miserlou/Zappa: Serverless Python Web Services)を使ってみようと思いました。

Zappaとは

Python/flaskベースのAWSの Serverless frameworkでAPI Gateway + lambda + S3を使用するようです。

テストアプリを作ってみた

zappa で hello world するまで - Qiitaを参考にさせてもらいながら もりもり作成して、デプロイしたわけです。

こんな感じで設定ファイルを書いて

{
    "dev": {
        "app_function": "test.app",
        "aws_region": "ap-northeast-1",
        "profile_name": "default",
        "s3_bucket": "zappa-xyzxyzxyzxyz"
    }
}

そしてデプロイしたわけです。

$ zappa deploy dev
Calling deploy for stage dev..
Creating demo-zappa-dev-ZappaLambdaExecutionRole IAM Role..
Creating zappa-permissions policy on demo-zappa-dev-ZappaLambdaExecutionRole IAM Role.
Warning! Your project and virtualenv have the same name! You may want to re-create your venv with a new name, or explicitly define a 'project_name', as this may cause errors.
Downloading and installing dependencies..
Packaging project as zip..
Uploading demo-zappa-dev-1498726098.zip (7.6MiB)..
100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 7.94M/7.94M [00:01<00:00, 4.31MB/s]
Scheduling..
Scheduled demo-zappa-dev-zappa-keep-warm-handler.keep_warm_callback with expression rate(4 minutes)!
Uploading demo-zappa-dev-template-1498726129.json (1.6KiB)..
100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1.64K/1.64K [00:00<00:00, 5.09KB/s]
Waiting for stack demo-zappa-dev to create (this can take a bit)..
100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 4/4 [00:15<00:00,  5.71s/res]
Deploying API Gateway..
Deployment complete!: https://xxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev

すげーデプロイできた!!。そして、実行。

$ curl -l https://xxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev
hello from Flask!

おお、楽すぎるーと感動しつつ・・。さて、マネージメントコンソールでどんな感じなのかなと 見てみました・・・。

何故か、該当するFunctionが見当たらない・・。

profileを確認してみる。

zappa_settings.jsonでは、defaultをしていました。

$ cat ~/.aws/config

[default]
region = ap-northeast-1

[profile xxxxxx]
output = json
region = ap-northeast-1

[profile yyyyyy]
region = ap-northeast-1
output = json

# @@@@は伏せ字
$ cat ~/.aws/credentials 

[xxxxxx]
aws_access_key_id = @@@@
aws_secret_access_key = @@@@
[yyyyyy]
aws_access_key_id = @@@@
aws_secret_access_key = @@@@

???。defaultaccess_keysecret_access_key が定義されていないのに、なぜかデプロイされちゃってます・・・。

調査する。

aws cliを駆使して調査しました。

$ aws lambda list-functions
{
    "Functions": [
        {
            "FunctionName": "demo-zappa-dev",
            "FunctionArn": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXX:function:demo-zappa-dev",
            "Runtime": "python3.6",
            "Role": "arn:aws:iam::[デプロイ先のAWSアカウント]:role/demo-zappa-dev-ZappaLambdaExecutionRole",
            "Handler": "handler.lambda_handler",
            "CodeSize": 7939825,
            "Description": "Zappa Deployment",
            "Timeout": 30,
            "MemorySize": 512,
            "LastModified": "2017-06-29T09:17:27.435+0000",
            "CodeSha256": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
            "Version": "$LATEST"
        }
    ]
}

デプロイされたlambda functionのAWSアカウントが分かりました。 しかし、いまいち覚えがないアカウント・・・。

$ aws sts get-caller-identity
{
    "UserId": [デプロイ先のAWSアカウント],
    "Account": [デプロイ先のAWSアカウント],
    "Arn": "arn:aws:iam::[デプロイ先のAWSアカウント]:root"
}

うーん、これも同じ。~/.aws/configは使用していない模様。

$ aws configure list
      Name                    Value             Type    Location
      ----                    -----             ----    --------
     profile                <not set>             None    None
     access_key     ****************XXXX     boto-config    
     secret_key     ****************4YT1     boto-config    
      region           ap-northeast-1      config-file    ~/.aws/config

configの一覧が確認できるようなので、試すとboto-config というキーワードがあります。それで思い出しました。以前、botoを使用するために /etc/boto.cfgを作成したことを・・

試しにboto.cfgを削除して、デプロイすると見事にエラーとなりました。

$ zappa deploy dev
Calling deploy for stage dev..
Oh no! An error occurred! :(

==============

Traceback (most recent call last):
 ・・・
==============

Need help? Found a bug? Let us know! :D
File bug reports on GitHub here: https://github.com/Miserlou/Zappa
And join our Slack channel here: https://slack.zappa.io
Love!,
 ~ Team Zappa!

まとめ

とりあえず、原因は分かりましたが、zappaのデプロイ時にzappa_settings.json に該当するprofileが無かった場合はせめてエラーメッセージ出力してデプロイしないで欲しいなあとも思ったのですが botoの挙動なのかもしれないので、ドキュメントを確認しました。

これ見る限り、 botoの仕様ぽいですね。良い勉強になりました。

The mechanism in which boto3 looks for credentials is to search through a list of possible locations and stop as soon as it finds credentials. The order in which Boto3 searches for credentials is:

Passing credentials as parameters in the boto.client() method
Passing credentials as parameters when creating a Session object
Environment variables
Shared credential file (~/.aws/credentials)
AWS config file (~/.aws/config)
Assume Role provider
Boto2 config file (/etc/boto.cfg and ~/.boto)
Instance metadata service on an Amazon EC2 instance that has an IAM role configured.

Amazon Web Services クラウドネイティブ・アプリケーション開発技法 一番大切な知識と技術が身につく

Amazon Web Services クラウドネイティブ・アプリケーション開発技法 一番大切な知識と技術が身につく