Zabbix agent installation and configuration with puppet exported resources

puppet zabbix_logo

Who doesn’t like to automate tasks when this is easy and can save a lot of time/troubles. When you are just starting with Zabbix, it seems that the only thing you can automate is installing the components with rpm/deb packages on the servers/clients. After installation of the packages, you’ll still need to create the host in the web interface which takes some time (And boring to if you have a lot of hosts to configure..). There is an possibility to use (auto) discovery rules, but this requires some configuration in the web interface and this only works once when the host isn’t configured in the web interface (Initial setup only).

Luckily, the Zabbix has an API which can be used for some tasks that can be automated, like creating hosts! The wdijkerman-zabbix module can use this API for the following tasks:

  • Create host
  • Update host with Templates

There is an requirement when you want to do this: Puppet Master needs the PuppetDB configured. If you want to configure an PuppetDB, please use Google for this as I won’t discuss this here.

Idea

The idea is that when an installation is done via the “zabbix::agent” class on the agent, it send some information via puppet to the PuppetDB. This is some basic information like ipaddress, name of the host and the hostgroups for this host. When the puppet agent on the “zabbix-server” runs, it will retrieve the information from the PuppetDB and will create via the Zabbix API the host(s). With this setup, everything is automated and you don’t have to worry for forgetting something.
So, how do you have to configure the zabbix module?
class { 'zabbix':
  zabbix_url       => 'zabbix.example.com',
  manage_resources => true,
}

This is an very basic configuration method mentioned above which will automatically configure the hosts in the web interface when a new “zabbix-agent” is installed. You don’t have to do anything else (yes ok, you’ll have to run some puppet runs on several machines. :-).)

This assumes that the password for the “Admin” user is still “zabbix”. You can override this of course, just like the database credentials which are default set to “zabbix-server”. (Don’t forget to change it to something non default 😉 )

Userparameters

There is an other nice feature in the “wdijkerman-zabbix” module which uses the Zabbix API. The “zabbix::userparameters” define can make use of the API. The goal for this define is installing an UserParameters file in the zabbix-agent includedir. This file consists of 1 or more UserParameter entries which explains what commands needs to be executed for an key.

An example:

zabbix::userparameters { 'Exim':
 content => 'UserParameter=exim.mailq,sudo /usr/sbin/exim -bpc',
}

There is an item in a template which executes the “sudo /usr/sbin/exim -pbc” command with the “exim.mailq” key. When the above 3 lines are in the exim puppet module and this module installs the UserParameter file, you still need to update the host in the web interface to make sure the “Template Exim” is assigned.

But stop, we can use it like the following now:

zabbix::userparameters { 'Exim':
 content  => 'UserParameter=exim.mailq,sudo /usr/sbin/exim -bpc',
 template => 'Template Exim',
}

We also supply the name of the Zabbix Template in this “user::parameters” define. When configured we first have to execute an puppet run on the agent, so it sends some data to the PuppetDB.

When the Puppet Agent runs on the “zabbix-server”, it first checks if the hosts exits and then it will assign the template “Template Exim” to the host automatically. Off course when the template does not exists, the Puppet run will fail.

Woot! 🙂

wdijkerman-zabbix puppet module now on release 1.2.0

puppetzabbix_logo

Almost a month ago, the wdijkerman-zabbix version 1.1.0 was released. I didn’t do much myself since this release 1.1.0 till now, but I did receive some pull requests. So I figured it is time to create a new release: 1.2.0.

Whats in this release? (I’m lazy, so this is copied from the CHANGELOG.md 🙂 )

  • Support for RedHat/CentOS/OracleLinux 7
  • Fixed bug with listenip & add lxc interface #46 (By pull request: meganuke19 (Thanks!))
  • Bad syntax in manifests/proxy.pp #50 (By pull request: fredprod (Thanks!))
  • Fix agent listenip #52 (By pull request: JvdW (Thanks!))
  • Fix in params.pp with default parameter of zabbix proxy for ubuntu #56 (By pull request: fredprod (Thanks!))
  • notify zabbix-agent service when userparameters change #57 (By pull request: rleemorlang (Thanks!))
  • Fix for: “Cannot Load Such File — zabbixapi” despite installation #54
  • Fix for correct order, so 1 puppet run installs the proxy again

The “#<NUM>” is a reference to an github issue. The release can now also be found on and downloaded from the forge.

If you find an bug or have an improvement for this zabbix puppet module, please create pull requests!

wdijkerman-zabbix what do you want to see in this puppet module?

So, the wdijkerman-zabbix puppet module is going strong. Almost 7100 downloads since the beginning of april last year and this amount still grows! The number one puppet module for Zabbix installations and also the only module which is puppet approved! This is really nice!

The module can be found on the forge, but also on github. But I don’t think this module is “done”. There are probably a lot of improvements needed, or new functionality that can be added. So please tell me what you want to see in the module.

What kind of improvements can be done, is it some better code, fixing some (nasty) bugs you encounter or some updates to the documentation. Is the documentation clear enough or do you want some howto’s for configuring the module to do some specific stuff, or do you want to use Nginx instead of Apache as frontend?

For now I have 2 things that I really would like to see, but due to limited resources (Knowledge and time) it is something that I can’t do in the near future:

  • Using Puppet on Windows. Like installing the zabbix-agent on Windows computers.
  • Sending Puppet Reports to zabbix-server for monitoring puppet runs.

Please send your suggestions via e-mail (which can be found in the module) or create issues on github. Or even better, fix or create some code and create an pull request! You’ll will be put in the list of fame. 😉

Thanks! 🙂

One node vs multi node setup zabbix module zabbix-proxy

zabbix_logo

With the previous post I showed you how you can use the zabbix-server on one or multiple machines with my wdijkerman-zabbix puppet module. At the end I said that you could also do this with the zabbix-proxy. So this blog item is showing how to setup the zabbix-proxy on 1 or 2 nodes. I don’t know if people are using it like this, but when I was busy for the zabbix-server, I thought that I also had to do this for the zabbix-proxy. 🙂

So sit back and watch the show. 🙂

Single node

PostgreSQL

So, we first show you have to do this with the PostgreSQL as backend.

node 'proxy.example.com'
 class { 'postgresql::server': }

 class { 'zabbix::proxy':
   zabbix_server_host => '192.168.20.11',
   zabbix_server_port => '10051',
 }
}

As you see in this manifests file, we have configured to use the postgresql-server class and the zabbix-proxy class. This zabbix-proxy class needs 1 parameter: ‘zabbix_server_host’. This is the ip address or fqdn of the zabbix-server host. The parameter ‘zabbix_server_port’ is optional, you only have to use this parameter when the zabbix-server is running on a different port than 10051.

MySQL

Okay, so you want to use MySQL as database backend? No worries, take a look at this:

node 'proxy.example.com'
 class { 'mysql::server': }

 class { 'zabbix::proxy':
   zabbix_server_host => '192.168.20.11',
   zabbix_server_port => '10051',
   database_type      => 'mysql',
 }
}

Like the zabbix-server, the zabbix-proxy uses the PostgreSQL as default database. So we have to use the ‘database_type’ parameter for specifying mysql.

Multi node

With the following example, we have 2 servers:

  • server11.example.com, which will be running the zabbix-proxy.
  • server12.example.com, which will be running the database.

MySQL

Lets start the manifests file again with the MySQL as ‘database_type’:

node 'server11.example.com' {
# My ip: 192.168.30.11
  class { 'mysql::client': }
  class { 'zabbix::proxy':
    zabbix_server_host => '192.168.20.11',
    manage_database    => false,
    database_host      => 'server12.example.com',
    database_type      => 'mysql',
  }
}

node 'server12.example.com' {
# My ip: 192.168.30.12
  class { 'mysql::server':
    override_options => {
      'mysqld'       => {
        'bind_address' => '192.168.30.12',
      },
    },
  }
  class { 'zabbix::database':
    database_type     => 'mysql',
    zabbix_type       => 'proxy',
    zabbix_proxy      => 'server11.example.com',
    database_name     => 'zabbix-proxy',
    database_user     => 'zabbix-proxy',
    database_password => 'zabbix-proxy',
  }
}

On the node of the zabbix-proxy, we had to add a new parameter: ‘manage_database’. We had to set it to false, the proxy class isn’t responsible for creating the database and loading the files. Thats what the ‘zabbix::database’ will do on the 2nd host.

PostgreSQL

Now with the PostgreSQL as ‘database_type’:

node 'server11.example.com' {
# My ip: 192.168.30.11
  class { 'postgresql::client': }
  class { 'zabbix::proxy':
    zabbix_server_host => '192.168.20.11',
    manage_database    => false,
    database_host      => 'server12.example.com',
  }
}

node 'server12.example.com' {
# My ip: 192.168.30.12
  class { 'postgresql::server':
    listen_addresses => '192.168.30.12'
  }
  class { 'zabbix::database':
    zabbix_type       => 'proxy',
    zabbix_proxy_ip   => '192.168.30.11',
    database_name     => 'zabbix-proxy',
    database_user     => 'zabbix-proxy',
    database_password => 'zabbix-proxy',
  }
}

With the above setup for both MySQL as PostgreSQL as ‘database_type’, we had to use the ‘database_name’ and ‘database_password’ parameters. The default values for the ‘zabbix::database’ class is for both parameters ‘zabbix-server’. Which is a kind of strange for the proxy. 🙂

Note

With the default installation on both the single as the multi node setup, the password for the database is ‘zabbix-server’. I would strongly recommend that you use the parameter: ‘database_password’ and give it a nice password.

One node vs multi node setup zabbix module zabbix-server

zabbix_logo
So it was quiet the last few months for posting stuff on the site, so I’ll try to do it now. I also moved the wordpress.com instead of hosting the site myself.
At the moment on writing this blog item, the wdijkerman-zabbix puppet module is at release 1.1.0. One of the biggest changes which came with release 1.0.0, is that you can choose whether your want everything one to run on a single host (Single Node, Like most of us) or running it on different servers (Multi node).

 

Up to release 1.0.0 you could only use the wdijkerman-zabbix puppet module if everything was running on the same host. Yes, from release > 0.5.0 you could even with some ‘hacking’ run the database on an other host, but that was not something I would document let alone it was a little bit confusing to do.

 

First, we start with the Single node setup. Apache, Zabbix-web, Zabbix-server and the database is installed on 1 system.

Single node

PostgreSQL

So, lets install the zabbix-server on one host:
node 'zabbix.example.com'
  class { 'apache':
    mpm_module => 'prefork',
  }
  include apache::mod::php
 
  class { 'postgresql::server': }
 
  class { 'zabbix':
    zabbix_url    => 'zabbix.example.com',
  }
}
With this manifest setup, you have configured an complete zabbix-server on one host.

 

It will install and configure Apache, postgresql (Default database for zabbix) and both zabbix components zabbix-web and zabbix-server. There is only one parameter needed for zabbix-server and it is the ‘zabbix_url’. This is the url on which the zabbix web interface is available, the rest of the parameters are optional.

MySQL

Oh, you want to run it on MySQL? No problem, this would be an very basic setup to begin with:
node 'zabbix.example.com'
  class { 'apache':
    mpm_module => 'prefork',
  }
  include apache::mod::php

  class { 'mysql::server': }

  class { 'zabbix':
    zabbix_url    => 'zabbix.example.com',
    database_type => 'mysql',
  }
}

multi node

Now, the multi node setup. This example consists of 3 nodes:
  • server01.example.com, which will be running Apache and the zabbix-web component.
  • server02.example.com, which will be running the zabbix-server component
  • server03.example.com, which will be running the database.

First we give an example of using this setup with the MySQL database.

MySQL

The following example will be given with the usage of MySQL as database backend. You can also choose to use the PostgreSQL database, but  than you have to change the setup a little bit. This will be described after the example:
node 'server01.example.com' {
  # My ip: 192.168.20.11
  class { 'apache':
    mpm_module => 'prefork',
  }
  class { 'apache::mod::php': }
  class { 'zabbix::web':
    zabbix_url => 'zabbix.example.com',
    zabbix_server => 'server02.example.com',
    database_host => 'server03.example.com',
    database_type => 'mysql',
  }
}

node 'server02.example.com' {
  # My ip: 192.168.20.12
  class { 'mysql::client': }
  class { 'zabbix::server':
    database_host => 'server03.example.com',
    database_type => 'mysql',
  }
}

node 'server03.example.com' {
  # My ip: 192.168.20.13
  class { 'mysql::server':
    override_options => {
      'mysqld' => {
      'bind_address' => '192.168.20.13',
      },
    },
  }
  class { 'zabbix::database':
  database_type => 'mysql',
    zabbix_server => 'server02.example.com',
    zabbix_web => 'server01.example.com',
  }
}
We have to fill in some ip’s or hostnames for this setup. Both the zabbix-web and -server needs to know where the database is and the zabbix-web needs to know where to find the zabbix-server.

PostgreSQL

When you want to use the PostgreSQL as backend in an multinode setup, you can use something like this:
node 'server01.example.com' {
# My ip: 192.168.20.11
 class { 'apache':
   mpm_module => 'prefork',
 }
 class { 'apache::mod::php': }
 class { 'zabbix::web':
   zabbix_url => 'zabbix.example.com',
   zabbix_server => 'server02.example.com',
   database_host => 'server03.example.com',
   database_type => ‘postgresql',
 }
}

node 'server02.example.com' {
# My ip: 192.168.20.12
 class { 'postgresql::client': }
 class { 'zabbix::server':
   database_host => 'server03.example.com',
   database_type => ‘postgresql',
 }
}

node 'server03.example.com' {
# My ip: 192.168.20.13
 class { 'postgresql::server':
   listen_addresses => '192.168.20.13'
 }
 class { 'zabbix::database':
   database_type => ‘postgresql',
   zabbix_web_ip => '192.168.20.12',
   zabbix_server_ip => '192.168.20.13',
 }
}
The PostgreSQL class accepts different values than MySQL: PostgreSQL accepts ipaddresses and MySQL accepts fqdn.

 

On a next item, I’ll go into the zabbix-proxy component. Like the zabbix-server, this can also be installed on a single node or multi node.

Note

With the default installation on both the single as the multi node setup, the password for the database is ‘zabbix-server’. I would strongly recommend that you use the parameter: ‘database_password’ and give it a nice password.

wdijkerman-zabbix puppet module now using exported resources

zabbix_logo

(old post from few months ago)

So it was a while when posting something on the website, but I’ve achieved a new goal with my zabbix puppet module. I took some vacation days and the weather wasn’t that great, so I had some time to make this work. Offcourse this was not only thing I did in my vacation, I also had to watch some movies. 🙂 Guardians of the Galaxy! 🙂 anywayz…

As of release 0.4.0 it also make use of exported resources. Offcourse the puppet infra must be configured to work with exported resources.

Idea

The main idea of making this work was about 2 things:

  1. Fully automated installation/configuration of monitoring environment
  2. I wanted to focus on writing my own puppet type/provider.

Monitoring environment

Ideally, you want everything fully automated to be configured so you won’t forgot anything. In previous versions with this module, every zabbix component was installed en configured, but you still had to logon into the web interface and manually create the hosts and assign templates to it.

So this needs to be automated. Luckilly zabbix has an API which can be used for these kind of actions! Nice!

I found an excellent rubygem for saving a lot of headaches: zabbixapi. With this gem, I can easily create new hosts like this:

zbx = ZabbixApi.connect(
  :url => 'http://localhost/zabbix/api_jsonrpc.php',
  :user => 'Admin',
  :password => 'zabbix'
)

zbx.hosts.create(
  :host => host.fqdn,
  :interfaces => [
    {
      :type => 1,
      :main => 1,
      :ip => '10.0.0.1',
      :dns => 'server.example.org',
      :port => 10050,
      :useip => 0
    }
  ],
  :groups => [ :groupid => zbx.hostgroups.get_id(:name => "hostgroup") ]
)

First we create the connection to the api, by specifying the url, an valid user which has enough rights to create and edit hosts with the password.

When we have an valid connection, we create the host. When creating the host, it will put it into the “hostgroup” hostgroup and it will create 1 interface for the agent ( :type => 1). It will configure both ip as dns name, the port on which the agent is running and it will connect via dns ( :useip =>0).

So now we can create the hosts automatically in zabbix. We want to create hosts on 1 machine, the zabbix-server, so we have to make use of exported resources. Why do we want to do this on 1 machine? Not every host is able to connect to the zabbix-server, like when you use an zabbix-proxy on different (sub)net. Also you’ll have to install the zabbixapi gem on all servers with an admin like username/password on the clients. Could be an security issue. Also we want to make use of exported resources, they rock! 🙂

exported resources

With exported resources you are able to “send data” into an puppet database which other hosts can download and use it. Ideal for monitoring. We add an zabbix-agent to host a, this will send some data into the puppet database. On host b, the zabbix-server, the puppet run will and gather this data and do some actions with it.

Easier said than done, we have to create an specific type for this. We can’t use the “file” type, or “package” or even the “nagios_host”. We have to create our own type before we can use of exported resources.

Puppet type/provider

So I had to write my own puppet types en providers. I won’t go in details about this, but I’ll show you some basic code.

With the following, we are able to export resources into the puppet database:


@@zabbix_host { $hostname:
  ipaddress   => $ipaddress,
  use_ip      => $use_ip,
  port        => $port,
  group       => $group,
  templates   => $templates,
  proxy       => $proxy,
  zabbix_url  => '',
  zabbix_user => '',
  zabbix_pass => '',
}

It has some basic stuff, like hostname, ipaddress and port. But I also had 3 extra parameters which I could override on the zabbix-server. These are the zabbix_url, zabbix_user and zabbix_pass. The above will be executed on every zabbix agent which has the parameter “manage_resources” set on true.

When an puppet runs on the zabbix-server, we have the following that collects the data:

Zabbix_host <<| |>> {
  zabbix_url  => $zabbix_url,
  zabbix_user => $zabbix_user,
  zabbix_pass => $zabbix_pass,
}

This specific class (zabbix::resources::server) has 3 parameters and will be used for overriding the default empty parameters.

The provider will only do something when the “zabbix_url” has information, so we know that it will only run on the zabbix-server.

With the following components, we make use of exported resources:

  • zabbix-agent
  • zabbix-proxy
  • zabbix-userparameters

With the zabbix-proxy, it will create the zabbix-proxy via the zabbix-api. When you use an proxy, you can set one of the parameters on the host which proxy it needs to be monitored by.

With the zabbix-userparameter you can install 1 or more specific userparameters into the host. Mostly this is done because an template needs these parameters. You can now specify the name of the template to which belongs to the userparameters you install.

Final note

So, exported resources gives the puppet module a lot of extra power to automate stuff. But when you have a lot of hosts, this will cause the runtime of the zabbix-server to increase a lot. For every host that exists, it will check via the zabbix-api if the host exists. If not, it will create it. But this takes time. Around 2 seconds for an host. So ..