X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=cookbooks%2Fdocker-grid%2Frecipes%2Fengine.rb;h=473180fa70a5bcfb647db1487337d7f43040cd8e;hb=1a55847141cef70a220ff387e438bda347627a7d;hp=88ee3efa7d595cfd9a32d08621fd73cdacb97405;hpb=bb246fcfd3c119a3566073a812cb28a6952bf823;p=metasearch%2Fgrid-chef-repo.git diff --git a/cookbooks/docker-grid/recipes/engine.rb b/cookbooks/docker-grid/recipes/engine.rb index 88ee3ef..473180f 100644 --- a/cookbooks/docker-grid/recipes/engine.rb +++ b/cookbooks/docker-grid/recipes/engine.rb @@ -2,7 +2,7 @@ # Cookbook Name:: docker-grid # Recipe:: engine # -# Copyright 2016, whitestar +# Copyright 2016-2017, whitestar # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -19,6 +19,39 @@ # https://dcos.io/docs/1.8/administration/installing/custom/system-requirements/ +platform = node['platform'] +platform_family = node['platform_family'] +platform_version = node['platform_version'] + +install_flavor = node['docker-grid']['install_flavor'] +override_apt_line = node['docker-grid']['apt_repo']['override_apt_line'] +if !override_apt_line.nil? && !override_apt_line.empty? \ + && override_apt_line.include?(node['docker-grid']['dockerproject']['apt_new_repo_url']) + Chef::Log.warn('This docker-grid::engine recipe uses the Docker new repository by the `override_apt_line` attribute.') + node.force_override['docker-grid']['dockerproject']['enable_new_repo'] = true +end +enable_new_repo = node['docker-grid']['dockerproject']['enable_new_repo'] +docker_ver = node['docker-grid']['engine']['version'] +docker_ver = '' if docker_ver.nil? +storage_driver = node['docker-grid']['engine']['storage-driver'] +userns_remap = node['docker-grid']['engine']['userns-remap'] + +if node['docker-grid']['engine']['skip_setup'] + log 'Skip the Docker Engine setup.' + return +end + +::Chef::Recipe.send(:include, PlatformUtils::Helper) +::Chef::Recipe.send(:include, PlatformUtils::VirtUtils) + +[ + 'bridge-utils', +].each {|pkg| + resources(package: pkg) rescue package pkg do + action :install + end +} + bash 'systemctl_daemon-reload' do code <<-EOH systemctl daemon-reload @@ -26,180 +59,232 @@ bash 'systemctl_daemon-reload' do action :nothing end -if node['docker-grid']['engine']['storage-driver'] == 'overlay' - bash 'load_overlayfs_kernel_module' do - code <<-EOH - modprobe overlay - EOH - not_if 'lsmod | grep overlay' - end - - template '/etc/modules-load.d/overlay.conf' do - source 'etc/modules-load.d/overlay.conf' - owner 'root' - group 'root' - mode '0644' +# https://docs.docker.com/engine/userguide/storagedriver/selectadriver/ +if shell_out("cat /etc/mtab | grep -E '\s+/\s+zfs\s+'").exitstatus.zero? + if container_guest_node? + Chef::Log.warn('This node is running in the Linux container with ZFS, set the storage-driver to vfs as a fallback.') + node.override['docker-grid']['engine']['storage-driver'] = 'vfs' + else + Chef::Log.warn('This node is running on ZFS, set the storage-driver to zfs.') + node.override['docker-grid']['engine']['storage-driver'] = 'zfs' end end -log 'reboot_message' do - message 'Please reboot this machine because of kernel boot option modified.' - level :warn - action :nothing +if storage_driver == 'overlay2' + if !docker_ver.empty? && Gem::Version.create(docker_ver.tr('~', '-')) < Gem::Version.create('1.12') + # tr('~', '-') for Ubuntu. + Chef::Application.fatal!('Docker version must be 1.12 or later for overlay2 storage driver.') # and exit. + end end +load_kernel_module('overlay') if storage_driver =~ /overlay2?/ -userns_remap = node['docker-grid']['engine']['userns-remap'] if !userns_remap.nil? && !userns_remap.empty? - unless Gem::Version.create(node['docker-grid']['engine']['version'].tr('~', '-')) >= Gem::Version.create('1.10') + if !docker_ver.empty? && Gem::Version.create(docker_ver.tr('~', '-')) < Gem::Version.create('1.10') # tr('~', '-') for Ubuntu. Chef::Application.fatal!('Docker version must be 1.10 or later for userns-remap.') # and exit. end - # By default user namespace feature is inactive in RHEL family (>= 7.2). - if node['platform_family'] == 'rhel' - unless Gem::Version.create(node['platform_version']) >= Gem::Version.create('7.2') - Chef::Application.fatal!('Platform version must be 7.2 or later for kernel user namespace feature.') # and exit. - end - bash 'enable_user_namespace_feature_of_kernerl' do - code <<-"EOH" - grubby --args='user_namespace.enable=1' --update-kernel=/boot/vmlinuz-#{node['kernel']['release']} - EOH - not_if "grubby --info=/boot/vmlinuz-#{node['kernel']['release']} | grep 'user_namespace.enable=1'" - notifies :write, 'log[reboot_message]' - end - end - - subid_files = [ - '/etc/subuid', - '/etc/subgid', - ] + include_recipe 'platform_utils::kernel_user_namespace' - subid_files.each {|subid_file| - file subid_file do - owner 'root' - group 'root' - mode '0644' - action :touch - not_if { File.exist?(subid_file) } - end - } - - this_recipe = self remap_user = userns_remap == 'default' ? 'dockremap' : userns_remap - ruby_block 'adds_subid_entries' do - action :run - not_if "cat /etc/subuid | grep #{remap_user}" - not_if "cat /etc/subgid | grep #{remap_user}" - notifies :restart, 'service[docker]' - block do - subid_files.each {|subid_file| - max_start_id = 100_000 - offset = 0 - already_exist = false - - begin - File.open(subid_file) {|file| - file.each_line {|line| - entry = line.split(':') - if entry[0] == remap_user - already_exist = true - break - end - if entry[1].to_i >= max_start_id - max_start_id = entry[1].to_i - offset = entry[2].to_i - end - } - } - - if already_exist - this_recipe.log "#{remap_user} already exists in #{subid_file}" - else - File.open(subid_file, 'a') {|file| - entry_str = "#{remap_user}:#{max_start_id + offset}:65536" - this_recipe.log "#{remap_user} (#{entry_str}) is added in #{subid_file}" - file.puts entry_str - } - end - rescue IOError => e - puts e - end - } - end - end -end - -directory '/etc/systemd/system/docker.service.d' do - owner 'root' - group 'root' - mode '0755' - action :create + notifies_conf = { + 'action' => :restart, + 'resource' => 'service[docker]', + 'timer' => :delayed, + } + ::Chef::Recipe.send(:include, PlatformUtils::Helper) + append_subusers([remap_user], notifies_conf) end -template '/etc/systemd/system/docker.service.d/override.conf' do - source 'etc/systemd/system/docker.service.d/override.conf' - owner 'root' - group 'root' - mode '0644' - notifies :run, 'bash[systemctl_daemon-reload]' - notifies :restart, 'service[docker]' +bash 'clean_up_docker0_bridge' do + code <<-"EOH" + if brctl show | grep docker0; then + ip link set docker0 down + brctl delbr docker0 + fi + # https://github.com/docker/docker/issues/23630 + if [ -d /var/lib/docker/network ]; then + rm -rf /var/lib/docker/network + fi + EOH + action :nothing end -case node['platform_family'] +case platform_family when 'rhel' - # https://dcos.io/docs/1.8/administration/installing/custom/system-requirements/install-docker-centos/ - template '/etc/yum.repos.d/docker.repo' do - source 'etc/yum.repos.d/docker.repo' - owner 'root' - group 'root' - mode '0644' + if storage_driver == 'devicemapper' + [ + #'yum-utils', + 'device-mapper-persistent-data', + 'lvm2', + ].each {|pkg| + resources(package: pkg) rescue package pkg do + action :install + end + } end - [ - 'docker-engine-selinux', - 'docker-engine', - ].each {|pkg| - package pkg do - action :install - version node['docker-grid']['engine']['version'] - # dockerrepo is disabled by default to prevent automatic update. - options '--enablerepo=dockerrepo' + if install_flavor == 'dockerproject' + # https://dcos.io/docs/1.8/administration/installing/custom/system-requirements/install-docker-centos/ + old_repo_action = nil + new_repo_action = nil + pkgs = nil + if enable_new_repo + old_repo_action = :delete + new_repo_action = :create + pkgs = [ + 'docker-ce', + ] + else + old_repo_action = :create + new_repo_action = :delete + pkgs = [ + 'docker-engine-selinux', + 'docker-engine', + ] end - } + + [ + 'docker.repo', + 'docker-ce.repo', + ].each {|repo_file| + template "/etc/yum.repos.d/#{repo_file}" do + source "etc/yum.repos.d/#{repo_file}" + owner 'root' + group 'root' + mode '0644' + action repo_file == 'docker.repo' ? old_repo_action : new_repo_action + end + } + + [ + 'docker', + 'docker-common', + #'container-selinux', + 'docker-selinux', + ].each {|pkg| + resources(package: pkg) rescue package pkg do + action platform_family == 'debian' ? :purge : :remove + notifies :run, 'bash[clean_up_docker0_bridge]', :immediately + end + } + + pkgs.each {|pkg| + resources(yum_package: pkg) rescue yum_package pkg do + allow_downgrade true + action :install + version docker_ver unless docker_ver.empty? + # dockerrepo is disabled by default to prevent automatic update. + options '--enablerepo=dockerrepo' unless enable_new_repo + notifies :run, 'bash[clean_up_docker0_bridge]', :before if pkg == 'docker-engine' || pkg == 'docker-ce' + end + } + else + # OS distribution + [ + 'docker-engine-selinux', + 'docker-engine', + ].each {|pkg| + resources(package: pkg) rescue package pkg do + action platform_family == 'debian' ? :purge : :remove + notifies :run, 'bash[clean_up_docker0_bridge]', :immediately + end + } + + file '/etc/systemd/system/docker.service.d/override.conf' do + action :delete + end + + [ + 'docker', + ].each {|pkg| + resources(yum_package: pkg) rescue yum_package pkg do + allow_downgrade true + action :install + version docker_ver unless docker_ver.empty? + notifies :run, 'bash[clean_up_docker0_bridge]', :before + end + } + + template '/etc/sysconfig/docker' do + source 'etc/sysconfig/docker' + owner 'root' + group 'root' + mode '0644' + notifies :restart, 'service[docker]' + end + end when 'debian' + # https://docs.docker.com/engine/installation/linux/debian/ # https://docs.docker.com/engine/installation/linux/ubuntulinux/ pkgs = [ 'apt-transport-https', 'ca-certificates', + 'curl', + 'gnupg2', + 'software-properties-common', ] - if node['docker-grid']['engine']['storage-driver'] == 'aufs' - pkgs += [ - "linux-image-extra-#{node['os_version']}", - 'linux-image-extra-virtual', - ] + if storage_driver == 'aufs' \ + && !container_guest_node? + if platform == 'debian' + pkgs += [ + 'aufs-dkms', + ] + elsif platform == 'ubuntu' + pkgs += [ + "linux-image-extra-#{node['os_version']}", + 'linux-image-extra-virtual', + ] + end end pkgs.each {|pkg| - package pkg do + resources(package: pkg) rescue package pkg do action :install end } - template '/etc/apt/sources.list.d/docker.list' do - source 'etc/apt/sources.list.d/docker.list' - owner 'root' - group 'root' - mode '0644' + apt_get_update = 'apt-get_update' + resources(execute: apt_get_update) rescue execute apt_get_update do + command 'apt-get update' + action :nothing end - apt_repo_config = node['docker-grid']['apt_repo'] - bash 'apt-key_adv_docker_tools_key' do - code <<-"EOH" - apt-key adv --keyserver #{apt_repo_config['keyserver']} --recv-keys #{apt_repo_config['recv-keys']} - apt-get update - EOH - not_if 'apt-key list | grep -i docker' + if install_flavor == 'dockerproject' + pkg_name_removed = 'docker.io' + pkg_name = node['docker-grid']['dockerproject']['package_name'] + + apt_repo_config = node['docker-grid']['apt_repo'] + apt_key_add_cmd = nil + apt_key_name = nil + if enable_new_repo + apt_key_add_cmd = "curl -fsSL https://download.docker.com/linux/#{platform}/gpg | apt-key add -" + apt_key_name = 'Docker Release (CE deb)' + else + apt_key_add_cmd = "apt-key adv --keyserver #{apt_repo_config['keyserver']} --recv-keys #{apt_repo_config['recv-keys']}" + apt_key_name = 'Docker Release Tool (releasedocker)' + end + bash 'apt-key_adv_docker_tools_key' do + code <<-"EOH" + #{apt_key_add_cmd} + EOH + action :nothing + not_if "apt-key list 2>&1 | grep '#{apt_key_name}'" + end + + template '/etc/apt/sources.list.d/docker.list' do + source 'etc/apt/sources.list.d/docker.list' + owner 'root' + group 'root' + mode '0644' + notifies :run, 'bash[apt-key_adv_docker_tools_key]', :before + notifies :run, "execute[#{apt_get_update}]", :immediately + end + else + # OS distribution + pkg_name_removed = node['docker-grid']['dockerproject']['package_name'] + pkg_name = 'docker.io' end # Pinning Docker version @@ -208,18 +293,104 @@ when 'debian' owner 'root' group 'root' mode '0644' + action :delete if docker_ver.empty? + variables( + pkg_name: pkg_name + ) end - [ - 'docker-engine', - ].each {|pkg| - package pkg do - action :install - version node['docker-grid']['engine']['version'] - end - } + resources(package: pkg_name_removed) rescue package pkg_name_removed do + action platform_family == 'debian' ? :purge : :remove + notifies :run, 'bash[clean_up_docker0_bridge]', :immediately + end + + resources(package: pkg_name) rescue package pkg_name do + action :install + options "-o Dpkg::Options::='--force-confnew'" if platform_family == 'debian' + options '--allow-downgrades' if platform == 'debian' || platform_version >= '16.04' # LTS (xenial) + options '--force-yes' if platform_version == '14.04' # LTS (trusty) + version docker_ver unless docker_ver.empty? + notifies :run, 'bash[clean_up_docker0_bridge]', :before + notifies :run, 'bash[apt-key_adv_docker_tools_key]', :before + notifies :run, "execute[#{apt_get_update}]", :before + end +end + +docker_opts = [] +docker_opts.push("--storage-driver=#{storage_driver}") if !storage_driver.nil? && !storage_driver.empty? +docker_opts.push("--userns-remap=#{userns_remap}") if !userns_remap.nil? && !userns_remap.empty? + +extra_options = node['docker-grid']['engine']['daemon_extra_options'] +# for docker-engine package on RHEL: remove '-H fd://' +# https://github.com/docker/docker/issues/22847 +if platform_family == 'rhel' || platform == 'debian' || (platform == 'ubuntu' && platform_version == '14.04') + # Note: docker_ver.empty? -> the latest version + if docker_ver.empty? \ + || Gem::Version.create(docker_ver.tr('~', '-')) >= Gem::Version.create('1.12') + extra_options = extra_options.gsub(%r{-H\sfd://}, '') # for frozen string. + end +end + +docker_opts.push(extra_options) if !extra_options.nil? && !extra_options.empty? + +init_package = node['init_package'] +if init_package == 'systemd' + directory '/etc/systemd/system/docker.service.d' do + owner 'root' + group 'root' + mode '0755' + action :create + end + + template '/etc/systemd/system/docker.service.d/override.conf' do + source 'etc/systemd/system/docker.service.d/override.conf' + owner 'root' + group 'root' + mode '0644' + variables( + docker_opts: docker_opts + ) + not_if { install_flavor == 'os-repository' && platform_family == 'rhel' } + notifies :run, 'bash[systemctl_daemon-reload]', :immediately + notifies :restart, 'service[docker]' + end +elsif init_package == 'init' # for Ubuntu 14.04,... + template '/etc/default/docker' do + source 'etc/default/docker' + owner 'root' + group 'root' + mode '0644' + variables( + docker_opts: docker_opts + ) + notifies :restart, 'service[docker]' + end end service 'docker' do + provider Chef::Provider::Service::Upstart if platform == 'ubuntu' && platform_version < '15.04' action [:start, :enable] + subscribes :restart, 'execute[update-ca-certificates]', :delayed end + +users = node['docker-grid']['engine']['users_allow'] +group 'docker' do + members users unless users.empty? + action :create + append true +end + +# utility scripts +[ + 'docker_containers_cleanup', + 'docker_images_cleanup', + 'docker_volumes_cleanup', +].each {|script| + template "/usr/local/bin/#{script}" do + source "usr/local/bin/#{script}" + owner 'root' + group 'root' + mode '0755' + action :create + end +}