You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

276 lines
11 KiB

Added file and container image caching (#4828) * File and container image downloads are now cached localy, so that repeated vagrant up/down runs do not trigger downloading of those files. This is especially useful on laptops with kubernetes runnig locally on vm's. The total size of the cache, after an ansible run, is currently around 800MB, so bandwidth (=time) savings can be quite significant. * When download_run_once is false, the default is still not to cache, but setting download_force_cache will still enable caching. * The local cache location can be set with download_cache_dir and defaults to /tmp/kubernetes_cache * A local docker instance is no longer required to cache docker images; Images are cached to file. A local docker instance is still required, though, if you wish to download images on localhost. * Fixed a FIXME, wher the argument was that delegate_to doesn't play nice with omit. That is a correct observation and the fix is to use default(inventory_host) instead of default(omit). See ansible/ansible#26009 * Removed "Register docker images info" task from download_container and set_docker_image_facts because it was faulty and unused. * Removed redundant when:download.{container,enabled,run_once} conditions from {sync,download}_container.yml * All features of commit d6fd0d2acaec9f53e75d82db30411f96a5bf2cc9 by Timoses <timosesu@gmail.com>, merged May 1st 2019, are included in this patch. Not all code was included verbatim, but each feature of that commit was checked to be working in this patch. One notable change: The actual downloading of the kubeadm images was moved to {download,sync)_container, to enable caching. Note 1: I considered splitting this patch, but most changes that are not directly related to caching, are a pleasant by-product of implementing the caching code, so splitting would be impractical. Note 2: I have my doubts about the usefulness of the upload, download and upgrade tags in the download role. Must they remain or can they be removed? If anybody knows, then please speak up.
5 years ago
Added file and container image caching (#4828) * File and container image downloads are now cached localy, so that repeated vagrant up/down runs do not trigger downloading of those files. This is especially useful on laptops with kubernetes runnig locally on vm's. The total size of the cache, after an ansible run, is currently around 800MB, so bandwidth (=time) savings can be quite significant. * When download_run_once is false, the default is still not to cache, but setting download_force_cache will still enable caching. * The local cache location can be set with download_cache_dir and defaults to /tmp/kubernetes_cache * A local docker instance is no longer required to cache docker images; Images are cached to file. A local docker instance is still required, though, if you wish to download images on localhost. * Fixed a FIXME, wher the argument was that delegate_to doesn't play nice with omit. That is a correct observation and the fix is to use default(inventory_host) instead of default(omit). See ansible/ansible#26009 * Removed "Register docker images info" task from download_container and set_docker_image_facts because it was faulty and unused. * Removed redundant when:download.{container,enabled,run_once} conditions from {sync,download}_container.yml * All features of commit d6fd0d2acaec9f53e75d82db30411f96a5bf2cc9 by Timoses <timosesu@gmail.com>, merged May 1st 2019, are included in this patch. Not all code was included verbatim, but each feature of that commit was checked to be working in this patch. One notable change: The actual downloading of the kubeadm images was moved to {download,sync)_container, to enable caching. Note 1: I considered splitting this patch, but most changes that are not directly related to caching, are a pleasant by-product of implementing the caching code, so splitting would be impractical. Note 2: I have my doubts about the usefulness of the upload, download and upgrade tags in the download role. Must they remain or can they be removed? If anybody knows, then please speak up.
5 years ago
Added file and container image caching (#4828) * File and container image downloads are now cached localy, so that repeated vagrant up/down runs do not trigger downloading of those files. This is especially useful on laptops with kubernetes runnig locally on vm's. The total size of the cache, after an ansible run, is currently around 800MB, so bandwidth (=time) savings can be quite significant. * When download_run_once is false, the default is still not to cache, but setting download_force_cache will still enable caching. * The local cache location can be set with download_cache_dir and defaults to /tmp/kubernetes_cache * A local docker instance is no longer required to cache docker images; Images are cached to file. A local docker instance is still required, though, if you wish to download images on localhost. * Fixed a FIXME, wher the argument was that delegate_to doesn't play nice with omit. That is a correct observation and the fix is to use default(inventory_host) instead of default(omit). See ansible/ansible#26009 * Removed "Register docker images info" task from download_container and set_docker_image_facts because it was faulty and unused. * Removed redundant when:download.{container,enabled,run_once} conditions from {sync,download}_container.yml * All features of commit d6fd0d2acaec9f53e75d82db30411f96a5bf2cc9 by Timoses <timosesu@gmail.com>, merged May 1st 2019, are included in this patch. Not all code was included verbatim, but each feature of that commit was checked to be working in this patch. One notable change: The actual downloading of the kubeadm images was moved to {download,sync)_container, to enable caching. Note 1: I considered splitting this patch, but most changes that are not directly related to caching, are a pleasant by-product of implementing the caching code, so splitting would be impractical. Note 2: I have my doubts about the usefulness of the upload, download and upgrade tags in the download role. Must they remain or can they be removed? If anybody knows, then please speak up.
5 years ago
  1. # -*- mode: ruby -*-
  2. # # vi: set ft=ruby :
  3. # For help on using kubespray with vagrant, check out docs/vagrant.md
  4. require 'fileutils'
  5. Vagrant.require_version ">= 2.0.0"
  6. CONFIG = File.join(File.dirname(__FILE__), ENV['KUBESPRAY_VAGRANT_CONFIG'] || 'vagrant/config.rb')
  7. FLATCAR_URL_TEMPLATE = "https://%s.release.flatcar-linux.net/amd64-usr/current/flatcar_production_vagrant.json"
  8. FEDORA35_MIRROR = "https://download.fedoraproject.org/pub/fedora/linux/releases/35/Cloud/x86_64/images/Fedora-Cloud-Base-Vagrant-35-1.2.x86_64.vagrant-libvirt.box"
  9. # Uniq disk UUID for libvirt
  10. DISK_UUID = Time.now.utc.to_i
  11. SUPPORTED_OS = {
  12. "flatcar-stable" => {box: "flatcar-stable", user: "core", box_url: FLATCAR_URL_TEMPLATE % ["stable"]},
  13. "flatcar-beta" => {box: "flatcar-beta", user: "core", box_url: FLATCAR_URL_TEMPLATE % ["beta"]},
  14. "flatcar-alpha" => {box: "flatcar-alpha", user: "core", box_url: FLATCAR_URL_TEMPLATE % ["alpha"]},
  15. "flatcar-edge" => {box: "flatcar-edge", user: "core", box_url: FLATCAR_URL_TEMPLATE % ["edge"]},
  16. "ubuntu1604" => {box: "generic/ubuntu1604", user: "vagrant"},
  17. "ubuntu1804" => {box: "generic/ubuntu1804", user: "vagrant"},
  18. "ubuntu2004" => {box: "generic/ubuntu2004", user: "vagrant"},
  19. "centos" => {box: "centos/7", user: "vagrant"},
  20. "centos-bento" => {box: "bento/centos-7.6", user: "vagrant"},
  21. "centos8" => {box: "centos/8", user: "vagrant"},
  22. "centos8-bento" => {box: "bento/centos-8", user: "vagrant"},
  23. "almalinux8" => {box: "almalinux/8", user: "vagrant"},
  24. "almalinux8-bento" => {box: "bento/almalinux-8", user: "vagrant"},
  25. "rockylinux8" => {box: "generic/rocky8", user: "vagrant"},
  26. "fedora35" => {box: "fedora/35-cloud-base", user: "vagrant", box_url: FEDORA35_MIRROR},
  27. "fedora36" => {box: "fedora/36-cloud-base", user: "vagrant"},
  28. "opensuse" => {box: "opensuse/Leap-15.4.x86_64", user: "vagrant"},
  29. "opensuse-tumbleweed" => {box: "opensuse/Tumbleweed.x86_64", user: "vagrant"},
  30. "oraclelinux" => {box: "generic/oracle7", user: "vagrant"},
  31. "oraclelinux8" => {box: "generic/oracle8", user: "vagrant"},
  32. "rhel7" => {box: "generic/rhel7", user: "vagrant"},
  33. "rhel8" => {box: "generic/rhel8", user: "vagrant"},
  34. }
  35. if File.exist?(CONFIG)
  36. require CONFIG
  37. end
  38. # Defaults for config options defined in CONFIG
  39. $num_instances ||= 3
  40. $instance_name_prefix ||= "k8s"
  41. $vm_gui ||= false
  42. $vm_memory ||= 2048
  43. $vm_cpus ||= 2
  44. $shared_folders ||= {}
  45. $forwarded_ports ||= {}
  46. $subnet ||= "172.18.8"
  47. $subnet_ipv6 ||= "fd3c:b398:0698:0756"
  48. $os ||= "ubuntu1804"
  49. $network_plugin ||= "flannel"
  50. # Setting multi_networking to true will install Multus: https://github.com/k8snetworkplumbingwg/multus-cni
  51. $multi_networking ||= "False"
  52. $download_run_once ||= "True"
  53. $download_force_cache ||= "False"
  54. # The first three nodes are etcd servers
  55. $etcd_instances ||= $num_instances
  56. # The first two nodes are kube masters
  57. $kube_master_instances ||= $num_instances == 1 ? $num_instances : ($num_instances - 1)
  58. # All nodes are kube nodes
  59. $kube_node_instances ||= $num_instances
  60. # The following only works when using the libvirt provider
  61. $kube_node_instances_with_disks ||= false
  62. $kube_node_instances_with_disks_size ||= "20G"
  63. $kube_node_instances_with_disks_number ||= 2
  64. $override_disk_size ||= false
  65. $disk_size ||= "20GB"
  66. $local_path_provisioner_enabled ||= "False"
  67. $local_path_provisioner_claim_root ||= "/opt/local-path-provisioner/"
  68. $libvirt_nested ||= false
  69. # boolean or string (e.g. "-vvv")
  70. $ansible_verbosity ||= false
  71. $ansible_tags ||= ENV['VAGRANT_ANSIBLE_TAGS'] || ""
  72. $playbook ||= "cluster.yml"
  73. host_vars = {}
  74. $box = SUPPORTED_OS[$os][:box]
  75. # if $inventory is not set, try to use example
  76. $inventory = "inventory/sample" if ! $inventory
  77. $inventory = File.absolute_path($inventory, File.dirname(__FILE__))
  78. # if $inventory has a hosts.ini file use it, otherwise copy over
  79. # vars etc to where vagrant expects dynamic inventory to be
  80. if ! File.exist?(File.join(File.dirname($inventory), "hosts.ini"))
  81. $vagrant_ansible = File.join(File.dirname(__FILE__), ".vagrant", "provisioners", "ansible")
  82. FileUtils.mkdir_p($vagrant_ansible) if ! File.exist?($vagrant_ansible)
  83. $vagrant_inventory = File.join($vagrant_ansible,"inventory")
  84. FileUtils.rm_f($vagrant_inventory)
  85. FileUtils.ln_s($inventory, $vagrant_inventory)
  86. end
  87. if Vagrant.has_plugin?("vagrant-proxyconf")
  88. $no_proxy = ENV['NO_PROXY'] || ENV['no_proxy'] || "127.0.0.1,localhost"
  89. (1..$num_instances).each do |i|
  90. $no_proxy += ",#{$subnet}.#{i+100}"
  91. end
  92. end
  93. Vagrant.configure("2") do |config|
  94. config.vm.box = $box
  95. if SUPPORTED_OS[$os].has_key? :box_url
  96. config.vm.box_url = SUPPORTED_OS[$os][:box_url]
  97. end
  98. config.ssh.username = SUPPORTED_OS[$os][:user]
  99. # plugin conflict
  100. if Vagrant.has_plugin?("vagrant-vbguest") then
  101. config.vbguest.auto_update = false
  102. end
  103. # always use Vagrants insecure key
  104. config.ssh.insert_key = false
  105. if ($override_disk_size)
  106. unless Vagrant.has_plugin?("vagrant-disksize")
  107. system "vagrant plugin install vagrant-disksize"
  108. end
  109. config.disksize.size = $disk_size
  110. end
  111. (1..$num_instances).each do |i|
  112. config.vm.define vm_name = "%s-%01d" % [$instance_name_prefix, i] do |node|
  113. node.vm.hostname = vm_name
  114. if Vagrant.has_plugin?("vagrant-proxyconf")
  115. node.proxy.http = ENV['HTTP_PROXY'] || ENV['http_proxy'] || ""
  116. node.proxy.https = ENV['HTTPS_PROXY'] || ENV['https_proxy'] || ""
  117. node.proxy.no_proxy = $no_proxy
  118. end
  119. ["vmware_fusion", "vmware_workstation"].each do |vmware|
  120. node.vm.provider vmware do |v|
  121. v.vmx['memsize'] = $vm_memory
  122. v.vmx['numvcpus'] = $vm_cpus
  123. end
  124. end
  125. node.vm.provider :virtualbox do |vb|
  126. vb.memory = $vm_memory
  127. vb.cpus = $vm_cpus
  128. vb.gui = $vm_gui
  129. vb.linked_clone = true
  130. vb.customize ["modifyvm", :id, "--vram", "8"] # ubuntu defaults to 256 MB which is a waste of precious RAM
  131. vb.customize ["modifyvm", :id, "--audio", "none"]
  132. end
  133. node.vm.provider :libvirt do |lv|
  134. lv.nested = $libvirt_nested
  135. lv.cpu_mode = "host-model"
  136. lv.memory = $vm_memory
  137. lv.cpus = $vm_cpus
  138. lv.default_prefix = 'kubespray'
  139. # Fix kernel panic on fedora 28
  140. if $os == "fedora"
  141. lv.cpu_mode = "host-passthrough"
  142. end
  143. end
  144. if $kube_node_instances_with_disks
  145. # Libvirt
  146. driverletters = ('a'..'z').to_a
  147. node.vm.provider :libvirt do |lv|
  148. # always make /dev/sd{a/b/c} so that CI can ensure that
  149. # virtualbox and libvirt will have the same devices to use for OSDs
  150. (1..$kube_node_instances_with_disks_number).each do |d|
  151. lv.storage :file, :device => "hd#{driverletters[d]}", :path => "disk-#{i}-#{d}-#{DISK_UUID}.disk", :size => $kube_node_instances_with_disks_size, :bus => "scsi"
  152. end
  153. end
  154. end
  155. if $expose_docker_tcp
  156. node.vm.network "forwarded_port", guest: 2375, host: ($expose_docker_tcp + i - 1), auto_correct: true
  157. end
  158. $forwarded_ports.each do |guest, host|
  159. node.vm.network "forwarded_port", guest: guest, host: host, auto_correct: true
  160. end
  161. if ["rhel7","rhel8"].include? $os
  162. # Vagrant synced_folder rsync options cannot be used for RHEL boxes as Rsync package cannot
  163. # be installed until the host is registered with a valid Red Hat support subscription
  164. node.vm.synced_folder ".", "/vagrant", disabled: false
  165. $shared_folders.each do |src, dst|
  166. node.vm.synced_folder src, dst
  167. end
  168. else
  169. node.vm.synced_folder ".", "/vagrant", disabled: false, type: "rsync", rsync__args: ['--verbose', '--archive', '--delete', '-z'] , rsync__exclude: ['.git','venv']
  170. $shared_folders.each do |src, dst|
  171. node.vm.synced_folder src, dst, type: "rsync", rsync__args: ['--verbose', '--archive', '--delete', '-z']
  172. end
  173. end
  174. ip = "#{$subnet}.#{i+100}"
  175. node.vm.network :private_network, ip: ip,
  176. :libvirt__guest_ipv6 => 'yes',
  177. :libvirt__ipv6_address => "#{$subnet_ipv6}::#{i+100}",
  178. :libvirt__ipv6_prefix => "64",
  179. :libvirt__forward_mode => "none",
  180. :libvirt__dhcp_enabled => false
  181. # Disable swap for each vm
  182. node.vm.provision "shell", inline: "swapoff -a"
  183. # ubuntu1804 and ubuntu2004 have IPv6 explicitly disabled. This undoes that.
  184. if ["ubuntu1804", "ubuntu2004"].include? $os
  185. node.vm.provision "shell", inline: "rm -f /etc/modprobe.d/local.conf"
  186. node.vm.provision "shell", inline: "sed -i '/net.ipv6.conf.all.disable_ipv6/d' /etc/sysctl.d/99-sysctl.conf /etc/sysctl.conf"
  187. end
  188. # Disable firewalld on oraclelinux/redhat vms
  189. if ["oraclelinux","oraclelinux8","rhel7","rhel8"].include? $os
  190. node.vm.provision "shell", inline: "systemctl stop firewalld; systemctl disable firewalld"
  191. end
  192. host_vars[vm_name] = {
  193. "ip": ip,
  194. "flannel_interface": "eth1",
  195. "kube_network_plugin": $network_plugin,
  196. "kube_network_plugin_multus": $multi_networking,
  197. "download_run_once": $download_run_once,
  198. "download_localhost": "False",
  199. "download_cache_dir": ENV['HOME'] + "/kubespray_cache",
  200. # Make kubespray cache even when download_run_once is false
  201. "download_force_cache": $download_force_cache,
  202. # Keeping the cache on the nodes can improve provisioning speed while debugging kubespray
  203. "download_keep_remote_cache": "False",
  204. "docker_rpm_keepcache": "1",
  205. # These two settings will put kubectl and admin.config in $inventory/artifacts
  206. "kubeconfig_localhost": "True",
  207. "kubectl_localhost": "True",
  208. "local_path_provisioner_enabled": "#{$local_path_provisioner_enabled}",
  209. "local_path_provisioner_claim_root": "#{$local_path_provisioner_claim_root}",
  210. "ansible_ssh_user": SUPPORTED_OS[$os][:user]
  211. }
  212. # Only execute the Ansible provisioner once, when all the machines are up and ready.
  213. # And limit the action to gathering facts, the full playbook is going to be ran by testcases_run.sh
  214. if i == $num_instances
  215. node.vm.provision "ansible" do |ansible|
  216. ansible.playbook = $playbook
  217. ansible.verbose = $ansible_verbosity
  218. $ansible_inventory_path = File.join( $inventory, "hosts.ini")
  219. if File.exist?($ansible_inventory_path)
  220. ansible.inventory_path = $ansible_inventory_path
  221. end
  222. ansible.become = true
  223. ansible.limit = "all,localhost"
  224. ansible.host_key_checking = false
  225. ansible.raw_arguments = ["--forks=#{$num_instances}", "--flush-cache", "-e ansible_become_pass=vagrant"]
  226. ansible.host_vars = host_vars
  227. if $ansible_tags != ""
  228. ansible.tags = [$ansible_tags]
  229. end
  230. ansible.groups = {
  231. "etcd" => ["#{$instance_name_prefix}-[1:#{$etcd_instances}]"],
  232. "kube_control_plane" => ["#{$instance_name_prefix}-[1:#{$kube_master_instances}]"],
  233. "kube_node" => ["#{$instance_name_prefix}-[1:#{$kube_node_instances}]"],
  234. "k8s_cluster:children" => ["kube_control_plane", "kube_node"],
  235. }
  236. end
  237. end
  238. end
  239. end
  240. end