Subscribed unsubscribe Subscribe Subscribe

Goodbye Plain Old Chef Repository

pfcasualで仕入れたネタをもとに、Chef環境を刷新したので、忘れないうちにメモしておく。

そもそもの問題意識は、

  • 現状のcookbookにテストが全くないこと
  • テストの欠落が原因でcookbookの変更に対して億劫になってしまっていること
  • Chefの理解・テストの欠落・煩雑な手順によりThe Lone Wolf Chefになってしまっていること

を解決したかった。

方針としてはChefConf 2013: Beginner Chef Antipatternsを参考にすることにした。

  • いわゆるchef-repo *1はやめてcookbookごとにリポジトリを分ける
  • Chefは最新の11にする
  • 各人のworkstationにChefでChefのcookbook開発に必要な環境を整備する
  • Chefのワークフローを決めたかったのでEtsyのknife-sporkを使うことにした。
    • pfcasualで @sethvargo さんが教えてくれたもの
    • environmentsの編集には、これも @sethvargo さんが使ってたknife-flipを使う。

などなど。

大まかなワークフローはこんな感じ。

cookbookの新規作成・編集は

  1. berks cookbook $cookbook --foodcritic --chef-minitest
  2. gitリポジトリも作っておく
  3. cookbookとテストを書いたらvagrant up/provisionでローカルマシンでテスト
  4. 必要であればknife spork bump $cookbookでバージョン番号を上げる
  5. git push
  6. 良さそうならknife spork upload $cookbookでサーバにアップロード
  7. knife spork promote development $cookbook --remoteでchef_environment:developで先ほどアップロードした$cookbookが使えるようにする
  8. knife node flip $node developmentで$nodeのenvironmentをdevelopmentにして$cookbookが反映されるようにする
  9. 問題無さそうならknife spork promote production $cookbook --remote
  10. environmentsのリポジトリが更新されているのでこちらもgit push

nodeの作成はコマンド一発で済む。

  1. knife bootstrap -x --sudo -r "recipe[$recipe]" -d chef-full -E production

chef-fullというのがいわゆるomnibusインストーラ。特別に理由がなければこれを使うのが楽で良いと思う。

cookbookの構成について

cookbookの構成をどうするかはコミュニティ内でも意見の分かれるところだと思う。これはChefの制限によるものが大きい。

たとえばBerkshelfの中の人に言わせてみれば、Chefのcookbookを束ねるroleは使うべきでない。なぜならroleはcookbookと違いバージョン管理されてないからである。この主張はenviornmentを利用し始めれば理解できる。environmentごとにcookbookのバージョンを指定することができても、roleにはバージョンがついてないため、developmentのみこのcookbookを適用したいみたいなことができない。

ではどうするかというと、roleと同じことをするcookbookを作ることになる。Chefのcookbookは元々boilerplateが多い上にBerkshelfの設定ファイルやVagrantの設定ファイルを置く必要があり、ある程度自動生成されるにしても面倒なことには変わりない。

今回移行したcookbookは結局こんな感じの構成になった。

  • application cookbooks: 一番トップレベルで使うcookbook。app-*という名前にしている。以前のroleに対応するもの。recipe自体は適切なattributesを設定して、あとはinclude_recipeするだけのものが多い。
  • wrapper cookbooks: community cookbookに少し手を加えたいときに作るcookbook。wrap-*という名前。たとえばあるcookbookのtemplateがいけてないので、そこだけ差し替えたり、決めうちでよいattributesを設定するために作る。
  • library cookbooks: community cookbookに無いものはlibrary cookbookとして作る。
  • 会社固有のcookbookは$company-*な名前

こんな感じでいま30個くらいのcookbookがある。

attributes周りの面倒

Chefのattributesは柔軟なcookbookを書くために役に立つが、複雑で間違いを起こしやすい。

いろいろ文句はあるのだけど書くのが面倒なので、About Attribute Files — Chef DocsのAttribute Precedenceを見れば複雑であることは伝わると思う。

それだけではあれなのでtipsを2つほど。

  • recipe中にpp node.debug_value(:key1, :key2, ...)と書くと、precedenceごとにattributesがどうセットされているかわかる
  • recipe attributesは、attribute fileなどと同様にrecipe適用前に構築されると思いきや、recipe内の順序に依存しているので、そのattributeを使う部分より前にセットする必要がある。
    • 使う部分より後でattributeを変更すると、Chef Serverのnode情報には正しい値が見えるのに、recipe適用時には反映されてないやっかいなバグの元になる。

その他

  • CIの設定はまだしてないのでやりたい
  • 一部大事なホストでserverspecなどを使ってテストしたいなと思っている
  • ChefもBerkshelfも結構バギーかつ複雑だったりするので、今後すごくシンプルなツールがはやる可能性もあるなと思う
  • わからないことはfreenodeの#chefでUSが起きてる時間帯に聞こう

The Lone Wolf Chef問題については、やっと準備ができてこれから皆に使ってもらおうという段階。うまくいくと良いな。

参考資料

pfcasualで教えてもらったChefConf 2013のBeginner Chef Antipatternsは大まかな方針を決めるときに役立つ。ただしすべてを鵜呑みにする必要はなくて、適宜自分の目的に合わせて解釈するのがよいと思う。

BerkshelfについてはThe Berkshelf Way - Jamie Winsorを見れば使い方はわかるだろう。

*1:Plain Old Chef Repository; POCRとでもしよう。読みにくい。