一个Windows Docker容器内的Service Fabric应用程序能否部署到集群中?

3
在Visual Studio(*.sfproj)中构建Service Fabric项目时,作为模板的一部分会创建一个Deploy-FabricApplication.ps1脚本,用于将该应用程序部署到Azure(或其他任何运行Service Fabric的地方)。因为我们的构建和部署过程已经容器化了,我正在寻找一种方法将该机制作为Windows Docker映像的一部分进行容器化。是否有办法从Windows Docker容器内运行此脚本?如果可以,映像需要具备什么先决条件?

我认为问题不够清晰。你是需要在Docker容器内部署集群(就像下面的答案所建议的)还是想要从Docker容器内创建应用程序以便在服务织物集群中部署? - Diego Mendes
@DiegoMendes - 我想从 Docker 容器内部将应用程序部署到在 Azure 上运行的 Service Fabric 集群中。基本上,我想从容器内运行 Deploy-FabricApplication.ps1 脚本,将其指向在 Azure 上运行的 URL。因此,需要将所有需要部署的工具 Docker 化。应用程序本身是在其他地方构建的,并且假定已经存在于此问题的目的。 - Mike Christensen
2个回答

5

更新:

作为Service Fabric 6.4的一部分发布的Service Fabric SDK 3.3.617现在可以在容器中安装,以构建和部署Service Fabric项目。可以使用以下命令在Dockerfile中完成此操作:

ADD https://download.microsoft.com/download/D/D/D/DDD408E4-6802-47FB-B0A1-ECF657BEB35F/MicrosoftServiceFabric.6.4.617.9590.exe C:\TEMP\MicrosoftServiceFabricRuntime.exe

ADD https://download.microsoft.com/download/D/D/D/DDD408E4-6802-47FB-B0A1-ECF657BEB35F/MicrosoftServiceFabricSDK.3.3.617.msi C:\TEMP\MicrosoftServiceFabricSDK.msi

RUN C:\TEMP\MicrosoftServiceFabricRuntime.exe /accepteula /sdkcontainerclient /quiet

RUN msiexec.exe /i "C:\TEMP\MicrosoftServiceFabricSDK.msi" /qn 

这里有一个Dockerfile的示例

原始答案:

事实证明,这并不是一件简单的事情。这个脚本需要安装Windows Service Fabric SDK。安装Service Fabric SDK的推荐(也是唯一支持的)方式是通过WebPI,可以在此处获得。可能可以将WebPI Dockerize,但存在一个问题。WebPI安装程序包含三个组件; Service Fabric SDK,Service Fabric Runtime和Visual Studio的Service Fabric工具。WebPI安装程序将安装所有这些组件。不幸的是,自写作时起,Service Fabric Runtime无法在Docker容器下运行,因为它想要安装内核级驱动程序。这个错误被追踪在此处,但已经持续了近一年,并没有真正的进展。这意味着一个人无法在Docker容器中运行Service Fabric集群,但是SDK和工具肯定仍然能够运行,对吗?不幸的是,没有办法告诉安装程序仅安装SDK和工具,而不是运行时。

那么,也许有一种不受支持的方法可以安装SDK和工具。事实证明,发行说明中有对各种MSI的引用以供参考。

SDK在此处可用

适用于Visual Studio的工具在此处可用

从Dockerfile运行msiexec.exe非常简单,这意味着我们应该能够以这种方式安装SDK。不行。不幸的是,msiexec将失败并显示通用的1603代码。如果你以详细模式运行msiexec并输出日志文件,你可以查看这个错误并查看根本原因:

MSI (s) (78:34) [19:07:56:049]: 产品: Microsoft Azure Service Fabric SDK - 此产品需要安装Service Fabric Runtime。

此产品需要安装Service Fabric Runtime。操作结束时间为19:07:56: LaunchConditions。返回值为3。

因此,我们又一次失败了。我没有找到其他经过打包的Service Fabric SDK版本(Chocolatey有一个版本,但它只是启动WebPI安装程序),这留下了最后一个解决方案;我们手动安装SDK而不需要安装程序的帮助。这需要反向工程确定安装程序所做的内容,并将其集成到我们的Dockerfile中。

SDK安装程序做了一些事情。它将一堆文件复制到c:\program files\microsoft sdks\service fabric\和一些文件复制到c:\program files\microsoft service fabric\。还将一些东西添加到GAC(如System.Fabric.dll),将一些东西添加到注册表中,并安装PowerShell模块。我们需要完成所有这些操作才能运行脚本。

我最终的解决方案是将关键文件夹作为Docker卷挂载,以便在容器内使用它们:

docker run `
  -v 'c:\program files\microsoft sdks\service fabric\tools\psmodule\servicefabricsdk:C:\ServiceFabricModules' `
  -v 'c:\program files\microsoft service fabric\bin\fabric\fabric.code:C:\ServiceFabricCode' `
  -v 'c:\program files\microsoft service fabric\bin\servicefabric:C:\ServiceFabricBin' `
  -e ModuleFolderPath=C:\ServiceFabricModules `
  -it build-agent powershell

首先,我需要分享 c:\program files\microsoft sdks\service fabric\tools\psmodule\servicefabricsdk 目录,它包含了Powershell模块,Deploy-FabricApplication.ps1 脚本会加载这些模块。
Import-Module "$ModuleFolderPath\ServiceFabricSDK.psm1"

接下来,我们需要共享,因为它包含了安装程序GAC的许多DLL文件。
最后,我们还需要共享,因为该目录包含了SDK安装的PowerShell模块。
当容器启动时,我们需要执行以下操作:
首先,将模块注册到PowerShell:
Copy-Item C:\ServiceFabricBin C:\windows\system32\WindowsPowerShell\v1.0\modules\ServiceFabric -Recurse

在您完成此操作后, Get-Module -ListAvailable 将显示 ServiceFabric 模块。但是,因为缺少一堆 DLL,所以没有导出会被加载。安装程序将这些 DLL 放入全局程序集缓存 (GAC) 中,但是 GAC 是愚蠢的,因此让我们将这些 DLL 放在相同的目录中,使模块能够找到它们:

Copy-Item C:\ServiceFabricCode\System.Fabric*.dll C:\windows\system32\WindowsPowerShell\v1.0\modules\ServiceFabric -Recurse

在此之后,您应该能够运行Get-Module -ListAvailable命令并查看完全加载了ServiceFabric模块。
还有一件事情要做。Deploy-FabricApplication.ps1脚本导入ServiceFabricSDK.psm1模块(如上所述)。但是,$ModuleFolderPath是什么?默认情况下,该脚本查找注册表中的此值,当然安装程序会为您设置这个值。我们不想在Docker镜像中破坏注册表,因此让我们将脚本更改为查看环境变量:
$ModuleFolderPath = $ENV:ModuleFolderPath
Import-Module "$ModuleFolderPath\ServiceFabricSDK.psm1"

现在,我们可以在运行Docker容器时(或从我们的Dockerfile中),设置环境变量。如果您不想修改Deploy-FabricApplication.ps1文件,您也可以在HKLM:\SOFTWARE\Microsoft\Service Fabric SDK\FabricSDKPSModulePath处设置此变量,当然,如果您真的不在意,您也可以直接编写代码。另外请注意,在脚本部署之前,您需要导入您的证书(您可以从Key Vault以PFX文件的形式下载)。
Import-PfxCertificate -Exportable -CertStoreLocation Cert:\CurrentUser\My\ -FilePath C:\Certs\MyCert.pfx

我认为更高质量的版本是在Dockerfile中将所需文件复制到镜像中,而不是将它们作为卷挂载,这样镜像就更加自包含,但这应该相当简单。此外,我相信已经GAC的DLL也可以通过NuGet获得,因此在Docker构建过程中可以通过NuGet下载所有这些文件。
此外,这是我的完整的Dockerfile,我已经成功地部署了一个使用Service Fabric的应用程序:
# escape=`

FROM microsoft/dotnet-framework:4.7.1

SHELL ["cmd", "/S", "/C"]

# Install Visual Studio Build Tools
ADD https://aka.ms/vs/15/release/vs_buildtools.exe C:\SETUP\vs_buildtools.exe
RUN C:\SETUP\vs_buildtools.exe --quiet --wait --norestart --nocache `
    --add Microsoft.VisualStudio.Workload.AzureBuildTools `
 || IF "%ERRORLEVEL%"=="3010" EXIT 0

SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]

# Our Deploy Certs
ADD ./Certs/ C:\Certs\

# Update Path (I forget if this was needed for something)
RUN SETX /M PATH $($Env:PATH + ';C:\ServiceFabricCode')

我希望这个能够帮到某些人,更重要的是我希望微软能修复他们安装程序中的运行时需求。

注意:似乎将 C:\ServiceFabricCode 添加到路径中是必要的。Deploy-FabricApplication.ps1 中有关于查找 FabricCommon.dll 的内容,但不确定具体是什么。不过安装程序似乎也会这样做。 - Mike Christensen

-2

安装Azure服务布局的最佳方法是创建一个PowerShell文件,并从dockerfile中调用它。

PowerShell文件:

Start-Process "msiexec" -ArgumentList '/i', 'C:/app/WebPlatformInstaller_amd64_en-US.msi', '/passive', '/quiet', '/norestart', '/qn' -NoNewWindow -Wait; 

& "C:\Program Files\Microsoft\Web Platform Installer\WebPICMD.exe" /Install /Products:MicrosoftAzure-ServiceFabric-CoreSDK /AcceptEULA

Dockerfile

RUN powershell -noexit "& ""./InstallServiceFabric.ps1"""

如上所述,安装程序在 Docker 下无法运行,因为运行时会尝试安装内核驱动程序并一直挂起。请参见 Issue 711 - Mike Christensen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接