Thursday 20 November 2014

Deploying Kamailio with Puppet

Almost three years ago I started automating the deployment of all server-side applications with Puppet.

One of the key applications in Truphone's RTC platform (and arguably in most of VoIP/WebRTC platforms today) is Kamailio, so with some proper encapsulation it’s been possible to build a Puppet module dedicated to it.

This is now publicly available on PuppetForge. Puppet Forge is a public repository of Puppet modules. We use many of them, and they can be incredibly useful to get you up to speed and solve common problems. You can also fork it on github, if you want.

You can use this module in different ways:

  • To quickly deploy a kamailio instance, with default configuration files.
  • As the basis for a custom configuration, where you use the official debian packages but with your own configuration details and business logic.


The first approach is very simple. Imagine you start from and empty VM or base docker container: all you have to do is install puppet, download the trulabs-kamailio module from Puppet Forge and apply the test manifest included in the module.

$ apt-get update
$ apt-get install -y puppet
$ puppet module install trulabs-kamailio

  
Dry-run the deployment with ‘noop’ first, and see what Puppet would do:

$ puppet apply -v /etc/puppet/modules/kamailio/tests/init.pp --noop

And then run it for real, by removing ‘noop’:

$ puppet apply -v /etc/puppet/modules/kamailio/tests/init.pp


Now you can verify that Kamailio is running, listening on the default interfaces, and at the latest stable version (this was tested on debian wheezy, and it’s expected to work on Ubuntu Precise and Trusty too).

The second approach (using trulabs-kamailio as a basis for your custom configuration) requires a little bit more work.

Here’s an example, where we want to deploy kamailio as WebSocket proxy. What changes in respect to the test installation is:

  1. We need to install also ‘kamailio-websocket-modules’ and ‘kamailio-tls-modules’ (as I’m assuming the WebSockets will be Secure).
  2. Take care of the kamailio cfg files directly, and not use the vanilla ones (trulabs-kamailio contains the “sample cfg files” already available with the official debian packages).


A sensible approach is to create a new Puppet module, e.g. ‘kamailio_ws’, and inside its init.pp instantiate the ‘kamailio’ class with these options:

class kamailio_ws () {
  class { '::kamailio':
    service_manage  => true,
    service_enable  => true,
    service_ensure  => 'running',
    manage_repo     => true,
    with_tls        => true,
    with_websockets => true,
    manage_config   => false,
  }
}

(This is similar to the concept of Composition in OOP.)

You can see that ‘manage_config’ is set to false, which is the way of telling the kamailio module not to install the vanilla cfg files, and that those will be managed elsewhere (inside the kamailio_ws module in this case).

To install your cfg files it’s sufficient to add something like this to the init.pp manifest:

  file { '/etc/kamailio/kamailio.cfg':
    ensure => present,
    source => 'puppet:///modules/kamailio_ws/kamailio.cfg',
    notify => Exec['warning-restart-needed'],
  }

In this way you’re declaring that the kamailio.cfg file (to be installed in /etc/kamailio/kamailio.cfg) has to be taken from the files/ folder inside the kamailio_ws module.

As an additional action, every time that file changes, Puppet should notify the user that a restart is necessary (and then leave to the sysadmin to choose the right moment to do so – the Exec resource is just expected to print something on std out).

If you want to restart kamailio immediately after kamailio.cfg changes, then you can use:
  file { '/etc/kamailio/kamailio.cfg':
    ensure => present,
    source => 'puppet:///modules/kamailio_ws/kamailio.cfg',
    notify => Service[‘kamailio’],
  }

Note that if the file doesn't change, for example because you’re just running Puppet to verify the configuration, or updating another file, then Puppet won’t try any action associated to the ‘notify’ keyword.

You can then add all the other files you want to manage (e.g. you may have a defines.cfg file that kamailio.cfg includes) by instantiating other File resources.

A common practice for modules is to have the main class (in this case kamailio_ws) inside the init.pp manifest, and the configuration part (e.g. kamailio.cfg) inside a config.pp manifests included by init.pp.

What do you think? Would you like to see any particular aspect of automating Kamailio configuration treated here? Will you try this module?


Your opinion is welcome.

No comments:

Post a Comment

About ICE negotiation

Disclaimer: I wrote this article on March 2022 while working with Subspace, and the original link is here:  https://subspace.com/resources/i...