Warm/active server setup with SQL always on - only wish to deploy once

I’ve got a deployment process that currently works fine in all our existing single-server environments.
However, we’re trying to add a new environment that has SQL server installed in an always on configuration, across two servers.
both servers have tentacle installed and a running as separate instances (not set as a clustered service, for reasons).

We need to deploy a database backup to that instance, restore it, and run a dacpac against it.
All of this works fine, except that currently it does it twice - one for the first db server machine, and again for the second machine.

we need to have both machines configured in octopus, as it’s possible that one server will go down and may not be available during deployment.

I initially thought I could separate them out with “primary” and “secondary” roles, but then found roles to be “or” rather than “and”.

I then wrote a script that runs at the start of the deployment process that checks if the primary node is online, and if it was, set the “isDisabled” property to true for the secondary node and vice versa.
Whilst this did set the machine disabled state correctly, the currently running deployment didn’t pay attention to the change and continues running on both servers.
(If I restart the process, it does pay attention, as it’s already disabled).

I then found the “ExcludedMachineIds” property on the Deployment object, and attempted to update that accordingly, but I get a 405 (not allowed) error whenever I try to set it, so I assume you can’t set it after creation.

I created a stackoverflow question that contains the scripts and some further explanation here https://stackoverflow.com/questions/44776103/octopusdeploy-sql-always-on-deployment

Any help would be appreciated.

Hi Ian,

Thanks for getting in touch. If you configure this step as a rolling deployment with a window of 1 (https://octopus.com/docs/patterns/rolling-deployments#Rollingdeployments-Configuringarollingdeployment) the step will run on the two machines sequentially, rather than in parallel, you can then set an Output Variable (https://octopus.com/docs/deploying-applications/variables/output-variables) when you deploy to one of the machines, and you will be able to check to see if that Output Variable has already been set.

So assuming you’re just using a PowerShell script step at the moment at the start you would have a check like:

If ( $OctopusParameters["Octopus.Action[Deploy Script Name].Output.AlreadyRun"] ) {
    write-host "Already run, exiting..."
    exit 0
}

and at the end of your deployment script you would do:

Set-OctopusVariable -name "AlreadyRun" -value "true"

The trick is making sure the run on each machine is sequential, as Output Variables are processed on the Octopus Server after the step completes on each machine, and the result is only available for machines/steps that kick off after that.

I hope that helps.
Mark

Hi Mark,

Unfortunately, we’re not talking about a single step, but an entire deployment process.

I’ll look into this, but Ideally, I need to find a way to apply this to an entire deployment process, and to not individual steps

For reference, here’s a screenshot of our process (sorry for the redaction, but company policy :/)

Hi Ian,

I think the best we can do in that case is right at the start (I guess in your DB Server Health script?) decide which server the following steps need to run in, and write that value to an output variable. Perhaps write the machine name or just some value that you can compare against a project variable you scope differently on each machine. Then in each of the other script steps check that output variable against the Octopus.Machine.Name variable.

In the deploy steps you can turn on the Custom Scripts feature (https://octopus.com/docs/deploying-applications/custom-scripts#Customscripts-Scriptsinpackagestepsscripts-configured-in-steps) and add a PreDeploy script that does the check, and if you don’t want to proceed do:

Set-OctopusVariable -name 'Octopus.Action.SkipRemainingConventions' -value 'True'

which will cause the rest of that step to be skipped. Note that it won’t skip the rest of the child steps so unfortunately you’ll have to do this on each of your three deployment child steps. Unfortunately packages will still be transferred and unzipped, but the the deployment won’t proceed after that.

A bit of repetition there, so not ideal, but I think it will achieve what you are after?

Regards,
Mark

Hi Mark,

that sounds like that might work.
As you say, a bit repetitive, and perhaps a chance for some improvement there for Octopus (pre-deploy scripts in parent/container steps?)

I’ll give it a go this afternoon and see what I can do.

Appreciate the help.

Cheers,
Ian