Chef >

目次

基本

Chefのテスト

chef-soloを使う

  1. Chef入門は chef-solo から、という話をよく聞きますが、Chef Server を利用している場合にもテスト用途に chef-solo を活用するとよいでしょう。
  2. chef-solo、chef-clientコマンドともに、-W オプションを付加することにより、確認のための空実行(dry-run)をさせることができます。
  3. Chefのテスト環境としては、よくVagrantが紹介されていますが、環境のクローニングの速さと動作の軽快さではLinuXContainers(LXC)もおすすめです。LXCでのChefリポジトリの共有は、bindマウントにより可能です。
    $ sudo mount --bind /home/alice/chef-repo /var/lib/lxc/deb4chef/rootfs/home/alice/chef-repo

ChefSpecを使う

  • きちんと単体テストするには、ChefSpecを利用するのがおすすめです。こちらをご参照ください。

空実行(dry-run)でのdirectoryリソースエラー

  • 11.4では空実行(dry-run)時に以下のようなdirectoryリソースのエラーが発生していました(CHEF-3957)が、11.6.0-1で修正されています。
    1. FATAL: Errno::ENOENT: directory[/grid/vol/0/var] (hadoop::apache line 143) had an error: Errno::ENOENT: No such file or directory - /grid/vol/0/var

knife bootstrap、knife ssh

複数ゲートウェイの経由

  • ターゲットノードへのアクセスには以下のようなゲートウェイを経由しなければならないものと想定します。
    1. gateway.wonderland.example.com => hare.wonderland.example.com
    2. gateway.wonderland.example.com => gateway.neverland.example.com => roger.neverland.example.com
  1. -G オプションでゲートウェイを設定することも可能ですが、二つ以上のゲートウェイには対応できません。そのようなときはSSHトンネルを利用します。ゲートウェイの設定を気にする必要がなくなりますので、むしろベターな方法です。note.pngただし、Windows環境では意図通りに動作しませんので、ご注意ください。まず ~/.ssh/config を以下のように設定します。
    1. Host gw.wonderland
    2.     HostName gateway.wonderland.example.com
    3.  
    4. Host gateway.wonderland.example.com
    5.     ProxyCommand none
    6.  
    7. Host *.wonderland.example.com
    8.     ProxyCommand ssh -qax gw.wonderland nc %h %p
    9.     # OpenSSH 5.4 or later
    10.     #ProxyCommand ssh -q -W %h:%p gw.wonderland
    11.  
    12. Host gw.neverland
    13.     HostName gateway.neverland.example.com
    14.     ProxyCommand ssh -qax gw.wonderland nc %h %p
    15.     #ProxyCommand ssh -q -W %h:%p gw.wonderland
    16.  
    17. Host gateway.neverland.example.com
    18.     ProxyCommand ssh -qax gw.wonderland nc %h %p
    19.     #ProxyCommand ssh -q -W %h:%p gw.wonderland
    20.  
    21. Host *.neverland.example.com
    22.     ProxyCommand ssh -qax gw.neverland nc %h %p
    23.     #ProxyCommand ssh -q -W %h:%p gw.neverland
    24.  
    25. Host *.example.com
    26.     # Not supported by Cygwin and MinGW
    27.     ControlPath ~/.ssh/mux-%r@%h-%p
    28.     ControlMaster auto
    29.     # OpenSSH 5.6 or later
    30.     #ControlPersist yes
    31.     ControlPersist 10
  2. sshコマンドで疎通を確認します。
    $ ssh hare.wonderland.example.com
    ...
    alice@hare:~$ exit
    logout
    Shared connection to hare.wonderland.example.com closed.
    $ ssh roger.neverland.example.com
    ...
    alice@roger:~$ exit
    logout
    Shared connection to roger.neverland.example.com closed.
  3. knife bootstrap します。問題なく実行されます。
    $ knife bootstrap hare.wonderland.example.com -N hare.wonderland.example.com -x `whoami` --sudo -V
    ...
    Creating new client for hare.wonderland.example.com
    Creating new node for hare.wonderland.example.com
    ...
    Connecting to hare.wonderland.example.com
    hare.wonderland.example.com knife sudo password:
    Enter your password:
    hare.wonderland.example.com
    ...
    hare.wonderland.example.com Converging 0 resources
    hare.wonderland.example.com
    hare.wonderland.example.com Running handlers:
    hare.wonderland.example.com Running handlers complete
    hare.wonderland.example.com Chef Client finished, 0/0 resources updated in 01 seconds
    
    $ knife bootstrap roger.neverland.example.com -N roger.neverland.example.com -x `whoami` --sudo -V
    ...
    Creating new client for roger.neverland.example.com
    Creating new node for roger.neverland.example.com
    ...
    Connecting to roger.neverland.example.com
    roger.neverland.example.com knife sudo password:
    Enter your password:
    roger.neverland.example.com
    ...
    roger.neverland.example.com Converging 0 resources
    roger.neverland.example.com
    roger.neverland.example.com Running handlers:
    roger.neverland.example.com Running handlers complete
    roger.neverland.example.com Chef Client finished, 0/0 resources updated in 07 seconds
  4. knife ssh の実行も問題ありません。
    $ knife ssh name:hare.wonderland.example.com 'sudo chef-client'
    hare.wonderland.example.com knife sudo password:
    Enter your password:
    hare.wonderland.example.com
    hare.wonderland.example.com Starting Chef Client, version 12.5.1
    ...
    hare.wonderland.example.com Converging 0 resources
    hare.wonderland.example.com
    hare.wonderland.example.com Running handlers:
    hare.wonderland.example.com Running handlers complete
    hare.wonderland.example.com Chef Client finished, 0/0 resources updated in 01 seconds
    
    $ knife ssh name:roger.neverland.example.com 'sudo chef-client'
    roger.neverland.example.com knife sudo password:
    Enter your password:
    roger.neverland.example.com
    roger.neverland.example.com Starting Chef Client, version 12.5.1
    ...
    roger.neverland.example.com Converging 0 resources
    roger.neverland.example.com
    roger.neverland.example.com Running handlers:
    roger.neverland.example.com Running handlers complete
    roger.neverland.example.com Chef Client finished, 0/0 resources updated in 07 seconds

knife ssh でChefサーバ管理外のノードを指定

  1. 運用上、堅牢ではありませんが、knife sshのコマンド実行対象ノードとしてクエリに代えて -m オプションによりノード名を直接指定することができます。
    $ knife ssh -m gateway.neverland.example.com 'sudo apt-get update'
    gateway.neverland.example.com knife sudo password:
    Enter your password:
    gateway.neverland.example.com
    ...

chef-repoの管理

クックブック

サードパーティクックブックのインストール

Berkshelfを使う

  1. 独自に作成したもの以外の(依存する)クックブックについては、Berkshelf等を使ってスマートに管理するとよいでしょう。
    1. BerkshelfBerkshelf-API-Server をご参照ください。

cookbook site コマンドを使う

  1. cookbook site コマンドでOpscodeのコミュニティサイトにアップされているクックブックを管理することができます。リポジトリ管理に git を使用している場合には以下の要領でインストールすることができます。git以外の場合には、cookbook site download コマンドでtar.gzアーカイブをダウンロードしてから手動でインストールします。本質的には、外部のクックブック本体をバージョン管理システムにコミットする必要はないので、やはりBerkshelfの利用をおすすめします。
    $ knife cookbook site install java
    • インストール時のgitのブランチ
      cookbook_site_install.png

サードパーティクックブックの拡張

  • サードパーティクックブックを拡張したい場合には、ソースコードをフォークせずターゲットのリソースオブジェクトをオーバーライドします。
  1. 拡張のためのクックブックを新規に作成します。
    $ knife cookbook create <yet_another_cookbook_name>
  2. cookbooks/<yet_another_cookbook_name>/metadeta.rb: depends 指定でターゲットのクックブックのデフォルト属性をロードします。新たに必要な属性は適宜、拡張クックブックに追加します。
    1. # (...)
    2. depends '<base_cookbook_name>'
  3. cookbooks/<yet_another_cookbook_name>/attributes/default.rb: 必要に応じて、ターゲットのクックブックのデフォルト属性値を上書きし、再ロードさせます。これは、レシピの中で行なっても構いません。
    1. # デフォルト値の上書き
    2. force_default['<base_cookbook_name>']['<key>'] = 'value'
    3. ...
    4. node.from_file(run_context.resolve_attribute('<base_cookbook_name>', 'default'))
  4. cookbooks/<yet_another_cookbook_name>/recipes/extended_recipe.rb: ターゲットのレシピをインクルードし、必要なリソースオブジェクトをオーバーライドします。以下はテンプレートの例ですが、cookbook属性をオーバーライドすることにより、拡張クックブックのリソースを参照できます。
    1. include_recipe '<base_cookbook_name>::<target_recipe>'
    2.  
    3. begin
    4.   res = resources(template: '/deploy/path/to/template/file')
    5.   res.cookbook '<yet_another_cookbook_name>'
    6.  # (...)
    7. end
    8.  
    9. # (...)

同名リソースの多重定義に対する警告を回避する

  • Chefでは、同じリソースタイプで同じ名前のリソースを複数定義した場合、警告が表示されクローニングが行われます(CHEF-3694)。リソース同士の衝突を防ぐ上で好ましい仕様ですが、よく使われるパッケージやサービスの定義でもこのケースにあてはまることが少なくありません。特に、レシピやロールを複数組み合わせた場合にはそれらが顕著になります。問題のないケースでは出来る限りこの警告表示を抑止した方が望ましいでしょう。抑止する方法には以下のようなものがあります。
    1. そもそもリソースの名前を衝突しないように工夫します。もちろん同一リソースではないことが前提です。
      1. bash "install_hadoop-#{version}" do
      2.   code <<-EOC
      3.     tar xvzf #{downloaded_tarball} -C #{node['grid']['app_root']}
      4.   EOC
      5.   creates install_root
      6. end
    2. 既存リソースの有無を検査します。resources()メソッドは該当リソースが存在しない場合、例外を発生しますのでそれを捕捉します。
      1. pkg = 'tar'
      2. resources(package: pkg) rescue package pkg do
      3.   action :install
      4. end
      1. なお、RuboCopのデフォルト設定ではrescue修飾子の使用がチェックされます。そのような場合には、以下のようにブロックで記述するか、.rubocop.yml でチェックの設定を無効にします。
        1. pkg = 'tar'
        2. begin
        3.   resources(package: pkg)
        4. rescue
        5.   package pkg do
        6.     action :install
        7.   end
        8. end
        1. # in .rubocop.yml
        2. Style/RescueModifier:
        3.   Enabled: false

複数のガードの動作

  • 複数のガードプロパティを記述した場合、いずれかのガード(抑止)条件が一つでも有効であれば、そのリソースのアクションが抑止されると考えて問題ないでしょう。ガード条件なのでこれは自然な動作です。
  • (リソース定義なので当然ですが)実行ログを見る限り、プロパティの記述順等による短絡評価(逆に全評価も)は期待しない方がよいでしょう。
  1. 以下のテストレシピを
    1. # multiple only_if
    2. log 'only_if true,  only_if true ' do
    3.   only_if { true }
    4.   only_if { true }
    5. end
    6.  
    7. log 'only_if true,  only_if false' do
    8.   only_if { true }
    9.   only_if { false }
    10. end
    11.  
    12. log 'only_if false, only_if true ' do
    13.   only_if { false }
    14.   only_if { true }
    15. end
    16.  
    17. log 'only_if false, only_if false' do
    18.   only_if { false }
    19.   only_if { false }
    20. end
    21.  
    22. # multiple not_if
    23. log 'not_if  true,  not_if  true ' do
    24.   not_if { true }
    25.   not_if { true }
    26. end
    27.  
    28. log 'not_if  true,  not_if  false' do
    29.   not_if { true }
    30.   not_if { false }
    31. end
    32.  
    33. log 'not_if  false, not_if  true ' do
    34.   not_if { false }
    35.   not_if { true }
    36. end
    37.  
    38. log 'not_if  false, not_if  false' do
    39.   not_if { false }
    40.   not_if { false }
    41. end
    42.  
    43. # only_if, not_if
    44. log 'only_if true,  not_if  true ' do
    45.   only_if { true }
    46.   not_if  { true }
    47. end
    48.  
    49. log 'only_if true,  not_if  false' do
    50.   only_if { true }
    51.   not_if  { false }
    52. end
    53.  
    54. log 'only_if false, not_if  true ' do
    55.   only_if { false }
    56.   not_if  { true }
    57. end
    58.  
    59. log 'only_if false, not_if  false' do
    60.   only_if { false }
    61.   not_if  { false }
    62. end
    63.  
    64. # not_if, only_if
    65. log 'not_if  true,  only_if true ' do
    66.   not_if  { true }
    67.   only_if { true }
    68. end
    69.  
    70. log 'not_if  true,  only_if false' do
    71.   not_if  { true }
    72.   only_if { false }
    73. end
    74.  
    75. log 'not_if  false, only_if true ' do
    76.   not_if  { false }
    77.   only_if { true }
    78. end
    79.  
    80. log 'not_if  false, only_if false' do
    81.   not_if  { false }
    82.   only_if { false }
    83. end
    84.  
    85. # etc
    86. log 'not_if  true,  not_if true,  only_if false' do
    87.   not_if  { true }
    88.   not_if  { true }
    89.   only_if { false }
    90. end
    91.  
    92. log 'not_if  true,  not_if true,  not_if true, only_if false' do
    93.   not_if  { true }
    94.   not_if  { true }
    95.   not_if  { true }
    96.   only_if { false }
    97. end
  2. 実行すると
    1. Starting Chef Client, version 12.5.1
    2. Compiling Cookbooks...
    3. Converging 18 resources
    4. Recipe: drillbook::guard_test
    5.   * log[only_if true,  only_if true ] action write
    6.  
    7.   * log[only_if true,  only_if false] action write (skipped due to only_if)
    8.   * log[only_if false, only_if true ] action write (skipped due to only_if)
    9.   * log[only_if false, only_if false] action write (skipped due to only_if)
    10.   * log[not_if  true,  not_if  true ] action write (skipped due to not_if)
    11.   * log[not_if  true,  not_if  false] action write (skipped due to not_if)
    12.   * log[not_if  false, not_if  true ] action write (skipped due to not_if)
    13.   * log[not_if  false, not_if  false] action write
    14.  
    15.   * log[only_if true,  not_if  true ] action write (skipped due to not_if)
    16.   * log[only_if true,  not_if  false] action write
    17.  
    18.   * log[only_if false, not_if  true ] action write (skipped due to only_if)
    19.   * log[only_if false, not_if  false] action write (skipped due to only_if)
    20.   * log[not_if  true,  only_if true ] action write (skipped due to not_if)
    21.   * log[not_if  true,  only_if false] action write (skipped due to only_if)
    22.   * log[not_if  false, only_if true ] action write
    23.  
    24.   * log[not_if  false, only_if false] action write (skipped due to only_if)
    25.   * log[not_if  true,  not_if true,  only_if false] action write (skipped due to only_if)
    26.   * log[not_if  true,  not_if true,  not_if true, only_if false] action write (skipped due to only_if)

共有ライブラリ

  • 他のクックブックのライブラリは、metadata.rb にその依存を記述することにより使用することができます。
  1. 共有ライブラリを作成します。
    • cookbooks/cookbook_name/libraries/helper.rb
      1. module CookbookName
      2.   module Helper
      3.     # (...)
      4.   end
      5. end
  2. 利用する側のメタデータに依存するクックブックを明示します。
    • cookbooks/drillbook/metadata.rb
      1. depends  'cookbook_name'
  3. レシピでは、以下の要領でインクルードします。
    1. ::Chef::Recipe.send(:include, CookbookName::Helper)
  4. 属性ファイルでも、以下の要領でインクルードできます。
    1. ::Chef::Node::Attribute.send(:include, CookbookName::Helper)

ローカルパッケージファイルが存在しない場合のpackageリソースエラーを回避する

  1. ローカルのパッケージファイルでインストールしている場合で、目的のパッケージがインストール済みで今回はインストール不要であるにもかかわらず、source に指定されたローカルファイルの存在がチェックされてしまいエラーが発生します。これを回避するために、冗長ではありますが not_if 条件を追加します。
    1.   package cdh_repo_pkg do
    2.     source downloaded_repo_pkg
    3.     options '--nogpgcheck'
    4.     not_if "rpm -qi #{cdh_repo_pkg}"
    5.     action :install
    6.   end

属性(attribute)

利用の注意点と指針

属性ファイルでライブラリを利用する

  1. Chef::Node::Attribute クラスの send() メソッドで目的のライブラリをmix-inします。
    1. ::Chef::Node::Attribute.send(:include, DockerGrid::Helper)

レシピ

同一レシピを複数回 run_list に設定したり、include_recipe した場合

  • 最初に設定したものが一度だけ実行されます。リソースの多重定義警告などは発生しません。

テンプレート

テンプレートでライブラリを利用する

  1. templateリソースのhelpersプロパティで目的のライブラリをmix-inします。あまり推奨されませんが、他のクックブックのライブラリでも可能です。こうすることにより、テンプレートファイルの中でライブラリを利用できるようになります。
    1. if node['openldap']['with_ssl_cert_cookbook']
    2.   [
    3.     '00_olc-add-ldaps.ldif',
    4.     '00_olc-mod-ldaps.ldif',
    5.   ].each {|ldif|
    6.     template "/etc/ldap/#{ldif}" do
    7.       source  "etc/ldap/#{ldif}"
    8.       owner 'root'
    9.       group 'root'
    10.       mode '0644'
    11.       helpers Chef::Mixin::ShellOut
    12.       helpers SSLCert::Helper
    13.     end
    14.   }
    15. end

