Knife-Zero まとめ

前回のData Bagの記事に加え、サーバー構成管理ツールKnife-Zeroおよび関連ツールの使い方を備忘録として記します。 なおRecipeの書き方については今回割愛させていただきます。

Knife-Zeroについて

Chef-Serverなどを介さずに直接サーバーにChefのインストール、Cookbook(サーバーをよしなにセットアップしてくれるやつ)を実行してくれるものです。素でChefを使うよりも楽に管理できると先輩氏から聞いています。

www.atmarkit.co.jp

弊社のサーバー構成管理ツール群の中でのKnife-Zeroの立ち位置は以下となります。

  1. CapistranoRailsの管理
  2. Knife-Zero…AWSで定義したサーバーの中で動くソフトウェア(nginxなど)の管理
  3. Terraform…AWSの管理

Knife-Zero基本コマンド

リモートサーバーの追加

~/.ssh/configを編集し対象のサーバーにアクセスできるようにした状態で、

bundle exec knife zero bootstrap -N [ノード名] -x [SSHのユーザー名] --sudo [SSHのサーバー名]
  • -N…Knife-Zero管理するノード名
  • -x…Knife-Zero実行時にSSHするときのユーザー名
  • --sudo…Knife-Zeroのbootstrapをsudoで実行する

もろもろファイルがつくられるので、バージョン管理できます。

knife bootstrap — Chef Docs

Cookbook追加

CookbookはChefで実際にサーバーのセットアップをしてくれるRecipeなどがまとまったものです。Coookbookの中にはRecipeの他に、セットアップに必要なnginx.confなどのファイルなども管理されています。

例: Server1というCookbookがあり、中にはnginx, td-agentという使うソフトウェアをひとつひとつセットアップするRecipeがある

bundle exec knife cookbook create [Cookbook名] -o [作成先のPATH]

作成先のPATHはbootstrap後にできるknife.rbにデフォルト値を指定することもできます。

About Cookbooks — Chef Docs

Cookbookの設定

Berkshelfによる依存性解決

Bundlerみたいな形で、Cookbook毎に依存性を解決できるツールです。

berkshelf.com

Cookbook内で依存性を記述した後、berks vendorコマンドで依存性解決してくれます。

ただし、berksコマンドで色々セットアップすると、Thorfile, Vagrantfileなど用途によっては不必要なファイルなどもいっぱい作られる… ただ依存性を解決してくれれば十分なので、弊社では以下のような形でつかっています。

  1. 特定のCookbookディレクトリにBerksfile(BundlerでいうGemfileみたいなもの)を作成
  2. 特定のCookbookディレクトリにあるmetadata.rbに依存性dependsを記述
  3. Berksfileに以下のようにmetadataを記述し、berks vendorでmetadata.rbに記述した依存性を解決してもらう
source "https://supermarket.getchef.com"

metadata

Berkshelfによる依存性解決コマンド

bundle exec berks vendor [Cookbook群が格納されているディレクトリPATH] -b [BerksfileのPATH]
  • -b…該当のCookbookのBerksfileを指定

なぜCookbook群が格納されているディレクトリPATHを指定してるかというと、Berkshelfのcookbook_pathはKnife-Zeroのcookbook_pathと自動で同じにはならないからです。BundlerでいうとRailsディレクトリをわざわざ指定しないといけない感じかと。

Berkshelfを使う場合、Knife-ZeroのCookbook群が格納されているディレクトリを意識して指定する必要があります。

他にもBerkshelfで引っかかるポイントとして、Recipeの内容を変更した後もberks vendorコマンドを実行しないと、サーバー先に変更が反映されません。デプロイ前にberks vendorコマンドを必ず実行するように注意する必要があります。

Recipeの設定

attributes

Chef Supermarkedt公開されているCookbookを使う際、細かな情報を指定するときに記述します。 例えばnginxのCookbookに関しては、node['nginx']['dir']node['nginx']['conf_template']などが指定できます。

About Attributes — Chef Docs

file

nginx.confなどサーバーに配置したいファイルを管理できます。 fileディレクトリは以下に配置することで、cookbook_fileでRecipe中に指定し、配置先を指定することでデプロイ先に配置されます。

cookbook_file — Chef Docs

templates

fileと似た形ですが、ERBを使い動的にファイルを生成したい場合に使います。

template — Chef Docs

パスワードなど、秘密情報のバージョン管理

Data Bagを使います。前回記事参照。

ノードへのCookbookの設定

作成したCookbookはノードに以下のコマンドでアサインする必要があります。

bundle exec knife node run_list add [ノード名] [Cookbook名] 

不必要なCookbookを削除する場合は以下

bundle exec knife node run_list remove [ノード名] "recipe[Cookbook名]"

About Run-lists — Chef Docs

デプロイ

Berkshelfを使用しているため、前述の通りberks vendorコマンドを使わないとRecipeの変更が反映されません。 そのため以下のようにしてデプロイします。

  1. 変更したCookbookに対してberks vendorを実行
  2. 変更したいノード(サーバー)に対し、knife convergeコマンドを実行
bundle exec knife zero converge name:[ノード名]

まとめ

今回Knife-Zero及び関連ツールで忘れやすいコマンド、ポイントをまとめました。あまり綺麗でないサーバー環境で、いきなりDocker化するのも難しい状況があると思います。そんなときKnife-Zeroが使える時があるかと。いろいろつまづきやすいところも多いかと思いますが、所感としてはBerkshelfをさわっているときが一番禿げそうでした。少しでもこの記事がサーバー管理者のストレス軽減につながれば幸いです。

追記: Knife-ZeroとBerkshelfを使う際の便利な設定方法

@sawanobolyさんから教えていただきました。

Cookbookマネージャと一緒に · Knife-Zero

以下のようにKnife-Zeroにbefore hookが用意されており、それを使いノード追加のbootstrapコマンド、デプロイのconvergeコマンド実行前にberks vendorを実行する方法です。

coobook_path [
  File.expand_path('../../berks-cookbooks', __FILE__)
]

knife[:before_bootstrap] = "berks vendor"
knife[:before_converge]  = "berks vendor"

## ex. under the bundler environment.
# knife[:before_bootstrap] = "bundle/chef exec berks vendor"
# knife[:before_converge]  = "bundle/chef exec berks vendor"

上記の場合、弊社のスタイルと違いKnife-Zeroを管理するディレクトリ配下に単一のBerksfileを起き、各Cookbookの依存関係を記述するスタイルになるかと思います。 ちょうどRailsディレクトリにGemfileを置く形に似ています。 以下のリンクも参考になるかと思います。

Provisioning Remote server accessible by SSH with Chef and knife-zero · GitHub

github.com

弊社のようにCookbook毎にBerksfileを用意するとCookbookごとの依存関係が明確になる良い点ありますが、上記の形で管理するとオペレーション断然楽になると思います。良い!

@sawanobolyさんありがとうございます!