diff --git a/docs/azure.md b/docs/azure.md
new file mode 100644
index 0000000000000000000000000000000000000000..204a3ce7f99d953c7a00a11b7adf542965b3da23
--- /dev/null
+++ b/docs/azure.md
@@ -0,0 +1,54 @@
+Azure
+===============
+
+To deploy kubespray on [Azure](https://azure.microsoft.com) uncomment the `cloud_provider` option in `group_vars/all.yml` and set it to `'azure'`.
+
+All your instances are required to run in a resource group and a routing table has to be attached to the subnet your instances are in.
+
+Not all features are supported yet though, for a list of the current status have a look [here](https://github.com/colemickens/azure-kubernetes-status)
+
+### Parameters
+
+Before creating the instances you must first set the `azure_` variables in the `group_vars/all.yml` file.
+
+All of the values can be retrieved using the azure cli tool which can be downloaded here: https://docs.microsoft.com/en-gb/azure/xplat-cli-install
+After installation you have to run `azure login` to get access to your account.
+
+
+#### azure\_tenant\_id + azure\_subscription\_id
+run `azure account show` to retrieve your subscription id and tenant id:
+`azure_tenant_id` -> Tenant ID field
+`azure_subscription_id` -> ID field
+
+
+#### azure\_location
+The region your instances are located, can be something like `westeurope` or `westcentralus`. A full list of region names can be retrieved via `azure location list`
+
+
+#### azure\_resource\_group
+The name of the resource group your instances are in, can be retrieved via `azure group list`
+
+#### azure\_vnet\_name
+The name of the virtual network your instances are in, can be retrieved via `azure network vnet list`
+
+#### azure\_subnet\_name
+The name of the subnet your instances are in, can be retrieved via `azure network vnet subnet list RESOURCE_GROUP VNET_NAME`
+
+#### azure\_security\_group\_name
+The name of the network security group your instances are in, can be retrieved via `azure network nsg list`
+
+#### azure\_aad\_client\_id + azure\_aad\_client\_secret
+These will have to be generated first:
+- Create an Azure AD Application with:
+`azure ad app create --name kubernetes --identifier-uris http://kubernetes --home-page http://example.com --password CLIENT_SECRET` 
+The name, identifier-uri, home-page and the password can be choosen
+Note the AppId in the output.
+- Create Service principal for the application with:
+`azure ad sp create --applicationId AppId`
+This is the AppId from the last command
+- Create the role assignment with:
+`azure role assignment create --spn http://kubernetes -o "Owner" -c /subscriptions/SUBSCRIPTION_ID`
+
+azure\_aad\_client\_id musst be set to the AppId, azure\_aad\_client\_secret is your choosen secret.
+
+
diff --git a/inventory/group_vars/all.yml b/inventory/group_vars/all.yml
index daf641335029ba759b8030abc916b2b69e5855aa..229a0d314f7779e656753ca83c3b326a36e6ee21 100644
--- a/inventory/group_vars/all.yml
+++ b/inventory/group_vars/all.yml
@@ -125,11 +125,24 @@ 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', 'aws' or 'openstack'
+# If set the possible values are either 'gce', 'aws', 'azure' 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.
+# When azure is used, you need to also set the following variables.
 # cloud_provider:
 
+# see docs/azure.md for details on how to get these values
+#azure_tenant_id:
+#azure_subscription_id:
+#azure_aad_client_id:
+#azure_aad_client_secret:
+#azure_resource_group:
+#azure_location:
+#azure_subnet_name:
+#azure_security_group_name:
+#azure_vnet_name:
+
+
 ## Set these proxy values in order to update docker daemon to use proxies
 # http_proxy: ""
 # https_proxy: ""
diff --git a/roles/kubernetes/master/templates/manifests/kube-apiserver.manifest.j2 b/roles/kubernetes/master/templates/manifests/kube-apiserver.manifest.j2
index 83c5525b1a50f32423faaf3d17286d618f55d0aa..530b009c65fe9b62068da2b5347b4acfbcf6496c 100644
--- a/roles/kubernetes/master/templates/manifests/kube-apiserver.manifest.j2
+++ b/roles/kubernetes/master/templates/manifests/kube-apiserver.manifest.j2
@@ -43,7 +43,7 @@ spec:
 {% endif %}
     - --v={{ kube_log_level }}
     - --allow-privileged=true
-{% if cloud_provider is defined and cloud_provider == "openstack" %}
+{% if cloud_provider is defined and cloud_provider in ["openstack", "azure"] %}
     - --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 1cd58d46cef3331294e4f3a6f6756be527780799..7821ee309ca569458070501e40c2358b4d2670a5 100644
--- a/roles/kubernetes/master/templates/manifests/kube-controller-manager.manifest.j2
+++ b/roles/kubernetes/master/templates/manifests/kube-controller-manager.manifest.j2
@@ -20,7 +20,7 @@ spec:
     - --root-ca-file={{ kube_cert_dir }}/ca.pem
     - --enable-hostpath-provisioner={{ kube_hostpath_dynamic_provisioner }}
     - --v={{ kube_log_level }}
-{% if cloud_provider is defined and cloud_provider == "openstack" %}
+{% if cloud_provider is defined and cloud_provider in ["openstack", "azure"] %}
     - --cloud-provider={{cloud_provider}}
     - --cloud-config={{ kube_config_dir }}/cloud_config
 {% elif cloud_provider is defined and cloud_provider == "aws" %}
@@ -37,7 +37,7 @@ spec:
     - mountPath: {{ kube_cert_dir }}
       name: ssl-certs-kubernetes
       readOnly: true
-{% if cloud_provider is defined and cloud_provider == "openstack" %}
+{% if cloud_provider is defined and cloud_provider in ["openstack", "azure"] %}
     - mountPath: {{ kube_config_dir }}/cloud_config
       name: cloudconfig
       readOnly: true
@@ -46,7 +46,7 @@ spec:
   - hostPath:
       path: {{ kube_cert_dir }}
     name: ssl-certs-kubernetes
-{% if cloud_provider is defined and cloud_provider == "openstack" %}
+{% if cloud_provider is defined and cloud_provider in ["openstack", "azure"] %}
   - 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 a575f065e44b615769d6bfd027dd48460059bdc7..3c1f31ab2268d5d839a19675419759730b9ba081 100644
--- a/roles/kubernetes/node/templates/kubelet.j2
+++ b/roles/kubernetes/node/templates/kubelet.j2
@@ -30,7 +30,7 @@ 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" %}
+{% if cloud_provider is defined and cloud_provider in ["openstack", "azure"] %}
 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/tasks/azure-credential-check.yml b/roles/kubernetes/preinstall/tasks/azure-credential-check.yml
new file mode 100644
index 0000000000000000000000000000000000000000..2ee57202bd41feaea2ebe868d160f080ec4285f1
--- /dev/null
+++ b/roles/kubernetes/preinstall/tasks/azure-credential-check.yml
@@ -0,0 +1,47 @@
+---
+- name: check azure_tenant_id value
+  fail:
+    msg: "azure_tenant_id is missing"
+  when: azure_tenant_id is not defined or azure_tenant_id == ""
+
+- name: check openstack_username value
+  fail:
+    msg: "azure_subscription_id is missing"
+  when: azure_subscription_id is not defined or azure_subscription_id == ""
+
+- name: check azure_aad_client_id value
+  fail:
+    msg: "azure_aad_client_id is missing"
+  when: azure_aad_client_id is not defined or azure_aad_client_id == ""
+
+- name: check azure_aad_client_secret value
+  fail:
+    msg: "azure_aad_client_secret is missing"
+  when: azure_aad_client_secret is not defined or azure_aad_client_secret == ""
+
+- name: check azure_resource_group value
+  fail:
+    msg: "azure_resource_group is missing"
+  when: azure_resource_group is not defined or azure_resource_group == ""
+
+- name: check azure_location value
+  fail:
+    msg: "azure_location is missing"
+  when: azure_location is not defined or azure_location == ""
+
+- name: check azure_subnet_name value
+  fail:
+    msg: "azure_subnet_name is missing"
+  when: azure_subnet_name is not defined or azure_subnet_name == ""
+
+- name: check azure_security_group_name value
+  fail:
+    msg: "azure_security_group_name is missing"
+  when: azure_security_group_name is not defined or azure_security_group_name == ""
+
+- name: check azure_vnet_name value
+  fail:
+    msg: "azure_vnet_name is missing"
+  when: azure_vnet_name is not defined or azure_vnet_name == ""
+
+
diff --git a/roles/kubernetes/preinstall/tasks/main.yml b/roles/kubernetes/preinstall/tasks/main.yml
index 5c6520ed3b40fdc7dbe8313c458636c66c5f58fb..7e4c2ac4884ea2b9f0277f9f8f8a34666644ddd0 100644
--- a/roles/kubernetes/preinstall/tasks/main.yml
+++ b/roles/kubernetes/preinstall/tasks/main.yml
@@ -60,12 +60,15 @@
 
 - name: check cloud_provider value
   fail:
-    msg: "If set the 'cloud_provider' var must be set either to 'generic', 'gce', 'aws' or 'openstack'"
-  when: cloud_provider is defined and cloud_provider not in ['generic', 'gce', 'aws', 'openstack']
+    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']
 
 - include: openstack-credential-check.yml
   when: cloud_provider is defined and cloud_provider == 'openstack'
 
+- include: azure-credential-check.yml
+  when: cloud_provider is defined and cloud_provider == 'azure'
+
 - name: Create cni directories
   file:
     path: "{{ item }}"
@@ -130,4 +133,12 @@
     mode: 0640
   when: cloud_provider is defined and cloud_provider == "openstack"
 
+- name: Write azure cloud-config
+  template:
+    src: azure-cloud-config.j2
+    dest: "{{ kube_config_dir }}/cloud_config"
+    group: "{{ kube_cert_group }}"
+    mode: 0640
+  when: cloud_provider is defined and cloud_provider == "azure"
+
 - include: etchosts.yml
diff --git a/roles/kubernetes/preinstall/templates/azure-cloud-config.j2 b/roles/kubernetes/preinstall/templates/azure-cloud-config.j2
new file mode 100644
index 0000000000000000000000000000000000000000..139a06cc1f47b83c11845a475a11bb1c97be1e49
--- /dev/null
+++ b/roles/kubernetes/preinstall/templates/azure-cloud-config.j2
@@ -0,0 +1,12 @@
+{
+  "tenantId": "{{ azure_tenant_id }}",
+  "subscriptionId": "{{ azure_subscription_id }}",
+  "aadClientId": "{{ azure_aad_client_id }}",
+  "aadClientSecret": "{{ azure_aad_client_secret }}",
+  "resourceGroup": "{{ azure_resource_group }}",
+  "location": "{{ azure_location }}",
+  "subnetName": "{{ azure_subnet_name }}",
+  "securityGroupName": "{{ azure_security_group_name }}",
+  "vnetName": "{{ azure_vnet_name }}",
+  "routeTableName": "{{ azure_route_table_name }}"
+}
\ No newline at end of file