自分のevernoteを見返すと3年前からchefを使っているようだ。当初からchef server構成を使っていたため、冗長化の方法に何かと頭を悩ましてきた。個人で使う分にはそれほど更新頻度は高くないので、定期的にrsyncしていれば何とかなるのだが、それでも切替のときには一旦止めてreconfigureして再起動のようなコールドスタンバイくらいしか方法がなかった。また、chef server上ではelastics searchやpostgresqlなど、多くのミドルウェアが動いてしまうため、独立ノードで使う事になってしまう。貧弱なクラウド環境での動作は性能的にイマイチなので、クラウド環境と自宅環境をopenvpnで繋いで、自宅でchef serverを動かす形を取っていた。
この構成を見直すきっかけとなったのがglusterfsを使い始めた事。glusterfsの冗長性を利用して、glusterfs上にlxcコンテナを作成、そこでchef serverを動かす事を考えた。しかし、glusterfsはfile open処理が非常に遅く、やたらとファイルにアクセスするchefの処理をglusterfs上で動かすのは非現実的だった。straceしてみればわかるのだが、万単位のファイルにアクセスしてしまうため、knifeの処理ですら30秒前後かかってしまう。だらだらとchefを使い続けてきたが、今やchef serverを使うためにインフラが振り回されている事に気が付いた。dockerのときと同様に無理してまで使うのを見直してもいいかもしれない。
glusterfsの利用開始はいろいろな面でインフラの在り方を見直すよいきっかけとなった。というのも、ファイルシステムレベルであらゆるデータの冗長性を保証してくれるため、個々のミドルウェアでの冗長化を考慮しなくてよくなったのだ。chefで作ってきたレシピたちも複雑なロジックの大半がマスター/スレーブの管理や障害時の昇格処理などだった。特に冗長性が担保されない場合は、rsyncやlsyncを駆使してSPOFをなくしていたために、ノード間の関係性が複雑化して昇格作業が実質不可能に近い状態だった。glusterfsの利用でそれらのロジックを取り去った結果、どれだけレシピがシンプルになったことやら。
構成管理ツールの利用が標準化する昨今、だから複雑な構成を利用可能と考えるよりはレシピをシンプルに維持するために、いかに各ノードの構造を平易にしていくかが重要だろう。以前はmysqlも慣れ親しんだマスター/スレーブで運用する方が楽と思っていたが、マルチマスターで全てのノードを同一にする方が構成管理上極めて有利と考えるようになった。以上の流れで、冗長性の担保が複雑なchef serverも見限る事を決意した。代わりとなる構成管理ツールはそれほど選択肢はなく、最初に思い浮かんだのがansibleだった。
利用開始はchefに比べれば遥かにハードルが低く、yum install ansibleして/etc/ansible/hostsに検証用のホスト名を幾つか書いたら、もう使い始める事が出来た。/etc/ansible配下にhostsファイルやtaskファイルさえあれば、どこでもansibleを動かす事ができるので、最もchef serverで悩んでいた点はあっさりと解消した。あとはchefで書いてきたレシピたちをansibleのplaybookに移植できるかどうか。
どうせ大した事やってないしとタカをくくっていたが、さすがに3年もあれやこれやとレシピを書いていると思ったよりもボリュームもあるし、ロジックも複雑。今回はあらゆるデータモデルを出来る限りマルチマスターな構成に切り替えるつもりなので、その書き直しも含めて1つ1つ修正していった。現時点で書き終わったレシピをまとめると以下。
- lxc
- apcupsd マスタースレーブ構成
- grub
- firewalld
- glusterd
- bind マルチマスターに変更
- dhcpd マスタースレーブ構成
- nginx
- openvpn
- kickstart glusterfsにて冗長化
- yumリポジトリ glusterfsにて冗長化
- gitリポジトリ glusterfsにて冗長化
- samba glusterfsにてマルチマスター
- minidlna glusterfsにてマルチマスター
ansibleはchefと違ってpush型の通信なので、必要なノードに対して横断的に変更を適用する事が出来る。bindなどは全てのマスターを同時変更する運用にして、スレーブをなくす事にした。yumリポジトリやgitリポジトリもそれぞれの機能でコピーを作っていたが、これももうglusterfs上に1つリポジトリを作るだけにした。オペミスまではカバー出来ないけど。
そして肝心のplaybook、当初はansibleの表現力が不安で複雑な処理を移植しきれないかとも思ったが意外と何とかなった。例えばbindのzoneファイルは任意のホストグループから自動生成して、変化があればSOAのserialを当日、あるいは既に当日の場合はインクリメントして更新みたいなこともtaskにする事ができた。また、処理の順序や変数の範囲も非常にわかり易い。順序や変数が期待通りにならない処理に悩むような事は今のところ皆無だ。移植に際して苦労した点を幾つか挙げてみる。
- dict(ハッシュ)でキー値に変数を使えないため、構造体の定義方法に苦しんだ
- 条件分岐でtask数が冗長気味になってしまうのが好みではない
- 各ノードの情報収集をするgagher_facts処理の高速化に時間を取られた
と、いろいろ苦労した点もあるが、肝心のコード自体はchefより遥かにきれいに感じている。というより、どんなに努力しても自分にはchefのレシピをきれいに書く事が出来なかった。今回、OSごとの処理分岐追加を考えたとき、もうchefで書くのはないなあと思った。結論としては、以下の点で運用の自由度を確保する事が出来た。
- hostsとplaybookファイルさえあればどのサーバでも運用可能
- sshさえ繋がればどのクライアントに対しても処理可能
- サーバ側のリソース不要なので貧弱なクラウド環境でも動作可能
- 任意の並列度で横断的に変更を適用出来るのでデプロイとしても利用可能
しかし、移植に要した時間は非常に問題。ansibleの学習も必要だったとはいえ、相当な時間がかかっている。しかもまだ半分くらいしか終わっていないし。個人的には、それでも移行してよかった点の方が大きいとは考えている。。。が、早く他のことしたいな。