Maak een Application Gateway controller voor een Azure Kubernetes Service

Azure Kubernetes Service (AKS) beheert uw gehoste Kubernetes-omgeving. Met AKS kunt u snel en eenvoudig in containers geplaatste toepassingen implementeren en beheren, zonder dat u kennis hoeft te hebben van het indelen van containers. AKS elimineert ook de last van het offline halen van toepassingen voor operationele en onderhoudstaken. Met AKS kunnen deze taken, waaronder het inrichten, upgraden en schalen van resources, op aanvraag worden uitgevoerd.

Een toegangscontroller biedt verschillende functies voor Kubernetes-services. Deze functies omvatten omgekeerde proxy, configureerbare verkeersroutering en TLS-beëindiging. Kubernetes-ingress-resources worden gebruikt voor het configureren van de regels voor ingressen voor afzonderlijke Kubernetes-services. Met behulp van een controller voor verkeer en regels voor inverkeer kan één IP-adres verkeer doorverzenden naar meerdere services in een Kubernetes-cluster. Al deze functionaliteit wordt geleverd door Azure Application Gateway,waardoor het een ideale controller voor ingress is voor Kubernetes in Azure.

In dit artikel leert u het volgende:

  • Een Kubernetes-cluster maken met behulp van AKS Application Gateway als controller voor ingress
  • Een Kubernetes-cluster definiëren
  • Maak een Application Gateway-resource
  • Een Kubernetes-cluster maken
  • De beschikbaarheid van een Kubernetes-cluster testen

1. Uw omgeving configureren

  • Azure-abonnement: Als u nog geen abonnement op Azure hebt, maak dan een gratis account aan voordat u begint.
  • Azure-service-principal:als u geen service-principal hebt, maakt u een service-principal. Noteer de waarden voor appId de , , en displayNamepasswordtenant .

  • Object-id van de service-principal:voer de volgende opdracht uit om de object-id van de service-principal op te halen:

2. Azure Storage configureren voor het opslaan van de Terraform-status

In Terraform wordt de status lokaal bijgehouden via het bestand terraform.tfstate. Dit patroon werkt goed in een omgeving met één persoon. In een praktischere omgeving met meerdere personen moet u echter met behulp van Azure Storage de status bijhouden op de server. In deze sectie leert u de benodigde opslagaccountgegevens op te halen en een opslagcontainer te maken. De Terraform-statusgegevens worden vervolgens opgeslagen in die container.

  1. Blader naar Azure Portal.

  2. Selecteer onder Azure-servicesStorage accounts. (Als de Storage accounts niet zichtbaar is op de hoofdpagina, selecteert u Meer services om de optie te vinden.)

  3. Selecteer op Storage pagina Accounts de naam van het opslagaccount waarin Terraform de status moet opslaan. U kunt bijvoorbeeld het opslagaccount gebruiken dat u hebt gemaakt toen u Cloud Shell de eerste keer opende. De opslagaccountnaam die door Cloud Shell wordt gemaakt, begint gewoonlijk met cs, gevolgd door een willekeurige tekenreeks met cijfers en letters.

  4. Noteer de naam van het geselecteerde opslagaccount.

  5. Selecteer op de opslagaccountpagina de optie Toegangssleutels.

    Opslagaccountmenu

  6. Noteer desleutelwaardekey1. (Als u het pictogram rechts van de sleutel selecteert, wordt de waarde gekopieerd naar het klembord.)

    Toegangssleutels voor opslagaccount

  7. Maak een container in uw Azure-opslagaccount. Vervang de tijdelijke aanduidingen door de juiste waarden voor uw Azure-opslagaccount.

    az storage container create -n tfstate --account-name <storage_account_name> --account-key <storage_account_key>
    

3. De Terraform-code implementeren

  1. Maak een map waarin u de Terraform-voorbeeldcode wilt testen en deze de huidige map wilt maken.

  2. Maak een bestand met de main.tf naam en voeg de volgende code in:

    terraform {
    
      required_version = ">=0.12"
    
      required_providers {
        azurerm = {
          source = "hashicorp/azurerm"
          version = "~>2.0"
        }
      }
      backend "azurerm" {
        resource_group_name = var.resource_group_name
        storage_account_name = var.storage_account_name
        container_name = "tfstate"
        key = "codelab.microsoft.tfstate"
      }
      }
    
      provider "azurerm" {
      features {}
    }
    
  3. Maak een bestand met de variables.tf naam dat de projectvariabelen bevat en voeg de volgende code in:

    variable "resource_group_name" {
        description = "Name of the resource group."
    }
    
    variable "location" {
        description = "Location of the cluster."
    }
    
    variable "aks_service_principal_app_id" {
        description = "Application ID/Client ID  of the service principal. Used by AKS to manage AKS related resources on Azure like vms, subnets."
    }
    
    variable "aks_service_principal_client_secret" {
        description = "Secret of the service principal. Used by AKS to manage Azure."
    }
    
    variable "aks_service_principal_object_id" {
        description = "Object ID of the service principal."
    }
    
    variable "virtual_network_name" {
        description = "Virtual network name"
        default     = "aksVirtualNetwork"
    }
    
    variable "virtual_network_address_prefix" {
        description = "VNET address prefix"
        default     = "15.0.0.0/8"
    }
    
    variable "aks_subnet_name" {
        description = "Subnet Name."
        default     = "kubesubnet"
    }
    
    variable "aks_subnet_address_prefix" {
        description = "Subnet address prefix."
        default     = "15.0.0.0/16"
    }
    
    variable "app_gateway_subnet_address_prefix" {
        description = "Subnet server IP address."
        default     = "15.1.0.0/16"
    }
    
    variable "app_gateway_name" {
        description = "Name of the Application Gateway"
        default = "ApplicationGateway1"
    }
    
    variable "app_gateway_sku" {
        description = "Name of the Application Gateway SKU"
        default = "Standard_v2"
    }
    
    variable "app_gateway_tier" {
        description = "Tier of the Application Gateway tier"
        default = "Standard_v2"
    }
    
    variable "aks_name" {
        description = "AKS cluster name"
        default     = "aks-cluster1"
    }
    variable "aks_dns_prefix" {
        description = "Optional DNS prefix to use with hosted Kubernetes API server FQDN."
        default     = "aks"
    }
    
    variable "aks_agent_os_disk_size" {
        description = "Disk size (in GB) to provision for each of the agent pool nodes. This value ranges from 0 to 1023. Specifying 0 applies the default disk size for that agentVMSize."
        default     = 40
    }
    
    variable "aks_agent_count" {
        description = "The number of agent nodes for the cluster."
        default     = 3
    }
    
    variable "aks_agent_vm_size" {
        description = "VM size"
        default     = "Standard_D3_v2"
    }
    
    variable "kubernetes_version" {
        description = "Kubernetes version"
        default     = "1.11.5"
    }
    
    variable "aks_service_cidr" {
        description = "CIDR notation IP range from which to assign service cluster IPs"
        default     = "10.0.0.0/16"
    }
    
    variable "aks_dns_service_ip" {
        description = "DNS server IP address"
        default     = "10.0.0.10"
    }
    
    variable "aks_docker_bridge_cidr" {
        description = "CIDR notation IP for Docker bridge."
        default     = "172.17.0.1/16"
    }
    
    variable "aks_enable_rbac" {
        description = "Enable RBAC on the AKS cluster. Defaults to false."
        default     = "false"
    }
    
    variable "vm_user_name" {
        description = "User name for the VM"
        default     = "vmuser1"
    }
    
    variable "public_ssh_key_path" {
        description = "Public key path for SSH."
        default     = "~/.ssh/id_rsa.pub"
    }
    
    variable "tags" {
        type = map(string)
    
        default = {
        source = "terraform"
        }
    }
    
    variable "storage_account_name" {
        description = "Name of storage account"
    }
    
  4. Maak een bestand met de resources.tf naam en voeg de volgende code in.

    # # Locals block for hardcoded names. 
    locals {
        backend_address_pool_name      = "${azurerm_virtual_network.test.name}-beap"
        frontend_port_name             = "${azurerm_virtual_network.test.name}-feport"
        frontend_ip_configuration_name = "${azurerm_virtual_network.test.name}-feip"
        http_setting_name              = "${azurerm_virtual_network.test.name}-be-htst"
        listener_name                  = "${azurerm_virtual_network.test.name}-httplstn"
        request_routing_rule_name      = "${azurerm_virtual_network.test.name}-rqrt"
        app_gateway_subnet_name = "appgwsubnet"
    }
    
    data "azurerm_resource_group" "rg" {
        name = var.resource_group_name
    }
    
    # User Assigned Identities 
    resource "azurerm_user_assigned_identity" "testIdentity" {
        resource_group_name = data.azurerm_resource_group.rg.name
        location            = data.azurerm_resource_group.rg.location
    
        name = "identity1"
    
        tags = var.tags
    }
    
    resource "azurerm_virtual_network" "test" {
        name                = var.virtual_network_name
        location            = data.azurerm_resource_group.rg.location
        resource_group_name = data.azurerm_resource_group.rg.name
        address_space       = [var.virtual_network_address_prefix]
    
        subnet {
        name           = var.aks_subnet_name
        address_prefix = var.aks_subnet_address_prefix
        }
    
        subnet {
        name           = "appgwsubnet"
        address_prefix = var.app_gateway_subnet_address_prefix
        }
    
        tags = var.tags
    }
    
    data "azurerm_subnet" "kubesubnet" {
        name                 = var.aks_subnet_name
        virtual_network_name = azurerm_virtual_network.test.name
        resource_group_name  = data.azurerm_resource_group.rg.name
        depends_on = [azurerm_virtual_network.test]
    }
    
    data "azurerm_subnet" "appgwsubnet" {
        name                 = "appgwsubnet"
        virtual_network_name = azurerm_virtual_network.test.name
        resource_group_name  = data.azurerm_resource_group.rg.name
        depends_on = [azurerm_virtual_network.test]
    }
    
    # Public Ip 
    resource "azurerm_public_ip" "test" {
        name                         = "publicIp1"
        location                     = data.azurerm_resource_group.rg.location
        resource_group_name          = data.azurerm_resource_group.rg.name
        allocation_method            = "Static"
        sku                          = "Standard"
    
        tags = var.tags
    }
    
    resource "azurerm_application_gateway" "network" {
        name                = var.app_gateway_name
        resource_group_name = data.azurerm_resource_group.rg.name
        location            = data.azurerm_resource_group.rg.location
    
        sku {
        name     = var.app_gateway_sku
        tier     = "Standard_v2"
        capacity = 2
        }
    
        gateway_ip_configuration {
        name      = "appGatewayIpConfig"
        subnet_id = data.azurerm_subnet.appgwsubnet.id
        }
    
        frontend_port {
        name = local.frontend_port_name
        port = 80
        }
    
        frontend_port {
        name = "httpsPort"
        port = 443
        }
    
        frontend_ip_configuration {
        name                 = local.frontend_ip_configuration_name
        public_ip_address_id = azurerm_public_ip.test.id
        }
    
        backend_address_pool {
        name = local.backend_address_pool_name
        }
    
        backend_http_settings {
        name                  = local.http_setting_name
        cookie_based_affinity = "Disabled"
        port                  = 80
        protocol              = "Http"
        request_timeout       = 1
        }
    
        http_listener {
        name                           = local.listener_name
        frontend_ip_configuration_name = local.frontend_ip_configuration_name
        frontend_port_name             = local.frontend_port_name
        protocol                       = "Http"
        }
    
        request_routing_rule {
        name                       = local.request_routing_rule_name
        rule_type                  = "Basic"
        http_listener_name         = local.listener_name
        backend_address_pool_name  = local.backend_address_pool_name
        backend_http_settings_name = local.http_setting_name
        }
    
        tags = var.tags
    
        depends_on = [azurerm_virtual_network.test, azurerm_public_ip.test]
    }
    
    resource "azurerm_role_assignment" "ra1" {
        scope                = data.azurerm_subnet.kubesubnet.id
        role_definition_name = "Network Contributor"
        principal_id         = var.aks_service_principal_object_id 
    
        depends_on = [azurerm_virtual_network.test]
    }
    
    resource "azurerm_role_assignment" "ra2" {
        scope                = azurerm_user_assigned_identity.testIdentity.id
        role_definition_name = "Managed Identity Operator"
        principal_id         = var.aks_service_principal_object_id
        depends_on           = [azurerm_user_assigned_identity.testIdentity]
    }
    
    resource "azurerm_role_assignment" "ra3" {
        scope                = azurerm_application_gateway.network.id
        role_definition_name = "Contributor"
        principal_id         = azurerm_user_assigned_identity.testIdentity.principal_id
        depends_on           = [azurerm_user_assigned_identity.testIdentity, azurerm_application_gateway.network]
    }
    
    resource "azurerm_role_assignment" "ra4" {
        scope                = data.azurerm_resource_group.rg.id
        role_definition_name = "Reader"
        principal_id         = azurerm_user_assigned_identity.testIdentity.principal_id
        depends_on           = [azurerm_user_assigned_identity.testIdentity, azurerm_application_gateway.network]
    }
    
    resource "azurerm_kubernetes_cluster" "k8s" {
        name       = var.aks_name
        location   = data.azurerm_resource_group.rg.location
        dns_prefix = var.aks_dns_prefix
    
        resource_group_name = data.azurerm_resource_group.rg.name
    
        linux_profile {
        admin_username = var.vm_user_name
    
        ssh_key {
            key_data = file(var.public_ssh_key_path)
        }
        }
    
        addon_profile {
        http_application_routing {
            enabled = false
        }
        }
    
        default_node_pool {
        name            = "agentpool"
        node_count      = var.aks_agent_count
        vm_size         = var.aks_agent_vm_size
        os_disk_size_gb = var.aks_agent_os_disk_size
        vnet_subnet_id  = data.azurerm_subnet.kubesubnet.id
        }
    
        service_principal {
        client_id     = var.aks_service_principal_app_id
        client_secret = var.aks_service_principal_client_secret
        }
    
        network_profile {
        network_plugin     = "azure"
        dns_service_ip     = var.aks_dns_service_ip
        docker_bridge_cidr = var.aks_docker_bridge_cidr
        service_cidr       = var.aks_service_cidr
        }
    
        role_based_access_control {
        enabled = var.aks_enable_rbac
        }
    
        depends_on = [azurerm_virtual_network.test, azurerm_application_gateway.network]
        tags       = var.tags
    }
    

    Belangrijkste punten:

    • Met de code in resources.tf het bestand worden de naam van het cluster, de locatie en de resource_group_name.
    • De dns_prefix waarde die deel uitmaakt van de Fully Qualified Domain Name (FQDN) die wordt gebruikt voor toegang tot het cluster, is ingesteld.
    • Met de record kunt u de instellingen configureren waarmee u zich via SSH kunt aanmelden bij linux_profile de werkknooppunten.
    • Met AKS betaalt u alleen voor de werkknooppunten.
    • De agent_pool_profile record configureert de details voor deze werkknooppunten.
    • De agent_pool_profile record omvat het aantal werkknooppunten dat moet worden maken en het type werkknooppunten.
    • Als u het cluster in de toekomst omhoog of omlaag wilt schalen, wijzigt u count de waarde in agent_pool_profile record record.
  5. Maak een bestand met de output.tf naam en voeg de volgende code in.

    output "client_key" {
        value = azurerm_kubernetes_cluster.k8s.kube_config.0.client_key
    }
    
    output "client_certificate" {
        value = azurerm_kubernetes_cluster.k8s.kube_config.0.client_certificate
    }
    
    output "cluster_ca_certificate" {
        value = azurerm_kubernetes_cluster.k8s.kube_config.0.cluster_ca_certificate
    }
    
    output "cluster_username" {
        value = azurerm_kubernetes_cluster.k8s.kube_config.0.username
    }
    
    output "cluster_password" {
        value = azurerm_kubernetes_cluster.k8s.kube_config.0.password
    }
    
    output "kube_config" {
        value = azurerm_kubernetes_cluster.k8s.kube_config_raw
        sensitive = true
    }
    
    output "host" {
        value = azurerm_kubernetes_cluster.k8s.kube_config.0.host
    }
    
    output "identity_resource_id" {
        value = azurerm_user_assigned_identity.testIdentity.id
    }
    
    output "identity_client_id" {
        value = azurerm_user_assigned_identity.testIdentity.client_id
    }
    

    Belangrijkste punten:

    • Met Terraform-uitvoer kunt u waarden definiëren die voor de gebruiker zijn gemarkeerd wanneer Terraform een plan past.
    • Deze waarden kunnen worden opgevraagd met behulp van de terraform output opdracht .
    • In deze sectie maakt u een uitvoerbestand waarmee via kubectl toegang wordt verkregen tot het cluster.
  6. Maak een bestand met de terraform.tfvars naam en voeg de volgende code in.

    resource_group_name = "<Name of the Resource Group already created>"
    
    location = "<Location of the Resource Group>"
        
    aks_service_principal_app_id = "<Service Principal AppId>"
        
    aks_service_principal_client_secret = "<Service Principal Client Secret>"
        
    aks_service_principal_object_id = "<Service Principal Object Id>"
    

    Belangrijkste punten:

    • Voer az account list-locations uit om de locatiewaarde van uw omgeving op te halen

4. Het Kubernetes-cluster testen

U kunt het gemaakte cluster controleren met de Kubernetes-hulpprogramma's.

  1. Voer az aks get-credentials uit om de Kubernetes-configuratie en toegangsreferenties op te halen uit Azure.

    az aks get-credentials --name <aks_cluster_name>  --resource-group <resource_group_name>
    
  2. Controleer de status van het cluster.

    kubectl get nodes
    

    Belangrijkste punten:

    • De details van uw werkknooppunten worden weergegeven met de status Gereed.

    Met het hulpprogramma kubectl kunt u de status van uw Kubernetes-cluster controleren

5. Azure AD Pod Identity installeren

Azure Active Directory Pod Identity biedt toegang op basis van een token tot Azure Resource Manager.

Azure AD Pod Identity voegt de volgende onderdelen toe aan uw Kubernetes-cluster:

Als RBAC is ingeschakeld, voer dande volgende opdracht uit om Azure AD Pod Identity te installeren in uw cluster:

kubectl create -f https://raw.githubusercontent.com/Azure/aad-pod-identity/master/deploy/infra/deployment-rbac.yaml

Als RBAC is uitgeschakeld,moet u de volgende opdracht uitvoeren om Azure AD Pod Identity te installeren in uw cluster:

kubectl create -f https://raw.githubusercontent.com/Azure/aad-pod-identity/master/deploy/infra/deployment.yaml

6. Helm installeren

De code in deze sectie maakt gebruik van Helm - Kubernetes Package Manager - om het pakket te installeren:

Voer de volgende Helm-opdrachten uit om de AGIC Helm-opslagplaats toe te voegen:

helm repo add application-gateway-kubernetes-ingress https://appgwingress.blob.core.windows.net/ingress-azure-helm-package/
helm repo update

7. Helm-grafiek voor ingress-controller installeren

  1. Download om helm-config.yaml AGIC te configureren:

    wget https://raw.githubusercontent.com/Azure/application-gateway-kubernetes-ingress/master/docs/examples/sample-helm-config.yaml -O helm-config.yaml
    
  2. Bewerk de helm-config.yaml en voer de juiste waarden in voor de appgwarmAuth secties en .

    code helm-config.yaml
    

    De waarden worden als volgt beschreven:

    • verbosityLevel: hiermee stelt u het verbosity-niveau van de AGIC-infrastructuur voor logboekregistratie in. Zie Logboekregistratieniveaus voor mogelijke waarden.
    • appgw.subscriptionId: De Azure-abonnements-id voor de App Gateway. Voorbeeld: a123b234-a3b4-557d-b2df-a0bc12de1234
    • appgw.resourceGroup: Naam van de Azure-resourcegroep waarin App Gateway is gemaakt.
    • appgw.name: Naam van de Application Gateway. Bijvoorbeeld: applicationgateway1.
    • appgw.shared: Deze Booleaanse vlag moet standaard worden ingesteld op false . Stel in true op trueals u een gedeelde App Gateway.
    • kubernetes.watchNamespace: Geef de naamruimte op die agic moet bekijken. De naamruimte kan één tekenreekswaarde of een door komma's gescheiden lijst met naamruimten zijn. Als u deze variabele weg laat, of als u deze in een lege of lege tekenreeks instelt, worden alle toegankelijke naamruimten gecomserveerd.
    • armAuth.type: Een waarde van of aadPodIdentityservicePrincipal .
    • armAuth.identityResourceID: Resource-id van de beheerde identiteit.
    • armAuth.identityClientId: De client-id van de identiteit.
    • armAuth.secretJSON: Alleen nodig wanneer het type Geheim van service-principal is gekozen (wanneer armAuth.type is ingesteld op servicePrincipal ).

    Belangrijkste punten:

    • De identityResourceID waarde wordt gemaakt in het terraform-script en kan worden gevonden door het volgende uit te voeren: echo "$(terraform output identity_resource_id)" .
    • De identityClientID waarde wordt gemaakt in het terraform-script en kan worden gevonden door het volgende uit te voeren: echo "$(terraform output identity_client_id)" .
    • De <resource-group> waarde is de resourcegroep van uw App Gateway.
    • De <identity-name> waarde is de naam van de gemaakte identiteit.
    • Alle identiteiten voor een bepaald abonnement kunnen worden weergegeven met: az identity list .
  3. Installeer het Application Gateway controllerpakket voor het ingress:

    helm install -f helm-config.yaml application-gateway-kubernetes-ingress/ingress-azure --generate-name
    

8. Een voorbeeld-app installeren

Zodra u de App Gateway, AKS en AGIC hebt geïnstalleerd, installeert u een voorbeeld-app.

  1. Gebruik de curl-opdracht om het YAML-bestand te downloaden:

    curl https://raw.githubusercontent.com/Azure/application-gateway-kubernetes-ingress/master/docs/examples/aspnetapp.yaml -o aspnetapp.yaml
    
  2. Pas het YAML-bestand toe:

    kubectl apply -f aspnetapp.yaml
    

9. Resources ops schonen

Wanneer u de resources die via Terraform zijn gemaakt niet meer nodig hebt, moet u de volgende stappen volgen:

  1. Voer terraform plan uit en geef de vlag op.

    terraform plan -destroy -out main.destroy.tfplan
    

    Belangrijkste punten:

    • Met terraform plan de opdracht wordt een uitvoeringsplan gemaakt, maar niet uitgevoerd. In plaats daarvan wordt bepaald welke acties nodig zijn om de configuratie te maken die is opgegeven in uw configuratiebestanden. Met dit patroon kunt u controleren of het uitvoeringsplan overeenkomt met uw verwachtingen voordat u wijzigingen aan werkelijke resources aantreft.
    • Met de -out optionele parameter kunt u een uitvoerbestand voor het plan opgeven. Door de parameter te gebruiken, zorgt u ervoor dat het plan dat -out u hebt gecontroleerd, precies is wat er wordt toegepast.
    • Zie de sectie beveiligingswaarschuwing voor meer informatie over persistente uitvoeringsplannen en beveiliging.
  2. Voer terraform apply uit om het uitvoeringsplan toe te passen.

    terraform apply main.destroy.tfplan
    

Problemen met Terraform in Azure oplossen

Veelvoorkomende problemen bij het gebruik van Terraform in Azure oplossen

Volgende stappen