【git】社内のChefリポジトリをgit subtreeで利用する

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

こんにちは植木和樹です。クラスメソッドではOSやミドルウェアの設定にchef(chef-solo)を頻繁に利用しています。chefを利用するようになって約1年。その間に多くの(本当に!)プロジェクトの構築を行ってきました。

多くの構築を経験していると、ある程度のパターンというか定石がでてきます。例えばApacheをインストール/設定するにしても、

  • KeepAliveはOnにする
  • TimeOutは120秒(かそれ以上)にする
  • ELBからのヘルスチェックはアクセスログに記録しない
  • 案件ごとに異なる設定は /etc/httpd/conf.d に入れてRoleやNodeで指定できるようにする

などです。

そうなると「クラメソ社内Chefリポジトリの整備が必要だよね〜」という話が当然でてきます。そして大瀧さんや望月さんの努力の結果、いい感じにChefリポジトリが整備されてきました。

本日はクラスメソッド社内向けの資料ですが、もし社内用Chefリポジトリを運用されている方の参考になればと思い公開させていただきました。

git submodule と git subtree

submoduleとsubtreeの違い

「Atlassian Stashで管理しているクラスメソッド社内向け共用Chefリポジトリ」というのは長いので以降「共用リポジトリ」というようにします。

案件ごとのgitリポジトリに、共用リポジトリを取り込むには2つの方法があります。git submoduleを使うかgit subtreeを使うかです。submoduleとsubtreeの違いはいろいろあるようですが、一言でまとめると次のようになります。

git submodule
共用リポジトリ内のファイルを案件リポジトリに取り込まない。(ポインタ管理)
git subtree
共用リポジトリ内のファイルを案件リポジトリに取り込む。(実体管理)

共用リポジトリの使い方として「典型的なテンプレートは共用リポジトリから流用したいけど、案件固有の修正は自由にしたいよね」を考えています。そのためsubmoduleよりもsubtreeの方が適していると考えました。

◎参考

なぜ共用リポジトリもgitで管理したいのか

単に共用リポジトリにあるクックブックを流用するだけなら、適当な場所にcloneしてファイルだけ案件リポジトリにコピーすればいいのではという意見もあるかと思います。

しかし仕掛中の案件で共通化できそうなパターンに気づいたり、元々のテンプレートに修正を行いたい場合などは、コピー方式だとフィードバックが面倒です。改めて共用リポジトリからcloneして、仕掛中案件での差分を抽出し、手マージして、pushしなければならないためです。手順が煩雑だとフィードバックも期待できません。

ということで、効率よく過去の知見をテンプレートとして再利用しつつ、フィードバックもやりやすい git subtreeを使うことにしました。

git subtreeを使ってみる

共用リポジトリを案件リポジトリに取り込む

取り込みは簡単です。git subtree addで対象のリポジトリを、ローカルのサブディレクトリにcloneするだけです。なおgit subtreeコマンドはローカルリポジトリのトップディレクトリ(.gitがあるディレクトリ)でないと実行できませんので注意してください。

大瀧さんがAmazon EC2(Linux)のswap自動作成を行うRPMパッケージ ec2-swap を作ってみた | Developers.IOで紹介したスワップ設定作業をChef Cookbookにして共用リポジトリに入れてくれてます(感謝!)。これを取り込んでみましょう。

$ cd $WORKDIR
$ git remote add ec2-swap ssh://git@stash.example.com/awschef/ec2-swap.git
$ git subtree add --prefix chef/st-cookbooks/ec2-swap ec2-swap master --squash

まず最初にgit remote addでリモートリポジトリに別名(ec2-swap)をつけます。

次にgit subtree addコマンドでec2-swapリポジトリをchef/st-cookbooks/ec2-swapディレクトリに取り込みました。(--squashをつけ過去の履歴は取り込まないようにしています。)

なおChefリポジトリのディレクトリ構成は以下のようにして区別しています。

cookbooks
Berkshelfで取得したコミュニティクックブックの置き場。(変更不可)
site-cookbooks
案件独自に作成したクックブックの置き場。
st-cookbooks
git subtreeで取得した共用クックブックの置き場。

knifeの設定ファイルにcookboos_pathを設定するのを忘れないようにしましょう。

.chef/knife.rb

cookbook_path    ["cookbooks", "site-cookbooks", "st-cookbooks"]

共用リポジトリのクックブックをsubtreeで取り込んでしまえば、あとは自分で作成したクックブックと違いはありません。改修/改変ご自由に。

共用リポジトリへフィードバックをpushする

共用リポジトリのクックブックに手元の改修をフィードバックしたい時の手順です。クラスメソッドではgitリポジトリにStashを使っているで、別ブランチに変更をpushした後Pullリクエストをリポジトリ担当者に送りましょう。

単純にgit pushしてしまうと、subtreeで取得したディレクトリだけでなく案件リポジトリ全体をpushしてしまうので気をつけましょう。

まずgit subtree splitして、ブランチ(addMemoryUsageCrontab)を切ります。

$ git subtree split --prefix chef/st-cookbooks/hoot24 -b addMemoryUsageCrontab

次にgit subtree pushで共用リポジトリ(hoot24)にブランチを作成してローカルの変更を反映します。

$ git subtree push --prefix chef/st-cookbooks/hoot24 hoot24 addMemoryUsageCrontab

この後Stashの画面からPullリクエストを作成しましょう。

まとめ

gitを使った社内Chefリポジトリの利用方法をご紹介しました。社内の有力者のみなさんがChefクックブックをガシガシ作成してはリポジトリにあげてくれているので、環境構築がだんだんと楽になってます。大変ありがたいです。

ミドルウェアのインストールをChefで行いたい場合は、ひとまずコミュニティクックブックを探して、なければ社内共用リポジトリを探しましょう。それでもなければ自分でクックブックを作成して、共用リポジトリにあげてもらえるとみんなが幸せになれると思います。