LoginSignup
3
4

More than 5 years have passed since last update.

AnsibleでAWS操作 Lambda編

Posted at

AnsibleでAWS操作シリーズ

  1. aws-cliインストール編
  2. EC2インスタンス編
  3. S3バケット編
  4. CloudFrontディストリビューション編
  5. Simple Email Service編
  6. Certificate Manager編
  7. Lambda編

関連記事

aws-cli コマンド一覧(随時追記)

やりたかったこと

  • Lambda関数の登録
  • S3バケットにオブジェクトがPutされたタイミングでCloudFrontにInvalidationをかけ、全てのキャッシュをリセット
  • GUIを使わずに黒い画面でコマンドを「ッターーン!」してかっこつけたい

やったこと

前提

  • CIサーバー(ansible実行サーバー)構築済み
  • CLIサーバー(aws-cli実行サーバー)構築済み
  • Ansibleインストール済み
  • aws-cliインストール済み
  • 各サーバーへのSSH接続設定済み
  • CFS3の設定済み
  • Lambda実行用のiam作成済み

${~}は各環境に合わせて値を設定してください。

作業フロー

1. 関数をLambdaにアップロード

command
ansible-playbook -i inventory/production upload-aws-lambda-function.yml

戻り値のarnをAWS.LAMBDA.ARNに指定する

2. lambda関数への実行権限の不要

command
ansible-playbook -i inventory/production update-aws-lambda-function.yml

3. S3バケットへのイベント設定

command
ansible-playbook -i inventory/production update-aws-s3-event.yml

ディレクトリ構成


├── ansible.cfg
├── templates
│   └── production
│       ├── lambda
│       │   └── lambda_function.j2
│       └── s3api
│           └── event.j2
├── inventory
│   └── production
│       └── inventory
├── roles
│   ├── update-aws-lambda-function
│   │   └── tasks
│   │       └── main.yml
│   ├── upload-aws-lambda-function
│   │   └── tasks
│   │       └── main.yml
│   └── update-aws-s3api-event
│       └── tasks
│           └── main.yml
├── update-aws-lambda-function.yml
├── upload-aws-lambda-function.yml
├── update-aws-s3api-event.yml
└── vars
    └── all.yml

Ansible構成ファイル

inventory

inventory/production/inventory
[ciservers]
${CIサーバーホスト}

[cliservers]
${CLIサーバーホスト}

[all:vars]
ENV=production

vars

vars/all.yml
AWS:
  CLOUD_FRONT:
    DISTRIBUTION:
      ID: ${ディストリビューションID}
  IAM:
    LAMDA:
      ROLE:
        ARN: ${ラムだ関数実行ロールARN}
  LAMBDA:
    ARN: ${lambda関数のarn}
    CLOUD_FRONT:
      INVALIDATION:
        NAME: ${Lambda関数名}
        STATEMENT: ${ステートメント名}
        SOURCE_ARN: ${ソースARN}
  S3:
    BUCKET:
      NAME: ${対象バケット名}
  S3API:
    LAMBDA_FUNCTION:
      ID: ${一意となるID}
TEMP:
  DIRECTORY: /temp

templates

production/lambda/lambda_function.j2
from __future__ import print_function
import boto3
import time
def lambda_handler(event, context):
    client = boto3.client('cloudfront')
    invalidation = client.create_invalidation(DistributionId='{{ AWS.CLOUD_FRONT.DISTRIBUTIO.IDN }}',
    InvalidationBatch={
        'Paths': {
            'Quantity': 1,
            'Items': ['/*']
        },
        'CallerReference': str(time.time())
    })
    for items in event["Records"]:
        path = "/" + items["s3"]["object"]["key"]
        print(path)

内容としては、 対象のバケットに一つでもオブジェクトがPutされたら全てのキャッシュを削除 します。

※最初は、PutされたオブジェクトだけInvalidationをかけていましたが、 静的ホスティング として利用していて、かつ デフォルトインデックスドキュメント を指定 していた場合に、 「/」にアクセスした際の **リダイレクトキャッシュ がInvaidationされずに古いキャッシュが残ってしまっていました。

原因としては、CloudFrontのキャッシュの仕様上、 ブラウザのURL単位 でキャッシュをしているようです。

