diff --git a/README.md b/README.md
index e8475d76bf9e320827c248936e7550b3782b9909..08e1ffafa7c7bd0adfb96bb9890133c3cb95f103 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@ Deploy a Production Ready Kubernetes Cluster
 
 If you have questions, join us on the [kubernetes slack](https://kubernetes.slack.com), channel **\#kubespray**.
 
--   Can be deployed on **AWS, GCE, Azure, OpenStack, vSphere or Baremetal**
+-   Can be deployed on **AWS, GCE, Azure, OpenStack, vSphere, Oracle Cloud Infrastructure (Experimental), or Baremetal**
 -   **Highly available** cluster
 -   **Composable** (Choice of the network plugin for instance)
 -   Supports most popular **Linux distributions**
diff --git a/inventory/sample/group_vars/all.yml b/inventory/sample/group_vars/all.yml
index fbb80b5a289b6a8e160a5b4d6155e2f18f11c2a0..dc2a56de96e91df15714f1b4c0c509848dc1d534 100644
--- a/inventory/sample/group_vars/all.yml
+++ b/inventory/sample/group_vars/all.yml
@@ -60,7 +60,7 @@ bin_dir: /usr/local/bin
 
 ## 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', 'openstack', 'vsphere', or 'external'
+## If set the possible values are either 'gce', 'aws', 'azure', 'openstack', 'vsphere', 'oci', or 'external'
 ## 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:
@@ -95,6 +95,22 @@ bin_dir: /usr/local/bin
 #openstack_lbaas_monitor_timeout: "30s"
 #openstack_lbaas_monitor_max_retries: "3"
 
+## When Oracle Cloud Infrastructure is used, set these variables
+#oci_private_key:
+#oci_region_id:
+#oci_tenancy_id:
+#oci_user_id:
+#oci_user_fingerprint:
+#oci_compartment_id:
+#oci_vnc_id:
+#oci_subnet1_id:
+#oci_subnet2_id:
+## Overide these default behaviors if you wish
+#oci_security_list_management: All
+# If oci_use_instance_principals is true, you do not need to set the region, tenancy, user, key, passphrase, or fingerprint
+#oci_use_instance_principals: false
+#oci_cloud_controller_version: 0.5.0
+
 ## Uncomment to enable experimental kubeadm deployment mode
 #kubeadm_enabled: false
 ## Set these proxy values in order to update package manager and docker daemon to use proxies
diff --git a/roles/kubernetes-apps/cloud_controller/oci/defaults/main.yml b/roles/kubernetes-apps/cloud_controller/oci/defaults/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ccfb700771250ccf547a9a81cbc06b20257e8fc8
--- /dev/null
+++ b/roles/kubernetes-apps/cloud_controller/oci/defaults/main.yml
@@ -0,0 +1,5 @@
+---
+
+oci_security_list_management: All
+oci_use_instance_principals: false
+oci_cloud_controller_version: 0.5.0
diff --git a/roles/kubernetes-apps/cloud_controller/oci/tasks/credentials-check.yml b/roles/kubernetes-apps/cloud_controller/oci/tasks/credentials-check.yml
new file mode 100644
index 0000000000000000000000000000000000000000..b6098686f96e76751fc7f55baaabe5566952265b
--- /dev/null
+++ b/roles/kubernetes-apps/cloud_controller/oci/tasks/credentials-check.yml
@@ -0,0 +1,56 @@
+---
+
+- name: "OCI Cloud Controller | Credentials Check | oci_private_key"
+  fail:
+    msg: "oci_private_key is missing"
+  when: (oci_use_instance_principals == false) and
+        (oci_private_key is not defined or oci_private_key == "")
+
+- name: "OCI Cloud Controller | Credentials Check | oci_region_id"
+  fail:
+    msg: "oci_region_id is missing"
+  when: (oci_use_instance_principals == false) and
+        (oci_region_id is not defined or oci_region_id == "")
+
+- name: "OCI Cloud Controller | Credentials Check | oci_tenancy_id"
+  fail:
+    msg: "oci_tenancy_id is missing"
+  when: (oci_use_instance_principals == false) and
+        (oci_tenancy_id is not defined or oci_tenancy_id == "")
+
+- name: "OCI Cloud Controller | Credentials Check | oci_user_id"
+  fail:
+    msg: "oci_user_id is missing"
+  when: (oci_use_instance_principals == false) and
+        (oci_user_id is not defined or oci_user_id == "")
+
+- name: "OCI Cloud Controller | Credentials Check | oci_user_fingerprint"
+  fail:
+    msg: "oci_user_fingerprint is missing"
+  when: (oci_use_instance_principals == false) and
+        (oci_user_fingerprint is not defined or oci_user_fingerprint == "")
+
+- name: "OCI Cloud Controller | Credentials Check | oci_compartment_id"
+  fail:
+    msg: "oci_compartment_id is missing. This is the compartment in which the cluster resides"
+  when: oci_compartment_id is not defined or oci_compartment_id == ""
+
+- name: "OCI Cloud Controller | Credentials Check | oci_vnc_id"
+  fail:
+    msg: "oci_vnc_id is missin. This is the Virtual Cloud Network in which the cluster resides"
+  when: oci_vnc_id is not defined or oci_vnc_id == ""
+
+- name: "OCI Cloud Controller | Credentials Check | oci_subnet1_id"
+  fail:
+    msg: "oci_subnet1_id is missing. This is the first subnet to which loadbalancers will be added"
+  when: oci_subnet1_id is not defined or oci_subnet1_id == ""
+
+- name: "OCI Cloud Controller | Credentials Check | oci_subnet2_id"
+  fail:
+    msg: "oci_subnet2_id is missing. Two subnets are required for load balancer high availability"
+  when: oci_subnet2_id is not defined or oci_subnet2_id == ""
+
+- name: "OCI Cloud Controller | Credentials Check | oci_security_list_management"
+  fail:
+    msg: "oci_security_list_management is missing, or not defined correctly. Valid options are (All, Frontend, None)."
+  when: oci_security_list_management is not defined or oci_security_list_management not in ["All", "Frontend", "None"]
\ No newline at end of file
diff --git a/roles/kubernetes-apps/cloud_controller/oci/tasks/main.yml b/roles/kubernetes-apps/cloud_controller/oci/tasks/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..37e5962d3dc0c192be8e010748078ca342fbd6b6
--- /dev/null
+++ b/roles/kubernetes-apps/cloud_controller/oci/tasks/main.yml
@@ -0,0 +1,51 @@
+---
+
+- include: credentials-check.yml
+  tags: oci
+
+- name: "OCI Cloud Controller | Generate Configuration"
+  template:
+    src: controller-manager-config.yml.j2
+    dest: /tmp/controller-manager-config.yml
+  register: controller_manager_config
+  when: inventory_hostname == groups['kube-master'][0]
+  tags: oci
+
+- name: "OCI Cloud Controller | Encode Configuration"
+  set_fact:
+    controller_manager_config_base64: "{{ lookup('file', '/tmp/controller-manager-config.yml') | b64encode }}"
+  when: inventory_hostname == groups['kube-master'][0]
+  tags: oci
+
+- name: "OCI Cloud Controller | Apply Configuration To Secret"
+  template:
+    src: cloud-provider.yml.j2
+    dest: /tmp/cloud-provider.yml
+  when: inventory_hostname == groups['kube-master'][0]
+  tags: oci
+
+- name: "OCI Cloud Controller | Apply Configuration"
+  kube:
+    kubectl: "{{ bin_dir }}/kubectl"
+    filename: "/tmp/cloud-provider.yml"
+  when: inventory_hostname == groups['kube-master'][0]
+  tags: oci
+
+- name: "OCI Cloud Controller | Download Controller Manifest"
+  get_url:
+    url: "https://raw.githubusercontent.com/oracle/oci-cloud-controller-manager/{{oci_cloud_controller_version}}/manifests/oci-cloud-controller-manager.yaml"
+    dest: "/tmp/oci-cloud-controller-manager.yml"
+    force: yes
+  register: result
+  until: "'OK' in result.msg"
+  retries: 4
+  delay: "{{ retry_stagger | random + 3 }}"
+  when: inventory_hostname == groups['kube-master'][0]
+  tags: oci
+
+- name: "OCI Cloud Controller | Apply Controller Manifest"
+  kube:
+    kubectl: "{{ bin_dir }}/kubectl"
+    filename: "/tmp/oci-cloud-controller-manager.yml"
+  when: inventory_hostname == groups['kube-master'][0]
+  tags: oci
diff --git a/roles/kubernetes-apps/cloud_controller/oci/templates/cloud-provider.yml.j2 b/roles/kubernetes-apps/cloud_controller/oci/templates/cloud-provider.yml.j2
new file mode 100644
index 0000000000000000000000000000000000000000..bff3ab43b60a994be80abc0820e30d937f0e3ad4
--- /dev/null
+++ b/roles/kubernetes-apps/cloud_controller/oci/templates/cloud-provider.yml.j2
@@ -0,0 +1,8 @@
+apiVersion: v1
+data:
+  cloud-provider.yaml: {{ controller_manager_config_base64 }}
+kind: Secret
+metadata:
+  name: oci-cloud-controller-manager
+  namespace: kube-system
+type: Opaque
diff --git a/roles/kubernetes-apps/cloud_controller/oci/templates/controller-manager-config.yml.j2 b/roles/kubernetes-apps/cloud_controller/oci/templates/controller-manager-config.yml.j2
new file mode 100644
index 0000000000000000000000000000000000000000..38c7ba86ce2d5fbb887df009a36029dc4cc848bb
--- /dev/null
+++ b/roles/kubernetes-apps/cloud_controller/oci/templates/controller-manager-config.yml.j2
@@ -0,0 +1,56 @@
+auth:
+
+{% if oci_use_instance_principals %}
+  # (https://docs.us-phoenix-1.oraclecloud.com/Content/Identity/Tasks/callingservicesfrominstances.htm).
+  # Ensure you have setup the following OCI policies and your kubernetes nodes are running within them
+  # allow dynamic-group [your dynamic group name] to read instance-family in compartment [your compartment name]
+  # allow dynamic-group [your dynamic group name] to use virtual-network-family in compartment [your compartment name]
+  # allow dynamic-group [your dynamic group name] to manage load-balancers in compartment [your compartment name]
+  useInstancePrincipals: true
+{% else %}
+  useInstancePrincipals: false
+  
+  region: {{ oci_region_id }}
+  tenancy: {{ oci_tenancy_id }}
+  user: {{ oci_user_id }}
+  key: | 
+    {{ oci_private_key }}
+
+  {% if oci_private_key_passphrase is defined %}  
+  passphrase: {{ oci_private_key_passphrase }}
+  {% endif %}
+
+
+  fingerprint: {{ oci_user_fingerprint }}
+{% endif %}
+
+# compartment configures Compartment within which the cluster resides.
+compartment: {{ oci_compartment_id }}
+
+# vcn configures the Virtual Cloud Network (VCN) within which the cluster resides.
+vcn: {{ oci_vnc_id }}
+
+loadBalancer:
+  # subnet1 configures one of two subnets to which load balancers will be added.
+  # OCI load balancers require two subnets to ensure high availability.
+  subnet1: {{ oci_subnet1_id }}
+
+  # subnet2 configures the second of two subnets to which load balancers will be
+  # added. OCI load balancers require two subnets to ensure high availability.
+  subnet2: {{ oci_subnet2_id }}
+
+  # SecurityListManagementMode configures how security lists are managed by the CCM.
+  #   "All" (default): Manage all required security list rules for load balancer services.
+  #   "Frontend":      Manage only security list rules for ingress to the load
+  #                    balancer. Requires that the user has setup a rule that
+  #                    allows inbound traffic to the appropriate ports for kube
+  #                    proxy health port, node port ranges, and health check port ranges.
+  #                    E.g. 10.82.0.0/16 30000-32000.
+  #   "None":          Disables all security list management. Requires that the
+  #                    user has setup a rule that allows inbound traffic to the
+  #                    appropriate ports for kube proxy health port, node port
+  #                    ranges, and health check port ranges. E.g. 10.82.0.0/16 30000-32000.
+  #                    Additionally requires the user to mange rules to allow
+  #                    inbound traffic to load balancers.
+  securityListManagementMode: {{ oci_security_list_management }}
+
diff --git a/roles/kubernetes-apps/cluster_roles/defaults/main.yml b/roles/kubernetes-apps/cluster_roles/defaults/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..2a99fc0fd7eaefad5b0abd650abbb7d987ec2990
--- /dev/null
+++ b/roles/kubernetes-apps/cluster_roles/defaults/main.yml
@@ -0,0 +1,2 @@
+---
+oci_cloud_controller_version: 0.5.0
diff --git a/roles/kubernetes-apps/cluster_roles/tasks/main.yml b/roles/kubernetes-apps/cluster_roles/tasks/main.yml
index 56ab951b623167b7903282ea3e268846a75bbef8..229e497e42addd93c2d2b4ecf6e1207b3dc5a1fb 100644
--- a/roles/kubernetes-apps/cluster_roles/tasks/main.yml
+++ b/roles/kubernetes-apps/cluster_roles/tasks/main.yml
@@ -168,3 +168,9 @@
     - kube_version | version_compare('v1.9.3', '<=')
     - inventory_hostname == groups['kube-master'][0]
   tags: vsphere
+
+- include_tasks: oci.yml
+  tags: oci
+  when:
+    - cloud_provider is defined
+    - cloud_provider == 'oci'
diff --git a/roles/kubernetes-apps/cluster_roles/tasks/oci.yml b/roles/kubernetes-apps/cluster_roles/tasks/oci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..fb89a85e82f609c5564cfaae763978e8a938445c
--- /dev/null
+++ b/roles/kubernetes-apps/cluster_roles/tasks/oci.yml
@@ -0,0 +1,23 @@
+---
+- name: Get OCI ClusterRole, and ClusterRoleBinding
+  get_url:
+    url: "https://raw.githubusercontent.com/oracle/oci-cloud-controller-manager/{{oci_cloud_controller_version}}/manifests/oci-cloud-controller-manager-rbac.yaml"
+    dest: "/tmp/oci-cloud-controller-manager-rbac.yaml"
+    force: yes
+  register: result
+  until: "'OK' in result.msg"
+  retries: 4
+  delay: "{{ retry_stagger | random + 3 }}"
+  when:
+    - cloud_provider is defined
+    - cloud_provider == 'oci'
+    - inventory_hostname == groups['kube-master'][0]
+
+- name: Apply OCI ClusterRole, and ClusterRoleBinding
+  kube:
+    kubectl: "{{bin_dir}}/kubectl"
+    filename: "/tmp/oci-cloud-controller-manager-rbac.yaml"
+  when:
+    - cloud_provider is defined
+    - cloud_provider == 'oci'
+    - inventory_hostname == groups['kube-master'][0]
diff --git a/roles/kubernetes-apps/meta/main.yml b/roles/kubernetes-apps/meta/main.yml
index 2ee491f065f03b1ae7d3e25b4ddd0864f5d0df76..e75f073b0780b3e323bb8d2e7c77f3ae77402395 100644
--- a/roles/kubernetes-apps/meta/main.yml
+++ b/roles/kubernetes-apps/meta/main.yml
@@ -27,3 +27,8 @@ dependencies:
     tags:
       - apps
       - persistent_volumes
+
+  - role: kubernetes-apps/cloud_controller/oci
+    when: cloud_provider is defined and cloud_provider == "oci"
+    tags:
+      - oci
diff --git a/roles/kubernetes/master/templates/kubeadm-config.v1alpha1.yaml.j2 b/roles/kubernetes/master/templates/kubeadm-config.v1alpha1.yaml.j2
index 237e371d4681e70402142e7f32a8f5f16a4e00c9..f0786b4e94a3abae216c3172e6502500e2cc7cac 100644
--- a/roles/kubernetes/master/templates/kubeadm-config.v1alpha1.yaml.j2
+++ b/roles/kubernetes/master/templates/kubeadm-config.v1alpha1.yaml.j2
@@ -19,7 +19,7 @@ networking:
   serviceSubnet: {{ kube_service_addresses }}
   podSubnet: {{ kube_pods_subnet }}
 kubernetesVersion: {{ kube_version }}
-{% if cloud_provider is defined and cloud_provider != "gce" %}
+{% if cloud_provider is defined and cloud_provider not in ["gce", "oci"] %}
 cloudProvider: {{ cloud_provider }}
 {% endif %}
 {% if kube_proxy_mode == 'ipvs' and kube_version | version_compare('v1.10', '<') %}
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 85e6043e68a51192f6fa65e396e72a6bc903755a..0557c4498ac3aea5bf714bf4572640ce1aafc544 100644
--- a/roles/kubernetes/master/templates/manifests/kube-controller-manager.manifest.j2
+++ b/roles/kubernetes/master/templates/manifests/kube-controller-manager.manifest.j2
@@ -48,6 +48,8 @@ spec:
     - --cloud-config={{ kube_config_dir }}/cloud_config
 {% elif cloud_provider is defined and cloud_provider in ["aws", "external"] %}
     - --cloud-provider={{cloud_provider}}
+{% elif cloud_provider is defined and cloud_provider == "oci" %}
+    - --cloud_provider=external
 {% endif %}
 {% if kube_network_plugin is defined and kube_network_plugin == 'cloud' %}
     - --configure-cloud-routes=true
diff --git a/roles/kubernetes/node/templates/kubelet.kubeadm.env.j2 b/roles/kubernetes/node/templates/kubelet.kubeadm.env.j2
index e313161a080e9cf16058bb9c5bab40e16d544fdf..aca97ae1221bd80ada115c6a292ec85a1fd73610 100644
--- a/roles/kubernetes/node/templates/kubelet.kubeadm.env.j2
+++ b/roles/kubernetes/node/templates/kubelet.kubeadm.env.j2
@@ -93,8 +93,10 @@ KUBELET_NETWORK_PLUGIN="--hairpin-mode=promiscuous-bridge --network-plugin=kuben
 KUBE_ALLOW_PRIV="--allow-privileged=true"
 {% 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" %}
+{% elif cloud_provider is defined and cloud_provider in ["aws", "external"] %}
 KUBELET_CLOUDPROVIDER="--cloud-provider={{ cloud_provider }}"
+{% elif cloud_provider is defined and cloud_provider == "oci" %}
+KUBELET_CLOUDPROVIDER="--cloud-provider=external"
 {% else %}
 KUBELET_CLOUDPROVIDER=""
 {% endif %}
diff --git a/roles/kubernetes/node/templates/kubelet.standard.env.j2 b/roles/kubernetes/node/templates/kubelet.standard.env.j2
index 031a59fdb16db781579bb3608200e91ae281a43b..c99194ba9a08a7841c12a6ad6b3841589cf5dd9f 100644
--- a/roles/kubernetes/node/templates/kubelet.standard.env.j2
+++ b/roles/kubernetes/node/templates/kubelet.standard.env.j2
@@ -117,8 +117,10 @@ KUBELET_VOLUME_PLUGIN="--volume-plugin-dir={{ kubelet_flexvolumes_plugins_dir }}
 KUBE_ALLOW_PRIV="--allow-privileged=true"
 {% 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" %}
+{% elif cloud_provider is defined and cloud_provider in ["aws", "external"] %}
 KUBELET_CLOUDPROVIDER="--cloud-provider={{ cloud_provider }}"
+{% elif cloud_provider is defined and cloud_provider == "oci" %}
+KUBELET_CLOUDPROVIDER="--cloud-provider=external"
 {% else %}
 KUBELET_CLOUDPROVIDER=""
 {% endif %}
diff --git a/roles/kubernetes/preinstall/tasks/main.yml b/roles/kubernetes/preinstall/tasks/main.yml
index 83347b59fa53a92ae58a9567c59819c339bd7177..505a6f8299453e280f80f658c23966137fc7c5d2 100644
--- a/roles/kubernetes/preinstall/tasks/main.yml
+++ b/roles/kubernetes/preinstall/tasks/main.yml
@@ -73,10 +73,10 @@
 
 - name: check cloud_provider value
   fail:
-    msg: "If set the 'cloud_provider' var must be set either to 'generic', 'gce', 'aws', 'azure', 'openstack', 'vsphere', or external"
+    msg: "If set the 'cloud_provider' var must be set either to 'generic', 'gce', 'aws', 'azure', 'openstack', 'vsphere', 'oci', or external"
   when:
     - cloud_provider is defined
-    - cloud_provider not in ['generic', 'gce', 'aws', 'azure', 'openstack', 'vsphere', 'external']
+    - cloud_provider not in ['generic', 'gce', 'aws', 'azure', 'openstack', 'vsphere', 'oci', 'external']
   tags:
     - cloud-provider
     - facts
diff --git a/roles/kubernetes/preinstall/tasks/verify-settings.yml b/roles/kubernetes/preinstall/tasks/verify-settings.yml
index cc18623472ae0cf5beae27d445e6a1be716ace53..003f33cf21bbe7847846b2484feda8f2815e30a4 100644
--- a/roles/kubernetes/preinstall/tasks/verify-settings.yml
+++ b/roles/kubernetes/preinstall/tasks/verify-settings.yml
@@ -92,6 +92,12 @@
   when: dashboard_enabled
   ignore_errors: "{{ ignore_assert_errors }}"
 
+- name: Stop if RBAC is not enabled when OCI cloud controller is enabled
+  assert:
+    that: rbac_enabled
+  when: cloud_provider is defined and cloud_provider == "oci"
+  ignore_errors: "{{ ignore_assert_errors }}"
+
 - name: Stop if RBAC and anonymous-auth are not enabled when insecure port is disabled
   assert:
     that: rbac_enabled and kube_api_anonymous_auth