📜 ⬆️ ⬇️

Puppet + Opsview: template-based automatic monitoring

Task


We use Opsview for monitoring and Puppet for configuration management. Opsview has templates (Host Templates) that allow you to define a specific list of checks (Service Checks) for a specific type of host. For example, for a host with an IIS template, various IIS parameters of this host will be checked, for example, the number of current connections or, for example, the average connection speed.

There was a task to automatically assign a template to a host, depending on which classes are assigned in the manifest. All this, as always, to meet the needs of automation and laziness. The final goal - I assigned a class to the host, returned 15 minutes later, and it’s already with IIS installed, with customized sites (as an option already with content), all of them are monitored and according to this data graphs are built, and also alerts let you know if It happened.

Difficulties


The main difficulty here, as usual, is that no one has done this for me. One-Click IIS Monitoring module does not exist for my infrastructure. Practically, the difficulty lies in telling the module that manages the Opsview configuration that a site was created in another module, passing the URI parameters that need to be monitored, as well as the host template names (in this case it will be at least the IIS template). My attempts and tests included the following:

Global variables


It did not work, because puppet scoping (how in Russian?) Works in such a way that you cannot make append to a global variable, you can only make a copy, and we need to accumulate the template names, since we can have countless .

Ruby Templates


There is also an option to implement global variables through templates (this is when in <% we write parental code ruby%>, which assigns the appropriate values, but this is considered a bug and can be fixed in the following Versions puppet (removed the chip with the ability to set the values ​​of variables in other scope) .
')

Plussignment


Quickly looked at the possibility of assigning resource parameters using "~>" - it seems like the values ​​were glued together, but again everything was reduced either to global variables or to the fact that the monitoring host that we monitor had to be described in every place where we want to add a template to this host, this is not entirely possible, since we cannot always know the initial parameters of this resource, and they are mandatory - for example, the host name, which is formed in the main opsview :: node class, and so on).

Finalize Provider


I thought to finish the Opsview management provider, which may have been the right decision if implemented correctly (again, there are likely difficulties with the need to declare the entire resource in each place) and this is what came to mind (as always “too simple” for many).

Implementation


Since the environment is heterogeneous (in Russian - “zoo”), you need to think on a scale of at least Windows and Linux.

Windows


It turns out that if you set the environment variable on the required node as FACTER_host_temates = IIS Server; Windows Server WMI; Basic Network, then when you next run puppet run, this will turn into a fact that can be used as a global variable in any manifest, which is what we need ! I did not write a separate provider, and quickly created a new type that uses the excellent windows_env module. Everything is very simple, you just need to note that the name of the resource must be unique, so you have to use an additional parameter (by default, the name of the environment variable is taken from the name of the resource). In the declaration of the fact resource, we can use the name of the resource to pass the name of the environment variable. The standard separator for Windows is ";"

Linux


The second part of the task was to do the same thing, but under Linux. I know that managing environment variables in nix is ​​straightforward, and there is nothing difficult in wrapping bash commands into a puppet resource, I still hoped that someone had already done a good deed and did not have to reinvent the wheel, but it was not there ... crutches. " I do this by creating a file in the default profile where the environment variable with all values ​​is exported (separated by a colon). All of this was decomposed into the correct operating systems and checks were added so that nothing could be run again.

The result was such a manifesto
define fact ($fact_name=$name, $value, $ensure = present) { case $::osfamily { 'windows': { windows_env { "${fact_name}:${value}": variable => "FACTER_${fact_name}", ensure => $ensure, mergemode => insert, value => $value, notify => Service['puppet'], #Restart service after environment update } } 'RedHat': { $splitvalue = join($value,":") file { "/etc/profile.d/FACTER_${fact_name}.sh": ensure => present, content => "export FACTER_${fact_name}=\"${$splitvalue}\"", mode => 775, } exec { "FACTER_${fact_name}=${splitvalue}": command => "/bin/bash -c \"source /etc/profile\"", unless => "/bin/echo \${FACTER_${fact_name}} | /bin/grep -q \"${splitvalue}\"", subscribe => File["/etc/profile.d/FACTER_${fact_name}.sh"], } } default: { case $::operatingsystem { 'Gentoo': { #No Gentoo in production. } } } } } 


Resource usage in packages :: iis class
 fact {"host_templates_iis_base": fact_name => "host_templates", value => ['Web Cluster','OS - Windows Server 2008 WMI - IIS Server'], ensure => present, } 


Main class opsview :: node
 #       if $::kernel == "windows" { $delimeter=";" } else { $delimeter=":" } #       if $::host_templates { #    ,    - $host_templates = split($::host_templates,$delimeter) } else { $host_templates =[] } #  $host_templates   null    . ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #      opsview_monitored @@opsview_monitored { "$::hostname": ip => $ip, hosttemplates => $host_templates, hostattributes => $hostattributes, hostgroup => $hostgroup, enable_snmp => $enable_snmp, snmp_community => $snmp_community, snmp_port => $snmp_port, notification_interval => $notification_interval, servicechecks => $servicechecks, icon_name => $icon_name, keywords => $keywords, reload_opsview => "1", require => [Class['packages::opsview']], } 


Conclusion


The task is completed, this implementation allows you to accumulate the names of the templates in the array, and apply them.
Disadvantages: the facts become available only on the next launch of puppet, which, if properly processed (or lack thereof) in the main opsview :: node class, is not a big problem, since These parameters are added at low intervals (if they are added at all).
Advantages: facts can be used not only for opsview templates, but also for many other tasks, including adding attributes, keywords, and any other potentially cumulative puppet parameters. Facts Puppet can be installed not only manually, but also through code, which allows them to be used as the basis for many interesting things.

As always, this decision, even though it is fully working, does not claim to be the place of the “most correct” one, and if anyone has any thoughts on this subject, you are welcome in comments. Often it is necessary to solve problems, solutions for which simply do not exist yet, so recently I had to write my own provider to manage the Windows registry, since the existing puppetlabs / registry did not want to work with keys containing the "\" symbol in any variants, with or without shielding.
If this post was interesting to someone, I will be glad to share my configuration management experience.

Source: https://habr.com/ru/post/203184/


All Articles