Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 40 additions & 16 deletions terraform/cluster/azure-aks/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,30 @@ provider "azurerm" {
}
}

#-----------------------------------------------------------------------------------------------------------------------
# Data Sources
#-----------------------------------------------------------------------------------------------------------------------

data "azurerm_client_config" "current" {}

data "azurerm_subnet" "private" {
count = var.vnet_subnet_id == null ? 1 : 0
name = "private-1-${var.context_id}"
resource_group_name = "${var.vnet_module_name}-${var.context_id}"
virtual_network_name = "${var.vnet_module_name}-${var.context_id}"
}

#-----------------------------------------------------------------------------------------------------------------------
# Locals
#-----------------------------------------------------------------------------------------------------------------------

locals {
kubeconfig_path = "${var.context_path}/.kube/config"
rg_name = var.resource_group_name == null ? "windsor-aks-rg-${var.context_id}" : var.resource_group_name
cluster_name = var.cluster_name == null ? "windsor-aks-cluster-${var.context_id}" : var.cluster_name
rg_name = var.resource_group_name == null ? "${var.name}-${var.context_id}" : var.resource_group_name
cluster_name = var.cluster_name == null ? "${var.name}-${var.context_id}" : var.cluster_name
tags = merge({
WindsorContextID = var.context_id
}, var.tags)
}

#-----------------------------------------------------------------------------------------------------------------------
Expand All @@ -47,6 +61,9 @@ locals {
resource "azurerm_resource_group" "aks" {
name = local.rg_name
location = var.region
tags = merge({
Name = local.rg_name
}, local.tags)
}

#-----------------------------------------------------------------------------------------------------------------------
Expand All @@ -61,7 +78,7 @@ resource "random_string" "key" {

resource "azurerm_key_vault" "key_vault" {
# checkov:skip=CKV2_AZURE_32: We are using a public cluster for testing, there is no need for private endpoints.
name = "keyvault-${var.context_id}-${random_string.key.result}"
name = "${var.name}-${var.context_id}-${random_string.key.result}"
location = azurerm_resource_group.aks.location
resource_group_name = azurerm_resource_group.aks.name
tenant_id = data.azurerm_client_config.current.tenant_id
Expand All @@ -79,6 +96,9 @@ resource "azurerm_key_vault" "key_vault" {
default_action = var.network_acls_default_action
bypass = "AzureServices"
}
tags = merge({
Name = "${var.name}-${var.context_id}-${random_string.key.result}"
}, local.tags)
}

resource "azurerm_key_vault_access_policy" "key_vault_access_policy" {
Expand Down Expand Up @@ -127,7 +147,7 @@ resource "azurerm_key_vault_access_policy" "key_vault_access_policy_disk" {
resource "time_static" "expiry" {}

resource "azurerm_key_vault_key" "key_vault_key" {
name = "key-${var.context_id}-${random_string.key.result}"
name = "${var.name}-${var.context_id}-${random_string.key.result}"
key_vault_id = azurerm_key_vault.key_vault.id
key_type = "RSA-HSM"
key_size = 2048
Expand Down Expand Up @@ -157,7 +177,7 @@ resource "azurerm_key_vault_key" "key_vault_key" {
}

resource "azurerm_disk_encryption_set" "main" {
name = "des-${var.context_id}-${random_string.key.result}"
name = "${var.name}-${var.context_id}-${random_string.key.result}"
resource_group_name = azurerm_resource_group.aks.name
location = azurerm_resource_group.aks.location
key_vault_key_id = azurerm_key_vault_key.key_vault_key.id
Expand All @@ -172,28 +192,27 @@ resource "azurerm_disk_encryption_set" "main" {
#-----------------------------------------------------------------------------------------------------------------------

resource "azurerm_log_analytics_workspace" "aks_logs" {
name = "aks-logs-${var.context_id}"
name = "${var.name}-${var.context_id}"
location = azurerm_resource_group.aks.location
resource_group_name = azurerm_resource_group.aks.name
sku = "PerGB2018"
retention_in_days = 30
tags = merge({
Name = "${var.name}-${var.context_id}"
}, local.tags)
}

#-----------------------------------------------------------------------------------------------------------------------
# AKS Cluster
#-----------------------------------------------------------------------------------------------------------------------

data "azurerm_subnet" "private" {
count = var.vnet_subnet_id == null ? 1 : 0
name = "${var.context_id}-private-1"
resource_group_name = var.vnet_resource_group_name == null ? "windsor-vnet-rg-${var.context_id}" : var.vnet_resource_group_name
virtual_network_name = var.vnet_name == null ? "windsor-vnet-${var.context_id}" : var.vnet_name
}

resource "azurerm_user_assigned_identity" "cluster" {
name = "${var.context_id}-cluster-identity"
name = "${var.name}-${var.context_id}"
location = var.region
resource_group_name = azurerm_resource_group.aks.name
tags = merge({
Name = "${var.name}-${var.context_id}"
}, local.tags)
}

resource "azurerm_kubernetes_cluster" "main" {
Expand Down Expand Up @@ -226,7 +245,7 @@ resource "azurerm_kubernetes_cluster" "main" {
vm_size = var.default_node_pool.vm_size
vnet_subnet_id = coalesce(var.vnet_subnet_id, try(data.azurerm_subnet.private[0].id, null))
orchestrator_version = var.kubernetes_version
only_critical_addons_enabled = true
only_critical_addons_enabled = var.default_node_pool.only_critical_addons_enabled
# checkov:skip=CKV_AZURE_226: we are using the managed disk type to reduce costs
os_disk_type = var.default_node_pool.os_disk_type
host_encryption_enabled = var.default_node_pool.host_encryption_enabled
Expand Down Expand Up @@ -280,6 +299,9 @@ resource "azurerm_kubernetes_cluster" "main" {
workload_autoscaler_profile
]
}
tags = merge({
Name = local.cluster_name
}, local.tags)
}

resource "azurerm_kubernetes_cluster_node_pool" "autoscaled" {
Expand All @@ -304,10 +326,12 @@ resource "azurerm_kubernetes_cluster_node_pool" "autoscaled" {
upgrade_settings
]
}
tags = merge({
Name = var.autoscaled_node_pool.name
}, local.tags)
}

resource "local_file" "kube_config" {
count = var.context_path != "" ? 1 : 0
content = azurerm_kubernetes_cluster.main.kube_config_raw
filename = local.kubeconfig_path
}
Expand Down
41 changes: 23 additions & 18 deletions terraform/cluster/azure-aks/test.tftest.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,17 @@ run "minimal_configuration" {

variables {
context_id = "test"
name = "windsor-aks"
}

assert {
condition = azurerm_kubernetes_cluster.main.name == "windsor-aks-cluster-test"
error_message = "Cluster name should default to 'windsor-aks-cluster-test' when cluster_name is omitted"
condition = azurerm_kubernetes_cluster.main.name == "windsor-aks-test"
error_message = "Cluster name should default to 'windsor-aks-test' when cluster_name is omitted"
}

assert {
condition = azurerm_resource_group.aks.name == "windsor-aks-rg-test"
error_message = "Resource group name should default to 'windsor-aks-rg-test' when resource_group_name is omitted"
condition = azurerm_resource_group.aks.name == "windsor-aks-test"
error_message = "Resource group name should default to 'windsor-aks-test' when resource_group_name is omitted"
}

assert {
Expand Down Expand Up @@ -74,18 +75,20 @@ run "full_configuration" {

variables {
context_id = "test"
name = "windsor-aks"
cluster_name = "test-cluster"
resource_group_name = "test-rg"
kubernetes_version = "1.32"
default_node_pool = {
name = "system"
vm_size = "Standard_D2s_v3"
os_disk_type = "Managed"
max_pods = 30
host_encryption_enabled = true
min_count = 1
max_count = 3
node_count = 1
name = "system"
vm_size = "Standard_D2s_v3"
os_disk_type = "Managed"
max_pods = 30
host_encryption_enabled = true
min_count = 1
max_count = 3
node_count = 1
only_critical_addons_enabled = false
}
autoscaled_node_pool = {
enabled = true
Expand Down Expand Up @@ -187,6 +190,7 @@ run "private_cluster" {

variables {
context_id = "test"
name = "windsor-aks"
cluster_name = "test-cluster"
private_cluster_enabled = true
}
Expand All @@ -197,19 +201,20 @@ run "private_cluster" {
}
}

# Verifies that no kubeconfig file is generated when context_path is empty,
# preventing unnecessary file creation in the root directory.
run "no_config_files" {
# Verifies that a kubeconfig file is generated,
# ensuring proper cluster access configuration.
run "config_file_created" {
command = plan

variables {
context_id = "test"
name = "windsor-aks"
cluster_name = "test-cluster"
context_path = ""
context_path = "/tmp"
}

assert {
condition = length(local_file.kube_config) == 0
error_message = "No kubeconfig file should be generated without context path"
condition = length(local_file.kube_config) >= 1
error_message = "Kubeconfig file should be generated when context path is provided"
}
}
85 changes: 46 additions & 39 deletions terraform/cluster/azure-aks/variables.tf
Original file line number Diff line number Diff line change
@@ -1,23 +1,40 @@
#-----------------------------------------------------------------------------------------------------------------------
# Variables
#-----------------------------------------------------------------------------------------------------------------------
variable "context_path" {
type = string
description = "The path to the context folder, where kubeconfig is stored"
default = ""
}

variable "context_id" {
description = "Context ID for the resources"
type = string
default = null
}

variable "name" {
description = "Name of the resource"
type = string
default = "cluster"
}

variable "resource_group_name" {
description = "Name of the resource group"
type = string
default = null
}

variable "vnet_resource_group_name" {
description = "Name of the VNET resource group"
variable "cluster_name" {
description = "Name of the AKS cluster"
type = string
default = null
}

variable "vnet_name" {
description = "Name of the VNET"
variable "vnet_module_name" {
description = "Name on the VNET module"
type = string
default = null
default = "network"
}

variable "vnet_subnet_id" {
Expand All @@ -32,51 +49,35 @@ variable "region" {
default = "eastus"
}

variable "cluster_name" {
description = "Name of the AKS cluster"
type = string
default = null
}

variable "kubernetes_version" {
description = "Version of Kubernetes to use"
type = string
default = "1.32"
}

variable "context_path" {
type = string
description = "The path to the context folder, where kubeconfig is stored"
default = ""
}

variable "context_id" {
description = "Context ID for the resources"
type = string
default = null
}

variable "default_node_pool" {
description = "Configuration for the default node pool"
type = object({
name = string
vm_size = string
os_disk_type = string
max_pods = number
host_encryption_enabled = bool
min_count = number
max_count = number
node_count = number
name = string
vm_size = string
os_disk_type = string
max_pods = number
host_encryption_enabled = bool
min_count = number
max_count = number
node_count = number
only_critical_addons_enabled = bool
})
default = {
name = "system"
vm_size = "Standard_D2s_v3"
os_disk_type = "Managed"
max_pods = 30
host_encryption_enabled = true
min_count = 1
max_count = 3
node_count = 1
name = "system"
vm_size = "Standard_D2s_v3"
os_disk_type = "Managed"
max_pods = 30
host_encryption_enabled = true
min_count = 1
max_count = 3
node_count = 1
only_critical_addons_enabled = true
}
}

Expand Down Expand Up @@ -209,3 +210,9 @@ variable "soft_delete_retention_days" {
description = "The number of days to retain the AKS cluster's key vault"
default = 7
}

variable "tags" {
description = "Tags to apply to the resources"
type = map(string)
default = {}
}
Loading
Loading