Condividi tramite


Guida introduttiva: Distribuire un cluster Kubernetes Di Azure Nexus con Bicep

  • Distribuire un cluster Kubernetes di Azure Nexus usando Bicep.

Bicep è un linguaggio specifico di dominio (DSL) che usa la sintassi dichiarativa per distribuire le risorse di Azure. Fornisce sintassi concisa, sicurezza dei tipi affidabile e supporto per il riutilizzo del codice. Bicep offre la migliore esperienza di creazione per le soluzioni di infrastruttura come codice in Azure.

Prerequisiti

Se non si ha un account Azure, creare un account gratuito prima di iniziare.

  • Installare la versione più recente delle estensioni dell'interfaccia della riga di comando di Azure necessarie.

  • Questo articolo richiede la versione 2.61.0 o successiva dell'interfaccia della riga di comando di Azure. Se si usa Azure Cloud Shell, la versione più recente è già installata.

  • Se sono presenti più sottoscrizioni di Azure, selezionare l'ID sottoscrizione appropriato in cui devono essere fatturate le risorse usando il az account comando .

  • Per l'elenco degli SKU di macchine virtuali supportati, vedere la tabella SKU della macchina virtuale nella sezione di riferimento .

  • Per l'elenco delle versioni di Kubernetes supportate, vedere le versioni di Kubernetes supportate.

  • Creare un gruppo di risorse usando il comando az group create. Un gruppo di risorse di Azure è un gruppo logico in cui le risorse di Azure vengono distribuite e gestite. Quando si crea un gruppo di risorse, viene richiesto di specificare una posizione. Questa posizione è la posizione di archiviazione dei metadati del gruppo di risorse e dove le risorse vengono eseguite in Azure se non si specifica un'altra regione durante la creazione della risorsa. L'esempio seguente crea un gruppo di risorse denominato myResourceGroup nella località stati uniti orientali.

    az group create --name myResourceGroup --location eastus
    

    L'esempio di output seguente è simile alla corretta creazione del gruppo di risorse:

    {
      "id": "/subscriptions/<guid>/resourceGroups/myResourceGroup",
      "location": "eastus",
      "managedBy": null,
      "name": "myResourceGroup",
      "properties": {
        "provisioningState": "Succeeded"
      },
      "tags": null
    }
    
  • Per distribuire un file Bicep o un modello di ARM, è necessario l'accesso in scrittura alle risorse distribuite e l'accesso per tutte le operazioni sul tipo di risorsa Microsoft.Resources/deployments. Ad esempio, per distribuire un cluster, sono necessarie autorizzazioni Microsoft.NetworkCloud/kubernetesclusters/write e Microsoft.Resources/deployments/* . Per un elenco dei ruoli e delle autorizzazioni, vedere Ruoli predefiniti di Azure.

  • È necessario l'ID risorsa del cluster Nexus dell'operatore custom location di Azure.

  • È necessario creare diverse reti in base ai requisiti specifici del carico di lavoro ed è essenziale avere gli indirizzi IP appropriati disponibili per i carichi di lavoro. Per garantire un'implementazione uniforme, è consigliabile consultare i team di supporto pertinenti per assistenza.

  • Questa guida introduttiva presuppone una comprensione di base dei concetti relativi a Kubernetes. Per altre informazioni, vedere Concetti di base relativi a Kubernetes per il servizio Azure Kubernetes.

Esaminare il file Bicep

Prima di distribuire il modello Kubernetes, esaminare il contenuto per comprenderne la struttura.

// Azure parameters

@description('The name of Nexus Kubernetes cluster')
param kubernetesClusterName string

@description('The Azure region where the cluster is to be deployed')
param location string = resourceGroup().location

@description('The custom location of the Nexus instance')
param extendedLocation string

@description('The metadata tags to be associated with the cluster resource')
param tags object = {}

@description('The username for the administrative account on the cluster')
param adminUsername string = 'azureuser'

@description('The object IDs of Azure Active Directory (AAD) groups that will have administrative access to the cluster')
param adminGroupObjectIds array = []

// Networking Parameters

@description('The Azure Resource Manager (ARM) id of the network to be used as the Container Networking Interface (CNI) network')
param cniNetworkId string

@description('The ARM id of the network to be used for cloud services network')
param cloudServicesNetworkId string

@description('The CIDR blocks used for Nexus Kubernetes PODs in the cluster')
param podCidrs array = ['10.244.0.0/16']

@description('The CIDR blocks used for k8s service in the cluster')
param serviceCidrs array = ['10.96.0.0/16']

@description('The IP address of the DNS service in the cluster')
param dnsServiceIp string = '10.96.0.10'

@description('The Layer 2 networks associated with the initial agent pool')
param agentPoolL2Networks array = []
// {
//   networkId: 'string'
//   pluginType: 'SRIOV|DPDK|OSDevice|MACVLAN'
// }

@description('The Layer 3 networks associated with the initial agent pool')
param agentPoolL3Networks array = []
// {
//   ipamEnabled: 'True/False'
//   networkId: 'string'
//   pluginType: 'SRIOV|DPDK|OSDevice|MACVLAN|IPVLAN'
// }

@description('The trunked networks associated with the initial agent pool')
param agentPoolTrunkedNetworks array = []
// {
//   networkId: 'string'
//   pluginType: 'SRIOV|DPDK|OSDevice|MACVLAN'
// }

@description('The Layer 2 networks associated with the cluster')
param l2Networks array = []
// {
//   networkId: 'string'
//   pluginType: 'SRIOV|DPDK|OSDevice|MACVLAN'
// }

@description('The Layer 3 networks associated with the cluster')
param l3Networks array = []
// {
//   ipamEnabled: 'True/False'
//   networkId: 'string'
//   pluginType: 'SRIOV|DPDK|OSDevice|MACVLAN|IPVLAN'
// }

@description('The trunked networks associated with the cluster')
param trunkedNetworks array = []
// {
//   networkId: 'string'
//   pluginType: 'SRIOV|DPDK|OSDevice|MACVLAN'
// }

@description('The LoadBalancer IP address pools associated with the cluster')
param ipAddressPools array = []
// {
//   addresses: [
//     'string'
//   ]
//   autoAssign: 'True/False'
//   name: 'string'
//   onlyUseHostIps: 'True/False'
// }

// Cluster Configuration Parameters

@description('The version of Kubernetes to be used in the Nexus Kubernetes cluster')
param kubernetesVersion string = 'v1.27.1'

@description('The number of control plane nodes to be deployed in the cluster')
param controlPlaneCount int = 1

@description('The zones/racks used for placement of the control plane nodes')
param controlPlaneZones array = []
// "string" Example: ["1", "2", "3"]

@description('The zones/racks used for placement of the agent pool nodes')
param agentPoolZones array = []
// "string" Example: ["1", "2", "3"]

@description('The size of the control plane nodes')
param controlPlaneVmSkuName string = 'NC_G6_28_v1'

@description('The number of worker nodes to be deployed in the initial agent pool')
param systemPoolNodeCount int = 1

@description('The size of the worker nodes')
param workerVmSkuName string = 'NC_P10_56_v1'

@description('The configurations for the initial agent pool')
param initialPoolAgentOptions object = {}
// {
//   "hugepagesCount": integer,
//   "hugepagesSize": "2M/1G"
// }

@description('The cluster wide SSH public key that will be associated with the given user for secure remote login')
param sshPublicKeys array = []
// {
//   keyData: "ssh-rsa AAAAA...."
// },
// {
//   keyData: "ssh-rsa AAAAA...."
// }

@description('The control plane SSH public key that will be associated with the given user for secure remote login')
param controlPlaneSshKeys array = []
// {
//   keyData: "ssh-rsa AAAAA...."
// },
// {
//   keyData: "ssh-rsa AAAAA...."
// }

@description('The agent pool SSH public key that will be associated with the given user for secure remote login')
param agentPoolSshKeys array = []
// {
//   keyData: "ssh-rsa AAAAA...."
// },
// {
//   keyData: "ssh-rsa AAAAA...."
// }

@description('The labels to assign to the nodes in the cluster for identification and organization')
param labels array = []
// {
//   key: 'string'
//   value: 'string'
// }
@description('The taints to apply to the nodes in the cluster to restrict which pods can be scheduled on them')
param taints array = []
// {
//   key: 'string'
//   value: 'string:NoSchedule|PreferNoSchedule|NoExecute'
// }
@description('The association of IP address pools to the communities and peers, allowing for announcement of IPs.')
param bgpAdvertisements array = []

@description('"The list of additional BgpPeer entities that the Kubernetes cluster will peer with. All peering must be explicitly defined.')
param bgpPeers array = []

@description('The indicator to specify if the load balancer peers with the network fabric.')
param fabricPeeringEnabled string = 'False'


resource kubernetescluster 'Microsoft.NetworkCloud/kubernetesClusters@2025-02-01' = {
  name: kubernetesClusterName
  location: location
  tags: tags
  extendedLocation: {
    name: extendedLocation
    type: 'CustomLocation'
  }
  properties: {
    kubernetesVersion: kubernetesVersion
    managedResourceGroupConfiguration: {
      name: '${uniqueString(resourceGroup().name)}-${kubernetesClusterName}'
      location: location
    }
    aadConfiguration: {
      adminGroupObjectIds: adminGroupObjectIds
    }
    administratorConfiguration: {
      adminUsername: adminUsername
      sshPublicKeys: empty(sshPublicKeys) ? [] : sshPublicKeys
    }
    initialAgentPoolConfigurations: [
      {
        name: '${kubernetesClusterName}-nodepool-1'
        administratorConfiguration: {
          adminUsername: adminUsername
          sshPublicKeys: empty(agentPoolSshKeys) ? [] : agentPoolSshKeys
        }
        count: systemPoolNodeCount
        vmSkuName: workerVmSkuName
        mode: 'System'
        labels: empty(labels) ? null : labels
        taints: empty(taints) ? null : taints
        agentOptions: empty(initialPoolAgentOptions) ? null : initialPoolAgentOptions
        attachedNetworkConfiguration: {
          l2Networks: empty(agentPoolL2Networks) ? null : agentPoolL2Networks
          l3Networks: empty(agentPoolL3Networks) ? null : agentPoolL3Networks
          trunkedNetworks: empty(agentPoolTrunkedNetworks) ? null : agentPoolTrunkedNetworks
        }
        availabilityZones: empty(agentPoolZones) ? null : agentPoolZones
        upgradeSettings: {
          maxSurge: '1'
        }
      }
    ]
    controlPlaneNodeConfiguration: {
      administratorConfiguration: {
        adminUsername: adminUsername
        sshPublicKeys: empty(controlPlaneSshKeys) ? [] : controlPlaneSshKeys
      }
      count: controlPlaneCount
      vmSkuName: controlPlaneVmSkuName
      availabilityZones: empty(controlPlaneZones) ? null : controlPlaneZones
    }
    networkConfiguration: {
      cniNetworkId: cniNetworkId
      cloudServicesNetworkId: cloudServicesNetworkId
      dnsServiceIp: dnsServiceIp
      podCidrs: podCidrs
      serviceCidrs: serviceCidrs
      attachedNetworkConfiguration: {
        l2Networks: empty(l2Networks) ? null : l2Networks
        l3Networks: empty(l3Networks) ? null : l3Networks
        trunkedNetworks: empty(trunkedNetworks) ? null : trunkedNetworks
      }
      bgpServiceLoadBalancerConfiguration: {
        bgpAdvertisements: empty(bgpAdvertisements) ? null : bgpAdvertisements
        bgpPeers: empty(bgpPeers) ? null : bgpPeers
        fabricPeeringEnabled: fabricPeeringEnabled
        ipAddressPools: empty(ipAddressPools) ? null : ipAddressPools
      }
    }
  }
}

Dopo aver esaminato e salvato il file modello denominato kubernetes-deploy.bicep, passare alla sezione successiva per distribuire il modello.

Implementazione del file Bicep

  1. Creare un file denominato kubernetes-deploy-parameters.json e aggiungere i parametri obbligatori in formato JSON. È possibile usare l'esempio seguente come punto di partenza. Sostituire i valori con i propri.
{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "kubernetesClusterName":{
      "value": "myNexusK8sCluster"
    },
    "adminGroupObjectIds": {
      "value": [
        "00000000-0000-0000-0000-000000000000"
      ]
    },
    "cniNetworkId": {
      "value": "/subscriptions/<subscription_id>/resourceGroups/<resource_group>/providers/Microsoft.NetworkCloud/l3Networks/<l3Network-name>"
    },
    "cloudServicesNetworkId": {
      "value": "/subscriptions/<subscription_id>/resourceGroups/<resource_group>/providers/Microsoft.NetworkCloud/cloudServicesNetworks/<csn-name>"
    },
    "extendedLocation": {
      "value": "/subscriptions/<subscription_id>/resourceGroups/<managed_resource_group>/providers/microsoft.extendedlocation/customlocations/<custom-location-name>"
    },
    "location": {
      "value": "eastus"
    },
    "sshPublicKeys": {
      "value": [
        {
          "keyData": "ssh-rsa AAAAA...."
        },
        {
          "keyData": "ssh-rsa BBBBB...."
        }
      ]
    }
  }
}
  1. Distribuire il modello.
    az deployment group create \
      --resource-group myResourceGroup \
      --template-file kubernetes-deploy.bicep \
      --parameters @kubernetes-deploy-parameters.json

Se non è disponibile una capacità sufficiente per distribuire i nodi del cluster richiesti, viene visualizzato un messaggio di errore. Tuttavia, questo messaggio non fornisce dettagli sulla capacità disponibile. Indica che la creazione del cluster non può continuare a causa di capacità insufficiente.

Annotazioni

Il calcolo della capacità prende in considerazione l'intero cluster della piattaforma, anziché essere limitato ai singoli rack. Pertanto, se un pool di agenti viene creato in una zona (in cui un rack è uguale a una zona) con capacità insufficiente, ma un'altra zona ha una capacità sufficiente, la creazione del cluster continua ma alla fine si verifica un timeout. Questo approccio al controllo della capacità ha senso solo se non viene specificata una zona specifica durante la creazione del cluster o del pool di agenti.

Esaminare le risorse distribuite

Al termine della distribuzione, è possibile visualizzare le risorse usando l'interfaccia della riga di comando o il portale di Azure.

Per visualizzare i dettagli del myNexusK8sCluster cluster nel myResourceGroup gruppo di risorse, eseguire il comando seguente della CLI di Azure:

az networkcloud kubernetescluster show \
  --name myNexusK8sCluster \
  --resource-group myResourceGroup

Per ottenere un elenco di nomi di pool di agenti associati al myNexusK8sCluster cluster nel myResourceGroup gruppo di risorse, è anche possibile usare il comando seguente dell'interfaccia della riga di comando di Azure.

az networkcloud kubernetescluster agentpool list \
  --kubernetes-cluster-name myNexusK8sCluster \
  --resource-group myResourceGroup \
  --output table

Connettersi al cluster

Ora che il cluster Nexus Kubernetes è stato creato e connesso ad Azure Arc, è possibile connettersi facilmente usando la funzionalità di connessione del cluster. La connessione cluster consente di accedere e gestire in modo sicuro il cluster da qualsiasi posizione, semplificando lo sviluppo interattivo, il debug e le attività di amministrazione del cluster.

Per informazioni più dettagliate sulle opzioni disponibili, vedere Connettersi a un cluster Nexus Kubernetes dell'operatore di Azure.

Annotazioni

Quando si crea un cluster Nexus Kubernetes, Nexus crea automaticamente un gruppo di risorse gestito dedicato all'archiviazione delle risorse del cluster, all'interno di questo gruppo, viene stabilita la risorsa cluster connessa Arc.

Per accedere al cluster, è necessario configurare il cluster connect kubeconfig. Dopo aver eseguito l'accesso all'interfaccia della riga di comando di Azure con l'entità Microsoft Entra pertinente, è possibile ottenere il kubeconfig necessario per comunicare con il cluster ovunque, anche all'esterno del firewall che lo circonda.

  1. Impostare le variabili CLUSTER_NAME, RESOURCE_GROUP e SUBSCRIPTION_ID.

    CLUSTER_NAME="myNexusK8sCluster"
    RESOURCE_GROUP="myResourceGroup"
    SUBSCRIPTION_ID=<set the correct subscription_id>
    
  2. Eseguire query sul gruppo di risorse gestite con az e archiviare in MANAGED_RESOURCE_GROUP

     az account set -s $SUBSCRIPTION_ID
     MANAGED_RESOURCE_GROUP=$(az networkcloud kubernetescluster show -n $CLUSTER_NAME -g $RESOURCE_GROUP --output tsv --query managedResourceGroupConfiguration.name)
    
  3. Il comando seguente avvia un proxy connectedk8s che consente di connettersi al server API Kubernetes per il cluster Nexus Kubernetes specificato.

    az connectedk8s proxy -n $CLUSTER_NAME  -g $MANAGED_RESOURCE_GROUP &
    
  4. Usare kubectl per inviare richieste al cluster:

    kubectl get pods -A
    

    Verrà visualizzata una risposta dal cluster contenente l'elenco di tutti i nodi.

Annotazioni

Se viene visualizzato il messaggio di errore "Failed to post access token to client proxyFailed to connect to MSI", potrebbe essere necessario eseguire un az login per eseguire di nuovo l'autenticazione con Azure.

Aggiungere un pool di agenti

Il cluster creato nel passaggio precedente ha un singolo pool di nodi. Aggiungiamo un secondo pool di agenti utilizzando il file Bicep. L'esempio seguente crea un pool di agenti denominato myNexusK8sCluster-nodepool-2:

  1. Esaminare il modello.

Prima di aggiungere il modello di pool di agenti, esaminare il contenuto per comprenderne la struttura.

// Azure Parameters
@description('The name of Nexus Kubernetes cluster')
param kubernetesClusterName string

@description('The Azure region where the cluster is to be deployed')
param location string = resourceGroup().location

@description('The custom location of the Nexus instance')
param extendedLocation string

@description('Tags to be associated with the resource')
param tags object = {}

@description('The username for the administrative account on the cluster')
param adminUsername string = 'azureuser'

@description('The agent pool SSH public key that will be associated with the given user for secure remote login')
param agentPoolSshKeys array = []
// {
//   keyData: "ssh-rsa AAAAA...."
// },
// {
//   keyData: "ssh-rsa AAAAA...."
// }

// Cluster Configuration Parameters
@description('Number of nodes in the agent pool')
param agentPoolNodeCount int = 1

@description('Agent pool name')
param agentPoolName string = 'nodepool-2'

@description('VM size of the agent nodes')
param agentVmSku string = 'NC_P10_56_v1'

@description('The zones/racks used for placement of the agent pool nodes')
param agentPoolZones array = []
// "string" Example: ["1", "2", "3"]

@description('Agent pool mode')
param agentPoolMode string = 'User'

@description('The configurations for the initial agent pool')
param agentOptions object = {}
// {
//   "hugepagesCount": integer,
//   "hugepagesSize": "2M/1G"
// }

@description('The labels to assign to the nodes in the cluster for identification and organization')
param labels array = []
// {
//   key: 'string'
//   value: 'string'
// }
@description('The taints to apply to the nodes in the cluster to restrict which pods can be scheduled on them')
param taints array = []
// {
//   key: 'string'
//   value: 'string:NoSchedule|PreferNoSchedule|NoExecute'
// }

// Networking Parameters
@description('The Layer 2 networks to connect to the agent pool')
param l2Networks array = []
// {
//   networkId: 'string'
//   pluginType: 'SRIOV|DPDK|OSDevice|MACVLAN|IPVLAN'
// }

@description('The Layer 3 networks to connect to the agent pool')
param l3Networks array = []
// {
//   ipamEnabled: 'True/False'
//   networkId: 'string'
//   pluginType: 'SRIOV|DPDK|OSDevice|MACVLAN|IPVLAN'
// }

@description('The trunked networks to connect to the agent pool')
param trunkedNetworks array = []
// {
//   networkId: 'string'
//   pluginType: 'SRIOV|DPDK|OSDevice|MACVLAN|IPVLAN'
// }

resource agentPools 'Microsoft.NetworkCloud/kubernetesClusters/agentPools@2025-02-01' = {
  name: '${kubernetesClusterName}/${kubernetesClusterName}-${agentPoolName}'
  location: location
  tags: tags
  extendedLocation: {
    name: extendedLocation
    type: 'CustomLocation'
  }
  properties: {
    administratorConfiguration: {
      adminUsername: adminUsername
      sshPublicKeys: empty(agentPoolSshKeys) ? null : agentPoolSshKeys
    }
    attachedNetworkConfiguration: {
      l2Networks: empty(l2Networks) ? null : l2Networks
      l3Networks: empty(l3Networks) ? null : l3Networks
      trunkedNetworks: empty(trunkedNetworks) ? null : trunkedNetworks
    }
    count: agentPoolNodeCount
    mode: agentPoolMode
    vmSkuName: agentVmSku
    labels: empty(labels) ? null : labels
    taints: empty(taints) ? null : taints
    agentOptions: empty(agentOptions) ? null : agentOptions
    availabilityZones: empty(agentPoolZones) ? null : agentPoolZones
    upgradeSettings: {
      maxSurge: '1'
    }
  }
}

Dopo aver esaminato e salvato il file modello denominato kubernetes-add-agentpool.bicep, passare alla sezione successiva per distribuire il modello.

  1. Creare un file denominato kubernetes-nodepool-parameters.json e aggiungere i parametri obbligatori in formato JSON. È possibile usare l'esempio seguente come punto di partenza. Sostituire i valori con i propri.
{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
      "kubernetesClusterName":{
        "value": "myNexusK8sCluster"
      },
      "extendedLocation": {
        "value": "/subscriptions/<subscription_id>/resourceGroups/<resource_group>/providers/microsoft.extendedlocation/customlocations/<custom-location-name>"
      }
    }
  }
  1. Distribuire il modello.
    az deployment group create \
      --resource-group myResourceGroup \
      --template-file kubernetes-add-agentpool.bicep \
      --parameters @kubernetes-nodepool-parameters.json

Annotazioni

È possibile aggiungere più pool di agenti durante la creazione iniziale del cluster stesso usando le configurazioni iniziali del pool di agenti. Tuttavia, se si vogliono aggiungere pool di agenti dopo la creazione iniziale, è possibile usare il comando precedente per creare pool di agenti aggiuntivi per il cluster Nexus Kubernetes.

L'esempio di output seguente è simile alla riuscita creazione del pool di agenti.

$ az networkcloud kubernetescluster agentpool list --kubernetes-cluster-name myNexusK8sCluster --resource-group myResourceGroup --output table
This command is experimental and under development. Reference and support levels: https://aka.ms/CLI_refstatus
Count    Location    Mode    Name                          ProvisioningState    ResourceGroup    VmSkuName
-------  ----------  ------  ----------------------------  -------------------  ---------------  -----------
1        eastus      System  myNexusK8sCluster-nodepool-1  Succeeded            myResourceGroup  NC_P10_56_v1
1        eastus      User    myNexusK8sCluster-nodepool-2  Succeeded            myResourceGroup  NC_P10_56_v1

Pulire le risorse

Quando non è più necessario, eliminare il gruppo di risorse. Il gruppo di risorse e tutte le risorse nel gruppo di risorse vengono eliminati.

Usare il comando az group delete per rimuovere il gruppo di risorse, il cluster Kubernetes e tutte le risorse correlate, ad eccezione delle risorse di rete Operator Nexus.

az group delete --name myResourceGroup --yes --no-wait

Passaggi successivi

È ora possibile distribuire i CNF direttamente tramite Cluster Connect o tramite Azure Operator Service Manager.