LoginSignup
118
111

More than 5 years have passed since last update.

構成管理ツールで Ansible を使ってる人必見!デプロイするなら Ansistrano ロールを使おう!

Last updated at Posted at 2016-05-31

前書き

デプロイツールは Ruby 製の Capistrano や、Python 製の Fabric、 PHP 製の Deployer など様々あります。
筆者は構成管理ツールで Ansible を使っているため、Ansible でデプロイ出来れば色々と都合がいいです。
そんな時に出会ったのが Ansistrano でした。
Ansible をある程度使える方なら簡単にデプロイ出来てしまうのでオススメです。

Ansistrano とは

ansistrano/deploy: Ansible role to deploy scripting applications like PHP, Python, Ruby, etc. in a capistrano style

PHP 、Python や Ruby などのようなスクリプトアプリケーションのデプロイプロセスを簡単に管理するための Ansible ロールです。Capistrano スタイルのデプロイが Ansible で可能になります。デプロイを行う ansistrano.deploy とデプロイのロールバックを行う ansistrano.rollback の 2 つのロールで構成されています。Ansistrano というプロジェクト名は Ansible + Capistrano から来てます。

インストール

Ansistrano は、Ansible Galaxy を使用したグローバルな分散型 Ansible ロールです。以下のコマンドでインストール出来ます。

$ ansible-galaxy install carlosbuenosvinos.ansistrano-deploy carlosbuenosvinos.ansistrano-rollback

アップデート

ロールを更新したい場合は、インストール時に --force パラメータを通す必要があります。以下のコマンドでアップデート出来ます。

ansible-galaxy install --force carlosbuenosvinos.ansistrano-deploy carlosbuenosvinos.ansistrano-rollback

サーバ側のディレクトリ構造

デプロイが完了するとサーバ側のディレクトリ構造は以下のようになります。指定したディレクトリ以下にcurrent/releases/sharedという3つのディレクトリができあがります。Webサーバ側ではcurrentを指定しておくことで、デプロイされる度にディレクトリを自動で切り替えてくれるようになります。

tree
.
├── current -> ./releases/20160530055905
├── releases
│   ├── 20160530055905
│   │   ├── cache -> ../../shared/cache
│   │   ├── logs -> ../../shared/logs
│   │   ├── tmp -> ../../shared/tmp
│   │   ...
│   ├── 20160530055658
│   │   ...
│   └── 20160530050508
│       ...
└── shared
    ├── cache
    ├── logs
    └── tmp

current

current ディレクトリは、シンボリックリンクとなっており、releases ディレクトリ以下に作成された特定のディレクトリを指します。ウェブサーバやアプリケーションサーバの設定ではドキュメントルートにこのディレクトリを指すようにします。

releases

releases ディレクトリには、アプリケーションコードを格納します。デプロイごとに現在日時 ( timestamp ) を名前とするディレクトリを作成し、その中にコードを格納します。過去のデプロイによるディレクトリを保持しているので、current ディレクトリのリンク先を変えることで異なるバージョンのコードを動かすことが出来ます。 ansistrano_shared_paths パラメータの数を超えたものは古いものから削除されていきます。

shared

shared ディレクトリには、releases ディレクトリ以下に作成された各バージョンのアプリケーションコードが利用するファイルやディレクトリ ( セッションやキャッシュ、ログなど ) を格納します。各バージョンのアプリケーションコードが利用するファイルやディレクトリのシンボリックリンクが shared ディレクトリ以下のファイルやディレクトリを指すようにし同じ内容が参照できるようにしています。

ロール変数

vars
- vars:
  ansistrano_deploy_from: "{{ playbook_dir }}" # Where my local project is (relative or absolute path)
  ansistrano_deploy_to: "/var/www/my-app" # Base path to deploy to.
  ansistrano_version_dir: "releases" # Releases folder name
  ansistrano_current_dir: "current" # Softlink name. You should rarely changed it.
  ansistrano_current_via: "symlink" # Deployment strategy who code should be deployed to current path. Options are symlink or rsync
  ansistrano_shared_paths: [] # Shared paths to symlink to release dir
  ansistrano_keep_releases: 0 # Releases to keep after a new deployment. See "Pruning old releases".
  ansistrano_deploy_via: "rsync" # Method used to deliver the code to the server. Options are copy, rsync, git, s3 or download.
  ansistrano_allow_anonymous_stats: yes

  # Variables used in the rsync deployment strategy
  ansistrano_rsync_extra_params: "" # Extra parameters to use when deploying with rsync in a single string. Although Ansible allows an array this can cause problems if we try to add multiple --include args as it was reported in https://github.com/ansistrano/deploy/commit/e98942dc969d4e620313f00f003a7ea2eab67e86
  ansistrano_rsync_set_remote_user: yes # See [ansible synchronize module](http://docs.ansible.com/ansible/synchronize_module.html). Options are yes, no.

  # Variables used in the Git deployment strategy
  ansistrano_git_repo: git@github.com:USERNAME/REPO.git # Location of the git repository
  ansistrano_git_branch: master # What version of the repository to check out. This can be the full 40-character SHA-1 hash, the literal string HEAD, a branch name, or a tag name
  ansistrano_git_identity_key_path: "" # If specified this file is copied over and used as the identity key for the git commands, path is relative to the playbook in which it is used

  # Variables used in the download deployment strategy
  ansistrano_get_url: https://github.com/someproject/somearchive.tar.gz

  # Variables used in the S3 deployment strategy
  ansistrano_s3_bucket: s3bucket
  ansistrano_s3_object: s3object.tgz # Add the _unarchive suffix to the ansistrano_deploy_via if your object is a package (ie: s3_unarchive)
  ansistrano_s3_region: eu-west-1
  # Optional variables, omitted by default
  ansistrano_s3_aws_access_key: YOUR_AWS_ACCESS_KEY
  ansistrano_s3_aws_secret_key: YOUR_AWS_SECRET_KEY

  # Hooks: custom tasks if you need them
  ansistrano_before_setup_tasks_file: "{{ playbook_dir }}/<your-deployment-config>/my-before-setup-tasks.yml"
  ansistrano_after_setup_tasks_file: "{{ playbook_dir }}/<your-deployment-config>/my-after-setup-tasks.yml"
  ansistrano_before_update_code_tasks_file: "{{ playbook_dir }}/<your-deployment-config>/my-before-update-code-tasks.yml"
  ansistrano_after_update_code_tasks_file: "{{ playbook_dir }}/<your-deployment-config>/my-after-update-code-tasks.yml"
  ansistrano_before_symlink_shared_tasks_file: "{{ playbook_dir }}/<your-deployment-config>/my-before-symlink-shared-tasks.yml"
  ansistrano_after_symlink_shared_tasks_file: "{{ playbook_dir }}/<your-deployment-config>/my-after-symlink-shared-tasks.yml"
  ansistrano_before_symlink_tasks_file: "{{ playbook_dir }}/<your-deployment-config>/my-before-symlink-tasks.yml"
  ansistrano_after_symlink_tasks_file: "{{ playbook_dir }}/<your-deployment-config>/my-after-symlink-tasks.yml"
  ansistrano_before_cleanup_tasks_file: "{{ playbook_dir }}/<your-deployment-config>/my-before-cleanup-tasks.yml"
  ansistrano_after_cleanup_tasks_file: "{{ playbook_dir }}/<your-deployment-config>/my-after-cleanup-tasks.yml"
変数 意味
ansistrano_deploy_from ansistrano_deploy_via が copy または rsync の場合の、ローカル上のデプロイ元アプリケーションコードのパス。
ansistrano_deploy_to リモートサーバ上のデプロイ先のパス。
ansistrano_shared_paths releases ディレクトリ以下に保持する世代数。
ansistrano_deploy_via アプリケーションコードのデプロイ方法。copy, rsync, git, s3, s3_unarchive, unarchive から指定。
ansistrano_allow_anonymous_stats Ansistrano のサイトに利用状況を送信するか否か。
ansistrano_git_repo コードを取得するGitリポジトリ。
ansistrano_git_branch コードを取得するブランチ。
ansistrano_git_identity_key_path リモートサーバー上にある Git リポジトリへの ssh 接続に利用する秘密鍵のパス。

メインワークフロー

Ansistrano はデプロイにおいて Capistrano のフローをフォローしています。

以下ダイアグラムの灰色箇所がメインワークフローの各ステップで、黄色箇所が各ステップの前後に実行されるカスタムタスクのフックポイントです。

Ansistrano フロー

ステップ

メインワークフローのフェーズは以下の 5 ステップで構成されています。

ステップ 意味
Setup releases ディレクトリ以下に現在日時 ( timestamp ) を名前とするディレクトリを作成します。
Update Code Setup ステップ で作成したディレクトリにアプリケーションコードを設置します。
Symlink Shared ansistrano_shared_paths パラメータに基づいて、シンボリックリンクが shared ディレクトリ以下のファイルやディレクトリを指すようにします。
Symlink current ディレクトリのシンボリックリンクが Setup ステップ で作成したディレクトリを指すように変更します。
Cleanup ansistrano_keep_releases パラメータに基づいて、任意の古いバージョンを削除します。

