Skip to content

Add example azure aks terraform #35

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
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
71 changes: 71 additions & 0 deletions terraform/azure/azure-aks-k8s/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# azure-aks-k8s

This example creates the following:

- a Virtual Network with appropriate subnets using the [Azure RM Module for Network](https://registry.terraform.io/modules/Azure/network/azurerm/latest)
from the Terraform Registry
- an Azure Kubernetes Service (AKS) cluster with default node pool
- a system-assigned managed identity for the AKS cluster
- Azure CNI networking for better network performance
- Optional Log Analytics workspace for monitoring

## Prerequisites

- [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli) installed
- [Terraform](https://www.terraform.io/downloads.html) installed (version >= 1.0)
- Azure subscription and appropriate permissions

## To use

Follow the documentation to configure the Azure provider:

- [Azure](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs)

### Deploy

```shell
terraform init
terraform apply
```

## To destroy

```shell
terraform destroy
```

## Configuration

The example uses variables with default values that can be overridden. You can create a `terraform.tfvars` file to customize the deployment:

```hcl
resource_group_name = "my-aks-rg"
location = "westeurope"
cluster_name = "my-production-cluster"
node_count = 3
vm_size = "Standard_D4s_v3"
```

## Outputs

After applying the configuration, Terraform will output:
- `kube_config`: The Kubernetes config file (sensitive)
- `cluster_endpoint`: The AKS cluster endpoint
- `cluster_ca_certificate`: The cluster CA certificate (sensitive)
- `cluster_name`: The name of the AKS cluster
- `resource_group_name`: The name of the resource group

## Features

- Azure CNI networking
- System-assigned managed identity
- Auto-scaling enabled by default
- Customizable node pool configuration
- Network security through VNet integration
- Resource tagging support

## Notes

- The default configuration uses `Standard_D2_v2` VMs which are suitable for development/testing
- For production workloads, consider using larger VM sizes and enabling additional security features
- The network configuration uses Azure CNI for better network performance and security
78 changes: 78 additions & 0 deletions terraform/azure/azure-aks-k8s/cluster.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# AKS Resources

resource "azurerm_resource_group" "aks" {
name = "${local.name}-rg"
location = var.location
tags = local.tags
}

module "vpc" {
source = "../internal-modules/azure-network"

name = local.name
tags = local.tags

location = var.location
resource_group_name = azurerm_resource_group.aks.name

cidrs = var.vnet_address_space
subnet_cidrs = var.subnet_address_prefixes
subnet_name_public = "aks-nodes"
subnet_name_private = "aks-private"
subnet_name_private_dns_resolver = "dns-resolver"
}

# AKS Cluster
resource "azurerm_kubernetes_cluster" "aks" {
name = local.name
location = azurerm_resource_group.aks.location
resource_group_name = azurerm_resource_group.aks.name
dns_prefix = local.name
kubernetes_version = var.kubernetes_version

# Add node resource group name
node_resource_group = "${local.name}-node-rg"

default_node_pool {
name = "default"
vm_size = var.vm_size
vnet_subnet_id = module.vpc.public_subnet_id
enable_auto_scaling = var.enable_auto_scaling
min_count = var.min_count
max_count = var.max_count
os_disk_size_gb = 50
zones = [1, 2, 3]
}

identity {
type = "SystemAssigned"
}

network_profile {
network_plugin = "azure"
service_cidr = var.service_cidr
dns_service_ip = var.dns_service_ip
load_balancer_sku = "standard"
}

# Use oms_agent addon directly instead of addon_profile
dynamic "oms_agent" {
for_each = var.enable_log_analytics_workspace ? [1] : []
content {
log_analytics_workspace_id = azurerm_log_analytics_workspace.aks[0].id
}
}

tags = local.tags
}

# Conditionally create Log Analytics workspace if monitoring is enabled
resource "azurerm_log_analytics_workspace" "aks" {
count = var.enable_log_analytics_workspace ? 1 : 0
name = "${local.name}-logs"
location = azurerm_resource_group.aks.location
resource_group_name = azurerm_resource_group.aks.name
sku = "PerGB2018"
retention_in_days = var.log_retention_in_days
tags = local.tags
}
9 changes: 9 additions & 0 deletions terraform/azure/azure-aks-k8s/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
locals {
name = var.cluster_name != "" ? var.cluster_name : "example-${basename(path.cwd)}"

tags = merge({
Name = local.name
Environment = var.environment
ManagedBy = "Terraform"
}, var.tags)
}
43 changes: 43 additions & 0 deletions terraform/azure/azure-aks-k8s/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Output the cluster's credentials
output "kube_config" {
description = "Raw kubeconfig content for the AKS cluster"
value = azurerm_kubernetes_cluster.aks.kube_config_raw
sensitive = true
}

output "cluster_endpoint" {
description = "Kubernetes API server endpoint"
value = azurerm_kubernetes_cluster.aks.kube_config.0.host
sensitive = true
}

output "cluster_ca_certificate" {
description = "Base64 encoded certificate authority of the Kubernetes cluster"
value = azurerm_kubernetes_cluster.aks.kube_config.0.cluster_ca_certificate
sensitive = true
}

output "cluster_name" {
description = "Name of the AKS cluster"
value = azurerm_kubernetes_cluster.aks.name
}

output "resource_group_name" {
description = "Name of the resource group containing the AKS cluster"
value = azurerm_resource_group.aks.name
}

output "vnet_id" {
description = "ID of the virtual network"
value = module.vpc.vnet_id
}

output "principal_id" {
description = "Principal ID of the AKS cluster identity"
value = azurerm_kubernetes_cluster.aks.identity[0].principal_id
}

output "node_resource_group" {
description = "Auto-generated resource group for the AKS cluster nodes"
value = azurerm_kubernetes_cluster.aks.node_resource_group
}
8 changes: 8 additions & 0 deletions terraform/azure/azure-aks-k8s/providers.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
provider "azurerm" {
skip_provider_registration = true
features {
resource_group {
prevent_deletion_if_contains_resources = false
}
}
}
118 changes: 118 additions & 0 deletions terraform/azure/azure-aks-k8s/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
variable "location" {
description = "Azure region where resources will be created"
type = string
default = "eastus"
}

variable "cluster_name" {
description = "Name of the AKS cluster (will generate one if empty)"
type = string
}

variable "environment" {
description = "Environment for the resources (e.g., dev, test, prod)"
type = string
default = "dev"
}

variable "tags" {
description = "A map of tags to add to all resources"
type = map(string)
default = {}
}

variable "kubernetes_version" {
description = "Kubernetes version to use for the AKS cluster"
type = string
default = "1.31.6"
}

variable "vm_size" {
description = "VM size for the AKS node pool"
type = string
default = "Standard_DS2_v2"
}

variable "enable_auto_scaling" {
description = "Enable auto scaling for the AKS node pool"
type = bool
default = true
}

variable "min_count" {
description = "Minimum number of nodes in the AKS node pool"
type = number
default = 1
}

variable "max_count" {
description = "Maximum number of nodes in the AKS node pool"
type = number
default = 3
}

variable "vnet_address_space" {
description = "Address space for the virtual network"
type = list(string)
default = ["10.0.0.0/16"]
}

variable "subnet_address_prefixes" {
description = "Address prefixes for the subnets (requires 3 subnets for nodes, private, and DNS resolver)"
type = list(string)
default = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
}

variable "service_cidr" {
description = "CIDR range for Kubernetes services"
type = string
default = "172.16.0.0/16"
}

variable "dns_service_ip" {
description = "IP address for Kubernetes DNS service (must be within service_cidr)"
type = string
default = "172.16.0.10"
}

variable "docker_bridge_cidr" {
description = "CIDR notation IP for Docker bridge"
type = string
default = "172.17.0.1/16"
}

variable "availability_zones" {
description = "List of availability zones to use for the node pool"
type = list(number)
default = [1, 2, 3]
}

variable "os_disk_size_gb" {
description = "Disk size for nodes in GB"
type = number
default = 50
}

variable "os_disk_type" {
description = "Disk type for nodes"
type = string
default = "Managed"
}

variable "node_labels" {
description = "Labels to apply to nodes in the default node pool"
type = map(string)
default = {}
}

variable "enable_log_analytics_workspace" {
description = "Enable the creation of a Log Analytics workspace for the AKS cluster"
type = bool
default = false
}

variable "log_retention_in_days" {
description = "Number of days to retain logs in Log Analytics"
type = number
default = 30
}
8 changes: 8 additions & 0 deletions terraform/azure/azure-aks-k8s/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.0"
}
}
}