Support SNMP pour Keepalived

Vincent Bernat

Kee­pa­li­ved est une so­lu­tion de haute dis­po­ni­bi­lité et de ré­par­ti­tion de charge. VRRP est uti­lisé pour par­ta­ger une adresse IP entre dif­fé­rents rou­teurs. À un mo­ment donné, un seul d’entre eux dis­pose de cette IP. Il s’agit du rou­teur maître. Les autres se tiennent prêts à prendre le re­lai en cas de dé­faillance. Ce sont les rou­teurs de secours.

VRRP n’est tou­te­fois pas un ges­tion­naire de res­sources pour les clus­ters. Bien qu’il soit pos­sible de gé­rer des ser­vices en plus des IP, il n’est pas pos­sible de ré­pondre à des pro­blé­ma­tiques com­plexes telles que « s’as­su­rer de la pré­sence d’au moins 10 ser­veurs web dans la grappe et de deux bases de don­nées tout en es­sayant de ne pas faire tour­ner les bases de don­nées sur les mêmes ser­veurs que les fron­taux web ». Dans ce cas, heart­beat est une so­lu­tion plus ap­propriée.

Pour la ré­par­ti­tion de charge, Kee­pa­li­ved s’ap­puie sur IPVS, un sous-sys­tème du noyau Li­nux pou­vant ef­fec­tuer de la ré­par­ti­tion de charge TCP et UDP. Kee­pa­li­ved va vé­ri­fier si les ser­vices vers les­quels les re­quêtes doivent être ré­par­ties sont fonc­tion­nels et confi­gu­rer IPVS cor­rec­te­ment. IPVS va en­suite choi­sir pour chaque re­quête en­trante le ser­veur qui va s’en oc­cu­per se­lon une po­li­tique que l’on peut confi­gu­rer. La plus cou­rante est la po­li­tique round-ro­bin qui en­voie la pre­mière re­quête sur le pre­mier ser­veur, la se­conde sur le se­cond et ainsi de suite. Quand on ar­rive au bout de la chaîne, on re­com­mence de­puis le début.

Keepalived & SNMP#

Afin de pou­voir in­ter­ro­ger Kee­pa­li­ved en SNMP, j’ai ajouté un sup­port com­plet de SNMP di­rec­te­ment dans Kee­pa­li­ved. Ce sup­port n’est pas en­core in­té­gré dans les sources of­fi­cielles. En at­ten­dant, il est pos­sible de ré­cu­pé­rer les sources com­plètes de Kee­pa­li­ved avec sup­port SNMP de­puis GitHub. Celles-ci sont ac­tuel­le­ment syn­chro­ni­sées avec la der­nière ver­sion dis­po­nible de Kee­palived.

Mise à jour (03.2014)

Le sup­port de SNMP dans Kee­pa­li­ved a été in­clus dans la ver­sion 1.2.5.

Voici ce que l’on peut faire avec un tel support :

  • ré­cu­pé­rer la confi­gu­ra­tion com­plète de Kee­pa­li­ved sans avoir be­soin d’ana­ly­ser le fi­chier de confi­guration ;
  • ré­cu­pé­rer l’état de Kee­pa­li­ved (le sta­tut des ins­tances VRRP, l’état des fron­taux) sans re­gar­der les logs ;
  • ré­cu­pé­rer des sta­tis­tiques sur les ser­veurs vir­tuels (nombre de connexions en­voyées sur tel fron­tal) sans avoir à in­ter­pré­ter la sor­tie de ipvsadm ;
  • être averti en cas de chan­ge­ment d’état (bas­cule VRRP ou ar­rêt d’un fron­tal) avec les traps SNMP ;
  • mo­di­fier le poids d’un fron­tal (pour le désac­ti­ver par exemple) ou chan­ger la prio­rité d’une ins­tance VRRP (pour pro­vo­quer une bascule).

Compilation#

Mise à jour (01.2022)

Le dé­pôt ci-des­sous n’est plus main­tenu à jour. Comme le sup­port SNMP a été in­té­gré de­puis la ver­sion 1.2.5, tour­nez vous sim­ple­ment vers une ver­sion récente.

$ git clone https://github.com/vincentbernat/keepalived.git
$ cd keepalived
$ git checkout snmp
$ ./configure --enable-snmp
$ make

On ob­tient un exé­cu­table bin/keepalived. Il est pos­sible de l’uti­li­ser di­rec­te­ment ou de l’ins­tal­ler avec make install. Avec RHEL, SNMP n’est pas cor­rec­te­ment pa­ckagé et cela pro­voque des dif­fi­cul­tés lors de la com­pi­la­tion. Il faut ins­tal­ler quelques RPM sup­plé­men­taires (sensors-devel par exemple) et uti­li­ser cette com­mande à la place de make:

$ make LDFLAGS="$(net-snmp-config --agent-libs) -lpopt -lssl -lcrypto"

Utilisation#

Avant de pou­voir pro­fi­ter du sup­port SNMP, il faut vé­ri­fier la pré­sence de la ligne master agentx dans snmpd.conf. Cette ligne per­met à des pro­grammes comme Kee­pa­li­ved de se connec­ter à l’agent prin­ci­pal (snmpd) et d’en étendre les fonc­tion­na­li­tés. En­suite, Kee­pa­li­ved doit être lancé avec l’op­tion -x. On doit trou­ver une ligne de ce type dans les logs:

May 28 17:21:19 L1 Keepalived_vrrp: NET-SNMP version 5.4.3 AgentX subagent connected

Mise à jour (02.2012)

L’in­ter­face avec l’agent snmpd via le pro­to­cole AgentX est nor­ma­le­ment asyn­chrone. Tou­te­fois, la vé­ri­fi­ca­tion ré­gu­lière de la connexion avec cet agent s’ef­fec­tue de ma­nière syn­chrone. Cela si­gni­fie que si ce­lui-ci ne ré­pond pas ra­pi­de­ment, Kee­pa­li­ved peut se re­trou­ver blo­qué, ce qui est cri­tique pour la par­tie VRRP. Il est pos­sible de ré­duire ce pro­blème en ap­pli­quant cer­taines contre-mesures.

Lab#

Pour mettre en œuvre Kee­pa­li­ved, nous al­lons mon­ter un lab avec UML. Pour mieux com­prendre en quoi cela consiste, je vous in­vite à lire mon ar­ticle pré­cé­dent sur com­ment créer un lab ré­seau avec UML. Les sources pour ce lab sont sur GitHub. Chan­gez dès main­te­nant le che­min vers les sources de Kee­pa­li­ved en tête du script setup.

Keepalived & SNMP lab
Utilisation typique de Keepalived

Le lab com­prend quatre ser­veurs web qui se­ront vus comme un unique ser­vice vir­tuel grâce à Kee­pa­li­ved. Étant donné que ce der­nier sup­porte dé­sor­mais l’IPv6, nous al­lons aussi faire un peu d’IPv6.

Voici la confi­gu­ra­tion VRRP du pre­mier Kee­palived :

vrrp_instance VI_1 {
   state MASTER
   interface eth2
   dont_track_primary
   track_interface {
      eth0
      eth1
   }
   virtual_router_id 1
   priority 150
   advert_int 2
   authentication {
      auth_type PASS
      auth_pass blibli
   }
   virtual_ipaddress {
      1.1.1.15/24 dev eth0
      2001:db8::15/64 dev eth0
      192.168.1.1/24 dev eth1
      fd00::1/64 dev eth1
  }
}

On dé­fi­nit deux ser­veurs vir­tuels. L’un en IPv6, l’autre en IPv4. Voici un ex­trait de la confi­guration :

virtual_server_group VS_GROUP_IPv4 {
   1.1.1.15 80
}
virtual_server group VS_GROUP_IPv4 {
   delay_loop 10
   lb_algo rr
   lb_kind NAT
   protocol TCP
   real_server 192.168.1.10 80 {
      weight 1
      HTTP_GET {
        url {
          path /
          status_code 200
        }
        connect_timeout 10
      }
   }
   […]
}

Une fois le lab dé­marré (avec la com­mande ./setup), il est pos­sible de vé­ri­fier que tout fonc­tionne comme at­tendu en se pla­çant sur le nœud C1 et en in­ter­ro­geant les ser­vices virtuels :

$ curl  http://1.1.1.15
W3
$ curl  http://1.1.1.15
W2
$ wget -o /dev/null -O - 'http://[2001:db8::15]'
W3
$ wget -o /dev/null -O - 'http://[2001:db8::15]'
W2

On peut pro­vo­quer une bas­cule en fai­sant tom­ber sur L1 l’in­ter­face eth1 (par exemple). Tout conti­nue alors à fonc­tionner.

SNMP#

Pour vé­ri­fier le bon fonc­tion­ne­ment de la par­tie SNMP, on se place di­rec­te­ment sur L1. La MIB à uti­li­ser est KEEPALIVED-MIB. L’OID de base pour celle-ci a été ob­te­nue via le pro­jet De­bian. Il s’agit de .1.3.6.1.4.1.9586.100.5.

Par exemple, pour ob­te­nir la confi­gu­ra­tion de notre ins­tance VRRP :

