Automating play application deployment with fabric I operated Amazon EC2 and ELB in the fabric, so I would like to give you a brief introduction.
http://fabric-ja.readthedocs.org/en/latest/tutorial.html
What is Fabric:
-A tool that executes arbitrary Python functions via the command line. -A library of subroutines (built on top of a low-level library) Easily execute shell commands via SSH in a Python-like way.
It's hard to understand if it's an official document, By combining the two, you can automate the process to the remote server. Production deployment Manual work is too scary and troublesome, so let's automate it more and more.
For comparison with Capistrano, I referred to the following article. http://dekokun.github.io/posts/2013-05-21.html
○ The flow of deployment looks like this Source update ↓ Remove EC2 from ELB ↓ play stop ↓ Deploy with play ↓ play start ↓ Add EC2 to ELB ↓ End of deployment
Play framework 2.3.x activator 1.2.10 The OS to deploy to is Amazon Linux Fabric 1.8.1
centOS sudo yum -y install python python-devel python-setuptools gcc sudo easy_install pip sudo pip install fabric==1.8.1
Mac sudo easy_install fabric
call local-> local shell command env-> env variable (global singleton), used for information sharing between tasks lcd-> local current directory specification execute-> execute task
Decorator @task-> Load as a valid task @runs_once-> Prevent wrapped functions from being executed multiple times
For the time being, I will put in a fabfile. Partially described below. fabfile
# -*- coding: utf-8 -*-
from fabric.api import *
from fabric.decorators import runs_once
import boto.ec2.elb
env.hosts = ['localhost']
env.user = "username"
env.project_root = "path/to/project"
env.build_path = "target/universal/stage/bin/project_name"
env.config_path = env.project_root + '/conf/application.conf'
env.branch = 'master'
env.region = "ap-northeast-1"
env.elb_name = 'your_elb_name'
env.aws_access_key = 'your_aws_access_key'
env.aws_secret_key = 'your_aws_secret_key'
##Build
@task
@runs_once
def build_play():
""" activator clean stage"""
with lcd(env.project_root):
local("activator clean stage")
##activator activation system
@task
def play_start():
"""Launch activator in production mode"""
with lcd(env.project_root):
local("%(bin)s -Dconfig.file=%(conf)s &" % {"bin":env.build_path, "conf":env.config_path})
@task
def play_stop():
"""Kill a process running in production mode"""
if local('ps -ef | grep "%(root)s/target/universal/stage" | grep -v grep | wc -l' % {"root":env.project_root}, capture=True) == "1":
local("kill `cat %(root)s/target/universal/stage/RUNNING_PID`" % {"root":env.project_root})
@task
def play_restart():
"""Reboot in production mode"""
execute(play_stop)
execute(play_start)
##AWS ELB operation
def get_ec2_id():
"""Get instanceID for ec2"""
env.ec2_id = local("curl http://169.254.169.254/latest/meta-data/instance-id", capture=True)
def conn_elb():
env.conn_elb = boto.ec2.elb.connect_to_region(
env.region,
aws_access_key_id = env.aws_access_key,
aws_secret_access_key = env.aws_secret_key)
def get_elb():
execute(conn_elb)
env.elb = env.conn_elb.get_all_load_balancers(env.elb_name)[0]
def remove_ec2():
""" ec2(myself)From ELB"""
execute(get_elb)
execute(get_ec2_id)
env.elb.deregister_instances(env.ec2_id)
def add_ec2():
""" ec2(myself)To ELB"""
execute(get_elb)
execute(get_ec2_id)
env.elb.register_instances(env.ec2_id)
@task
@runs_once
def update(branch=env.branch):
""" env.Synchronize with branch. When specifying a branch-> fab update:branch=branch_name"""
with lcd(env.project_root):
local("git fetch")
local("git reset --hard HEAD")
local("git checkout " + branch)
local("git pull")
##Deploy
@task
@runs_once
def deploy(branch=env.branch):
"""Branch specification-> fab deploy:branch=branch_name"""
execute(remove_ec2)
execute(play_stop)
execute(update,branch=branch)
execute(build_play)
execute(play_start)
execute(add_ec2)
@task
def play_start():
"""Launch activator in production mode"""
with lcd(env.project_root):
local("%(bin)s -Dconfig.file=%(conf)s &" % {"bin":env.build_path, "conf":env.config_path})
Delete the process using the RUNNING_PID file that manages the process in the play application.
@task
def play_stop():
"""Kill a process running in production mode"""
if local('ps -ef | grep "%(root)s/target/universal/stage" | grep -v grep | wc -l' % {"root":env.project_root}, capture=True) == "1":
local("kill `cat %(root)s/target/universal/stage/RUNNING_PID`" % {"root":env.project_root})
boto I use a library called boto (AWS SDK for Python) to operate ELB from fabric. API document: http://boto.readthedocs.org/en/latest/ https://github.com/boto/boto
import boto.ec2.elb
def conn_elb():
env.conn_elb = boto.ec2.elb.connect_to_region(
env.region,
aws_access_key_id = env.aws_access_key,
aws_secret_access_key = env.aws_secret_key)
def get_elb():
execute(conn_elb)
env.elb = env.conn_elb.get_all_load_balancers(env.elb_name)[0]
EC2 seems to be able to get various meta information of itself. Benri to know http://d.hatena.ne.jp/rx7/20100605/p1
Note that in the case of local, it will not be entered in the variable unless capture = True.
def get_ec2_id():
"""Get instanceID for ec2"""
env.ec2_id = local("curl http://169.254.169.254/latest/meta-data/instance-id", capture=True)
def remove_ec2():
""" ec2(myself)From ELB"""
execute(get_elb)
execute(get_ec2_id)
env.elb.deregister_instances(env.ec2_id)
def add_ec2():
""" ec2(myself)To ELB"""
execute(get_elb)
execute(get_ec2_id)
env.elb.register_instances(env.ec2_id)
demo
Execute the fab command in the current directory where the fabfile is installed. I think it can be placed in the project route or under / home / user.
The list with the @task decorator is displayed. $ fab --list
$ fab deploy
I touched both fabric and boto for the first time this time, but I thought that the benefits were high for the low learning cost. I also made a deploy version from the deploy server to the remote host, so when I have time, that too I would like to blog.
Thank you for reading until the end.
Recommended Posts