diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 7fbcbc9848c5297bab28c9685e429a8050613474..c674c2e9936f2892fd1a4ddc9bf021cd89172317 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -94,9 +94,11 @@ before_script:
     # Check out latest tag if testing upgrade
     # Uncomment when gitlab kargo repo has tags
     #- test "${UPGRADE_TEST}" != "false" && git fetch --all && git checkout $(git describe --tags $(git rev-list --tags --max-count=1))
-    - test "${UPGRADE_TEST}" != "false" && git checkout 72ae7638bcc94c66afa8620dfa4ad9a9249327ea
+    - test "${UPGRADE_TEST}" != "false" && git checkout ba0a03a8ba2d97a73d06242ec4bb3c7e2012e58c
     # Checkout the CI vars file so it is available
     - test "${UPGRADE_TEST}" != "false" && git checkout "${CI_BUILD_REF}" tests/files/${CI_JOB_NAME}.yml
+    # Workaround https://github.com/kubernetes-incubator/kubespray/issues/2021
+    - 'sh -c "echo ignore_assert_errors: true | tee -a tests/files/${CI_JOB_NAME}.yml"'
 
 
     # Create cluster
diff --git a/README.md b/README.md
index abd1548abe556b838809e76fc670d9e91339d214..0554a5fc076448ccb08d7218d7e02fd21664aff9 100644
--- a/README.md
+++ b/README.md
@@ -54,7 +54,7 @@ Versions of supported components
 --------------------------------
 
 
-[kubernetes](https://github.com/kubernetes/kubernetes/releases) v1.8.4 <br>
+[kubernetes](https://github.com/kubernetes/kubernetes/releases) v1.9.0 <br>
 [etcd](https://github.com/coreos/etcd/releases) v3.2.4 <br>
 [flanneld](https://github.com/coreos/flannel/releases) v0.8.0 <br>
 [calico](https://docs.projectcalico.org/v2.5/releases/) v2.5.0 <br>
diff --git a/inventory/group_vars/k8s-cluster.yml b/inventory/group_vars/k8s-cluster.yml
index f8210f2914587b5a07a8d9efc5084f5bb092a930..43b2d3e322a75a4b8b493d50ead1ac4bd20c50bf 100644
--- a/inventory/group_vars/k8s-cluster.yml
+++ b/inventory/group_vars/k8s-cluster.yml
@@ -23,7 +23,7 @@ kube_users_dir: "{{ kube_config_dir }}/users"
 kube_api_anonymous_auth: false
 
 ## Change this to use another Kubernetes version, e.g. a current beta release
-kube_version: v1.8.4
+kube_version: v1.9.0
 
 # Where the binaries will be downloaded.
 # Note: ensure that you've enough disk space (about 1G)
diff --git a/roles/download/defaults/main.yml b/roles/download/defaults/main.yml
index b642a88010f5f69b7dd1bdc469d6f4875ff7cf87..8f5c5d3a71401604fe66c7debf4a2ab70f2a45cf 100644
--- a/roles/download/defaults/main.yml
+++ b/roles/download/defaults/main.yml
@@ -24,7 +24,7 @@ download_always_pull: False
 download_delegate: "{% if download_localhost %}localhost{% else %}{{groups['kube-master'][0]}}{% endif %}"
 
 # Versions
-kube_version: v1.8.4
+kube_version: v1.9.0
 kubeadm_version: "{{ kube_version }}"
 etcd_version: v3.2.4
 # TODO(mattymo): Move calico versions to roles/network_plugins/calico/defaults
@@ -36,27 +36,21 @@ calico_policy_version: "v1.0.0"
 calico_rr_version: "v0.4.0"
 flannel_version: "v0.9.1"
 flannel_cni_version: "v0.3.0"
+istio_version: "0.2.6"
+vault_version: 0.8.1
 weave_version: 2.0.5
 pod_infra_version: 3.0
 contiv_version: 1.1.7
 
 # Download URLs
+istioctl_download_url: "https://storage.googleapis.com/istio-release/releases/{{ istio_version }}/istioctl/istioctl-linux"
 kubeadm_download_url: "https://storage.googleapis.com/kubernetes-release/release/{{ kubeadm_version }}/bin/linux/amd64/kubeadm"
+vault_download_url: "https://releases.hashicorp.com/vault/{{ vault_version }}/vault_{{ vault_version }}_linux_amd64.zip"
 
 # Checksums
-kubeadm_checksum: "08c93bb83c1af8703d49027b863fee08721cb96900f8d70d4d45b50dd1e5bc2c"
-
-istio_version: "0.2.6"
-
-istioctl_download_url: "https://storage.googleapis.com/istio-release/releases/{{ istio_version }}/istioctl/istioctl-linux"
 istioctl_checksum: fd703063c540b8c0ab943f478c05ab257d88ae27224c746a27d0526ddbf7c370
-
-vault_version: 0.8.1
+kubeadm_checksum: 069e386f620e7274e114226ab7532c2320be7f65328c1e55b23a69b73122b828
 vault_binary_checksum: 3c4d70ba71619a43229e65c67830e30e050eab7a81ac6b28325ff707e5914188
-vault_download_url: "https://releases.hashicorp.com/vault/{{ vault_version }}/vault_{{ vault_version }}_linux_amd64.zip"
-vault_image_repo: "vault"
-vault_image_tag: "{{ vault_version }}"
-
 
 # Containers
 etcd_image_repo: "quay.io/coreos/etcd"
@@ -127,6 +121,8 @@ helm_image_repo: "lachlanevenson/k8s-helm"
 helm_image_tag: "{{ helm_version }}"
 tiller_image_repo: "gcr.io/kubernetes-helm/tiller"
 tiller_image_tag: "{{ helm_version }}"
+vault_image_repo: "vault"
+vault_image_tag: "{{ vault_version }}"
 
 downloads:
   netcheck_server:
diff --git a/roles/kubernetes-apps/persistent_volumes/openstack/templates/openstack-storage-class.yml b/roles/kubernetes-apps/persistent_volumes/openstack/templates/openstack-storage-class.yml
index c643cfa09bee3fdd90013e2d023fd56eb53ae819..02d39dd976020f714fdec2dd890a5ae84bf3d0a7 100644
--- a/roles/kubernetes-apps/persistent_volumes/openstack/templates/openstack-storage-class.yml
+++ b/roles/kubernetes-apps/persistent_volumes/openstack/templates/openstack-storage-class.yml
@@ -1,3 +1,4 @@
+---
 kind: StorageClass
 apiVersion: storage.k8s.io/v1
 metadata:
diff --git a/roles/kubernetes/kubeadm/tasks/main.yml b/roles/kubernetes/kubeadm/tasks/main.yml
index 14a57710653403c34e552894eb2f712fc1e1125c..7be760458f26855bf1d72499145fea8bef263f6b 100644
--- a/roles/kubernetes/kubeadm/tasks/main.yml
+++ b/roles/kubernetes/kubeadm/tasks/main.yml
@@ -16,6 +16,13 @@
     path: "{{ kube_config_dir }}/kubelet.conf"
   register: kubelet_conf
 
+
+- name: Calculate kubeadm CA cert hash
+  shell: openssl x509 -pubkey -in {{ kube_config_dir }}/ssl/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
+  register: kubeadm_ca_hash
+  delegate_to: "{{ groups['kube-master'][0] }}"
+  run_once: true
+
 - name: Create kubeadm client config
   template:
     src: kubeadm-client.conf.j2
@@ -25,7 +32,10 @@
   register: kubeadm_client_conf
 
 - name: Join to cluster if needed
-  command: "{{ bin_dir }}/kubeadm join --config {{ kube_config_dir}}/kubeadm-client.conf --skip-preflight-checks"
+  command: >-
+    {{ bin_dir }}/kubeadm join
+    --config {{ kube_config_dir}}/kubeadm-client.conf
+    --ignore-preflight-errors=all
   register: kubeadm_join
   when: not is_kube_master and (kubeadm_client_conf.changed or not kubelet_conf.stat.exists)
 
diff --git a/roles/kubernetes/kubeadm/templates/kubeadm-client.conf.j2 b/roles/kubernetes/kubeadm/templates/kubeadm-client.conf.j2
index 3c8ede9ad8a8eb28916c695b2bd4df418ae38ca7..18c6c2af603dea797e074bcfa062d2fe4dfbcf01 100644
--- a/roles/kubernetes/kubeadm/templates/kubeadm-client.conf.j2
+++ b/roles/kubernetes/kubeadm/templates/kubeadm-client.conf.j2
@@ -4,3 +4,5 @@ caCertPath: {{ kube_config_dir }}/ssl/ca.crt
 token: {{ kubeadm_token }}
 discoveryTokenAPIServers:
 - {{ kubeadm_discovery_address | replace("https://", "")}}
+DiscoveryTokenCACertHashes:
+- sha256:{{ kubeadm_ca_hash.stdout }}
diff --git a/roles/kubernetes/master/tasks/kubeadm-setup.yml b/roles/kubernetes/master/tasks/kubeadm-setup.yml
index c901bc4fa02b9614f77c6b94e854eb6cadbc7460..1405a9dd06a9e83994238b34981d8c1d0890dcb6 100644
--- a/roles/kubernetes/master/tasks/kubeadm-setup.yml
+++ b/roles/kubernetes/master/tasks/kubeadm-setup.yml
@@ -72,7 +72,7 @@
   register: kubeadm_config
 
 - name: kubeadm | Initialize first master
-  command: timeout -k 240s 240s {{ bin_dir }}/kubeadm init --config={{ kube_config_dir }}/kubeadm-config.yaml --skip-preflight-checks
+  command: timeout -k 240s 240s {{ bin_dir }}/kubeadm init --config={{ kube_config_dir }}/kubeadm-config.yaml --ignore-preflight-errors=all
   register: kubeadm_init
   # Retry is because upload config sometimes fails
   retries: 3
@@ -86,7 +86,7 @@
     {{ bin_dir }}/kubeadm
     upgrade apply -y {{ kube_version }}
     --config={{ kube_config_dir }}/kubeadm-config.yaml
-    --skip-preflight-checks
+    --ignore-preflight-errors=all
     --allow-experimental-upgrades
     --allow-release-candidate-upgrades
   register: kubeadm_upgrade
@@ -135,7 +135,7 @@
   when: inventory_hostname != groups['kube-master']|first
 
 - name: kubeadm | Init other uninitialized masters
-  command: timeout -k 240s 240s {{ bin_dir }}/kubeadm init --config={{ kube_config_dir }}/kubeadm-config.yaml --skip-preflight-checks
+  command: timeout -k 240s 240s {{ bin_dir }}/kubeadm init --config={{ kube_config_dir }}/kubeadm-config.yaml --ignore-preflight-errors=all
   register: kubeadm_init
   when: inventory_hostname != groups['kube-master']|first and not kubeadm_ca.stat.exists
   failed_when: kubeadm_init.rc != 0 and "field is immutable" not in kubeadm_init.stderr
@@ -147,7 +147,7 @@
     {{ bin_dir }}/kubeadm
     upgrade apply -y {{ kube_version }}
     --config={{ kube_config_dir }}/kubeadm-config.yaml
-    --skip-preflight-checks
+    --ignore-preflight-errors=all
     --allow-experimental-upgrades
     --allow-release-candidate-upgrades
   register: kubeadm_upgrade
diff --git a/roles/kubernetes/master/templates/kubeadm-config.yaml.j2 b/roles/kubernetes/master/templates/kubeadm-config.yaml.j2
index 774a7810febfcc83967e39a46a0f9f70c5268c24..26e3b46a46de4db10a9b88056f121dd3f21ba510 100644
--- a/roles/kubernetes/master/templates/kubeadm-config.yaml.j2
+++ b/roles/kubernetes/master/templates/kubeadm-config.yaml.j2
@@ -16,7 +16,9 @@ networking:
   serviceSubnet: {{ kube_service_addresses }}
   podSubnet: {{ kube_pods_subnet }}
 kubernetesVersion: {{ kube_version }}
-cloudProvider: {{ cloud_provider|default('') }}
+{% if cloud_provider is defined and cloud_provider != "gce" %}
+cloudProvider: {{ cloud_provider }}
+{% endif %}
 authorizationModes:
 {% for mode in authorization_modes %}
 - {{ mode }}
diff --git a/roles/kubespray-defaults/defaults/main.yaml b/roles/kubespray-defaults/defaults/main.yaml
index 579eb7b832d08f7aada2d1dc679f05457e6ec0ac..f0febcf3957994007ba0242eb9d62ffc266a35eb 100644
--- a/roles/kubespray-defaults/defaults/main.yaml
+++ b/roles/kubespray-defaults/defaults/main.yaml
@@ -13,7 +13,7 @@ kube_api_anonymous_auth: false
 is_atomic: false
 
 ## Change this to use another Kubernetes version, e.g. a current beta release
-kube_version: v1.8.4
+kube_version: v1.9.0
 
 # Set to true to allow pre-checks to fail and continue deployment
 ignore_assert_errors: false
diff --git a/tests/files/centos7-calico-ha.yml b/tests/files/centos7-calico-ha.yml
index a34ab2dfb4f5b989f01bfa48fa5cb5c67198e83c..0bca5842e692dc6f994c940805fdc330fbe1c55a 100644
--- a/tests/files/centos7-calico-ha.yml
+++ b/tests/files/centos7-calico-ha.yml
@@ -1,7 +1,8 @@
 # Instance settings
 cloud_image_family: centos-7
-cloud_region: europe-west1-b
-mode: ha-scale
+cloud_region: us-central1-c
+cloud_machine_type: "n1-standard-1"
+mode: ha
 
 # Deployment settings
 kube_network_plugin: calico
diff --git a/tests/files/centos7-flannel-addons.yml b/tests/files/centos7-flannel-addons.yml
index 8824df4a13fa1c58a07f7daf774f8576d1933a1d..f2d77dbca19e27668ba436e30b8c37ad3c884d02 100644
--- a/tests/files/centos7-flannel-addons.yml
+++ b/tests/files/centos7-flannel-addons.yml
@@ -1,6 +1,6 @@
 # Instance settings
 cloud_image_family: centos-7
-cloud_region: us-west1-a
+cloud_region: us-central1-c
 cloud_machine_type: "n1-standard-1"
 mode: default
 
diff --git a/tests/files/coreos-alpha-weave-ha.yml b/tests/files/coreos-alpha-weave-ha.yml
index d8087c62188f9d97a6f8c60fccf0d27edba41b85..dd579c0322fdc90fb98790d125ce1cf22d1586cc 100644
--- a/tests/files/coreos-alpha-weave-ha.yml
+++ b/tests/files/coreos-alpha-weave-ha.yml
@@ -1,7 +1,8 @@
 # Instance settings
 cloud_image_family: coreos-alpha
-cloud_region: us-west1-a
-mode: ha-scale
+cloud_region: us-central1-a
+cloud_machine_type: "n1-standard-1"
+mode: ha
 startup_script: 'systemctl disable locksmithd && systemctl stop locksmithd'
 
 # Deployment settings
diff --git a/tests/files/coreos-calico-aio.yml b/tests/files/coreos-calico-aio.yml
index 37ff7ac8f77397bd36927076ac87fa8c1d7739bd..b1d06fc6ff06a71bb68bb015b12649a71c4ae5cf 100644
--- a/tests/files/coreos-calico-aio.yml
+++ b/tests/files/coreos-calico-aio.yml
@@ -1,6 +1,6 @@
 # Instance settings
 cloud_image_family: coreos-stable
-cloud_region: us-west1-b
+cloud_region: us-central1-a
 cloud_machine_type: "n1-standard-2"
 mode: aio
 ##user-data to simply turn off coreos upgrades
diff --git a/tests/files/coreos-canal.yml b/tests/files/coreos-canal.yml
index afbedc30ca143c86bfbde1c8acde494c41244f53..a3a750fd9134bf11e7c8da98aaa320810e58136e 100644
--- a/tests/files/coreos-canal.yml
+++ b/tests/files/coreos-canal.yml
@@ -1,6 +1,6 @@
 # Instance settings
 cloud_image_family: coreos-stable
-cloud_region: us-east1-b
+cloud_region: us-central1-c
 mode: default
 startup_script: 'systemctl disable locksmithd && systemctl stop locksmithd'
 
diff --git a/tests/files/rhel7-canal-sep.yml b/tests/files/rhel7-canal-sep.yml
index 2fc39cbb17d70d0d353d19104b2ffa615f42f557..e3c679629a3646a812eeff069e3493f340118057 100644
--- a/tests/files/rhel7-canal-sep.yml
+++ b/tests/files/rhel7-canal-sep.yml
@@ -1,6 +1,6 @@
 # Instance settings
 cloud_image_family: rhel-7
-cloud_region: us-east1-b
+cloud_region: us-central1-a
 mode: separate
 
 # Deployment settings
diff --git a/tests/files/rhel7-weave.yml b/tests/files/rhel7-weave.yml
index 66804df5c820e6c092965b2f103b7f7eb41716c5..df80a556f82f4dcc224d6ed947e6f0b5b31a6ee0 100644
--- a/tests/files/rhel7-weave.yml
+++ b/tests/files/rhel7-weave.yml
@@ -1,6 +1,6 @@
 # Instance settings
 cloud_image_family: rhel-7
-cloud_region: europe-west1-b
+cloud_region: us-central1-b
 mode: default
 
 # Deployment settings
diff --git a/tests/files/ubuntu-canal-ha.yml b/tests/files/ubuntu-canal-ha.yml
index 7900c055bbaa416535eec6abd64a9405739a0203..241c7d5a29ae2047462a0a07b361de5b825f212c 100644
--- a/tests/files/ubuntu-canal-ha.yml
+++ b/tests/files/ubuntu-canal-ha.yml
@@ -1,6 +1,6 @@
 # Instance settings
 cloud_image_family: ubuntu-1604-lts
-cloud_region: europe-west1-b
+cloud_region: us-central1-c
 mode: ha
 
 # Deployment settings
diff --git a/tests/files/ubuntu-canal-kubeadm.yml b/tests/files/ubuntu-canal-kubeadm.yml
index 93574118fdbd39a7f69269c640279f17137353f5..1f8fd2d76d8a7ab6f632cecf609a2871bffd23cf 100644
--- a/tests/files/ubuntu-canal-kubeadm.yml
+++ b/tests/files/ubuntu-canal-kubeadm.yml
@@ -1,7 +1,7 @@
 # Instance settings
 cloud_image_family:  ubuntu-1604-lts
 cloud_machine_type: "n1-standard-1"
-cloud_region: europe-west1-b
+cloud_region: us-central1-c
 mode: ha
 
 # Deployment settings
diff --git a/tests/files/ubuntu-contiv-sep.yml b/tests/files/ubuntu-contiv-sep.yml
index 0489817b72c8723e953742ca099b1373d9306fbb..0b3b575ab3a9fe6762dc50b99261c9faf224d9f7 100644
--- a/tests/files/ubuntu-contiv-sep.yml
+++ b/tests/files/ubuntu-contiv-sep.yml
@@ -1,6 +1,6 @@
 # Instance settings
 cloud_image_family: ubuntu-1604-lts
-cloud_region: us-west1-a
+cloud_region: us-central1-b
 mode: separate
 
 # Deployment settings
diff --git a/tests/files/ubuntu-flannel-sep.yml b/tests/files/ubuntu-flannel-sep.yml
index 6292926c8ade0002445a462f34973f69b8a5d43f..df77a46b3a9522da1d66ea78883d5eb070bcee59 100644
--- a/tests/files/ubuntu-flannel-sep.yml
+++ b/tests/files/ubuntu-flannel-sep.yml
@@ -1,6 +1,6 @@
 # Instance settings
 cloud_image_family: ubuntu-1604-lts
-cloud_region: europe-west1-b
+cloud_region: us-central1-a
 mode: separate
 
 # Deployment settings
diff --git a/tests/files/ubuntu-rkt-sep.yml b/tests/files/ubuntu-rkt-sep.yml
index 297ce5be06f7f4ac4d4f9dc365021af6097cebc6..b15989231e311597e8c7a837b1a09b1ae67ce805 100644
--- a/tests/files/ubuntu-rkt-sep.yml
+++ b/tests/files/ubuntu-rkt-sep.yml
@@ -1,6 +1,6 @@
 # Instance settings
 cloud_image_family: ubuntu-1604-lts
-cloud_region: us-central1-b
+cloud_region: us-central1-c
 mode: separate
 
 # Deployment settings
diff --git a/tests/files/ubuntu-weave-sep.yml b/tests/files/ubuntu-weave-sep.yml
index 9ab13c278549a8e62e1794ce20f6fbc742ee59e3..133bd907af526f88794b3d03ceec7d81071fee6c 100644
--- a/tests/files/ubuntu-weave-sep.yml
+++ b/tests/files/ubuntu-weave-sep.yml
@@ -1,6 +1,6 @@
 # Instance settings
 cloud_image_family: ubuntu-1604-lts
-cloud_region: us-central1-b
+cloud_region: us-central1-c
 mode: separate
 
 # Deployment settings