快速入门:使用 Terraform 创建具有Azure Kubernetes 服务的 Kubernetes 群集

文章使用以下 Terraform 和 Terraform 提供程序版本进行测试:

使用 Terraform 可以定义、预览和部署云基础结构。 使用 Terraform 时,请使用 HCL 语法来创建配置文件。 利用 HCL 语法,可指定 Azure 这样的云提供程序和构成云基础结构的元素。 创建配置文件后,请创建一个执行计划,利用该计划,可在部署基础结构更改之前先预览这些更改。 验证了更改后,请应用该执行计划以部署基础结构。

Azure Kubernetes 服务 (AKS) 管理托管的 Kubernetes 环境。 使用 AKS 可以部署和管理容器化应用程序,而无需具备容器业务流程方面的专业知识。 使用 AKS 还可在应用不离线的情况下进行许多常见的维护操作。 这些操作包括按需预配、更新和缩放资源。

在本文中,学习如何:

  • 使用 HCL(HashiCorp 语言)定义 Kubernetes 群集
  • 使用 Terraform 和 AKS 创建 Kubernetes 群集
  • 使用 kubectl 工具测试 Kubernetes 群集的可用性

备注

本文中的示例代码位于 Microsoft Terraform GitHub 存储库中。

先决条件

  • Azure 订阅:如果没有 Azure 订阅,请在开始之前创建一个免费帐户

实现 Terraform 代码

  1. 创建用于测试和运行示例 Terraform 代码的目录,并将其设为当前目录。

  2. 创建名为 providers.tf 的文件并插入下列代码:

    terraform {
      required_version = ">=1.0"
    
      required_providers {
        azurerm = {
          source  = "hashicorp/azurerm"
          version = "~>3.0"
        }
        random = {
          source  = "hashicorp/random"
          version = "~>3.0"
        }
      }
    }
    
    provider "azurerm" {
      features {}
    }
    
  3. 创建名为 main.tf 的文件并插入下列代码:

    # Generate random resource group name
    resource "random_pet" "rg_name" {
      prefix = var.resource_group_name_prefix
    }
    
    resource "azurerm_resource_group" "rg" {
      location = var.resource_group_location
      name     = random_pet.rg_name.id
    }
    
    resource "random_id" "log_analytics_workspace_name_suffix" {
      byte_length = 8
    }
    
    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}"
      resource_group_name = azurerm_resource_group.rg.name
      sku                 = var.log_analytics_workspace_sku
    }
    
    resource "azurerm_log_analytics_solution" "test" {
      location              = azurerm_log_analytics_workspace.test.location
      resource_group_name   = azurerm_resource_group.rg.name
      solution_name         = "ContainerInsights"
      workspace_name        = azurerm_log_analytics_workspace.test.name
      workspace_resource_id = azurerm_log_analytics_workspace.test.id
    
      plan {
        product   = "OMSGallery/ContainerInsights"
        publisher = "Microsoft"
      }
    }
    
    resource "azurerm_kubernetes_cluster" "k8s" {
      location            = azurerm_resource_group.rg.location
      name                = var.cluster_name
      resource_group_name = azurerm_resource_group.rg.name
      dns_prefix          = var.dns_prefix
      tags                = {
        Environment = "Development"
      }
    
      default_node_pool {
        name       = "agentpool"
        vm_size    = "Standard_D2_v2"
        node_count = var.agent_count
      }
      linux_profile {
        admin_username = "ubuntu"
    
        ssh_key {
          key_data = file(var.ssh_public_key)
        }
      }
      network_profile {
        network_plugin    = "kubenet"
        load_balancer_sku = "standard"
      }
      service_principal {
        client_id     = var.aks_service_principal_app_id
        client_secret = var.aks_service_principal_client_secret
      }
    }
    
  4. 创建名为 variables.tf 的文件并插入下列代码:

    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 "cluster_name" {
      default = "k8stest"
    }
    
    variable "dns_prefix" {
      default = "k8stest"
    }
    
    # Refer to https://azure.microsoft.com/global-infrastructure/services/?products=monitor for available Log Analytics regions.
    variable "log_analytics_workspace_location" {
      default = "eastus"
    }
    
    variable "log_analytics_workspace_name" {
      default = "testLogAnalyticsWorkspaceName"
    }
    
    # Refer to https://azure.microsoft.com/pricing/details/monitor/ for Log Analytics pricing
    variable "log_analytics_workspace_sku" {
      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"
    }
    
  5. 创建名为 outputs.tf 的文件并插入下列代码:

    output "client_certificate" {
      value     = azurerm_kubernetes_cluster.k8s.kube_config[0].client_certificate
      sensitive = true
    }
    
    output "client_key" {
      value     = azurerm_kubernetes_cluster.k8s.kube_config[0].client_key
      sensitive = true
    }
    
    output "cluster_ca_certificate" {
      value     = azurerm_kubernetes_cluster.k8s.kube_config[0].cluster_ca_certificate
      sensitive = true
    }
    
    output "cluster_password" {
      value     = azurerm_kubernetes_cluster.k8s.kube_config[0].password
      sensitive = true
    }
    
    output "cluster_username" {
      value     = azurerm_kubernetes_cluster.k8s.kube_config[0].username
      sensitive = true
    }
    
    output "host" {
      value     = azurerm_kubernetes_cluster.k8s.kube_config[0].host
      sensitive = true
    }
    
    output "kube_config" {
      value     = azurerm_kubernetes_cluster.k8s.kube_config_raw
      sensitive = true
    }
    
    output "resource_group_name" {
      value = azurerm_resource_group.rg.name
    }
    
  6. 创建名为 terraform.tfvars 的文件并插入下列代码。

    aks_service_principal_app_id = "<service_principal_app_id>"
    aks_service_principal_client_secret = "<service_principal_password>"
    

初始化 Terraform

运行 terraform init,将 Terraform 部署进行初始化。 此命令下载管理 Azure 资源所需的 Azure 模块。

terraform init

创建 Terraform 执行计划

运行 terraform plan 以创建执行计划。

terraform plan -out main.tfplan

要点:

  • terraform plan 命令将创建一个执行计划,但不会执行它。 它会确定创建配置文件中指定的配置需要执行哪些操作。 此模式允许你在对实际资源进行任何更改之前验证执行计划是否符合预期。
  • 使用可选 -out 参数可以为计划指定输出文件。 使用 -out 参数可以确保所查看的计划与所应用的计划完全一致。
  • 若要详细了解如何使执行计划和安全性持久化,请参阅安全警告一节

应用 Terraform 执行计划

运行 terraform apply,将执行计划应用到云基础结构。

terraform apply main.tfplan

要点:

  • 上面的 terraform apply 命令假设之前运行了 terraform plan -out main.tfplan
  • 如果为 -out 参数指定了不同的文件名,请在对 terraform apply 的调用中使用该相同文件名。
  • 如果未使用 -out 参数,则无需任何参数即可调用 terraform apply

验证结果

  1. 获取资源组名称。

    echo "$(terraform output resource_group_name)"
    
  2. 浏览到 Azure 门户

  3. Azure 服务下,选择 资源组 并找到新资源组,以查看在此演示中创建的以下资源:

    • 解决 方案: 默认情况下,演示将此解决方案命名为 ContainerInsights。 门户将在括号中显示解决方案的工作区名称。
    • Kubernetes 服务: 默认情况下,演示将此服务命名 为 k8stest。 (托管 Kubernetes 群集也称为 AKS/Azure Kubernetes 服务.)
    • Log Analytics 工作区: 默认情况下,演示将此工作区命名为 TestLogAnalyticsWorkspaceName 前缀, 后跟随机数。
  4. 从 Terraform 状态中获取 Kubernetes 配置,并将其存储在 kubectl 可以读取的文件中。

    echo "$(terraform output kube_config)" > ./azurek8s
    
  5. 验证上一个命令未添加 ASCII EOT 字符。

    cat ./azurek8s
    

    要点:

    • 如果在开头和EOT末尾看到<< EOT,请从文件中删除这些字符。 否则,可能会收到以下错误消息: error: error loading config file "./azurek8s": yaml: line 2: mapping values are not allowed in this context
  6. 设置环境变量,使 kubectl 拾取正确的配置。

    export KUBECONFIG=./azurek8s
    
  7. 验证群集的运行状况。

    kubectl get nodes
    

    使用 kubectl 工具可以验证 Kubernetes 群集的运行状况

要点:

  • 创建 AKS 群集以后,已启用监视功能来捕获群集节点和 Pod 的运行状况指标。 Azure 门户提供这些运行状况指标。 有关容器运行状况监视的详细信息,请参阅监视 Azure Kubernetes 服务运行状况
  • 应用 Terraform 执行计划时,会输出多个键值。 例如,输出主机地址、AKS 群集用户名和 AKS 群集密码。
  • 若要查看所有输出值,请运行 terraform output
  • 若要查看特定的输出值,请运行 echo "$(terraform output <output_value_name>)"

清理资源

删除 AKS 资源

不再需要通过 Terraform 创建的资源时,请执行以下步骤:

  1. 运行 terraform plan 并指定 destroy 标志。

    terraform plan -destroy -out main.destroy.tfplan
    

    要点:

    • terraform plan 命令将创建一个执行计划,但不会执行它。 它会确定创建配置文件中指定的配置需要执行哪些操作。 此模式允许你在对实际资源进行任何更改之前验证执行计划是否符合预期。
    • 使用可选 -out 参数可以为计划指定输出文件。 使用 -out 参数可以确保所查看的计划与所应用的计划完全一致。
    • 若要详细了解如何使执行计划和安全性持久化,请参阅安全警告一节
  2. 运行 terraform apply 以应用执行计划。

    terraform apply main.destroy.tfplan
    

删除服务主体

注意

仅当未将其用于任何其他内容时,才删除在此演示中使用的服务主体。

  1. 运行 az ad sp list 以获取服务主体的对象 ID。

    az ad sp list --display-name "<display_name>" --query "[].{\"Object ID\":id}" --output table
    
    
  2. 运行 az ad sp delete 以删除服务主体。

    az ad sp delete --id <service_principal_object_id>
    

Azure 上的 Terraform 故障排除

排查在 Azure 上使用 Terraform 时遇到的常见问题

后续步骤