Agree with Avraham. Some other considerations:
I use Linux package managers (e.g., apt-get on Debian) for non-critical technology. This usually (but not always) means all non-Python technology, plus Python technology that we don’t push to its limits.
But, OTOH, at least in Ubuntu, it can sometimes be a hassle to locate the Ubuntu package containing the Python package I want to install. OTTH, it *is* quite nice to let apt-get to take care of all the dependencies, and install the big technologies (e.g., postgres).
When using pip, make sure you lock your versions in your dependency file. (e.g., celery==3.0.1) BUT don’t blindly trust it. I’ve had instances where I asked for version x and pip installed a different version and my life turned into hell for half a day. I partly blame pip (if I ask for version 3.0.1, then I want 3.0.1 dammit, and if you can’t install 3.0.1 then you should throw an exception!) and partly blame lazy package maintainers who assert that, e.g., 3.0.4 is a drop in replacement for 3.0.1 when in fact it is not.
Our systems are smallish (~ 25 nodes or so) and I find managing them with fabric is satisfactory. I have fabric tasks for updating nodes, provisioning new nodes, etc., and it works for me. But I have been thinking about adding Ansible to the mix. YMMV.
John