Update: Multi-tenant deployments will be shipping as part of Octopus Deploy 3.4 and Beta 2 has been released! See the 3.4 Beta 2 blog post for the latest information.
Update: We have revisited this RFC based on some compelling customer feedback! Read the updated RFC proposing Tenant as a first-class concept...
Octopus Deploy is designed to deploy software releases, and promote them through a series of environments with repeatable results. Octopus models this typical scenario nicely, but it doesn't scale well for multi-tenant applications. Let's consider the example discussed in our guidance for multi-tenant deployments using Octopus Deploy...
NameBadge make HR software for large corporate customers. They provide the software as a SaaS offering to their customers, and host the web site and associated services for them. Due to how the application is architected, for each customer, they deploy a different SQL database, a copy of an ASP.NET website, and a copy of a Windows Service.
The key issue in this scenario is that the same components need to be deployed multiple times, one for each end-customer, which makes it different from the scenarios Octopus is typically designed to handle.
To manage this kind of situation today we make three recommendations:
- consider architectural changes to enable shared hosting which has many benefits beyond deployments
- model deployments as environment-per-tenant which is our recommended solution if you cannot solve multi-tenancy architecturally
- model deployments as project-per-tenant which a reasonable compromise if you want to customise the deployment process heavily (this is less relevant with the introduction of Channels in Octopus 3.2)
Sadly both environment-per-tenant and project-per-tenant scale poorly in Octopus and that is the problem we would like to solve, starting with this RFC!
We will primarily concentrate on environment-per-tenant in this RFC since it is by far the most popular method used today
This is a big RFC, but it's also a big set of features! We encourage you to take the time to understand what we're proposing, how it will affect your situation, and help us steer!
- Multi-tenancy is painful
- What we propose to do about multi-tenancy in Octopus Deploy
- It's not just about multi-tenancy
- Wrapping up
- Leave a comment!
After helping many of our customers deal with multi-tenant deployments in Octopus we've seen the following themes:
- Managing lots of environments is difficult
- Adding a new tenant is harder than it needs to be
- There is no single place to manage a customer
- Library variable sets are global
Did we miss something significant? Leave a comment!
The Octopus deployment engine and API can handle thousands of environments. The main complaint from our customers is the user experience for managing more than just a handful of environments is poor.
- The Environments page itself doesn't scale well. Slow load times, no filtering/search, lots of vertical scrolling, and there can be a lot of repeated information when many tenants are hosted on shared infrastructure.
- The Dashboard and Project Overview pages do not scale well. Slow load times, no filtering/search, there is no way to aggregate state, they overflow horizontally and horizontal scrolling is hard.
- Every time you add a new environment you need to update lots of disconnected resources:
- Lifecycle phases that should include the new environment
- Deployment targets/machines that host the software for the new environment
- Accounts that enable deployment to the new environment
- Steps that should be scoped to the new environment
- Variables that should be scoped to the new environment
Based on our recommendation for environment-per-tenant you would need to:
- Create new environment for the tenant called
- Add the
Production-CustomerAenvironment to all required lifecycle(s)
- Add the
Production-CustomerAenvironment to all required account(s)
- Add the
Production-CustomerAenvironment to all required deployment target(s)
- Add the
- Create a new library variable set called
Production-CustomerAto contain the variables specific to the new tenant
- You need to know the full set of variables that are required for the new tenant
- Manually enter each variable name and value being careful not to make a mistake!
- Individually scope all of these variables to the
- For each required project:
- Add the
Production-CustomerAvariable set to all required Project(s)
- Optionally scope deployment step(s) to the
- Deploy the latest release to the
- Add the
If the end-customer requires a staging environment for testing and approving releases to their production environment, you'd have to repeat all of that for
Many of our customers automate the process for creating new tenants via the Octopus API, but that doesn't relieve the pain involved in the ongoing management of tenants over time.
When you are managing a customer with one or more environments you often need to jump around the Octopus user interface with little or no help navigating between pieces of information related to the same customer. Using a naming convention for environments, variable sets, accounts and dedicated machines is a really good idea, but it only gets you so far.
Consider the case where certain important customers should only be managed by a select few people. This can be achieved by setting permissions to the environments and ensuring each variable in the library variable set are scoped properly to the environment. However the library variable set itself is not connected to an environment - it is considered a global resource.
We are proposing to introduce a series of new features across the breadth of Octopus Deploy. We believe these features will benefit the vast majority of our customers in addition to those managing multi-tenant deployments.
- Managing environments as groups using tags
- Managing tenant-specific variables
Have something to say? Leave a comment!
One of most common problems we've discussed so far is dealing with lots of environments, especially that you cannot aggregate environments on the dashboards, and you cannot deal with environments as groups. We propose introducing tags to enable these types of scenarios.
Firstly you would determine which tags you want to make available by creating tag sets in the Library, with the valid list of tags for each tag set. Which tag sets and tags you create is completely up to your discretion. In this example we have created several tag sets each representing different attributes we want to leverage throughout Octopus Deploy.
Note these tags mean very little at the moment - read on to see how each of these different attributes can be leveraged to enable some compelling scenarios.
Octopus Deploy could now make these tag sets available when configuring your environments, and you could configure which actual tags you want applied to each environment. Take a look below and you'll notice the tag sets have been ordered to match the order from the Library. In this example we have tagged the
Production-Tenant-Mobil environment as belonging to the
Production phase, hosted in the
Shared 2 hosting group, with the selected modules, and as a
If you have lots of environments it would be a lot easier if you could manage which tags are applied to environments in bulk. This would enable you to add a new tag set, and very quickly tag all of your environments.
Once you have configured some tag sets and tagged some environments Octopus could aggregate the environments page by tag sets. You could drill directly in to one of the tags and be presented with the matching environments.
After configuring your tags and environments you could configure the dashboards to group by one of the tags. Octopus could aggregate the most important information about the group including the number of environments, overall status of the group with indicators that draw your attention if necessary, the range of releases that have been deployed to the contained environments, and the progress of rolling out the latest release to the contained environments.
In this example we are grouping environments by the phase tag.
Some people might be more interested in customer type or another aggregation.
Similarly the project overview could be grouped by tag showing the release history as it does today.
Clicking on one of the groups could drill in to that group and show more details about the environments in the group. In this example we have clicked on the 3.2.6-3.2.7 to see details of that group. Notice we can now arrange the environments vertically (no more horizontal scrolling) and potentially filter environments by name or another tag. We can also show the release history for each environment, and the
Deploy button so you can upgrade all of the production tenants from the same screen.
When you want to refer to an environment in Octopus Deploy today you need to reference it explicitly, by the environment name. After you have created some tag sets you could start referencing environments by tag. Consider this example of configuring a deployment target as a shared host for multiple environments before tag sets.
With tags you could simplify this deployment target, configuring it once, and allowing Octopus to dynamically resolve which environments apply at runtime.
While referencing environments by tag will be more convenient in many ways, it could become more confusing depending on the complexity of each situation. To help tame the additional complexity we could provide a design view, similar to what we've done for designing the version rules for Channels.
Provided you can reference environments by tag, managing environments in lifecycles, deployment targets and accounts could become more concise and powerful. For example, whenever you add a new environment Octopus could automatically include the environment in the correct deployment targets, lifecycle phases, and accounts according to its tag(s). We just saw an example of a deployment target. In this example we have defined a simple lifecycle where the environments in each phase are driven by the
Phase: * tags.
In this example all environments tagged with
Phase: Production would be authorized to use the
Synergy Production Subscription account.
Scoping variable values would be more convenient if you could scope based on tags. In this example the variable value would be used when we deploy to any of the production tenants defined by the
Phase: Production tag.
Similarly scoping deployment steps could become much simpler. In this example we have customized our deployment process based on several different tags. Firstly we will deploy the Exploration module to tenants tagged with
Module: Exploration. We will also notify the priority support team when a VIP customer, tagged with
Customer type: VIP, has been upgraded. We will also send a tailored email notification to our production tenants, tagged with
Phase: Production, once their deployment has been completed successfully.
The next piece of the puzzle is managing variables specific to each tenant. To deal with this we are planning to let you add variables directly to an environment, but before we get on to that, how do you know which variables need to be added to these environments? Imagine if projects could define the variables required for each different environment, and then each environment could prompt you for the variables it requires. We are proposing to introduce the concept of variable templates.
Variable templates could allow a project to define which variables are required for a successful deployment. We think variable templates will be more manageable as composite parts, just like project variables and library variable sets are today. Each project could define the set of variables that change between environments, optionally including common variable templates from the library. In this example the project has defined two specific variable templates and included two variable set templates from the library.
Each of these variable templates could be defined in a similar fashion to how parameters are defined for a step template, where you can provide the variable name, a label, help text, a default value and an input control type, such as single-line/multi-line text box, sensitive/password box, check box, or drop down.
Many customers doing multi-tenant deployments with Octopus today will create a library variable set for each tenant. We propose to make variables available as part of the environment settings. This way you could specify all of the environment-specific variables as part of the environment itself, and Octopus would automatically and implicitly scope these variables to that environment. When you deploy a release to a particular environment Octopus will automatically merge the variable set from that environment.
Projects are already mapped to environments by way of lifecycles, so it would be natural to assume that an environment will use variable templates from any projects it is linked to via lifecycle.
In this example the Synergy project will be deployed to this environment, and based on the variable templates defined in Synergy, we require:
Standard tenant detailslibrary variable set template
Common storage accountlibrary variable set template
In this case we haven't defined a value for the
MojoDatabase variable and are being prompted to set that value.
Today, variables in Octopus Deploy generally come from projects, library variable sets, or step templates. Adding environments as a source for variables will simplify some aspects of managing variables, but diagnosing problems with variables could become more difficult. We are proposing to add a variable inspector that will make it easier to get an overview of all of the variables in a project, their source, and if there are any problems.
Managing large-scale multi-tenant deployments in Octopus Deploy is clearly painful today. We believe the features proposed in this RFC will benefit the vast majority of our customers. Consider these scenarios:
- Other use-cases similar to multi-tenancy:
- Managing multi-region deployments in the public cloud where you deploy to several geographic regions but consider them all as Production.
- Teams with multiple test engineers where each person has their own test environment.
- Dynamically commissioning/decommissioning feature branch environments for testing new features in isolation before going through the normal Dev/Test/Production lifecycle.
- Starting a new project, you configure the Dev and Test environments. Weeks later you want to add Staging and Production environments, but have forgotten which new variables need to be added for these new environments.
- Simply managing lots of environments and variables for a variety of reasons.
- Wanting to keep your environment-specific variables directly on the environment for reasons of cohesion/authority/security.
- Wanting to add some more structure to your project variables.
With these features in place we hope the pain involved with managing large-scale multi-tenant deployments will be eased significantly. Consider what would be involved in creating a new tenant:
- Create new environment for the tenant called
- Add tags as appropriate
- Enter the prompted variables
- Deploy the latest release(s) to the
What do you think? This is your chance to speak up and help us build the right features for your environment.