From b4d429be35073f013bfb635e6912be5b0a496988 Mon Sep 17 00:00:00 2001 From: Tom Archer Date: Fri, 12 May 2023 08:52:11 -0700 Subject: [PATCH 1/5] User Story 90135 --- .../201-k8s-cluster-with-tf-and-aks/main.tf | 41 ++++++++----- .../outputs.tf | 16 +++-- .../providers.tf | 6 +- .../201-k8s-cluster-with-tf-and-aks/readme.md | 20 +++---- .../201-k8s-cluster-with-tf-and-aks/sp.tf | 28 +++++++++ .../201-k8s-cluster-with-tf-and-aks/ssh.tf | 25 ++++++++ .../terraform.tfvars | 2 - .../variables.tf | 60 ++++++++----------- 8 files changed, 130 insertions(+), 68 deletions(-) create mode 100644 quickstart/201-k8s-cluster-with-tf-and-aks/sp.tf create mode 100644 quickstart/201-k8s-cluster-with-tf-and-aks/ssh.tf delete mode 100644 quickstart/201-k8s-cluster-with-tf-and-aks/terraform.tfvars diff --git a/quickstart/201-k8s-cluster-with-tf-and-aks/main.tf b/quickstart/201-k8s-cluster-with-tf-and-aks/main.tf index 7bfa90f88..57dccc1d7 100644 --- a/quickstart/201-k8s-cluster-with-tf-and-aks/main.tf +++ b/quickstart/201-k8s-cluster-with-tf-and-aks/main.tf @@ -8,15 +8,19 @@ resource "azurerm_resource_group" "rg" { name = random_pet.rg_name.id } -resource "random_id" "log_analytics_workspace_name_suffix" { - byte_length = 8 +data "azurerm_client_config" "current" {} + +locals { + current_user_id = coalesce(var.msi_id, data.azurerm_client_config.current.object_id) +} + +resource "random_pet" "azurerm_log_analytics_workspace_name" { + prefix = "ws" } resource "azurerm_log_analytics_workspace" "test" { - location = var.log_analytics_workspace_location - # The WorkSpace name has to be unique across the whole of azure; - # not just the current subscription/tenant. - name = "${var.log_analytics_workspace_name}-${random_id.log_analytics_workspace_name_suffix.dec}" + location = var.log_analytics_workspace_location + name = random_pet.azurerm_log_analytics_workspace_name.id resource_group_name = azurerm_resource_group.rg.name sku = var.log_analytics_workspace_sku } @@ -34,25 +38,30 @@ resource "azurerm_log_analytics_solution" "test" { } } +resource "random_pet" "azurerm_kubernetes_cluster_name" { + prefix = "cluster" +} + +resource "random_pet" "azurerm_kubernetes_cluster_dns_prefix" { + prefix = "dns" +} + resource "azurerm_kubernetes_cluster" "k8s" { location = azurerm_resource_group.rg.location - name = var.cluster_name + name = random_pet.azurerm_kubernetes_cluster_name.id resource_group_name = azurerm_resource_group.rg.name - dns_prefix = var.dns_prefix - tags = { - Environment = "Development" - } + dns_prefix = random_pet.azurerm_kubernetes_cluster_dns_prefix.id default_node_pool { name = "agentpool" vm_size = "Standard_D2_v2" - node_count = var.agent_count + node_count = var.node_count } linux_profile { admin_username = "ubuntu" ssh_key { - key_data = file(var.ssh_public_key) + key_data = jsondecode(azapi_resource_action.ssh_public_key_gen.output).publicKey } } network_profile { @@ -60,7 +69,7 @@ resource "azurerm_kubernetes_cluster" "k8s" { load_balancer_sku = "standard" } service_principal { - client_id = var.aks_service_principal_app_id - client_secret = var.aks_service_principal_client_secret + client_id = azuread_service_principal.app.application_id + client_secret = azuread_service_principal_password.app.value } -} +} \ No newline at end of file diff --git a/quickstart/201-k8s-cluster-with-tf-and-aks/outputs.tf b/quickstart/201-k8s-cluster-with-tf-and-aks/outputs.tf index b41d7ae13..ae021ac73 100644 --- a/quickstart/201-k8s-cluster-with-tf-and-aks/outputs.tf +++ b/quickstart/201-k8s-cluster-with-tf-and-aks/outputs.tf @@ -1,3 +1,15 @@ +output "resource_group_name" { + value = azurerm_resource_group.rg.name +} + +output "kubernetes_cluster_name" { + value = azurerm_kubernetes_cluster.k8s.name +} + +output "log_analytics_workspace_name" { + value = azurerm_log_analytics_workspace.test.name +} + output "client_certificate" { value = azurerm_kubernetes_cluster.k8s.kube_config[0].client_certificate sensitive = true @@ -31,8 +43,4 @@ output "host" { output "kube_config" { value = azurerm_kubernetes_cluster.k8s.kube_config_raw sensitive = true -} - -output "resource_group_name" { - value = azurerm_resource_group.rg.name } \ No newline at end of file diff --git a/quickstart/201-k8s-cluster-with-tf-and-aks/providers.tf b/quickstart/201-k8s-cluster-with-tf-and-aks/providers.tf index 74dc62e14..cfba58243 100644 --- a/quickstart/201-k8s-cluster-with-tf-and-aks/providers.tf +++ b/quickstart/201-k8s-cluster-with-tf-and-aks/providers.tf @@ -2,6 +2,10 @@ terraform { required_version = ">=1.0" required_providers { + azapi = { + source = "azure/azapi" + version = "~>1.5" + } azurerm = { source = "hashicorp/azurerm" version = "~>3.0" @@ -15,4 +19,4 @@ terraform { provider "azurerm" { features {} -} +} \ No newline at end of file diff --git a/quickstart/201-k8s-cluster-with-tf-and-aks/readme.md b/quickstart/201-k8s-cluster-with-tf-and-aks/readme.md index e56453ce9..dbf948245 100644 --- a/quickstart/201-k8s-cluster-with-tf-and-aks/readme.md +++ b/quickstart/201-k8s-cluster-with-tf-and-aks/readme.md @@ -2,14 +2,21 @@ This template provisions an [AKS / Azure Kubernetes service (also known as a Managed Kubernetes Cluster)](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/kubernetes_cluster). +- [random_string](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string) + ## Terraform resource types - [random_pet](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) -- [random_string](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string) - [azurerm_resource_group](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/resource_group) +- [azurerm_client_config](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/client_config) - [azurerm_log_analytics_workspace](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/log_analytics_workspace) - [azurerm_log_analytics_solution](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/log_analytics_solution) - [azurerm_kubernetes_cluster](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/kubernetes_cluster) +- [azuread_application](https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/data-sources/application) +- [azuread_service_principal](https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/data-sources/service_principal) +- [azuread_service_principal_password](https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/resources/service_principal_password) +- [azapi_resource](https://registry.terraform.io/providers/Azure/azapi/latest/docs/resources/azapi_resource) +- [azapi_resource_action](https://registry.terraform.io/providers/Azure/azapi/latest/docs/resources/azapi_resource_action) ## Variables @@ -17,16 +24,9 @@ This template provisions an [AKS / Azure Kubernetes service (also known as a Man |-|-|-| | `resource_group_name_prefix` | Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription. | rg | | `resource_group_location` | Location of the resource group. | eastus | -| `agent_count` | Initial number of nodes which should exist in this Node Pool. Value must be between 1 and 1000. | 3 | -| `ssh_public_key` | File containing the an ssh_key block. | ~/.ssh/id_rsa.pub | -| `dns_prefix` | DNS prefix specified when creating the managed cluster. | k8stest | -| `cluster_name` | Name of the Managed Kubernetes Cluster to create. | k8stest | -| `log_analytics_workspace_name` | Prefix of the name of the Log Analytics Workspace. Random value is appended to ensure uniqueness across Azure. | testLogAnalyticsWorkspaceName | -| `log_analytics_workspace_location` | Azure location where the resource exists. | eastus | +| `node_count` | Initial number of nodes which should exist in this Node Pool. Value must be between 1 and 1000. | 3 | +| `log_analytics_workspace_location` | Location of the log analytics workspace. | eastus | | `log_analytics_workspace_sku` | SKU of the Log Analytics Workspace. | PerGB2018 | -| `aks_service_principal_app_id` | Service principal app ID. | | -| `aks_service_principal_client_secret` | Service principal password. | | -| `aks_service_principal_object_id` | Service principal object ID. | | ## Example diff --git a/quickstart/201-k8s-cluster-with-tf-and-aks/sp.tf b/quickstart/201-k8s-cluster-with-tf-and-aks/sp.tf new file mode 100644 index 000000000..6d96548ed --- /dev/null +++ b/quickstart/201-k8s-cluster-with-tf-and-aks/sp.tf @@ -0,0 +1,28 @@ +# Create Azure AD App Registration +resource "azuread_application" "app" { + display_name = "my-app" + owners = [local.current_user_id] +} + +# Create Service Principal +resource "azuread_service_principal" "app" { + application_id = azuread_application.app.application_id + app_role_assignment_required = true + owners = [local.current_user_id] +} + +# Create Service Principal password +resource "azuread_service_principal_password" "app" { + service_principal_id = azuread_service_principal.app.id +} + +# Output the Service Principal and password +output "sp" { + value = azuread_service_principal.app.id + sensitive = true +} + +output "sp_password" { + value = azuread_service_principal_password.app.value + sensitive = true +} \ No newline at end of file diff --git a/quickstart/201-k8s-cluster-with-tf-and-aks/ssh.tf b/quickstart/201-k8s-cluster-with-tf-and-aks/ssh.tf new file mode 100644 index 000000000..6e142ef3d --- /dev/null +++ b/quickstart/201-k8s-cluster-with-tf-and-aks/ssh.tf @@ -0,0 +1,25 @@ +resource "random_pet" "ssh_key_name" { + prefix = "ssh" + separator = "" +} + +resource "azapi_resource" "ssh_public_key" { + type = "Microsoft.Compute/sshPublicKeys@2022-11-01" + name = random_pet.ssh_key_name.id + location = "westus3" + parent_id = azurerm_resource_group.rg.id +} + +resource "azapi_resource_action" "ssh_public_key_gen" { + type = "Microsoft.Compute/sshPublicKeys@2022-11-01" + resource_id = azapi_resource.ssh_public_key.id + action = "generateKeyPair" + method = "POST" + + response_export_values = ["publicKey"] +} + +output "key_data" { + value = azapi_resource.ssh_public_key.body + sensitive = true +} \ No newline at end of file diff --git a/quickstart/201-k8s-cluster-with-tf-and-aks/terraform.tfvars b/quickstart/201-k8s-cluster-with-tf-and-aks/terraform.tfvars deleted file mode 100644 index 866eb9212..000000000 --- a/quickstart/201-k8s-cluster-with-tf-and-aks/terraform.tfvars +++ /dev/null @@ -1,2 +0,0 @@ -aks_service_principal_app_id = "" -aks_service_principal_client_secret = "" \ No newline at end of file diff --git a/quickstart/201-k8s-cluster-with-tf-and-aks/variables.tf b/quickstart/201-k8s-cluster-with-tf-and-aks/variables.tf index c90da17db..087f2eacb 100644 --- a/quickstart/201-k8s-cluster-with-tf-and-aks/variables.tf +++ b/quickstart/201-k8s-cluster-with-tf-and-aks/variables.tf @@ -1,49 +1,39 @@ -variable "agent_count" { - default = 3 -} - -# The following two variable declarations are placeholder references. -# Set the values for these variable in terraform.tfvars -variable "aks_service_principal_app_id" { - default = "" -} - -variable "aks_service_principal_client_secret" { - default = "" +variable "resource_group_location" { + type= string + default = "eastus" + description = "Location of the resource group." } -variable "cluster_name" { - default = "k8stest" +variable "resource_group_name_prefix" { + type= string + default = "rg" + description = "Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription." } -variable "dns_prefix" { - default = "k8stest" +variable "node_count" { + type = number + description = "The initial quantity of nodes for the node pool." + default = 3 } -# Refer to https://azure.microsoft.com/global-infrastructure/services/?products=monitor for available Log Analytics regions. +# For available Log Analytics regions, refer to: +# https://azure.microsoft.com/global-infrastructure/services/?products=monitor variable "log_analytics_workspace_location" { + type= string default = "eastus" + description = "Location of the log analytics workspace." } -variable "log_analytics_workspace_name" { - default = "testLogAnalyticsWorkspaceName" -} - -# Refer to https://azure.microsoft.com/pricing/details/monitor/ for Log Analytics pricing +# For Log Analytics pricing, refer to: +# https://azure.microsoft.com/pricing/details/monitor variable "log_analytics_workspace_sku" { + type=string + description = "" default = "PerGB2018" } -variable "resource_group_location" { - default = "eastus" - description = "Location of the resource group." -} - -variable "resource_group_name_prefix" { - default = "rg" - description = "Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription." -} - -variable "ssh_public_key" { - default = "~/.ssh/id_rsa.pub" -} +variable "msi_id" { + type = string + description = "The Managed Service Identity ID used to create the service principal. If this value is null (the default), the AzureRM provider configuration Object ID is used.." + default = null +} \ No newline at end of file From 71cee46b77a2db239e97d5adc568a8c0e0cfebe0 Mon Sep 17 00:00:00 2001 From: Tom Archer Date: Fri, 12 May 2023 17:10:12 -0700 Subject: [PATCH 2/5] Ran 'terraform fmt' --- .../201-k8s-cluster-with-tf-and-aks/main.tf | 2 +- .../201-k8s-cluster-with-tf-and-aks/variables.tf | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/quickstart/201-k8s-cluster-with-tf-and-aks/main.tf b/quickstart/201-k8s-cluster-with-tf-and-aks/main.tf index 57dccc1d7..1af8c3033 100644 --- a/quickstart/201-k8s-cluster-with-tf-and-aks/main.tf +++ b/quickstart/201-k8s-cluster-with-tf-and-aks/main.tf @@ -19,7 +19,7 @@ resource "random_pet" "azurerm_log_analytics_workspace_name" { } resource "azurerm_log_analytics_workspace" "test" { - location = var.log_analytics_workspace_location + location = var.log_analytics_workspace_location name = random_pet.azurerm_log_analytics_workspace_name.id resource_group_name = azurerm_resource_group.rg.name sku = var.log_analytics_workspace_sku diff --git a/quickstart/201-k8s-cluster-with-tf-and-aks/variables.tf b/quickstart/201-k8s-cluster-with-tf-and-aks/variables.tf index 087f2eacb..6093806bd 100644 --- a/quickstart/201-k8s-cluster-with-tf-and-aks/variables.tf +++ b/quickstart/201-k8s-cluster-with-tf-and-aks/variables.tf @@ -1,35 +1,35 @@ variable "resource_group_location" { - type= string + type = string default = "eastus" description = "Location of the resource group." } variable "resource_group_name_prefix" { - type= string + type = string default = "rg" description = "Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription." } variable "node_count" { - type = number + type = number description = "The initial quantity of nodes for the node pool." - default = 3 + default = 3 } # For available Log Analytics regions, refer to: # https://azure.microsoft.com/global-infrastructure/services/?products=monitor variable "log_analytics_workspace_location" { - type= string - default = "eastus" + type = string + default = "eastus" description = "Location of the log analytics workspace." } # For Log Analytics pricing, refer to: # https://azure.microsoft.com/pricing/details/monitor variable "log_analytics_workspace_sku" { - type=string + type = string description = "" - default = "PerGB2018" + default = "PerGB2018" } variable "msi_id" { From 669f6c96c6eeae44a6ba2180eb11fe0408bd45d2 Mon Sep 17 00:00:00 2001 From: Tom Archer Date: Fri, 12 May 2023 17:30:37 -0700 Subject: [PATCH 3/5] Added validation for workspace sku --- quickstart/201-k8s-cluster-with-tf-and-aks/readme.md | 4 ++-- quickstart/201-k8s-cluster-with-tf-and-aks/variables.tf | 9 +++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/quickstart/201-k8s-cluster-with-tf-and-aks/readme.md b/quickstart/201-k8s-cluster-with-tf-and-aks/readme.md index dbf948245..f4a7ceeb6 100644 --- a/quickstart/201-k8s-cluster-with-tf-and-aks/readme.md +++ b/quickstart/201-k8s-cluster-with-tf-and-aks/readme.md @@ -25,8 +25,8 @@ This template provisions an [AKS / Azure Kubernetes service (also known as a Man | `resource_group_name_prefix` | Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription. | rg | | `resource_group_location` | Location of the resource group. | eastus | | `node_count` | Initial number of nodes which should exist in this Node Pool. Value must be between 1 and 1000. | 3 | -| `log_analytics_workspace_location` | Location of the log analytics workspace. | eastus | -| `log_analytics_workspace_sku` | SKU of the Log Analytics Workspace. | PerGB2018 | +| `log_analytics_workspace_location` | Location of the Log Analytics workspace. | eastus | +| `log_analytics_workspace_sku` | SKU of the Log Analytics workspace. The SKU of the log analytics workspace. Choose from: Free, PerNode, Premium, Standard, Standalone, Unlimited, CapacityReservation, PerGB2018 | PerGB2018 | ## Example diff --git a/quickstart/201-k8s-cluster-with-tf-and-aks/variables.tf b/quickstart/201-k8s-cluster-with-tf-and-aks/variables.tf index 6093806bd..47046edf4 100644 --- a/quickstart/201-k8s-cluster-with-tf-and-aks/variables.tf +++ b/quickstart/201-k8s-cluster-with-tf-and-aks/variables.tf @@ -21,15 +21,20 @@ variable "node_count" { variable "log_analytics_workspace_location" { type = string default = "eastus" - description = "Location of the log analytics workspace." + description = "Location of the Log Analytics workspace." } # For Log Analytics pricing, refer to: # https://azure.microsoft.com/pricing/details/monitor variable "log_analytics_workspace_sku" { type = string - description = "" + description = "The SKU of the Log Analytics workspace. Choose from: Free, PerNode, Premium, Standard, Standalone, Unlimited, CapacityReservation, PerGB2018" default = "PerGB2018" + + validation { + condition = contains(["Free", "PerNode", "Premium", "Standard", "Standalone", "Unlimited", "CapacityReservation", "PerGB2018"], var.log_analytics_workspace_sku) + error_message = "The Log Analytics workspace SKU must be one of the following: Free, PerNode, Premium, Standard, Standalone, Unlimited, CapacityReservation, PerGB2018" + } } variable "msi_id" { From b316c4dd0de84869e9b82adec194212511af8df7 Mon Sep 17 00:00:00 2001 From: Tom Archer Date: Wed, 24 May 2023 11:02:38 -0700 Subject: [PATCH 4/5] Ran 'terraform fmt' --- quickstart/201-k8s-cluster-with-tf-and-aks/variables.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstart/201-k8s-cluster-with-tf-and-aks/variables.tf b/quickstart/201-k8s-cluster-with-tf-and-aks/variables.tf index 47046edf4..89d16be3b 100644 --- a/quickstart/201-k8s-cluster-with-tf-and-aks/variables.tf +++ b/quickstart/201-k8s-cluster-with-tf-and-aks/variables.tf @@ -32,7 +32,7 @@ variable "log_analytics_workspace_sku" { default = "PerGB2018" validation { - condition = contains(["Free", "PerNode", "Premium", "Standard", "Standalone", "Unlimited", "CapacityReservation", "PerGB2018"], var.log_analytics_workspace_sku) + condition = contains(["Free", "PerNode", "Premium", "Standard", "Standalone", "Unlimited", "CapacityReservation", "PerGB2018"], var.log_analytics_workspace_sku) error_message = "The Log Analytics workspace SKU must be one of the following: Free, PerNode, Premium, Standard, Standalone, Unlimited, CapacityReservation, PerGB2018" } } From 88d524b952860a7dcca1e6a7a52aadb84ca2cf68 Mon Sep 17 00:00:00 2001 From: Tom Archer Date: Wed, 24 May 2023 11:59:56 -0700 Subject: [PATCH 5/5] Made edits per Code Review --- quickstart/201-k8s-cluster-with-tf-and-aks/main.tf | 2 ++ quickstart/201-k8s-cluster-with-tf-and-aks/providers.tf | 4 ++++ quickstart/201-k8s-cluster-with-tf-and-aks/sp.tf | 9 +++++++++ 3 files changed, 15 insertions(+) diff --git a/quickstart/201-k8s-cluster-with-tf-and-aks/main.tf b/quickstart/201-k8s-cluster-with-tf-and-aks/main.tf index 1af8c3033..5fc878bd2 100644 --- a/quickstart/201-k8s-cluster-with-tf-and-aks/main.tf +++ b/quickstart/201-k8s-cluster-with-tf-and-aks/main.tf @@ -72,4 +72,6 @@ resource "azurerm_kubernetes_cluster" "k8s" { client_id = azuread_service_principal.app.application_id client_secret = azuread_service_principal_password.app.value } + + depends_on = [time_sleep.wait_30_seconds] } \ No newline at end of file diff --git a/quickstart/201-k8s-cluster-with-tf-and-aks/providers.tf b/quickstart/201-k8s-cluster-with-tf-and-aks/providers.tf index cfba58243..7eff01791 100644 --- a/quickstart/201-k8s-cluster-with-tf-and-aks/providers.tf +++ b/quickstart/201-k8s-cluster-with-tf-and-aks/providers.tf @@ -14,6 +14,10 @@ terraform { source = "hashicorp/random" version = "~>3.0" } + time = { + source = "hashicorp/time" + version = "0.9.1" + } } } diff --git a/quickstart/201-k8s-cluster-with-tf-and-aks/sp.tf b/quickstart/201-k8s-cluster-with-tf-and-aks/sp.tf index 6d96548ed..adde91827 100644 --- a/quickstart/201-k8s-cluster-with-tf-and-aks/sp.tf +++ b/quickstart/201-k8s-cluster-with-tf-and-aks/sp.tf @@ -16,6 +16,15 @@ resource "azuread_service_principal_password" "app" { service_principal_id = azuread_service_principal.app.id } +# Sleep for 30 seconds to allow for propagation +# of the Service Principal creation before attempting +# to create the AKS cluster. +resource "time_sleep" "wait_30_seconds" { + create_duration = "30s" + + depends_on = [azuread_service_principal_password.app] +} + # Output the Service Principal and password output "sp" { value = azuread_service_principal.app.id