Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Thanks for the clarification. I think I get the theory a bit better now.

I'm still struggling with seeing some practical examples of those differences.

for example, `apt-get` is pretty much idempotent already, no? if I run `apt-get install -y <package>` x 1000 times in a loop it won't install it 1000 times...

Fabric does give you the building blocks for those kind of checks elsewhere, such as `exists`, `contains`, `append` (which is supposed to also be idempotent) etc... I've designed my deployment / bootstrap scripts with fabric to take this into account. It does add a little overhead, but nothing that makes me feel I need a better tool... Maybe my deployment base is still relatively small and homogeneous.

So it's true that I have to put in those checks myself, and that I don't have a very easy way to discover what state a server is at.

I'll try to take another stab at one of those tools. Maybe things will sink in when I actually use them. Thanks again for explaining.



When you install the package you do it as a on-off. When a configuration system does it then it will keep re-happening if anything changes.

Say you install "less", and I remove it. With Chef this will be fixed the next run - with fabric? You'll need to re-run your magic script.

That's the main difference. Automation like Chef/CFEngine/Slaughter will keep fixing breakages - as defined by differences in state from their rules - whereas you'll be playing a game of catchup.


If you're only doing one or two things, the value is a bit more vague. But consider even the simplest interaction: the config file for a service should look like X, and if it has to be changed, the service needs to be restarted afterward. Oh and there are 10 config files, but you only want to restart the service once if any of them changes, after they've all been changed. That's not hard, but it's already starting to look non-trivial.

And what if you want to have the same logic for several services? I guess you abstract it out to a function. But then it turns out one of those services doesn't have a restart command, and you have to do stop+start. And another service won't start if you use restart while it's not running, so you have to check if it's stopped and use start, otherwise use restart.

It's much more than just whether the code is declarative or imperative, or whether it's idempotent or not. An imperative tool can change your system from known initial state A to desired state B. A declarative system can change it from whatever initial state it's in to desired state B, even if you never considered it might be in that state.


When you want to make a configuration change to your servers, and they aren't already in a "known state", why would you think any tool could put them into a known state? When a computer has a virus, say, you don't think it's been put into a "known state" after the anti-virus program gets done with it; the virus may have done any number of things you might be unaware of, altered any number of data or configuration files in subtle ways that the tool doesn't look for, but implicitly relies upon.

Example: what if, say, one of the provisioning requirements is "make sure this gem is installed", but on one of the servers /etc/gemrc has "install: --no-rdoc --no-ri" in it? Now on one server, the docs are missing, while everywhere else they're available. That sort of thing.

If you're already running on an IaaS like EC2, I think there's a simpler, better way: rather than trying to get "unknown state" to "known state", why not use the simplest known state of all--unprovisioned? Write an imperative script that reinitializes a freshly-provisioned IaaS node to your known state, and then do a rolling reprovision, terminating old nodes and provisioning new ones.

An equivalent comparison[1]: would you feel safe running an automated script that would SSH into a production machine and "git pull" a checked-out repo sitting on it, from whatever state it happens to be sitting at, up to refs/heads/master, so as to deploy code from it? Could you guarantee that that repo hadn't been moved to some state where refs/heads/master isn't a fast-forward commit? Or would you rather do a fresh "git clone"?

---

[1] A contrived comparison, though; although the former option is unreliable, the latter is terribly inefficient, and they're both horrible for keeping a .git directory inside of a directory that might very well be web-accessible.


apt-get is most definitively not idempotent without a lot of care. It will upgrade packages if a new version is available, and such upgrades can have widespread implications.

Otherwise I agree with you - Puppet/ Chef etc. are overly big on ceremony for me. We "only" use about 100 VM's on about 20 physical servers at the moment, so it's a "simple" setup.

I think where people get the most value out of systems like Puppet and Chef is if a lot of their servers or VM's have simple enough requirements that they can largely use "off the shelf" community provided configurations. The more customisation you need, the more the leve of ceremony starts biting you. The more you can rely on ready-made scripts, the more those apps help you because of the size of their communities.


Regarding apt-get -- You're right.

If you use a single distribution and can get all your stuff packaged using the distribution's packaging system, you're OK.

It can be more difficult when you get to system configuration (editing files), but you can do it manually like you do with fabric if you're careful.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: