Forum Discussion

Jakk127's avatar
Jakk127
Icon for Nimbostratus rankNimbostratus
Jul 30, 2019

Health monitor to mark pool member up when a ping FAILS (inverse ping health check)

Hello,

 

I am attempting to figure out the best way to create a health monitor that is an inverse of the ICMP monitor-when ping to an IP fails, I want the pool member to be marked UP. When ping to an IP succeeds, I want the pool member to be marked DOWN.

 

My first attempt at this was using an external monitor with the below script; that does not seem to be working.

 

#!/bin/sh

ping -c 5 [IP here] > /dev/null && exit || echo "down"

exit $?

 

I am running 11.5.3 HF2. Does anyone know if the best way to achieve this beahvior, or why my script isn't working? It looks like it outputs nothing to stdout (should cause the monitor to fail) unless the ping fails, at which point it outputs something (should cause the monitor to pass)

  • JG's avatar
    JG
    Icon for Cumulonimbus rankCumulonimbus

    It sounds like you are trying to set up a service redundancy/failover solution. If that is the case, in the absence of details of your business requirement, it could be suggested that you would be better off setting up a health monitor for your remote service with a more reliable protocol than ICMP; e.g. an HTTP service, which is much easier and handy to set up.

  • Thanks for the response.

     

    Are you saying that I should create the above script in a separate file as /usr/bin/monitors/custom_monitor.bash instead of uploading it as a custom monitor in the file section? If so, how do I call it then, and is the argument that I specify in the external monitor the IP address to ping? I want to ping a totally external address to see if it responds-NOT ping the actual pool member itself.

     

    The reason for this is that I only want the pool/VS to be active if the external IP stops responding to ping, because that IP is tied to a remote site, and this VS needs to become active for that site if the IP stops responding.

     

    I'm still a bit confused-when I run my script manually, I get no script output unless the IP does not to ping-that to me means what you said-that the monitor should be marked as down as long as the IP responds as there is no output.

    • Hello.

      Normally external monitors are configured with final evaluation:

      if [ $? -eq 0 ]
      ...

      Which means, if last execution was good, mark the node as UP. In your case you need exactly the opposite, for this reason you need to switch it to "1".

      BTW, the process to create that external monitor is

      1. upload the script to F5
      2. create the monitor and reference that script.

      First arguments are automatically updated ($1 : IP, $2 : Port), the rest of them depend on your monitor configuration.

      Here some doc about external monitors

      REF - https://devcentral.f5.com/s/articles/ltm-external-monitors-the-basics

      KR,

      Dario.

  • Hello.

    Take into account that any output in the script execution will produce an UP state in the monitor. So, the best way to fix your problems is something like this.

    #!/bin/bash
     
    # Remove IPv6/IPv4 compatibility prefix (LTM passes addresses in IPv6 format)
    IP=`echo $1 | sed 's/::ffff://'`
     
    ping -c5 -W2 $IP 2>&1 > /dev/null
     
    if [ $? -eq 1 ]
    then
       rm -f $pidfile
       echo "UP"
    else
       rm -f $pidfile
    fi

    Some additional doc about external monitors:

    REF - https://devcentral.f5.com/s/articles/ltm-external-monitors-the-basics

    I recommend you to use always this template for external monitors

    REF - https://devcentral.f5.com/s/articles/template-for-external-monitors

    The complete script with your particular scenario would be like this ->

    #!/bin/bash
     
    # Save as /usr/bin/monitors/custom_monitor.bash
    # Make executable using chmod 700 custom_monitor.bash
     
    # Use a custom shell command to perform a health check of the pool member IP address and port
     
    # Log debug to local0.debug (/var/log/ltm)?
    # Check if a variable named DEBUG exists from the monitor definition
    # This can be set using a monitor variable DEBUG=0 or 1
    if [ -n "$DEBUG" ]
    then
       if [ $DEBUG -eq 1 ]; then echo "EAV `basename $0`: \$DEBUG: $DEBUG" | logger -p local0.debug; fi
    else
       # If the monitor config didn't specify debug, enable/disable it here
       DEBUG=0
       #echo "EAV `basename $0`: \$DEBUG: $DEBUG" | logger -p local0.debug
    fi
     
    # Remove IPv6/IPv4 compatibility prefix (LTM passes addresses in IPv6 format)
    IP=`echo $1 | sed 's/::ffff://'`
     
    # Save the port for use in the shell command
    PORT=$2
     
    # Check if there is a prior instance of the monitor running
    pidfile="/var/run/`basename $0`.$IP.$PORT.pid"
    if [ -f $pidfile ]
    then
       kill -9 `cat $pidfile` > /dev/null 2>&1
       echo "EAV `basename $0`: exceeded monitor interval, needed to kill ${IP}:${PORT} with PID `cat $pidfile`" | logger -p local0.error
    fi
     
    # Add the current PID to the pidfile
    echo "$$" > $pidfile
     
    # Debug
    if [ $DEBUG -eq 1 ]
    then
       ####  Customize the log statement here if you want to log the command run or the output ####
       echo "EAV `basename $0`: Running for ${IP}:${PORT} using custom command" | logger -p local0.debug
    fi
     
    ping -c5 -W2 $IP 2>&1 > /dev/null
     
    if [ $? -eq 1 ]
    then
       rm -f $pidfile
       if [ $DEBUG -eq 1 ]; then echo "EAV `basename $0`: Succeeded for ${IP}:${PORT}" | logger -p local0.debug; fi
       echo "UP"
    else
       rm -f $pidfile
       if [ $DEBUG -eq 1 ]; then echo "EAV `basename $0`: Failed for ${IP}:${PORT}" | logger -p local0.debug; fi
    fi

    KR,

    Dario.