ども、cloudpack の 夜の Player かっぱ (@inokara) です。今年の紅白歌合戦出場は辞退しました。すいません。

はじめに

AWS 環境において fabric を利用して Play2 アプリケーションをリモートホストに対してデプロイしようとした際にリモートホストの情報を動的に取得したいと思ったので組み込んでみました。

boto

fabric が Python 実装ということで fabric から AWS 環境を扱おうとすると boto というライブラリが必須ですのでインストールしておきましょう。環境に応じてインストール方法は異なりますのでご注意下さい。

初めて知りましたが boto = AWS SDK for Python だったんですね。

実装

ギットハヴ

ツッコミ宜しくお願い致します!

ざっくりイメージ

以下のように EC2 のインスタンス Name タグを指定して Public IP アドレス等のデプロイ先の情報を取得してきます。
Play Framework 2 を fabric ででプロイする: イメージ図

抜粋

該当する部分のみ抜粋。

from fabric.api import local, run, env, cd, lcd, execute, put, sudo
from boto.ec2 import EC2Connection, get_region, connect_to_region


def deploy_host(tag = "Name", value = "app-server", region = "region を指定"):
  key = "tag:"+tag
  env.hosts = _get_host_ip(region, key, value)

def _get_host_ip(region, key, value ="*"):
  private_ip = []
  conn = _create_connection(region)
  reservations = conn.get_all_instances(filters = {key : value})
  for reservation in reservations:
      for instance in reservation.instances:
          print "Instance", instance.private_ip_address
          private_ip.append(str(instance.private_ip_address))
  return private_ip

def _create_connection(region):
  print "Connecting to ", region
  conn = connect_to_region(
      region_name = region
  )
  print "Connection with AWS established"
  return conn


〜中略〜

def app_status():
  execute(default_path)
  sudo('supervisorctl status %(app)s' % { 'app':env.app }, pty=True, shell=False)

def app_start():
  execute(set_path)
  with cd("%(current_path)s/%(snap_shot)s/" % { 'current_path':env.current_path, 'snap_shot':env.snap_shot }):
    run('if [ -f RUNNING_PID ]; then rm RUNNING_PID ; fi')
  sudo('supervisorctl start %(app)s' % { 'app':env.app }, pty=True, shell=False)

def app_stop():
  execute(default_path)
  sudo('supervisorctl stop %(app)s' % { 'app':env.app }, pty=True, shell=False

deploy_host 関数を引数で渡して実行します。
ポイントは…

  • 冒頭の boto.ec2 ライブラリを読み込んでいる部分
  • _get_host_ip_create_connection を実行して AWS への接続を行う
  • _get_host_ip で取得された接続情報が env.host に代入される

IAM ロール

注意点としては fabric を実行するインスタンスは IAM ロールで以下の権限を付与しています。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "ec2:Describe*",
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": "elasticloadbalancing:Describe*",
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "cloudwatch:ListMetrics",
        "cloudwatch:GetMetricStatistics",
        "cloudwatch:Describe*"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": "autoscaling:Describe*",
      "Resource": "*"
    }
  ]
}

多分、"Action": "ec2:Describe*" だけあればイケるのではないかと思います。

demo

以下のように実行することでインスタンスの Name タグに app-server とあるインスタンスの IP アドレスを取得してサブコマンドで指定された処理を行います。

fab -f deploy.py deploy_host command

例えば、アプリケーションのステータスを取得したい場合には app_status というコマンドを実行します。

fab -f deploy.py deploy_host app_status

以下のようにリモートホストにてコマンドを実行した結果が出力されます。
Play Framework 2 を fabric ででプロイする: 出力結果

最後に

特に Play Framework に特化したことではありませんが、Capistrano でも同様に AWS SDK を利用してデプロイ先の情報を取得してデプロイを行うことが出来るので SDK ってサイコーって思ったりしています。

ということでおやすみなさい。

元記事はこちらです。
Play2 アプリケーションのデプロイを fabric でやろうと思ったのでメモ(3)〜対象ホストを SDK で取得する巻〜