前書き
デプロイツールは Ruby 製の Capistrano や、Python 製の Fabric、 PHP 製の Deployer など様々あります。
筆者は構成管理ツールで Ansible を使っているため、Ansible でデプロイ出来れば色々と都合がいいです。
そんな時に出会ったのが Ansistrano でした。
Ansible をある程度使える方なら簡単にデプロイ出来てしまうのでオススメです。
Ansistrano とは
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を指定しておくことで、デプロイされる度にディレクトリを自動で切り替えてくれるようになります。
.
├── 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:
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 のフローをフォローしています。
以下ダイアグラムの灰色箇所がメインワークフローの各ステップで、黄色箇所が各ステップの前後に実行されるカスタムタスクのフックポイントです。
ステップ
メインワークフローのフェーズは以下の 5 ステップで構成されています。
ステップ | 意味 |
---|---|
Setup |
releases ディレクトリ以下に現在日時 ( timestamp ) を名前とするディレクトリを作成します。 |
Update Code |
Setup ステップ で作成したディレクトリにアプリケーションコードを設置します。 |
Symlink Shared |
ansistrano_shared_paths パラメータに基づいて、シンボリックリンクが shared ディレクトリ以下のファイルやディレクトリを指すようにします。 |
Symlink |
current ディレクトリのシンボリックリンクが Setup ステップ で作成したディレクトリを指すように変更します。 |
Cleanup |
ansistrano_keep_releases パラメータに基づいて、任意の古いバージョンを削除します。 |
カスタムタスクのフック
ansistrano_before_*_tasks_file
と ansistrano_after_*_tasks_file
パラメータに、各ステップの前後にカスタムタスクファイルを指定することができます。
任意のフックポイントで任意のタスクを実行することが可能です。
# 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 アプリケーションを想定しています。
.
├── deploy.yml
├── group_vars
│ └── all.yml
├── hosts
└── roles
└── hooks
└── tasks
├── after_update_code.yml
├── before_symlink_shared.yml
└── after_symlink.yml
hosts ファイル
www.example.com
vars ファイル
group_vars
で変数を定義していますが、別の場所で定義しても問題ありません。
---
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 で定義しています。
---
- hosts: all
become: yes
become_user: www-data
vars:
ansistrano_deploy_via: git
roles:
- carlosbuenosvinos.ansistrano-deploy
フックで実行されるカスタムタスク
Update Code
ステップの後で実行されるカスタムタスク。
---
- 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
ステップの前で実行されるカスタムタスク。
---
- name: ANSISTRANO | HOOKS | Create shared paths
file: state=directory path={{ ansistrano_deploy_to }}/shared/{{ item }} mode=0777
with_items: ansistrano_shared_paths
Symlink
ステップの後で実行されるカスタムタスク。
---
- 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
全てが正しく設定されている場合、このコマンドは、サーバー側で以下のようなディレクトリ構造を作成します。
.
├── 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 環境の場合は以下のようになります。
.
├── 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]
prod.example.com
[staging]
stg.example.com
vars ファイル
group_vars/production.yml
と group_vars/staging.yml
を作成し、それぞれ環境ごとに Ansistrano のロール変数やユーザーやパスワード等の変数を定義します。
実行
ansible-playbook -i production deploy.yml
ansible-playbook -i staging deploy.yml
ロールバック
ロール変数
デプロイのロール変数に比べてロールバックのロール変数は少ないです。
- 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 つだった場合、ロールバックしようとするとエラーが発生し実行されません。