2014/05/22

Ansibleのファイルとディレクトリ管理

冬ぐらいからAnsibleを触りだして、春ぐらいにはいろいろとPlaybookを書いて実戦投入するようになり、夏ぐらいには新しく作るサーバは全部Ansibleで構成出来るようになるかなぁというところまで来ています。

PlaybookはBest Practicesに従ってなるべくRoleに切り出して書いて、ansible-playbookコマンドの引数となるファイルで、各Roleを実行する順序で並べて構成しています。

ただ、Roleに分けたファイルはBest Practicesに従ったディレクトリ構造に収まるので良いのですが、それよりも上をどういうディレクトリ構造で管理しようか、という点で冬から春にかけていろいろ試行錯誤をしていて、最近やっと自分の中で固まってきた気がするので、ブログにでも書いておこうかと思います。

2015/09/30(水)追記: この記事は古くなりました。もう少し改良したディレクトリ構造とServerspecとの共存について「AnsibleとServerspecでインベントリファイルを共通化した」を書いていますので、そちらをご覧ください。

~/var/rhosts

安易に~/var/rhostsというディレクトリを作って、そこにサイトのドメイン名ディレクトリを作っています。更にその中に、サーバの役割別にディレクトリを作る事もあります。
~/var/rhosts
├── azumakuniyuki.org/
│   ├── .gitignore     ←リポジトリに入れないもの
│   ├── .vagrant/      ←砂箱としてつかうVagrant
│   ├── Makefile       ←makeコマンドでいろいろ便利に
│   ├── Vagrantfile    ←砂箱として使う仮想マシンの為に
│   ├── ansible/
│   │   ├── config          ←~/.ansible.cfgを上書きする用
│   │   ├── develop         ←開発サーバだけ書いたインベントリファイル
│   │   ├── hosts           ←砂箱(Vagrant)マシンだけ書いた〃
│   │   ├── log             ←ansible.cfgで指定したログファイル
│   │   ├── make-server.yml ←ansible-playbookコマンドで実行するファイル
│   │   ├── product         ←本番環境用のインベントリファイル
│   │   ├── roles/
│   │   │   ├── apache/
│   │   │   ├── common/
│   │   │   ├── cpanm/
│   │   │   ├── dovecot/
│   │   │   ├── mailman/
│   │   │   ├── mysql-5.5/
│   │   │   ├── nginx/
│   │   │   ├── opensmtpd/
│   │   │   ├── openssh/
│   │   │   ├── perl/
│   │   │   ├── php-5.3/
│   │   │   ├── postgresql/
│   │   │   ├── sendmail/
│   │   │   └── vsftpd/
│   │   └── staging
│   └── ansible.cfg -> ./ansible/config
├── haineko.org/
│   ├── smtpd.haineko.org/
│   │  ├── .gitignore
│   │  ├── .vagrant/
│   │  ├── Makefile
│   │  ├── Vagrantfile
│   │  ├── ansible/
│   │  └── ansible.cfg -> ./ansible/config
│   └── www.haineko.org/
Ansibleに関係するファイルは全部ansible/ディレクトリの中に入れて、外にはVagrant関係のファイルやマウントポイント用ディレクトリ、まだ使ってないですがserverspec用のファイルかディレクトリを置く事にしています。

Makefile

新しくサーバを作る時や既存のサーバをAnsibleで構成出来るようにする時、上記のようなディレクトリ構造を作ったり、Vagrantの準備をしたり、そういった雑事をmakeコマンド一発で出来るようにMakefileを作りました。Makefileは~/var/rhosts/make-serverというディレクトリにマスターデータとなるものがあって、そこから毎回コピーしています。

Ansibleでnginxを構成するRoleを追加する時は、make nginx-roleを実行すればansible/roles/nginx以下にディレクトリ構造が作られて、必要なファイルがコピーされるようにMakefileにターゲットを書きました。

Vagrantfile

予めよく使う仮想マインイメージのboxを用意しているので、make centos65-x86_64-box とかで砂箱用の仮想マシンが作られるようにしています。