なので、PutされたオブジェクトのみInvalidationをしてもリダイレクトキャッシュは残ってしまっていたようです。

やり方はあると思いますが、そこは調べる時間が取れなかったので一旦 リダイレクトキャッシュ含む全てのオブジェクト に対してInvalidationをかけています。

production/s3api/event.j2
{
    "LambdaFunctionConfigurations": [
        {
            "LambdaFunctionArn": "{{ AWS.LAMBDA.ARN }}",
            "Id": "{{ AWS.S3API.LAMBDA_FUNCTION.ID }}",
            "Events": [
                "s3:ObjectCreated:*"
            ]
        }
    ]
}

playbook

upload-aws-lambda-function.yml
- hosts: cliservers
  roles:
    - upload-aws-lambda-function
  vars_files:
    - vars/all.yml
update-aws-lambda-function.yml
- hosts: cliservers
  roles:
    - update-aws-lambda-function
  vars_files:
    - vars/all.yml
update-aws-s3api-event.yml
- hosts: cliservers
  roles:
    - update-aws-s3api-event
  vars_files:
    - vars/all.yml

tasks

role/upload-aws-lambda-function/tasks/main.yml
- name: Create File
  template: 
    src={{ ENV }}/lambda/lambda_function.j2
    dest={{ TEMP.DIRECTORY }}/lambda/lambda_function.py
  tags:
    - always
    - 
- name: "Create Zip"
  shell: zip -r {{ TEMP.DIRECTORY }}/lambda_function.zip *
  args:
    chdir: "{{ TEMP.DIRECTORY }}/lambda"
  tags:
    - always

- name: "Upload Zip"
  shell: |
    aws lambda create-function \
    --function-name {{ AWS.LAMBDA.CLOUD_FRONT.INVALIDATION.NAME }} \
    --zip-file fileb://{{ TEMP.DIRECTORY }}/lambda_function.zip \
    --role {{ AWS.IAM.LAMDA.ROLE.ARN }} \
    --handler lambda_function.lambda_handler \
    --runtime python2.7 \
    --timeout 10 \
    --memory-size 1024
  register: result
  changed_when: False

- debug: var=result.stdout_lines
  when: result | success
  tags:
    - always
role/update-aws-lambda-function/tasks/main.yml
- name: "Add Permission"
  shell: |
    aws lambda add-permission \
    --function-name "{{ AWS.LAMBDA.CLOUD_FRONT.INVALIDATION.NAME }}" \
    --statement-id "{{ AWS.LAMBDA.CLOUD_FRONT.INVALIDATION.STATEMENT }}" \
    --action "lambda:InvokeFunction" \
    --principal "s3.amazonaws.com" \
    --source-arn "{{ AWS.LAMBDA.CLOUD_FRONT.INVALIDATION.SOURCE_ARN }}"
  register: result
  changed_when: False

- debug: var=result.stdout_lines
  when: result | success
  tags:
    - always
role/update-aws-s3api-event/tasks/main.yml
- name: Create File
  template: 
    src={{ ENV }}/s3api/event.j2
    dest={{ TEMP.DIRECTORY }}/event.json
  tags:
    - always
    - 
- name: "Update Zip"
  shell: |
    aws s3api put-bucket-notification-configuration \
    --bucket {{AWS.S3.BUCKET.NAME }} \
    --notification-configuration file://{{ TEMP.DIRECTORY }}/event.json
  register: result
  changed_when: False

- debug: var=result.stdout_lines
  when: result | success
  tags:
    - always

終わりに

これで、対象のS3バケットにオブジェクトをPutするとCloudFrontInvalidationがかかり、キャッシュがリセットされると思います。

また、Lambda実行iamにCloudWatchの権限をつけることで、Lambda関数の実行ログが 自動 で出力されるので、監視も非常にしやすいです♪

S3+CloudFrontの組み合わせは静的サイトを作成する際にはパフォーマンス面で非常に強力です。

しかし、しっかりとキャッシュを意識しないと更新内容が即時に反映されずに逆効果になってしまう場合もあります。

都度手動でインバリデーションをかけるのは運用的にも大変ですし、ヒューマンエラーも起きやすくなるので、是非Lambdaを利用して自動化しておきましょう♪

じゃあの。

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