kolbasik / aws-service-fabric

Setup Service Fabric on AWS

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Introduction

If you forget a command in powershell :

Get-Command -Module *Fabric*

You need to define the user name and password in order to connect to the service fabric cluster using windows credentials with:

  • Credentials Manager
  • Command line: cmdkey.exe /add:service-fabric.address /user:"domain\user_name" /pass:"password"

Connect to the service fabric cluster using windows credentials:

Connect-ServiceFabricCluster -ConnectionEndpoint 192.168.99.99:19000 -WindowsCredential
Test-ServiceFabricClusterConnection
$ServiceFabricClusterConnection = @{ ConnectionEndpoint = 'service-fabric-949735929.eu-west-1.elb.amazonaws.com:8000' ; WindowsCredential = $True }
Connect-ServiceFabricCluster $ServiceFabricClusterConnection

Get-ServiceFabricApplication
Get-ServiceFabricApplication | Test-ServiceFabricApplication
Get-ServiceFabricApplication | Get-ServiceFabricService
Get-ServiceFabricApplication | Get-ServiceFabricService | Test-ServiceFabricService
Get-ServiceFabricApplication | Get-ServiceFabricService | Get-ServiceFabricPartition

Development

Service Fabric runs applications by default under the LOCAL_AUTHORITY user so

Setup Global Environment Variables

ASPNETCORE_ENVIRONMENT=Development

Setup User Secrets

The secrets are stored at the following path
%APPDATA%\microsoft\UserSecrets\<userSecretsId>\secrets.json

Examples:

  • user : C:\Users\{user}\AppData\Roaming\Microsoft\UserSecrets\{SECRET_ID}\secrets.json
  • service fabric (LOCAL_AUTHORITY) : C:\WINDOWS\system32\config\systemprofile\AppData\Roaming\Microsoft\UserSecrets\{SECRET_ID}\secrets.json

In order to use your own secrets in service fabric for development purpose you can make a symlink to your secrets:

mklink /D /H %WINDIR%\system32\config\systemprofile\AppData\Roaming\Microsoft\UserSecrets %APPDATA%\Microsoft\UserSecrets

Reverse Proxy

ASP.NET Core

Docker

Service Fabric are not able to redirect requests to the docker container which locates on the same box due to Windows NAT limitation. There is a workaround for it just to use placement-constraints to deploy docker images on another boxes than reverse proxy.

Deployment

Simple Deployment Pipeline

Connect-ServiceFabricCluster -ConnectionEndpoint 'idealcluster.westus.cloudapp.azure.com:19000'
Copy-ServiceFabricApplicationPackage -ApplicationPackagePath . -ImageStoreConnectionString "fabric:ImageStore" -ApplicationPackagePathInImageStore "ActorTicTacToeApplicationType"
Register-ServiceFabricApplicationType -ApplicationPathInImageStore "ActorTicTacToeApplicationType"
New-ServiceFabricApplication "fabric:/ActorTicTacToeApplication" "ActorTicTacToeApplicationType" "1.0.2"
#Remove-ServiceFabricApplication "fabric:/ActorTicTacToeApplication"

Continuous Integration

build.bat file

call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Common7\Tools\VsMSBuildCmd.bat"

for /f %%f in ('dir /s/b *.sln') do MSBuild.exe -t:Clean,Restore,Build /p:Configuration=Release /p:Platform="x64" %%f
for /f %%f in ('dir /s/b *.sfproj') do MSBuild.exe -t:Package /p:Configuration=Release /p:Platform="x64" %%f

pushd %CD%
for /f %%f in ('dir /s/b pkg') do (
    cd %%f\..
    xcopy /I /F /V /Y PublishProfiles\*.xml pkg\Release\PublishProfiles
    xcopy /I /F /V /Y ApplicationParameters\*.xml pkg\Release\ApplicationParameters
)
popd

Continuous Delivery

deploy.ps1 file

<#
.SYNOPSIS
Deploys a Service Fabric application type to a cluster.

.EXAMPLE

Connect-ServiceFabricCluster -ConnectionEndpoint service-fabric-949735929.eu-west-1.elb.amazonaws.com:8000 -WindowsCredential
.\build.ps1 -UseExistingClusterConnection
#>
param (
    [Switch]
    $UseExistingClusterConnection = $true,

    [String][ValidateSet('Release', 'Debug')]
    $Configuration = 'Release',

    [String]
    $PublishProfileFile = "Cloud.xml",

    [Hashtable]
    $ApplicationParameters = @{},

    [String][ValidateSet('None', 'ForceUpgrade', 'VetoUpgrade')]
    $OverrideUpgradeBehavior = 'None',

    [String][ValidateSet('Never', 'Always', 'SameAppTypeAndVersion')]
    $OverwriteBehavior = 'Never',

    [Switch]
    $DeployOnly = $false,

    [Switch]
    $SkipPackageValidation = $false,

    [Switch]
    $UnregisterUnusedApplicationVersionsAfterUpgrade = $false
)

Get-ChildItem -Recurse -Directory -Filter pkg | ForEach-Object {
    $DIR = $_.Parent.FullName
    Write-Host "Deploying $DIR"
    & "$DIR\Scripts\Deploy-FabricApplication.ps1" `
        -UseExistingClusterConnection:$UseExistingClusterConnection `
        -ApplicationPackagePath "$DIR\pkg\$Configuration" `
        -PublishProfileFile "$DIR\pkg\$Configuration\PublishProfiles\$PublishProfileFile" `
        -ApplicationParameter:$ApplicationParameters `
        -OverrideUpgradeBehavior $OverrideUpgradeBehavior `
        -OverwriteBehavior $OverwriteBehavior `
        -DeployOnly:$DeployOnly `
        -SkipPackageValidation:$SkipPackageValidation `
        -UnregisterUnusedApplicationVersionsAfterUpgrade $UnregisterUnusedApplicationVersionsAfterUpgrade `
        -ErrorAction Stop
}
Connect-ServiceFabricCluster -ConnectionEndpoint 'service-fabric-949735929.eu-west-1.elb.amazonaws.com:8000' -WindowsCredential
$ApplicationParameters = @{ AppSettings_ProjectKey="zxcasd" ; AppSettings_ClientId="gF47ep" ; AppSettings_ClientSecret="qwerty123" }
.\deploy.ps1 -UseExistingClusterConnection -PublishProfileFile "Cloud.xml" -ApplicationParameters $ApplicationParameters

Infrastructure

Provisioning Script

netsh advfirewall firewall set rule group="File and Printer Sharing" new enable=Yes

New-NetFirewallRule -DisplayName "Allow inbound ICMPv4" -Direction Inbound -Protocol ICMPv4 -IcmpType 8 -RemoteAddress Any -Action Allow
New-NetFirewallRule -DisplayName "Allow inbound Service Fabric Int" -Direction Inbound -Protocol TCP -LocalPort 135,137-139,445 -RemoteAddress Any -Action Allow
New-NetFirewallRule -DisplayName "Allow inbound Serfice Fabric Ext" -Direction Inbound -Protocol TCP -LocalPort 19000-19003,19080-19081,20001-21000 -RemoteAddress Any -Action Allow

Set-Service -Name RemoteRegistry -StartUpType Automatic
Start-Service -Name RemoteRegistry
Get-Service -Name RemoteRegistry

Invoke-WebRequest "http://go.microsoft.com/fwlink/?LinkId=730690" -OutFile c:\sf.zip
#Start-BitsTransfer -Source "http://go.microsoft.com/fwlink/?LinkId=730690" -Destination c:\SF.zip
Expand-Archive c:\sf.zip c:\sf

Create Cluster

  1. Make a copy of the ClusterConfig.Windows.MultiMachine.json example configuration file.
    xcopy .\ClusterConfig.Windows.MultiMachine.json .\ClusterConfig.AWS.json*
  2. Replace the $.nodes.*.iPAddress fields with the machine names
  3. Add the following object to the $.properties.fabricSettings array:
    {
        "name": "FileStoreService",
        "parameters": [
            {
                "name": "AnonymousAccessEnabled",
                "value": "true"
            }
        ]
    }
  4. Add the users who have permissions to work with the cluster
  5. The last step to create a cluster is to execute the powershell script
    .\CreateServiceFabricCluster.ps1 -ClusterConfigFilePath .\ClusterConfig.AWS.json -AcceptEULA

Maintenance

Add a new node to the cluster

.\AddNode.ps1 -NodeName 'vm3' -NodeType 'NodeType0' -NodeIpAddressOrFQDN "$Env:COMPUTERNAME" -UpgradeDomain 'UD3' -FaultDomain 'fd:/dc1/r3' -ExistingClientConnectionEndpoint '192.168.5.46:19000' -AcceptEULA
# or using Add-ServiceFabricNode directly

Remove the existing node from the cluster

.\RemoveNode.ps1 -ExistingClientConnectionEndpoint 192.168.5.251:19000
# or using Remove-ServiceFabricNode directly

Upgrade the cluster configuration

Get-ServiceFabricClusterConfiguration
Start-ServiceFabricClusterConfigurationUpgrade -ClusterConfigPath .\ClusterConfig.AWS.json

Restart the node

Restart-ServiceFabricNode -NodeName vm3 -CommandCompletionMode Verify

Scale the service

Update-ServiceFabricService -Stateful 'fabric:/System/ImageStoreService' -MinReplicaSetSize 3 -TargetReplicaSetSize 3 -Force
Repair-ServiceFabricPartition -All -Force

Sample of rollback an application

$app = Get-ServiceFabricApplication -ApplicationName "fabric:/xxx"
$table = @{}
$app.ApplicationParameters | ForEach-Object { $table.Add($_.Name, $_.Value) }
Start-ServiceFabricApplicationUpgrade -ApplicationName "fabric:/xxx" -ApplicationTypeVersion 1.0.0 -ApplicationParameter $table -HealthCheckStableDurationSec 60 -UpgradeDomainTimeoutSec 1200 -UpgradeTimeout 3000 -FailureAction Rollback -Monitored 

Sample of how to add a new user to a cluster:

function Add-ServiceFabricUser([bool]$isAdmin=$False, [Parameter(Mandatory=$True)]$identity) {
    $configPath = ".\ClusterConfig.$((Get-Date).Ticks).json"
    $config = Get-ServiceFabricClusterConfiguration | ConvertFrom-Json
    $config.Properties.Security.WindowsIdentities.ClientIdentities = $config.Properties.Security.WindowsIdentities.ClientIdentities + [PsCustomObject]@{ IsAdmin = $isAdmin; Identity = $identity }
    $config.ClusterConfigurationVersion = [version]$config.ClusterConfigurationVersion | foreach { (New-Object -TypeName System.Version -ArgumentList $_.Major, $_.Minor, $_.Build, ($_.Revision + 2)).ToString() }
    $config | ConvertTo-Json -Depth 50 | Set-Content -Path $configPath
    Start-ServiceFabricClusterConfigurationUpgrade -ClusterConfigPath $configPath
    return Get-ServiceFabricClusterConfigurationUpgradeStatus
}

Find a mistake to fix configuration on a live

cd C:\ProgramData\SF
Get-ChildItem -Path . -Include *.json,*.xml -Recurse | Select-String -Pattern '[CONTENT]' -AllMatches | group path | select name

About

Setup Service Fabric on AWS