normalian blog

Let's talk about Microsoft Azure, ASP.NET and Java!

Configuration tips when you need to upgrade Service Fabric cluster applications

Service Fabric is one of components to offer Microservice architecture and it's also used with CI/CD tools such like VSTS. In this post, you can learn tips to construct Microservice architecture CI/CD pipeline.

Error #1 "You must first remove the existing application before a new application can be deployed or provide a new name for the application."

You will get this error when you try to upgrade your Service Fabric applications as latest version. Here is error message within VSTS release process.

2018-07-24T23:02:08.4239940Z Imported cluster client certificate with thumbprint 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'.
2018-07-24T23:02:27.2235680Z Successfully connected to cluster.
2018-07-24T23:02:27.2624467Z Searching for path: D:\a\r1\a
2018-07-24T23:02:27.3693528Z No items were found with search pattern D:\a\r1\a.
2018-07-24T23:02:35.2334317Z ##[error]An application with name 'fabric:/MySFASPAppType' already exists, its type is 'MySFASPAppType' and version is '1.0.0.20180724.1'. You must first remove the existing application before a new application can be deployed or provide a new name for the application.
2018-07-24T23:02:35.8774898Z ##[section]Finishing: Deploy Service Fabric Application

You need to configure upgrade option for Service Fabric cluster with Visual Studio like below. You can come up this dialog by right click and choose "Publish".
f:id:waritohutsu:20180725161131p:plain

The configuration will be reflected into "your Service Fabric project name"\PublishProfiles\Cloud.xml like below.

<?xml version="1.0" encoding="utf-8"?>
<PublishProfile xmlns="http://schemas.microsoft.com/2015/05/fabrictools">
  <ClusterConnectionParameters ConnectionEndpoint="" />
  <ApplicationParameterFile Path="..\ApplicationParameters\Cloud.xml" />
  <CopyPackageParameters CompressPackage="true" />
  <UpgradeDeployment Mode="UnmonitoredAuto" Enabled="true">
    <Parameters UpgradeReplicaSetCheckTimeoutSec="1" Force="True" />
  </UpgradeDeployment>
</PublishProfile>

Confirm "UpgradeDeployment" tag including its child tags. This should solve the error.

Error #2 "The content in ConfigPackage Name:Config and Version:x.x.x in Service Manifest 'xxxxxxxxxxxxxxx' has changed, but the version number is the same."

You should look over - Start-ServiceFabricApplicationUpgrade (ServiceFabric) | Microsoft Docs before proceeding this post. Service Fabric applications have several versions such like Service Fabric package itself, code and config. You need to update some of the versions to upgrade Service Fabric applications.
A temporary solution is to use "Build.BuildId" for the versions. Edit ApplicationManifest.xml and ServiceManifest.xml in your Service Fabric project like below.

"your Service Fabric project name"\ApplicationPackageRoot\ApplicationManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<ApplicationManifest ApplicationTypeName="SFwithASPNetAppType"
                     ApplicationTypeVersion="1.0.#{Build.BuildId}#"
                     xmlns="http://schemas.microsoft.com/2011/01/fabric"
                     xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Parameters>
    <Parameter Name="GuestContainer1_InstanceCount" DefaultValue="-1" />
  </Parameters>
  <!-- Import the ServiceManifest from the ServicePackage. The ServiceManifestName and ServiceManifestVersion 
       should match the Name and Version attributes of the ServiceManifest element defined in the 
       ServiceManifest.xml file. -->
  <ServiceManifestImport>
    <ServiceManifestRef ServiceManifestName="GuestContainer1Pkg" ServiceManifestVersion="1.0.#{Build.BuildId}#" />
    <ConfigOverrides />
    <Policies>
      <ContainerHostPolicies CodePackageRef="Code" Isolation="hyperv">
    ...

"your Service Fabric project name"\ApplicationPackageRoot\"ServiceManifestName"\ServiceManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<ServiceManifest Name="GuestContainer1Pkg"
                 Version="1.0.#{Build.BuildId}#"
                 xmlns="http://schemas.microsoft.com/2011/01/fabric"
                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <ServiceTypes>
    <!-- This is the name of your ServiceType.
         The UseImplicitHost attribute indicates this is a guest service. -->
    <StatelessServiceType ServiceTypeName="GuestContainer1Type" UseImplicitHost="true" />
  </ServiceTypes>

  <!-- Code package is your service executable. -->
  <CodePackage Name="Code" Version="1.0.#{Build.BuildId}#">
    <EntryPoint>
      <ContainerHost>
        <ImageName>"my container registry account ".azurecr.io/#{Build.Repository.Name}#:#{Build.BuildId}#</ImageName>
      </ContainerHost>
    </EntryPoint>
    <EnvironmentVariables>
      <EnvironmentVariable Name="VariableName" Value="VariableValue"/>
    </EnvironmentVariables>
  </CodePackage>

  <ConfigPackage Name="Config" Version="1.0.#{Build.BuildId}#" />

  <Resources>
    <Endpoints>
      <Endpoint Name="GuestContainer1TypeEndpoint" UriScheme="http" Port="xxxx" Protocol="http" />
    </Endpoints>
  </Resources>
</ServiceManifest>

You also need to follow Replace configuration files with environment variables on VSTS tasks - normalian blog to replace #{Build.BuildId}# in your xml files.