Quick IKS Terraform

Matt
6 min readMar 1, 2021

Here we will briefly go over a proof of concept for infrastructure as code (IaC) using Terraform. So without further ado let’s begin.

Terraform is in the category of declarative IaC tools. This meaning you write what you want your desired state to be and leave it to Terraform and the provider to handle getting you to that state. Terraform is also cloud agnostic. Anybody can create a provider that Terraform can use to deploy to their cloud. It is mostly free (they have some paid offerings) and open source. There are other tools but I will not go into those here today.

Basics of how it works:

Terraform has providers that it will search for you or you can add yourself. These providers will let Terraform know what it kinds of resources it can support and what information it needs as input to create them. The Terraform software will allow you to define some configurations for resources you wish to create that it will then check against the provider. Ultimately if everything looks good and you want to apply those changes it will delegate to the provider to begin working on getting you what you want. You don’t and shouldn’t care how it does that. Simply when it is done you have what you requested and are happy to move on with other important parts of your day. Keep in mind this is a simplification, there are more parts to it, and considerations like if you’re going to have multiple users potentially simultaneously creating resources, or how you will track your changes over the lifetime of your sources. Always review best practices which help inform maintenance, testing, security concerns and other considerations with the tools you choose to use.

Our mission:

We will explore a simple example on creating an IKS (IBM Kubernetes Service essentially a Kubernetes cluster on IBM Cloud), because I build on some Kubernetes concepts in my other posts.

Terraform stages:

We will cover 3 basic Terraform stages: {init, plan, apply}. Terraform init, will be useful for ensuring terraform can find our provider, plan will give read our configs and formulate a fairly detailed list of settings it figured you want based on your configs and input. If you like the settings you will then ask Terraform to go ahead and get these created in the apply stage.

Preparation:

You will need to have both terraform installed, which is as simple as downloading, unzip and move the files to your path. In addition you will need an account created with the provider of your choice, with the ability to create the resources you need. Often this means and api key sufficient access.

# example terraform zip for install (will depend on your os)curl -s  https://releases.hashicorp.com/terraform/0.13.5/terraform_0.13.5_darwin_amd64.zip -o terraform_0.13.5_darwin_amd64.zipunzip terraform_0.13.5_darwin_amd64.zipmv terraform /usr/local/bin/#test
terraform version

Add the provider:

Normally, you would look up the provider in Terraform’s provider list, but instead we will download the provider locally and have Terraform pick it up:

mkdir -p ~/.terraform.d/plugins/localdomain/provider/ibm/1.10.0/linux_amd64curl -s https://github.com/IBM-Cloud/terraform-provider-ibm/releases/download/v1.10.0/terraform-provider-ibm_1.10.0_linux_amd64.zip -o terraform-provider-ibm_1.10.0_linux_amd64.zipunzip terraform-provider-ibm_1.10.0_linux_amd64.zipmv terraform-provider-ibm_1.10.0 ~/.terraform.d/plugins/localdomain/provider/ibm/1.10.0/linux_amd64

Just because we have the provider file does not mean terraform will use them until you reference them. This is usually easily found by clicking the use provider drop down in Terraform. In addition we will need to authenticate with the cloud provider to be able to get it create the resources we want. In this example I used a platform api key.

We add a variable for the api key for this provider.

# Tells Terraform where to look for the provider files
# Directory is: ~/.terraform.d/plugins/localdomain/provider/ibm
terraform {
required_providers {
ibm = {
source = "localdomain/provider/ibm"
version = "1.14.0"
}
}
}
# We also need to define a variable we will fill in for accessing the cloudvariable "ibmcloud_api_key" {
description = "Enter your IBM Cloud API Key, you can get your IBM Cloud API key using: https://cloud.ibm.com/iam#/apikeys"
}
# We tell Terraform to use this provider
# We tell Terraform to set the key
provider "ibm" {
# Configuration options
ibmcloud_api_key=var.ibmcloud_api_key
}

Formulate our plan:

Creating a cluster has a decent amount of input we would need to set. Before we get into this it is easier to create a simpler resource to see that this is in fact working properly. A simple test might be to create an access group. The nice thing might be that you may choose to grant access to users in this way. But i will leave this as an exercise. In fact since adding the policy for the cluster we create will require knowing the id of the cluster. Anyway, for another time.

resource "ibm_iam_access_group" "v1_terraform_new_group" {
name="terraform-test_access_group"
description="testing creating a resource group using terraform"
}

Let’s run the plan: terraform plan -out terra-plan.out

Refreshing Terraform state in-memory prior to plan...The refreshed state will be used to calculate this plan, but will not be persisted to local or remote state storage.--------------------------------------------------------------------An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:# ibm_iam_access_group.v1_terraform_new_group will be created
+ resource "ibm_iam_access_group" "v1_terraform_new_group" {
+ description = "testing creating a resource group using terraform"
+ id = (known after apply)
+ name = "terraform-test_access_group"
+ version = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
--------------------------------------------------------------------
This plan was saved to: terra-plan.outTo perform exactly these actions, run the following command to apply:
terraform apply "terra-plan.out"

And let’s confirm by creating it: terraform apply terra-plan.out

ibm_iam_access_group.v1_terraform_new_group: Creating...
ibm_iam_access_group.v1_terraform_new_group: Creation complete after 2s
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.The state of your infrastructure has been saved to the path
below. This state is required to modify and destroy your
infrastructure, so keep it safe. To inspect the complete state
use the `terraform show` command.
State path: terraform.tfstate

Finally confirm on cloud that the access group exists. If so we can move on to preparing our cluster.

# Tells Terraform where to look for the provider files
# Directory is: ~/.terraform.d/plugins/localdomain/provider/ibm
terraform {
required_providers {
ibm = {
source = "localdomain/provider/ibm"
version = "1.14.0"
}
}
}
# We also need to define a variable we will fill in for accessing the cloudvariable "ibmcloud_api_key" {
description = "Enter your IBM Cloud API Key, you can get your IBM Cloud API key using: https://cloud.ibm.com/iam#/apikeys"
}
# We tell Terraform to use this provider
# We tell Terraform to set the key
provider "ibm" {
# Configuration options
ibmcloud_api_key=var.ibmcloud_api_key
}
resource "ibm_container_cluster" "v1_terraform_cluster" {
name = "terraform-example-cluster"
datacenter = "dal10"
machine_type = "u3c.2x4"
hardware = "shared"
public_vlan_id = "1110552"
private_vlan_id = "1110558"
kube_version = "1.20.4"
default_pool_size = 1
}

Confirm and get creating:

Hopefully we are happy with our plan now:

Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be persisted to local or remote state storage.
ibm_iam_access_group.v1_terraform_new_group: Refreshing state...-------------------------------------------------------------------An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions: # ibm_container_cluster.v1_terraform_cluster will be created
+ resource "ibm_container_cluster" "v1_terraform_cluster" {
+ albs = (known after apply)
+ crn = (known after apply)
+ datacenter = "dal10"
+ default_pool_size = 1
+ disk_encryption = true
+ force_delete_storage = false
+ gateway_enabled = false
+ hardware = "shared"
+ id = (known after apply)
+ ingress_hostname = (known after apply)
+ ingress_secret = (sensitive value)
+ isolation = (known after apply)
+ kube_version = "1.20.4"
+ machine_type = "u3c.2x4"
+ name = "terraform-example-cluster"
+ no_subnet = false
+ private_service_endpoint = (known after apply)
+ private_service_endpoint_url = (known after apply)
+ private_vlan_id = "1110558"
+ public_service_endpoint = (known after apply)
+ public_service_endpoint_url = (known after apply)
+ public_vlan_id = "1110552"
+ region = (known after apply)
+ resource_controller_url = (known after apply)
+ resource_crn = (known after apply)
+ resource_group_id = (known after apply)
+ resource_group_name = (known after apply)
+ resource_name = (known after apply)
+ resource_status = (known after apply)
+ server_url = (known after apply)
+ tags = (known after apply)
+ update_all_workers = false
+ wait_for_worker_update = true
+ worker_num = 0
+ worker_pools = (known after apply)
+ workers_info {
+ id = (known after apply)
+ pool_name = (known after apply)
+ version = (known after apply)
}
}
Plan: 1 to add, 0 to change, 0 to destroy.
--------------------------------------------------------------------
This plan was saved to: terra-plan.out
To perform exactly these actions, run the following command to apply:
terraform apply "terra-plan.out"

So we trigger the create: terraform apply terra-plan.out

ibm_container_cluster.v1_terraform_cluster: Creating...
ibm_container_cluster.v1_terraform_cluster: Still creating... [10s elapsed]
ibm_container_cluster.v1_terraform_cluster: Still creating... [20s elapsed]
. . .ibm_container_cluster.v1_terraform_cluster: Still creating... [43m10s elapsed]
ibm_container_cluster.v1_terraform_cluster: Creation complete after 43m16s [id=c0tirstd0ail898hf74g]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.The state of your infrastructure has been saved to the path
below. This state is required to modify and destroy your
infrastructure, so keep it safe. To inspect the complete state
use the `terraform show` command.
State path: terraform.tfstate

Voila, we can start to experiment with K8s (Kubernetes) !!

--

--

Matt
0 Followers

A curious mind in the tech field. #Question-everything