Creating Kubernetes Cluster (OKE) Using Terraform On Oracle Cloud Infrastructure (OCI)
Prerequisites
Refer this for more details.
OCI Tenancy
Refer this to get more details on how to get details of OCI tenancy, this would be used below in Implementation Section below.
Implementation
Terraform Project
Terraform Code
We need to create the following files
- variable.tf
- provider.tf
- outputs.tf
- datasources.tf
- network.tf
- cluster.tf
- env_vars.ps1
variable.tf
# Required by the OCI Provider
variable "tenancy_ocid" {}
variable "user_ocid" {}
variable "fingerprint" {}
variable "private_key_path" {}
variable "compartment_ocid" {}
variable "ssh_public_key_file" {
default = "~/.ssh/id_rsa.pub"
}
variable "region" {
default = "eu-frankfurt-1"
}
# Choose an Availability Domain
variable "availability_domain" {
default = "3"
}
variable "internet_gateway_enabled" {
default = "true"
}
variable "worker_ol_image_name" {
default = "Oracle-Linux-7.5"
}
variable "oke" {
type = "map"
default = {
name = "oke"
version = "v1.12.6"
shape = "VM.Standard2.2"
nodes_per_subnet = 1
}
}
variable "network_cidrs" {
type = "map"
default = {
vcnCIDR = "10.0.0.0/16"
workerSubnetAD1 = "10.0.10.0/24"
workerSubnetAD2 = "10.0.11.0/24"
workerSubnetAD3 = "10.0.12.0/24"
LoadBalancerSubnetAD1 = "10.0.20.0/24"
LoadBalancerSubnetAD2 = "10.0.21.0/24"
LoadBalancerSubnetAD3 = "10.0.22.0/24"
}
}
provider.tf
# https://www.terraform.io/docs/configuration/providers.html
# https://www.terraform.io/docs/providers/oci/index.html
provider "oci" {
tenancy_ocid = "${var.tenancy_ocid}"
user_ocid = "${var.user_ocid}"
fingerprint = "${var.fingerprint}"
private_key_path = "${var.private_key_path}"
region = "${var.region}"
}
outputs.tf
# https://www.terraform.io/docs/commands/output.html
# https://learn.hashicorp.com/terraform/getting-started/outputs.html
# Output the result
output "show-ads" {
value = "${data.oci_identity_availability_domains.ADs.availability_domains}"
}
datasources.tf
# https://www.terraform.io/docs/configuration/data-sources.html
# https://www.terraform.io/docs/providers/oci/d/identity_availability_domains.html
# Gets a list of Availability Domains
data "oci_identity_availability_domains" "ADs" {
compartment_id = "${var.compartment_ocid}"
}
# https://www.terraform.io/docs/providers/oci/d/core_images.html
data "oci_core_images" "oracle_linux_image" {
compartment_id = "${var.compartment_ocid}"
operating_system = "Oracle Linux"
operating_system_version = "7.6"
}
network.tf
# https://www.terraform.io/docs/configuration/resources.html
# https://www.terraform.io/docs/providers/oci/r/core_vcn.html
resource "oci_core_vcn" "oke_vcn" {
#Required
cidr_block = "${lookup(var.network_cidrs, "vcnCIDR")}"
compartment_id = "${var.compartment_ocid}"
#Optional
dns_label = "vcn1"
display_name = "oke-vcn"
}
# https://www.terraform.io/docs/providers/oci/r/core_security_list.html
resource "oci_core_security_list" "oke_sl" {
#Required
compartment_id = "${var.compartment_ocid}"
vcn_id = "${oci_core_vcn.oke_vcn.id}"
egress_security_rules = [
{
destination = "0.0.0.0/0"
protocol = "all"
},
]
ingress_security_rules = [
{
protocol = "all"
source = "0.0.0.0/0"
},
]
#Optional
display_name = "oke-sl"
}
# https://www.terraform.io/docs/providers/oci/r/core_internet_gateway.html
resource "oci_core_internet_gateway" "oke_ig" {
#Required
compartment_id = "${var.compartment_ocid}"
vcn_id = "${oci_core_vcn.oke_vcn.id}"
#Optional
enabled = "${var.internet_gateway_enabled}"
display_name = "oke-gateway"
}
# https://www.terraform.io/docs/providers/oci/r/core_route_table.html
resource "oci_core_route_table" "oke_rt" {
#Required
compartment_id = "${var.compartment_ocid}"
vcn_id = "${oci_core_vcn.oke_vcn.id}"
route_rules {
destination = "0.0.0.0/0"
network_entity_id = "${oci_core_internet_gateway.oke_ig.id}"
}
#Optional
display_name = "oke-rt"
}
# https://www.terraform.io/docs/providers/oci/r/core_subnet.html
resource "oci_core_subnet" "workerSubnetAD1" {
#Required
cidr_block = "${lookup(var.network_cidrs, "workerSubnetAD1")}"
compartment_id = "${var.compartment_ocid}"
security_list_ids = ["${oci_core_security_list.oke_sl.id}"]
vcn_id = "${oci_core_vcn.oke_vcn.id}"
#Optional
availability_domain = "${lookup(data.oci_identity_availability_domains.ADs.availability_domains[0], "name")}"
dhcp_options_id = "${oci_core_vcn.oke_vcn.default_dhcp_options_id}"
display_name = "workerSubnetAD1"
dns_label = "worker1"
route_table_id = "${oci_core_route_table.oke_rt.id}"
}
resource "oci_core_subnet" "workerSubnetAD2" {
#Required
cidr_block = "${lookup(var.network_cidrs, "workerSubnetAD2")}"
compartment_id = "${var.compartment_ocid}"
security_list_ids = ["${oci_core_security_list.oke_sl.id}"]
vcn_id = "${oci_core_vcn.oke_vcn.id}"
#Optional
availability_domain = "${lookup(data.oci_identity_availability_domains.ADs.availability_domains[1], "name")}"
dhcp_options_id = "${oci_core_vcn.oke_vcn.default_dhcp_options_id}"
display_name = "workerSubnetAD2"
dns_label = "worker2"
route_table_id = "${oci_core_route_table.oke_rt.id}"
}
resource "oci_core_subnet" "workerSubnetAD3" {
#Required
cidr_block = "${lookup(var.network_cidrs, "workerSubnetAD3")}"
compartment_id = "${var.compartment_ocid}"
security_list_ids = ["${oci_core_security_list.oke_sl.id}"]
vcn_id = "${oci_core_vcn.oke_vcn.id}"
#Optional
availability_domain = "${lookup(data.oci_identity_availability_domains.ADs.availability_domains[2], "name")}"
dhcp_options_id = "${oci_core_vcn.oke_vcn.default_dhcp_options_id}"
display_name = "workerSubnetAD3"
dns_label = "worker3"
route_table_id = "${oci_core_route_table.oke_rt.id}"
}
resource "oci_core_subnet" "LoadBalancerSubnetAD1" {
#Required
cidr_block = "${lookup(var.network_cidrs, "LoadBalancerSubnetAD1")}"
compartment_id = "${var.compartment_ocid}"
security_list_ids = ["${oci_core_security_list.oke_sl.id}"]
vcn_id = "${oci_core_vcn.oke_vcn.id}"
#Optional
availability_domain = "${lookup(data.oci_identity_availability_domains.ADs.availability_domains[0], "name")}"
dhcp_options_id = "${oci_core_vcn.oke_vcn.default_dhcp_options_id}"
display_name = "LoadBalancerSubnetAD1"
dns_label = "loadbalancer1"
route_table_id = "${oci_core_route_table.oke_rt.id}"
}
resource "oci_core_subnet" "LoadBalancerSubnetAD2" {
#Required
cidr_block = "${lookup(var.network_cidrs, "LoadBalancerSubnetAD2")}"
compartment_id = "${var.compartment_ocid}"
security_list_ids = ["${oci_core_security_list.oke_sl.id}"]
vcn_id = "${oci_core_vcn.oke_vcn.id}"
#Optional
availability_domain = "${lookup(data.oci_identity_availability_domains.ADs.availability_domains[1], "name")}"
dhcp_options_id = "${oci_core_vcn.oke_vcn.default_dhcp_options_id}"
display_name = "LoadBalancerSubnetAD1"
dns_label = "loadbalancer2"
route_table_id = "${oci_core_route_table.oke_rt.id}"
}
cluster.tf
# https://www.terraform.io/docs/providers/oci/r/containerengine_cluster.html
resource "oci_containerengine_cluster" "k8s_cluster" {
#Required
compartment_id = "${var.compartment_ocid}"
kubernetes_version = "${var.oke["version"]}"
name = "${var.oke["name"]}"
vcn_id = "${oci_core_vcn.oke_vcn.id}"
#Optional
options {
service_lb_subnet_ids = ["${oci_core_subnet.LoadBalancerSubnetAD1.id}", "${oci_core_subnet.LoadBalancerSubnetAD2.id}"]
}
}
# https://www.terraform.io/docs/providers/oci/r/containerengine_node_pool.html
resource "oci_containerengine_node_pool" "k8s_node_pool" {
#Required
cluster_id = "${oci_containerengine_cluster.k8s_cluster.id}"
compartment_id = "${var.compartment_ocid}"
kubernetes_version = "${var.oke["version"]}"
name = "${var.oke["name"]}"
node_image_name = "${var.worker_ol_image_name}"
node_shape = "${var.oke["shape"]}"
subnet_ids = ["${oci_core_subnet.workerSubnetAD1.id}", "${oci_core_subnet.workerSubnetAD2.id}", "${oci_core_subnet.workerSubnetAD3.id}"]
quantity_per_subnet = "${var.oke["nodes_per_subnet"]}"
ssh_public_key = "${file(var.ssh_public_key_file)}"
}
# https://www.terraform.io/docs/providers/oci/d/containerengine_cluster_kube_config.html
data "oci_containerengine_cluster_kube_config" "cluster_kube_config" {
cluster_id = "${oci_containerengine_cluster.k8s_cluster.id}"
expiration = 2592000
token_version = "1.0.0"
}
# https://www.terraform.io/docs/providers/local/r/file.html
resource "local_file" "kubeconfig" {
content = "${data.oci_containerengine_cluster_kube_config.cluster_kube_config.content}"
filename = "${path.module}/kubeconfig"
}
env_vars.ps1
### Authentication details
$env:TF_VAR_tenancy_ocid = "ocid1.tenancy.oc1..afsafsafsafsafadsfdsafdsaf"
$env:TF_VAR_user_ocid = "ocid1.user.oc1..asdfdsafdsafdsafdsafdsafdsafds"
$env:TF_VAR_fingerprint = "35:84:df:b5:fe:6b:81:25:e5:bf:b6:e2:66:66:b8:56"
$env:TF_VAR_private_key_path = "C:\Users\nadeem\.oci\oci_api_key.pem"
### Region
$env:TF_VAR_region = "eu-frankfurt-1"
### Compartment
$env:TF_VAR_compartment_ocid = "ocid1.compartment.oc1..safdsafdsafdsafdsafsdfsda"
execute env_vars.ps1
PS D:\practices\terraform\oke> .\env_vars.ps1
PS D:\practices\terraform\oke>
Execute terraform init
PS D:\practices\terraform\oke> terraform init
Initializing provider plugins...
- Checking for available provider plugins on https://releases.hashicorp.com...
- Downloading plugin for provider "oci" (3.20.0)...
- Downloading plugin for provider "local" (1.2.0)...
The following providers do not have any version constraints in configuration,
so the latest version was installed.
To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.
* provider.local: version = "~> 1.2"
* provider.oci: version = "~> 3.20"
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
PS D:\practices\terraform\oke>
Execute terraform validate
PS D:\practices\terraform\oke> terraform validate
PS D:\practices\terraform\oke>
Execute terraform plan
Execute terraform apply
Testing
PS D:\practices\terraform\oke> kubectl --kubeconfig .\kubeconfig get nodes
NAME STATUS ROLES AGE VERSION
10.0.10.2 Ready node 5m v1.12.6
10.0.11.2 Ready node 55s v1.12.6
10.0.12.2 Ready node 5m v1.12.6
PS D:\practices\terraform\oke>