diff --git a/inventory/group_vars/all.yml b/inventory/group_vars/all.yml
index ca46d28171c04b3f4a4fe73522d7dab4b30c27a4..a4f6fbda4474b028557ab2f61267dc47a8a2d1d6 100644
--- a/inventory/group_vars/all.yml
+++ b/inventory/group_vars/all.yml
@@ -47,7 +47,7 @@
 
 ## There are some changes specific to the cloud providers
 ## for instance we need to encapsulate packets with some network plugins
-## If set the possible values are either 'gce', 'aws', 'azure' or 'openstack'
+## If set the possible values are either 'gce', 'aws', 'azure', 'openstack', or 'vsphere'
 ## When openstack is used make sure to source in the openstack credentials
 ## like you would do when using nova-client before starting the playbook.
 #cloud_provider:
diff --git a/roles/kubernetes/master/templates/manifests/kube-apiserver.manifest.j2 b/roles/kubernetes/master/templates/manifests/kube-apiserver.manifest.j2
index 86c9e2d78e79ea86b626b27c056dd1e91cc555e3..4619db8d5da1b75553cd0cbb3fc47b10a6bff0d4 100644
--- a/roles/kubernetes/master/templates/manifests/kube-apiserver.manifest.j2
+++ b/roles/kubernetes/master/templates/manifests/kube-apiserver.manifest.j2
@@ -52,7 +52,7 @@ spec:
 {% endif %}
     - --v={{ kube_log_level }}
     - --allow-privileged=true
-{% if cloud_provider is defined and cloud_provider in ["openstack", "azure"] %}
+{% if cloud_provider is defined and cloud_provider in ["openstack", "azure", "vsphere"] %}
     - --cloud-provider={{ cloud_provider }}
     - --cloud-config={{ kube_config_dir }}/cloud_config
 {% elif cloud_provider is defined and cloud_provider == "aws" %}
diff --git a/roles/kubernetes/master/templates/manifests/kube-controller-manager.manifest.j2 b/roles/kubernetes/master/templates/manifests/kube-controller-manager.manifest.j2
index 7bcd51cc4d0edfc26d74546560a1be8fda6eb909..6faf6dea512a451b357400f896020129503a19e0 100644
--- a/roles/kubernetes/master/templates/manifests/kube-controller-manager.manifest.j2
+++ b/roles/kubernetes/master/templates/manifests/kube-controller-manager.manifest.j2
@@ -32,7 +32,7 @@ spec:
     - --node-monitor-period={{ kube_controller_node_monitor_period }}
     - --pod-eviction-timeout={{ kube_controller_pod_eviction_timeout }}
     - --v={{ kube_log_level }}
-{% if cloud_provider is defined and cloud_provider in ["openstack", "azure"] %}
+{% if cloud_provider is defined and cloud_provider in ["openstack", "azure", "vsphere"] %}
     - --cloud-provider={{cloud_provider}}
     - --cloud-config={{ kube_config_dir }}/cloud_config
 {% elif cloud_provider is defined and cloud_provider == "aws" %}
@@ -54,7 +54,7 @@ spec:
     - mountPath: {{ kube_cert_dir }}
       name: ssl-certs-kubernetes
       readOnly: true
-{% if cloud_provider is defined and cloud_provider in ["openstack", "azure"] %}
+{% if cloud_provider is defined and cloud_provider in ["openstack", "azure", "vsphere" ] %}
     - mountPath: {{ kube_config_dir }}/cloud_config
       name: cloudconfig
       readOnly: true
@@ -63,7 +63,7 @@ spec:
   - hostPath:
       path: {{ kube_cert_dir }}
     name: ssl-certs-kubernetes
-{% if cloud_provider is defined and cloud_provider in ["openstack", "azure"] %}
+{% if cloud_provider is defined and cloud_provider in ["openstack", "azure", "vsphere"] %}
   - hostPath:
       path: {{ kube_config_dir }}/cloud_config
     name: cloudconfig
diff --git a/roles/kubernetes/node/templates/kubelet.j2 b/roles/kubernetes/node/templates/kubelet.j2
index 8ec348a056fea6016dcd5940885e833c5c1ed186..10135c13fb7765e5e87ec47d736b80556449ee9b 100644
--- a/roles/kubernetes/node/templates/kubelet.j2
+++ b/roles/kubernetes/node/templates/kubelet.j2
@@ -42,7 +42,7 @@ KUBELET_NETWORK_PLUGIN="--hairpin-mode=promiscuous-bridge --network-plugin=kuben
 {% endif %}
 # Should this cluster be allowed to run privileged docker containers
 KUBE_ALLOW_PRIV="--allow-privileged=true"
