diff --git a/azure/aks/main.tf b/azure/aks/main.tf new file mode 100644 index 00000000..c5460b7b --- /dev/null +++ b/azure/aks/main.tf @@ -0,0 +1,27 @@ +resource "azurerm_resource_group" "app_rg" { + name = var.resource_group_name + location = var.location +} + +module "network" { + source = "./modules/network" + resource_group_name = azurerm_resource_group.app_rg.name + location = var.location + nsg_name = "camunda-aks-nsg" + enable_nsg = true +} + +module "aks" { + source = "./modules/aks" + resource_group_name = azurerm_resource_group.app_rg.name + location = var.location + aks_cluster_name = var.aks_cluster_name + subnet_id = module.network.aks_subnet_id + admin_group_object_id = var.admin_group_object_id + node_pool_count = var.node_pool_count + api_private_access = var.api_private_access + private_dns_zone_id = var.private_dns_zone_id + api_allowed_ip_ranges = var.api_allowed_ip_ranges + tags = var.tags + depends_on = [module.network] +} diff --git a/azure/aks/modules/aks/main.tf b/azure/aks/modules/aks/main.tf new file mode 100644 index 00000000..b8657ac9 --- /dev/null +++ b/azure/aks/modules/aks/main.tf @@ -0,0 +1,33 @@ +terraform { + required_version = ">= 0.12" + + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = ">= 2.0" + } + } +} + +resource "azurerm_kubernetes_cluster" "aks" { + name = var.aks_cluster_name + location = var.location + resource_group_name = var.resource_group_name + dns_prefix = "platform-aks" + + identity { + type = "SystemAssigned" + } + + role_based_access_control_enabled = true + + default_node_pool { + name = "default" + vm_size = var.node_vm_size + os_disk_size_gb = var.node_disk_size_gb + vnet_subnet_id = var.subnet_id + node_count = var.node_pool_count + } + + tags = var.tags +} diff --git a/azure/aks/modules/aks/outputs.tf b/azure/aks/modules/aks/outputs.tf new file mode 100644 index 00000000..bcf1dd68 --- /dev/null +++ b/azure/aks/modules/aks/outputs.tf @@ -0,0 +1,15 @@ +output "aks_cluster_id" { + description = "ID of the deployed AKS cluster" + value = azurerm_kubernetes_cluster.aks.id +} + +output "aks_fqdn" { + description = "FQDN of the AKS cluster" + value = azurerm_kubernetes_cluster.aks.fqdn +} + +output "aks_kube_config" { + description = "Kube config to connect to the AKS cluster" + value = azurerm_kubernetes_cluster.aks.kube_config_raw + sensitive = true +} diff --git a/azure/aks/modules/aks/variables.tf b/azure/aks/modules/aks/variables.tf new file mode 100644 index 00000000..afa28b84 --- /dev/null +++ b/azure/aks/modules/aks/variables.tf @@ -0,0 +1,42 @@ +variable "aks_cluster_name" { + description = "Name of the AKS cluster" + type = string +} + +variable "location" { + description = "Region where the AKS cluster will be deployed" + type = string +} + +variable "resource_group_name" { + description = "Name of the Azure resource group" + type = string +} + +variable "subnet_id" { + description = "ID of the subnet where the AKS cluster will be deployed" + type = string +} + +variable "node_pool_count" { + description = "Fixed number of nodes in the default node pool" + type = number +} + +variable "tags" { + description = "Tags to apply to AKS cluster" + type = map(string) + default = {} +} + +variable "node_vm_size" { + description = "VM size for AKS node pool" + type = string + default = "Standard_D2s_v5" +} + +variable "node_disk_size_gb" { + description = "OS disk size in GB for AKS nodes" + type = number + default = 30 +} diff --git a/azure/aks/modules/network/main.tf b/azure/aks/modules/network/main.tf new file mode 100644 index 00000000..9f0256ce --- /dev/null +++ b/azure/aks/modules/network/main.tf @@ -0,0 +1,47 @@ +terraform { + required_version = ">= 0.12" + + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = ">= 2.0" + } + } +} + +resource "azurerm_virtual_network" "aks_vnet" { + name = "aks-vnet" + location = var.location + resource_group_name = var.resource_group_name + address_space = ["10.1.0.0/16"] +} + +resource "azurerm_subnet" "aks_subnet" { + name = "aks-subnet" + resource_group_name = var.resource_group_name + virtual_network_name = azurerm_virtual_network.aks_vnet.name + address_prefixes = ["10.1.0.0/24"] +} + +resource "azurerm_network_security_group" "aks_nsg" { + name = var.nsg_name + location = var.location + resource_group_name = var.resource_group_name + + security_rule { + name = "Node-to-Node-All" + priority = 100 + direction = "Inbound" + access = "Allow" + protocol = "*" + source_port_range = "*" + destination_port_range = "*" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "VirtualNetwork" + } +} + +resource "azurerm_subnet_network_security_group_association" "aks_nsg_association" { + subnet_id = azurerm_subnet.aks_subnet.id + network_security_group_id = azurerm_network_security_group.aks_nsg.id +} diff --git a/azure/aks/modules/network/outputs.tf b/azure/aks/modules/network/outputs.tf new file mode 100644 index 00000000..75b06ebc --- /dev/null +++ b/azure/aks/modules/network/outputs.tf @@ -0,0 +1,9 @@ +output "aks_subnet_id" { + description = "ID of the subnet where AKS is deployed" + value = azurerm_subnet.aks_subnet.id +} + +output "aks_nsg_id" { + description = "ID of the Network Security Group for AKS" + value = azurerm_network_security_group.aks_nsg.id +} diff --git a/azure/aks/modules/network/variables.tf b/azure/aks/modules/network/variables.tf new file mode 100644 index 00000000..f9bf912d --- /dev/null +++ b/azure/aks/modules/network/variables.tf @@ -0,0 +1,15 @@ +variable "resource_group_name" { + description = "Name of the Azure resource group" + type = string +} + +variable "location" { + description = "Region where resources will be deployed" + type = string +} + +variable "nsg_name" { + description = "Name of the Network Security Group" + type = string + default = "camunda-aks-nsg" +} diff --git a/azure/aks/outputs.tf b/azure/aks/outputs.tf new file mode 100644 index 00000000..93149781 --- /dev/null +++ b/azure/aks/outputs.tf @@ -0,0 +1,7 @@ +output "aks_cluster_id" { + value = module.aks.aks_cluster_id +} + +output "network_security_group_id" { + value = module.network.aks_nsg_id +} diff --git a/azure/aks/providers.tf b/azure/aks/providers.tf new file mode 100644 index 00000000..0a303941 --- /dev/null +++ b/azure/aks/providers.tf @@ -0,0 +1,16 @@ +terraform { + required_version = ">= 1.3.0" + + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = ">= 4.19.0" + } + } +} + +provider "azurerm" { + features {} + resource_provider_registrations = "none" + subscription_id = "5667840f-dd25-4fe1-99ee-5e752ec80b5c" +} diff --git a/azure/aks/storage-class.yaml b/azure/aks/storage-class.yaml new file mode 100644 index 00000000..61ef8a73 --- /dev/null +++ b/azure/aks/storage-class.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + name: premium-lrs-sc + annotations: + storageclass.kubernetes.io/is-default-class: 'true' +provisioner: kubernetes.io/azure-disk +parameters: + storageaccounttype: Premium_LRS + kind: Managed +reclaimPolicy: Retain +volumeBindingMode: WaitForFirstConsumer diff --git a/azure/aks/variables.tf b/azure/aks/variables.tf new file mode 100644 index 00000000..cd69b8ae --- /dev/null +++ b/azure/aks/variables.tf @@ -0,0 +1,54 @@ +variable "location" { + description = "Region where resources will be deployed" + type = string + default = "swedencentral" +} + +variable "resource_group_name" { + description = "Name of the Azure resource group" + type = string + default = "camunda-rg" +} + +variable "tags" { + description = "A map of tags to add to all resources" + type = map(string) + default = {} +} + +variable "aks_cluster_name" { + description = "Name of the AKS cluster" + type = string + default = "camunda-aks" +} + + +variable "node_pool_count" { + description = "Fixed number of nodes in the default node pool" + type = number + default = 3 +} + +variable "api_private_access" { + description = "Enable private API access for AKS" + type = bool + default = true +} + +variable "private_dns_zone_id" { + description = "Private DNS Zone ID for AKS API Server" + type = string + default = null +} + +variable "api_allowed_ip_ranges" { + description = "List of allowed IP ranges for public API access" + type = list(string) + default = [] +} + +variable "admin_group_object_id" { + description = "Microsoft Entra ID group for Kubernetes admins" + type = string + default = "00000000-0000-0000-0000-000000000000" +}