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 d6fd0d2aca 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.
This commit is contained in:
Johnny Halfmoon
2019-06-10 20:21:07 +02:00
committed by Kubernetes Prow Robot
parent 14141ec137
commit 23c9071c30
15 changed files with 531 additions and 424 deletions

View File

@@ -1,141 +1,37 @@
---
- name: container_download | Make download decision if pull is required by tag or sha256
include: set_docker_image_facts.yml
when:
- download.enabled
- download.container
tags:
- block:
- name: sync_container | Gather information about the current image (how to download, is it cached etc.)
import_tasks: set_container_facts.yml
tags:
- facts
- name: container_download | Set file name of container tarballs
set_fact:
fname: "{{ local_release_dir }}/containers/{{ download.repo|regex_replace('/|\0|:', '_') }}:{{ download.tag|default(download.sha256)|regex_replace('/|\0|:', '_') }}.tar"
run_once: true
when:
- download.enabled
- download.container
- download_run_once
tags:
- facts
- name: "container_download | Set default value for 'container_changed' to false"
set_fact:
container_changed: "{{ pull_required|default(false) }}"
when:
- download.enabled
- download.container
- download_run_once
- name: "container_download | Update the 'container_changed' fact"
set_fact:
container_changed: "{{ pull_required|default(false) or not 'up to date' in pull_task_result.stdout }}"
when:
- download.enabled
- download.container
- download_run_once
- pull_required|default(download_always_pull)
run_once: "{{ download_run_once }}"
tags:
- facts
- name: container_download | Stat saved container image
stat:
path: "{{ fname }}"
register: img
changed_when: false
delegate_to: "{{ download_delegate }}"
delegate_facts: no
become: false
run_once: true
when:
- download.enabled
- download.container
- download_run_once
- any_pull_required | default(download_always_pull)
tags:
- facts
- name: container_download | save container images
shell: "{{ docker_bin_dir }}/docker save {{ pull_args }} | gzip -{{ download_compress }} > {{ fname }}"
delegate_to: "{{ download_delegate }}"
delegate_facts: no
register: saved
failed_when: saved.stderr
when:
- download.enabled
- download.container
- download_run_once
- any_pull_required | default(download_always_pull)
- (ansible_os_family not in ["CoreOS", "Container Linux by CoreOS"] or download_delegate == "localhost")
- (container_changed or not img.stat.exists)
- name: container_download | create container images directory on ansible host
file:
state: directory
path: "{{ fname | dirname }}"
delegate_to: localhost
delegate_facts: no
run_once: true
become: false
when:
- download.enabled
- download.container
- download_run_once
- any_pull_required | default(download_always_pull)
- name: sync_container | Upload container image to node
synchronize:
src: "{{ image_path_cached }}"
dest: "{{ image_path_final }}"
use_ssh_args: "{{ has_bastion | default(false) }}"
mode: push
delegate_facts: no
register: get_task
become: true
until: get_task is succeeded
retries: 4
delay: "{{ retry_stagger | random + 3 }}"
when:
- ansible_os_family not in ["CoreOS", "Container Linux by CoreOS"]
- inventory_hostname == download_delegate
- download_delegate != "localhost"
- saved.changed
- name: container_download | copy container images to ansible host
synchronize:
src: "{{ fname }}"
dest: "{{ fname }}"
use_ssh_args: "{{ has_bastion | default(false) }}"
mode: pull
private_key: "{{ ansible_ssh_private_key_file }}"
become: false
when:
- download.enabled
- download.container
- download_run_once
- name: sync_container | Load container image into docker
shell: "{{ docker_bin_dir }}/docker load < {{ image_path_final }}"
when:
- ansible_os_family not in ["CoreOS", "Container Linux by CoreOS"]
- inventory_hostname == download_delegate
- download_delegate != "localhost"
- saved.changed
- name: container_download | upload container images to nodes
synchronize:
src: "{{ fname }}"
dest: "{{ fname }}"
use_ssh_args: "{{ has_bastion | default(false) }}"
mode: push
become: true
register: get_task
until: get_task is succeeded
retries: 4
delay: "{{ retry_stagger | random + 3 }}"
when:
- download.enabled
- download.container
- download_run_once
- pull_required|default(download_always_pull)
- (ansible_os_family not in ["CoreOS", "Container Linux by CoreOS"] and
inventory_hostname != download_delegate or
download_delegate == "localhost")
tags:
- upload
- upgrade
- name: sync_container | Remove container image from cache
file:
state: absent
path: "{{ image_path_final }}"
when:
- not download_keep_remote_cache
- ansible_os_family not in ["CoreOS", "Container Linux by CoreOS"]
- name: container_download | load container images
shell: "{{ docker_bin_dir }}/docker load < {{ fname }}"
when:
- download.enabled
- download.container
- download_run_once
- pull_required|default(download_always_pull)
- (ansible_os_family not in ["CoreOS", "Container Linux by CoreOS"] and
inventory_hostname != download_delegate or download_delegate == "localhost")
tags:
- upload
- upgrade
- upload