How to update nginx via Chef

2019-05-11 20:49发布

Note this is a copy of a question I asked on ServerFault but was unable to get an answer for. Hoping I can get some feedback here.

I am a developer who recently inherited our previous devops person's chef setup. I'm running Chef 10 server and have realized that the nginx cookbook from opscode still uses nginx version 1.2.6. Since there are many security patches that have been released I'd like to move to 1.4.1 and feel that Chef should make this very easy. However it has proven to be nightmarish.

My first thought was to simply make the nginx cookbook "custom" and change the default['nginx']['version'] attribute to 1.4.1, upload the cookbook and converge a testing server. I watched it fetch the new version of the cookbook (I remembered to update the metadata), and promptly ignore it as it continued using 1.2.6.

Then I thought I should override attributes in the role I am using (rails_tier_web is the name of the role). Speaking with a more experienced Chef person he cautioned against it since roles cannot be versioned and pinned the way cookbooks can. However reading the documentation for the cookbook, they tell you to use the override attributes in your role so that's what I've done:

override_attributes( 'nginx' => { 'source' => { 'version' => '1.4.1', 'prefix' => '/opt/nginx-1.4.1' }, 'version' => '1.4.1' } )

However when I converge I am still seeing traces of 1.2.6 show up in the log output.

[2013-07-15T18:52:03-04:00] INFO: Processing remote_file[http://nginx.org/download/nginx-1.2.6.tar.gz] action create (nginx::source line 56)
[2013-07-15T18:52:05-04:00] INFO: remote_file[http://nginx.org/download/nginx-1.2.6.tar.gz] updated

and then right after that...

Mixlib::ShellOut::ShellCommandFailed
------------------------------------
Expected process to exit with [0], but received '1'
---- Begin output of "bash"  "/tmp/chef-script20130715-4790-1m689ee" ----
STDOUT:
STDERR: /tmp/chef-script20130715-4790-1m689ee: line 2: cd: nginx-1.4.1: No such file or directory
---- End output of "bash"  "/tmp/chef-script20130715-4790-1m689ee" ----
Ran "bash"  "/tmp/chef-script20130715-4790-1m689ee" returned 1

Resource Declaration:
---------------------
# In /var/chef/cache/cookbooks/nginx/recipes/source.rb

 84: bash "compile_nginx_source" do
 85:   cwd ::File.dirname(src_filepath)
 86:   code <<-EOH
 87:     tar zxf #{::File.basename(src_filepath)} -C #{::File.dirname(src_filepath)} &&
 88:     cd nginx-#{node['nginx']['source']['version']} &&
 89:     ./configure #{node.run_state['nginx_configure_flags'].join(" ")} &&
 90:     make && make install
 91:   EOH
 92:
 93:   not_if do
 94:     nginx_force_recompile == false &&
 95:       node.automatic_attrs['nginx'] &&
 96:       node.automatic_attrs['nginx']['version'] == node['nginx']['source']['version'] &&
 97:       node.automatic_attrs['nginx']['configure_arguments'].sort == configure_flags.sort
 98:   end
 99:
100:   notifies :restart, "service[nginx]"
101: end
102:

Compiled Resource:
------------------
# Declared in /var/chef/cache/cookbooks/nginx/recipes/source.rb:84:in `from_file'

bash("compile_nginx_source") do
  action "run"
  retries 0
  retry_delay 2
  command "\"bash\"  \"/tmp/chef-script20130715-4790-1m689ee\""
  backup 5
  cwd "/var/chef/cache"
  returns 0
  code "    tar zxf nginx-1.4.1.tar.gz -C /var/chef/cache &&\n    cd nginx-1.4.1 &&\n    ./configure --prefix=/opt/nginx-1.2.6 --conf-path=/etc/nginx/nginx.conf --with-http_gzip_static_module --with-http_realip_module --with-http_ssl_module --with-http_stub_status_module &&\n    make && make install\n"
  interpreter "bash"
  cookbook_name "nginx"
  recipe_name "source"
  not_if { #code block }
end

I am really at wits end because I was hoping I could just override a version attribute and have it all fall into place. Obviously that is not the case thus far and I really don't want to have to do manual patching and/or editing of node objects if I can help it. Any help would be appreciated.

标签: nginx chef
2条回答
我命由我不由天
2楼-- · 2019-05-11 21:36

I'm running into this very same issue. Best I can tell, the root of the issue is the use of string concatenation in the attributes files in the nginx cookbook. If you look at attributes/source.rb you see the following

default['nginx']['source']['default_configure_flags'] = [
  "--prefix=#{node['nginx']['source']['prefix']}",
  "--conf-path=#{node['nginx']['dir']}/nginx.conf",
  "--sbin-path=#{node['nginx']['source']['sbin_path']}"
]

These are fine, reasonable defaults. And one would think that if one overrides one of the referenced attributes, node['nginx']['source']['prefix'], then the resulting default_configure_flags would reflect that change. However, that doesn't appear to be the case. It looks like attributes files are one of, if not the, first things loaded when running chef. So the values assigned to things like default_configure_flags are based on the defaults provided with the cookbook (i.e. the version string 1.2.6 which is set in attributes/default.rb).

Short of doing some serious cleanup work on the nginx cookbook itself, my best solution was to override the default_configure_flags attribute in my own attributes file (along with a number of others that seem like they should be fine, but cause the same issue, look at the rest of the attributes/source.rb for the reset). Unfortunately, I'm overriding it to the same thing as the default, it just get's evaluated later after the other values that it references are set to what I want.

查看更多
神经病院院长
3楼-- · 2019-05-11 21:46

This line:

[2013-07-15T18:52:03-04:00] INFO: Processing remote_file[http://nginx.org/download/nginx-1.2.6.tar.gz] action create (nginx::source line 56)

Points to line 56 of the source recipe on the nginx cookbook. There you can see that the URL for the source archive is set using this logic:

nginx_url = node['nginx']['source']['url'] || "http://nginx.org/download/nginx-#{node['nginx']['source']['version']}.tar.gz"

So I guess that node['nginx']['source']['url'] is pointing to version nginx version 1.6. It should be dependent on the node['nginx']['source']['version'] attribute as can be seen here, but maybe there's some attribute loading order at work here that's getting in the way.

Try setting node['nginx']['source']['url'] to http://nginx.org/download/nginx-1.4.1.tar.gz while keeping the source version also set to 1.4.1.

My guess is that you're downloading 1.2.6 while trying to extract 1.4.1, which is not there, so the bash script fails.

查看更多
登录 后发表回答