We are major advocates of using infrastructure as code to manage Kubernetes. Terraform is one tool we use to mange the entire lifecycle of Kubernetes infrastructure. Read about the benefits of using Terraform here.
This blog provides a step-by-step guide on how to get started with Terraform and Azure Kubernetes Service (AKS) by deploying your first cluster with infrastructure as code.
If you want to follow along and create your own AKS Cluster in Terraform, follow these steps.
Create a directory for the project (for example, terraform-aks
). Next, set up an ssh key pair in the directory by running this command: ssh-keygen -t rsa -f ./aks-key.
Then, runaz login
from the command line to log into your Azure account.
We’ll now set up several Terraform files to contain the various resource configurations. Let’s name the first fileprovider.tf.
Create the file and add these lines of code:
provider "azurerm" {
version = "~> 2.5.0"
features {}
}
provider "azuread" {
version = "0.9.0"
}
Now, create a file called cluster.tf.
This new file will include our modules for a virtual network, cluster, and node pool. Now we can add a resource group, which is something Azure requires for resources to be created in.
## Create a resource group to place resources
resource "azurerm_resource_group" "aks" {
name = "myakscluster"
location = "centralus"
}
This code will set up the network for your AKS cluster, add this to cluster.tf
as well.
## Create the virtual network for an AKS cluster
module "network" {
source = "[email protected]:FairwindsOps/azure-terraform-modules.git//virtual_network?ref=virtual_network-v0.6.0"
region = "centralus"
resource_group_name = azurerm_resource_group.aks.name
name = "myakscluster"
network_cidr_prefix = "10.64.0.0"
network_cidr_suffix = 10
subnets = [{
name = "aks-subnet"
cidr_block = 16
}]
}
You’ll notice that in thesource
field, thenetwork
module is being pulled from our git repo: [email protected]:FairwindsOps/azure-terraform-modules.git//virtual_network.
If you explore that repo, look under theaks_cluster
directory; you’ll notice theaad.tf
file. This module supports an Azure Active Directory integration, but we won’t be using that here. You can also see all the other resources that are being created by this module. Next, add this code to the cluster.tf
file for the AKS cluster itself:
## Create the AKS cluster
module "cluster" {
source = "[email protected]:FairwindsOps/azure-terraform-modules.git//aks_cluster?ref=aks_cluster-v0.8.0"
region = "centralus"
cluster_name = "myakscluster"
kubernetes_version = "1.16.10"
resource_group_name = azurerm_resource_group.aks.name
node_subnet_id = module.network.subnet_ids[0] # use the subnet from the module above
network_plugin = "azure"
network_policy = "calico"
public_ssh_key_path = "aks-key.pub"
}
Note: This sample code uses Kubernetes 1.16.10. Check the AKS release notes to confirm the latest supported version.
Note that certain values, such asmodule.network.subnet_ids[``0``],
are referenced from thenetwork
module. This feature of Terraform enables you to set values in one module or resource and using them in others. Lastly, add this code tocluster.tf
to set up the node pool that will contain the AKS worker nodes:
## Create the node pool
module "node_pool" {
source = "[email protected]:FairwindsOps/azure-terraform-modules.git//aks_node_pool?ref=aks_node_pool-v0.4.0"
name = "myakspool"
kubernetes_version = "1.16.10"
aks_cluster_id = module.cluster.id
node_subnet_id = module.network.subnet_ids[0]
}
Note: Again, this sample code uses Kubernetes 1.16.10. Check AKS release notes to confirm the latest supported version.
That’s it! Your Terraform files are all ready to go.
The next step is to initialize Terraform by runningterraform init.
Terraform will generate a directory named.terraform
and download each module source declared incluster.tf.
Initialization pulls in any providers required by these modules. In this example, it will download thegoogle
provider. If configured, Terraform will also configure thebackend
for storing the state file.
terraform init
Initializing modules...
Downloading [email protected]:FairwindsOps/azure-terraform-modules.git for cluster...
- cluster in .terraform/modules/cluster/aks_cluster
Downloading [email protected]:FairwindsOps/azure-terraform-modules.git for network...
- network in .terraform/modules/network/virtual_network
Downloading [email protected]:hashicorp/terraform-cidr-subnets.git?ref=v1.0.0 for network.subnet_addrs...
- network.subnet_addrs in .terraform/modules/network.subnet_addrs
Downloading [email protected]:FairwindsOps/azure-terraform-modules.git for node_pool...
- node_pool in .terraform/modules/node_pool/aks_node_pool
Initializing the backend...
Initializing provider plugins...
- Checking for available provider plugins...
- Downloading plugin for provider "azurerm" (hashicorp/azurerm) 2.5.0...
- Downloading plugin for provider "azuread" (hashicorp/azuread) 0.9.0...
- Downloading plugin for provider "kubernetes" (hashicorp/kubernetes) 1.11.3...
- Downloading plugin for provider "null" (hashicorp/null) 2.1.2...
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.kubernetes: version = "~> 1.11"
* provider.null: version = "~> 2.1"
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.
Once you successfully initialize Terraform, you’ll be able to runterraform plan.
It’s always a good idea to runterraform plan
and review the output before allowing Terraform to make any changes.
terraform plan
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.
module.cluster.data.azurerm_subscription.current: 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:
# azurerm_resource_group.aks will be created
+ resource "azurerm_resource_group" "aks" {
+ id = (known after apply)
+ location = "centralus"
+ name = "myakscluster"
}
# module.cluster.azurerm_kubernetes_cluster.cluster will be created
+ resource "azurerm_kubernetes_cluster" "cluster" {
+ dns_prefix = "myakscluster"
+ fqdn = (known after apply)
+ id = (known after apply)
+ kube_admin_config = (known after apply)
+ kube_admin_config_raw = (sensitive value)
+ kube_config = (known after apply)
+ kube_config_raw = (sensitive value)
+ kubernetes_version = "1.16.9"
+ location = "centralus"
+ name = "myakscluster"
+ node_resource_group = (known after apply)
+ private_fqdn = (known after apply)
+ resource_group_name = "myakscluster"
+ tags = {
+ "cluster-name" = "myakscluster"
+ "created-by" = "Terraform"
+ "module-source" = "github.com/FairwindsOps/azure-terraform-modules/aks_cluster"
}
+ addon_profile {
+ aci_connector_linux {
+ enabled = false
}
+ azure_policy {
+ enabled = false
}
+ http_application_routing {
+ enabled = false
+ http_application_routing_zone_name = (known after apply)
}
+ kube_dashboard {
+ enabled = false
}
}
+ default_node_pool {
+ availability_zones = [
+ "1",
+ "2",
+ "3",
]
+ enable_auto_scaling = true
+ enable_node_public_ip = false
+ max_count = 10
+ max_pods = 110
+ min_count = 1
+ name = "default"
+ node_count = 1
+ os_disk_size_gb = 50
+ type = "VirtualMachineScaleSets"
+ vm_size = "Standard_D2_v2"
+ vnet_subnet_id = (known after apply)
}
...
Plan: 4 to add, 0 to change, 0 to destroy.
Note: this snippet has been been edited to cut down on the size of this article.
As shown in the example above, Terraform will take action to add our four AKS resources. When applied, Terraform will create our network, subnetwork (for pods and services), AKS cluster, and node pool.
After the plan is validated, apply the changes by runningterraform apply.
For one last validation step, Terraform will output the plan again and prompt for confirmation before applying. This step takes around 10 minutes to complete. To interact with your cluster, run this command in your terminal.
az aks get-credentials --resource-group myakscluster --name myakscluster --admin
Then you should be able tokubectl get nodes
and you’ll see two worker nodes from your cluster!
kubectl get nodes
NAME STATUS ROLES AGE VERSION
aks-default-14693408-vmss000000 Ready agent 8m24s v1.16.9
aks-myakspool-14693408-vmss000000 Ready agent 4m31s v1.16.9
Congratulations, you’ve successfully deployed a Kubernetes AKS cluster using Terraform! You can now begin deploying your applications to Kubernetes.
This post was originally published on July 14, 2020 and has been updated.
*** This is a Security Bloggers Network syndicated blog from Fairwinds | Blog authored by Brian Bensky, Nate Baker & Mary Goodhart. Read the original post at: https://www.fairwinds.com/blog/getting-started-with-terraform-and-aks-a-step-by-step-guide-to-deploying-your-first-cluster