diff --git a/inventory/group_vars/all.yml b/inventory/group_vars/all.yml
index 16012e3cb11dd911f1c20dfaf09bf8311b6b2e45..956814ce7eb416cccbb6265c4aaac1c05ba0c1eb 100644
--- a/inventory/group_vars/all.yml
+++ b/inventory/group_vars/all.yml
@@ -116,6 +116,9 @@ bin_dir: /usr/local/bin
 ## Please specify true if you want to perform a kernel upgrade
 kernel_upgrade: false
 
+# Set to true to allow pre-checks to fail and continue deployment
+#ignore_assert_errors: false
+
 ## Etcd auto compaction retention for mvcc key value store in hour
 #etcd_compaction_retention: 0
 
diff --git a/roles/kubernetes-apps/rotate_tokens/tasks/main.yml b/roles/kubernetes-apps/rotate_tokens/tasks/main.yml
index 6f54ff927a3463ee3cf3ec4d7b94784b44b1951f..0e257a65ad98d6aff0b1f58b29056289deb9dd32 100644
--- a/roles/kubernetes-apps/rotate_tokens/tasks/main.yml
+++ b/roles/kubernetes-apps/rotate_tokens/tasks/main.yml
@@ -1,6 +1,6 @@
 ---
-#FIXME(mattymo): Exclude built in secrets that were automatically rotated,
-#instead of filtering manually
+# FIXME(mattymo): Exclude built in secrets that were automatically rotated,
+# instead of filtering manually
 - name: Rotate Tokens | Get all serviceaccount tokens to expire
   shell: >-
     {{ bin_dir }}/kubectl get secrets --all-namespaces
diff --git a/roles/kubernetes/master/tasks/kubeadm-setup.yml b/roles/kubernetes/master/tasks/kubeadm-setup.yml
index 3533cb1bcf9a4d5eb7898b1a738020f38771b521..ff79bcced694b4c8bb3b78779c0deeb0e4c7ba47 100644
--- a/roles/kubernetes/master/tasks/kubeadm-setup.yml
+++ b/roles/kubernetes/master/tasks/kubeadm-setup.yml
@@ -63,7 +63,7 @@
 - name: kubeadm | Initialize first master
   command: timeout -k 240s 240s {{ bin_dir }}/kubeadm init --config={{ kube_config_dir }}/kubeadm-config.yaml --skip-preflight-checks
   register: kubeadm_init
-  #Retry is because upload config sometimes fails
+  # Retry is because upload config sometimes fails
   retries: 3
   when: inventory_hostname == groups['kube-master']|first and not admin_conf.stat.exists
   failed_when: kubeadm_init.rc != 0 and "field is immutable" not in kubeadm_init.stderr
@@ -72,7 +72,7 @@
 - name: kubeadm | Upgrade first master
   command: timeout -k 240s 240s {{ bin_dir }}/kubeadm upgrade apply --config={{ kube_config_dir }}/kubeadm-config.yaml {{ kube_version }} --skip-preflight-checks
   register: kubeadm_upgrade
-  #Retry is because upload config sometimes fails
+  # Retry is because upload config sometimes fails
   retries: 3
   when: inventory_hostname == groups['kube-master']|first and (kubeadm_config.changed and admin_conf.stat.exists)
   failed_when: kubeadm_upgrade.rc != 0 and "field is immutable" not in kubeadm_upgrade.stderr
diff --git a/roles/kubernetes/node/tasks/facts.yml b/roles/kubernetes/node/tasks/facts.yml
index 74da739e8dfce86d1f8e6e6ebcc494575505c961..a23e7596c5d9fdcdfaf3fac51459d59b8d8e6d28 100644
--- a/roles/kubernetes/node/tasks/facts.yml
+++ b/roles/kubernetes/node/tasks/facts.yml
@@ -1,3 +1,4 @@
+---
 - name: look up docker cgroup driver
   shell: "docker info | grep 'Cgroup Driver' | awk -F': ' '{ print $2; }'"
   register: docker_cgroup_driver_result
diff --git a/roles/kubernetes/preinstall/defaults/main.yml b/roles/kubernetes/preinstall/defaults/main.yml
index 686c0e9bc56eb77f54708faf974495e58075d0b2..86a1e85ae51a11e8054c3d5795095e4ecc73b808 100644
--- a/roles/kubernetes/preinstall/defaults/main.yml
+++ b/roles/kubernetes/preinstall/defaults/main.yml
@@ -1,6 +1,9 @@
 ---
 run_gitinfos: false
 
+# Set to true to allow pre-checks to fail and continue deployment
+ignore_assert_errors: false
+
 epel_rpm_download_url: "https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm"
 
 common_required_pkgs:
diff --git a/roles/kubernetes/preinstall/tasks/main.yml b/roles/kubernetes/preinstall/tasks/main.yml
index 38a32978165a93d0294059e6ea5854ebf32a24d2..db07794c045d014fc2f7b712941161420865cbc1 100644
--- a/roles/kubernetes/preinstall/tasks/main.yml
+++ b/roles/kubernetes/preinstall/tasks/main.yml
@@ -1,6 +1,6 @@
 ---
-- include: pre-upgrade.yml
-  tags: [upgrade, bootstrap-os]
+- include: verify-settings.yml
+  tags: asserts
 
 - name: Force binaries directory for Container Linux by CoreOS
   set_fact:
diff --git a/roles/kubernetes/preinstall/tasks/pre-upgrade.yml b/roles/kubernetes/preinstall/tasks/pre-upgrade.yml
deleted file mode 100644
index f7ce5f1d953b1e0eef7ebea5eeaf97022c2e6474..0000000000000000000000000000000000000000
--- a/roles/kubernetes/preinstall/tasks/pre-upgrade.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-- name: Stop if non systemd OS type
-  assert:
-    that: ansible_service_mgr == "systemd"
-  tags:
-    - asserts
diff --git a/roles/kubernetes/preinstall/tasks/verify-settings.yml b/roles/kubernetes/preinstall/tasks/verify-settings.yml
new file mode 100644
index 0000000000000000000000000000000000000000..b35946407d762423ff24aafa3e44349525f90876
--- /dev/null
+++ b/roles/kubernetes/preinstall/tasks/verify-settings.yml
@@ -0,0 +1,71 @@
+---
+- name: Stop if ansible version is too low
+  assert:
+    that:
+      - ansible_version.full|version_compare('2.3.0.0', '>=')
+  run_once: yes
+
+- name: Stop if non systemd OS type
+  assert:
+    that: ansible_service_mgr == "systemd"
+  ignore_errors: "{{ ignore_assert_errors }}"
+
+- name: Stop if unknown OS
+  assert:
+    that: ansible_distribution in ['RedHat', 'CentOS', 'Fedora', 'Ubuntu', 'Debian', 'CoreOS', 'Container Linux by CoreOS']
+  ignore_errors: "{{ ignore_assert_errors }}"
+
+- name: Stop if unknown network plugin
+  assert:
+    that: network_plugin in ['calico', 'canal', 'flannel', 'weave', 'cloud']
+  when: network_plugin is defined
+  ignore_errors: "{{ ignore_assert_errors }}"
+
+- name: Stop if incompatible network plugin and cloudprovider
+  assert:
+    that: network_plugin != calico
+  when: cloud_provider is defined and cloud_provider == 'azure'
+  ignore_errors: "{{ ignore_assert_errors }}"
+
+- name: "Stop if known booleans are set as strings (Use JSON format on CLI: -e \"{'key': true }\")"
+  assert:
+    that: item|type_debug == 'bool'
+  run_once: yes
+  with_items:
+    - kubeadm_enabled
+    - download_run_once
+    - deploy_netchecker
+    - download_always_pull
+    - efk_enabled
+    - helm_enabled
+    - openstack_lbaas_Enabled
+    - rbac_enabled
+  ignore_errors: "{{ ignore_assert_errors }}"
+
+- name: Stop if even number of etcd hosts
+  assert:
+    that: groups.etcd|length is not divisibleby 2
+  ignore_errors: "{{ ignore_assert_errors }}"
+
+- name: Stop if memory is too small for masters
+  assert:
+    that: ansible_memtotal_mb >= 1500
+  ignore_errors: "{{ ignore_assert_errors }}"
+  when: inventory_hostname in groups['kube-master']
+
+- name: Stop if memory is too small for nodes
+  assert:
+    that: ansible_memtotal_mb >= 1024
+  ignore_errors: "{{ ignore_assert_errors }}"
+  when: inventory_hostname in groups['kube-node']
+
+- name: Stop if ip var does not match local ips
+  assert:
+    that: ip in ansible_all_ipv4_addresses
+  ignore_errors: "{{ ignore_assert_errors }}"
+  when: ip is defined
+
+- name: Stop if access_ip is not pingable
+  command: ping -c1 {{ access_ip }}
+  when: access_ip is defined
+  ignore_errors: "{{ ignore_assert_errors }}"
diff --git a/roles/kubespray-defaults/defaults/main.yaml b/roles/kubespray-defaults/defaults/main.yaml
index 3c07147da6947a3603d2bed388988f4587d81bb6..44400f16b65883f384adb97e0dd8b532854db393 100644
--- a/roles/kubespray-defaults/defaults/main.yaml
+++ b/roles/kubespray-defaults/defaults/main.yaml
@@ -10,6 +10,9 @@ is_atomic: false
 ## Change this to use another Kubernetes version, e.g. a current beta release
 kube_version: v1.6.7
 
+# Set to true to allow pre-checks to fail and continue deployment
+ignore_assert_errors: false
+
 # Directory where the binaries will be installed
 bin_dir: /usr/local/bin
 docker_bin_dir: /usr/bin
@@ -129,15 +132,15 @@ efk_enabled: false
 enable_network_policy: false
 
 ## When OpenStack is used, Cinder version can be explicitly specified if autodetection fails (https://github.com/kubernetes/kubernetes/issues/50461)
-#openstack_blockstorage_version: "v1/v2/auto (default)"
+# openstack_blockstorage_version: "v1/v2/auto (default)"
 ## When OpenStack is used, if LBaaSv2 is available you can enable it with the following variables.
 openstack_lbaas_enabled: false
-#openstack_lbaas_subnet_id: "Neutron subnet ID (not network ID) to create LBaaS VIP"
-#openstack_lbaas_floating_network_id: "Neutron network ID (not subnet ID) to get floating IP from, disabled by default"
-#openstack_lbaas_create_monitor: "yes"
-#openstack_lbaas_monitor_delay: false
-#openstack_lbaas_monitor_timeout: false
-#openstack_lbaas_monitor_max_retries: false
+# openstack_lbaas_subnet_id: "Neutron subnet ID (not network ID) to create LBaaS VIP"
+# openstack_lbaas_floating_network_id: "Neutron network ID (not subnet ID) to get floating IP from, disabled by default"
+# openstack_lbaas_create_monitor: "yes"
+# openstack_lbaas_monitor_delay: false
+# openstack_lbaas_monitor_timeout: false
+# openstack_lbaas_monitor_max_retries: false
 
 ## List of authorization modes that must be configured for
 ## the k8s cluster. Only 'AlwaysAllow','AlwaysDeny', and