カスタムタスクのフック

ansistrano_before_*_tasks_fileansistrano_after_*_tasks_file パラメータに、各ステップの前後にカスタムタスクファイルを指定することができます。

任意のフックポイントで任意のタスクを実行することが可能です。

vars
# Hooks: custom tasks if you need them
ansistrano_before_setup_tasks_file: "{{ playbook_dir }}/<your-deployment-config>/my-before-setup-tasks.yml"
ansistrano_after_setup_tasks_file: "{{ playbook_dir }}/<your-deployment-config>/my-after-setup-tasks.yml"
ansistrano_before_update_code_tasks_file: "{{ playbook_dir }}/<your-deployment-config>/my-before-update-code-tasks.yml"
ansistrano_after_update_code_tasks_file: "{{ playbook_dir }}/<your-deployment-config>/my-after-update-code-tasks.yml"
ansistrano_before_symlink_shared_tasks_file: "{{ playbook_dir }}/<your-deployment-config>/my-before-symlink-shared-tasks.yml"
ansistrano_after_symlink_shared_tasks_file: "{{ playbook_dir }}/<your-deployment-config>/my-after-symlink-shared-tasks.yml"
ansistrano_before_symlink_tasks_file: "{{ playbook_dir }}/<your-deployment-config>/my-before-symlink-tasks.yml"
ansistrano_after_symlink_tasks_file: "{{ playbook_dir }}/<your-deployment-config>/my-after-symlink-tasks.yml"
ansistrano_before_cleanup_tasks_file: "{{ playbook_dir }}/<your-deployment-config>/my-before-cleanup-tasks.yml"
ansistrano_after_cleanup_tasks_file: "{{ playbook_dir }}/<your-deployment-config>/my-after-cleanup-tasks.yml"

Ansistrano の使い方

デプロイ

playbook の準備

デプロイするアプリケーションは PHP アプリケーションを想定しています。

playbook
.
├── deploy.yml
├── group_vars
│   └── all.yml
├── hosts
└── roles
    └── hooks
        └── tasks
            ├── after_update_code.yml
            ├── before_symlink_shared.yml
            └── after_symlink.yml
hosts ファイル
hosts
www.example.com
vars ファイル

group_vars で変数を定義していますが、別の場所で定義しても問題ありません。

group_vars/all.yml
---
ansistrano_deploy_to: /var/www/app
ansistrano_shared_paths:
  - cache
  - logs
  - tmp
ansistrano_allow_anonymous_stats: no
ansistrano_keep_releases: 5
ansistrano_deploy_via: git
ansistrano_git_repo: git@github.com:USERNAME/REPO.git
ansistrano_git_branch: master
ansistrano_after_update_code_tasks_file: "{{ playbook_dir }}/roles/hooks/task/after_update_code.yml"
ansistrano_after_update_code_tasks_file: "{{ playbook_dir }}/roles/hooks/tasks/before_symlink_shared.yml"
ansistrano_after_symlink_tasks_file: "{{ playbook_dir }}/roles/hooks/task/after_symlink.yml"
playbook

Ansistranoでnode.jsのアプリケーションをインストールする - Qiita

ansistrano_deploy_via については Ansistrano の中で include を使ったトリックが使われているのでvars_filesではうまく行きませんでした。

の通り、 vars_files や group_vars で ansistrano_deploy_via を定義すると、パラメータ関係なしに rsync で実行されてしまいます。そのためトップレベル YAML の vars で定義しています。

deploy.yml
---
- hosts: all
  become: yes
  become_user: www-data
  vars:
    ansistrano_deploy_via: git
  roles:
    - carlosbuenosvinos.ansistrano-deploy
フックで実行されるカスタムタスク

Update Code ステップの後で実行されるカスタムタスク。

roles/hooks/tasks/after_update_code.yml
---
- name: ANSISTRANO | HOOKS | Whether or not the composer is present
  stat: path=/usr/bin/composer
  register: is_composer

- name: ANSISTRANO | HOOKS | Install composer
  shell: curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin --filename=composer creates=/usr/bin/composer
  become_user: root
  when: not is_composer.stat.exists

- name: ANSISTRANO | HOOKS | Update composer
  become: yes
  become_user: root
  composer:
    command=install
    working_dir={{ ansistrano_release_path.stdout }}

