From eb069c164af5205e21fddaa7affe6621ff2f550c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoine=20Beaupr=C3=A9?= <anarcat@debian.org> Date: Sat, 20 Apr 2019 17:32:57 -0400 Subject: [PATCH] explain how i did the 3rdparty magic trick It's messy, but it's the best I've got so far. --- tsa/howto/puppet.mdwn | 180 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) diff --git a/tsa/howto/puppet.mdwn b/tsa/howto/puppet.mdwn index 96079624..8c4a5f76 100644 --- a/tsa/howto/puppet.mdwn +++ b/tsa/howto/puppet.mdwn @@ -153,6 +153,186 @@ moved into a class parameter, probably in `common.yaml`. # How to guides +## Modifying an existing configuration + +For new deployments, this is *NOT* the prefered method. For example, +if you are deploying new software that is not already in use in our +infrastructure, do *not* follow this guide and instead follow the +`Adding new configuration` guide below. + +If you are touching an *existing* configuration, things are much +simpler however: you simply go to the module where the code already +exists and make changes. You `git commit` and `git push` the code, +then immediately run `puppet agent -t` on the affected node. + +Look at the `File layout` section above to find the right piece of +code to modify. If you are making changes that potentially affect more +than one host, you should also definitely look at the `Progressive +deployment` section below. + +## Adding new configuration + +This is a broad topic, but let's take the Prometheus monitoring system +as an example which followed the [role/profile/module][] +pattern. + +First, the [Prometheus modules on the Puppet forge][] were evaluated +for quality and popularity. There was a clear winner there: the +[Prometheus module][] from [Vox Populi][] had hundreds of thousands +more downloads than the [next option][], which was deprecated. + +[next option]: https://forge.puppet.com/brutus777/prometheus +[Vox Populi]: https://voxpupuli.org/ +[Prometheus module]: https://forge.puppet.com/puppet/prometheus +[Prometheus modules on the Puppet forge]: https://forge.puppet.com/modules?q=prometheus + +Next, the module was added to the Puppetfile (in +`3rdparty/Puppetfile`): + + mod 'puppet-prometheus', '6.4.0' + +... and librarian was ran: + + librarian-puppet install + +This fetched a lot of code from the Puppet forge: the stdlib, archive +and system modules were all installed or updated. All those modules +were audited manually, by reading each file and looking for obvious +security flaws or backdoors. Then the code was committed into git: + + git add 3rdparty + git commit -m'install prometheus module after audit' + +Then the module was configured in a profile, in `modules/profile/manifests/prometheus/server.pp`: + + class profile::prometheus::server { + class { + 'prometheus::server': + # follow prom2 defaults + localstorage => '/var/lib/prometheus/metrics2', + storage_retention => '15d', + } + } + +The above contains our local configuration for the upstream +`prometheus::server` class installed in the `3rdparty` directory. In +particular, it sets a retention period and a different path for the +metrics, so that they follow the new Prometheus 2.x defaults. + +Then this profile was added to a *role*, in +`modules/roles/manifests/monitoring.pp`: + + # the monitoring server + class roles::monitoring { + include profile::prometheus::server + } + +Notice how the role does not refer to any implementation detail, like +that the monitoring server uses Prometheus. It looks like a trivial, +useless, class but it can actually grow to include *multiple* +profiles. + +Then that role is added to the Hiera configuration of the monitoring +server, in `hiera/nodes/hetzner-nbg1-01.torproject.org.yaml`: + + classes: + - roles::monitoring + +And Puppet was ran on the host, with: + + puppet --enable ; puppet agent -t --noop ; puppet --disable "testing prometheus deployment" + +This led to some problems as the upstream module doesn't support +installing from Debian packages. Support for Debian was added to the +code in `3rdparty/modules/prometheus`, and committed into git: + + emacs 3rdparty/modules/prometheus/manifests/*.pp # magic happens + git commit -m'implement all the missing stuff' 3rdparty + git push + +And the above puppet commandline was ran again, continuing that loop +until things were good. + +If you need to deploy the code to multiple hosts, see the `Progressive +deployment` section below. To contribute changes back upstream (and +you should do so), see the section right below. + +## Contributing changes back upstream + +For simple changes, the above workflow works well, but eventually it +is preferable to actually fork the upstream repo and operate on our +fork until the changes are merged upstream. + +First, the modified module is moved out of the way: + + mv 3rdparty/modules/prometheus{,.orig} + +The module is then forked on GitHub or wherever it is hosted, and then +added to the Puppetfile: + + mod 'puppet-prometheus', + :git => 'https://github.com/anarcat/puppet-prometheus.git', + :branch => 'deploy' + +Then Librarian is ran again to fetch that code: + + librarian-puppet install + +Because Librarian is a little dumb, it might checkout your module in +"detached head" mode, in which case you will want to fix the checkout: + + cd 3rdparty/modules/prometheus + git checkout deploy + git reset --hard origin/deploy + git pull + +Note that the `deploy` branch here is a merge of all the different +branches proposed upstream in different pull requests, but it could +also be the `master` branch or a single branch if only a single pull +request was sent. + +Since you now have a clone of the upstream repository, you can push +and pull normally with upstream. When you make a change, however, you +need to commit (and push) the change *both* in the sub-repo and the +main repository: + + cd 3rdparty/modules/prometheus + $EDITOR manifests/init.pp # more magic stuff + git commit -m'change the frobatz to a argblu' + git push + cd .. + git commit -m'change the frobatz to a argblu' + git push + +Often, I make commits directly in our main Puppet repository, without +pushing to the third party fork, until I am happy with the code, and +then I craft a nice pretty commit that can be pushed upstream, +reversing that process: + + $EDITOR 3rdparty/prometheus/manifests/init.pp # dirty magic stuff + git commit -m'change the frobatz to a quuxblah' + git push + # see if that works, generally not + git commit -m'rah. wanted a quuxblutz' + git push + # now we are good, update our pull request + cd 3rdparty/modules/prometheus + git commit -m'change the frobatz to a quuxblutz' + git push + +It's annoying to double-commit things, but I haven't found a best way +to do so just yet. This problem is further discussed in [ticket +#29387][]. + +Also note that when you update code like this, the `Puppetfile` does +not change, but the `Puppetfile.lock` file *does* change. The `GIT.sha` +parameter needs to be updated. This can be done by hand, but since +that is error-prone, you might want to simply run `librarian-puppet +update prometheus-puppet` to update that module. + +This will *also* update dependencies so make sure you audit those +changes before committing and pushing. + ## Listing all hosts under puppet This will list all active hosts known to the Puppet master: -- GitLab