Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Concept of making the broker aware of managed sharable (IE) multi tenant services #979

Closed
maleck13 opened this issue Jun 5, 2018 · 11 comments

Comments

@maleck13
Copy link
Contributor

maleck13 commented Jun 5, 2018

Feature:

Many services are heavy weight and designed to allow multiple tenants to access them. A concrete example of this is Keycloak.

Usecase: As a managed service provider ( think hosted service, enterprise operations team), I do not want to require any user who wants access to use this shared managed service to need to know the specific and potentially restricted information: (admin level) credentials, the service instance id, the namespace it is in etc, that the provisioning bundle potentially needs in order to setup the required resources. I also want this process as automated as possible without the user needing to find and ask me to set it up for them.

Obviously this could be done in a different more specialized broker, but I want to discuss the option of bringing the concept in a generic format to the the automation broker.

Current State

We have achieved the idea of a "shareable" service by allowing a developer to tick a box during provision and provide the URL and admin credentials of the sharable service. The provision bundle sees these parameters and instead of provisioning a full instance instead sets the user up as a tenant.
The main drawback to this is that the user looking to make use of the already provisioned service needs to know the credentials to allow the APB to provision him a new tenant on the existing service. This has obvious drawbacks in a managed or hosted environment.

Future state
At its most simple, it would be valuable to be able to have an option for specifying a service is sharable in the APB spec. As a very rough example of how it might work:

- sharedServiceConfig:
    maxProvisions: 10
    maxBindings: 30

The result of this would be something along the lines of:

  • first provision sets up a full instance and saves credentials (nothing different than now) and stores that this is an instance of a shared service and can be shared. (relationship between the service id and the service instance id)
  • when a second provision of that ServiceClass happens, the broker knows about the existing ServiceInstance (without the user having to provide that information via params) and looks up the parent credentials these are then made available to the provisoning bundle.

Note
In the next few weeks I will be progressing spikes around this area. If it is something that we feel could be part of this broker, I would be happy to progress a proposal and implementation

@maleck13
Copy link
Contributor Author

maleck13 commented Jun 5, 2018

ping @philipgough @philbrookes

@maleck13
Copy link
Contributor Author

maleck13 commented Jun 5, 2018

suggesting from @mhrivnak hope I have this right from IRC

using two APBs one that provisions the service and one that gives you the slice of the service

From a users perspective we don't want them to have to know any of the information about where the service is or the credentials to access it. They just want to use the service.

Also we can probably do this via the plans option in provision IE

  1. provision new sharable dedicated service
  2. provision slice of sharable dedicated service

But we still have the same issue of the APB provisioning the slice needing to know the credentials and location to of the service it should provision a slice from.

There was mention on IRC of the AWS work. However I presume with that they require some kind of AWS credentials from you and then use the always available and always in one location AWS API. In this case the service may not have been provisioned and also the location of it could be different.

@maleck13
Copy link
Contributor Author

Some thoughts on how I will proceed in the spike bellow. I have a doc on the go currently but wanted to outline some thoughts here for general feedback. There is mention of role checks below. That is where issue 982 originated.

Single APB multiple plans approach

Define Single APB with multiple plans see this gist https://gist.github.com/philbrookes/792ac0b68bfe46d7c436992677271444 with an example APB yaml changes

The plans would allows you to provision either a shared service instance or a slice of a shared service instance.

As shown, the shared service instance plan has configuration to define how many slices of this service are allowed to be provisioned. (This config would be used by the broker and not meant as part of the plan sent back as part of the ClusterServiceClass)

The slice plan has configuration to define how many bindings to the shared service are allowed per provision. (This config would be used by the broker and not meant as part of the plan sent back as part of the ClusterServiceClass)

The total number of bindings allowed is the number of provisions multiplied by the the number of bindings in the "slice" plan. With this approach it would be possible to have multiple slice plans with different numbers of bindings allowed. The maximum bindings overall would then be the the number of provisions multiplied by the highest number of allowed bindings.

If max provisions was 10 and we had 2 plans one with max bindings of 3 and one of max bindings of 7 the overall possible number of bindings would be 70 10(provisions) * 7 (bindings per provision)

Provision Shared Service

When a new shared service plan is provisioned the following would happen:

Provision of Shared Service Slice

When a slice plan is chosen and provisioned the following will happen:

  • The role defined in the APB.yaml plan will be checked on the provisioning user by the broker
  • The shared service resource updated based on the service name.
  • If not found it will fail with an error that states no available shared service found
  • If there is an available shared service instance a count will be done on the slices array in that resource and a check done against the the maxProvisions value in the APB yaml. If above the threshold a clear error returned stating no capacity left in shared service instance.
  • The current service instance id being provisioned will then be added to the array
  • The credentials of the shared service instance will be retrieved and passed to the bundle provisioning the slice
  • The shared service instance id will be stored on the slice service instance object.
  • If the provision fails the serviceinstance id will be removed from the shared service resource

There is more to it than this, but wanted to update from the community meeting last week
ping @jmrodri @shawn-hurley

@johnfriz
Copy link

@maleck13 Can you elaborate a bit on the max bindings concept - not really following the logic here. Are we increasing complexity bringing in number of bindings as well as number of slices?

Could this be simplified by just specifying the criteria on the shared service itself - i.e

  • bindings per provisioned instance
  • max provisions

e.g.

{
    "apiVersion": "v1alpha1",
    "kind": "SharedService",
    "metadata": {
        "name": "dh-keycloak-apb",
        "namespace": "shared",
    },
    "spec":{
      "instances":[{
        "serviceInstanceID":"",
        "maxProvisions":10,  
        "bindingsPerProvision": 20,
      }]
    }
}

^^ for a total of 200 available "slices"?

@philbrookes
Copy link

@johnfriz I believe the original intent of the plans in the apb file, was to allow for users to pay more or less money, for more or less resources on that provision. In that case, I think have a slim-slice with 10 bindings and super-slice with 100 bindings fits into that model better.

With the bindings-per-slice defined in the sharedservice plan that would never be an option.

@johnfriz
Copy link

Thanks @philbrookes & @maleck13 for the clarification - it makes sense now.

However, I think we need both - the sharable service (that will give out slices) needs to define how many slices per instance it will support and how many instances it will provision. This give us the total available slices.

From the plan side, we can certainly define how many slices the plan allows you to provision, but that's separate from the service being able to define / decide how man slices per instance it can support - i.e. I think we will need both, and at least initially, defining slices per shared service provider is probably more important.

@maleck13
Copy link
Contributor Author

maleck13 commented Jun 14, 2018

However, I think we need both - the sharable service (that will give out slices) needs to define how many slices per instance it will support and how many instances it will provision. This give us the total available slices.

@johnfriz I think you may be mixing up slices and bindings here. The shared service plan will define how many slices can be provisioned with the maxProvisions property.
Then any slice plan present will define how many bindings can be made against that slice.
As there is the possibility of multiple plans, the max bindings of a shared service will then be maxSharedServicePlanProvisions * maxSlicePlanBindings

So each slice plan dictates how many bindings are allowed for that plan but the maximum number of overall bindings is a combination of the maxProvisions property defined by the shared service and the highest bindings value across all available slice plans.

@johnfriz
Copy link

@maleck13 - Sorry, I though maxProvisions was how many total instances of the shared service we want to provision. e.g. Say a Keycloak instance can support on average 20 different tenants per instance and we want to be able to support up to 200 tenants, then I would see maxProvisions as 10 (max number of Keycloaks we would ever provision) and slices as 20 (number of tenants per keycloak). I still don't see how we can get away without defining both of these for the sharable service itself.

I'm also a bit confused about "any slice plan present will define how many bindings can be made against that slice." would there not be a 1:1 relationship between bindings and slices - i.e. does each binding not result in a new slice being allocated?

How widely used are plans at the moment? Are we over complicating things by trying to factor in multiple plans at this early stage?

@maleck13
Copy link
Contributor Author

How widely used are plans at the moment? Are we over complicating things by trying to factor in multiple plans at this early stage?

They are used for all provisions. Most things only have one plan though which is named default. From the spec a plan is defined as

Service Plan: The representation of the costs and benefits for a given variant of the service, potentially as a tier.


I'm also a bit confused about "any slice plan present will define how many bindings can be made against that slice." would there not be a 1:1 relationship between bindings and slices - i.e. does each binding not result in a new slice being allocated?

No a slice is a fresh provision based on a plan (without the user needing to know any specific details) that creates a new ServiceInstance resource in the user's namespace. Behind the scenes the APB that runs is handed the credentials of a shared service of the requested type and creates a "slice" of the shared service for that user. So there would be no pods running in the users namespace for the service, but a representation of that service would be present (AKA) the service instance.
So using Keycloak as the example again, provisioning a slice would set up the realm and user for that realm. The secret created during the provision and placed into the user's namepsace would contain the details for this realm and user.

On bindings. You cannot bind to service instance that is not in your namespace. So the provision outlined above sets up the slice and service instance. The user then binds to that service instance. The current suggestion is to allow a limit to be set on the number of bindings that user can create (a benefit of the plan they chose) against that service instance as the binding results in resources being provisioned and potentially signifies capacity being used. However it should be possible to set the number of bindings to unlimited.
So back to the Keycloak example, the binding here would setup a client that can be used from your application and create a secret in your namespace that contains these details ready for you to consume.

Sorry, I though maxProvisions was how many total instances of the shared service we want to provision.

I think this could be named better perhaps maxSlices. The total number of shared service instances allowed to be provisioned is not covered here currently. If we limit who can actually provision the shared instance, then this could be managed by either the operations team or potentially an operator that functions against the shared service CRD

@maleck13
Copy link
Contributor Author

maleck13 commented Jul 3, 2018

After some discussion, it was decided that the broker shouldn't need to know about the number of provisions etc and that the specific problem the broker could potentially solve is the sharing of credentials across service instances

@maleck13
Copy link
Contributor Author

maleck13 commented Jul 3, 2018

Will close this issue as it is no longer relevant to the broker. I will create new issues for any new work around shared secrets and credentials

@maleck13 maleck13 closed this as completed Jul 3, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants