diff --git a/.travis.yml b/.travis.yml
index 00e27304ec8d3e27413a82b8fa3a9f4c933e1fe8..6c26cd110b1932bd4449cc4230bbc1a156f9cc70 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -58,18 +58,18 @@ env:
       CLOUD_IMAGE=rhel-7-sudo
       CLOUD_REGION=europe-west1-b
 
-    # Ubuntu 14.04
+    # Ubuntu 16.04
     - >-
       KUBE_NETWORK_PLUGIN=flannel
-      CLOUD_IMAGE=ubuntu-1404-trusty
+      CLOUD_IMAGE=ubuntu-1604-xenial
       CLOUD_REGION=us-central1-c
     - >-
       KUBE_NETWORK_PLUGIN=calico
-      CLOUD_IMAGE=ubuntu-1404-trusty
+      CLOUD_IMAGE=ubuntu-1604-xenial
       CLOUD_REGION=us-east1-d
     - >-
       KUBE_NETWORK_PLUGIN=weave
-      CLOUD_IMAGE=ubuntu-1404-trusty
+      CLOUD_IMAGE=ubuntu-1604-xenial
       CLOUD_REGION=asia-east1-c
 
     # Ubuntu 15.10
@@ -87,11 +87,6 @@ env:
       CLOUD_REGION=us-east1-d
 
 
-matrix:
-  allow_failures:
-    - env: KUBE_NETWORK_PLUGIN=weave CLOUD_IMAGE=ubuntu-1404-trusty CLOUD_REGION=asia-east1-c
-    - env: KUBE_NETWORK_PLUGIN=calico CLOUD_IMAGE=ubuntu-1404-trusty CLOUD_REGION=us-east1-d
-
 before_install:
   # Install Ansible.
   - pip install --user boto -U
diff --git a/README.md b/README.md
index 8e4f8ae39b656a9ef6ae4bbf5af7bccdb720788d..67e183ae8e9d3ad467e84cda75e3fd607eecda07 100644
--- a/README.md
+++ b/README.md
@@ -9,9 +9,16 @@
 - Support most popular **Linux distributions**
 - **Continuous integration tests**
 
-To create a cluster in vagrant simply run `vagrant up`
 
-For an easy way to use it, check out [**kargo-cli**](https://github.com/kubespray/kargo-cli) </br>
+To deploy the cluster you can use :
+
+* [**kargo-cli**](https://github.com/kubespray/kargo-cli)
+* **vagrant** by simply running `vagrant up`
+* **Ansible** usual commands
+
 A complete **documentation** can be found [**here**](https://docs.kubespray.io)
 
-[![Build Status](https://travis-ci.org/kubespray/kargo.svg)](https://travis-ci.org/kubespray/kargo)
+if you have any question you can **chat** with us [**here**](https://chat.kubespray.io)
+
+[![Build Status](https://travis-ci.org/kubespray/kargo.svg)](https://travis-ci.org/kubespray/kargo) </br>
+CI tests sponsored by Google (GCE), and [TeutoNet](https://teuto.net/) for OpenStack.
diff --git a/roles/docker/vars/ubuntu-16.04.yml b/roles/docker/vars/ubuntu-16.04.yml
new file mode 100644
index 0000000000000000000000000000000000000000..c019c7696fda46b51993400203f4c716e1884ce2
--- /dev/null
+++ b/roles/docker/vars/ubuntu-16.04.yml
@@ -0,0 +1,27 @@
+---
+docker_version: 1.11
+docker_kernel_min_version: '3.2'
+
+# https://apt.dockerproject.org/repo/dists/ubuntu-trusty/main/filelist
+docker_versioned_pkg:
+  latest: docker-engine
+  1.11: docker-engine=1.11.1-0~{{ ansible_distribution_release|lower }}
+
+docker_package_info:
+  pkg_mgr: apt
+  pkgs:
+    - "{{ docker_versioned_pkg[docker_version] }}"
+
+docker_repo_key_info:
+  pkg_key: apt_key
+  keyserver: hkp://p80.pool.sks-keyservers.net:80
+  repo_keys:
+    - 58118E89F3A912897C070ADBF76221572C52609D
+
+docker_repo_info:
+  pkg_repo: apt_repository
+  repos:
+    - >
+       deb https://apt.dockerproject.org/repo
+       {{ ansible_distribution|lower }}-{{ ansible_distribution_release|lower }}
+       main
diff --git a/roles/download/defaults/main.yml b/roles/download/defaults/main.yml
index a6e11a7593e407fb3c60b09f916d99bb7b8e1c26..30952f691190fefaa417d8954410bc9b71fff0af 100644
--- a/roles/download/defaults/main.yml
+++ b/roles/download/defaults/main.yml
@@ -2,7 +2,7 @@
 local_release_dir: /tmp
 
 # Versions
-kube_version: v1.2.2
+kube_version: "v1.2.4"
 etcd_version: v2.2.5
 calico_version: v0.19.0
 calico_cni_version: v1.2.1
@@ -25,9 +25,9 @@ calico_cni_checksum: "b2eeb45fdfce58394e3a0019dd4b74bebe4bb35ed6d7c399213297594f
 calico_cni_ipam_checksum: "fd122bee97af3ed86fc18fa4d797da29be3a5857a526aa154b433e50d7b36845"
 weave_checksum: "28d2c4e2b1ad8600da69882501eba697679aea10a5e61c769aa3a9ee72b0d89a"
 etcd_checksum: "aa6037406257d2a1bc48ffa769afe7a4f8a04cc1ffcd36ef84f9ee8bc4eca756"
-kubectl_checksum: "473e6924569fba30d4a50cecdc2cae5f31d97d1f662463e85b74a472105dcff4"
-kubelet_checksum: "f16827dc7e7c82f0e215f0fc73eb01e2dfe91a2ec83f9cbcaf8d37c91b64fd3b"
-kube_apiserver_checksum: "eb1bfd8b877052cbd1991b8c429a1d06661f4cb019905e20e128174f724e16de"
+kubectl_checksum: "dac61fbd506f7a17540feca691cd8a9d9d628d59661eebce788a50511f578897"
+kubelet_checksum: "4adaf40592248eef6fd4fa126464915ea41e624a70dc77178089760ed235e341"
+kube_apiserver_checksum: "6ac99b36b02968459e026fcfc234207c66064b5e11816b69dd8fc234b2ffec1e"
 
 downloads:
   - name: calico
diff --git a/roles/kubernetes/node/defaults/main.yml b/roles/kubernetes/node/defaults/main.yml
index 63320f6fefeac5a576299ceb6fb4c4205a6be1c4..e96e7115bab9a951d5eab01b0582a37723f638bb 100644
--- a/roles/kubernetes/node/defaults/main.yml
+++ b/roles/kubernetes/node/defaults/main.yml
@@ -32,7 +32,7 @@ dns_domain: "{{ cluster_name }}"
 kube_proxy_mode: userspace
 
 hyperkube_image_repo: quay.io/smana/kubernetes-hyperkube
-hyperkube_image_tag: v1.2.2
+hyperkube_image_tag: "v1.2.4"
 
 # IP address of the DNS server.
 # Kubernetes will create a pod with several containers, serving as the DNS
diff --git a/roles/uploads/defaults/main.yml b/roles/uploads/defaults/main.yml
index 177cd13295775c83b6d04c663e7aef33750bcbfc..af1176921bd14f64d42e060211e16925ff937d61 100644
--- a/roles/uploads/defaults/main.yml
+++ b/roles/uploads/defaults/main.yml
@@ -2,7 +2,7 @@
 local_release_dir: /tmp
 
 # Versions
-kube_version: v1.2.2
+kube_version: "v1.2.4"
 etcd_version: v2.2.5
 calico_version: v0.19.0
 calico_cni_version: v1.2.1
@@ -22,9 +22,9 @@ calico_cni_checksum: "b2eeb45fdfce58394e3a0019dd4b74bebe4bb35ed6d7c399213297594f
 calico_cni_ipam_checksum: "fd122bee97af3ed86fc18fa4d797da29be3a5857a526aa154b433e50d7b36845"
 weave_checksum: "28d2c4e2b1ad8600da69882501eba697679aea10a5e61c769aa3a9ee72b0d89a"
 etcd_checksum: "aa6037406257d2a1bc48ffa769afe7a4f8a04cc1ffcd36ef84f9ee8bc4eca756"
-kubectl_checksum: "473e6924569fba30d4a50cecdc2cae5f31d97d1f662463e85b74a472105dcff4"
-kubelet_checksum: "f16827dc7e7c82f0e215f0fc73eb01e2dfe91a2ec83f9cbcaf8d37c91b64fd3b"
-kube_apiserver_checksum: "eb1bfd8b877052cbd1991b8c429a1d06661f4cb019905e20e128174f724e16de"
+kubectl_checksum: "dac61fbd506f7a17540feca691cd8a9d9d628d59661eebce788a50511f578897"
+kubelet_checksum: "4adaf40592248eef6fd4fa126464915ea41e624a70dc77178089760ed235e341"
+kube_apiserver_checksum: "6ac99b36b02968459e026fcfc234207c66064b5e11816b69dd8fc234b2ffec1e"
 
 downloads:
   - name: calico
diff --git a/roles/uploads/tasks/main.yml b/roles/uploads/tasks/main.yml
index 000e1f9a276cc4e092248464ed6304209e4bbd8c..279d26dd58c6282660e2377dab6a03d2fd75de4d 100644
--- a/roles/uploads/tasks/main.yml
+++ b/roles/uploads/tasks/main.yml
@@ -1,4 +1,22 @@
 ---
+- name: Create the checksum file
+  lineinfile:
+    create: yes
+    dest: "{{ role_path }}/{{ kube_version }}_k8s-sha256"
+    line: '{{item.name}}:{{item.sha256}}'
+  with_items: '{{downloads}}'
+  when: item.name in ["kubernetes-kubelet", "kubernetes-kubectl", "kubernetes-apiserver"]
+
+- name: Upload checksum file on GS
+  gc_storage:
+    bucket: kargo
+    object: "{{ kube_version }}_k8s-sha256"
+    src: "{{ role_path }}/{{ kube_version }}_k8s-sha256"
+    mode: put
+    permission: public-read
+    gs_access_key: "changeme"
+    gs_secret_key: "changeme"
+
 - name: Create dest directories
   file: path={{local_release_dir}}/{{item.dest|dirname}} state=directory recurse=yes
   with_items: '{{downloads}}'
diff --git a/scripts/change_k8s_version.sh b/scripts/change_k8s_version.sh
new file mode 100755
index 0000000000000000000000000000000000000000..8c00e7168454ec6a1d9b2a7d2d76570043e558f2
--- /dev/null
+++ b/scripts/change_k8s_version.sh
@@ -0,0 +1,117 @@
+#!/bin/bash
+
+# This file is part of Kargo.
+#
+#    Foobar is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU General Public License as published by
+#    the Free Software Foundation, either version 3 of the License, or
+#    (at your option) any later version.
+#
+#    Foobar is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU General Public License for more details.
+#
+#    You should have received a copy of the GNU General Public License
+#    along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+
+#color variables
+txtbld=$(tput bold)             # Bold
+bldred=${txtbld}$(tput setaf 1) #  red
+bldgre=${txtbld}$(tput setaf 2) #  green
+bldylw=${txtbld}$(tput setaf 3) #  yellow
+txtrst=$(tput sgr0)             # Reset
+err=${bldred}ERROR${txtrst}
+info=${bldgre}INFO${txtrst}
+warn=${bldylw}WARNING${txtrst}
+
+usage()
+{
+    cat << EOF
+Update ansible playbook with a specific kubernetes version
+
+Usage : $(basename $0) -v <k8s version>
+      -h | --help         : Show this message
+      -i | --init         : Initial upgrade (download binaries)
+      -v | --version      : Kubernetes version
+               
+               ex : switch to kubernetes v1.2.4
+               $(basename $0) -v v1.2.4
+EOF
+}
+
+# Options parsing
+while (($#)); do
+    case "$1" in
+        -h | --help)   usage;   exit 0;;
+        -i | --init) INIT=1; shift;;
+        -v | --version) VERS=${2}; shift 2;;
+        *)
+            usage
+            echo "ERROR : Unknown option"
+            exit 3
+        ;;
+    esac
+done
+
+if [ -z ${VERS} ]; then
+    usage
+    echo -e "\n${err}: The option version must be defined"
+    exit 3
+else
+   if ! [[ ${VERS} =~ ^v[0-9]\.[0-9]\.[0-9]$ ]]; then
+       echo -e "\n${err}: Invalid version format (ex: v1.2.4)"
+       exit 1
+   fi
+fi
+
+UPLOAD_VARFILE="roles/uploads/defaults/main.yml"
+DOWNLOAD_VARFILE="roles/download/defaults/main.yml"
+K8S_BIN="kubelet kubectl kube-apiserver"
+
+if [[ ${INIT} -eq 1 ]]; then
+   DOWNLOAD_URL=https://storage.googleapis.com/kubernetes-release/release/${VERS}/bin/linux/amd64
+   TMP_DIR=$(mktemp -d --tmpdir kubernetes_tmpbin_XXXXXXX)
+   sed -i "s/^hyperkube_image_tag.*$/hyperkube_image_tag: \"${VERS}\"/" roles/kubernetes/node/defaults/main.yml
+   trap 'rm -rf "${tmpdir}"' EXIT
+   cd "${tmpdir}"
+
+   for BIN in ${K8S_BIN}; do
+       curl -s -o ${BIN} ${DOWNLOAD_URL}/${BIN}
+       if [ $? -ne 0 ]; then
+           echo -e "\n${err}: Downloading ${BIN} failed! Try again"
+           exit 1
+       else
+           echo -e "\n${info}: ${BIN} downloaded successfuly"
+       fi
+   done
+
+   for varfile in ${UPLOAD_VARFILE} ${DOWNLOAD_VARFILE}; do
+       sed -i "s/^kube_version.*$/kube_version: \"${VERS}\"/" ${varfile}
+   
+       for BIN in ${K8S_BIN}; do
+           CHECKSUM=$(sha256sum ${BIN} | cut -d' ' -f1)
+           BIN=$(echo ${BIN} | tr '-' '_')
+           sed  -i "s/^${BIN}_checksum.*$/${BIN}_checksum: \"${CHECKSUM}\"/" ${varfile}
+       done
+   done
+   
+   rm -rf "${tmpdir}"
+else
+   CHECKSUM_URL=https://storage.googleapis.com/kargo/${VERS}_k8s-sha256
+   sed -i "s/^hyperkube_image_tag.*$/hyperkube_image_tag: \"${VERS}\"/" roles/kubernetes/node/defaults/main.yml
+    for varfile in ${UPLOAD_VARFILE} ${DOWNLOAD_VARFILE}; do
+        sed -i "s/^kube_version.*$/kube_version: \"${VERS}\"/" ${varfile}
+        for BIN in ${K8S_BIN}; do
+            if [[ "${BIN}" =~ "apiserver" ]]; then
+                BIN="apiserver"
+            fi
+            line=$(curl -sk ${CHECKSUM_URL} | grep ${BIN})
+            CHECKSUM=$(echo ${line} | cut -d':' -f2)
+            if [[ "${BIN}" =~ "apiserver" ]]; then
+                BIN="kube_apiserver"
+            fi
+            sed  -i "s/^${BIN}_checksum.*$/${BIN}_checksum: \"${CHECKSUM}\"/" ${varfile}
+        done
+    done
+fi
diff --git a/tests/cloud_playbooks/create-aws.yml b/tests/cloud_playbooks/create-aws.yml
index 88d3326d58aec6d32da056e873d73bae914afbbf..0ff198405f05e8dca0c6fab85cf2bf0fcc712481 100644
--- a/tests/cloud_playbooks/create-aws.yml
+++ b/tests/cloud_playbooks/create-aws.yml
@@ -30,4 +30,4 @@
       port: 22
       timeout: 300
       state: started
-    with_items: ec2.instances
+    with_items: "{{ec2.instances}}"
diff --git a/tests/cloud_playbooks/create-gce.yml b/tests/cloud_playbooks/create-gce.yml
index 18b5f51a3cdb8aeaa7704d7ee76cda5ee82d09b2..840cf2e7c318a5c57bc9c617ef853fd937ca70e4 100644
--- a/tests/cloud_playbooks/create-gce.yml
+++ b/tests/cloud_playbooks/create-gce.yml
@@ -30,4 +30,4 @@
 
     - name: Wait for SSH to come up
       wait_for: host={{item.public_ip}} port=22 delay=10 timeout=180 state=started
-      with_items: gce.instance_data
+      with_items: "{{gce.instance_data}}"
diff --git a/tests/testcases/020_check-create-pod.yml b/tests/testcases/020_check-create-pod.yml
index 4e40273594a826f21acae4819b66b738d6e09c6f..590fe9a8c14698344145418b0f194f9b25c825a8 100644
--- a/tests/testcases/020_check-create-pod.yml
+++ b/tests/testcases/020_check-create-pod.yml
@@ -8,6 +8,6 @@
   - name: Pods are running
     shell: "/usr/local/bin/kubectl get pods --no-headers -o json"
     register: run_pods_log
-    until: (run_pods_log.stdout | from_json)['items'] | map(attribute = 'status.phase') | join(',') == "Running,Running"
+    until: [ '(run_pods_log.stdout | from_json)["items"] | map(attribute = "status.phase") | join(",") == "Running,Running"' ]
     retries: 24
     delay: 5
diff --git a/tests/testcases/030_check-network.yml b/tests/testcases/030_check-network.yml
index a65d5e1e5c30df2b4736e70f20b07012d5f51f5f..528168198ff3f40f0b775d92a0a3284e335ebee8 100644
--- a/tests/testcases/030_check-network.yml
+++ b/tests/testcases/030_check-network.yml
@@ -14,7 +14,7 @@
   - name: Check pods IP are in correct network
     assert:
       that: item | ipaddr(kube_pods_subnet)
-    with_items: pod_ips
+    with_items: "{{pod_ips}}"
 
 
   - name: Ping between pods is working