Symlink ステップの前で実行されるカスタムタスク。

roles/hooks/tasks/before_symlink_shared
---
- name: ANSISTRANO | HOOKS | Create shared paths
  file: state=directory path={{ ansistrano_deploy_to }}/shared/{{ item }} mode=0777
  with_items: ansistrano_shared_paths

Symlink ステップの後で実行されるカスタムタスク。

roles/hooks/tasks/after_symlink.yml
---
- name: ANSISTRANO | HOOKS | Restart nginx
  service: name=nginx state=restarted
  become: yes
  become_user: root

カスタムタスクのファイルを記述する場合は、必要とされるいくつかの変数を使うことができます。

変数 意味
{{ ansistrano_release_path.stdout }} current ディレクトリのリンク先のパス
{{ ansistrano_releases_path.stdout }} releases ディレクトリへのパス
{{ ansistrano_shared_path.stdout }} shared ディレクトリへのパス
{{ ansistrano_release_version }} current ディレクトリのリンク先のディレクトリ名 ( timestamp )

実行

ansible-playbook -i hosts deploy.yml

全てが正しく設定されている場合、このコマンドは、サーバー側で以下のようなディレクトリ構造を作成します。

/var/www/app
.
├── current -> ./releases/20160530055905
├── releases
│   ├── 20160530055905
│   │   ├── cache -> ../../shared/cache
│   │   ├── logs -> ../../shared/logs
│   │   ├── tmp -> ../../shared/tmp
│   │   ...
│   ├── 20160530055658
│   │   ...
│   └── 20160530050508
│       ...
└── shared
    ├── cache
    ├── logs
    └── tmp

複数のサーバーにデプロイ

各サーバーの releases ディレクトリ以下に異なる timestamp でディレクトリが作成されることを防止するために serial オプションを使用します。 serial オプションには ansistrano_release_version を設定し実行します。

$ ansible-playbook -i hosts -e "ansistrano_release_version=`date -u +%Y%m%d%H%M%S`" deploy.yml

多段環境のデプロイ

development 、staging や production などのような様々な環境にデプロイする場合は、異なるインベントリーファイルと変数ファイルを作成します。作成したら、 デプロイしたい環境のインベトリーファイルを -i パラメータを使って指定し実行します。 

playbook の準備

staging と production 環境の場合は以下のようになります。

playbook
.
├── production         # inventory file for production servers
├── staging            # inventory file for staging environment
├── group_vars
│   ├── all.yml
│   ├── production.yml # variables file for production groups
│   └── staging.yml    # variables file for staging groups
├── deploy.yml
└── roles
    └── hooks
        └── tasks
            ├── after_symlink.yml
            ├── after_update_code.yml
            └── before_symlink_shared.yml
hosts ファイル
production
[production]
prod.example.com
staging
[staging]
stg.example.com
vars ファイル

group_vars/production.ymlgroup_vars/staging.yml を作成し、それぞれ環境ごとに Ansistrano のロール変数やユーザーやパスワード等の変数を定義します。

実行

ansible-playbook -i production deploy.yml
ansible-playbook -i staging deploy.yml

ロールバック

ロール変数

デプロイのロール変数に比べてロールバックのロール変数は少ないです。

vars
- vars:
  ansistrano_deploy_to: "/var/www/my-app" # Base path to deploy to.
  ansistrano_version_dir: "releases" # Releases folder name
  ansistrano_current_dir: "current" # Softlink name. You should rarely changed it.
  ansistrano_remove_rolled_back: yes # Remove rolled back release?
  ansistrano_allow_anonymous_stats: yes

  # Hooks: custom tasks if you need them
  ansistrano_before_symlink_tasks_file: "{{ playbook_dir }}/<your-deployment-config>/my-before-symlink-tasks.yml"
  ansistrano_after_symlink_tasks_file: "{{ playbook_dir }}/<your-deployment-config>/my-after-symlink-tasks.yml"
  ansistrano_before_cleanup_tasks_file: "{{ playbook_dir }}/<your-deployment-config>/my-before-cleanup-tasks.yml"
  ansistrano_after_cleanup_tasks_file: "{{ playbook_dir }}/<your-deployment-config>/my-after-cleanup-tasks.yml"

実行

ansible-playbook -i hosts rollback.yml

releases ディレクトリ以下に作成されたアプリケーションコードが 0 または 1 つだった場合、ロールバックしようとするとエラーが発生し実行されません。

注意点

参考文献

118
111
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
118
111