High Availability for Node-RED (and more) with Node-RED

Hello all,

working with Node-RED for years now for hobby and work. But still I am sometimes surprised how it can leverage automation.

It all started with a raspberry pi running Node-RED on a SD card. With the growing of the automations it was already getting obvious how important this Node-RED instance became. It became for a lot of lights and primary household appliances a single point of failure. So when the first SD card crashed I had to do some damage-control for the WAF (Wife-Acceptance-Factor). This led me through a great (and long) journey of learning new things and finally I am happy with the current result of a high available solution for Node-RED at home.

The main part of the automations were on that timed based on MQTT so just 2 pi's with both the same flows running would be a little problematic because every mqtt event will be executed twice. For instance a toggle command would switch the light on, while the other will switch it directly off.

My first approach was to make it on a docker cluster with 2 pi's. So I was aiming for an automated failover. Node-RED or RPI dies, other pi will start a new instance of the NR container. So I had to learn docker swarm and came to the conclusion I needed a third RPI with docker to have a concensus. So the pi cloud grows.

Part of this solutions was to have a collective storage for storing the flow files, in this first attempt it was a NFS share on a Synology NAS that was mounted on all RPI's.

After that the conclusion came quickly the stability improved. This was mostly due to the fact that most write actions (influx/mqtt) were now done on the network share and not on the SD card anymore.

The cluster was reachable through a round robin DNS address. (One name, all IP addresses).

But there were still some things I wanted to tackle:
-The NAS as SPOF (single point of failure)
-The amount of time docker needed to start a new instance of node red.
-If a node was down the cluster was not reachable on that specific IP address.

I solved them by:

-For the NAS SPOF I changed the SD cards for SSD's connected to the pi through USB enclosures. And installed GlusterFS on all three to have a storage cluster devided over the pi cluster.

-To accelerate the failover of the node red instance I had to take into consideration what kind of flows were running on the NR instance. For HTTP it was no problem to run active-active solutions, but for mqtt this is a challenge like mentioned above.

I got inspired by this youtube movie from Kurt Braun and build myself a heart beat system in Node Red.

