12

Is there a way to view the current state (Master/Backup) using a command line inside a server instance?

Cheers

9 Answers 9

9

You could use the notify command to write out a state file.

       # for ANY state transition.
       # "notify" script is called AFTER the
       # notify_* script(s) and is executed
       # with 3 arguments provided by keepalived
       # (ie don’t include parameters in the notify line).
       # arguments
       # $1 = "GROUP"|"INSTANCE"
       # $2 = name of group or instance
       # $3 = target state of transition
       #     ("MASTER"|"BACKUP"|"FAULT")
       notify /path/notify.sh

The create a notify script like:

#!/bin/bash
# notify.sh

echo $1 $2 is in $3 state > /var/run/keepalive.$1.$2.state

And a get state script like:

#!/bin/bash
# getstate.sh

cat /var/run/keepalive.*.*.state
4
  • Nice solution! But what if you wanted to check the status without any state transition? Is it possible without using a patch?
    – Ben
    Dec 9, 2013 at 1:19
  • You mean if initial startup state is equal to current state? I guess you could just write out the /var/run/keepalive.*.*.stat file as part of your startup script.
    – dmourati
    Dec 9, 2013 at 1:44
  • I mean, if the keepalived is currently running. How can I determine the current running state without having a startup script?
    – Ben
    Dec 9, 2013 at 2:06
  • Try the above, I think it will work as is.
    – dmourati
    Dec 9, 2013 at 21:06
12

Dumping current state can be done by sending USR2 signal to keepalived parent process:

kill -USR2 $(cat /var/run/keepalived.pid)

Look inside file /tmp/keepalived.stats. Here are examples of the result (for Keepalived v2.0.7):

  • Master instance:

    VRRP Instance: Server1
      Advertisements:
        ...
      Became master: 15          <--- one more than the Released counter
      Released master: 14
      Packet Errors:
      ...
    
  • Backup instance:

    VRRP Instance: Server2
      Advertisements:
        ...
      Became master: 33          <--- equal to Released counter
      Released master: 33
      Packet Errors:
      ...
    

Note: if SELinux is used (CentOS 7), this may prevent writing to this file. You can get around this with this:

touch /tmp/keepalived.stats
chmod go+w /tmp/keepalived.stats
chcon -t keepalived_var_run_t /tmp/keepalived.stats

Now try sending the signal again.

2
7

Reading the current status through SNMP has proven the most reliable for me. To enable this you have to start keepalived with snmp support:

  • add -x to the deamon options (see /etc/sysconfig/keepalived on RedHat based systems)

and install snmpd.

You can then reliably query the status via

snmpget -Oq -Ov -v2c -cpublic localhost KEEPALIVED-MIB::vrrpInstanceState.1

It can also be done throug the notify scripts, but these don't always fire, leaving the state file out of sync with reality.

1
  • As of this post, this does NOT work on CentOS 7 from the native repositories. Yum in the repo is 1.2.13. This has been solved in later versions if you want to compile it.
    – jnovack
    Oct 8, 2015 at 15:56
7

If you issue the command:

journalctl -u keepalived

it has the state listed:

Jul 12 13:45:52 vmt007 Keepalived_vrrp[14335]: VRRP_Instance(VI_INT) Entering MASTER STATE

on the slave side you can see:

Jul 12 13:45:51 vmt008 Keepalived_vrrp[3569]: VRRP_Instance(VI_INT) Entering BACKUP STATE
6

DBus

With version 1.3.0, Keepalived added a DBus interface to query the VRRP state, monitor VRRP events using signals and even modify some VRRP configuration at runtime. As of 2021, the interface is for VRRP functionality only and does not expose anything related to the IPVS subsystem of Keepalived. DBus support is enabled with the enable_dbus option in the global_defs block of the config file. Some additional options (not explained here) can be specified too.

The Interface

You can access the DBus interface with any DBus client/library (e.g. dbus-send, gdbus, qdbus). I'm using systemd's busctl as an example here, because it has a very nice interface:

# busctl tree org.keepalived.Vrrp1
└─/org
  └─/org/keepalived
    └─/org/keepalived/Vrrp1
      ├─/org/keepalived/Vrrp1/Instance
      │ └─/org/keepalived/Vrrp1/Instance/eth0
      │   └─/org/keepalived/Vrrp1/Instance/eth0/1
      │     └─/org/keepalived/Vrrp1/Instance/eth0/1/IPv4
      └─/org/keepalived/Vrrp1/Vrrp

Two interfaces are available, the global org.keepalived.Vrrp1.Vrrp on /org/keepalived/Vrrp1/Vrrp:

# busctl introspect org.keepalived.Vrrp1 /org/keepalived/Vrrp1/Vrrp org.keepalived.Vrrp1.Vrrp
NAME                      TYPE      SIGNATURE RESULT/VALUE FLAGS
.CreateInstance           method    ssuu      -            -
.DestroyInstance          method    s         -            -
.PrintData                method    -         -            -
.PrintStats               method    -         -            -
.ReloadConfig             method    -         -            -
.VrrpReloaded             signal    -         -            -
.VrrpStarted              signal    -         -            -
.VrrpStopped              signal    -         -            -

And foreach VRRP instance, the org.keepalived.Vrrp1.Instance interface on paths according to this template /org/keepalived/Vrrp1/Instance/<interface>/<virtual-router-id>/<ip-family>. For an IPv4 VRRP instance with id 1 on eth1 named my-instance, we get the following:

# busctl introspect org.keepalived.Vrrp1 /org/keepalived/Vrrp1/Instance/eth0/1/IPv4 org.keepalived.Vrrp1.Instance
NAME                          TYPE      SIGNATURE RESULT/VALUE   FLAGS
.SendGarp                     method    -         -              -
.Name                         property  s         "my-instance"  emits-change
.State                        property  (us)      2 "Master"     emits-change
.VrrpStatusChange             signal    u         -              -

If you're using multiple keepalived processes and set the instance option or if you're using the network namespace feature with the namespace option, the paths also include the instance and/or namespace.

Querying State

To get the state of a particular instance, we can use the following command

# busctl get-property org.keepalived.Vrrp1 /org/keepalived/Vrrp1/Instance/eth0/1/IPv4  org.keepalived.Vrrp1.Instance State
(us) 2 "Master"

The returned property is a STRUCT, with a state code and a human readable name. The important states are 0 "Init", 1 "Backup", 2 "Master", 3 "Fault". The first three are official RFC 2338 states and the last one is defined by Keepalived. Different versions of Keepalived have some additional states. As of version 2.2.4, there are for example also 97 "Stop" and 98 "Deleted". Until version 2.0.0 there was for example also 4 "Goto master" and code 98 had different semantics 98 "Goto fault", therefore your code should rely mainly on the four main ones and also handle new state codes.

Monitoring Signals

You can also monitor state changes using DBus signals. The following output shows DBus signals when starting, introducing a fault and stopping a Keepalived instance:

# busctl monitor --match="type='signal',sender='org.keepalived.Vrrp1'
‣ Type=signal  Endian=l  Flags=1  Version=1  Priority=0 Cookie=5
  Sender=:1.80  Path=/org/keepalived/Vrrp1/hades_root/Instance/br_vrrp/67/IPv4  Interface=org.keepalived.Vrrp1.Instance  Member=VrrpStatusChange
  UniqueName=:1.80
  MESSAGE "u" {
          UINT32 1;
  };

‣ Type=signal  Endian=l  Flags=1  Version=1  Priority=0 Cookie=6
  Sender=:1.80  Path=/org/keepalived/Vrrp1/Instance/eth0/1/IPv4  Interface=org.keepalived.Vrrp1.Instance  Member=VrrpStatusChange
  UniqueName=:1.80
  MESSAGE "u" {
          UINT32 2;
  };

‣ Type=signal  Endian=l  Flags=1  Version=1  Priority=0 Cookie=7
  Sender=:1.80  Path=/org/keepalived/Vrrp1/hades_root/Instance/br_vrrp/67/IPv4  Interface=org.keepalived.Vrrp1.Instance  Member=VrrpStatusChange
  UniqueName=:1.80
  MESSAGE "u" {
          UINT32 3;
  };

‣ Type=signal  Endian=l  Flags=1  Version=1  Priority=0 Cookie=8
  Sender=:1.80  Path=/org/keepalived/Vrrp1/hades_root/Instance/br_vrrp/67/IPv4  Interface=org.keepalived.Vrrp1.Instance  Member=VrrpStatusChange
  UniqueName=:1.80
  MESSAGE "u" {
          UINT32 1;
  };

‣ Type=signal  Endian=l  Flags=1  Version=1  Priority=0 Cookie=9
  Sender=:1.80  Path=/org/keepalived/Vrrp1/hades_root/Instance/br_vrrp/67/IPv4  Interface=org.keepalived.Vrrp1.Instance  Member=VrrpStatusChange
  UniqueName=:1.80
  MESSAGE "u" {
          UINT32 2;
  };

‣ Type=signal  Endian=l  Flags=1  Version=1  Priority=0 Cookie=7
  Sender=:1.80  Path=/org/keepalived/Vrrp1/Instance/eth0/1/IPv4  Interface=org.keepalived.Vrrp1.Instance  Member=VrrpStatusChange
  UniqueName=:1.80
  MESSAGE "u" {
          UINT32 98;
  };

‣ Type=signal  Endian=l  Flags=1  Version=1  Priority=0 Cookie=8
  Sender=:1.80  Path=/org/keepalived/Vrrp1/Vrrp  Interface=org.keepalived.Vrrp1.Vrrp  Member=VrrpStopped
  UniqueName=:1.80
  MESSAGE "" {
  };

We observe:

  1. When Keepalived is started, no signal for the INIT state is emitted.
  2. The instance transitions to BACKUP state (state BACKUP config was used).
  3. The instance transitions to MASTER state.
  4. A fault is detected and the instance transitions to FAULT state.
  5. The instance recovers via going to BACKUP and then MASTER again.
  6. Keepalived is stopped and the instance transitions to the STOP state.
  7. Keepalived also emits a global VrrpStopped signal.

Keepalived must be built with the --enable-dbus configure option for this to work though. Most binary distributions however should have enabled it by now. Debian and Ubuntu for example do it since package version 1:1.3.9-1.

1
  • on Ubuntu 20 this works out of the box, only need to enable dbus in the config as mentioned above
    – gdanov
    Nov 13, 2021 at 9:21
3

Using the following command

sudo kill -s $(keepalived --signum=DATA) $(cat /var/run/keepalived.pid)
cat /tmp/keepalived.data

You will find

State = MASTER   or 
State = BACKUP
0

From man 8 keepalived:

SIGNALS
       keepalived reacts to a set of signals.  You can send a signal to the parent keepalived process using the
       following:

              kill -SIGNAL $(cat /var/run/keepalived.pid)

       Note that -SIGNAL must be replaced with the actual signal you are trying to send, e.g. with HUP. So it
       then becomes:

              kill -HUP $(cat /var/run/keepalived.pid)

       HUP    This causes keepalived to close down all interfaces, reload its configuration, and start up with
              the new configuration.

       TERM, INT
              keepalived will shut down.

       USR1   Write configuration data to /tmp/keepalived.data

       USR2   Write statistics info to /tmp/keepalived.stats

So you only have to grep the regular file /tmp/keepalived.data

pid=$(cat /var/run/keepalived.pid 2>/dev/null)
[[ $? -eq 0 ]] || { printf 'no keepalived running\n' >&2; exit 0; }
kill -USR1 $pid
grep -E 'VRRP Instance|State' /tmp/keepalived.data

Obtaining something like this:

 VRRP Instance = VRRP_A
   State = MASTER
 VRRP Instance = VRRP_B
   State = MASTER
0
Keepalived v2.2.4 (08/21,2021)

Copyright(C) 2001-2021 Alexandre Cassen, <[email protected]>

Built with kernel headers for Linux 5.15.27
Running on Linux 5.15.0-83-generic #92-Ubuntu SMP Mon Aug 14 09:30:42 UTC 2023
Distro: Ubuntu 22.04.3 LTS

check interface IPs, the interface of the master node does have the virtual IP, Vice versa

VM2 - Secondary node

ip add
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:34:9d:03 brd ff:ff:ff:ff:ff:ff
    altname enp2s1
    inet 172.16.252.3/22 brd 172.16.255.255 scope global ens33
       valid_lft forever preferred_lft forever

VM1 Master Node with virtual IP: 172.16.252.10

ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: ens35: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:f3:89:53 brd ff:ff:ff:ff:ff:ff
    altname enp2s3
    inet 172.16.252.2/22 brd 172.16.255.255 scope global ens35
       valid_lft forever preferred_lft forever
    inet 172.16.252.10/22 scope global secondary ens35
       valid_lft forever preferred_lft forever
-1

I use this simple line:

service keepalived status | tail -1

Sorry, but this won't work if any errors occur on the last line.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .