Service Fabric Multiple service instances with config override - azure-service-fabric

Our service fabric application includes a stateless service that exposes an HTTP endpoint through OwinCommunicationListener.
The ServiceManifest.Xml for this service specifies the service endpoint <Endpoint Name="ServiceEndpoint" Type="Input" Protocol="http" Port="8090" />
The stateless service can then be accessed via a browser on http://localhost:8090/
What we are trying to do is instantiate multiple instances of this service on different endpoints in the same Service Fabric application through the ApplicationManifest.
The ServiceManifestImport imports our service package and allows configuration overrides at the application level. We're not able to override the ServiceEndpoint this way, only the values in Settings.xml
<ServiceManifestImport>
<ServiceManifestRef ServiceManifestName="FooServicePkg" ServiceManifestVersion="1.0.0" >
<ConfigOverrides Name="Config">
<Settings>
<SectionName Name="MySettings">
<Parameter Name="MySetting" Value="SomeValue">
</Settings>
</ConfigOverrides>
</ServiceManifestImport>
We can create named instances of the service by specifying multiple Service nodes under DefaultServices
<DefaultServices>
<Service Name="FooInstanceA">
<StatelessService ServiceTypeName="FooType" InstanceCount="1" />
<SingletonPartition />
</StatelessService>
</Service>
<Service Name="FooInstanceB">
<StatelessService ServiceTypeName="FooType" InstanceCount="1" />
<SingletonPartition />
</StatelessService>
</Service>
</DefaultServices>
Is it possible to specify configuration overrides per instance of a service through configuration?
I tried to make the service instances listen on a specific port by using their service name to work out which port so FooInstanceA listens on port 8090 and FooInstanceB listens on 8091.
Clearly Service Fabric is doing some magic during deployment because when FooInstanceB listens on a port other than the one specified on the ServiceEndpoint configuration the service is not accessible.
The first reason is the DACL is not set on the endpoint, this is resolved by running;
netsh http add urlacl http://+:8091/ user=everyone listen=yes
This allows the services to come up and show healthy in the Service Fabric Explorer, however the FooInstanceB is responding with an HTTP 503 error when we access with http://localhost:8091/
How can we get the service instances listening on different ports?
I hope that's clear, thank you.

Not a lot of great options to accomplish this. Here are some ideas:
Create multiple application instances instead of multiple services of the same type within an app. That would allow you to use the app parameters to configure the behavior of the particular service.
Create multiple config packages within your service type. Each config package would be intended for one of the service instances. Determining which config package a service instance is assigned to would need to be dynamic, maybe based on the service instance's name? Not a great option, of course, since it couples the service definition with the number of instances that will be created.
A custom configuration implementation. Maybe have your service expose an endpoint that allows you to configure it post-deployment. Or have the service call some other management service that provides its configuration at activation time.

You can also let Service Fabric assign the ports automatically and then use the reverse proxy that comes with Service Fabric.

I think its a very good idea to have a url rewriting service in front of a SF cluster .
This can give you multiple end points and do url rewriting , firewalls/ black listing , https etc .
Other way is to package the service as a lib or in Nuget and create the N services you need with different service manifests.

I've managed to do this using ApplicationParameter xml files and choose the right one during deployment in VSTS.
This, for example, is my Cloud.xml which I use for deployment to my test environment. The trick is the Name parameter on the second line. I've specified the port using this documentation: https://learn.microsoft.com/en-us/azure/service-fabric/service-fabric-how-to-specify-port-number-using-parameters
<?xml version="1.0" encoding="utf-8"?>
<Application xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Name="fabric:/DotNetCoreTest" xmlns="http://schemas.microsoft.com/2011/01/fabric">
<Parameters>
<Parameter Name="Web1_InstanceCount" Value="2" />
<Parameter Name="ServiceEndpoint_PortNumber" Value="8909" />
</Parameters>
</Application>
This is the xml file for Staging: Staging.xml
<?xml version="1.0" encoding="utf-8"?>
<Application xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Name="fabric:/DotNetCoreStaging" xmlns="http://schemas.microsoft.com/2011/01/fabric">
<Parameters>
<Parameter Name="Web1_InstanceCount" Value="2" />
<Parameter Name="ServiceEndpoint_PortNumber" Value="8910" />
</Parameters>
</Application>
Using the Traefik Reverse Proxy as described here I can use a hostname to reach my service.
In VSTS I'm using a tokenizer to replace both the host name in the ServiceManifest and replacing the ApplicationTypeName in the ApplicationManifest during deployment.
This is my ServiceManifest:
<ServiceTypes>
<!-- This is the name of your ServiceType.
This name must match the string used in RegisterServiceType call in Program.cs. -->
<StatelessServiceType ServiceTypeName="Web1Type">
<Extensions>
<Extension Name="Traefik">
<Labels xmlns="http://schemas.microsoft.com/2015/03/fabact-no-schema">
<Label Key="traefik.frontend.rule.hostname">Host: #{HostName}#</Label>
<Label Key="traefik.expose">true</Label>
<Label Key="traefik.frontend.passHostHeader">true</Label>
</Labels>
</Extension>
</Extensions>
</StatelessServiceType>
</ServiceTypes>

Related

Azure Service Fabric - Configure service instance parameters using Powershell

Is it possible to inject parameters at run time into a Guest Executable via the Settings.xml file or another means? I have a GuestExecutable which I need to pass some configuration to it - a URL at service creation time.
I need two instances of the service running with different parameters, the service instance information has to differ in terms of a custom parameter I need to pass through . Is this possible using Powershell or, do I need to version the config and create a new version?
Thanks in advance
Have you tried the following command: New-ServiceFabricApplication ?
When you create your application manifest file, the parameters will contain replaceable parameters that you set when you register a new application.
An ApplicationManifest.xml example like this:
<?xml version="1.0" encoding="utf-8"?>
<ApplicationManifest ApplicationTypeName="MyAppTypeName" ApplicationTypeVersion="1.0.0" xmlns=...>
<Parameters>
<Parameter Name="Web1_InstanceCount" Value="-1" />
<Parameter Name="ENVIRONMENT_NAME" Value="DEV" />
<Parameter Name="FEPlacementConstraints" Value="NodeTypeName==FrontEnd" />
</Parameters>
<ServiceManifestImport>
<ServiceManifestRef ServiceManifestName="MyServicePkg" ServiceManifestVersion="1.0.0" />
<ConfigOverrides />
<EnvironmentOverrides />
</ServiceManifestImport>
<DefaultServices>
<Service Name="Web1">
<StatelessService ServiceTypeName="MyServiceType" InstanceCount="[Web1_InstanceCount]">
<SingletonPartition />
<PlacementConstraints>[FEPlacementConstraints]</PlacementConstraints>
</StatelessService>
</Service>
</DefaultServices>
</ApplicationManifest>
You would change the settings file using config overrides like this:
<ConfigOverrides>
<ConfigOverride Name="Config">
<Settings>
<Section Name="MyConfigSection">
<Parameter Name="MySetting" Value="[ENVIRONMENT_NAME]"/>
</Section>
</Settings>
</ConfigOverride>
</ConfigOverrides>
Or you could set environment variables on your service like this:
<EnvironmentOverrides CodePackageRef="Code">
<EnvironmentVariable Name="ASPNETCORE_ENVIRONMENT" Value="[ENVIRONMENT_NAME]" />
</EnvironmentOverrides>
In my opinion the environment overrides would work better on your case,
because most guest executable are not flexible on how you can configure them but generally they accept environment variables.
Then you:
Upload your application with: Copy-ServiceFabricApplicationPackage
Register your application with Register-ServiceFabricApplicationType
And then you register each new app with the settings you need:
.
New-ServiceFabricApplication -ApplicationName fabric:/myapp/todolist-dev -ApplicationTypeName "MyAppTypeName" -ApplicationTypeVersion "1.0.0" -ApplicationParameter #{Web1_InstanceCount='-1'; ENVIRONMENT_NAME='DEV'}
New-ServiceFabricApplication -ApplicationName fabric:/myapp/todolist-uat -ApplicationTypeName "MyAppTypeName" -ApplicationTypeVersion "1.0.0" -ApplicationParameter #{Web1_InstanceCount='-1'; ENVIRONMENT_NAME='UAT'}
The only down side of this approach is that you would end up with two applications, but don't think would be a problem for you, they will be managed mostly the same way as you would do with a single application.
if you strictly need to run both together on same application, you could do some workarounds:
Using multiple Config packages(don't think would work well with guest executables, but works well with reliable services
Using the startup script, where you would add the logic to pass the parameter to your startup exe, something like the following:
In your ServiceManifest.xml:
<CodePackage Name="Code" Version="1.0.0">
<EntryPoint>
<ExeHost>
<Program>start.bat</Program>
<WorkingFolder>CodePackage</WorkingFolder>
</ExeHost>
</EntryPoint>
</CodePackage>
On the same folder (code) of your .exe, you create the start.bat file with following contents:
myApp.exe %EnvironmentVariableNameSetBySF%

Service Fabric can't connect to guest executable on UDP (Unreal Engine Server)

I'm trying to deploy Unreal Server guest executable to Service Fabric.
I've been fallowing this blog post:
http://haishibai.blogspot.com/2017/03/setting-up-highly-available-minecraft.html
Except I'm not using containers and use Windows based service.
On local cluster everything works. I can connect from client to deployed server.
When trying to connect to remote server, I can't connect to it.
When looking at my service fabric managment page It seems like my server process is working (it have proper process id).
In my LoadBalancing service I have port forwarding on UDP/7777, though HealthProbes are on TCP (there is no option to select UDP, I don't know if that mnatter).
Here Is my ServiceManifest:
<?xml version="1.0" encoding="utf-8"?>
<ServiceManifest Name="UnrealGuestPkg"
Version="1.0.0"
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 executable service. -->
<StatelessServiceType ServiceTypeName="UnrealGuestType" UseImplicitHost="true" />
</ServiceTypes>
<!-- Code package is your service executable. -->
<CodePackage Name="Code" Version="1.0.0">
<!-- The SetupEntryPoint is an optional element used to specify a
program to be executed before the service's code is launched. -->
<!--
<SetupEntryPoint>
<ExeHost>
<Program></Program>
</ExeHost>
</SetupEntryPoint>
-->
<EntryPoint>
<ExeHost>
<Program>ActionRPGGame\Binaries\Win64\ActionRPGGameServer.exe</Program>
<Arguments>-log</Arguments>
<WorkingFolder>CodeBase</WorkingFolder>
<!-- Uncomment to log console output (both stdout and stderr) to one of the
service's working directories. -->
<!-- <ConsoleRedirection FileRetentionCount="5" FileMaxSizeInKb="2048"/> -->
</ExeHost>
</EntryPoint>
</CodePackage>
<!-- Config package is the contents of the Config directoy under PackageRoot that contains an
independently-updateable and versioned set of custom configuration settings for your service. -->
<ConfigPackage Name="Config" Version="1.0.0" />
<Resources>
<Endpoints>
<!-- This endpoint is used by the communication listener to obtain the port on which to
listen. Please note that if your service is partitioned, this port is shared with
replicas of different partitions that are placed in your code. -->
<Endpoint Name="UnrealGuestTypeEndpoint" Port="7777" Protocol="udp" />
</Endpoints>
</Resources>
</ServiceManifest>
1.You seem to be missing the service endpoint configuration.
<Resources>
<Endpoints>
<!-- This endpoint is used by the communication listener to obtain the port on which to
listen. Please note that if your service is partitioned, this port is shared with
replicas of different partitions that are placed in your code. -->
<Endpoint Name="ServiceEndpoint" Port="7777" />
</Endpoints>
</Resources>
UDP isn't supported for probes on the load balancer. So, expose a second service endpoint that uses tcp, just as a health endpoint.

What do the EndPoints configure in the ServiceManifest of an Service Fabric Service?

We have a Service Fabric Service project with multiple services: Actors, Stateful services and Stateless services combined into one ServiceManifest.
Two stateful services did not work: the constructors were called, the communicationlisteners (through remoting) were created, but the RunAsync method was not called.
After removing the endpoint listing from the ServiceManifest.xml the services started working again. But now we are left wondering why and how this works. Could someone explain?
To illustrate, the relevant section was
<Resources>
<Endpoints>
<Endpoint Name="WebServiceEndpoint" Type="Input" Protocol="http" Port="80" />
<Endpoint Name="StatelessServiceEndpoint1" Type="Input" Protocol="http" Port="10101" />
<Endpoint Name="ActorServiceEndpoint1" />
<Endpoint Name="ActorServiceReplicatorEndpoint1" />
<Endpoint Name="ActorServiceEndpoint2" />
<Endpoint Name="ActorServiceReplicatorEndpoint2" />
<Endpoint Name="ActorServiceEndpoint3" />
<Endpoint Name="ActorServiceReplicatorEndpoint3" />
<Endpoint Name="ActorServiceEndpoint4" />
<Endpoint Name="ActorServiceReplicatorEndpoint4" />
<Endpoint Name="StatefulServiceEndpoint1" Type="Input" Protocol="http" />
<Endpoint Name="StatefulServiceReplicatorEndpoint1" />
<Endpoint Name="StatefulServiceEndpoint2" Type="Input" Protocol="http" />
<Endpoint Name="StatefulServiceReplicatorEndpoint2" />
<Endpoint Name="StatelessServiceEndPoint2" Type="Input" Protocol="http" />
</Endpoints>
</Resources>
After changing it to this
<Resources>
<Endpoints>
<Endpoint Name="WebServiceEndpoint" Type="Input" Protocol="http" Port="80" />
<Endpoint Name="StatelessServiceEndpoint1" Protocol="http" />
<Endpoint Name="ActorServiceReplicatorEndpoint1" />
<Endpoint Name="ActorServiceReplicatorEndpoint2" />
<Endpoint Name="ActorServiceReplicatorEndpoint3" />
<Endpoint Name="ActorServiceReplicatorEndpoint4" />
<Endpoint Name="StatefulServiceReplicatorEndpoint1" />
<Endpoint Name="StatefulServiceReplicatorEndpoint2" />
</Endpoints>
</Resources>
everything worked. But why?
EDIT
The complete ServiceManifest is this:
<?xml version="1.0" encoding="utf-8"?>
<ServiceManifest Name="Service" Version="1.0.0"
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>
<StatefulServiceType ServiceTypeName="ActorService1Type" />
<StatefulServiceType ServiceTypeName="ActorService1Type" HasPersistedState="true" />
<StatefulServiceType ServiceTypeName="ActorService3Type" />
<StatefulServiceType ServiceTypeName="ActorService4Type" HasPersistedState="true" />
<StatefulServiceType ServiceTypeName="StatefulService1Type" HasPersistedState="true" />
<StatefulServiceType ServiceTypeName="StatefulService2Type" HasPersistedState="true" />
<StatelessServiceType ServiceTypeName="StatelessService1Type" />
<StatelessServiceType ServiceTypeName="StatelessService2Type" />
<StatelessServiceType ServiceTypeName="WebServiceType" />
</ServiceTypes>
<CodePackage Name="Code" Version="1.0.0">
<SetupEntryPoint>
<ExeHost>
<Program>Setup.exe</Program>
</ExeHost>
</SetupEntryPoint>
<EntryPoint>
<ExeHost>
<Program>Service.exe</Program>
</ExeHost>
</EntryPoint>
</CodePackage>
<ConfigPackage Name="Config" Version="1.0.0" />
<Resources>
<Endpoints>
<Endpoint Name="WebServiceEndpoint" Type="Input" Protocol="http" Port="80" />
<Endpoint Name="StatelessServiceEndpoint1" Protocol="http" />
<Endpoint Name="ActorServiceReplicatorEndpoint1" />
<Endpoint Name="ActorServiceReplicatorEndpoint2" />
<Endpoint Name="ActorServiceReplicatorEndpoint3" />
<Endpoint Name="ActorServiceReplicatorEndpoint4" />
<Endpoint Name="StatefulServiceReplicatorEndpoint1" />
<Endpoint Name="StatefulServiceReplicatorEndpoint2" />
</Endpoints>
</Resources>
</ServiceManifest>
Hard to know what happened in your initial reported case since there's no specific error or error message to work off of, but usually this is port conflicts when you end up sharing ports that you don't really want to or which can't be shared, or port exhaustion.
The endpoint resource in your service manifest is mainly for times when:
you want SF to help with allocating communication resources like ports for your services
you want SF to help configure those resources:
Allocating some port and consistently assigning it to some set of workloads
Punching a hole in the local firewall
Setting up a URLACL (relevant to http on windows through http.sys only)
Setting up and configuring certs to enable secure communication (same caveat)
In general you're free to ignore the endpoint resource if you don't need/want the help, since SF really is expecting the service code to do it's setup. In cases where you're not really using SF's programming models then the endpoint resource is more important since it's how you communicate to SF what your endpoints are.
The behavior you get really depends on the transport you're using, as well as the OS's dynamic port range and the Application port range that you've defined, as well as what the service code actually does.
https://learn.microsoft.com/en-us/azure/service-fabric/service-fabric-cluster-fabric-settings#section-name-fabricnode
Let's say you're setting up an http communication listener in your service like so, and walk through a few examples of what happens when you define and endpoint in your manifest or don't.
1) Let's say you put nothing in your service manifest about endpoints. This means that effectively you're specifying 0 as the port in code. In this case SF's not doing any allocation or management. The port is getting assigned by the OS from the OS dynamic port range. The port that actually gets assigned will be different for each service instance listener. This should work as a reasonable default choice in most scenarios.
2) Let's say you're specifying an endpoint in the manifest and not specifying any port at all, i.e.:
<Endpoint Name="HealthServiceEndpoint"/>
In this case, the port that is assigned will come from the SF application port range. It will be the same for any service instances hosted in the same process, but different across processes. (So it matters if you are using the Exclusive or Shared process hosting model) This also presumes that reusing the port is supported for your transport. Most transports don't (like http on via Kestrel in .NET, TCP under most cases), but there are some notable examples (http.sys based http transports on Windows like WebListener/HttpSys, tcp via net.tcp in WCF probably a few others).
3) Let's say you're specifying an endpoint in the service fabric manifest and explicitly specifying 0 for that port i.e.:
<Endpoint Name="HealthServiceEndpoint" Port="0" Protocol="http"/>
In this case the port that gets assigned will be from the OS dynamic port range, and it will end up the same/shared for any service instances hosted in the same process that use that endpoint. The port will be different across processes. (So again it matters if you are using the Exclusive or Shared process hosting model)
4) Naturally if the endpoint is specified and a specific port is specified, that port will be used for all service instances both within and across processes. This somewhat implicitly assumes that such sharing is going to work, which again depends on your transport and platform, or that you're never planning on running more than one instance of the service on this node.
Other trivia:
the "transport" element mainly determines whether SF registers your url with http.sys on windows or configures certificates to secure traffic (most of this can be done within your service code or a SetupEntryPoint).
as of this writing Type is ignored (this is a holdover from an older version of SF)
PathSuffix is used to create a default uri fragment that gets appended to the IP and port assigned by the platform. This is used in cases where there's code not using SF's listener APIs that sets up some listener on a different path like /api/value, like a the code inside a container might do.

Service Fabric: are multiple service types allowed in ServiceManifest.xml

I'm trying to register multiple service-fabric services within a single exe (ServiceRuntime.RegisterServiceAsync). Is this supported? If so, how would I configure them?
Eg: ServiceManifest.xml supports multiple StatelessServiceType elements within ServiceTypes:
<?xml version="1.0" encoding="utf-8"?>
<ServiceManifest Name="EchoGatewayPkg"
Version="1.0.0"
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>
<StatelessServiceType ServiceTypeName="Service1Type" >
</StatelessServiceType>
<StatelessServiceType ServiceTypeName="Service2Type" >
</StatelessServiceType>
</ServiceTypes>
...
and ApplicationManifest.xml does not support multiple StatelessService elements within DefaultServices/Service:
<?xml version="1.0" encoding="utf-8"?>
<ApplicationManifest xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ApplicationTypeName="EchoServiceType" ApplicationTypeVersion="1.0.0" xmlns="http://schemas.microsoft.com/2011/01/fabric">
<Parameters>
<Parameter Name="Service1_InstanceCount" DefaultValue="1" />
<Parameter Name="Service2_InstanceCount" DefaultValue="1" />
</Parameters>
<ServiceManifestImport>
<ServiceManifestRef ServiceManifestName="MyServicePkg" ServiceManifestVersion="1.0.0" />
<ConfigOverrides />
</ServiceManifestImport>
<DefaultServices>
<Service Name="MyService1">
<StatelessService ServiceTypeName="Service1Type" InstanceCount="[Service1_InstanceCount]">
<SingletonPartition />
</StatelessService>
</Service>
<Service Name="MyService2">
<StatelessService ServiceTypeName="Service2Type" InstanceCount="[Service2_InstanceCount]">
<SingletonPartition />
</StatelessService>
</Service>
</DefaultServices>
</ApplicationManifest>
Hence, this effectively spawns 2 processes, and each process' activation-context has both default service types listed (I would have expected only one with this configuration).
Any suggestions (on how to configure multiple service types within a single exe) or clarifications are welcome.
Disregarding default services for a second..
Yes, this is how you get multiple service types to share a host process. You're seeing 2 processes because Service Fabric is placing those two service instances on different nodes and each one needs a host process. Try creating each service with InstanceCount="-1" to see the two types share host processes.
OK, back to default services. This is inherently confusing because application manifest and service manifest are only meant to describe type information, not instance information. But in order to create service instances by default when an application instance is created, you have to specify, declaratively, the instances and their parameters. So what you see under default services there in your example is the XML equivalent of:
PS > New-ServiceFabricService -Stateless -PartitionSchemeSingleton -InstanceCount 1 -ApplicationName fabric:/EchoService -ServiceName fabric:/EchoService/MyService1 -ServiceTypeName Service1Type
PS > New-ServiceFabricService -Stateless -PartitionSchemeSingleton -InstanceCount 1 -ApplicationName fabric:/EchoService -ServiceName fabric:/EchoService/MyService2 -ServiceTypeName Service2Type
So it doesn't make sense to have more than one StatelessService element in the Service element, because you're defining the service instances you want to create, along with the type and version of the service instance.
And just for posterity, this is the registration code that goes with the service manifest you posted:
internal static class Program
{
private static void Main()
{
try
{
ServiceRuntime.RegisterServiceAsync("Service1Type",
context => new Stateless1(context)).GetAwaiter().GetResult();
ServiceRuntime.RegisterServiceAsync("Service2Type",
context => new Stateless2(context)).GetAwaiter().GetResult();
Thread.Sleep(Timeout.Infinite);
}
catch (Exception e)
{
ServiceEventSource.Current.ServiceHostInitializationFailed(e.ToString());
throw;
}
}
}
}

How do I configure local cluster for addtional node types

I have a cluster configuration with two Node Types specified in the ServiceManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<ServiceManifest Name="MKopa.M2M.ConfigurationPkg"
Version="1.0.0"
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.
This name must match the string used in RegisterServiceType call in Program.cs. -->
<StatelessServiceType ServiceTypeName="ConfigurationType">
<PlacementConstraints>(NodeType == Internal)</PlacementConstraints>
</StatelessServiceType>
</ServiceTypes>
<!-- Code package is your service executable. -->
<CodePackage Name="Code" Version="1.0.0">
<EntryPoint>
<ExeHost>
<Program>MKopa.M2M.Configuration.Service.exe</Program>
</ExeHost>
</EntryPoint>
</CodePackage>
<!-- Config package is the contents of the Config directoy under PackageRoot that contains an
independently-updateable and versioned set of custom configuration settings for your service. -->
<ConfigPackage Name="Config" Version="1.0.0" />
<Resources>
<Endpoints>
<!-- This endpoint is used by the communication listener to obtain the port on which to
listen. Please note that if your service is partitioned, this port is shared with
replicas of different partitions that are placed in your code. -->
<Endpoint Name="ServiceEndpoint" />
<Endpoint Name="HttpEndpoint" Protocol="http" Port="8081"/>
</Endpoints>
</Resources>
</ServiceManifest>
My issue that this causes the deployment to the local cluster to fail as this NodeType doesn't exist in the Local Cluster.
I've seen mention of the cluster.xml file and I've found it but making changes to it doesn't seem to have any effect. I've tried a reset, start and stop but the reset overrides the changes.
Here's is hoping that the answer is not starting the services dynamically :-)
I don't know how it works while the cluster is running, but I was able to do it by re-installing the local cluster. These were my steps:
Go to C:\Program Files\Microsoft SDKs\Service Fabric\ClusterSetup\
Uninstall the existing cluster by calling .\CleanCluster.ps1
Create a backup of the file C:\Program Files\Microsoft SDKs\Service Fabric\ClusterSetup\NonSecure\ClusterManifestTemplate.xml
Now you can adjust this file and add placement properties to every node:
<NodeType ...>
<Endpoints>...</Endpoints>
<PlacementProperties>
<Property Name="NodeType" Value="Internal" />
</PlacementProperties>
</NodeType>
Re-create the cluster by calling .\DevClusterSetup.ps1