はじめまして、高野です。MonotaROでは、データ基盤の開発と運用をしています。
この記事では、AWS CloudFormationの実行をInvokeで管理する方法を紹介します。Invokeとは、Fabricの一部が切り出される形で作られた、Python製のタスクランナーです。一般的な用途や使い方は、GNU MakeやRakeをイメージすると分かりやすいかもしれません。
背景
弊社のデータ基盤はAWSとGCPのマルチクラウドで構築されており、インフラリソースの管理にはCloudFormationとDeployment Managerを併用しています。これらを運用していくにあたり、下記のニーズがありました。
- テンプレートだけでなく、実行時に指定するスタック名やパラメータもバージョン管理したい
- 本番環境と開発環境でパラメータの切り替えを行いたい
- CloudFormationとDeployment Managerは、同様のインタフェースで実行したい
シェルスクリプト、Ansible、Clickなども候補にあがりましたが、スクリプト言語の柔軟性やシェルコマンドとの相性から、Invokeの採用に至りました。
Rake等でも同じことが可能と思いますが、弊社の主要な開発言語と同じPythonで実装されている点もInvokeを選定した理由の一つです。
Invokeを使ってみる
Invokeの基本的な使い方を確認しましょう。今回使用するPythonのバージョンは3.6.3、Invokeは0.22.1です。 Ubuntu 17.10のコンソールから実行しています。
Invokeのインストールはpipから行います。
$ pip install invoke
"tasks.py"というファイルを作成し、下記の内容で保存します。二つのタスクを作成しています。
from invoke import task # Pythonのコマンドを実行する @task def print_hello(ctx): print("Hello!") # シェルコマンドを実行する. # オプションで出力形式を変更可能にしている. @task def list_files(ctx, long_format=False): if long_format: ctx.run("ls -l") else: ctx.run("ls")
それではタスクを実行してみましょう。inv(もしくはinvoke)コマンドを使います。
# "-l"で実行可能なタスクの一覧を表示します $ inv -l Available tasks: list-files print-hello # タスクを実行します $ inv print-hello Hello! # タスクのヘルプを見てみましょう $ inv -h list-files Usage: inv[oke] [--core-opts] list-files [--options] [other tasks here ...] Docstring: none Options: -l, --long-format # タスクを実行します. オプションはタスク名の後に指定します. $ inv list-files -l -rw-r--r-- 1 foo foo 184 3月 10 23:36 tasks.py
他にも、実行時にパラメータを与える、タスク間の依存関係を設定する、ヘルプメッセージをカスタマイズする、などのことができます。詳しくは公式ドキュメントを参照してください。
CloudFormationの実行を管理する
Invokeの基本的な操作が分かったところで、CloudFormationをInvokeから実行してみましょう。この例では、CloudFormationからS3のバケットを作成します。また、AWS CLIのインストールとクレデンシャルの設定は完了済みとします。
ディレクトリ構成は下記にします。
. ├── tasks.py └── templates └── cfn-s3.yaml
"tasks.py"の内容は、下記のように変更しましょう。
from invoke import task import os def get_template_path(filename): current_dir = os.path.dirname(os.path.abspath(__file__)) template_path = current_dir + "/templates/" + filename return template_path @task def cfn_s3(ctx, create=False): if create: action = "create-stack" else: action = "update-stack" stack_name = "invoke-test" template_path = get_template_path("cfn-s3.yaml") cmd = "aws cloudformation {action} --stack-name {name} --template-body file://{path}"\ .format(action=action, name=stack_name, path=template_path) print("Execute CloudFormation. command: {cmd}".format(cmd=cmd)) ctx.run(cmd)
templates/cfn-s3.yamlを下記の内容で作成します。
AWSTemplateFormatVersion: 2010-09-09 Resources: S3Bucket: Type: 'AWS::S3::Bucket'
それでは、実際に実行してみましょう。
# タスク名を確認 $ inv -l Available tasks: cfn-s3 # 実行. # 初回(スタック作成時)は"-c"オプションをつける. $ inv cfn-s3 -c Execute CloudFormation. command: aws cloudformation create-stack --stack-name invoke-test --template-body file:///path/to/templates/cfn-s3.yaml { "StackId": "xxxxx" }
コマンドの実行が完了したら、AWSのマネジメントコンソールから"invoke-test"スタックが作成されていることを確認してください。
まとめ
Invokeを使うことで、CloudFormationの実行時の設定を管理することができるようになりました。また、シンプルなタスク名でCloudFormationを実行できるようになりました。
ここから発展させて、環境ごとのパラメーターの切り替えやCloudFormation以外のデプロイタスクの追加を行うことができます。
次回は、環境ごとのパラメータの切り替えについて紹介できればと思います。ここまで読んでいただき、ありがとうございました。