-{% if cloud_provider is defined and cloud_provider in ["openstack", "azure"] %}
+{% if cloud_provider is defined and cloud_provider in ["openstack", "azure", "vsphere"] %}
 KUBELET_CLOUDPROVIDER="--cloud-provider={{ cloud_provider }} --cloud-config={{ kube_config_dir }}/cloud_config"
 {% elif cloud_provider is defined and cloud_provider == "aws" %}
 KUBELET_CLOUDPROVIDER="--cloud-provider={{ cloud_provider }}"
diff --git a/roles/kubernetes/preinstall/defaults/main.yml b/roles/kubernetes/preinstall/defaults/main.yml
index 59076c2042b9de80074e3837fa51d51df7ba653f..c775f748dbb591396ab09cc4e22eb81c754ebb8d 100644
--- a/roles/kubernetes/preinstall/defaults/main.yml
+++ b/roles/kubernetes/preinstall/defaults/main.yml
@@ -29,6 +29,22 @@ openstack_password: "{{ lookup('env','OS_PASSWORD')  }}"
 openstack_region: "{{ lookup('env','OS_REGION_NAME')  }}"
 openstack_tenant_id: "{{ lookup('env','OS_TENANT_ID')|default(lookup('env','OS_PROJECT_ID'),true)  }}"
 
+# For the vsphere integration, kubelet will need credentials to access
+# vsphere apis
+# Documentation regarting these values can be found 
+# https://github.com/kubernetes/kubernetes/blob/master/pkg/cloudprovider/providers/vsphere/vsphere.go#L105
+vsphere_vcenter_ip: "{{ lookup('env', 'VSPHERE_VCENTER') }}"
+vsphere_vcenter_port: "{{ lookup('env', 'VSPHERE_VCENTER_PORT') }}"
+vsphere_user: "{{ lookup('env', 'VSPHERE_USER') }}"
+vsphere_password: "{{ lookup('env', 'VSPHERE_PASSWORD') }}"
+vsphere_datacenter: "{{ lookup('env', 'VSPHERE_DATACENTER') }}"
+vsphere_datastore: "{{ lookup('env', 'VSPHERE_DATASTORE') }}"
+vsphere_working_dir: "{{ lookup('env', 'VSPHERE_WORKING_DIR') }}"
+vsphere_insecure: "{{ lookup('env', 'VSPHERE_INSECURE') }}"
+vsphere_scsi_controller_type: pvscsi
+# vsphere_public_network is name of the network the VMs are joined to
+vsphere_public_network: "{{ lookup('env', 'VSPHERE_PUBLIC_NETWORK')|default('') }}"
+
 # Container Linux by CoreOS cloud init config file to define /etc/resolv.conf content
 # for hostnet pods and infra needs
 resolveconf_cloud_init_conf: /etc/resolveconf_cloud_init.conf
diff --git a/roles/kubernetes/preinstall/tasks/main.yml b/roles/kubernetes/preinstall/tasks/main.yml
index 27e98949ddd239050e68b63b8dcf5168b533a25a..4d89a73dde49b4385c754018a4381614bcb829c0 100644
--- a/roles/kubernetes/preinstall/tasks/main.yml
+++ b/roles/kubernetes/preinstall/tasks/main.yml
@@ -64,17 +64,13 @@
 
 - name: check cloud_provider value
   fail:
-    msg: "If set the 'cloud_provider' var must be set either to 'generic', 'gce', 'aws', 'azure' or 'openstack'"
-  when: cloud_provider is defined and cloud_provider not in ['generic', 'gce', 'aws', 'openstack', 'azure']
+    msg: "If set the 'cloud_provider' var must be set either to 'generic', 'gce', 'aws', 'azure', 'openstack' or 'vsphere'"
+  when: cloud_provider is defined and cloud_provider not in ['generic', 'gce', 'aws', 'azure', 'openstack', 'vsphere']
   tags: [cloud-provider, facts]
 
