教程:使用 Go SDK 在 Azure 公共 MEC 中部署资源

本教程介绍如何使用 Go SDK 在 Azure 公共多接入边缘计算 (MEC) 中部署资源。 本教程提供了用 Go 编写的代码片段,用于在 Azure 公共 MEC 解决方案中部署虚拟机和公共 IP 资源。 你可以使用相同的模型和模板来部署 Azure 公共 MEC 支持的其他资源和服务。 本文并不是针对 Go 的教程,仅重点介绍在 Azure 公共 MEC 中部署资源所需的 API 调用。

有关 Go 的详细信息,请参阅 Azure for Go 开发人员。 有关 Go 示例,请参阅 Azure Go SDK 示例

在本教程中,你将了解如何执行以下操作:

  • 创建虚拟机
  • 创建公共 IP 地址
  • 部署虚拟网络和公共 IP 地址

先决条件

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

  • 将允许列表中的订阅添加到 Azure 帐户,这使你能够在 Azure 公共 MEC 中部署资源。 如果没有可用的允许订阅,请联系 Azure 公共 MEC 产品团队

安装 Go

你可以下载并安装最新版本的 Go。 它将替换计算机上现有的 Go。 如果要在同一计算机上安装多个 Go 版本,请参阅管理 Go 安装

身份验证

在使用任何 Azure 服务之前,都需要进行身份验证。 你可以使用 Azure CLI 登录或设置身份验证环境变量。

使用 Azure CLI 登录

可以在命令行中使用 az login 通过默认浏览器登录到 Azure。 可以在使用 Azure CLI 登录中找到详细说明。

设置环境变量。

需要以下值才能向 Azure 进行身份验证:

  • 订阅 ID
  • 客户端 ID
  • 客户端机密
  • 租户 ID

按照以下说明从门户获取这些值:

  • 获取订阅 ID

    1. 登录到 Azure 帐户
    2. 选择左侧边栏中的“订阅
    3. 选择所需的任何订阅
    4. 选择“概述”
    5. 复制订阅 ID
  • 获取客户端 ID / 客户端密码 / 租户 ID

    有关如何获取客户端 ID、客户端密码和租户 ID 的信息,请参阅《创建可以访问资源的 Microsoft Entra 应用程序和服务主体

  • 设置环境变量

    获取值后,需要将以下值设置为你的环境变量:

    • AZURE_CLIENT_ID
    • AZURE_CLIENT_SECRET
    • AZURE_TENANT_ID
    • AZURE_SUBSCRIPTION_ID

    要在你的开发系统上设置以下环境变量:

    Windows(需要管理员访问权限)

    1. 打开“控制面板”
    2. 选择“系统安全>系统
    3. 选择左侧的“高级系统设置
    4. 在“系统属性”窗口中,选择“Environment Variables…”按钮。
    5. 选择要更改的属性,然后选择“编辑...”。 如果未列出属性名称,则选择“新建...”。

    基于 Linux 的 OS

        export AZURE_CLIENT_SECRET="__CLIENT_SECRET__"
        export AZURE_TENANT_ID="__TENANT_ID__"
        export AZURE_SUBSCRIPTION_ID="__SUBSCRIPTION_ID__"````
    
    

安装包

新的 SDK 使用 Go 模块进行版本控制和依赖项管理。

运行以下命令,在项目文件夹下安装本教程的包:

go get github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5
go get github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v3
go get github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources
go get github.com/Azure/azure-sdk-for-go/sdk/azcore
go get github.com/Azure/azure-sdk-for-go/sdk/azidentity

预配虚拟机

package main

import (
	"context"
	"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
	"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
	"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5"
	"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v3"
	"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources"
	"log"
	"os"
)

func main() {
	subscriptionId := os.Getenv("AZURE_SUBSCRIPTION_ID")

	cred, err := azidentity.NewDefaultAzureCredential(nil)
	if err != nil {
		log.Fatalf("authentication failure: %+v", err)
	}

	// client factory
	resourcesClientFactory, err := armresources.NewClientFactory(subscriptionId, cred, nil)
	if err != nil {
		log.Fatalf("cannot create client factory: %+v", err)
	}

	computeClientFactory, err := armcompute.NewClientFactory(subscriptionId, cred, nil)
	if err != nil {
		log.Fatalf("cannot create client factory: %+v", err)
	}

	networkClientFactory, err := armnetwork.NewClientFactory(subscriptionId, cred, nil)
	if err != nil {
		log.Fatalf("cannot create client factory: %+v", err)
	}

	// Step 1: Provision a resource group
	_, err = resourcesClientFactory.NewResourceGroupsClient().CreateOrUpdate(
		context.Background(),
		"<resourceGroupName>",
		armresources.ResourceGroup{
			Location: to.Ptr("westus"),
		},
		nil,
	)
	if err != nil {
		log.Fatal("cannot create resources group:", err)
	}

	// Step 2: Provision a virtual network
	virtualNetworksClientCreateOrUpdateResponsePoller, err := networkClientFactory.NewVirtualNetworksClient().BeginCreateOrUpdate(
		context.Background(),
		"<resourceGroupName>",
		"<virtualNetworkName>",
		armnetwork.VirtualNetwork{
			Location: to.Ptr("westus"),
			ExtendedLocation: &armnetwork.ExtendedLocation{
				Name: to.Ptr("<edgezoneid>"),
				Type: to.Ptr(armnetwork.ExtendedLocationTypesEdgeZone),
			},
			Properties: &armnetwork.VirtualNetworkPropertiesFormat{
				AddressSpace: &armnetwork.AddressSpace{
					AddressPrefixes: []*string{
						to.Ptr("10.0.0.0/16"),
					},
				},
				Subnets: []*armnetwork.Subnet{
					{
						Name: to.Ptr("test-1"),
						Properties: &armnetwork.SubnetPropertiesFormat{
							AddressPrefix: to.Ptr("10.0.0.0/24"),
						},
					},
				},
			},
		},
		nil,
	)
	if err != nil {
		log.Fatal("network creation failed", err)
	}
	virtualNetworksClientCreateOrUpdateResponse, err := virtualNetworksClientCreateOrUpdateResponsePoller.PollUntilDone(context.Background(), nil)
	if err != nil {
		log.Fatal("cannot create virtual network:", err)
	}
	subnetID := *virtualNetworksClientCreateOrUpdateResponse.Properties.Subnets[0].ID

	// Step 3: Provision an IP address
	publicIPAddressesClientCreateOrUpdateResponsePoller, err := networkClientFactory.NewPublicIPAddressesClient().BeginCreateOrUpdate(
		context.Background(),
		"<resourceGroupName>",
		"<publicIPName>",
		armnetwork.PublicIPAddress{
			Name:     to.Ptr("<publicIPName>"),
			Location: to.Ptr("westus"),
			ExtendedLocation: &armnetwork.ExtendedLocation{
				Name: to.Ptr("<edgezoneid>"),
				Type: to.Ptr(armnetwork.ExtendedLocationTypesEdgeZone),
			},
			SKU: &armnetwork.PublicIPAddressSKU{
				Name: to.Ptr(armnetwork.PublicIPAddressSKUNameStandard),
			},
			Properties: &armnetwork.PublicIPAddressPropertiesFormat{
				PublicIPAllocationMethod: to.Ptr(armnetwork.IPAllocationMethodStatic),
			},
		},
		nil,
	)
	if err != nil {
		log.Fatal("public ip creation failed", err)
	}
	publicIPAddressesClientCreateOrUpdateResponse, err := publicIPAddressesClientCreateOrUpdateResponsePoller.PollUntilDone(context.Background(), nil)
	if err != nil {
		log.Fatal("cannot create public ip: ", err)
	}

	// Step 4: Provision the network interface client
	interfacesClientCreateOrUpdateResponsePoller, err := networkClientFactory.NewInterfacesClient().BeginCreateOrUpdate(
		context.Background(),
		"<resourceGroupName>",
		"<networkInterfaceName>",
		armnetwork.Interface{
			Location: to.Ptr("westus"),
			ExtendedLocation: &armnetwork.ExtendedLocation{
				Name: to.Ptr("<edgezoneid>"),
				Type: to.Ptr(armnetwork.ExtendedLocationTypesEdgeZone),
			},
			Properties: &armnetwork.InterfacePropertiesFormat{
				EnableAcceleratedNetworking: to.Ptr(true),
				IPConfigurations: []*armnetwork.InterfaceIPConfiguration{
					{
						Name: to.Ptr("<ipConfigurationName>"),
						Properties: &armnetwork.InterfaceIPConfigurationPropertiesFormat{
							Subnet: &armnetwork.Subnet{
								ID: to.Ptr(subnetID),
							},
							PublicIPAddress: &armnetwork.PublicIPAddress{
								ID: publicIPAddressesClientCreateOrUpdateResponse.ID,
							},
						},
					},
				},
			},
		},
		nil,
	)
	if err != nil {
		log.Fatal("interface creation failed", err)
	}
	interfacesClientCreateOrUpdateResponse, err := interfacesClientCreateOrUpdateResponsePoller.PollUntilDone(context.Background(), nil)
	if err != nil {
		log.Fatal("cannot create interface:", err)
	}

	// Step 5: Provision the virtual machine
	virtualMachinesClientCreateOrUpdateResponsePoller, err := computeClientFactory.NewVirtualMachinesClient().BeginCreateOrUpdate(
		context.Background(),
		"<resourceGroupName>",
		"<vmName>",
		armcompute.VirtualMachine{
			Location: to.Ptr("westus"),
			ExtendedLocation: &armcompute.ExtendedLocation{
				Name: to.Ptr("<edgezoneid>"),
				Type: to.Ptr(armcompute.ExtendedLocationTypesEdgeZone),
			},
			Properties: &armcompute.VirtualMachineProperties{
				StorageProfile: &armcompute.StorageProfile{
					ImageReference: &armcompute.ImageReference{
						Publisher: to.Ptr("<publisher>"),
						Offer:     to.Ptr("<offer>"),
						SKU:       to.Ptr("<sku>"),
						Version:   to.Ptr("<version>"),
					},
				},
				HardwareProfile: &armcompute.HardwareProfile{
					VMSize: to.Ptr(armcompute.VirtualMachineSizeTypesStandardD2SV3),
				},
				OSProfile: &armcompute.OSProfile{
					ComputerName:  to.Ptr("<computerName>"),
					AdminUsername: to.Ptr("<adminUsername>"),
					AdminPassword: to.Ptr("<adminPassword>"),
				},
				NetworkProfile: &armcompute.NetworkProfile{
					NetworkInterfaces: []*armcompute.NetworkInterfaceReference{
						{
							ID: interfacesClientCreateOrUpdateResponse.ID,
							Properties: &armcompute.NetworkInterfaceReferenceProperties{
								Primary: to.Ptr(true),
							},
						},
					},
				},
			},
		},
		nil,
	)
	if err != nil {
		log.Fatal("virtual machine creation failed", err)
	}
	_, err = virtualMachinesClientCreateOrUpdateResponsePoller.PollUntilDone(context.Background(), nil)
	if err != nil {
		log.Fatal("cannot create virtual machine:", err)
	}
}

清理资源

在本教程中,你使用 Go SDK 在 Azure 公共 MEC 中创建了 VM。 如果将来不需要这些资源,请使用 Azure 门户删除所创建的资源组。

后续步骤

若要使用 Python SDK 在 Azure 公共 MEC 中部署虚拟机,请转到以下文章: