Deploy to dynamically created Azure Service Fabric Cluster or Service Fabric Mesh cluster

Hi Guys,

At the moment we are deploying to on prem Service Fabric cluster, but we want to move to Azure.

We have a powershell script and ARM template that will create the Service Fabric cluster in Azure and my question is what is the best practice way to dynamically add Azure Service Fabric deployment target and then to deploy to it?

In other words how do I hook Octopus in the following process:

  1. Trigger PowerShell script in Azure that will create the SF cluster
  2. Add new ASF deplaoyment target in Azure
  3. Deploy related projects to the newly adde ASF deployment target

I guess what I am asking is, how to acheive Multi-tenantted ASF clusters and deploy to those clusters?

Another option I guess is to use Project triggers and as soon as new ASF cluster is available to deploy to it?.. Also in this case what’s the best way to trigger the cluster creation from Octopus if I want Octopus users to be able to spin a new ASF cluster?

So far I am talking about Azure Service Fabric cluster, but please include Service Fabric Mesh in your answer especially if you have done any work in that direction already…

Thanks,
Emil

Hi Emil,

Thanks for getting in touch.

The dynamic target scenario you are describing is absolutely possible. The best place to start would be reading through the blog post on dynamic infrastructure. In this post, there is a walk-through for Web Apps, but the same principles apply to Azure Service Fabric.

You will need to use the cmdlet for creating an Octopus Service Fabric Deployment Target, this can be run in a post-deploy script in the ARM step (available via Configure Features), plus Automatic Deployment to trigger the application deployment from a different deployment process when the new Service Fabric target gets created and passes a health check.

Hopefully, this helps you.

Regards
Ben

Thanks Ben!

this is exactly the kind of info what I am looking for :smile:

Emil

Hey Ben,

I need a bit of help again :slight_smile:

All going well with the dynamic infrastructure creating ASF cluster & adding ASF deployment target also.

The issue I have now is that during the cluster creation we are using custom domain name with wild card SSL certificate and each newly create cluster is essentially a subdomain.

Because the subdomain is input prompt value in the Octopus project responsible for spinning new ASF cluster later in the actual projects I have a config variable that needs the base URL which I don’t know since the tenant typed it to spin a new cluster. I hope that makes sense.

Here is the scenario:

  1. Tenant creates a release and runs a Octopus project that will create a new cluster for one or more tenants. He is prompted for a value that will be used as cluster name, for example test1-tnt1 where tnt1 is the name of the tenant. The subdomain here is essentially the ClusterName
  2. When the project deployment completes we end up with a cluster name like this: test1-tnt1.mydomain.com
  3. Next the tenant (or each tenant, if step 1 had multiple tenants) will choose what versions of the code to deploy to this new cluster.

My issue is how to work out the ClusterName in the projects that need to deploy to the cluster?

I guess the ASF connection endpoint for the dynamically configured deployment target already has this information… But that will be used once the deployment is triggered and I have a project variable called BaseURL - How can I populate it…

Please suggest best approach I haven’t kept up to date with features in recent releases…

Many Thanks,
Emil

Hi Emil,

Thanks for getting in touch.

Your project variables can contain references to other variables using our variable substitution syntax, so your BaseURL variable could reference your prompted variable.

E.g. If you have a prompted variable called “MyClusterName” that tenants enter at deployment time, you can reference that variable in your project’s BaseURL variable (ahead of deployment time) with a value of #{MyClusterName}. So in your example where the cluster name is part of the domain name, you could write a value for BaseURL like this: {#MyClusterName}.mydomain.com

Would something like that work for you?

Cheers
Mark

Hi Mark,

what throws me off is the fact that the first project where the ASF cluster is created with the prompt value for #{MyClusterName} is a totally separate project from all the other projects that does the deployment after.

In other words in the Cluster creation project I need to create a global cross project Octopus variable for each Cluster-Tenant combination which I have to read later when I am actually deploying to those combinations, for example:

 test1-tnt1.mydomain.com
 test1-tnt2.mydomain.com 
 test1-tnt3.mydomain.com

I end up with the above clusters being created dynamically and I looking at the best Octopus approved solution to update the #{BaseURL} value in the config for projects that let say a tenant (environment owner) will be pushing onto this dynamically created infrastructure. The config in the projects being deployed need to be updated… What is the best way? It looks like I need cross-project global variables?

Hi Emil,

Thanks for the additional information.

We had a talk this morning in the team and our recommended approach in this instance is to consider creating a function as a script module (as that can be shared across your projects).

If your tenants are using prompted variables to create those cluster names, then a BaseURL value in the projects themselves won’t work. Your scripts would instead reference this shared script module function which would reference your prompted variable and create your base URLs from that as required.

We have an example of this in [our dynamic infrastructure blog post] that Ben previously shared(https://octopus.com/blog/dynamic-infrastructure). See the section titled “Create a Script Module”

I hope this helps. Let me know how you go.

Cheers
Mark

Hi Mark,

I appreciate for your response, however I am not sure you understand my question.

Thank you for pointing out the idea about the shared script modue function and the dynamic infrastructure blog article. The script module function example has a parameter called $prefix and in my example this is the prompted value a user types in and the function retunes the unique cluster name that I use similar to the article example.

All is fine unless in any deployment projects you need to get hold of the unique name that was returned by the function during cluster creation and the only unknown is the $prefix parameter the function took when generated the unique name (uknown because the $prefix was user input)…

I guess, I need to create new function that takes no parameters and it works out the uknown value (the user supplied $prefix value). One I can think of is may be using the name of the Deployment target that was dynamically created. Every time a new Cluster is created dynamically a coresponding ASF Deployment target is created and it contains the full cluster name including the value of the $prefix input parameter the user was prompted for… In other words every new cluster has a corresponding deployment target that also has the dynamic cluster name returned by the function also in it’s name and this is what I need to find out when deploying to that cluster…

My question is is this the best way to work out the dynamically generated cluster name?
In this case every dynamically generated cluster has a corresponding deployment target, which name already contains the unique name generated by the function.

When, I try to deploy to a dynamically generated cluster I asume can write a function to substitude the name of teh cluster from the corresponding deployment target and constracu the BaseURL that I need…

I hope all this makes sense - it should be a common scenario when creating dynamic infrastructure…

Thanks,
Emil

Hi Emil,

Sorry for the confusion. I think there are probably some aspects to the blog post which we need to clarify as it may not be immediately obvious. I hope the following helps to clarify things for you.

Infrastructure Provisioning

We can provision infrastructure through a number of ways and you obviously need to know how to deploy to whatever you have provisioned. The means of provisioning can be whatever you like, PowerShell / ARM template as long as a target gets created with a well known role. The target that gets created here contains all the knowledge of where the target exists and how to connect to it.

Target role and context

Naturally a target is only one side of the picture. You also have other things that come into play such as a tenant and environment. It is the combination of these things that allow us to limit a deployment to a specific context, which can happen multiple times such as for multiple tenants. The important thing to note here, is that the role is known beforehand and used as part of the deployment. Associating a given target to a tenant for example would isolate the deployment to that specific cluster that you would be targeting. You don’t need to know the target name in this instance. Another important thing to call out here, is that when creating a target under the context of the tenant, the target will automatically be scoped to that particular tenant.

State, Conventions and Variables

We usually recommend using some form of naming convention based on tenant and or environment in most cases. This in combination with the variables contributed by the target which you can usually see by enabling OctopusPrintVariables would usually get you most of the way. There are however still situations where state needs to be stored/passed between projects and in those cases you can either use additional roles with well-known prefixes such as clustername-xyz where xyz is the prompted value or alternatively use things like Azure tags to store some information. The tagging approach was taken in the tear-down step in the blog post for example.

Deployment and Orchestration

I haven’t really covered much in terms of the deployment side of things, but generally if you have the infrastructure provisioning and deployment as part of a single project the deployment to that infrastructure can be quite seamless as we can limit targets for the correct scope automatically. If things are split up between multiple projects, things do tend to get a bit more tricky as you would have to have some means to trigger a deployment when the infrastructure has been provisioned. In these situations you can make use of the Deploy Release Step as that would allow you to prompt and pass variables to child steps, with the caveat that each child must have at least one release created. The alternative options here would be to either use auto-deploy or to orchestrate the process using our API.

Putting it together

So what would this look like when using the Deploy Release Step as an example? When you create a release it prompts for the variable, then triggers a release for the infrastructure project with the prompted variable passed in. This goes off and provisions the cluster and creates the associated target with the role and scoped to the tenant. It then triggers a release for the deployment which will use the same role and the scoped tenant to provision to the created cluster.

Regards,
Shaun