Fabricを使用してWebアプリケーションをデプロイする

アプリケーションは成長し、より複雑になっています。 それらを展開および更新するために必要な操作の数は増え続けています。







この記事では、エキサイティングな、場合によっては予測不可能な冒険を、予測可能な結果を​​伴うシンプルで日常的で退屈な操作に変える方法について説明します。



私たちの目標




ファブリックをインストールする


生地を使用します 。 このセットは、システム管理タスクを自動化するための優れた汎用ツールです。 彼はこの記事でよく代表されています



したがって、Linuxとpython(2.5-2.7)を備えたワークステーションが既にあると仮定します。 必要なツールをインストールします。

# pip install fabric # pip install fabtools
      
      







ちょっとした推論


sshを介してサーバーと対話します。 したがって、キーを既に生成し、その使用を〜/ .ssh / configで決定し、パブリック部分をサーバーに配置していると想定しています。 サーバー上でユーザーを管理しやすくするために、各展開エンジニアに個人アカウントを作成します。このアカウントは、プロセスでプロジェクトユーザーからのコマンドを実行したり、プロジェクトユーザーになったりできます。



最も単純な展開プロジェクトは次のもので構成されます。

 myapp_deploy/ fabfile.py #  ,   . sudoers/ devel_sudo #  /etc/sudoers    - config/ config-production.php # 
      
      







1つのサーバーにある最も単純なサービスを展開します。 このサービスでは、その特異性を決定する一連のパラメーターを定義します。 このようなアプローチにより、アプリケーションを論理的にモジュールに分割し、各モジュールを個別にデプロイできます。



スクリプトを書く


 from fabric.api import env, run, sudo, local, put, settings import fabtools def production(): """Defines production environment""" env.hosts = ['192.168.1.2'] #  env.shell = 'bash -c' #       env.use_ssh_config = True #   ssh- env.project_user = "myappuser" #,        env.sudo_user = env.project_user env.base_dir = "/apps" #    env.domain_name = "myapp.example.com" #FQDN     env.domain_path = "%(base_dir)s/%(domain_name)s" % { 'base_dir':env.base_dir, 'domain_name':env.domain_name } #       myapp env.current_path = "%(domain_path)s/current" % { 'domain_path':env.domain_path } #    myapp env.releases_path = "%(domain_path)s/releases" % { 'domain_path':env.domain_path } #     env.git_clone = "git@git.example.com:myapp.git" #,     . env.config_file = "config/config-production.php" #    
      
      







次に、機能を直接扱いましょう。 まず、サーバーの初期設定を行う必要があります。 システムの設定を変更する必要がある場合にのみ、この操作を実行します。 関数呼び出しは、システム内のすべての特権を持つシステム管理者に委任するのが最適です。



 def permissions(): """Set proper permissions for release""" sudo("chown -R %(project_user)s:%(project_user)s %(domain_path)s" % { 'domain_path':env.domain_path, 'project_user':env.sudo_user }) def setup(): """Prepares one or more servers for deployment""" with settings(sudo_user='root'): sudo("mkdir -p %(domain_path)s/releases" % { 'domain_path':env.domain_path }) sudo("mkdir -p %(base_dir)s/logs/" % { 'base_dir':env.base_dir }) permissions() put("sudoers/devel_sudo", "/tmp/devel_sudo") sudo("chown root:root /tmp/devel_sudo") sudo("chmod 0440 /tmp/devel_sudo") sudo("mv /tmp/devel_sudo /etc/sudoers.d/devel_sudo")
      
      







次に、サーバー上のリリースのストレージを決定します。 ディレクトリ構造は次のようになります。

 /apps myapp.example.com/ current #    releases/ #  release0 release1 ... releaseN #  
      
      







タイムスタンプを使用してリリースインデックスを決定します。 したがって、最新のリリースと最後から2番目のリリース(ロールバックする場合)およびそれらへのパスを見つける必要があります。



 def releases(): """List a releases made""" env.releases = sorted(sudo('ls -x %(releases_path)s' % { 'releases_path':env.releases_path }).split()) if len(env.releases) >= 1: env.current_revision = env.releases[-1] env.current_release = "%(releases_path)s/%(current_revision)s" % { 'releases_path':env.releases_path, 'current_revision':env.current_revision } if len(env.releases) > 1: env.previous_revision = env.releases[-2] env.previous_release = "%(releases_path)s/%(previous_revision)s" % { 'releases_path':env.releases_path, 'previous_revision':env.previous_revision }
      
      







頻繁に接続される展開では、一部のサービスの再起動が必要です。 最も単純なプロジェクトがあるにもかかわらず、既知の問題を回避するにはphp-fpmをリロードする必要があります



 def restart(): """Restarts your application services""" with settings(sudo_user='root',use_shell=False): sudo("/etc/init.d/php5-fpm reload")
      
      







ここで、何らかの方法でリポジトリからコードを取得する必要があります。 gitリポジトリから最新バージョンのファイルを複製します。



 def checkout(): """Checkout code to the remote servers""" env.timestamp = run("/bin/date +%s") env.current_release = "%(releases_path)s/%(timestamp)s" % { 'releases_path':env.releases_path, 'timestamp':env.timestamp } sudo("cd %(releases_path)s; git clone -q -b master --depth 1 %(git_clone)s %(current_release)s" % { 'releases_path':env.releases_path, 'git_clone':env.git_clone, 'current_release':env.current_release })
      
      







構成ファイルをリリースディレクトリにコピーします。



 def copy_config(): """Copy custom config to the remote servers""" if not env.has_key('releases'): #  ,       releases() put("%s" % env.config_file, "/tmp/config.php") sudo("cp /tmp/config.php %(current_release)s/config/" % { 'current_release':env.current_release }) run("rm /tmp/config.php")
      
      







シンボリックリンクを使用して、最新リリースを適切なものにします



 def symlink(): """Updates the symlink to the most recently deployed version""" if not env.has_key('current_release'): releases() sudo("ln -nfs %(current_release)s %(current_path)s" % { 'current_release':env.current_release, 'current_path':env.current_path })
      
      







展開手順全体を単一の全体にまとめます



 def deploy(): """Deploys your project. This calls 'checkout','copy_config','migration','symlink','restart','cleanup'""" checkout() copy_config() symlink() restart()
      
      







リリースをクリーンアップする必要性を考慮してください。



 def cleanup(): """Clean up old releases""" if not env.has_key('releases'): releases() if len(env.releases) > 10: directories = env.releases directories.reverse() del directories[:10] env.directories = ' '.join([ "%(releases_path)s/%(release)s" % { 'releases_path':env.releases_path, 'release':release } for release in directories ]) sudo("rm -rf %(directories)s" % { 'directories':env.directories })
      
      







リリース後に問題が発生した場合、以前のバージョンにすばやくロールバックする機能が必要です。



 def rollback_code(): """Rolls back to the previously deployed version""" if not env.has_key('releases'): releases() if env.has_key('previous_release'): sudo("ln -nfs %(previous_release)s %(current_path)s && rm -rf %(current_release)s" % { 'current_release':env.current_release, 'previous_release':env.previous_release, 'current_path':env.current_path }) else: print "no releases older then current" sys.exit(1) def rollback(): """Rolls back to a previous version and restarts""" rollback_code() restart()
      
      







今日はすばらしい、十分なpython。



使用する


次のようにして、スクリプトで実行できるすべてのリストを取得できます。



 $ fab --list Available commands: checkout Checkout code to the remote servers cleanup Clean up old releases copy_config Copy custom config to the remote servers deploy Deploys your project. This calls 'checkout','copy_config','migration','symlink','restart','cleanup' permissions Set proper permissions for release production Defines production environment releases List a releases made restart Restarts your application services rollback Rolls back to a previous version and restarts rollback_code Rolls back to the previously deployed version setup Prepares one or more servers for deployment symlink Updates the symlink to the most recently deployed version
      
      







さあ、サーバーにデプロイしましょう



 $ fab production deploy [192.168.1.2] Executing task 'deploy' [192.168.1.2] run: /bin/date +%s [192.168.1.2] out: 1431941361 [192.168.1.2] out: [192.168.1.2] sudo: cd /apps/myapp.example.com/releases; git clone -q -b master --depth 1 git@git.example.com:myapp.git /apps/myapp.example.com/releases/1431941361 [192.168.1.2] sudo: ls -x /apps/myapp.example.com/releases [192.168.1.2] out: 1431940514 1431940525 1431940537 1431940547 1431940558 1431940568 1431940578 1431940589 1431940599 1431941361 [192.168.1.2] out: [192.168.1.2] put: config/config-production.php -> /tmp/config.php [192.168.1.2] sudo: cp /tmp/config.php /apps/myapp.example.com/releases/1431941361/config/ [192.168.1.2] run: rm /tmp/config.php [192.168.1.2] sudo: ln -nfs /apps/myapp.example.com/releases/1431941361 /apps/myapp.example.com/current [192.168.1.2] sudo: /etc/init.d/php-fpm reload [192.168.1.2] out: Reloading php-fpm: [18-May-2015 05:29:29] NOTICE: configuration file /etc/php-fpm.conf test is successful [192.168.1.2] out: [192.168.1.2] out: [ OK ] [192.168.1.2] out: [192.168.1.2] out: Done. Disconnecting from 192.168.1.2... done.
      
      







その結果、優れたツールが得られました。このツールは、わずかな変更を加えるだけで、さまざまな仕様を持つ多数のプロジェクトで使用できます。



All Articles