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
11 changes: 4 additions & 7 deletions docs/terraform/cluster/azure-aks.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,6 @@ No modules.
| [azurerm_kubernetes_cluster_node_pool.autoscaled](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/kubernetes_cluster_node_pool) | resource |
| [azurerm_log_analytics_workspace.aks_logs](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/log_analytics_workspace) | resource |
| [azurerm_resource_group.aks](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/resource_group) | resource |
| [azurerm_role_assignment.aks_network_contributor](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) | resource |
| [azurerm_role_assignment.aks_vmss_contributor](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) | resource |
| [azurerm_role_assignment.azurerm_disk_encryption_set_key_vault_access](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) | resource |
| [azurerm_role_assignment.control_plane_managed_identity_operator_on_kubelet](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) | resource |
| [azurerm_role_assignment.des_reader](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) | resource |
| [azurerm_user_assigned_identity.cluster](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/user_assigned_identity) | resource |
| [local_file.kube_config](https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/file) | resource |
| [random_string.key](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string) | resource |
| [time_static.expiry](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/static) | resource |
Expand All @@ -68,7 +62,6 @@ No modules.

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_additional_cluster_identity_ids"></a> [additional\_cluster\_identity\_ids](#input\_additional\_cluster\_identity\_ids) | Additional user assigned identity IDs for the AKS cluster | `list(string)` | `[]` | no |
| <a name="input_auto_scaler_profile"></a> [auto\_scaler\_profile](#input\_auto\_scaler\_profile) | Configuration for the AKS cluster's auto-scaler | <pre>object({<br/> balance_similar_node_groups = bool<br/> max_graceful_termination_sec = number<br/> scale_down_delay_after_add = string<br/> scale_down_delay_after_delete = string<br/> scale_down_delay_after_failure = string<br/> scan_interval = string<br/> scale_down_unneeded = string<br/> scale_down_unready = string<br/> scale_down_utilization_threshold = string<br/> })</pre> | <pre>{<br/> "balance_similar_node_groups": true,<br/> "max_graceful_termination_sec": 600,<br/> "scale_down_delay_after_add": "10m",<br/> "scale_down_delay_after_delete": "10s",<br/> "scale_down_delay_after_failure": "3m",<br/> "scale_down_unneeded": "10m",<br/> "scale_down_unready": "20m",<br/> "scale_down_utilization_threshold": "0.5",<br/> "scan_interval": "10s"<br/>}</pre> | no |
| <a name="input_automatic_upgrade_channel"></a> [automatic\_upgrade\_channel](#input\_automatic\_upgrade\_channel) | The automatic upgrade channel for the AKS cluster | `string` | `"stable"` | no |
| <a name="input_autoscaled_node_pool"></a> [autoscaled\_node\_pool](#input\_autoscaled\_node\_pool) | Configuration for the autoscaled node pool | <pre>object({<br/> enabled = bool<br/> name = string<br/> vm_size = string<br/> mode = string<br/> os_disk_type = string<br/> max_pods = number<br/> host_encryption_enabled = bool<br/> min_count = number<br/> max_count = number<br/> })</pre> | <pre>{<br/> "enabled": true,<br/> "host_encryption_enabled": true,<br/> "max_count": 3,<br/> "max_pods": 110,<br/> "min_count": 1,<br/> "mode": "User",<br/> "name": "autoscaled",<br/> "os_disk_type": "Managed",<br/> "vm_size": "Standard_D2s_v3"<br/>}</pre> | no |
Expand All @@ -80,6 +73,9 @@ No modules.
| <a name="input_dns_service_ip"></a> [dns\_service\_ip](#input\_dns\_service\_ip) | IP address for Kubernetes DNS service | `string` | `"10.96.0.10"` | no |
| <a name="input_endpoint_private_access"></a> [endpoint\_private\_access](#input\_endpoint\_private\_access) | Whether to enable private access to the Kubernetes API server | `bool` | `false` | no |
| <a name="input_expiration_date"></a> [expiration\_date](#input\_expiration\_date) | The expiration date for the AKS cluster's key vault | `string` | `null` | no |
| <a name="input_kubelet_client_id"></a> [kubelet\_client\_id](#input\_kubelet\_client\_id) | Client ID of the user-assigned identity to use for the kubelet. If not provided, the cluster will use the system-assigned identity. | `string` | `null` | no |
| <a name="input_kubelet_object_id"></a> [kubelet\_object\_id](#input\_kubelet\_object\_id) | Object ID of the user-assigned identity to use for the kubelet. If not provided, the cluster will use the system-assigned identity. | `string` | `null` | no |
| <a name="input_kubelet_user_assigned_identity_id"></a> [kubelet\_user\_assigned\_identity\_id](#input\_kubelet\_user\_assigned\_identity\_id) | Resource ID of the user-assigned identity to use for the kubelet. If not provided, the cluster will use the system-assigned identity. | `string` | `null` | no |
| <a name="input_kubernetes_version"></a> [kubernetes\_version](#input\_kubernetes\_version) | Version of Kubernetes to use | `string` | `"1.32"` | no |
| <a name="input_local_account_disabled"></a> [local\_account\_disabled](#input\_local\_account\_disabled) | Whether to disable local accounts for the AKS cluster | `bool` | `false` | no |
| <a name="input_name"></a> [name](#input\_name) | Name of the resource | `string` | `"cluster"` | no |
Expand All @@ -93,6 +89,7 @@ No modules.
| <a name="input_sku_tier"></a> [sku\_tier](#input\_sku\_tier) | The SKU tier for the AKS cluster | `string` | `"Standard"` | no |
| <a name="input_soft_delete_retention_days"></a> [soft\_delete\_retention\_days](#input\_soft\_delete\_retention\_days) | The number of days to retain the AKS cluster's key vault | `number` | `7` | no |
| <a name="input_tags"></a> [tags](#input\_tags) | Tags to apply to the resources | `map(string)` | `{}` | no |
| <a name="input_user_assigned_identity_ids"></a> [user\_assigned\_identity\_ids](#input\_user\_assigned\_identity\_ids) | User assigned identity IDs for the AKS cluster. If provided, the cluster will use only user-assigned identities. | `list(string)` | `[]` | no |
| <a name="input_vnet_module_name"></a> [vnet\_module\_name](#input\_vnet\_module\_name) | Name on the VNET module | `string` | `"network"` | no |
| <a name="input_vnet_subnet_id"></a> [vnet\_subnet\_id](#input\_vnet\_subnet\_id) | ID of the subnet | `string` | `null` | no |
| <a name="input_workload_autoscaler_profile"></a> [workload\_autoscaler\_profile](#input\_workload\_autoscaler\_profile) | Configuration for the AKS cluster's workload autoscaler | <pre>object({<br/> keda_enabled = bool<br/> vertical_pod_autoscaler_enabled = bool<br/> })</pre> | <pre>{<br/> "keda_enabled": false,<br/> "vertical_pod_autoscaler_enabled": false<br/>}</pre> | no |
Expand Down
61 changes: 11 additions & 50 deletions terraform/cluster/azure-aks/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -206,15 +206,6 @@ resource "azurerm_log_analytics_workspace" "aks_logs" {
# AKS Cluster
#-----------------------------------------------------------------------------------------------------------------------

resource "azurerm_user_assigned_identity" "cluster" {
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" {
name = local.cluster_name
location = azurerm_resource_group.aks.location
Expand Down Expand Up @@ -246,12 +237,12 @@ resource "azurerm_kubernetes_cluster" "main" {
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 = var.default_node_pool.only_critical_addons_enabled
# checkov:skip=CKV_AZURE_226: we are using the managed disk type to reduce costs

# 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
# checkov:skip=CKV_AZURE_168: This is set in the variable by default to 50

# checkov:skip=CKV_AZURE_168: This is set in the variable by default to 50
max_pods = var.default_node_pool.max_pods
temporary_name_for_rotation = "rotate"
}
Expand Down Expand Up @@ -285,17 +276,17 @@ resource "azurerm_kubernetes_cluster" "main" {
}

identity {
type = "UserAssigned"
identity_ids = concat(
[azurerm_user_assigned_identity.cluster.id],
var.additional_cluster_identity_ids
)
type = length(var.user_assigned_identity_ids) > 0 ? "UserAssigned" : "SystemAssigned"
identity_ids = var.user_assigned_identity_ids
}

kubelet_identity {
client_id = azurerm_user_assigned_identity.cluster.client_id
object_id = azurerm_user_assigned_identity.cluster.principal_id
user_assigned_identity_id = azurerm_user_assigned_identity.cluster.id
dynamic "kubelet_identity" {
for_each = var.kubelet_user_assigned_identity_id != null ? [1] : []
content {
client_id = var.kubelet_client_id
object_id = var.kubelet_object_id
user_assigned_identity_id = var.kubelet_user_assigned_identity_id
}
}

tags = merge({
Expand Down Expand Up @@ -330,33 +321,3 @@ resource "local_file" "kube_config" {
content = azurerm_kubernetes_cluster.main.kube_config_raw
filename = local.kubeconfig_path
}

resource "azurerm_role_assignment" "aks_vmss_contributor" {
scope = azurerm_resource_group.aks.id
role_definition_name = "Virtual Machine Contributor"
principal_id = azurerm_user_assigned_identity.cluster.principal_id
}

resource "azurerm_role_assignment" "azurerm_disk_encryption_set_key_vault_access" {
scope = azurerm_key_vault.key_vault.id
role_definition_name = "Key Vault Crypto Service Encryption User"
principal_id = azurerm_user_assigned_identity.cluster.principal_id
}

resource "azurerm_role_assignment" "aks_network_contributor" {
scope = azurerm_resource_group.aks.id
role_definition_name = "Network Contributor"
principal_id = azurerm_user_assigned_identity.cluster.principal_id
}

resource "azurerm_role_assignment" "des_reader" {
scope = azurerm_disk_encryption_set.main.id
role_definition_name = "Reader"
principal_id = azurerm_user_assigned_identity.cluster.principal_id
}

resource "azurerm_role_assignment" "control_plane_managed_identity_operator_on_kubelet" {
scope = azurerm_user_assigned_identity.cluster.id
role_definition_name = "Managed Identity Operator"
principal_id = azurerm_user_assigned_identity.cluster.principal_id
}
37 changes: 37 additions & 0 deletions terraform/cluster/azure-aks/test.tftest.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ run "minimal_configuration" {
condition = azurerm_kubernetes_cluster.main.local_account_disabled == false
error_message = "Local accounts should be enabled by default"
}

assert {
condition = azurerm_kubernetes_cluster.main.identity[0].type == "SystemAssigned"
error_message = "Cluster should use system-assigned identity by default"
}
}

# Tests a full configuration with all optional variables explicitly set,
Expand All @@ -79,6 +84,13 @@ run "full_configuration" {
cluster_name = "test-cluster"
resource_group_name = "test-rg"
kubernetes_version = "1.32"
user_assigned_identity_ids = [
"/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.ManagedIdentity/userAssignedIdentities/test-identity-1",
"/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.ManagedIdentity/userAssignedIdentities/test-identity-2"
]
kubelet_client_id = "test-client-id"
kubelet_object_id = "test-object-id"
kubelet_user_assigned_identity_id = "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.ManagedIdentity/userAssignedIdentities/test-identity-1"
default_node_pool = {
name = "system"
vm_size = "Standard_D2s_v3"
Expand Down Expand Up @@ -181,6 +193,31 @@ run "full_configuration" {
condition = azurerm_kubernetes_cluster.main.local_account_disabled == false
error_message = "Local accounts should be enabled"
}

assert {
condition = azurerm_kubernetes_cluster.main.identity[0].type == "UserAssigned"
error_message = "Cluster should use user-assigned identity when IDs are provided"
}

assert {
condition = length(azurerm_kubernetes_cluster.main.identity[0].identity_ids) == 2
error_message = "Cluster should have 2 user-assigned identity IDs"
}

assert {
condition = azurerm_kubernetes_cluster.main.kubelet_identity[0].client_id == "test-client-id"
error_message = "Kubelet client ID should match input"
}

assert {
condition = azurerm_kubernetes_cluster.main.kubelet_identity[0].object_id == "test-object-id"
error_message = "Kubelet object ID should match input"
}

assert {
condition = azurerm_kubernetes_cluster.main.kubelet_identity[0].user_assigned_identity_id == "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.ManagedIdentity/userAssignedIdentities/test-identity-1"
error_message = "Kubelet user-assigned identity ID should match input"
}
}

# Tests the private cluster configuration, ensuring that enabling the private_cluster_enabled
Expand Down
22 changes: 20 additions & 2 deletions terraform/cluster/azure-aks/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -199,9 +199,9 @@ variable "expiration_date" {
default = null
}

variable "additional_cluster_identity_ids" {
variable "user_assigned_identity_ids" {
type = list(string)
description = "Additional user assigned identity IDs for the AKS cluster"
description = "User assigned identity IDs for the AKS cluster. If provided, the cluster will use only user-assigned identities."
default = []
}

Expand Down Expand Up @@ -234,3 +234,21 @@ variable "endpoint_private_access" {
type = bool
default = false
}

variable "kubelet_client_id" {
description = "Client ID of the user-assigned identity to use for the kubelet. If not provided, the cluster will use the system-assigned identity."
type = string
default = null
}

variable "kubelet_object_id" {
description = "Object ID of the user-assigned identity to use for the kubelet. If not provided, the cluster will use the system-assigned identity."
type = string
default = null
}

variable "kubelet_user_assigned_identity_id" {
description = "Resource ID of the user-assigned identity to use for the kubelet. If not provided, the cluster will use the system-assigned identity."
type = string
default = null
}
Loading