diff --git a/inventory/group_vars/all.yml b/inventory/group_vars/all.yml
index 0fe6b5d8622478fa5117b5fa6689cf0bd148bd8f..5ed2035a93fd9f25ae0bbb95dde06875a7c858e5 100644
--- a/inventory/group_vars/all.yml
+++ b/inventory/group_vars/all.yml
@@ -103,7 +103,9 @@ dns_server: "{{ kube_service_addresses|ipaddr('net')|ipaddr(2)|ipaddr('address')
 
 # 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' or 'aws'
+# If set the possible values are either 'gce', 'aws' or 'openstack'
+# 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:
 
 # For multi masters architecture:
diff --git a/roles/kubernetes/master/templates/kube-apiserver.j2 b/roles/kubernetes/master/templates/kube-apiserver.j2
index b45fa46f28dea5a6b3698624df9a2f1aee45fbff..a19687f3083da5937db9e51bb53f8abbb36241ae 100644
--- a/roles/kubernetes/master/templates/kube-apiserver.j2
+++ b/roles/kubernetes/master/templates/kube-apiserver.j2
@@ -38,7 +38,15 @@ KUBE_TLS_CONFIG="--tls_cert_file={{ kube_cert_dir }}/apiserver.pem --tls_private
 # Add you own!
 KUBE_API_ARGS="--token_auth_file={{ kube_token_dir }}/known_tokens.csv --basic-auth-file={{ kube_users_dir }}/known_users.csv --service_account_key_file={{ kube_cert_dir }}/apiserver-key.pem"
 
+{% if cloud_provider is defined and cloud_provider == "openstack" %}
+KUBELET_CLOUDPROVIDER="--cloud-provider={{ cloud_provider }} --cloud-config={{ kube_config_dir }}/cloud_config"
+{% else %}
+{# TODO: gce and aws don't need the cloud provider to be set? #}
+KUBELET_CLOUDPROVIDER=""
+{% endif %}
+
 {% if ansible_service_mgr in ["sysvinit","upstart"] %}
 DAEMON_ARGS="$KUBE_LOGGING $KUBE_LOG_LEVEL $KUBE_ALLOW_PRIV $KUBE_API_PORT $KUBE_SERVICE_ADDRESSES \
-$KUBE_ETCD_SERVERS $KUBE_ADMISSION_CONTROL $KUBE_RUNTIME_CONFIG $KUBE_TLS_CONFIG $KUBE_API_ARGS"
+$KUBE_ETCD_SERVERS $KUBE_ADMISSION_CONTROL $KUBE_RUNTIME_CONFIG $KUBE_TLS_CONFIG $KUBE_API_ARGS \
+$KUBELET_CLOUDPROVIDER"
 {% endif %}
diff --git a/roles/kubernetes/master/templates/kube-apiserver.service.j2 b/roles/kubernetes/master/templates/kube-apiserver.service.j2
index dbfd58f1c836fe00663230b9689d4cf941431653..90bc8e6888c487218fc3f3d5430f509be07cc1cf 100644
--- a/roles/kubernetes/master/templates/kube-apiserver.service.j2
+++ b/roles/kubernetes/master/templates/kube-apiserver.service.j2
@@ -19,7 +19,8 @@ ExecStart={{ bin_dir }}/kube-apiserver \
         $KUBE_ADMISSION_CONTROL \
         $KUBE_RUNTIME_CONFIG \
         $KUBE_TLS_CONFIG \
-        $KUBE_API_ARGS
+        $KUBE_API_ARGS \
+        $KUBELET_CLOUDPROVIDER
 Restart=on-failure
 Type=notify
 LimitNOFILE=65536
diff --git a/roles/kubernetes/node/templates/kubelet.j2 b/roles/kubernetes/node/templates/kubelet.j2
index b7fc61d57a5fabfc917ccadb55b906ff4d4e11c3..fe22c76880a5d88cf0e54980df62ab5c64d19db5 100644
--- a/roles/kubernetes/node/templates/kubelet.j2
+++ b/roles/kubernetes/node/templates/kubelet.j2
@@ -32,7 +32,14 @@ DOCKER_SOCKET="--docker-endpoint=unix:/var/run/weave/weave.sock"
 {% 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 == "openstack" %}
+KUBELET_CLOUDPROVIDER="--cloud-provider={{ cloud_provider }} --cloud-config={{ kube_config_dir }}/cloud_config"
+{% else %}
+{# TODO: gce and aws don't need the cloud provider to be set? #}
+KUBELET_CLOUDPROVIDER=""
+{% endif %}
 {% if ansible_service_mgr in ["sysvinit","upstart"] %}
 DAEMON_ARGS="$KUBE_LOGGING $KUBE_LOG_LEVEL $KUBE_ALLOW_PRIV $KUBELET_API_SERVER $KUBELET_ADDRESS \
-$KUBELET_HOSTNAME $KUBELET_REGISTER_NODE $KUBELET_ARGS $DOCKER_SOCKET $KUBELET_ARGS $KUBELET_NETWORK_PLUGIN"
+$KUBELET_HOSTNAME $KUBELET_REGISTER_NODE $KUBELET_ARGS $DOCKER_SOCKET $KUBELET_ARGS $KUBELET_NETWORK_PLUGIN \
+$KUBELET_CLOUDPROVIDER"
 {% endif %}
diff --git a/roles/kubernetes/node/templates/kubelet.service.j2 b/roles/kubernetes/node/templates/kubelet.service.j2
index 6ffa07309e5ba452f6f7c13461c7e9020f844aef..9fa47bf13a4d39629d6b60c6c3aa2f0a73a2fb24 100644
--- a/roles/kubernetes/node/templates/kubelet.service.j2
+++ b/roles/kubernetes/node/templates/kubelet.service.j2
@@ -20,7 +20,8 @@ ExecStart={{ bin_dir }}/kubelet \
 		$KUBELET_ARGS \
 		$DOCKER_SOCKET \
 		$KUBELET_REGISTER_NODE \
-		$KUBELET_NETWORK_PLUGIN
+		$KUBELET_NETWORK_PLUGIN \
+		$KUBELET_CLOUDPROVIDER
 Restart=on-failure
 
 [Install]
diff --git a/roles/kubernetes/preinstall/defaults/main.yml b/roles/kubernetes/preinstall/defaults/main.yml
index cc1027a14dc3c61ccb59f7ecdf07f483cb739042..49f9b7c0ee8477388b9c03a9afdff0ae62855e29 100644
--- a/roles/kubernetes/preinstall/defaults/main.yml
+++ b/roles/kubernetes/preinstall/defaults/main.yml
@@ -8,3 +8,13 @@ common_required_pkgs:
   - rsync
   - bash-completion
 
+
+
+# For the openstack integration kubelet will need credentials to access
+# openstack apis like nova and cinder. Per default this values will be
+# read from the environment.
+openstack_auth_url: "{{ lookup('env','OS_AUTH_URL')  }}"
+openstack_username: "{{ lookup('env','OS_USERNAME')  }}"
+openstack_password: "{{ lookup('env','OS_PASSWORD')  }}"
+openstack_region: "{{ lookup('env','OS_REGION_NAME')  }}"
+openstack_tenant_id: "{{ lookup('env','OS_TENANT_ID')  }}"
diff --git a/roles/kubernetes/preinstall/tasks/main.yml b/roles/kubernetes/preinstall/tasks/main.yml
index be9515a2d8d4a2921fbcaaa055a7bd55835339e6..c81cf47f1db909c3806e5e32000991bbcaac8ed9 100644
--- a/roles/kubernetes/preinstall/tasks/main.yml
+++ b/roles/kubernetes/preinstall/tasks/main.yml
@@ -48,8 +48,11 @@
 
 - name: check cloud_provider value
   fail:
-    msg: "If set the 'cloud_provider' var must be set eithe to 'gce' or 'aws'"
-  when: cloud_provider is defined and cloud_provider not in ['gce', 'aws']
+    msg: "If set the 'cloud_provider' var must be set either to 'gce', 'aws' or 'openstack'"
+  when: cloud_provider is defined and cloud_provider not in ['gce', 'aws', 'openstack']
+
+- include: openstack-credential-check.yml
+  when: cloud_provider is defined and cloud_provider == 'openstack'
 
 - name: Create cni directories
   file:
@@ -105,4 +108,12 @@
   when: ansible_os_family == "RedHat"
   changed_when: False
 
+- name: Write openstack cloud-config
+  template:
+    src: openstack-cloud-config.j2
+    dest: "{{ kube_config_dir }}/cloud_config"
+    group: "{{ kube_cert_group }}"
+    mode: 0640
+  when: cloud_provider is defined and cloud_provider == "openstack"
+
 - include: etchosts.yml
diff --git a/roles/kubernetes/preinstall/tasks/openstack-credential-check.yml b/roles/kubernetes/preinstall/tasks/openstack-credential-check.yml
new file mode 100644
index 0000000000000000000000000000000000000000..db544066e3de39e767b436e303cf08eac4e56b12
--- /dev/null
+++ b/roles/kubernetes/preinstall/tasks/openstack-credential-check.yml
@@ -0,0 +1,25 @@
+---
+- name: check openstack_auth_url value
+  fail:
+    msg: "openstack_auth_url is missing"
+  when: openstack_auth_url is not defined or openstack_auth_url == ""
+
+- name: check openstack_username value
+  fail:
+    msg: "openstack_username is missing"
+  when: openstack_username is not defined or openstack_username == ""
+
+- name: check openstack_password value
+  fail:
+    msg: "openstack_password is missing"
+  when: openstack_password is not defined or openstack_password == ""
+
+- name: check openstack_region value
+  fail:
+    msg: "openstack_region is missing"
+  when: openstack_region is not defined or openstack_region == ""
+
+- name: check tenant_id value
+  fail:
+    msg: "tenant_id is missing"
+  when: openstack_tenant_id is not defined or openstack_tenant_id == ""
diff --git a/roles/kubernetes/preinstall/templates/openstack-cloud-config.j2 b/roles/kubernetes/preinstall/templates/openstack-cloud-config.j2
new file mode 100644
index 0000000000000000000000000000000000000000..77668f295167a60b7f5889a62b456f2f46ce6422
--- /dev/null
+++ b/roles/kubernetes/preinstall/templates/openstack-cloud-config.j2
@@ -0,0 +1,6 @@
+[Global]
+auth-url={{ openstack_auth_url }}
+username={{ openstack_username }}
+password={{ openstack_password }}
+region={{ openstack_region }}
+tenant-id={{ openstack_tenant_id }}
\ No newline at end of file