What do you need from a deployment tool?

Dockyard is hiring someone to build an open source deployment tool for Elixir.

I’m not sure whether it is the same thing José was referring to in his ElixirConf keynote (where he says a deployment/releases tool may be included in core at some point) but that would be really cool!

So, I’m interested in what others need from a deployment tool …and who knows, perhaps whoever is selected to create it will take notes from this thread :003:


Edit:

Please see this post for an update :023:

Edit 2 (Feb 2018)

See this post for another update :023:

8 Likes

Maybe not the same thing José was referring to, but the article does say that the project “will have direct oversign by José Valim.”

Neat stuff.

2 Likes

Would anyone familiar with how Nerve does deployments enlighten the rest of us on what Brian is referring to :)?

2 Likes

We are looking at solving the build tool problem at my company, but not the deployment, as we believe deployment is highly specific to your environment (AWS, a VPS like DO, your own infra, etc etc)

I am not sure a lot can be ported from the Nerves team, but i hope some ideas can.

2 Likes

Although I haven’t deployed an Elixir app yet, I have deployed lots in various other languages and frameworks.

  • Static HTML sites are obviously the easiest - you can generally just upload and that’s it.
  • PHP is not far behind as LAMP is installed on most (hosting) servers by default - again just upload and you are pretty much ready to go.
  • Complexity begins to increase when it comes to Ruby - you could actually just upload your files manually and run bundle (once you’ve installed Ruby - perhaps in addition to a version manager) but generally you’ll end up using a tool like Capistrano, which is great, but can be a pain to set up. It can also make things appear like ‘magic’.

So what would I like to see for Elixir?

Something simple and robust (that will run on standard linux servers). Something not dependent on having VMs/Docker on your dev (or production) machine and something that doesn’t seem too much like magic.

Bonuses would be the ability to do rollbacks, the ability to configure shared folders that persist over builds (for user uploads etc) and exploiting the benefits of Elixir/Erlang such as hot code swapping.

2 Likes

I think Justin mentions it briefly in his conference Keynote - I vaguely recall something about the whole nerves and linux package being just 30mb…

3 Likes

Don’t! I managed to get into a lot of trouble because of having already uploaded A, but B was still the old one but used a function from A. And a client requested B before it got updated. This incident not only led to malformed display at the client side, but an inconsistent database as well.

Since then I do not deploy anything anymore without at least symlink swapping.

3 Likes

Luckily the PHP software I used would not function if there was an install or upgrade script in the admin folder. There was also an on/off switch (read-only mode) and I’m pretty sure I used to use .htaccess to redirect all traffic to a ‘be back soon’ page when carrying out backups (of a fairly large DB).

1 Like

Let’s call it deployex. I would like to use:

  1. install deployex archive like phoenix
  2. mix deployex - command that starts Phoenix server
  3. support for projects - just simple CRUD with directory chooser + validate mix.exs file
  4. support for deploy profiles based on specific rule - for example domain
  5. each deploy profile for specified project have it’s own prepare.sh, before.sh, after.sh and rollback.sh scripts to be runned on deploy machine
  6. each project should have a list of deploy machines with specified profile - fallback to default profile - search by deploy profile rule (again for example based on domain)
  7. allow to deploy more that one compiled version of specified project + ability to easy switch them - in case new version have a bigger problem to solve
  8. this deploy tool should already have defined some profiles for mos t popular services
  9. this deploy tool should already have defined prepare.sh files for most used distrobutions
  10. should be approved by José Valim and community :smiley:

Shell scripts:

  1. prepare.sh: install erlang, elixir and dependencies
  2. bofore.sh: prepare environment before deploy
  3. after.sh: post installation script
  4. rollback.sh: script executed when switching to older version

There were more ideas somewhere in my mind, but need to refresh my slow cache for that. Generally all or almost all ideas in my mind are like super workstations - that you will probably never use 100% of things that it provides (I will need to buy a custom device that will cover all features for one of my bigger projects :smiley:), so if you plan to create something then ping me and I will send you so many ideas that their quantity will discourage you.

:077:

2 Likes

I think it’s important to understand that deployment tooling has to integrate neatly into a very wide variety of environments and use cases, so I don’t agree that a nifty UI based tool is the primary solution (although having such a UI which consumes the underlying tools as a library might be really cool for those preferring that kind of thing). On the easy side, you have deploying to a VM/VPC, AWS/Azure/etc., where the tooling is simple and can be very flexible. Things are still fairly easy, but a little more constrained with deploying to services like Heroku, et al. Then you have people deploying releases via RPM or other package formats, perhaps installing in a VM and creating images for deployment to customer sites. Another group is deploying in an environment running Kubernetes, Mesos/Marathon, or OpenShift for example, and there are a lot of variables. How you deploy depends on whether you do blue/green, A/B deploys, or neither and just push the latest into service immediately. Luckily, Nerves has more or less solved the embedded side of things, so we don’t have to worry about that all that much, but the underlying tools still need to support Nerves. Right now that is Distillery, but if it became another tool, that tool would need to support other tools using some of the lower-level primitives to compose their own solution.

My personal take on this is that there is considerable room for improvement on the build side - making it extremely simple to build a deployment package for another platform, regardless of where you are building from. This should be exposed as one of the “primitives”, since some people will want to take that package and do their own thing with it. I think the build tooling should support generating container images, RPMs, etc., either through plugins or out of the box, making it trivial to choose the format you want to deploy with. On the deployment side, I suspect that those running container orchestration platforms like Kubernetes will use the tooling those systems provide to actually handle deployment, but having a flexible build tool will make it easy to integrate Elixir into the environment. In my own experience, working with Elixir under Kubernetes/OpenShift is already very easy, so there is not much else required here. For those deploying to VMs/VPC or AWS/Azure, this is where better tooling is most needed, and where most tooling currently sits. The biggest issue is that one needs a build machine which matches the target machine, more or less exactly. I suspect what Brian meant in his video is that Nerves allows you to build packages for a variety of hardware all from whatever machine you are currently using, via buildroot and a cross-compilation toolchain. If we could do something similar for general Elixir deployment, it would be a huge improvement over the situation today, as it would alleviate the vast majority of issues newcomers experience. Once you get beyond building a release and getting it to a target, the rest is actually quite pleasant with Elixir. There are still some rough patches with regards to configuration and differences between Mix and releases, but those gaps are closing, slowly but surely. I suspect being able to focus on the problem full-time, these too can be solved more elegantly.

16 Likes

UI could be really useful in case you want to automate some process. I would like to don’t make lots of manual edits of configuration file (deploy configuration + vm.args for each instance). So UI for making profiles (custom environments) could be really useful.

3 Likes

A graphical UI should only be one way of working with the tools though, not the only way. The ideal design then is to build command-line tooling/libraries, which can be used for the actual automation, and provide the graphical UI as an extra tool which integrates with them. This is what I meant by “primary solution” - a UI is something easily built on top of lower level primitives, and the problems which need solving the most are at that lower level.

10 Likes

I have to admit I also didn’t quite understand what part of which deployment process Brian was talking about in the video. Deploying an application is vastly different depending on the target platform.

Should the improvements be about the orchestration of multiple servers on a specific IaaS? Building native packages like RPM or MSI?

Heroku and similar services (e.g. CloudFoundry) all support Docker now, so in my experience, a two-stage build system like mix_docker makes the build process quite manageable.
And for VPS edeliver works reasonably well.

Like @bitwalker already pointed out, the points where things could be made easier are probably related to cross-compilation or providing ERTS versions that are compatible with the target system.

Maybe @bcd765 and @josevalim could to elaborate a bit more where they see the greatest weaknesses at the moment and/or what prompted them to launch the current effort?

2 Likes

I think this sounds like a really interesting project.

I work in a software consultancy, and we’ve started to use Elixir in a few cases. We almost always deploy to virtual machines running Linux (Debian or Ubuntu) in private cloud environments (Xen, VMWare). For deployment we currently use

  1. Distillery to build releases
  2. Docker to provide a build environment matching the deployment environment (as developers build on their own laptops - we don’t use a central build server)
  3. Conform to configure the deployed release
  4. Ansible to tie it all together

We have a standardised Ansible role that automates the whole thing. When we run our deployment script, it will check the project out from git, build a release using a Dockerfile specified in the project, ship the generated tarfile to the specified server(s), unpack it, write the config file and restart the application. The application is run as a systemd service, and runs as its own dedicated user.

This approach works well for us, as Ansible is very flexible, and it allows use one tool for installing dependencies, doing orchestration, managing configuration and rolling a new release. All we need is SSH, so it works well for bare metal and virtual machine environments.

One thing I do miss is hot code swapping. It’s a really neat feature, but not one that we have needed yet. It’s something I’d love to know more about. Currently we simply deploy a new artifact and restart the application, mostly because we’re not sure if hot code swapping would work for us. We don’t know if our dependencies support it, and we don’t know what we need to do build libraries and applications to support it. So education about hot code swapping would be really nice. Currently the feature is too esoteric to depend on (for Elixir newbs like us, anyway) - if it could be made a easy, with wide support throughout the ecosystem, I think that would be a real boon for deployments.

4 Likes

So what would I like to see for Elixir?

Something simple and robust. Something not dependent on having VMs/Docker on your dev (or production) machine and something that doesn’t seem too much like magic.

Bonuses would be the ability to do rollbacks, the ability to configure shared folders that persist over builds (for user uploads etc) and exploiting the benefits of Elixir/Erlang such as hot code swapping.

Other than the hot code swapping, sounds like Capistrano to me :grinning:

2 Likes

i don’t really see what the goal here is

i think the reality is that there’s no dominant target that it makes sense to write an elixir specific deployment tool to target. writing a ‘generic’ tool to target bare metal, vps, aws, heroku, k8s, mesos, gce, azure, digital ocean, etc is a herculean task and likely a fool’s errand. most of these platforms are going to need additional configuration management likely out of scope of the project goals which means instead of using a tool like chef, terraform, ansible or cloudformation you are instead going to use that plus the new elixir tool

i think the effort would be better spent on integrating with these existing tools and writing high quality documentation for using existing platforms

4 Likes

From @bcd765 video it’s pretty obvious the current state of things is a problem for them and their clients, so for them I would guess the goal would be to address the pain points that they and their clients have. Also resume driven development aside for good majority of projects you do not need mesos, k8s, terraform etc. and to me it often looks similar to people building crazy big data setups to deal with 50GB of data. I do not have stats on hand but I would bet that a good majority of projects are deployed to 1-4 fixed boxes/instances so making even that simple case dead simple out of the box would go long way toward improving adoption.

5 Likes

No useful suggestions from me, however I’m interested in working on something like this, but I’m not available full time. Can whoever picks up this project call me I’ll help with some tasks, as much as I can…

2 Likes

Distillery + a fairly simple (multi-stage) Docker file is a pretty simple to set-up for Kubernetes et al; it is ‘bare metal’ or at least ‘bare VM’ is where the pain-point is (BTW I really appreciate the work @bitwalker has done on Distillery).

I used Distillery + CloudFormation + edeliver + asdf to get some EC2 instances up for building and running (before we adopted K8S), but the need for a separate, target-architecture build machine, and understanding Erlang’s build-time configuration were problematic for me, in going from running everything with mix or iex, to stand-alone deployment, for the first time.

Personally, I think the run-time configuration thing needs a bit more thought: if we can have straight-forward, easy to understand, and standardised support for 12-factor config, that would go somewhere to solving the ‘production leap’ that faces an Elixir adopter.

I was hoping that the {:system, var} tuple was going to end up being a standard, since it is simple, and understandable, but there seems to be a reaction against it now - mostly because it isn’t, actually, standard enough! (the other point on there, supporting other types of config providers, is solvable by making the thing that interprets the tuple pluggable).

Mix’s config.exs is a great bridge to the Erlang way of doing config things, but I feel Elixir needs a generally accepted way of the Elixir way of doing config things.

:thinking:

5 Likes

What I’ve always wanted is where you can just give it an anonymous function to return whatever you want (optionally cached on first call into the Application of course). Then you could do whatever, look up from the system environment, ask the database, perform a remote call to a Cthulhu dimension, whatever.

5 Likes