Hello,
I was wondering if anyone was aware of a playbook or module out in the wild that handled atomic deployments similar to the copy strategy in Capistrano 2?
Thanks in advance,
Stan
Hello,
I was wondering if anyone was aware of a playbook or module out in the wild that handled atomic deployments similar to the copy strategy in Capistrano 2?
Thanks in advance,
Stan
no but easy to implement with ansible:
action: whatever you need to deploy code to release specific dir (git/copy/unarchive/etc)
file: path=/procuduction/link src=/path/you/just/deployed/to
service: name=appserver state=reloaded|restarted
Yep, exactly.
I would probably do something like making the path the git module include the version number in the destination path {{ version }}
and that way you wouldn’t have to do a live update on the code existing code tree.
(General disclaimer – Many folks would use a load balancer instead for this purpose, as not all applications can deal with simply swapping out the code directory and must require service restarts. Of course, for those that can, this is great)
I'm doing exactly this and once I finish I will uploaded it to Ansible galaxy.
The rolling restart and LB pool problem is very easy to solve if you have a LB that could check a status file to be present on the webserver and if not present take that server out of the pool automatically then you will be sure that you don't have any connections on the server so you can perform your upgrade/deploy.
Thanks! I’d love to take a look at that. Rolling LB’s isn’t a requirement for my current project, though it’s not entirely out of the foreseeable future.
Here is a gist of what I threw together today while fiddling around:
https://gist.github.com/stanlemon/8153200
I’d appreciate any feedback or suggestions as I’m rather new to Ansible.
I have two, arguably three apps that need this same type of deployment and so I was leaning towards sticking the tasks in their own separate file and including that in an app-specific playbook. Any advice there would also be appreciated.
Thanks,
Great! This would make an awesome role.
-- Michael
nothing broken I can see, but a few things:
- local_action: and delegate_to: 127.0.0.1 mean the same thing you can
remove one, don't need both.
- sudo: false is the default, since you don't set it to true at the play
level you should only need to set it to true for tasks that require it.
- git archive can create a tarball that already doesn't have special
files/dirs
I’d maybe consider passing in what version (git tag, etc?) you are deploying with “-e” and then you could probably save the “timestamp” step too.
Note that the timestamp might be different between hosts, so passing it in seems better to me, that way your directory names would be consistent.
(Or otherwise, use the hostvars trick to get the variable from a very specific host)
Which is more preferable, local_action or delegate_to then - does it matter at all?
With regards to sudo… I’m sure this is a noob question… but right now I’ve been running my play books with the sudo flag, but the local operations I did not want to run with sudo, ergo the sudo:false. I have needed to run my playbooks with the sudo for those that run yum installs and so forth… should I not be doing that? What’s the best/recommended approach on this front?
The reason I didn’t use git archive is because I have some post-checkout build operations that I wanted to perform before compressing to send to the server.
Thanks so much for your help!
I’d actually done this with my local copy over the weekend and tied it into the deploy.yml that gets included. I’m still very much iterating, but ansible let me get atomic deploys up and running over the weekend for three deploys (two apps, one with a staging branch) on a super-crusty-old server that is due to be rebuilt next month.
“-e” flag, for git? Not sure I’m familiar with this… maybe I misunderstand?
I may not understand how this works, so please correct me if this is the case - but I was exporting the timestamp on the local (aka deployment) machine and register that as a variable to be used on the node(s) when deploying. I considered using a git sha1 for the build too - but then my “keepers” pruning won’t work reliably. I don’t have strict build tag numbers (yet) from my CI system, but that would also be another option.
The issue is that if you have a play that runs across 50 hosts and you delegate 50 steps to localhost they will all use a different timestamp because it was told to register 50 different versions of that variable.
-e to Ansible is the --extra-vars flag.
ansible-playbook foo.yml -e “version=1.2.3.4”
etc
The alternative would be to do the timestamp step only once:
hosts: localhost
tasks:
shell: whatever
register: time
hosts: webservers
roles:
do real things here
and then where needed:
{{ hostvars[“localhost”][“time”] }}
and that way the timestamp would be consistent amongst hosts.
Ahhhh, that makes sense! That’s a great suggestion, thank you!
I normally have 3 plays for my deployment playbook.
hosts: localhost
tasks:
notify start (mail/jabber/irc)
checkout from repo
generate unique ids for release (git rev-parse --short HEAD)
build stuff
create deployment package
And then a deploy play:
And a cleanup play