# snmpwalk -v2c -cpublic localhost KEEPALIVED-MIB::vrrpInstanceTable
KEEPALIVED-MIB::vrrpInstanceName.1 = STRING: VI_1
KEEPALIVED-MIB::vrrpInstanceVirtualRouterId.1 = Gauge32: 1
KEEPALIVED-MIB::vrrpInstanceState.1 = INTEGER: master(2)
KEEPALIVED-MIB::vrrpInstanceInitialState.1 = INTEGER: master(2)
KEEPALIVED-MIB::vrrpInstanceWantedState.1 = INTEGER: master(2)
KEEPALIVED-MIB::vrrpInstanceBasePriority.1 = INTEGER: 150
KEEPALIVED-MIB::vrrpInstanceEffectivePriority.1 = INTEGER: 150
KEEPALIVED-MIB::vrrpInstanceVipsStatus.1 = INTEGER: allSet(1)
KEEPALIVED-MIB::vrrpInstancePrimaryInterface.1 = STRING: eth2
KEEPALIVED-MIB::vrrpInstanceTrackPrimaryIf.1 = INTEGER: tracked(1)
KEEPALIVED-MIB::vrrpInstanceAdvertisementsInt.1 = Gauge32: 2 seconds
KEEPALIVED-MIB::vrrpInstancePreempt.1 = INTEGER: preempt(1)
KEEPALIVED-MIB::vrrpInstancePreemptDelay.1 = Gauge32: 0 seconds
KEEPALIVED-MIB::vrrpInstanceAuthType.1 = INTEGER: password(1)
KEEPALIVED-MIB::vrrpInstanceLvsSyncDaemon.1 = INTEGER: disabled(2)
KEEPALIVED-MIB::vrrpInstanceGarpDelay.1 = Gauge32: 0 seconds
KEEPALIVED-MIB::vrrpInstanceSmtpAlert.1 = INTEGER: disabled(2)
KEEPALIVED-MIB::vrrpInstanceNotifyExec.1 = INTEGER: disabled(2)

Ou pour ob­te­nir des sta­tis­tiques via IPVS :

# snmpwalk -v 2c -c public localhost KEEPALIVED-MIB::virtualServerTable | grep Stats
KEEPALIVED-MIB::virtualServerStatsConns.1 = Gauge32: 6 connections
KEEPALIVED-MIB::virtualServerStatsConns.2 = Gauge32: 6 connections
KEEPALIVED-MIB::virtualServerStatsInPkts.1 = Counter32: 36 packets
KEEPALIVED-MIB::virtualServerStatsInPkts.2 = Counter32: 36 packets
KEEPALIVED-MIB::virtualServerStatsOutPkts.1 = Counter32: 24 packets
KEEPALIVED-MIB::virtualServerStatsOutPkts.2 = Counter32: 24 packets
KEEPALIVED-MIB::virtualServerStatsInBytes.1 = Counter64: 2970 bytes
KEEPALIVED-MIB::virtualServerStatsInBytes.2 = Counter64: 3312 bytes
KEEPALIVED-MIB::virtualServerStatsOutBytes.1 = Counter64: 2592 bytes
KEEPALIVED-MIB::virtualServerStatsOutBytes.2 = Counter64: 3072 bytes

Il est aussi pos­sible de désac­ti­ver un frontal :

# snmpget -v2c -cpublic localhost KEEPALIVED-MIB::realServerAddrType.1.1 \
>                               KEEPALIVED-MIB::realServerAddress.1.1
KEEPALIVED-MIB::realServerAddrType.1.1 = INTEGER: ipv4(1)
KEEPALIVED-MIB::realServerAddress.1.1 = Hex-STRING: C0 A8 01 0A
# snmpget -v2c -cpublic localhost KEEPALIVED-MIB::realServerAddress.2.1 \
>                               KEEPALIVED-MIB::realServerAddress.2.1
KEEPALIVED-MIB::realServerAddress.2.1 = Hex-STRING: FD 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10
KEEPALIVED-MIB::realServerAddress.2.1 = Hex-STRING: FD 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10
# snmpset -v2c -cprivate localhost KEEPALIVED-MIB::realServerWeight.1.1 = 0
KEEPALIVED-MIB::realServerWeight.1.1 = INTEGER: 0
# snmpset -v2c -cprivate localhost KEEPALIVED-MIB::realServerWeight.2.1 = 0
KEEPALIVED-MIB::realServerWeight.2.1 = INTEGER: 0

De­puis C1, on peut alors vé­ri­fier que nous ne sommes plus ren­voyés sur W1.

En­fin, il est pos­sible de gra­pher le nombre de connexions par se­conde à l’aide d’un script basé sur rrdtool. Voici le gra­phique que nous obtenons :

graphique obtenu avec rrdtool depuis des données récupérées via l'agent SNMP de Keepalived
Utilisation de rrdtool avec des valeurs récupérées via SNMP