-- include: openstack-credential-check.yml
-  when: cloud_provider is defined and cloud_provider == 'openstack'
-  tags: [cloud-provider, openstack, facts]
-
-- include: azure-credential-check.yml
-  when: cloud_provider is defined and cloud_provider == 'azure'
-  tags: [cloud-provider, azure, facts]
+- include: "{{ cloud_provider }}-credential-check.yml"
+  when: cloud_provider is defined and cloud_provider in [ 'openstack', 'azure', 'vsphere' ]
+  tags: [cloud-provider, "{{ cloud_provider }}", facts]
 
 - name: Create cni directories
   file:
@@ -179,23 +175,14 @@
     state: present
   tags: bootstrap-os
 
-- name: Write openstack cloud-config
-  template:
-    src: openstack-cloud-config.j2
-    dest: "{{ kube_config_dir }}/cloud_config"
-    group: "{{ kube_cert_group }}"
-    mode: 0640
-  when: inventory_hostname in groups['k8s-cluster'] and cloud_provider is defined and cloud_provider == "openstack"
-  tags: [cloud-provider, openstack]
-
-- name: Write azure cloud-config
+- name: Write cloud-config
   template:
-    src: azure-cloud-config.j2
+    src: "{{ cloud_provider }}-cloud-config.j2"
     dest: "{{ kube_config_dir }}/cloud_config"
     group: "{{ kube_cert_group }}"
     mode: 0640
-  when: inventory_hostname in groups['k8s-cluster'] and cloud_provider is defined and cloud_provider == "azure"
-  tags: [cloud-provider, azure]
+  when: inventory_hostname in groups['k8s-cluster'] and cloud_provider is defined and cloud_provider in [ 'openstack', 'azure', 'vsphere' ]
+  tags: [cloud-provider, "{{ cloud_provider }}"]
 
 - include: etchosts.yml
   tags: [bootstrap-os, etchosts]
diff --git a/roles/kubernetes/preinstall/tasks/vsphere-credential-check.yml b/roles/kubernetes/preinstall/tasks/vsphere-credential-check.yml
new file mode 100644
index 0000000000000000000000000000000000000000..b91726d50ad722c27781b71aa0937ed0ae03d20f
--- /dev/null
+++ b/roles/kubernetes/preinstall/tasks/vsphere-credential-check.yml
@@ -0,0 +1,21 @@
+- name: check vsphere environment variables
+  fail:
+    msg: "{{ item.name }} is missing"
+  when: item.value is not defined or item.value == ''
+  with_items:
+    - name: vsphere_vcenter_ip
+      value: "{{ vsphere_vcenter_ip }}"
+    - name: vsphere_vcenter_port
+      value: "{{ vsphere_vcenter_port }}"
+    - name: vsphere_user
+      value: "{{ vsphere_user }}"
+    - name: vsphere_password
+      value: "{{ vsphere_password }}"
+    - name: vsphere_datacenter
+      value: "{{ vsphere_datacenter }}"
+    - name: vsphere_datastore
+      value: "{{ vsphere_datastore }}"
+    - name: vsphere_working_dir
+      value: "{{ vsphere_working_dir }}"
+    - name: vsphere_insecure
+      value: "{{ vsphere_insecure }}"
diff --git a/roles/kubernetes/preinstall/templates/vsphere-cloud-config.j2 b/roles/kubernetes/preinstall/templates/vsphere-cloud-config.j2
new file mode 100644
index 0000000000000000000000000000000000000000..c68ac0f55c37aaa1619d17bac8c7ead2205b70aa
--- /dev/null
+++ b/roles/kubernetes/preinstall/templates/vsphere-cloud-config.j2
@@ -0,0 +1,20 @@
+[Global]
+datacenter = {{ vsphere_datacenter }}
+datastore = {{ vsphere_datastore }}
+insecure-flag = {{ vsphere_insecure }}
+password = {{ vsphere_password }}
+port = {{ vsphere_vcenter_port }}
+server = {{ vsphere_vcenter_ip }}
+user = {{ vsphere_user }}
+working-dir = {{ vsphere_working_dir }}
+{% if vsphere_vm_uuid is defined %}
+vm-uuid = {{ vsphere_vm_uuid }}
+{% endif %}
+
+[Disk]
+scsicontrollertype = {{ vsphere_scsi_controller_type }}
+
+{% if vsphere_public_network is defined and vsphere_public_network != ""  %}
+[Network]
+public-network = {{ vsphere_public_network }}
+{% endif %}