在 VM 创建期间运行自定义脚本 - VmStartupScript(预览版)

简介

重要

此功能为预览版。 欢迎立即开始使用并向我们提供反馈。 本文末尾提供了有关如何与我们联系的说明。 请注意,预览版期间提供的技术支持有限。

VmStartupScript 允许在 Azure PlayFab 多人游戏服务器 (MPS) 中使用的虚拟机 (VM) 上运行自定义脚本。 MPS 针对游戏服务器托管进行了优化,使游戏能够根据需求轻松动态缩放。 为了便于在 VM 初始化期间快速自定义大量服务器,自定义脚本设置为可以在托管游戏服务器的每个底层 VM 上运行。 它可用于完成安装自定义软件、修改安全设置、使用自定义服务记录游戏服务器输出和指标等任务。

注意

这是一项高级功能,应谨慎使用。 运行脚本通过管理员(根)权限在虚拟机 (VM) 级别执行。 如果未正确使用,它可能会干扰正在运行的游戏服务器的正常流程,甚至完全阻止它们运行。 最终用户对脚本的内容负责。

如何使用 VmStartupScript

若要使用 VmStartupScript 功能,必须提供自定义脚本以及计划安装的所有相关软件(可选)。 该脚本在虚拟机初始化时开始执行。 此操作发生在每个虚拟机上的游戏服务器启动之前。 脚本成功执行后,MPS 服务将继续完成游戏服务器的初始化并将其转入 StandingBy 状态。 要了解有关不同游戏服务器状态的更多信息,请参阅多人游戏服务器的生命周期

若要在实际生产环境中使用此功能,请在开始前参阅建议的开发人员工作流

创建脚本

  • 为 Linux VM 创建名为 PF_StartupScript.sh 的文件,或者为 Windows VM 创建 PF_StartupScript.ps1
  • 在文件中添加设置/执行命令。 如果需要它们,可在脚本中使用以下常用环境变量。 某些操作不受支持,或者会导致 VM 无法成功启动,从而产生不必要的费用。 有关详细信息,请参阅不支持的操作部分。

有关脚本示例,请参阅 VmStartupScriptGallery

创建并上传压缩文件

  1. 将所有相关软件收集到脚本计划使用或调用的文件夹中。 如果脚本安装了第三方软件,则脚本可以在执行期间下载它,也可以将其与它捆绑在压缩文件中。 如果未安装任何内容,请跳过此步骤。
  2. 根据需要,使用在前面小节中创建的脚本(.sh 或.ps1)以及在前面步骤中收集的软件创建压缩文件 (.zip)。 脚本文件应位于压缩文件的根目录中,而不是目录中。 此外,如果脚本文件未命名为 PF_StartupScript.sh (Linux) 或 PF_StartupScript.ps1 (Windows),则不会执行,并且游戏服务器将无法启动。
  3. 使用以下方法之一上传压缩文件:

注意

建议在压缩文件中包括脚本所需的所有二进制文件和资产,因为这样可以加快执行速度并缩短 MPS 交付游戏服务器的时间。 确保包含游戏服务器将运行的相关平台的资产。 例如,如果使用 Linux 服务器,则应包含“amd64”Debian/Ubuntu 软件包。

将自定义脚本应用于新版本

上传 .zip 文件后,在配置 VmStartupScriptAssetReference 属性后,使用 MPS API 创建新版本。 有关说明,请参阅如何使用 MPS API 创建内部版本

  • 添加 VmStartupScriptConfiguration.VmStartupScriptAssetReference 属性,其中包含对已上传资产文件的引用。 此属性是所有“CreateBuild”相关 API 的一部分,例如 CreateBuildWithCustomContainerCreateBuildWithManagedContainerCreateBuildWithProcessBasedServer
  • VmStartupScriptAssetReference.FileName 属性添加有效值。 此值必须与资产文件的名称相同,例如 vmstartupscriptassets.zip
  • VmStartupScriptAssetReference.MountPath 属性必须为空,因为 VmStartupScript 功能不支持该属性。

注意

如果为 MountPath 属性设置了值,则创建内部版本的操作将失败。

下面的代码示例使用 Linux 容器创建内部版本,然后使用 vmstartupscriptassets.zip 中的脚本来自定义 VM:

var request = new CreateBuildWithCustomContainerRequest()
{ 
    ContainerImageReference = new ContainerImageReference()
    {
         ImageName= "testimagename",
         Tag= "0.1"
    },
    ContainerFlavor = ContainerFlavor.CustomLinux,
    BuildName = "testbuildwithvmstartupscript",
    VmSize = AzureVmSize.Standard_D2as_v4,
    MultiplayerServerCountPerVm = 3,
    Ports= new List<Port>
    {
        new Port()
        {
            Name= "port",
            Num= 123,
            Protocol = ProtocolType.TCP   
        }
    },
    RegionConfigurations = new List<BuildRegionParams> { new BuildRegionParams()
    {
        Region = "EastUs",
        StandbyServers = 3,
        MaxServers = 6

    } 
    },
    VmStartupScriptConfiguration = new VmStartupScriptParams()
    {
        VmStartupScriptAssetReference = new AssetReferenceParams()
        {
            FileName = "vmstartupscriptassets.zip"
        }
    }
};
var result = await PlayFabMultiplayerAPI.CreateBuildWithCustomContainerAsync(request);

VmStartupScript 在 VM 的“准备就绪”阶段执行,并且必须成功终止才能启动游戏服务器。 如果失败(退出代码不是 0),VM 将不会转换到“正在运行”状态,并且需要通过 RDP/SSH 连接到 VM 进行调试。 若要了解详细信息,请参阅建议的开发人员工作流。 VM 将继续重试以执行 VmStartupScript。

特殊注意事项

在 Linux 上,是否需要将 PF_StartupScript.sh 文件标记为可执行文件?

MPS 在运行脚本文件之前,会将其标记为可执行文件,然后将任何 Windows 行结尾(“\r\n”)转换为 linux 行结尾(“\n”)。 所以,不必担心这两件事。

环境变量

下面是可在启动脚本中使用的环境变量。

名称 说明
PF_TITLE_ID PlayFab 游戏 ID
PF_BUILD_ID PlayFab MPS 内部版本 ID
PF_VM_ID MPS 虚拟机 ID
PF_REGION 托管 VM 的 Azure 区域
PF_PUBLIC_IPV4_ADDRESS VM 的公共 IP 地址
PF_FQDN 与 VM 的公共 IP 对应的完全限定域名
PF_SHARED_CONTENT_FOLDER_VM 包含整个 VM 的共享内容的文件夹

不支持的操作

不应从脚本中执行这些操作,因为很有可能会中断 VM 和游戏服务器的生命周期:

  • 不要阻止启动脚本执行。 脚本必须成功结束,然后才能创建游戏服务器。 如果需要在后台运行某些内容,可以将其安装为 Linux 上的系统服务或 Windows 服务。
  • 不要使用从 30000 开始的端口,因为它们用于游戏服务器;也不要使用端口 56001,因为它由 VmAgent 进程(MPS 游戏服务器协调器可执行文件)使用。
  • 不要修改 D: (Windows) 或 /mnt (Linux) 路径上的任何文件,因为这些文件是 VmAgent 操作所必需的(包含可编辑内容的文件夹除外,例如 PF_SHARED_CONTENT_FOLDER_VM)。
  • 不应在 VmStartupScript 或由其启动的应用程序中使用 GSDK。 GSDK 只能在游戏服务器上使用。
  • 不应手动重启虚拟机,因为此操作会给与 MPS 控制平面的通信带来挑战。

端口

使用 VmStartupScript 功能时,可以请求在每台 VM 上公开多个端口。 这些端口可供脚本启动的任何程序使用,有别于 MPS 为游戏服务器打开的端口。

用法

最多可以为每个虚拟机请求五个端口。 对于每个端口,必须指定协议(TCP 或 UDP)和名称。 下面是如何请求两个端口的示例:

VmStartupScriptConfiguration = new VmStartupScriptParams()
{
    VmStartupScriptAssetReference = new AssetReferenceParams()
    {
        FileName = "vmstartupscriptassets.zip"
    },
    PortRequests = new List<VmStartupScriptPortRequest>()
        {
            new VmStartupScriptPortRequest()
            {
                Name = "port0",
                Protocol = ProtocolType.TCP
            },
            new VmStartupScriptPortRequest()
            {
                Name = "port1",
                Protocol = ProtocolType.UDP
            }
        }
}

如果请求任何端口,脚本可以使用以下环境变量来帮助你获取有关端口的信息:

名称 说明
PF_STARTUP_SCRIPT_PORT_COUNT VmStartupScript 端口数
PF_STARTUP_SCRIPT_PORT_NAME_(index) 端口的名称,如请求中所述
PF_STARTUP_SCRIPT_PORT_PROTOCOL_(index) 端口的协议,如请求中所述
PF_STARTUP_SCRIPT_PORT_INTERNAL_(index) 程序应在 VM 中绑定到的端口
PF_STARTUP_SCRIPT_PORT_EXTERNAL_(index) 在外部终结点中打开的端口。 外部客户端应使用此端口连接到绑定到 INTERNAL 端口的程序

例如,对于上述示例脚本中请求的两个端口,应该会在 VmStartupScript 中找到这些环境变量:

PF_STARTUP_SCRIPT_PORT_COUNT

PF_STARTUP_SCRIPT_PORT_INTERNAL_0
PF_STARTUP_SCRIPT_PORT_EXTERNAL_0
PF_STARTUP_SCRIPT_PORT_NAME_0
PF_STARTUP_SCRIPT_PORT_PROTOCOL_0

PF_STARTUP_SCRIPT_PORT_INTERNAL_1
PF_STARTUP_SCRIPT_PORT_EXTERNAL_1
PF_STARTUP_SCRIPT_PORT_NAME_1
PF_STARTUP_SCRIPT_PORT_PROTOCOL_1

重要

与我们为游戏服务器打开的端口类似,需要由你对连接到端口的客户端进行身份验证。 MPS 不为这些端口提供任何身份验证机制。

注意

客户会发现,分配的端口从数字 20000 及更高值开始。 但是,建议不要在脚本中对此值进行硬编码,因为它将来可能会更改,并且始终使用环境变量来获取正确的端口信息。

开发/调试

建议在使用 VmStartupScript 功能之前,在 GitHub 上的开源存储库 (VmStartupScriptGallery) 上查看这些示例脚本。 欢迎参与!

最初,应使用单个 VM 创建测试版本。 此 VM 的规格应与计划部署生产版本时的 VM 类似。 部署此单个虚拟机后,可以通过 RDP/SSH 连接虚拟机、复制必要的文件并尝试编辑/运行脚本直至成功。

一旦此 VM 启动并运行,并且你验证脚本的行为符合预期,就可以将脚本和资产放入 .zip 文件中。 之后,可以上传它并尝试使用它来创建内部版本。 在确定脚本正常工作后,请尝试再次创建单个 VM 内部版本,以节省成本并纵向扩展。

如果在运行脚本时遇到问题,可以通过 RDP/SSH 登录虚拟机进行调试,并分别检查脚本的标准输出和标准错误流的 PF_StartupScriptStdOut.txtPF_StartupScriptStdErr.txt 文件。 这些文件位于 Windows 的 D: 盘上或 Linux 的 /mnt 上。

该脚本应该是幂等的,因为它有可能被执行多次。 例如,如果脚本尝试下载外部资源但由于网络问题而失败,MPS 会重试整个脚本执行。

支持

MPS 服务将运行 VmStartupScript 上的任何内容。 但是,团队不会为作为脚本的一部分安装/执行的单个操作和可执行文件提供支持。

在预览期间,使用 PlayFab 社区论坛Discord 获取支持并提供反馈。 如果 VmStartupScriptGallery 存储库中的任何脚本出现问题或想要请求新脚本,请使用 GitHub 上的创建问题