ロール

run_list と env_run_lists は排他的

  • 一つのロールの中に定義された run_list と env_run_lists はノードが属するEnvironmentについて排他的に適用されます。二つがマージされるわけではないので、注意が必要です。両方、定義することを避け、別々のロールに分けた方が見通しが良くなるでしょう。
  • たとえば、以下の例では dev 環境のノードには apache2::dev レシピのみが適用され(prod、stagingも同様)、_default 環境のノードには何も適用されません([]、空配列)。env_run_lists を使用する場合には、_default 環境の定義が必須なのも厄介な点です。そして、env_run_lists に明示的にリストされていない環境のノードにのみ run_list にある commons::platform_update レシピだけが適用されます。
    1. name 'security_update'
    2. description 'Security Update role.'
    3.  
    4. run_list(
    5.   'recipe[commons::platform_update]',
    6. )
    7.  
    8. env_run_lists(
    9.   'prod' => ['recipe[apache2]'],
    10.   'staging' => ['recipe[apache2::staging]'],
    11.   'dev' => ['recipe[apache2::dev]'],
    12.   '_default' => [],
    13. )

ロール間の共有情報

  1. ロール間での属性値の再利用であれば、まず共通の属性値を設定したロールを作成し、それを必要な他のロールの run_list でリストして使用します。
  2. 共通の情報に基づくものの、各ロールでそれぞれ適切な属性値を生成および設定したい場合には、Rubyの定数を利用します。ただし、Chefのロール定義としては、やや見通しが悪くなりますので、濫用は避けましょう。以下は、あるクラスタのGangliaとNagiosのセットアップを行うロールの例です。
    1. ruby.pnggrid-chef-repo:/roles/_lib/grid.rb: すべてのノードの情報を集約しているモジュールです。
    2. cake.pnggrid-chef-repo:/roles/pleiades-gm.rb: クラスタのGanglia(gmetad)の設定です。
    3. cake.pnggrid-chef-repo:/roles/pleiades-nm.rb: クラスタのNagiosの設定です。

knife-role-spaghetti プラグインでロールの依存グラフを作成

info.pnggrid-chef-repoのロール依存グラフ

  1. knife-role-spaghetti をインストールします。最も簡単な方法は、ChefのOmnibusインストーラでセットアップした環境を利用することです。
    1. まず必要となるGraphvizパッケージとネイティブライブラリをビルドするためのビルドツールをインストールします。最新のOmnibus Chefには、Ruby 1.9.3が同梱されていますので、Rubyのバージョンは問題ありません。現時点では、Chef Ver. 10 に依存していますので、最新のChef Ver. 11ワークステーション環境等への影響を懸念される場合には、別途仮想マシンなどを用意するとよいでしょう。
      $ sudo apt-get install graphviz build-essential
    2. gemコマンドで knife-role-spaghetti をインストールします。
      $ sudo /opt/chef/embedded/bin/gem install knife-role-spaghetti
  2. 目的のChefリポジトリのルートに移動して、以下のコマンドでロールの依存グラフを出力させます。
    $ knife role spaghetti

ロールのレシピ化

トラブルシューティング

chef-client -z (ローカルモード)

ロールをJSON形式で用意しなければならない

  1. chef-zero(簡易Chefサーバ)上で動作するためか、ロールをJSON形式で用意しなければなりません。ロールをRuby DSL形式で書いている場合、chef-soloからchef-clientローカルモードへの移行は大変になりますし、移行後のメリットはあまりないでしょう。

Hosted Chef

管理権限のある初期ユーザと同名のクライアントを作成するとWeb UIでの管理権限が失われる

  • Hosted Chef のWeb UIから、誤って管理権限のある初期ログインユーザ同名のクライアントを作成すると、その作成と同時にWeb UIでの管理権限が剥奪されてしまいます。
    • lightbulb.png復旧方法としては、作成してしまったクライアントのセットアップを一度行い、CLIからクライアント自身を削除します。
      $ knife client delete USERNAME

添付ファイル: filecookbook_site_install.png 225件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2018-11-10 (土) 20:27:44 (752d)