[{"id":"93518d52.ef69f","type":"tab","label":"Heartbeat","disabled":false,"info":""},{"id":"f1fa8f7.92a347","type":"switch","z":"93518d52.ef69f","name":"host?","property":"host","propertyType":"global","rules":[{"t":"empty"},{"t":"null"},{"t":"else"}],"checkall":"true","repair":false,"outputs":3,"x":410,"y":140,"wires":[["b480b625.b12d68"],["b480b625.b12d68"],["b8a02164.a8e01"]]},{"id":"299156be.857e5a","type":"change","z":"93518d52.ef69f","name":"","rules":[{"t":"set","p":"host","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1000,"y":120,"wires":[["f9cfb3cb.04622"]]},{"id":"b8a02164.a8e01","type":"change","z":"93518d52.ef69f","name":"set host","rules":[{"t":"set","p":"payload","pt":"msg","to":"host","tot":"global"}],"action":"","property":"","from":"","to":"","reg":false,"x":600,"y":160,"wires":[["f9cfb3cb.04622","9a3077b4.2867e8"]]},{"id":"b480b625.b12d68","type":"file in","z":"93518d52.ef69f","name":"","filename":"/hostetc/hostname","format":"utf8","chunk":false,"sendError":false,"encoding":"none","x":630,"y":120,"wires":[["e3bf9515.6a9b78"]]},{"id":"c007a121.f126","type":"trigger","z":"93518d52.ef69f","name":"","op1":"true","op2":"false","op1type":"bool","op2type":"bool","duration":"1000","extend":true,"overrideDelay":false,"units":"ms","reset":"","bytopic":"topic","topic":"topic","outputs":1,"x":580,"y":360,"wires":[["eafd9045.c9b8d"]]},{"id":"f9cfb3cb.04622","type":"template","z":"93518d52.ef69f","name":"set topic","field":"topic","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"noderedha/{{global.host}}/pulse","output":"str","x":1160,"y":160,"wires":[["d5df44d3.6fae48"]]},{"id":"d5df44d3.6fae48","type":"mqtt out","z":"93518d52.ef69f","name":"","topic":"","qos":"","retain":"","broker":"8dc8d818.347f98","x":1310,"y":160,"wires":[]},{"id":"799d202c.1651c","type":"mqtt in","z":"93518d52.ef69f","name":"","topic":"noderedha/+/pulse","qos":"2","datatype":"auto","broker":"8dc8d818.347f98","x":210,"y":360,"wires":[["904831f8.130ca"]]},{"id":"e3bf9515.6a9b78","type":"string","z":"93518d52.ef69f","name":"","methods":[{"name":"strip","params":[{"type":"str","value":"\\n"}]},{"name":"decodeHTMLEntities","params":[]}],"prop":"payload","propout":"payload","object":"msg","objectout":"msg","x":810,"y":120,"wires":[["299156be.857e5a","9a3077b4.2867e8"]]},{"id":"904831f8.130ca","type":"change","z":"93518d52.ef69f","name":"","rules":[{"t":"set","p":"host","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":410,"y":360,"wires":[["c007a121.f126"]]},{"id":"eafd9045.c9b8d","type":"function","z":"93518d52.ef69f","name":"set state node","func":"var context = \"noderedha.\"+msg.host+\".state\";\nglobal.set(context, msg.payload, \"memory\");\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":760,"y":360,"wires":[["310df807.b704f8"]]},{"id":"a068d750.751d58","type":"inject","z":"93518d52.ef69f","name":"500 ms","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"0.5","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":260,"y":140,"wires":[["f1fa8f7.92a347"]]},{"id":"2ed01163.5c54ee","type":"change","z":"93518d52.ef69f","name":"2raspdock master","rules":[{"t":"set","p":"master","pt":"msg","to":"2raspdock","tot":"str"},{"t":"set","p":"noderedha.0raspdockman.master","pt":"global","to":"false","tot":"bool"},{"t":"set","p":"noderedha.1raspdock.master","pt":"global","to":"false","tot":"bool"},{"t":"set","p":"noderedha.2raspdock.master","pt":"global","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":1430,"y":340,"wires":[["69cc4908.994ac8"]]},{"id":"310df807.b704f8","type":"switch","z":"93518d52.ef69f","name":"2raspdock online?","property":"noderedha.2raspdock.state","propertyType":"global","rules":[{"t":"true"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":990,"y":360,"wires":[["2ed01163.5c54ee"],["bc33ad1d.bf35f"]]},{"id":"f9e691a9.86d01","type":"change","z":"93518d52.ef69f","name":"1raspdock master","rules":[{"t":"set","p":"master","pt":"msg","to":"1raspdock","tot":"str"},{"t":"set","p":"0raspdockman.master","pt":"global","to":"false","tot":"bool"},{"t":"set","p":"1raspdock.master","pt":"global","to":"true","tot":"bool"},{"t":"set","p":"2raspdock.master","pt":"global","to":"false","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":1430,"y":380,"wires":[["69cc4908.994ac8"]]},{"id":"bc33ad1d.bf35f","type":"switch","z":"93518d52.ef69f","name":"1raspdock online?","property":"noderedha.1raspdock.state","propertyType":"global","rules":[{"t":"true"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":1210,"y":400,"wires":[["f9e691a9.86d01"],["ac6076fa.dfbfd8"]]},{"id":"ac6076fa.dfbfd8","type":"change","z":"93518d52.ef69f","name":"0raspdockman master","rules":[{"t":"set","p":"master","pt":"msg","to":"0raspdockman","tot":"str"},{"t":"set","p":"0raspdockman.master","pt":"global","to":"true","tot":"bool"},{"t":"set","p":"1raspdock.master","pt":"global","to":"false","tot":"bool"},{"t":"set","p":"2raspdock.master","pt":"global","to":"false","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":1440,"y":420,"wires":[["69cc4908.994ac8"]]},{"id":"51fe151f.c747ac","type":"change","z":"93518d52.ef69f","name":"master = true","rules":[{"t":"set","p":"noderedha.master.b","pt":"global","to":"true","tot":"bool"},{"t":"set","p":"noderedha.master.host","pt":"global","to":"master","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1830,"y":360,"wires":[["4e305936.d22e58"]]},{"id":"661accd6.9b06a4","type":"change","z":"93518d52.ef69f","name":"master = false","rules":[{"t":"set","p":"noderedha.master.b","pt":"global","to":"false","tot":"bool"},{"t":"set","p":"noderedha.master.host","pt":"global","to":"master","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1840,"y":400,"wires":[["4e305936.d22e58"]]},{"id":"69cc4908.994ac8","type":"switch","z":"93518d52.ef69f","name":"is this host master?","property":"master","propertyType":"msg","rules":[{"t":"eq","v":"host","vt":"global"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":1650,"y":380,"wires":[["51fe151f.c747ac"],["661accd6.9b06a4"]]},{"id":"e0953b55.868398","type":"switch","z":"93518d52.ef69f","name":"Master?","property":"noderedha.master.b","propertyType":"global","rules":[{"t":"true"}],"checkall":"true","repair":false,"outputs":1,"x":820,"y":520,"wires":[["bfe0f80f.4de768"]]},{"id":"bfe0f80f.4de768","type":"debug","z":"93518d52.ef69f","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":970,"y":520,"wires":[]},{"id":"4e305936.d22e58","type":"change","z":"93518d52.ef69f","name":"who is master","rules":[{"t":"set","p":"payload","pt":"msg","to":"noderedha.master","tot":"global"}],"action":"","property":"","from":"","to":"","reg":false,"x":2020,"y":380,"wires":[["288a01bd.65ba3e"]]},{"id":"288a01bd.65ba3e","type":"link out","z":"93518d52.ef69f","name":"master?","links":["e834912.10efd7"],"x":2135,"y":380,"wires":[]},{"id":"e834912.10efd7","type":"link in","z":"93518d52.ef69f","name":"","links":["288a01bd.65ba3e"],"x":1555,"y":140,"wires":[["e6c94a10.78cd18","1e798fde.cb786"]]},{"id":"e6c94a10.78cd18","type":"debug","z":"93518d52.ef69f","name":"Master?","active":true,"tosidebar":false,"console":false,"tostatus":true,"complete":"payload.b","targetType":"msg","statusVal":"payload.b","statusType":"auto","x":1690,"y":100,"wires":[]},{"id":"1e798fde.cb786","type":"debug","z":"93518d52.ef69f","name":"Master","active":true,"tosidebar":false,"console":false,"tostatus":true,"complete":"payload.host","targetType":"msg","statusVal":"payload.host","statusType":"auto","x":1680,"y":160,"wires":[]},{"id":"9a3077b4.2867e8","type":"debug","z":"93518d52.ef69f","name":"","active":true,"tosidebar":false,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":1030,"y":60,"wires":[]},{"id":"e8e7bb73.c16ed8","type":"http in","z":"93518d52.ef69f","name":"","url":"/test","method":"get","upload":false,"swaggerDoc":"","x":350,"y":880,"wires":[["c08bdb57.496338"]]},{"id":"83e8a20a.1c17","type":"http response","z":"93518d52.ef69f","name":"","statusCode":"","headers":{},"x":670,"y":880,"wires":[]},{"id":"c08bdb57.496338","type":"template","z":"93518d52.ef69f","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"Hello from {{global.host}}","output":"str","x":520,"y":880,"wires":[["83e8a20a.1c17"]]},{"id":"3cf33ef.24a69c2","type":"inject","z":"93518d52.ef69f","name":"20s","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"20","crontab":"","once":true,"onceDelay":"5","topic":"","payload":"","payloadType":"date","x":750,"y":320,"wires":[["310df807.b704f8"]]},{"id":"d6df7f08.3a7b3","type":"comment","z":"93518d52.ef69f","name":"heartbeat","info":"","x":270,"y":60,"wires":[]},{"id":"bcf87a52.5e1da8","type":"comment","z":"93518d52.ef69f","name":"master","info":"","x":230,"y":300,"wires":[]},{"id":"bb2c986a.ff12d8","type":"inject","z":"93518d52.ef69f","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":640,"y":520,"wires":[["e0953b55.868398"]]},{"id":"8dc8d818.347f98","type":"mqtt-broker","name":"","broker":"mqtt.wesselink","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closePayload":"","willTopic":"","willQos":"0","willPayload":""}]

All Mqtt flows have now a switch node to check if they are master or not.
Failover is done within 1 second.

-To solve the problem that all my sensors and other system can reach the cluster on this pi I installed keepalived on the raspberry pi's. But I did something wrong and before I fixed it I just thought in my mind what to do and how would I build that in Node-RED. The most important thing is that the master host is listening to a virtual IP address. On linux setting this is very simple with one command: "sudo ifconfig eth0:0 192.168.x.xxx". So together with the flow that I had above. I just opted to install an extra node red instance on every node to handle the Virtual IP address.

[{"id":"5bfd9057.fd1ba","type":"tab","label":"Heartbeat/VIP","disabled":false,"info":""},{"id":"f1fa8f7.92a347","type":"switch","z":"5bfd9057.fd1ba","name":"","property":"host","propertyType":"global","rules":[{"t":"empty"},{"t":"null"},{"t":"else"}],"checkall":"true","repair":false,"outputs":3,"x":710,"y":520,"wires":[["b480b625.b12d68"],["b480b625.b12d68"],["b8a02164.a8e01"]]},{"id":"299156be.857e5a","type":"change","z":"5bfd9057.fd1ba","name":"","rules":[{"t":"set","p":"host","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1260,"y":500,"wires":[["672bd18e.ce6b9"]]},{"id":"b8a02164.a8e01","type":"change","z":"5bfd9057.fd1ba","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"host","tot":"global"}],"action":"","property":"","from":"","to":"","reg":false,"x":900,"y":540,"wires":[["9a3077b4.2867e8","672bd18e.ce6b9"]]},{"id":"b480b625.b12d68","type":"file in","z":"5bfd9057.fd1ba","name":"","filename":"/etc/hostname","format":"utf8","chunk":false,"sendError":false,"encoding":"none","x":900,"y":500,"wires":[["e3bf9515.6a9b78"]]},{"id":"e3bf9515.6a9b78","type":"string","z":"5bfd9057.fd1ba","name":"","methods":[{"name":"strip","params":[{"type":"str","value":"\\n"}]},{"name":"decodeHTMLEntities","params":[]}],"prop":"payload","propout":"payload","object":"msg","objectout":"msg","x":1090,"y":500,"wires":[["299156be.857e5a","9a3077b4.2867e8"]]},{"id":"eafd9045.c9b8d","type":"function","z":"5bfd9057.fd1ba","name":"set state node","func":"var context = \"noderedha.\"+msg.host+\".state\";\nglobal.set(context, msg.payload, \"memory\");\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":540,"y":700,"wires":[["310df807.b704f8"]]},{"id":"a068d750.751d58","type":"inject","z":"5bfd9057.fd1ba","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"0.5","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":150,"y":520,"wires":[["234acba9.4503f4"]]},{"id":"2ed01163.5c54ee","type":"change","z":"5bfd9057.fd1ba","name":"","rules":[{"t":"set","p":"master","pt":"msg","to":"2raspdock","tot":"str"},{"t":"set","p":"noderedha.0raspdockman.master","pt":"global","to":"false","tot":"bool"},{"t":"set","p":"noderedha.1raspdock.master","pt":"global","to":"false","tot":"bool"},{"t":"set","p":"noderedha.2raspdock.master","pt":"global","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":1060,"y":660,"wires":[["69cc4908.994ac8"]]},{"id":"310df807.b704f8","type":"switch","z":"5bfd9057.fd1ba","name":"","property":"noderedha.2raspdock.state","propertyType":"global","rules":[{"t":"true"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":710,"y":700,"wires":[["2ed01163.5c54ee"],["bc33ad1d.bf35f"]]},{"id":"f9e691a9.86d01","type":"change","z":"5bfd9057.fd1ba","name":"","rules":[{"t":"set","p":"master","pt":"msg","to":"1raspdock","tot":"str"},{"t":"set","p":"noderedha0raspdockman.master","pt":"global","to":"false","tot":"bool"},{"t":"set","p":"noderedha1raspdock.master","pt":"global","to":"true","tot":"bool"},{"t":"set","p":"noderedha2raspdock.master","pt":"global","to":"false","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":1060,"y":700,"wires":[["69cc4908.994ac8"]]},{"id":"bc33ad1d.bf35f","type":"switch","z":"5bfd9057.fd1ba","name":"","property":"noderedha.1raspdock.state","propertyType":"global","rules":[{"t":"true"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":890,"y":720,"wires":[["f9e691a9.86d01"],["ac6076fa.dfbfd8"]]},{"id":"ac6076fa.dfbfd8","type":"change","z":"5bfd9057.fd1ba","name":"","rules":[{"t":"set","p":"master","pt":"msg","to":"0raspdockman","tot":"str"},{"t":"set","p":"noderedha0raspdockman.master","pt":"global","to":"true","tot":"bool"},{"t":"set","p":"noderedha1raspdock.master","pt":"global","to":"false","tot":"bool"},{"t":"set","p":"noderedha2raspdock.master","pt":"global","to":"false","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":1060,"y":740,"wires":[["69cc4908.994ac8"]]},{"id":"51fe151f.c747ac","type":"change","z":"5bfd9057.fd1ba","name":"","rules":[{"t":"set","p":"noderedha.master.b","pt":"global","to":"true","tot":"bool"},{"t":"set","p":"noderedha.master.host","pt":"global","to":"master","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1480,"y":680,"wires":[["4e305936.d22e58"]]},{"id":"661accd6.9b06a4","type":"change","z":"5bfd9057.fd1ba","name":"","rules":[{"t":"set","p":"noderedha.master.b","pt":"global","to":"false","tot":"bool"},{"t":"set","p":"noderedha.master.host","pt":"global","to":"master","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1480,"y":720,"wires":[["4e305936.d22e58"]]},{"id":"69cc4908.994ac8","type":"switch","z":"5bfd9057.fd1ba","name":"","property":"master","propertyType":"msg","rules":[{"t":"eq","v":"host","vt":"global"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":1290,"y":700,"wires":[["51fe151f.c747ac"],["661accd6.9b06a4"]]},{"id":"4e305936.d22e58","type":"change","z":"5bfd9057.fd1ba","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"noderedha.master","tot":"global"}],"action":"","property":"","from":"","to":"","reg":false,"x":1680,"y":700,"wires":[["288a01bd.65ba3e"]]},{"id":"288a01bd.65ba3e","type":"link out","z":"5bfd9057.fd1ba","name":"master?","links":["e834912.10efd7","68c9f101.81598"],"x":1815,"y":700,"wires":[]},{"id":"e834912.10efd7","type":"link in","z":"5bfd9057.fd1ba","name":"","links":["288a01bd.65ba3e"],"x":695,"y":100,"wires":[["e6c94a10.78cd18","1e798fde.cb786"]]},{"id":"e6c94a10.78cd18","type":"debug","z":"5bfd9057.fd1ba","name":"Master?","active":true,"tosidebar":false,"console":false,"tostatus":true,"complete":"payload.b","targetType":"msg","statusVal":"payload.b","statusType":"auto","x":830,"y":60,"wires":[]},{"id":"1e798fde.cb786","type":"debug","z":"5bfd9057.fd1ba","name":"Master","active":true,"tosidebar":false,"console":false,"tostatus":true,"complete":"payload.host","targetType":"msg","statusVal":"payload.host","statusType":"auto","x":820,"y":120,"wires":[]},{"id":"9a3077b4.2867e8","type":"debug","z":"5bfd9057.fd1ba","name":"","active":true,"tosidebar":false,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":1450,"y":480,"wires":[]},{"id":"4cca1ddc.762934","type":"http in","z":"5bfd9057.fd1ba","name":"","url":"/testinfra","method":"get","upload":false,"swaggerDoc":"","x":150,"y":80,"wires":[["d8f1398e.61e678"]]},{"id":"db8db01b.d57d1","type":"http response","z":"5bfd9057.fd1ba","name":"","statusCode":"","headers":{},"x":500,"y":80,"wires":[]},{"id":"d8f1398e.61e678","type":"template","z":"5bfd9057.fd1ba","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"hello from {{global.host}}","output":"str","x":330,"y":80,"wires":[["db8db01b.d57d1"]]},{"id":"958b6c65.d99ca","type":"n2n out","z":"5bfd9057.fd1ba","iface":"","name":"","bcast":true,"x":1750,"y":540,"wires":[]},{"id":"71bffe7.610af","type":"function","z":"5bfd9057.fd1ba","name":"","func":"var msg_o = {};\nvar process_data = 1212;\n\nmsg_o = {payload : process_data};\n\nreturn msg_o;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1620,"y":540,"wires":[["958b6c65.d99ca"]]},{"id":"672bd18e.ce6b9","type":"change","z":"5bfd9057.fd1ba","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"clusterha","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1470,"y":540,"wires":[["71bffe7.610af"]]},{"id":"4bac890f.a55b68","type":"trigger","z":"5bfd9057.fd1ba","name":"","op1":"true","op2":"false","op1type":"bool","op2type":"bool","duration":"1000","extend":true,"overrideDelay":false,"units":"ms","reset":"","bytopic":"topic","topic":"host","outputs":1,"x":340,"y":700,"wires":[["eafd9045.c9b8d"]]},{"id":"6493a572.aba46c","type":"n2n in","z":"5bfd9057.fd1ba","name":"","topic":"","iface":"","rate":"0","ignore":true,"bcast":true,"x":170,"y":700,"wires":[["4bac890f.a55b68"]]},{"id":"386a4aa7.d65ed6","type":"exec","z":"5bfd9057.fd1ba","command":"ifconfig","addpay":"","append":"","useSpawn":"false","timer":"","oldrc":false,"name":"","x":480,"y":960,"wires":[["4ab2391f.4d9578"],[],[]]},{"id":"4ab2391f.4d9578","type":"switch","z":"5bfd9057.fd1ba","name":"","property":"payload","propertyType":"msg","rules":[{"t":"cont","v":"eth0:0","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":630,"y":960,"wires":[["fc72aae3.4469e8"],["be7c490b.1e0e18"]]},{"id":"c760bb6b.aa8298","type":"delay","z":"5bfd9057.fd1ba","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"5","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"x":300,"y":960,"wires":[["386a4aa7.d65ed6"]]},{"id":"fc72aae3.4469e8","type":"switch","z":"5bfd9057.fd1ba","name":"","property":"noderedha.master.b","propertyType":"global","rules":[{"t":"true"},{"t":"false"}],"checkall":"true","repair":false,"outputs":2,"x":770,"y":920,"wires":[[],["3dcfc941.f0ec86"]]},{"id":"be7c490b.1e0e18","type":"switch","z":"5bfd9057.fd1ba","name":"","property":"noderedha.master.b","propertyType":"global","rules":[{"t":"true"},{"t":"false"}],"checkall":"true","repair":false,"outputs":2,"x":770,"y":980,"wires":[["232490c3.317f7"],[]]},{"id":"232490c3.317f7","type":"exec","z":"5bfd9057.fd1ba","command":"sudo ifconfig eth0:0 192.168.2.206","addpay":"","append":"","useSpawn":"false","timer":"","oldrc":false,"name":"","x":1020,"y":980,"wires":[[],[],[]]},{"id":"3dcfc941.f0ec86","type":"exec","z":"5bfd9057.fd1ba","command":"sudo ifconfig eth0:0 down","addpay":"","append":"","useSpawn":"false","timer":"","oldrc":false,"name":"","x":990,"y":920,"wires":[[],[],[]]},{"id":"d5735d97.5aa37","type":"inject","z":"5bfd9057.fd1ba","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"5","crontab":"","once":true,"onceDelay":"5","topic":"","payload":"","payloadType":"date","x":310,"y":920,"wires":[["386a4aa7.d65ed6"]]},{"id":"68c9f101.81598","type":"link in","z":"5bfd9057.fd1ba","name":"","links":["288a01bd.65ba3e"],"x":155,"y":960,"wires":[["c760bb6b.aa8298"]]},{"id":"45168dcb.123ac4","type":"exec","z":"5bfd9057.fd1ba","command":"sudo systemctl status docker","addpay":"","append":"","useSpawn":"false","timer":"","oldrc":false,"name":"","x":400,"y":280,"wires":[["1991860f.0d2d9a"],[],[]]},{"id":"22c9dc18.968ea4","type":"inject","z":"5bfd9057.fd1ba","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"5","crontab":"","once":true,"onceDelay":"5","topic":"","payload":"","payloadType":"date","x":150,"y":280,"wires":[["45168dcb.123ac4"]]},{"id":"1991860f.0d2d9a","type":"switch","z":"5bfd9057.fd1ba","name":"","property":"payload","propertyType":"msg","rules":[{"t":"cont","v":"active (running)","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":670,"y":300,"wires":[["93fdfc48.4017c"],["35129e7d.a0bde2"]]},{"id":"93fdfc48.4017c","type":"change","z":"5bfd9057.fd1ba","name":"","rules":[{"t":"set","p":"dockeractive","pt":"global","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":860,"y":280,"wires":[[]]},{"id":"35129e7d.a0bde2","type":"change","z":"5bfd9057.fd1ba","name":"","rules":[{"t":"set","p":"dockeractive","pt":"global","to":"false","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":860,"y":320,"wires":[[]]},{"id":"234acba9.4503f4","type":"switch","z":"5bfd9057.fd1ba","name":"Docker active?","property":"dockeractive","propertyType":"global","rules":[{"t":"true"}],"checkall":"true","repair":false,"outputs":1,"x":430,"y":520,"wires":[["f1fa8f7.92a347"]]},{"id":"14637fe4.98aef","type":"comment","z":"5bfd9057.fd1ba","name":"docker active","info":"","x":130,"y":220,"wires":[]},{"id":"842ae888.4c92f8","type":"comment","z":"5bfd9057.fd1ba","name":"heartbeat","info":"","x":120,"y":460,"wires":[]},{"id":"b7e5e083.d36f2","type":"comment","z":"5bfd9057.fd1ba","name":"who is master?","info":"","x":140,"y":620,"wires":[]},{"id":"3315548a.c5a29c","type":"comment","z":"5bfd9057.fd1ba","name":"if master set VIP active","info":"","x":160,"y":840,"wires":[]}]

I changed the method of sending the heartbeat here to an UDP broadcast instead of mqtt and I build in an extra check to see if Docker is running before sending out the heartbeat.
At this moment I just was again reminded at how powerfull Node-RED is.
If you can think it you can build it.

Besides for the a happy wife happy life motivation it was also a really nice learning experience. This post is mostly to show my gratitude towards this project. Great work!!

Future projects:
-improve mqtt cluster (from a bridged mosquitto, upgrade to an rabbitmq mqtt cluster)
-power back up for network and cluster
-high available network at home (but I think those kinde of switches etc will not go through the budget committee)

4 Likes

Replying on myself: design already obsolete now I dove into Mqtt 5.0 and discovered the shared subscriptions. :joy: still valid for the virtual IP.

Dont forget UPS