deployster icon indicating copy to clipboard operation
deployster copied to clipboard

Wildcard idea: Introduce "apps"

Open ivanvanderbyl opened this issue 10 years ago • 2 comments

After thinking about the higher level use-cases we have, and reading about some of the other solutions in this space, something I found in Mesosphere's Marathon is the concept of "Apps". I think a couple of ideas here could be useful for composing what we deploy.

I brought up the idea of adding extra details to a deployment in an earlier issue to apply the router config and health checks. The awkward part is having to handle those details on each deploy. So adding Apps would allow us to describe the deployment of a service, initiate a first deploy, and allow future deployments with minimal configuration.

Here's an example of an app payload:

POST /apps

{
  "app": {
    "id": "my-app",
    "namespace": "/mycompany",
    "image": "ivanvanderbyl/tomster",
    "instances": 3,
    "version": "version1",
    "network": "BRIDGE",
    "cpu": 1.5,
    "memory": 256,
    "cmd": "bundle exec rails server",
    "port_mappings": [
      {
        "container_port": 3000,
        "host_port": 0,
        "protocol": "TCP"
      }
    ],
    "health_checks": [
      {
        "protocol": "HTTP",
        "path": "/health",
        "grace_period_seconds": 3,
        "interval_seconds": 10,
        "port_index": 0,
        "timeout_seconds": 10,
        "max_consecutive_failures": 3
      }
    ],
    "dependencies": [
      "/mycompany/postgres",
      "/mycompany/redis"
    ],
    "conflicts": ["/mycompany/*"],
    "upstream": "Host('example.com') && Path('/')"
  }
}

This would use CoreOS to schedule the deployment of 3 instances. It would set up the necessary routes in the router in use. In this example I used the routing language of Vulcan, however this could easily be translated to Nginx or HA, as the route parser is a standalone library.

health_checks

Health checks could be implemented as a plugin, and read this configuration from etcd. It would probably make sense to implement this as a sidekick process.

dependencies

Describes the services which must be running to support this app, which controls restart order, and bring up a whole stack in order. If /my-app depends on /postgres, then the launch order will be /postgres, then /my-app.

The other use case of dependencies would be for creating the networking fabric in flannel to associate all these services.

conflicts

Essentially sets the conflict option in fleet service when launching.

upstream

Describes the routing logic to send public traffic to this app.

Future deployments could the be as simple as:

POST /apps/my-app/deployments

{
  "deploy": {
    "version": "version2",
    "instances": 5
  }
}

ivanvanderbyl avatar Apr 01 '15 03:04 ivanvanderbyl

I like this idea and I think for deployster to truly be usable, many of these things will need to be supported. Just a couple thoughts:

  • The biggest differentiator that I see between Deployster and something like Marathon or Kubernetes is that Deployster should aim for simplicity and conventions wherever it can. To that end, I think deployments should be possible with the current simplicity, but allow for conventions to be overridden where necessary. If you follow conventions, you likely wouldn't need to specify ports or health checks or commands.
  • You shouldn't need to create an app before you can deploy a service. Deploying a new service should implicitly create a service if necessary.
  • I'm not sure we should differentiate between service or app. In your example, the only difference is that one has a bare configuration and the other is fully configured. Whether we call then "services" or "apps," I think both the simple version and the fully configured version should be the same resource/concept.
  • If we start implementing this, we should prioritize a list of things we want to support. Out of the example payload, the things I'd be interested in first would probably be upstreams, dependencies, and conflicts.

Does that make sense? Agree/disagree?

bmorton avatar Apr 01 '15 08:04 bmorton

I agree that we should be more about simplicity and convention for sure.

Let me refactor this a bit, I want to explore some other use cases, namely using deployster to deploy plugin services, so things like the router and health checks can be deployed the same way as everything else/make everything a first class citizen.

In my example above services and apps are essentially the same thing. The part i'm having trouble grappling with is how to handle the configuration of services which don't have/need to be routed, like sidekiq workers for example. Other considerations like restarting services when their configuration changes in etcd would be nice as well. We could have a convention around a key prefix which does this perhaps.

ivanvanderbyl avatar Apr 01 '15 15:04 ivanvanderbyl