OSDN Git Service

473180fa70a5bcfb647db1487337d7f43040cd8e
[metasearch/grid-chef-repo.git] / cookbooks / docker-grid / recipes / engine.rb
1 #
2 # Cookbook Name:: docker-grid
3 # Recipe:: engine
4 #
5 # Copyright 2016-2017, whitestar
6 #
7 # Licensed under the Apache License, Version 2.0 (the "License");
8 # you may not use this file except in compliance with the License.
9 # You may obtain a copy of the License at
10 #
11 #     http://www.apache.org/licenses/LICENSE-2.0
12 #
13 # Unless required by applicable law or agreed to in writing, software
14 # distributed under the License is distributed on an "AS IS" BASIS,
15 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 # See the License for the specific language governing permissions and
17 # limitations under the License.
18 #
19
20 # https://dcos.io/docs/1.8/administration/installing/custom/system-requirements/
21
22 platform = node['platform']
23 platform_family = node['platform_family']
24 platform_version = node['platform_version']
25
26 install_flavor = node['docker-grid']['install_flavor']
27 override_apt_line = node['docker-grid']['apt_repo']['override_apt_line']
28 if !override_apt_line.nil? && !override_apt_line.empty? \
29   && override_apt_line.include?(node['docker-grid']['dockerproject']['apt_new_repo_url'])
30   Chef::Log.warn('This docker-grid::engine recipe uses the Docker new repository by the `override_apt_line` attribute.')
31   node.force_override['docker-grid']['dockerproject']['enable_new_repo'] = true
32 end
33 enable_new_repo = node['docker-grid']['dockerproject']['enable_new_repo']
34 docker_ver = node['docker-grid']['engine']['version']
35 docker_ver = '' if docker_ver.nil?
36 storage_driver = node['docker-grid']['engine']['storage-driver']
37 userns_remap = node['docker-grid']['engine']['userns-remap']
38
39 if node['docker-grid']['engine']['skip_setup']
40   log 'Skip the Docker Engine setup.'
41   return
42 end
43
44 ::Chef::Recipe.send(:include, PlatformUtils::Helper)
45 ::Chef::Recipe.send(:include, PlatformUtils::VirtUtils)
46
47 [
48   'bridge-utils',
49 ].each {|pkg|
50   resources(package: pkg) rescue package pkg do
51     action :install
52   end
53 }
54
55 bash 'systemctl_daemon-reload' do
56   code <<-EOH
57     systemctl daemon-reload
58   EOH
59   action :nothing
60 end
61
62 # https://docs.docker.com/engine/userguide/storagedriver/selectadriver/
63 if shell_out("cat /etc/mtab | grep -E '\s+/\s+zfs\s+'").exitstatus.zero?
64   if container_guest_node?
65     Chef::Log.warn('This node is running in the Linux container with ZFS, set the storage-driver to vfs as a fallback.')
66     node.override['docker-grid']['engine']['storage-driver'] = 'vfs'
67   else
68     Chef::Log.warn('This node is running on ZFS, set the storage-driver to zfs.')
69     node.override['docker-grid']['engine']['storage-driver'] = 'zfs'
70   end
71 end
72
73 if storage_driver == 'overlay2'
74   if !docker_ver.empty? && Gem::Version.create(docker_ver.tr('~', '-')) < Gem::Version.create('1.12')
75     # tr('~', '-') for Ubuntu.
76     Chef::Application.fatal!('Docker version must be 1.12 or later for overlay2 storage driver.')  # and exit.
77   end
78 end
79 load_kernel_module('overlay') if storage_driver =~ /overlay2?/
80
81 if !userns_remap.nil? && !userns_remap.empty?
82   if !docker_ver.empty? && Gem::Version.create(docker_ver.tr('~', '-')) < Gem::Version.create('1.10')
83     # tr('~', '-') for Ubuntu.
84     Chef::Application.fatal!('Docker version must be 1.10 or later for userns-remap.')  # and exit.
85   end
86
87   include_recipe 'platform_utils::kernel_user_namespace'
88
89   remap_user = userns_remap == 'default' ? 'dockremap' : userns_remap
90   notifies_conf = {
91     'action' => :restart,
92     'resource' => 'service[docker]',
93     'timer' => :delayed,
94   }
95   ::Chef::Recipe.send(:include, PlatformUtils::Helper)
96   append_subusers([remap_user], notifies_conf)
97 end
98
99 bash 'clean_up_docker0_bridge' do
100   code <<-"EOH"
101     if brctl show | grep docker0; then
102       ip link set docker0 down
103       brctl delbr docker0
104     fi
105     # https://github.com/docker/docker/issues/23630
106     if [ -d /var/lib/docker/network ]; then
107       rm -rf /var/lib/docker/network
108     fi
109   EOH
110   action :nothing
111 end
112
113 case platform_family
114 when 'rhel'
115   if storage_driver == 'devicemapper'
116     [
117       #'yum-utils',
118       'device-mapper-persistent-data',
119       'lvm2',
120     ].each {|pkg|
121       resources(package: pkg) rescue package pkg do
122         action :install
123       end
124     }
125   end
126
127   if install_flavor == 'dockerproject'
128     # https://dcos.io/docs/1.8/administration/installing/custom/system-requirements/install-docker-centos/
129     old_repo_action = nil
130     new_repo_action = nil
131     pkgs = nil
132     if enable_new_repo
133       old_repo_action = :delete
134       new_repo_action = :create
135       pkgs = [
136         'docker-ce',
137       ]
138     else
139       old_repo_action = :create
140       new_repo_action = :delete
141       pkgs = [
142         'docker-engine-selinux',
143         'docker-engine',
144       ]
145     end
146
147     [
148       'docker.repo',
149       'docker-ce.repo',
150     ].each {|repo_file|
151       template "/etc/yum.repos.d/#{repo_file}" do
152         source  "etc/yum.repos.d/#{repo_file}"
153         owner 'root'
154         group 'root'
155         mode '0644'
156         action repo_file == 'docker.repo' ? old_repo_action : new_repo_action
157       end
158     }
159
160     [
161       'docker',
162       'docker-common',
163       #'container-selinux',
164       'docker-selinux',
165     ].each {|pkg|
166       resources(package: pkg) rescue package pkg do
167         action platform_family == 'debian' ? :purge : :remove
168         notifies :run, 'bash[clean_up_docker0_bridge]', :immediately
169       end
170     }
171
172     pkgs.each {|pkg|
173       resources(yum_package: pkg) rescue yum_package pkg do
174         allow_downgrade true
175         action :install
176         version docker_ver unless docker_ver.empty?
177         # dockerrepo is disabled by default to prevent automatic update.
178         options '--enablerepo=dockerrepo' unless enable_new_repo
179         notifies :run, 'bash[clean_up_docker0_bridge]', :before if pkg == 'docker-engine' || pkg == 'docker-ce'
180       end
181     }
182   else
183     # OS distribution
184     [
185       'docker-engine-selinux',
186       'docker-engine',
187     ].each {|pkg|
188       resources(package: pkg) rescue package pkg do
189         action platform_family == 'debian' ? :purge : :remove
190         notifies :run, 'bash[clean_up_docker0_bridge]', :immediately
191       end
192     }
193
194     file '/etc/systemd/system/docker.service.d/override.conf' do
195       action :delete
196     end
197
198     [
199       'docker',
200     ].each {|pkg|
201       resources(yum_package: pkg) rescue yum_package pkg do
202         allow_downgrade true
203         action :install
204         version docker_ver unless docker_ver.empty?
205         notifies :run, 'bash[clean_up_docker0_bridge]', :before
206       end
207     }
208
209     template '/etc/sysconfig/docker' do
210       source  'etc/sysconfig/docker'
211       owner 'root'
212       group 'root'
213       mode '0644'
214       notifies :restart, 'service[docker]'
215     end
216   end
217 when 'debian'
218   # https://docs.docker.com/engine/installation/linux/debian/
219   # https://docs.docker.com/engine/installation/linux/ubuntulinux/
220   pkgs = [
221     'apt-transport-https',
222     'ca-certificates',
223     'curl',
224     'gnupg2',
225     'software-properties-common',
226   ]
227
228   if storage_driver == 'aufs' \
229     && !container_guest_node?
230     if platform == 'debian'
231       pkgs += [
232         'aufs-dkms',
233       ]
234     elsif platform == 'ubuntu'
235       pkgs += [
236         "linux-image-extra-#{node['os_version']}",
237         'linux-image-extra-virtual',
238       ]
239     end
240   end
241
242   pkgs.each {|pkg|
243     resources(package: pkg) rescue package pkg do
244       action :install
245     end
246   }
247
248   apt_get_update = 'apt-get_update'
249   resources(execute: apt_get_update) rescue execute apt_get_update do
250     command 'apt-get update'
251     action :nothing
252   end
253
254   if install_flavor == 'dockerproject'
255     pkg_name_removed = 'docker.io'
256     pkg_name = node['docker-grid']['dockerproject']['package_name']
257
258     apt_repo_config = node['docker-grid']['apt_repo']
259     apt_key_add_cmd = nil
260     apt_key_name = nil
261     if enable_new_repo
262       apt_key_add_cmd = "curl -fsSL https://download.docker.com/linux/#{platform}/gpg | apt-key add -"
263       apt_key_name = 'Docker Release (CE deb)'
264     else
265       apt_key_add_cmd = "apt-key adv --keyserver #{apt_repo_config['keyserver']} --recv-keys #{apt_repo_config['recv-keys']}"
266       apt_key_name = 'Docker Release Tool (releasedocker)'
267     end
268     bash 'apt-key_adv_docker_tools_key' do
269       code <<-"EOH"
270         #{apt_key_add_cmd}
271       EOH
272       action :nothing
273       not_if "apt-key list 2>&1 | grep '#{apt_key_name}'"
274     end
275
276     template '/etc/apt/sources.list.d/docker.list' do
277       source  'etc/apt/sources.list.d/docker.list'
278       owner 'root'
279       group 'root'
280       mode '0644'
281       notifies :run, 'bash[apt-key_adv_docker_tools_key]', :before
282       notifies :run, "execute[#{apt_get_update}]", :immediately
283     end
284   else
285     # OS distribution
286     pkg_name_removed = node['docker-grid']['dockerproject']['package_name']
287     pkg_name = 'docker.io'
288   end
289
290   # Pinning Docker version
291   template '/etc/apt/preferences.d/docker.pref' do
292     source  'etc/apt/preferences.d/docker.pref'
293     owner 'root'
294     group 'root'
295     mode '0644'
296     action :delete if docker_ver.empty?
297     variables(
298       pkg_name: pkg_name
299     )
300   end
301
302   resources(package: pkg_name_removed) rescue package pkg_name_removed do
303     action platform_family == 'debian' ? :purge : :remove
304     notifies :run, 'bash[clean_up_docker0_bridge]', :immediately
305   end
306
307   resources(package: pkg_name) rescue package pkg_name do
308     action :install
309     options "-o Dpkg::Options::='--force-confnew'" if platform_family == 'debian'
310     options '--allow-downgrades' if platform == 'debian' || platform_version >= '16.04'  # LTS (xenial)
311     options '--force-yes' if platform_version == '14.04'  # LTS (trusty)
312     version docker_ver unless docker_ver.empty?
313     notifies :run, 'bash[clean_up_docker0_bridge]', :before
314     notifies :run, 'bash[apt-key_adv_docker_tools_key]', :before
315     notifies :run, "execute[#{apt_get_update}]", :before
316   end
317 end
318
319 docker_opts = []
320 docker_opts.push("--storage-driver=#{storage_driver}") if !storage_driver.nil? && !storage_driver.empty?
321 docker_opts.push("--userns-remap=#{userns_remap}") if !userns_remap.nil? && !userns_remap.empty?
322
323 extra_options = node['docker-grid']['engine']['daemon_extra_options']
324 # for docker-engine package on RHEL: remove '-H fd://'
325 # https://github.com/docker/docker/issues/22847
326 if platform_family == 'rhel' || platform == 'debian' || (platform == 'ubuntu' && platform_version == '14.04')
327   # Note: docker_ver.empty? -> the latest version
328   if docker_ver.empty? \
329     || Gem::Version.create(docker_ver.tr('~', '-')) >= Gem::Version.create('1.12')
330     extra_options = extra_options.gsub(%r{-H\sfd://}, '')  # for frozen string.
331   end
332 end
333
334 docker_opts.push(extra_options) if !extra_options.nil? && !extra_options.empty?
335
336 init_package = node['init_package']
337 if init_package == 'systemd'
338   directory '/etc/systemd/system/docker.service.d' do
339     owner 'root'
340     group 'root'
341     mode '0755'
342     action :create
343   end
344
345   template '/etc/systemd/system/docker.service.d/override.conf' do
346     source  'etc/systemd/system/docker.service.d/override.conf'
347     owner 'root'
348     group 'root'
349     mode '0644'
350     variables(
351       docker_opts: docker_opts
352     )
353     not_if { install_flavor == 'os-repository' && platform_family == 'rhel' }
354     notifies :run, 'bash[systemctl_daemon-reload]', :immediately
355     notifies :restart, 'service[docker]'
356   end
357 elsif init_package == 'init'  # for Ubuntu 14.04,...
358   template '/etc/default/docker' do
359     source  'etc/default/docker'
360     owner 'root'
361     group 'root'
362     mode '0644'
363     variables(
364       docker_opts: docker_opts
365     )
366     notifies :restart, 'service[docker]'
367   end
368 end
369
370 service 'docker' do
371   provider Chef::Provider::Service::Upstart if platform == 'ubuntu' && platform_version < '15.04'
372   action [:start, :enable]
373   subscribes :restart, 'execute[update-ca-certificates]', :delayed
374 end
375
376 users = node['docker-grid']['engine']['users_allow']
377 group 'docker' do
378   members users unless users.empty?
379   action :create
380   append true
381 end
382
383 # utility scripts
384 [
385   'docker_containers_cleanup',
386   'docker_images_cleanup',
387   'docker_volumes_cleanup',
388 ].each {|script|
389   template "/usr/local/bin/#{script}" do
390     source  "usr/local/bin/#{script}"
391     owner 'root'
392     group 'root'
393     mode '0755'
394     action :create
395   end
396 }