FLINTERS Engineer's Blog

FLINTERSのエンジニアによる技術ブログ

複数プロジェクトをChefで運用管理するための独自ルール

みなさま2015年あけましておめでとうございます!

私の会社でchefを本格的に導入しよう!と決めてから、色々と悩んで悩んで右往左往してましたが、ようやく形になってきました。
いやーここまで来るのに本当に寄り道しまくりました…。
現状、社内でも共有しきれていませんが2,3プロジェクトをこの方法で管理運用しています。
そこで、社内でも共有する資料作りと平行してこちらにも情報を公開してみたいと思います!

前提

  • 一つの会社の中に複数のプロジェクト(以降PJ)がある
  • chefのrecipeは一人以上の複数名で書ける
  • 全社的にchef使おうぜー
  • Private Git repositoryを既に運用している
  • The Environment Cookbook Patternをさらっと読んで、総論賛成各論反対!そのまんま適用は無理!と思った

基本となる考え方とかをしっかり理解したい方は上や下のリンクを読んでください。
細かい説明はすっ飛ばして、それでも分かるように極力気をつけますので。


ちゃんと元ネタを理解したい人用リンク

以下に日本語で解説してくれてるサイトがあります!
大規模にchefを使い倒すためのcookbook pattern
Chef Cookbook の管理方針、The Environment Cookbook Pattern について

ざっくりとした全体像

  • knife solo + berkshelf
  • chefのroleは使わない
  • site-cookbookも使わない
  • depends(metadata.rb)からのinclude_recipe!
  • berks-api使ってます(が、chef-serverの方がいいのかもしれないが脳内停止中)

cookbookの種類

Cookbookは以下の命名規則に沿ってリポジトリに登録するようにしました。

名前 利用範囲 命名規則 概要
Library cookbook 全体 lib- LWRPを作る(中上級者用)
App cookbook 全体 app- アプリケーションをインストールする
Company cookbook 全体 <会社名> 全社共通の設定とか
Project base cookbook Pj毎 [PJ]-base Project共通の設定とか
Project wrapper cookbook Pj毎 [PJ]-wrap Project用のラッパー
Project env cookbook PJ毎 [PJ]-env PJ用のRoleみたいなもの
Community cookbook 全世界 - https://supermarket.chef.io/

上記のうち、LibraryについてはLWRPを使う前提なので、それ以外についてもう少し詳細に説明します。

App cookbook

Appは複数PJで使う前提なので、単体で動くことを最優先にします。
また、Appは1cookbookで1アプリケーションです。(例:app-httpd, app-nginx, app-mysql56)
つまり、include_recipeでそれを読みこめば、とりあえず動く。
この「とりあえず」というのがちょっとミソで、httpdなら本当にrpmインストールして終わりレベルだったりしますが、その他個別にある程度設定を入れてたりします。
あとはちょっとした設定とかはここに作っちゃったりしてます。(EC2用のapp-amznlinux-swaponとか)
個人的には、このapp-cookbookが充実して後述するwrapperであまり色々やらなくても、attributesやdata_bagsをよしなにやるだけで環境構築できるようになるのが一番いいと思ってます。

Company cookbook

会社共通のパッケージとか設定とかとりあえずぶっこんでます。
dstatとかvimとかvimとか。

Project base cookbook

CompanyてほどじゃないけどPJでは共通で使うよ、というのはこちらに逃してます。
例えばrpmでlibxxxをインストール!とかそういうのは一々App cookbookを作るのが面倒なのでこっちで一括インストールしてます。

Project wrapper cookbook

これが各PJで一番触るcookbookです。
App-cookbookやcommunity-cookbookをincludeして、設定とかサービスの上げ下げとかをここに一気に書きます。
どっかではベストプラクティスでwrapperも分けろ的な話が出てましたが、そしたらもう腐るほど増えそうだったのでPJ毎にまとめました。
各App毎にrecipeを分けて作ります。
(例:pj-wrap::httpd, pj-wrap::nginx, pj-wrap::mysql)

Project env cookbook

ChefのRole的な役割をします。nodesファイルに書くのはこのenv cookbookだけにしています。
ここでwrapper,app,community,base,companyなどなど上で上げたcookbookをただただinclude_recipeするrecipeを書きます。
(例:pj-env::common, pj-env::web, pj-env::batch)

よくある議論:community cookbookは使うべき?

私は基本的には使うのは賛成ですかね。何やってるか(読まないと)よくわからないし、無駄なことも多いけど、それ以上のメリットが有ります。
ただ、簡単なものは極力自分で書いたほうが勉強にもなるから、本家を見ながらわかりやすくパッケージングしたりすることもあります。
自社開発だとdistributionも限られてるだろうからそんなに大変じゃないです。
後はcommunity cookbookの実装方法が気に食わないとか。例えばこれ

berks-api

berks-apiがメジャーかどうかはよく分かりませんが、metadata.rbと同様のtagをつける以上のメリットがあると思ったので導入してみました。
berks-apiについてはこことかここに情報があります。
なお、Atlassian stash用のプラグインがなかったので、それは自作しました。そのうち公開…。
これを使うとmetadataのversion(と、git tag)で各cookbookのバージョン管理ができるので、最初の手間と理解の壁を超えると凄くわかりやすくなると思います。

このやり方でのメリット、デメリット

※以下のメリット・デメリットがありますが、デメリットについてはある程度自動化したりして吸収出来ちゃうので、今のところこれで行くつもりです。

メリット

cookbookの再活用がとても捗るし、cookbookを改良した時に他のPJに適用するのもすごく楽。

デメリット

  • 立ち上げ時には全体を理解し切るまで結構苦労する。
  • これはどのcookbookに入れよう…という迷いがたまに発生。
  • ちょっと設定ファイルをいじったりするのにも手間が割とかかる。でもこれはchefというよりberks-api依存。

ひとまずまとめ、と次回へ続く…

ここまでで、とりあえず「どんなルール」で進めてるかというのは書けたと思います。
ただ、これだとよくわからないので、次回は具体的にどうやって進めるのよ、というのを書きます。
ということでつまりは次回が本番です、きっと。

その他参考サイト

以下のサイトを超参考にさせて頂きました!
Goodbye Plain Old Chef Repository

あと、コレも定番?ですが、一通り見ておくといいと思います!
[和訳] 初心者Chefアンチパターン by Julian Dunn #opschef_ja

Qiita原文

Qiitaの自己投稿の転載になります。
Qiitaの記事はコチラ→http://qiita.com/sagehash/items/3f99f091e5c304467587