前回書いた『VirtualBox + Vagrant + Ansibleを使って『Pythonプロフェッショナルプログラミング』で使う開発環境(に近いもの)をほぼ自動で構築するPlaybookを作ってみました』という記事の続きです。なので、前回の記事を読んでないと意味不明かもしれません。
がっつり調べたというわけではなく、「色々試してやっと基本的なところが出来ました」というくらいの話しなので、軽めに書きます---と言いたかったのですが、書いてみたらえらく長くなってしまいました。
最初に結論をまとめると
- 前回の記事で手前味噌ながら紹介した「『Pythonプロフェッショナルプログラミング』で使う開発環境を構築できるお試しセット」を、Ansibleのv1.2以降で使えるようになるRolesという機能を使って書き換えてみました。
- URLはこちら。role-sampleという名前のブランチでRoles機能を使っています。
- https://github.com/takuan-osho/ansible-vagrant-pypro-skel
- ブランチの名前を変えるかもしれない*1のでmasterブランチのURLにしています。
- まだ作業途中なので内容が変わるかもしれませんが、やっていることはmasterブランチの内容と全く同じで、単にRolesという機能を使うように変更しただけです。
- READMEはまだ書き換えてないので無視して下さい。
- 現時点ではPyPIに上がっているAnsibleのバージョンは1.1なので、Ansibleをgithubから取ってきてsudo python setup.py installするなりしてAnsibleのバージョンを1.2相当にした後、実行するコマンドを以下のように変更してもらうとsshのパスワードを聞かれた後Ansibleが起動します。Roles機能を使わないときと同じ動作をすると思います。
ansible-playbook main.yml -i hosts/local -k
- 注意事項など
- 前回の記事で書いた注意事項は最低限気をつけて下さい。
- 今回(Ansible1.2)の場合に気をつけるべき事はこの記事内の後のほうに書きます。
そもそもAnsibleのRolesって何よ?という人のための簡単な説明
Ansibleの説明はもう面倒臭い必要ないと思うので省きます。
前回の記事の下の方に参考記事リンクをバリバリ貼っているので、Ansibleが何か知らない人はそこを見たり、為になるこちらの記事を見てください。あと、Ansibleの基本的な使い方は前回記事で紹介したリポジトリのREADMEを読んで実際に手を動かしてみた人という想定でこれから書きます。一つ一つ説明書くといつまで経ってもRolesの説明が出来ないので*2。
いまこの記事を書いている現在のAnsibleのバージョン(PyPIに上がっている方)は1.1なのですが、github上にある開発バージョンには1.1に含まれていない機能・モジュールが多数あります。Rolesもその一つです。
Rolesというのは乱暴に言ってしまうと、あらかじめ決められたディレクトリ構成を作って所定の位置にファイルを置けばAnsibleのincludeをより便利且つ楽に使えるようになる仕組みのことです。
includeとは何かというと、あるplaybookから他のplaybookを呼び出す機能*3なのですが、前回の記事で作ったリポジトリを例にした方が分かると思うのでそうします。
まずrolesを使わずincludeだけを使った場合の例を示します。
--- ├── editor.yml ├── essential.yml ├── hosts │ └── local ├── main.yml └── python.yml
includeだけを使ったplaybookのディレクトリ構成は上のようになっています。ここで実際にAnsibleを使うときに指定するplaybookであるmain.ymlの中身を見てみましょう。
--- # main.yml - hosts: pypro user: vagrant sudo: yes tasks: - include: essential.yml tags=essential - include: editor.yml tags=editor - include: python.yml tags=python
ここでincludeが使われていますが、includeの後に呼び出したいファイルを指定するとそのファイルが読み込まれて中に書かれている内容を処理します。
ここでは最初にincludeを使って呼び出されているessential.ymlの中を見てみましょう。
--- # essential.yml - name: Install basic server pkgs apt: pkg=$item force=yes update_cache=yes with_items: - build-essential - libsqlite3-dev - libreadline6-dev - libgdbm-dev - zlib1g-dev - libbz2-dev - sqlite3 - tk-dev - zip - python-dev - python-pip - python-setuptools - python3.2 - subversion - openjdk-7-jre-headless - nginx
何をやっているかはだいたい見てもらえれば分かると思いますが、Ansibleに標準付属されているaptモジュールを使って開発に必要なパッケージ群をインストールする処理が書かれています。
includeを使わないで同じ処理をしようと思ったときにmain.ymlの中身がどうなるかというと…
--- # main.yml - hosts: pypro user: vagrant sudo: yes tasks: - name: Install basic server pkgs apt: pkg=$item force=yes update_cache=yes with_items: - build-essential - libsqlite3-dev - libreadline6-dev - libgdbm-dev - zlib1g-dev - libbz2-dev - sqlite3 - tk-dev - zip - python-dev - python-pip - python-setuptools - python3.2 - subversion - openjdk-7-jre-headless - nginx (以下省略)
このように大変長くなってしまいます。これくらいならまだ一つにまとめてもいいかもしれませんが、もっと処理が多くなると一つにまとめた場合、どこにどんな処理が書いてあるのか把握するのも大変になってきます。
includeを使うと一つのファイルに処理をまとめて書く必要がなくなり、ファイルを分割して記述が出来るようになります。プログラミングで小さなモジュールを組み合わせて使うのと同じように、includeを使えば一つのファイルに必要以上に命令を書き込まず、再利用可能なplaybookを作ることが可能になるんですね。
includeがあれば再利用可能なplaybookを作るのは可能なんですが、ディレクトリ構成をどうするかなどの方針を決めずに使いすぎるとどこに必要な処理を書いたのか後から把握するのが辛くなりますし、そもそも再利用可能なディレクトリ構成を考えつつ再利用可能なplaybookを書くのは結構骨が折れます。
そもそも上で使用したのはtaskだけで、fileとかtemplate、handlerやvarといったtask以外の機能を使用してません。これらの機能も含めてplaybookを分割して分かりやすくディレクトリ構成を決めるのは大変なはずです。
そこでRolesという機能の出番です。
Rolesというのは公式ドキュメントの説明を基に超訳すると
- 「includeディレクティブを単に自動化したもの」
- 「参照するファイルのパスを見つける処理を改良しているだけ」
のものです。
日本語で言っているだけだと意味不明だと思うので実例を見てみましょう。
下で紹介する例は上で紹介したincludeの例を単純にrolesで置き換えたものです。
. ├── hosts │ └── local ├── main.yml └── roles └── common ├── tasks │ └── main.yml └── vars └── main.yml
hostsディレクトリとmain.ymlの場所は変わっていません。変わっているのはessential.ymlなどのplaybookが無くなり、代わりにrolesというディレクトリが増えています。
このときのmain.ymlの中身は下のようになっています。
--- # file: main.yml - hosts: pypro user: vagrant sudo: True roles: - common
上のように、rolesというディレクティブを使い、rolesディレクトリの直下にあるディレクトリ(この場合はcommon)を指定すると、roles/tasks/main.ymlとroles/vars/main.ymlが自動的にincludeされます。
それぞれのファイルの中身のうち、essential.ymlの処理に当たる箇所は以下の通りになっています。
--- # file: roles/common/tasks/main.yml - name: Install basic server pkgs apt: pkg={{ item }} force=yes update_cache=yes with_items: ${system_packages}
--- # file: roles/common/vars/main.yml system_packages: - build-essential - libsqlite3-dev - libreadline6-dev - libgdbm-dev - zlib1g-dev - libbz2-dev - sqlite3 - tk-dev - zip - python-dev - python-pip - python-setuptools - python3.2 - subversion - openjdk-7-jre-headless - nginx
一番最初の例で使ってなかった変数の機能(var)を使っているので分かりづらくなっているかもしれませんが、ここで大事なのはplaybook内でroles: xと書けば、わざわざincludeと明示的に指定しなくても以下のファイルを勝手にincludeしてくれるということです。そのため、ansible-playbook main.yml -i hosts/local -k と打って実行すると、includeのみを使用したときと同じように動作します。
- roles/x/tasks/main.yml
- roles/x/handlers/main.yml
- roles/x/vars/main.yml
後他にもroles/x/(files|templates|handlers)ディレクトリに何かファイルがあれば色々やってくれるそうですが、まだ私自身が試してないので気になる方は公式ドキュメントの説明を読んで自分で確認してみてください。
まあ、要するにRolesに関して理解すればいいのは
- playbook内で role: x と書くと
- roles/xディレクトリ配下にある特定のファイル(tasks/main.ymlなど)を自動的にincludeしてくれる!
ということです。基本的には。
今回はxディレクトリに当たる部分がcommonしかなかったですが、commonだけでなく、webserversディレクトリとかdbserversディレクトリとか自分の好きなように作れるので、それぞれサーバー毎に必要なplaybookの固まりをそれぞれのディレクトリの所定の場所に突っ込んでおけば、後はansible-playbookコマンドを使うときに指定するplaybook内に role: webserversとかrole: dbserversと書くだけで自動的にincludeされるので、自分でディレクトリ構成を考える必要も無く、記述も楽になるので大変オススメだ、ということです。
…長々と書いたせいか、理解できるように書けていない気がするのですが、もうこれ以上書くのも疲れたし分かりやすく書ける気がしないので、冒頭で紹介したリポジトリをcloneでもして実際に動かしてみるといいと思います(と宣伝)。
Ansibleはこの6/10にv1.2をリリース予定とのことなので、v1.2が来たらわざわざgithubから取ってきてインストールするなどといった面倒臭いことはしなくてすむのでよかったですね!
…よし、これでだいたい言いたいことは終わった−。
注意事項
2013/06/04 13:57現在、github上のAnsibleを使うと以下のような問題がありますので気をつけてください。
- playbookがおかれている場所のパスの中に空白文字がある時、rolesは正常に動作しません。
- バグです。
- issue登録されてます。
Ansible学習の参考になりそうな新たな記事リンク集
- https://bitbucket.org/r_rudi/ansible-test
- An example of provisioning and deployment with Ansible - Stavros' Stuff
- Ansibleを使った構成管理とデプロイのベストプラクティス的な例。非常に為になりますよ。英語ですけどね!!
- http://ansible.cc/docs/playbooks.html
- http://ansible.cc/docs/playbooks2.html
- http://ansible.cc/docs/bestpractices.html
- 公式のドキュメント。英語なので読むのが面倒ですが、最初から丹念に読んでいけばかなりのことが分かります。特に一番下のベストプラクティスは目を通しておくといいと思います。
以上です。書くの疲れました。