让我们试着制作一个ohai的自定义插件

相关文章

    • Chefを使ってより効率的にサーバを管理しよう。まずは用語から

 

    • Berkshelfを使って外部クックブックをノードに適用する。

 

    • クックブックを作成してノードに適用する。- その1

 

    • クックブックを作成してノードに適用する。- その2

 

    • ChefでCentOS 6.7 + rbenv + ruby 2.3.0の環境を構築する。

 

    • ChefでCentOS 6.7 + Vim 7.4 + luaを設置する。

 

    • ChefでVimプラグインマネージャーNeoBundleを設置する。

 

    • Chefのレシピをデバッグしてみよう。

 

    • ChefでCentOS 6.7 + nginxを設置する。- 外部クックブック

 

    • ChefでCentOS 6.7 + nginxを設置する。- カスタムクックブック

 

    • ChefでCentOS 6.7 + nodejs + npmを設置する。

 

    • ChefでVimプラグインマネージャーvim-plugを設置する。

 

    • ohaiのカスタムプラグインを作ってみよう。

 

    • Chef SoloからChef Zeroへ

 

    Chefでnginx + php(php-fpm) + mariadb + wordpressを設置する。

“ohai” 是什么意思?

    • ノードの情報をAttributeで保持しているシステムでChefをインストールするとき一緒にインストールされる。

 

    ノート上のさまざまな情報をJSONのデータとして扱えるようにしてくれる。

自定义插件的必要性

    • nginxをtarballでインストールする。

 

    • nginxのバージョンと使っているmoduleが同じであれば次にChefを実行するときはインストールをスキプしたい。

 

    • ohaiを使って最初インストールするときのバージョンとmoduleの情報をノード上に保持する。

 

    • Chefを実行するときノード上に保持されているバージョンとmoduleの情報をクックブックのattributeと比較する。

 

    比較して異なる場合のみインストールする。

创建自定义插件

在Berksfile中添加

    ohaiというコミュニティクックブックに依存的なので、先にインストールする。
% vi Berksfile

... snip ...
cookbook 'ohai'

:wq

% bin/berks vendor cookbook
    nginxのコミュニティクックブックがインストールされている場合はすでにohaiがインストールされている。

添加依赖性

    nginxのカスタムクックブック内のmetadata.rbファイルに依存性を記入する。
... snip ...
depends 'ohai'

生成食谱

    • 既存nginxのレシピ(default.rb)からohaiを使うためにohai_pluginという新規レシピを作成する。

 

    • nginxのコミュニティクックブックからそのまま持ってきた。

 

    • ノード上の/etc/chef/ohai_pluginsの配下にnginx.rbファイルが生成される。

 

    site-cookbooks/nginx/recipes/ohai_plugin.rb
ohai 'reload_nginx' do
  plugin 'nginx'
  action :nothing
end

template "#{node['ohai']['plugin_path']}/nginx.rb" do
  source 'plugins/nginx.rb.erb'
  owner  'root'
  group  'root'
  mode   '0755'
  notifies :reload, 'ohai[reload_nginx]', :immediately
end

include_recipe 'ohai::default'

修改现有食谱

    • 新規作成したohai_pluginをdefaultレシピの中からincludeする。

 

    nginxがインストールされるたびに今度作成したohaiのカスタムプラグインをリロード(再実行)する。
include_recipe 'nginx::ohai_plugin' 
nginx_url = node['nginx']['url']
nginx_filename = "nginx-#{node['nginx']['ver']}.tar.gz"
src_filepath  = "#{Chef::Config['file_cache_path'] || '/tmp'}/#{nginx_filename}"

... snip ...

bash "install nginx" do
  cwd File.dirname(src_filepath)
  code <<-EOH
    tar zxf #{nginx_filename} -C #{File.dirname(src_filepath)}
    cd #{File.dirname(src_filepath)}/#{File.basename(nginx_filename, ".tar.gz")}
    ./configure #{configure_flags.join(' ')}
    make
    make install
  EOH

  not_if do
    force_recompile == false &&
    node.automatic_attrs['nginx'] &&
    node.automatic_attrs['nginx']['version'] == node['nginx']['ver'] &&
    node.automatic_attrs['nginx']['configure_arguments'].sort == configure_flags.sort
  end

  notifies :restart, 'service[nginx]'
  notifies :reload,  'ohai[reload_nginx]', :immediately
end

... snip ...

用模板生成自定义插件。

    • ohaiのバージョン(6, 7, 8)別にプラグインの記述方法が異なる。

 

    • nginxのコミュニティクックブックからそのまま持ってきた。

 

    • しかし、バージョン6で記述されていて古い。

 

    site-cookbooks/nginx/templates/default/plugins/nginx.rb.erb
provides "nginx"
provides "nginx/version"
provides "nginx/configure_arguments"
provides "nginx/prefix"
provides "nginx/conf_path"

def parse_flags(flags)
  prefix = nil
  conf_path = nil

  flags.each do |flag|
    case flag
    when /^--prefix=(.+)$/
      prefix = $1
    when /^--conf-path=(.+)$/
      conf_path = $1
    end
  end

  [ prefix, conf_path ]
end

nginx Mash.new unless nginx
nginx[:version]             = nil unless nginx[:version]
nginx[:configure_arguments] = Array.new unless nginx[:configure_arguments]
nginx[:prefix]              = nil unless nginx[:prefix]
nginx[:conf_path]           = nil unless nginx[:conf_path]

status, stdout, stderr = run_command(:no_status_check => true, :command => "<%= node['nginx']['sbin'] %> -V")

if status == 0
  stderr.split("\n").each do |line|
    case line
    when /^configure arguments:(.+)/
      # This could be better: I'm splitting on configure arguments which removes them and also
      # adds a blank string at index 0 of the array. This is why we drop index 0 and map to
      # add the '--' prefix back to the configure argument.
      nginx[:configure_arguments] = $1.split(/\s--/).drop(1).map { |ca| "--#{ca}" }

      prefix, conf_path = parse_flags(nginx[:configure_arguments])

      nginx[:prefix] = prefix
      nginx[:conf_path] = conf_path
    when /^nginx version: nginx\/(\d+\.\d+\.\d+)/
      nginx[:version] = $1
    end
  end
end
    • バージョン6の記述方法はすでにdeprecatedになっているので、バージョン7で直してみた。

 

    • バージョン7と8の記述方法は同様である。

 

    site-cookbooks/nginx/templates/default/plugins/nginx.rb.erb
Ohai.plugin(:Nginx) do
  provides "nginx"

  def parse_flags
    so = shell_out("<%= node['nginx']['sbin'] %> -V 2>&1")
    so.stdout.lines.each do |line|
      case line
      when /^nginx version: nginx\/(\d+\.\d+\.\d+)/
        @version = $1
      when /^configure arguments:(.+)/
        @configure_arguments = $1.split(/\s--/).drop(1).map { |ca| "--#{ca}" }
      end
    end
  end

  collect_data do
    parse_flags
    nginx Mash.new
    nginx[:version]             = @version
    nginx[:configure_arguments] = @configure_arguments
  end
end

provides

このプラグインが提供する項目を宣言する。
保持したい情報を宣言した項目に割り当てる。

Mash

データストアとしてMashを利用する。Hashだと考えばいい。
Mashに保持したいデータをセットする。

collect_data

ohaiにより呼び出されるrubyのブロックでデータを取集して保持する。
platformを引数として指定するのもできる。ex):aix, :freebsd, :linux…

手机外壳.

    • chef-shell(又はirb)でカスタムプラグインの中のコマンドを実行してみる。

 

    使いたいコマンドの実行結果を加工して集取するのができるので、カスタムプラグインの作成のとき役に立つ。
chef (12.7.2)> include Chef::Mixin::ShellOut
 => Object

chef (12.7.2)> so = shell_out('/opt/nginx-1.8.1/sbin/nginx -V 2>&1')
 => <Mixlib::ShellOut#41687580: command: '/opt/nginx-1.8.1/sbin/nginx -V 2>&1' process_status: #<Process::Status: pid 9533 exit 0> stdout: 'nginx version: nginx/1.8.1
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-16) (GCC)
built with OpenSSL 1.0.1e-fips 11 Feb 2013
TLS SNI support enabled
configure arguments: --prefix=/opt/nginx-1.8.1 --conf-path=/etc/nginx/nginx.conf --sbin-path=/opt/nginx-1.8.1/sbin/nginx --with-http_ssl_module --with-http_stub_status_module --with-http_gzip_static_module --with-http_flv_module --with-http_mp4_module' stderr: '' child_pid: 9533 environment: {"LC_ALL"=>"en_US.UTF-8", "LANGUAGE"=>"en_US.UTF-8", "LANG"=>"en_US.UTF-8"} timeout: 600 user:  group:  working_dir:  >

chef (12.7.2)> so.stdout
 => "nginx version: nginx/1.8.1\nbuilt by gcc 4.4.7 20120313 (Red Hat 4.4.7-16) (GCC) \nbuilt with OpenSSL 1.0.1e-fips 11 Feb 2013\nTLS SNI support enabled\nconfigure arguments: --prefix=/opt/nginx-1.8.1 --conf-path=/etc/nginx/nginx.conf --sbin-path=/opt/nginx-1.8.1/sbin/nginx --with-http_ssl_module --with-http_stub_status_module --with-http_gzip_static_module --with-http_flv_module --with-http_mp4_module\n"

chef (12.7.2)> so.stdout.lines
 => ["nginx version: nginx/1.8.1\n", "built by gcc 4.4.7 20120313 (Red Hat 4.4.7-16) (GCC) \n", "built with OpenSSL 1.0.1e-fips 11 Feb 2013\n", "TLS SNI support enabled\n", "configure arguments: --prefix=/opt/nginx-1.8.1 --conf-path=/etc/nginx/nginx.conf --sbin-path=/opt/nginx-1.8.1/sbin/nginx --with-http_ssl_module --with-http_stub_status_module --with-http_gzip_static_module --with-http_flv_module --with-http_mp4_module\n"]

执行ohai插件。

    • コマンドの実行結果にプラグインから生成したデータが含まれている。

 

    • このデータとクックブックのattributeのデータを比べてインストールするかどうかを決める。

 

    • バージョン6の記述方法でプラグインが作成されている場合は、deprecatedになっているという警告メッセージが表示される。

 

    • そして、バージョン6の場合は最初に表示されるため|headを付けて確認する必要がある。

 

    バージョン7の場合は最後に表示されるため付けなくても結構だ。
$ ohai -d /etc/chef/ohai_plugins/

... snip ...
  "nginx": {
    "version": "1.8.1",
    "configure_arguments": [
      "--prefix=/opt/nginx-1.8.1",
      "--conf-path=/etc/nginx/nginx.conf",
      "--sbin-path=/opt/nginx-1.8.1/sbin/nginx",
      "--with-http_ssl_module",
      "--with-http_stub_status_module",
      "--with-http_gzip_static_module",
      "--with-http_flv_module",
      "--with-http_mp4_module"
    ]
  }

通过使用chef-shell来验证的方法

$ chef-shell -s -c solo.rb -j dna.json

chef (12.7.2)> Ohai::Config[:plugin_path] << '/etc/chef/ohai_plugins'
 => ["/opt/chef/embedded/lib/ruby/gems/2.1.0/gems/ohai-8.10.0/lib/ohai/plugins", "/etc/chef/ohai_plugins"]

chef (12.7.2)> o = Ohai::System.new
[2016-03-16T13:25:44+00:00] WARN: Ohai::Config[:plugin_path] is set. Ohai::Config[:plugin_path] is deprecated and will be removed in future releases of ohai. Use ohai.plugin_path in your configuration file to configure :plugin_path for ohai.
 => #<Ohai::System:0x00000004ea1b00 @plugin_path="", @config={}, @data={}, @provides_map=#<Ohai::ProvidesMap:0x00000004ea1a38 @map={}>, @v6_dependency_solver={}, @loader=#<Ohai::Loader:0x00000004ea0e30 @controller=#<Ohai::System:0x00000004ea1b00 ...>, @v6_plugin_classes=[], @v7_plugin_classes=[]>, @runner=#<Ohai::Runner:0x00000004ea0db8 @provides_map=#<Ohai::ProvidesMap:0x00000004ea1a38 @map={}>, @safe_run=true>>
chef (12.7.2)> o.all_plugins

... snip ...