多分デフォルトで割り当てられる、というかよく見かけるVagrantfileに書いてある192.168.33.*のIPアドレスが自宅のものと被ったので、別のプライベートIPアドレス/16の範囲からランダムにIPアドレスを決定(Makefileで)し、Vagrantfileを作るようにしました。
$ mkdir -p ~/var/rhosts/example.org⏎
$ cd ~/var/rhosts/example.org
$ cp ../make-server/Makefile ./
$ make list⏎
vagrant box list
centos56-i386    (virtualbox)
centos64-x86_64  (virtualbox)
centos65-x86_64  (virtualbox)
freebsd92-i386   (virtualbox)
openbsd53-x86_64 (virtualbox)

$ make freebsd92-i386-box⏎
if [ ! -f "./Vagrantfile" ]; then \
  vagrant init freebsd92-i386 ;\
  X="`perl -lE 'print int(rand(250)) + 2'`" ;\
  Y="`perl -lE 'print int(rand(250)) + 2'`" ;\
  cat ~/var/rhosts/make-server/Vagrantfile | sed \
   -e 's/__HOSTNAME__/vm.example.org/g' \
   -e "s/__IPV4ADDRESS__/172.25.$X.$Y/g" \
   -e 's/__VIRTUALBOX__/freebsd92-i386/g' > ./Vagrantfile ;\
 fi
A `Vagrantfile` has been placed in this directory. You are now
ready to `vagrant up` your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on
`vagrantup.com` for more information on using Vagrant.
mkdir -p ./data

$ make up⏎
vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'freebsd92-i386'...
Progress: 20%

ansible/以下のファイル

インベントリファイル

~/.ansible.cfgで引数を指定しなかった場合のインベントリファイルを./ansible/hostsとしています。うっかり事故防止の為に、ansible/hostsにはMakefileから作った仮想マシンのホストのみを書いています。それ以外のインベントリファイルは、開発環境(develop)・ステージングサーバ(staging)・本番環境(product)とファイルを分けて、必ず-iオプションで実行時に指定する感じの安全対策です。
  • hosts Vagrantfileに書いてあるIPアドレスをvmというホスト名で定義してるだけ
  • develop 開発サーバを列挙する
  • staging ステージングサーバを列挙する
  • product 本番サーバを列挙する

設定ファイル(ansible.cfg)

./ansible/configを実体として、ansible.cfgという名前でリンクを作っています。~/.ansible.cfgの内容を上書きしたい時に使う為で、例えば対象サーバによってはsudo実行時にパスワードが要るとか、このサーバはSSH pipeliningが使えるとか、そういう僅かな違いへの対応を、実行時のコマンドラインオプションでやるのが面倒なので対象サーバに合わせて設定ファイルを使う事にしています。

make-server.yml

ansible-playbookコマンドで実行するPlaybookです。中身は実行するroleを列挙しているだけのものです。他に各サーバでuptimeだけ実行するexec-uptime.ymlとか、毎回ansible -m shell -a "uptime"とかやるのが面倒でよく使うものをPlaybookにして置いています。

roles/

仕事では圧倒的にCentOSを扱う(指定される)ことが多いので、yumで入れる場合は設定ファイルをテンプレートから作る程度の事と他細々したタスクをroles/nginx/tasks/main.ymlに全部書いているのですが、ソースビルドする時のタスクを全部main.ymlに書くと長すぎて見通しが悪いので、適当に分割したものをmain.ymlからincludeしています。

vars/main.yml

環境によって変化しそうな、そうでもないような値を変数として定義しています。Best Practicesに書いてあったgroup_vars/とかは``_''が気に入らないので使っていません。あと、ドキュメントで確認したわけではありませんが、変数のスコープはhosts:で指定した範囲内でグローバルな感じです。

tasks/install-pkg.yml

例えばnginxをソースビルドするroleなら、pcre-develあたりをyumでaptで(libpcre3-dev)入れるといったタスクを書いています。コンパイルに必要なgccやautoconfとか、そういったパッケージはroles/common/tasks/install-pkg.ymlで入れる事にしています。

