OSDN Git Service

- adds the `['docker-grid']['dockerproject']['apt_new_repo_sections']` attribute.
[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? || docker_ver == 'latest'
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 file '/etc/systemd/system/docker.service.d/override.conf' do
100   action :nothing
101 end
102
103 bash 'clean_up_docker0_bridge' do
104   code <<-"EOH"
105     if brctl show | grep docker0; then
106       ip link set docker0 down
107       brctl delbr docker0
108     fi
109     # https://github.com/docker/docker/issues/23630
110     if [ -d /var/lib/docker/network ]; then
111       rm -rf /var/lib/docker/network
112     fi
113   EOH
114   action :nothing
115 end
116
117 case platform_family
118 when 'rhel'
119   ex_enablerepo = node['docker-grid']['dockerproject']['yum_new_repo_extra_enablerepo']
120
121   if storage_driver == 'devicemapper'
122     [
123       #'yum-utils',
124       'device-mapper-persistent-data',
125       'lvm2',
126     ].each {|pkg|
127       resources(package: pkg) rescue package pkg do
128         action :install
129       end
130     }
131   end
132
133   if install_flavor == 'dockerproject'
134     # https://dcos.io/docs/1.8/administration/installing/custom/system-requirements/install-docker-centos/
135     old_repo_action = nil
136     new_repo_action = nil
137     pkgs = nil
138     if enable_new_repo
139       old_repo_action = :delete
140       new_repo_action = :create
141       pkgs = [
142         'docker-ce',
143       ]
144     else
145       old_repo_action = :create
146       new_repo_action = :delete
147       pkgs = [
148         'docker-engine-selinux',
149         'docker-engine',
150       ]
151     end
152
153     [
154       'docker.repo',
155       'docker-ce.repo',
156     ].each {|repo_file|
157       template "/etc/yum.repos.d/#{repo_file}" do
158         source  "etc/yum.repos.d/#{repo_file}"
159         owner 'root'
160         group 'root'
161         mode '0644'
162         action repo_file == 'docker.repo' ? old_repo_action : new_repo_action
163       end
164     }
165
166     [
167       'docker',
168       'docker-common',
169       #'container-selinux',
170       'docker-selinux',
171     ].each {|pkg|
172       resources(package: pkg) rescue package pkg do
173         action platform_family == 'debian' ? :purge : :remove
174         notifies :delete, 'file[/etc/systemd/system/docker.service.d/override.conf]', :immediately
175         notifies :run, 'bash[clean_up_docker0_bridge]', :immediately
176       end
177     }
178
179     pkgs.each {|pkg|
180       resources(yum_package: pkg) rescue yum_package pkg do
181         allow_downgrade true
182         action :install
183         version docker_ver unless docker_ver.empty?
184         # for the new repository
185         options "--enablerepo=#{ex_enablerepo}" if enable_new_repo && !ex_enablerepo.nil? && !ex_enablerepo.empty?
186         # old dockerrepo is disabled by default to prevent automatic update.
187         options '--enablerepo=dockerrepo' unless enable_new_repo
188         notifies :run, 'bash[clean_up_docker0_bridge]', :before if pkg == 'docker-engine' || pkg == 'docker-ce'
189       end
190     }
191   else
192     # OS distribution
193     [
194       'docker-engine-selinux',
195       'docker-engine',
196     ].each {|pkg|
197       resources(package: pkg) rescue package pkg do
198         action platform_family == 'debian' ? :purge : :remove
199         notifies :delete, 'file[/etc/systemd/system/docker.service.d/override.conf]', :immediately
200         notifies :run, 'bash[clean_up_docker0_bridge]', :immediately
201       end
202     }
203
204     [
205       'docker',
206     ].each {|pkg|
207       resources(yum_package: pkg) rescue yum_package pkg do
208         allow_downgrade true
209         action :install
210         version docker_ver unless docker_ver.empty?
211         notifies :run, 'bash[clean_up_docker0_bridge]', :before
212       end
213     }
214
215     template '/etc/sysconfig/docker' do
216       source  'etc/sysconfig/docker'
217       owner 'root'
218       group 'root'
219       mode '0644'
220       notifies :restart, 'service[docker]'
221     end
222   end
223 when 'debian'
224   # https://docs.docker.com/engine/installation/linux/debian/
225   # https://docs.docker.com/engine/installation/linux/ubuntulinux/
226   pkgs = [
227     'apt-transport-https',
228     'ca-certificates',
229     'curl',
230     'gnupg2',
231     'software-properties-common',
232   ]
233
234   if storage_driver == 'aufs' \
235     && !container_guest_node?
236     if platform == 'debian'
237       pkgs += [
238         'aufs-dkms',
239       ]
240     elsif platform == 'ubuntu'
241       pkgs += [
242         "linux-image-extra-#{node['os_version']}",
243         'linux-image-extra-virtual',
244       ]
245     end
246   end
247
248   pkgs.each {|pkg|
249     resources(package: pkg) rescue package pkg do
250       action :install
251     end
252   }
253
254   apt_get_update = 'apt-get_update'
255   resources(execute: apt_get_update) rescue execute apt_get_update do
256     command 'apt-get update'
257     action :nothing
258   end
259
260   if install_flavor == 'dockerproject'
261     pkg_name_removed = 'docker.io'
262     pkg_name = node['docker-grid']['dockerproject']['package_name']
263
264     apt_repo_config = node['docker-grid']['apt_repo']
265     apt_key_add_cmd = nil
266     apt_key_name = nil
267     if enable_new_repo
268       apt_key_add_cmd = "curl -fsSL https://download.docker.com/linux/#{platform}/gpg | apt-key add -"
269       apt_key_name = 'Docker Release (CE deb)'
270     else
271       apt_key_add_cmd = "apt-key adv --keyserver #{apt_repo_config['keyserver']} --recv-keys #{apt_repo_config['recv-keys']}"
272       apt_key_name = 'Docker Release Tool (releasedocker)'
273     end
274     bash 'apt-key_adv_docker_tools_key' do
275       code <<-"EOH"
276         #{apt_key_add_cmd}
277       EOH
278       action :nothing
279       not_if "apt-key list 2>&1 | grep '#{apt_key_name}'"
280     end
281
282     template '/etc/apt/sources.list.d/docker.list' do
283       source  'etc/apt/sources.list.d/docker.list'
284       owner 'root'
285       group 'root'
286       mode '0644'
287       notifies :run, 'bash[apt-key_adv_docker_tools_key]', :before
288       notifies :run, "execute[#{apt_get_update}]", :immediately
289     end
290   else
291     # OS distribution
292     pkg_name_removed = node['docker-grid']['dockerproject']['package_name']
293     pkg_name = 'docker.io'
294   end
295
296   # Pinning Docker version
297   template '/etc/apt/preferences.d/docker.pref' do
298     source  'etc/apt/preferences.d/docker.pref'
299     owner 'root'
300     group 'root'
301     mode '0644'
302     action :delete if docker_ver.empty?
303     variables(
304       pkg_name: pkg_name
305     )
306   end
307
308   resources(package: pkg_name_removed) rescue package pkg_name_removed do
309     action platform_family == 'debian' ? :purge : :remove
310     notifies :delete, 'file[/etc/systemd/system/docker.service.d/override.conf]', :immediately
311     notifies :run, 'bash[clean_up_docker0_bridge]', :immediately
312   end
313
314   resources(package: pkg_name) rescue package pkg_name do
315     action :install
316     options "-o Dpkg::Options::='--force-confnew'" if platform_family == 'debian'
317     options '--allow-downgrades' if platform == 'debian' || platform_version >= '16.04'  # LTS (xenial)
318     options '--force-yes' if platform_version == '14.04'  # LTS (trusty)
319     version docker_ver unless docker_ver.empty?
320     notifies :run, 'bash[clean_up_docker0_bridge]', :before
321     notifies :run, 'bash[apt-key_adv_docker_tools_key]', :before
322     notifies :run, "execute[#{apt_get_update}]", :before
323   end
324 end
325
326 docker_opts = []
327 docker_opts.push("--storage-driver=#{storage_driver}") if !storage_driver.nil? && !storage_driver.empty?
328 docker_opts.push("--userns-remap=#{userns_remap}") if !userns_remap.nil? && !userns_remap.empty?
329
330 extra_options = node['docker-grid']['engine']['daemon_extra_options']
331 # for docker-engine package on RHEL: remove '-H fd://'
332 # https://github.com/docker/docker/issues/22847
333 if platform_family == 'rhel' || platform == 'debian' || (platform == 'ubuntu' && platform_version == '14.04')
334   # Note: docker_ver.empty? -> the latest version
335   if docker_ver.empty? \
336     || Gem::Version.create(docker_ver.tr('~', '-')) >= Gem::Version.create('1.12')
337     extra_options = extra_options.gsub(%r{-H\sfd://}, '')  # for frozen string.
338   end
339 end
340
341 docker_opts.push(extra_options) if !extra_options.nil? && !extra_options.empty?
342
343 init_package = node['init_package']
344 if init_package == 'systemd'
345   directory '/etc/systemd/system/docker.service.d' do
346     owner 'root'
347     group 'root'
348     mode '0755'
349     action :create
350   end
351
352   template '/etc/systemd/system/docker.service.d/override.conf' do
353     source  'etc/systemd/system/docker.service.d/override.conf'
354     owner 'root'
355     group 'root'
356     mode '0644'
357     variables(
358       docker_opts: docker_opts
359     )
360     not_if { install_flavor == 'os-repository' && platform_family == 'rhel' }
361     notifies :run, 'bash[systemctl_daemon-reload]', :immediately
362     notifies :restart, 'service[docker]'
363   end
364 elsif init_package == 'init'  # for Ubuntu 14.04,...
365   template '/etc/default/docker' do
366     source  'etc/default/docker'
367     owner 'root'
368     group 'root'
369     mode '0644'
370     variables(
371       docker_opts: docker_opts
372     )
373     notifies :restart, 'service[docker]'
374   end
375 end
376
377 service 'docker' do
378   provider Chef::Provider::Service::Upstart if platform == 'ubuntu' && platform_version < '15.04'
379   action [:start, :enable]
380   subscribes :restart, 'execute[update-ca-certificates]', :delayed
381 end
382
383 users = node['docker-grid']['engine']['users_allow']
384 group 'docker' do
385   members users unless users.empty?
386   action :create
387   append true
388 end
389
390 # utility scripts
391 [
392   'docker_containers_cleanup',
393   'docker_images_cleanup',
394   'docker_volumes_cleanup',
395 ].each {|script|
396   template "/usr/local/bin/#{script}" do
397     source  "usr/local/bin/#{script}"
398     owner 'root'
399     group 'root'
400     mode '0755'
401     action :create
402   end
403 }