chef (12.7.2)> o.attributes_print('nginx')
 => "{\n  \"version\": \"1.8.1\",\n  \"configure_arguments\": [\n    \"--prefix=/opt/nginx-1.8.1\",\n    \"--conf-path=/etc/nginx/nginx.conf\",\n    \"--sbin-path=/opt/nginx-1.8.1/sbin/nginx\",\n    \"--with-http_ssl_module\",\n    \"--with-http_stub_status_module\",\n    \"--with-http_gzip_static_module\",\n    \"--with-http_flv_module\",\n    \"--with-http_mp4_module\"\n  ]\n}\n"

chef (12.7.2)> o.attributes_print('nginx/version')
 => "[\n  \"1.8.1\"\n]\n"

chef (12.7.2)> o.attributes_print('nginx/configure_arguments')
 => "[\n  \"--prefix=/opt/nginx-1.8.1\",\n  \"--conf-path=/etc/nginx/nginx.conf\",\n  \"--sbin-path=/opt/nginx-1.8.1/sbin/nginx\",\n  \"--with-http_ssl_module\",\n  \"--with-http_stub_status_module\",\n  \"--with-http_gzip_static_module\",\n  \"--with-http_flv_module\",\n  \"--with-http_mp4_module\"\n]\n"

嵌入的位置 de

    • ohaiのカスタムプラグインの記述方法をバージョン6からバージョン7に変更したあと、考えたとおりに行かなくて苦労した。

 

    • 特にこの部分については入門書のレベルでは説明がほぼなかったためぐっぐたネット情報に依存するしかなかった。

 

    • 日本語の情報もほとんどない。

 

    • 英語でとても参考になったサイトのURLを最後に貼っておいたので参考にしていただきたい。

 

    shell_outについてはqiitaに投稿されている記事が役に立った。

命令的错误

    • nginxをtarballで設置するときのコンパイル情報を調べるためには-Vオプションを付ければいい。

 

    • /opt/nginx-1.8.1/sbin/nginx -Vをして置いたがコンパイル情報の取得に失敗した。

 

    • ‘nginx/version’だけversion7というわからないデータが保持されて’nginx/configure_arguments’は空っぽだった。

 

    • ここでshell_outで使うコマンドに問題があることは気が付かずにバージョン7の記述方法に問題があったんではないかと疑っていた。

 

    • /opt/nginx-1.8.1/sbin/nginx -V 2>&1に変更したらコンパイル情報が正常に取得された。

 

    正常に結果を得られるまで1日位時間が掛かった。

节点的运行状态

    • Chef-solo(又はChef-client)が起動される間データを一時的に保持する。

 

    • nginxのコミュニティクックブックの中で使っていたので、使ってみたが保持したはずなのにずっとnilだった。

 

    • 問題は実行のタイミングにあった。

 

    • 明示的に遅延されていないrubyコード(ruby_block、lazy、not_if/only_if)はコンパイル段階で実行される。

 

    • Chefの実行はコンパイル>収束(Converge)>通知(Notification)順で行う。

 

    • コンパイル段階で実行されるところに収束の段階で実行されるnode.run_stateを参照するとnilになるわけだ。

 

    詳細はここを参考にしていただきたい。(特に英語のサイト)
# bashリソースのnot_ifブロックの中でnilになってしまい進めない。
node.run_state['force_recompile'] = false
node.run_state['configure_flags'] = node['nginx']['default_configure_flags'] | node['nginx']['modules']

# bashリソースのnot_ifブロックの中でもnilにならない。
force_recompile = false
configure_flags = node['nginx']['default_configure_flags'] | node['nginx']['modules']

请参阅

第7版的写作方式

    • http://blog.levvel.io/blog-post/levvel-up-your-devops-game-with-custom-ohai-plugins-chef/

 

    • https://docs.chef.io/release/ohai-8/

 

    https://github.com/rackerlabs/ohai-plugins/tree/master/plugins

关于shell_out的说明

    http://qiita.com/sawanoboly/items/43bc9e15739355f9c533

解释厨师执行时机

    • http://www.engineyard.co.jp/blog/2013/chef-recipe-lifecycle/

 

    https://coderanger.net/two-pass/

图书

    • Chef実践入門

 

    オライリーの「Customizing Chef」(まだ翻訳されてない)
广告
将在 10 秒后关闭
bannerAds