你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
- 使用 Bicep 部署 Azure Nexus Kubernetes 群集。
Bicep 是一种特定于域的语言 (DSL),使用声明性语法来部署 Azure 资源。 它提供简明的语法、可靠的类型安全性以及对代码重用的支持。 Bicep 会针对你的 Azure 基础结构即代码解决方案提供最佳创作体验。
先决条件
如果没有 Azure 帐户,请在开始前创建一个免费帐户。
在 Azure Cloud Shell 中使用 Bash 环境。 有关详细信息,请参阅 Azure Cloud Shell 入门。
如需在本地运行 CLI 参考命令,请安装 Azure CLI。 如果在 Windows 或 macOS 上运行,请考虑在 Docker 容器中运行 Azure CLI。 有关详细信息,请参阅如何在 Docker 容器中运行 Azure CLI。
如果使用的是本地安装,请使用 az login 命令登录到 Azure CLI。 若要完成身份验证过程,请遵循终端中显示的步骤。 有关其他登录选项,请参阅 使用 Azure CLI 向 Azure 进行身份验证。
出现提示时,请在首次使用时安装 Azure CLI 扩展。 有关扩展的详细信息,请参阅 使用和管理 Azure CLI 中的扩展。
运行az version命令,以查看已安装的版本和依赖库。 若要升级到最新版本,请运行az upgrade。
安装必需的 Azure CLI 扩展的最新版本。
本文需要 2.61.0 或更高版本的 Azure CLI。 如果使用 Azure Cloud Shell,则最新版本已安装。
如果你有多个 Azure 订阅,请使用
az account
命令选择应在其中计收资源费用的相应订阅 ID。有关支持的 VM SKU 列表,请参阅参考部分中的 VM SKU 表。
有关受支持的 Kubernetes 版本的列表,请参阅受支持的 Kubernetes 版本。
使用
az group create
命令创建资源组。 Azure 资源组是用于部署和管理 Azure 资源的逻辑组。 创建资源组时,系统会提示你指定一个位置。 此位置是资源组元数据的存储位置,也是资源在 Azure 中运行的位置(如果你在创建资源期间未指定其他区域)。 以下示例在“eastus”位置创建名为“myResourceGroup”的资源组。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 内置角色。
需要 Azure Operator Nexus 群集的
custom ___location
资源 ID。需要根据特定的工作负载要求创建各种网络,并且必须具有适用于工作负载的相应 IP 地址。 为确保顺利实施,建议咨询相关支持团队以获取帮助。
本快速入门假设读者基本了解 Kubernetes 的概念。 有关详细信息,请参阅 Azure Kubernetes 服务 (AKS) 的 Kubernetes 核心概念。
查阅 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 文件
- 创建一个名为
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...."
}
]
}
}
}
- 部署模板。
az deployment group create \
--resource-group myResourceGroup \
--template-file kubernetes-deploy.bicep \
--parameters @kubernetes-deploy-parameters.json
如果没有足够的容量来部署请求的群集节点,则会显示一条错误消息。 但是,此消息不提供任何有关可用容量的详细信息。 它会指出群集创建由于容量不足而无法继续。
注释
容量计算考虑到了整个平台群集,而不是仅限于单个机架。 因此,如果在容量不足的某个区域(这里,一个机架等于一个区域)中创建代理池,但另一个区域具有足够的容量,则群集创建将继续,但最终会超时。仅当在创建群集或代理池期间未指定特定区域时,这种容量检查方法才有意义。
查看已部署的资源
部署完成后,可以使用 CLI 或 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 后,可以使用群集连接功能轻松连接到它。 通过群集连接,可以从任意位置安全地访问和管理群集,方便执行交互式开发、调试和群集管理任务。
有关可用选项的更多详细信息,请参阅连接到 Azure Operator Nexus Kubernetes 群集。
注释
创建 Nexus Kubernetes 群集时,Nexus 会自动创建专用于存储群集资源的托管资源组,在此组中,会建立 Arc 连接的群集资源。
要访问群集,需要设置群集连接 kubeconfig
。 使用相关 Microsoft Entra 实体登录到 Azure CLI 后,可以获取从任意位置(甚至在群集周围的防火墙以外)与群集通信所需的 kubeconfig
。
设置
CLUSTER_NAME
、RESOURCE_GROUP
和SUBSCRIPTION_ID
变量。CLUSTER_NAME="myNexusK8sCluster" RESOURCE_GROUP="myResourceGroup" SUBSCRIPTION_ID=<set the correct subscription_id>
查询具有
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)
以下命令会启动 connectedk8s 代理,你可以通过该代理连接到指定 Nexus Kubernetes 群集的 Kubernetes API 服务器。
az connectedk8s proxy -n $CLUSTER_NAME -g $MANAGED_RESOURCE_GROUP &
使用
kubectl
将请求发送到群集:kubectl get pods -A
现在应会看到来自群集的响应,其中包含所有节点的列表。
注释
如果看到错误消息“无法将访问令牌发布到客户端代理,无法连接到 MSI”,则可能需要执行 az login
以使用 Azure 重新进行身份验证。
添加代理池
在上一步骤中创建的群集包含单个节点池。 让我们使用 Bicep 文件添加第二个代理池。 以下示例创建一个名为 myNexusK8sCluster-nodepool-2
的代理池:
- 查看模板。
在添加代理池模板之前,让我们查看内容以了解其结构。
// 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
的模板文件后,继续按下一节所述部署模板。
- 创建一个名为
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>"
}
}
}
- 部署模板。
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
后续步骤
现在即可直接通过群集连接或通过 Azure Operator Service Manager 来部署 CNF。