tasks/create-user.yml

Apacheならhttpdというユーザを、OpenSMTPDなら_smtpdと_smtpqというユーザを確認して無ければ作るタスクを書いています。作るべきユーザの一覧はvars/main.ymlで定義している(apacheでもhttpdでも設定ファイルで実行ユーザを指定出来る)事もあれば、このファイルに直接書いている(OpenSMTPDなら_smtpdという名前が固定されている)事もあります。

tasks/get-archive.yml

ソースビルドする為のアーカイブファイルを取ってきて展開だけしています。必要であればパッチファイルも取ってきたりします。

tasks/compile-src.yml

configureしたりMySQLならcmakeしたり、makeしてmake installするとこまでのタスクを書いています。このファイルの処理は殆どがshellモジュールによる実行なので、冪等とか考えて、Makefileがあったらconfigureのタスクは実行しない、コンパイル済バイナリがあったらmakeのタスクは実行しない、makeのタスクがchangedになった場合だけmake installのタスクを実行する、とかでなんとかしのいでいます。

tasks/make-config.yml

コンパイルしたものがインストールされた後に、設定ファイルをデプロイしたり、ログのローテーション設定をしたり、細々とした雑事をこなすタスクを書いています。

tasks/boot-script.yml

yumで入れたやつは最初から/etc/init.dに便利な起動スクリプトが入るのですが、ソースから入れたやつは自分で用意するか、/etc/rc.localに起動コマンドを書く必要があります。仕事で扱うのがRedHat系ばかりなので未だRedHat用のやつしかテンプレートにおいていないですが、起動スクリプトを/etc/init.d/にデプロイして、/etc/rc.d/init.d/以下にリンクを作るタスクを書いています。

templates/とfiles/

設定ファイルの元となるファイルを置いています。最初はこれらのディレクトリ直下に置いていたのですが、なるべく深くならない程度に、実際にサーバに置かれる位置に合わせてテンプレート(templates)やコピーするだけのファイル(files)を置く事にしました。

例えば、起動スクリプトならtemplates/etc/init.d/nginx.RedHat.j2ってファイル名で置きます。"RedHat"という文字列は、ansible_os_familyで得られるものに合わせています、将来Debian系の処理を同じPlaybookに書く時のために。

ファイルの管理とディレクトリ構造

ファイルの管理については、三月ごろにようやく今の形になって、それからディレクトリ構造も殆ど変更していないので、今のところは「これでいいか」と思っています。誰が考えても同じような構造になると思うので、特段ブログで「こうしています」って書くほどの事でもない気がしますが、自分がファイル管理やディレクトリ構成をどうするか考える時に、誰か何か書いてないか検索したので、書いておこうかと。

かんそう

自社のサーバ以外にもお客さんのサーバを作ったり管理したりする事もあるので、chefで統一するのは難しそう、と思っていたところでAnsibleを知りました。Ansibleは比較的新しいサーバであればansibleはSSHで繋いでsudoが出来れば殆どの事が出来るので、導入に対するハードルは低いですし、かなり良いソフトウェアという感想です。

ただ、使用するモジュールによっては実行される側にPythonのモジュールが入っている必要がある事が前提です。例えばmysql_dbモジュールやs3モジュールは、それようのPythonモジュールが要りますので、SSHさえ繋がればOKってわけでもない部分があります。しかし、shellモジュールやpipモジュールが使えるのであれば、Playbookの中で必要とされるモジュールを入れる事も出来るので、やはりクライアントが被構成側で稼働していなければならない構成管理ツールよりは楽です。

面倒くさいところと言えば最初のPlaybookを作る辺りぐらいで、仮想マシンを対象にデバッグしつつ、一度完成してしまえば構成対象に合わせて、あるいは変化に合わせて内容を変更すれば良いだけですので、開発に慣れているのであれば特に苦痛でもないでしょう。

Ansible, かなり良いです。

0 件のコメント:

コメントを投稿