|
What is Puppet? In theory, Puppet is a configuration management tool that lets you setup any number of machines in a consistent, reliable manner. You declare the state you want your machine to be in (e.g. should have package X, service Y should be running, use this config file for it) and it all magically comes into existence at the press of a button! In reality Puppet is staggering amount of hacks written on top of other hacks that defies reason and common sense at every turn. I strongly suspect it began life as a series of Perl scripts written by non-programming sys-admins that were eventually ported to Ruby by an unpaid intern. It's just bad decision followed by bad decision and then more bad decisions on top of that to make the previous bad decision work. Surely you exagerate Here are some fun facts about puppet:
Why does anyone use this awful thing? Because it was the first of its kind to come around and thus is the oldest and has most of the 3rd party modules and support. Other tools have since come along (Chef, Ansible, Docker depending on how you look at it) and although I haven't had much time to look at them in-depth (too much of our poo poo runs in puppet, switching it all out is out of the question at this point), I cannot imagine they could posisbly be worse. Simply by not designing their own hosed-up declarative dialect from lala-land that makes the PHP type system look like Hindley-Milner, they are sure to be decades ahead. So if you are considering Puppet to get a grip on your configurations and streamline deployment environments, don't. Leave this thread and forget Puppet exists - look at any of those other options I mentioned. If on the other hand you were a dumb poo poo like me and already sunk an regeretable number of hourse into this piece of grabage, this is the thread to post your questions and regeret the sitaution you find yourself in. Mrs. Wynand fucked around with this message at 22:55 on Jul 29, 2014 |
![]() |
|
![]()
|
# ? May 18, 2024 18:47 |
|
I'll start! What is the loving secret incantation to get newpoperty to just leave the property value the gently caress alone?? Here's a somewhat easier to read gist: https://gist.github.com/rubyruy/b44389f68becd46e8975 My custom type: Ruby code:
code:
Ruby code:
|
![]() |
|
Mr. Wynand posted:So if you are considering Puppet to get a grip on your configurations and streamline deployment environments, don't. Leave this thread and forget Puppet exists - look at any of those other options I mentioned. The last conference I was at we had a BoF discussion and someone brought up configuration management. Someone said "what should you use" and everyone said in unison "ansible". Even the guy who maintains puppet packages for an OS which I will not name Bring your puppet questions here, but if you're adventuring into the world of configuration management don't implement puppet. feld fucked around with this message at 22:51 on Jul 29, 2014 |
![]() |
|
Yeah ansible owns.
|
![]() |
|
Ansible does indeed own. Irregardless of the config management/deployment toolkit wars, does anyone have any stories of taking an environment with no config management and turing it around? I have a few areas where I've been able to implement stuff, but a whole bunch of legacy pets remain. What's the best way you've made progress while still keeping My only wish is that ansible would dump the silly yaml syntax. Give me curly brackets or even python syntax.
|
![]() |
|
I have worked with 3 separate companies (start ups) turning their infrastructure/deployment from mess of shell scripts (or nothing) into a <5 minute scratch-to-production using Chef. I'd start with gathering all the shell scripts and making them easier to user, then shoving the CM tool inside the shell scripts, then you can move the entire shell scripts into the CM tool, and then finally start merging the CM recipes/playbooks into a single set of (environment) cookbooks. The hardest part is always the orchestration, that's where you have to have the Database, Cache Servers, etc coming up before the application stack, or better yet how about sharding, replication and failover handling. They usually resolve (heh) down into problems with DNS, NTP, and your choice of lock/state storage (etcd, consul, zk, redis). TBH I chose to go the CM route (and drop my shell scripts) because it felt more natural and it was easier to convince non-sys/tech-ops people to learn more about the infrastructure and the implications of their programming decisions when it was a mess of scripts in a language they were familiar with (no idea how/why kids are coming out of college without a decent amount of scripting experience). Ansible is going down the wrong route at the moment (in my opinion). As a person who watched Chef go through the entire problem of "oh my nginx is better than yours" and "I need to fork your entire cookbook so I can make this adjustment", Ansible should be trying to expose people to write entire playbooks in python instead of the amalgamation of yaml that they are using. This way you can turn a playbook entirely into a library for commonly shared infrastructure components. E.g. How to install a package, choosing a supervisor, or a sysvinit replacement should be up to the user not the playbook.
|
![]() |
|
Puppet is fantastic if you're like me and pretend you don't know anything better exists. We're doing an Ansible spike as a secret part of a new platform being brought up and I'm pretty excited to make the transition. I'm at least glad most of our stuff is declared in yaml via hiera though so it won't be too bad doing the eventual migration. I'm going to be so happy when I can have two server types both declare that they want a goddamn package installed without writing a custom manifest for a single package or a dumb mess of if not defined.
ahmeni fucked around with this message at 12:07 on Jul 30, 2014 |
![]() |
|
Surprise: Puppet is a functional language which specifies a graph under constraints that seem odd to people who want to think of configuration management as shell scripts come hell or high water. I will definitely check out Anisble since it seems to be getting popular, but unfortunately it simply doesn't do to replace your configuration management system based on trends.
Novo fucked around with this message at 21:41 on Jul 30, 2014 |
![]() |
|
At my company we're all-in on SaltStack for both config management and remote execution/orchestration. If this thread is going to be general config management chat and not just Puppet I'd be happy to talk Salt with you nerds.
|
![]() |
|
I figured out my problem. See, when you do this in a puppet custom type:Ruby code:
So you're basically defining a a special subclass of Puppet::Property in that block. That method is actually Puppet::Property::describe and it will modify that subclass in-place to do whatever. Which in and of itself wouldn't be so bad (though still very stupid) except for the fact that you don't actually know if Puppet::Property is the base of your hosed-up inline class because that newproperty "helper" switches it out dynamically depending on which options you pass it which is just such a terrifyingly weird and obtuse thing to do for absolutely no reason. Anywho, so what it comes down is that the default Property implementation actually makes a whole fuckload of assumptions about data validation and formatting and so forth. For example, it assumes values will only ever be strings, hashes or arrays of strings. Arrays of hashes? Who could have predicted such a thing could exist, we aren't theoretical physicists here! SO, to handle the highly exotic and unsual functionality of "passing a property value to ruby umolested", we must do the following: Ruby code:
Ruby code:
![]()
|
![]() |
|
Now for my next riddle:The puppet resource man page posted:
Now to me, this would suggest you can use the --param flag to display additional params (like, read-only params - not to be confused with properties - properties are states we can monitor and change, params are not). Well, whatevre the hell it is, it is deifinitely not that. Nothing I set it to seems to change anything about the output. What do you think it is? Perhaps it's like art interpretation. I think all opinions should be equally valid here.
|
![]() |
|
Novo posted:Surprise: Puppet is a functional language which specifies a graph under constraints that seem odd to people who want to think of configuration management as shell scripts come hell or high water. I will definitely check out Anisble since it seems to be getting popular, but unfortunately it simply doesn't do to replace your configuration management system based on trends. Nothing wrong with declarative execution - declarative is awsome, but it is definitely one of the more subtly difficult things to implement. There is a reason Haskell is developed primarily by people holding multiple PhDs. You know who probably can't be trusted with getting it right though? People who can't implement a basic loving array without making GBS threads the bed. I just don't get what is going on there, like, ok, you're a novice programmer, fine, you know? I would never poo poo on someone just for that, but what is with this constant over-reaching for doing things the most novel and difficult way possible? Like, they are about to add loops to the language - great, but they won't just be adding loops, oh no - they will be implementing generic lambdas - and loops will simply be a method that takes a lambda, you know just like Ruby's each-blocks! Just, you know, maybe learn to walk before you try to run? Especially when you just fell flat on your face for the past 10 miles because you can't take a step without trying to eat your own shoes?
|
![]() |
|
Mr. Wynand posted:Now for my next riddle: The param is a type attribute. Yes, this really, really terrible naming. Especially because it doesn't actually refer to the individual instance of a resource. Just the metaclass it's based on. Go look at the type reference and pick one (vlan, augeas, whatever) to get a list of params you can use for that type. Config management general? General response from someone who has to write custom puppet types and providers: avoid if it you possibly can. If you need to do anything beyond what Puppet's DSL provides for your environment, run for the hills (Chef, Salt, or Ansible). Only muck with types/providers if you need to write providers for end-users and you're F5 or NetApp or someone. On that note, I end up looking this any time I need to do anything new with providers because they've probably already done something similar to what I want to do.
|
![]() |
|
alo posted:Irregardless of the config management/deployment toolkit wars, does anyone have any stories of taking an environment with no config management and turing it around? I have a few areas where I've been able to implement stuff, but a whole bunch of legacy pets remain. What's the best way you've made progress while still keeping I have ansible at work and it doesn't do much simply because we have WAY too many systems doing different tasks. If we had more similar systems it would be easier to implement, but we manage most servers directly. However I am able to push out mass changes to system configs (ldap, dns, ntp, etc) or change passwords of local users en-masse. Servers that are touched regularly now have their configs in svn, but getting people to actually check in changes is like pulling teeth. I regularly run "svn status" and shame people. It's surprising how many people don't even grok the concept of tools like svn/git/cvs/etc. As far as ansible itself: nobody else at work really knows it is there and there hasn't been much time for educating. Now, as far as setting it up? Step 1: write a script that adds an ansible user with password disabled or a random password, creates the proper authorized_keys file, and permits the user to sudo. Step 2: use something like clusterssh or whatever tools you're comfortable with and get this onto all your servers, NOW. Do you have a template you build servers from? Put it on there so every new server is bootstrapped. Step 3: write a playbook that manages common config files as a test -- maybe something like your resolv.conf. Step 4: push to one server as a test. worked? good. Step 5: push to all servers Step 6: come up with more things to control Step 7: rinse, repeat Soon you'll have some playbooks/recipes/what have you and when you get the dreaded "oh man I have to do that on ALL the servers" task you're bootstrapped and ready to start using it. Getting people to commit their changes to svn or the like and having ansible pull down from your repo and restart services would be a good improvement as well. Do you have a ticketing system? Hack the svn email python script to automatically insert a diff into the ticket if they supply the correct syntax -- I use TT#12345 as the format and it can be anywhere in the commit log. Suddenly work is like magic, and people are blown away at how "simple" documenting changes is. edit: Step 8 try to find time to review the changes people are committing... because... thats how you prevent disasters. feld fucked around with this message at 23:09 on Jul 30, 2014 |
![]() |
|
evol262 posted:General response from someone who has to write custom puppet types and providers: avoid if it you possibly can. If you need to do anything beyond what Puppet's DSL provides for your environment, run for the hills (Chef, Salt, or Ansible). Only muck with types/providers if you need to write providers for end-users and you're F5 or NetApp or someone. Puppet is most definitely not a way to use Ruby for configuration management. You should be wringing every last ounce out of defining custom types before you consider writing your own implementations. Novo fucked around with this message at 23:42 on Jul 30, 2014 |
![]() |
|
Novo posted:Puppet is most definitely not a way to use Ruby for configuration management. You should be wringing every last ounce out of defining custom types before you consider writing your own implementations. The problem is that defining those custom types is also about as fun as writing RPG. Also, I work for Red Hat and I get to write providers for some of our products which cannot possibly be done with extant code, and so I spend time writing Ruby so end users can use Puppet and not worry about the implementation details. But implementing providers and types is terrible, terrible, terrible.
|
![]() |
|
Agreed, the main problem with Puppet is that the language is only tolerable to the extent that it provides clean abstractions for everything, and now you have two problems as they say.
|
![]() |
|
pram posted:Yeah ansible owns. Does ansible do multi-master yet? Because SSH doesn't really scale, and everybody hates fireball mode. E: Also we're still on puppet 2.7 and I hate it to death with fire and AIDS.
|
![]() |
|
evol262 posted:The param is a type attribute. I don't understand what you mean by any of that. I know a param is, in general, a thing that is like a property but not measurable - usually you use it to configure how something should run instead of how something should be - e.g. augeas's force=> true. In the context of my question though, that is an option passed to the puppet resource command which can list resources. It looks like it is intended to allow you to list specific params instead of just properties for each resources - except it's not doing that. After some code diving, I still think that is the intention: (comments mine) Ruby code:
See, the way those resources are gotten is this: Ruby code:
Ruby code:
Ruby code:
The whole loving codebase is just such an unmitigated disaster. The current maintainers seem to be just as flabbergasted by it as I am: Ruby code:
Oh yeah and just as a bonus, I also found this: Ruby code:
|
![]() |
|
Mr. Wynand posted:I don't understand what you mean by any of that. I'll have to dive into it a bit when I get a chance this week. Phone posting. I think you're misunderstanding the intention, though. The representation is not the class. You'd need to use reflection to really look at the instance. -param someparam doesn't let you set arbitrary parameters. They must be present in the actual resource (type attribute) without an instance. e.g. in the base, uninitialized type. I've never tried this particular option, though, and I'd have to look at it. Also, please never look at any decade-old codebase with a team that's turned over multiple times with no major rewrites and castigate the developers because they're afraid to refactor parts which might be important but nobody knows. Yes, it's bad. They also know that. That's why there are todos. But it happens.
|
![]() |
|
Mr. Wynand posted:
Comradephate posted:Does ansible do multi-master yet? Because SSH doesn't really scale, and everybody hates fireball mode. I'm not sure what a multi-master environment would be like. Are you saying that puppet or something else has the ability for multiple servers to manage/control these changes you're pushing out and it can spread the load among them to make the changes apply quicker to your entire infrastructure? That sounds cool and all but we all know what happens when you start layering on complexity... feld fucked around with this message at 15:28 on Jul 31, 2014 |
![]() |
|
Yes. Most config management tools have the ability to run multiple masters for both load balancing and redundancy. If you have a lot of servers exclusively managed by Puppet you don't really want to lose the ability to interact with them all when your only master takes a poo poo and you have to rebuild it.
|
![]() |
|
feld posted:I'm not sure what a multi-master environment would be like. Are you saying that puppet or something else has the ability for multiple servers to manage/control these changes you're pushing out and it can spread the load among them to make the changes apply quicker to your entire infrastructure? Yes it's complex, but Ansible can't successfully talk to as many servers as we have, so it's a non-starter. Also what DocJowles said - if a puppetmaster or puppet API server falls over, puppet slows down a little, but it doesn't stop. If I had the time I could make it so that if a puppetmaster falls over, puppet will just shoot it and build a new one. Ansible can't save itself from failure, because if your ansible server falls over, your config management doesn't exist anymore.
|
![]() |
|
Saltstack is another one to look at from the same generation as Ansible. It's a little bit more involved to get it started into your infrastructure (but not much) but it has multi master and while halite (the web interface) is no Ansible Tower, it's at the very least functional for quick views into the infrastructure.
|
![]() |
|
evol262 posted:
Well actually I ended up just using a custom read-only property and I'm giving up on discovering what the gently caress --param is used for here. quote:
Oh I wasn't castigating the current developers at all - I was commiserating with them. I mean obviously now a whole team of people has to somehow make a tasty dish out of this poo poo-sandwich, and my prayers are with them. The original developers though who let this out into the world to begin with? Less empathy there.
|
![]() |
|
Thank you for this thread. Our developers spin up their PIE boxes with Puppet. tango alpha delta fucked around with this message at 09:27 on Aug 1, 2014 |
![]() |
|
We're using Foreman+Puppet to deploy and manage our machines. I don't know if it's puppet being terrible or our implementation being terrible, but every time I've had to write a Puppet module for something of ours, I end up having to modify some module 10 levels away that just assumes that resource X is always going to be the same no matter what. Also a CUPS server is un-Puppetable, gently caress that so hard.
|
![]() |
|
From the top. I know you're ranting, but you might give some people the very wrong idea about how this poo poo works.Mr. Wynand posted:A array with one value is just the value... unless of course you're calling it from within a Ruby template, in which case it's an array again. Oh unless of course the Ruby code is an actual type provider implementation, in which case it might be the array, the single value, a single string concentrating each array value and joining them with spaces, or the first value of the array even if it has more than one value. Mr. Wynand posted:Nothing, nothing in puppet can be defined more than once. Not variables, not resources. This becomes especially interesting when you have a resource class (which is a set of definitions that can be repeated under different names) that depends on a shared single resource (e.g. a number of nginx vhosts, all depend on a single base nginx install + configuration). There is no clean/safe way of having each instance declare that shared dependency. (ensure_resource exists yes, but it is decievingly prone to extremely hard to debug edge cases because puppet's execution model is basicaly nondeterministic outside of the requirements graph). There are at least two good ways of handling this shared dependency:
Mr. Wynand posted:If you see puppet code, you might (not unreasonably) conclude puppet has the usual scalar values - strings, bools, numbers etc. Puppet actually just has one scalar type: string. Numbers, undef, keyword-looking things - these are all strings. If you write Ruby code against it, you just sort of have to type-sniff everything. Isn't that fun? What is loving annoying is that older versions of Puppet (0.25?) did have different typing behavior when dropping Puppet variables into templates, so if you're supporting 4-year-old versions of Puppet then you do need to do all kinds of crazy things like you describe. Mr. Wynand posted:Other tools have since come along (Chef, Ansible, Docker depending on how you look at it) and although I haven't had much time to look at them in-depth (too much of our poo poo runs in puppet, switching it all out is out of the question at this point), I cannot imagine they could posisbly be worse. Vulture Culture fucked around with this message at 15:35 on Aug 6, 2014 |
![]() |
|
I find myself writing a lot of basic modules that consist of init.pp, conf.pp (to copy over a single config file), pkg.pp (to install the relevant package), and service.pp (to run the relevant service). Is there some kind of workflow that starts with those basic files so I don't spend all my time manually copying them over? My original thought was a git repo that I could "copy" without forking (which I guess I can do with a bare clone and a mirror) but maybe there's a better way? I downloaded gepetto (the puppet IDE, basically Eclipse with puppet support) but that might be over complicated.
|
![]() |
|
FISHMANPET posted:I find myself writing a lot of basic modules that consist of init.pp, conf.pp (to copy over a single config file), pkg.pp (to install the relevant package), and service.pp (to run the relevant service). Is there some kind of workflow that starts with those basic files so I don't spend all my time manually copying them over? My original thought was a git repo that I could "copy" without forking (which I guess I can do with a bare clone and a mirror) but maybe there's a better way? I downloaded gepetto (the puppet IDE, basically Eclipse with puppet support) but that might be over complicated.
|
![]() |
|
Dr. Jackal posted:Ansible is going down the wrong route at the moment (in my opinion). As a person who watched Chef go through the entire problem of "oh my nginx is better than yours" and "I need to fork your entire cookbook so I can make this adjustment", Ansible should be trying to expose people to write entire playbooks in python instead of the amalgamation of yaml that they are using. This way you can turn a playbook entirely into a library for commonly shared infrastructure components. E.g. How to install a package, choosing a supervisor, or a sysvinit replacement should be up to the user not the playbook. I've seen this a bit with the playbooks on Galaxy, which is annoying because I had high hopes ![]()
|
![]() |
|
Mr. Wynand posted:[*] Nothing, nothing in puppet can be defined more than once. Not variables, not resources. This becomes especially interesting when you have a resource class (which is a set of definitions that can be repeated under different names) that depends on a shared single resource (e.g. a number of nginx vhosts, all depend on a single base nginx install + configuration). There is no clean/safe way of having each instance declare that shared dependency. (ensure_resource exists yes, but it is decievingly prone to extremely hard to debug edge cases because puppet's execution model is basicaly nondeterministic outside of the requirements graph). You can only define a resource once, but you can declare it in multiple places with virtual resources: https://docs.puppetlabs.com/guides/virtual_resources.html . That would solve your example problem. Also, if you use 'include-style' declaration of classes, you can declare them in multiple places. If you use Hiera, you can pass parameters with the 'include-style', which avoids the only-declare-once weakness that the 'resource-style' declaration has.
|
![]() |
|
Are there any issues surrounding letter case in agent hostnames? I'm loving around with Puppet for the first time, and had a bunch of trouble getting an agent test to run successfully. I kept getting 403 forbidden errors when the node tries to get its own node definition, and as near a I could tell it was trickling all the way down to the deny all rule at the bottom. The hostname was in all caps, but the node gets added as all lowercase. I tried again with a different new node using all lower-case in the hostname, and it worked perfectly. e: Looks like there kind of is. All the certs get created with the hostname in lowercase, but puppet.conf says to use the hostname in uppercase. Presumably it can't find that cert when it tries to authenticate, so the whole thing fails. ![]() stubblyhead fucked around with this message at 00:18 on Oct 14, 2014 |
![]() |
|
swampcow posted:You can only define a resource once, but you can declare it in multiple places with virtual resources: https://docs.puppetlabs.com/guides/virtual_resources.html . That would solve your example problem. This! While it is true you can only define it once, if you define it as a virtual resource you can realize it where you need it, and override values. Some things I have found useful in puppet: - Use an external classifier. Puppetdb, your special DB, whatever. Trying to classify every host in code is painful fast. - Write generic modules that do specific things when possible. Make them customizable by inputs. It's more work setting up the first module, but in the long run it's worth it. - Abuse https://forge.puppetlabs.com/. Rarely do I find something that is exactly what I need, but often times you can get an idea or direction to go with. People do cool, stupid and crazy poo poo. Just like everywhere else on the internet.
|
![]() |
|
stubblyhead posted:e: Looks like there kind of is. All the certs get created with the hostname in lowercase, but puppet.conf says to use the hostname in uppercase. Presumably it can't find that cert when it tries to authenticate, so the whole thing fails. Weird, I have the same problem with a new Puppet 3 install and with all nodes I add (unless I add "allow *" at the bottom of auth.conf). My node hostnames are all lowercase, the certs are all lowercase too, but if I keep the default auth.conf, I'll get this for all client nodes: code:
|
![]() |
|
Senso posted:Weird, I have the same problem with a new Puppet 3 install and with all nodes I add (unless I add "allow *" at the bottom of auth.conf). My node hostnames are all lowercase, the certs are all lowercase too, but if I keep the default auth.conf, I'll get this for all client nodes: That is pretty weird. I actually opened a bug with them about it, and they rather unceremoniously closed it without comment. 119 I think refers to the last line in your auth.conf which is the default "deny all" rule. Basically it's saying it went all the way through the file without finding anything else that matched. If all your stuff is in the same case though I don't know what else to say. What does puppet.conf say on the client nodes?
|
![]() |
|
stubblyhead posted:That is pretty weird. I actually opened a bug with them about it, and they rather unceremoniously closed it without comment. 119 I think refers to the last line in your auth.conf which is the default "deny all" rule. Basically it's saying it went all the way through the file without finding anything else that matched. If all your stuff is in the same case though I don't know what else to say. What does puppet.conf say on the client nodes? Yeah, that's the default deny all rule. My client configs are typically like this: code:
|
![]() |
|
What's a good resource to learn modern puppet if I've spent the last 3 years in chef-land?
|
![]() |
|
luminalflux posted:What's a good resource to learn modern puppet if I've spent the last 3 years in chef-land? Start here, because modules and hiera are the future.
|
![]() |
|
![]()
|
# ? May 18, 2024 18:47 |
|
evol262 posted:Start here, because modules and hiera are the future. The link you provided is the old way of writing modules. The params section is obsoleted by hiera and automatic parameter lookups, for instance. Also, puppetlabs is now teaching that you shouldn't use inheritance.
|
![]() |