High Availability on Vultr with Floating IP and BGP using BIRD 2.0
BIRD 2.0 was out with the first experimental version in 2016. Currently, BIRD 2.0 is stable and has a lot of improvement in BGP performance and security enhancement. Let's see how you can enable high availability for your application on Vultr using Floating IP and BGP in BIRD 2.0. If you still need BIRD version 1, check out the High Availability on Vultr with Floating IP and BGP article.
What is Floating IP
A floating IP is an IP that can act as a load-balancing address. It can route to any server in the same network system.
Why Floating IP
With floating IP, if the primary server that the IP routes to is down, the IP can route to another server in the same network. The user traffic comes to another server instead of waiting for the primary server to be up again. Using floating IP brings a smooth user experience to your application and helps your app to achieve high availability.
What is BGP
BGP stands for Border Gateway Protocol, which is a routing protocol that enables network stability in your system. With BGP, the routers can quickly initiate another connection with another server and send data packets to the new server immediately.
What is Vultr reserved IP
Vultr Reserved IP is the static and permanent IP that you can use. You can use Vultr reserved IP as a floating IP to achieve high availability for your system.
Prerequisites
To follow the steps in this guide, you need the following:
- A Vultr account with BGP usage is ready. Please complete this form to enable BGP for your account.
- One reserved IP v4 address and one reserved IP v6 address. Check out this guide for how to reserve IP addresses with Vultr. Note that the reserved IPs must be in the same region as your Vultr servers.
- Four Ubuntu version 20.04 server instances that are ready to use in Vultr platform. Three servers for applying Floating IP with IP v4 and one server for IP v6. Following this guide, you can use other Linux distros, but the commands and configuration files might differ.
Example values
Replace these example values with the ones you own throughout the doc.
- Server 1 (IP v4 address): 45.76.146.91
- Server 2 (IP v4 address): 139.180.213.161
- Server 3 (IP v4 address): 139.180.186.3
- ASN for the Vultr account: 4288000203
- BGP password: q9BWVUCaiV1v8F2y
- Reserved IP v4: 207.148.65.177
- Reserved IP v6: 2401:c080:1400:54af::/64
- Server 4 (IP v6 address): 2401:c080:1400:6398:5400:04ff:fe40:5b7e
Vultr's BGP Info
- ASN for Vultr side: 64515 (This is the value for Vultr cloud, change it with 20473 if you're using Vultr bare metal).
- IP v4 address for Vultr side: 169.254.169.254 (This is the value for Vultr cloud, change it with 169.254.1.1 if you're using Vultr bare metal).
1. Configure a dummy network
Accessing your server one as root, then run the below commands to create a dummy network interface:
# ip link add dev dummy1 type dummy
Bring up the interface:
# ip link set dummy1 up
Bind the dummy interface to the Reserved IP address. Replace the example 45.76.146.91 with your reserved IP:
# ip addr add dev dummy1 45.76.146.91/32
Confirm the network configuration:
# ip addr show dev dummy1 3: dummy1: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000 link/ether 06:75:41:99:bd:ff brd ff:ff:ff:ff:ff:ff inet 207.148.65.177/32 scope global dummy1 valid_lft forever preferred_lft forever inet6 fe80::475:41ff:fe99:bdff/64 scope link valid_lft forever preferred_lft forever
2. Configure BIRD 2.0
Enable your firewall to permit traffic on TCP port 179:
# ufw allow 179 # ufw status verbose
You should see the following output in the console:
Status: active Logging: on (low) Default: deny (incoming), allow (outgoing), disabled (routed) New profiles: skip To Action From -- ------ ---- 22 ALLOW IN Anywhere 179 ALLOW IN Anywhere 22 (v6) ALLOW IN Anywhere (v6) 179 (v6) ALLOW IN Anywhere (v6)
Install BIRD 2.0 into your Ubuntu server instance:
# apt update # apt install bird2 # bird --version
You should see similar output:
BIRD version 2.0.7
Update BIRD 2.0 configuration for your Ubuntu server instance:
# nano /etc/bird/bird.conf
Replace your current
bird.conf
with the one below(Note that you need to change the example values with your values):log syslog all; router id 45.76.146.91; protocol device { } protocol direct { # Disable by default ipv4; # Connect to default IPv4 table #ipv6; # ... and to default IPv6 table interface "dummy1"; } protocol kernel { ipv4 { # Connect protocol to IPv4 table by channel export all; # Export to protocol. default is export none }; } protocol kernel { ipv6 { export all; }; } protocol static { ipv4; # Again, IPv4 channel with default options } protocol bgp vultr { local as 4288000203; source address 45.76.146.91; ipv4 { import none; export all; }; graceful restart on; multihop 2; neighbor 169.254.169.254 as 64515; password "q9BWVUCaiV1v8F2y"; }
Here router id
and source address
values are the IP v4 address of your server one. The local as
value is the ASN for your Vultr account. The password
value is the BGP password of your Vultr account.
3. Verify BGP connectivity
Start BIRD 2.0 service:
# systemctl start bird
Check that you successfully established the BGP session:
# birdc show proto all vultr
You should see the following output:
BIRD 2.0.7 ready. Name Proto Table State Since Info vultr BGP --- up 00:00:28.089 Established BGP state: Established Neighbor address: 169.254.169.254 Neighbor AS: 64515 Local AS: 4288000203 Neighbor ID: 45.32.98.8 Local capabilities Multiprotocol AF announced: ipv4 Route refresh Graceful restart Restart time: 120 AF supported: ipv4 AF preserved: 4-octet AS numbers Enhanced refresh Long-lived graceful restart Neighbor capabilities Multiprotocol AF announced: ipv4 Route refresh Extended message Graceful restart 4-octet AS numbers ADD-PATH RX: ipv4 TX: Enhanced refresh Long-lived graceful restart LL stale time: 0 AF supported: AF preserved: ipv4 Session: external multihop AS4 Source address: 45.76.146.91 Hold timer: 100.101/180 Keepalive timer: 4.679/60 Channel ipv4 State: UP Table: master4 Preference: 100 Input filter: REJECT Output filter: ACCEPT Routes: 0 imported, 1 exported, 0 preferred Route change stats: received rejected filtered ignored accepted Import updates: 1 0 1 0 0 Import withdraws: 0 0 --- 1 0 Export updates: 1 0 0 --- 1 Export withdraws: 0 --- --- --- 0 BGP Next hop: 45.76.146.91 IGP IPv4 table: master4
4. Test the Floating IP
Verify BIRD 2.0 is advertising the route to your floating IP:
# birdc show route
You should see the following output:
BIRD 2.0.7 ready. Table master4: 207.148.65.177/32 unicast [direct1 2022-12-22] * (240) dev dummy1
Open another terminal in your local environment to test the connection to the reserved IP:
# ping 207.148.65.177
You should see a similar output:
PING 207.148.65.177 (207.148.65.177) 56(84) bytes of data. 64 bytes from 207.148.65.177: icmp_seq=26 ttl=54 time=47.6 ms 64 bytes from 207.148.65.177: icmp_seq=27 ttl=54 time=48.4 ms 64 bytes from 207.148.65.177: icmp_seq=28 ttl=54 time=48.7 ms 64 bytes from 207.148.65.177: icmp_seq=29 ttl=54 time=46.5 ms 64 bytes from 207.148.65.177: icmp_seq=30 ttl=54 time=48.2 ms 64 bytes from 207.148.65.177: icmp_seq=31 ttl=54 time=48.9 ms
Bring the dummy service down from your server 1 terminal:
# ip link set dummy1 down
The ping process fails to capture data packets at the other terminal.
Enable the dummy service again.
# ip link set dummy1 up
The ping process successfully capture data packets again.
Similarly, install and configure BIRD 2.0 for servers two and three.
Enable/Disable the dummy service in your servers two and three. You should see a similar result as with server one.
Now you successfully set up the three servers with the reserved IP address. If one or even two of your servers are down, user traffic going through the reserved IP will come to the remaining servers.
Use BGP Prepends to Assign Traffic Priority
What if you want to control the distribution traffic of user requests to your servers? In that case, you can use BGP prepends. Let's say you want:
- Your server one is the primary instance that receives all traffic
- Your server two is the second instance that receives all traffic if server 1 is down
- Your server three is the third instance that receives all traffic if both server one and server 2 are down
Update the BIRD 2.0 configuration for your server two:
# nano /etc/bird/bird.conf
Add the below content to
protocol bgp vultr
block (Update the BGP 4288000203 value with your BGP value for your Vultr account):export filter { # Artificially increase path length # by prepending the local AS number. bgp_path.prepend(4288000203); accept; };
Your
protocol bgp vultr
configuration for server two should look like the following now:protocol bgp vultr { local as 4288000203; source address 139.180.213.161; ipv4 { import none; export all; export filter { # Artificially increase path length # by prepending the local AS number. bgp_path.prepend(4288000203); accept; }; }; graceful restart on; multihop 2; neighbor 169.254.169.254 as 64515; password "q9BWVUCaiV1v8F2y"; }
For server three, add two lines of
bgp_path.prepend(4288000203)
instead of one line. Yourprotocol bgp vultr
configuration for server three should look like the following:protocol bgp vultr { local as 4288000203; source address 139.180.186.3; ipv4 { import none; export all; export filter { # Artificially increase path length # by prepending the local AS number. bgp_path.prepend(4288000203); bgp_path.prepend(4288000203); accept; }; }; graceful restart on; multihop 2; neighbor 169.254.169.254 as 64515; password "q9BWVUCaiV1v8F2y"; }
And that's how you apply BGP prepends for BIRD 2.0 version for your servers.
Using Floating IPs with IPv6
Applying Floating IPs with IPv6 is similar to using IPv4. On your server four, you need to:
Create a dummy network interface:
# ip link add dev dummy1 type dummy
Bring the interface up:
# ip link set dummy1 up
Bind the dummy interface to the number of IP v6 addresses you want. Refer to Vultr IPv6 calculator to see the available address for your IPv6 value. Let's bind the dummy interface to two IPv6 addresses, then.
# ip addr add dev dummy1 2401:c080:1400:54af::1/64 # ip addr add dev dummy1 2401:c080:1400:54af::2/64
Verify the interface:
# ip addr show dev dummy1
You should see a similar output:
4: dummy1: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000 link/ether ce:f6:df:be:b6:4f brd ff:ff:ff:ff:ff:ff inet6 2401:c080:1400:54af::2/64 scope global valid_lft forever preferred_lft forever inet6 2401:c080:1400:54af::1/64 scope global valid_lft forever preferred_lft forever inet6 fe80::ccf6:dfff:febe:b64f/64 scope link valid_lft forever preferred_lft forever
BIRD 2.0 configuration with IPv6
Open up the BIRD 2.0 configuration file for server 4:
# nano /etc/bird/bird.conf
Replace your existing content with the below:
log syslog all; router id 45.76.189.34; protocol device { } protocol direct { # Disable by default #ipv4; # Connect to default IPv4 table ipv6; # ... and to default IPv6 table interface "dummy1"; } protocol kernel { ipv4 { # Connect protocol to IPv4 table by channel export all; # Export to protocol. default is export none }; } protocol kernel { ipv6 { export all; }; } protocol static { ipv4; # Again, IPv4 channel with default options } protocol bgp vultr { local as 4288000203; source address 2401:c080:1400:6398:5400:04ff:fe40:5b7e; ipv6 { import none; export all; }; graceful restart on; multihop 2; neighbor 2001:19f0:ffff::1 as 64515; password "q9BWVUCaiV1v8F2y"; }
Note that you need to change the example values with your values. The
router id
value is the IP v4 address of server four. Thelocal as
value is the ASN value for your Vultr account. Thesource address
value is the IP v6 address of your server four. Thepassword
value is your Vultr BGP password.Start the BIRD 2.0 service:
# systemctl start bird
Check the BIRD 2.0 route:
# birdc show route
You should see a similar output below, which shows the configured IPv6 address:
BIRD 2.0.7 ready. Table master6: 2401:c080:1400:54af::/64 unicast [direct1 2022-12-22] * (240) dev dummy1
Check whether the configuration of Vultr protocol for IPv6 is successful:
# birdc show proto all vultr
You should see a similar output:
BIRD 2.0.7 ready. Name Proto Table State Since Info vultr BGP --- up 2022-12-22 Established BGP state: Established Neighbor address: 2001:19f0:ffff::1 Neighbor AS: 64515 Local AS: 4288000203 Neighbor ID: 45.32.98.19 Local capabilities Multiprotocol AF announced: ipv6 Route refresh Graceful restart Restart time: 120 AF supported: ipv6 AF preserved: 4-octet AS numbers Enhanced refresh Long-lived graceful restart Neighbor capabilities Multiprotocol AF announced: ipv6 Route refresh Extended message Graceful restart 4-octet AS numbers ADD-PATH RX: ipv6 TX: Enhanced refresh Long-lived graceful restart LL stale time: 0 AF supported: AF preserved: ipv6 Session: external multihop AS4 Source address: 2401:c080:1400:6398:5400:4ff:fe40:5b7e Hold timer: 149.640/180 Keepalive timer: 34.947/60 Channel ipv6 State: UP Table: master6 Preference: 100 Input filter: REJECT Output filter: ACCEPT Routes: 0 imported, 1 exported, 0 preferred Route change stats: received rejected filtered ignored accepted Import updates: 1 0 1 0 0 Import withdraws: 0 0 --- 1 0 Export updates: 1 0 0 --- 1 Export withdraws: 0 --- --- --- 0 BGP Next hop: 2401:c080:1400:6398:5400:4ff:fe40:5b7e IGP IPv6 table: master6
Open a new terminal from your local environment, then run the below command to test the connection to the IPv6 reserved IP.
# ping6 2401:c080:1400:54af::1
You should see the output below:
64 bytes from 2401:c080:1400:54af::1: icmp_seq=2 ttl=59 time=0.548 ms 64 bytes from 2401:c080:1400:54af::1: icmp_seq=3 ttl=59 time=0.528 ms 64 bytes from 2401:c080:1400:54af::1: icmp_seq=4 ttl=59 time=0.483 ms 64 bytes from 2401:c080:1400:54af::1: icmp_seq=5 ttl=59 time=0.467 ms 64 bytes from 2401:c080:1400:54af::1: icmp_seq=6 ttl=59 time=0.528 ms 64 bytes from 2401:c080:1400:54af::1: icmp_seq=7 ttl=59 time=0.551 ms 64 bytes from 2401:c080:1400:54af::1: icmp_seq=8 ttl=59 time=0.468 ms 64 bytes from 2401:c080:1400:54af::1: icmp_seq=9 ttl=59 time=0.535 ms
Checking with the other ipv6 address:
# ping6 2401:c080:1400:54af::2
You should see a similar result:
64 bytes from 2401:c080:1400:54af::2: icmp_seq=1 ttl=59 time=0.500 ms 64 bytes from 2401:c080:1400:54af::2: icmp_seq=2 ttl=59 time=0.480 ms 64 bytes from 2401:c080:1400:54af::2: icmp_seq=3 ttl=59 time=0.689 ms 64 bytes from 2401:c080:1400:54af::2: icmp_seq=4 ttl=59 time=0.442 ms
Now you have successfully applied floating IP IPv4 and IPv6 using BIRD 2.0 with Vultr reserved IPs. Vultr also provides APIs to help you manage your reserved IPs. You can: