Поделиться через


Краткое руководство. Развертывание кластера Azure Nexus Kubernetes с помощью Bicep

  • Разверните кластер Azure Nexus Kubernetes с помощью Bicep.

Bicep — это предметно-ориентированный язык (DSL), который использует декларативный синтаксис для развертывания ресурсов Azure. Он обеспечивает краткий синтаксис, надежную безопасность типов и поддержку повторного использования кода. Bicep предлагает лучшие возможности для разработки решений Azure типа "инфраструктура как код".

Предпосылки

Если у вас нет аккаунта Azure, создайте бесплатную учетную запись перед началом.

  • Установите последнюю версию необходимых расширений Azure CLI.

  • Для этой статьи требуется версия 2.61.0 или более поздняя версия Azure CLI. Если вы используете Azure Cloud Shell, последняя версия уже установлена.

  • Если у вас несколько подписок Azure, выберите соответствующий идентификатор подписки, в котором должны выставляться счета за ресурсы с помощью az account команды.

  • Ознакомьтесь с таблицей SKU виртуальных машин в разделе справочных материалов для списка поддерживаемых SKU виртуальных машин.

  • Ознакомьтесь с поддерживаемыми версиями Kubernetes для списка поддерживаемых версий Kubernetes.

  • Создайте группу ресурсов с помощью команды az group create. Группа ресурсов Azure — это логическая группа, в которой развертываются и управляются ресурсы Azure. При создании группы ресурсов вам будет предложено указать расположение. Это расположение хранилища метаданных группы ресурсов и место, где ресурсы выполняются в Azure, если вы не указываете другой регион во время создания ресурса. В следующем примере создается группа ресурсов с именем myResourceGroup в расположении eastus.

    az group create --name myResourceGroup --location eastus
    

    Следующий выходной пример напоминает успешное создание группы ресурсов:

    {
      "id": "/subscriptions/<guid>/resourceGroups/myResourceGroup",
      "location": "eastus",
      "managedBy": null,
      "name": "myResourceGroup",
      "properties": {
        "provisioningState": "Succeeded"
      },
      "tags": null
    }
    
  • Для развертывания файла Bicep или шаблона ARM необходимы права на запись для развертываемых ресурсов и доступ ко всем операциям с ресурсным типом Microsoft.Resources/deployments. Например, для развертывания кластера требуются разрешения Microsoft.NetworkCloud/kubernetesclusters/write и Microsoft.Resources/deployments/* . Список ролей и разрешений см. в статье Встроенные роли Azure.

  • Вам нужен custom location идентификатор ресурса кластера Nexus оператора Azure.

  • Необходимо создать различные сети в соответствии с вашими требованиями к рабочей нагрузке и иметь соответствующие IP-адреса, доступные для рабочих нагрузок. Чтобы обеспечить плавную реализацию, рекомендуется обратиться к соответствующим группам поддержки за помощью.

  • В этом руководстве быстрого старта предполагается, что у вас есть базовое понимание концепций Kubernetes. Дополнительные сведения см. в статье Ключевые концепции Kubernetes для службы Azure Kubernetes (AKS).

Проверьте файл Bicep

Перед развертыванием шаблона Kubernetes ознакомьтесь с содержимым, чтобы понять его структуру.

// 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
      }
    }
  }
}

После проверки и сохранения файла шаблона с именем kubernetes-deploy.bicepперейдите к следующему разделу, чтобы развернуть шаблон.

Разверните BICEP-файл

  1. Создайте файл с именем kubernetes-deploy-parameters.json и добавьте необходимые параметры в формате JSON. В качестве отправной точки можно использовать следующий пример. Замените значения собственными.
{
  "$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. Разверните шаблон .
    az deployment group create \
      --resource-group myResourceGroup \
      --template-file kubernetes-deploy.bicep \
      --parameters @kubernetes-deploy-parameters.json

Если недостаточно емкости для развертывания запрошенных узлов кластера, появится сообщение об ошибке. Однако это сообщение не содержит никаких сведений о доступной емкости. Он указывает, что создание кластера не может продолжаться из-за нехватки емкости.

Замечание

Вычисление емкости учитывает весь кластер платформы, а не ограничивается отдельными стойками. Таким образом, если пул агентов создается в зоне (где стойка соответствует зоне) с недостаточной производительностью, но другая зона обладает достаточной производительностью, создание кластера продолжается, хотя в конечном итоге произойдет тайм-аут. Этот подход к проверке производительности имеет смысл только в том случае, если определенная зона не указана во время создания кластера или пула агентов.

Проверка развернутых ресурсов

После завершения развертывания можно просмотреть ресурсы с помощью интерфейса командной строки или портала Azure.

Чтобы просмотреть сведения о myNexusK8sCluster кластере myResourceGroup в группе ресурсов, выполните следующую команду Azure CLI:

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

Кроме того, чтобы получить список имен пулов агентов, связанных с myNexusK8sCluster кластером в myResourceGroup группе ресурсов, можно использовать следующую команду Azure CLI.

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

Подключение к кластеру

Теперь, когда кластер Nexus Kubernetes успешно создан и подключен к Azure Arc, вы можете легко подключиться к нему с помощью функции подключения кластера. Подключение к кластеру позволяет безопасно получать доступ к кластеру и управлять ими в любом месте, что упрощает интерактивную разработку, отладку и задачи администрирования кластера.

Дополнительные сведения о доступных параметрах см. в разделе "Подключение к кластеру Kubernetes" оператора Azure Nexus.

Замечание

При создании кластера Nexus Kubernetes, Nexus автоматически создает управляемую группу ресурсов, предназначенную для хранения ресурсов кластера; в этой группе создается ресурс кластера, подключенный к Arc.

Чтобы получить доступ к кластеру, необходимо настроить подключение к kubeconfig кластеру. После входа в Azure CLI с соответствующей сущностью Microsoft Entra вы можете получить необходимые kubeconfig сведения для взаимодействия с кластером из любого места, даже за пределами брандмауэра, который окружает его.

  1. Задать CLUSTER_NAMEи RESOURCE_GROUPSUBSCRIPTION_ID переменные.

    CLUSTER_NAME="myNexusK8sCluster"
    RESOURCE_GROUP="myResourceGroup"
    SUBSCRIPTION_ID=<set the correct subscription_id>
    
  2. Запросить управляемую группу ресурсов с использованием az и сохранить в 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. Следующая команда запускает прокси-сервер connectedk8s, который позволяет подключаться к серверу API Kubernetes для указанного кластера Nexus Kubernetes.

    az connectedk8s proxy -n $CLUSTER_NAME  -g $MANAGED_RESOURCE_GROUP &
    
  4. Используйте kubectl для отправки запросов в кластер:

    kubectl get pods -A
    

    Теперь вы увидите ответ из кластера, содержащий список всех узлов.

Замечание

Если появится сообщение об ошибке "Не удалось отправить токен доступа к клиентскому прокси-серверу: Не удалось подключиться к MSI", может потребоваться выполнить az login повторную проверку подлинности с помощью Azure.

Добавление пула агентов

Кластер, созданный на предыдущем шаге, имеет один пул узлов. Давайте добавим второй пул агентов с помощью файла Bicep. В следующем примере создается пул агентов с именем myNexusK8sCluster-nodepool-2:

  1. Изучите шаблон.

Прежде чем добавлять шаблон пула агентов, давайте рассмотрим содержимое, чтобы понять его структуру.

// 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'
    }
  }
}

После проверки и сохранения файла шаблона с именем kubernetes-add-agentpool.bicepперейдите к следующему разделу, чтобы развернуть шаблон.

  1. Создайте файл с именем kubernetes-nodepool-parameters.json и добавьте необходимые параметры в формате JSON. В качестве отправной точки можно использовать следующий пример. Замените значения собственными.
{
    "$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. Разверните шаблон .
    az deployment group create \
      --resource-group myResourceGroup \
      --template-file kubernetes-add-agentpool.bicep \
      --parameters @kubernetes-nodepool-parameters.json

Замечание

Во время первоначального создания кластера можно добавить несколько пулов агентов с помощью конфигураций начального пула агентов. Однако если вы хотите добавить пулы агентов после первоначального создания, можно использовать приведенную выше команду для создания дополнительных пулов агентов для кластера Nexus Kubernetes.

Следующий выходной пример напоминает успешное создание пула агентов.

$ 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

Очистите ресурсы

При отсутствии необходимости удалите группу ресурсов. Группа ресурсов и все ресурсы в группе ресурсов удаляются.

Используйте команду az group delete , чтобы удалить группу ресурсов, кластер Kubernetes и все связанные ресурсы, кроме сетевых ресурсов Operator Nexus.

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

Дальнейшие шаги

Теперь вы можете развернуть CNFS напрямую через подключение к кластеру или через Диспетчер служб операторов Azure.