From 8f51bc9ff5c4640172d81433ef6df6508fee899e Mon Sep 17 00:00:00 2001 From: Rob Cameron Date: Fri, 20 Dec 2019 14:55:21 -0800 Subject: [PATCH] Enable GLB Healthcheck to announce VIP/Bind status into BGP This pull request adds a new feature to GLB healthcheck. It allows it to locally announce the status of a VIP/bind into BGP using a local instance of GoBGP. It integrates with a locally deployed GoBGP daemon to announce the VIP/Bind into BGP when at least one backend is marked healthy. This allows you to prevent a statically announced route via BIRD to black hole traffic for a GLB instance that is unable to talk to its backends. In the event that all backends are marked either inactive or marked as unhealthy GLB healthcheck will withdraw the route. The feature is configurable (see included documentation) and defaults to off. We have been running this in production for a while and it simplified our integration with BGP. Merge Golang fixes --- Makefile | 3 +- Vagrantfile | 64 +- docs/README.md | 1 + docs/setup/forwarding-table-config.md | 37 +- docs/setup/gobgp-integration.md | 146 ++++ script/Dockerfile.latest | 10 + script/Dockerfile.stretch | 15 +- script/cibuild-create-packages | 26 +- script/cibuild-prepare | 1 + src/glb-director/script/cibuild | 7 +- src/glb-healthcheck/HealthCheckerAnnouce.go | 734 ++++++++++++++++++ .../HealthCheckerAppContext.go | 1 + src/glb-healthcheck/Makefile | 2 +- src/glb-healthcheck/glide.lock | 78 +- src/glb-healthcheck/glide.yaml | 4 + src/glb-healthcheck/main.go | 21 + src/glb-healthcheck/packaging/version.sh | 2 +- src/glb-redirect/Makefile | 10 +- 18 files changed, 1113 insertions(+), 49 deletions(-) create mode 100644 docs/setup/gobgp-integration.md create mode 100644 script/Dockerfile.latest create mode 100644 src/glb-healthcheck/HealthCheckerAnnouce.go diff --git a/Makefile b/Makefile index f3c3ef5..1427070 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,8 @@ mkdeb: cd src/glb-director && script/cibuild clean: - make -C src/glb-redirect clean + make -C src/glb-redirect clean && rm -rf ${BUILDDIR}/glb-director_*.deb make -C src/glb-healthcheck clean make -C src/glb-director clean make -C src/glb-director/cli clean + make -C src/glb-director/ftctl clean \ No newline at end of file diff --git a/Vagrantfile b/Vagrantfile index 94a62be..7f5bca1 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -6,9 +6,10 @@ Vagrant.configure("2") do |config| config.vm.synced_folder "src/glb-wireshark-dissector/", "/home/vagrant/.config/wireshark/plugins/glb-wireshark-dissector", type: 'rsync' - config.vm.provision "shell", inline: <<-SHELL + config.vm.provision "shell", name: "Base Host Tool Installation", inline: <<-SHELL apt-get update - DEBIAN_FRONTEND=noninteractive apt-get install -y tcpdump net-tools tshark build-essential libxtables-dev linux-headers-$(uname -r) python-pip jq bird curl + DEBIAN_FRONTEND=noninteractive apt-get install -y tcpdump net-tools tshark build-essential libxtables-dev python-pip jq bird curl + DEBIAN_FRONTEND=noninteractive apt-get install -y linux-headers-$(uname -r) groupadd wireshark || true usermod -a -G wireshark vagrant || true chgrp wireshark /usr/bin/dumpcap @@ -21,7 +22,7 @@ Vagrant.configure("2") do |config| v.vm.network "private_network", ip: "192.168.50.2", virtualbox__intnet: "glb_datacenter_network", :mac=> "001122334455" v.vm.hostname = "router" - v.vm.provision "shell", inline: <<-SHELL + v.vm.provision "shell", name: "Enable IPv4 forwarding", inline: <<-SHELL if ! grep -q '^net.ipv4.ip_forward' /etc/sysctl.conf; then echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf sysctl -w net.ipv4.ip_forward=1 @@ -35,7 +36,7 @@ Vagrant.configure("2") do |config| v.vm.network "private_network", ip: "192.168.40.2", virtualbox__intnet: "glb_user_network" v.vm.hostname = "user" - v.vm.provision "shell", inline: <<-SHELL + v.vm.provision "shell", name: "Configure routes", inline: <<-SHELL /vagrant/script/helpers/configure-vagrant-user.sh ip addr add 192.168.40.50/24 dev eth1 || true @@ -66,7 +67,7 @@ Vagrant.configure("2") do |config| vb.customize ["setextradata", :id, "VBoxInternal/CPUM/SSE4.2", "1"] end - v.vm.provision "shell", inline: <<-SHELL + v.vm.provision "shell", name: "Huge pages configuration", inline: <<-SHELL mkdir -p /mnt/huge if ! grep -q 'hugetlbfs' /etc/fstab; then echo 'hugetlbfs /mnt/huge hugetlbfs mode=1770 0 0' >>/etc/fstab @@ -78,40 +79,57 @@ Vagrant.configure("2") do |config| fi SHELL + v.vm.provision "shell", name: "Update Kernel", inline: <<-SHELL + apt-get update + DEBIAN_FRONTEND=noninteractive apt-get install -y linux-image-amd64 + DEBIAN_FRONTEND=noninteractive apt-get install -y apt-transport-https curl + SHELL + + # reload VM to pick up the new kernel so the correct header files can be installed + v.vm.provision :reload + v.vm.synced_folder ".", "/vagrant", type: "rsync" + # install DPDK et al. - v.vm.provision "shell", inline: <<-SHELL - apt-get install -y apt-transport-https curl + v.vm.provision "shell", run: "always", name: "Install DPDK and enable DPDK modules", inline: <<-SHELL echo 'deb http://ftp.debian.org/debian stretch-backports main' >/etc/apt/sources.list.d/backports.list apt-get update curl -s https://packagecloud.io/install/repositories/github/unofficial-dpdk-stable/script.deb.sh | sudo bash - apt-get install -y linux-headers-`(uname -r)` # dpdk requires this for the current kernel, but won't block if not installed - apt-get install -y python-pip dpdk-dev=17.11.1-6 dpdk=17.11.1-6 dpdk-rte-kni-dkms dpdk-igb-uio-dkms libjansson-dev - apt-get install -y valgrind vim tcpdump clang golang - + DEBIAN_FRONTEND=noninteractive apt-get install -y linux-headers-`(uname -r)` # dpdk requires this for the current kernel, but won't block if not installed + DEBIAN_FRONTEND=noninteractive apt-get install -y python-pip dpdk-dev=17.11.1-6 dpdk=17.11.1-6 dpdk-rte-kni-dkms dpdk-igb-uio-dkms libjansson-dev + DEBIAN_FRONTEND=noninteractive apt-get install -y valgrind vim tcpdump clang + + #Install an updated version of Golang that matches Debian Latest + curl -s https://dl.google.com/go/go1.11.6.linux-amd64.tar.gz -o /tmp/go1.11.6.linux-amd64.tar.gz + tar -C /usr/local -xzf /tmp/go1.11.6.linux-amd64.tar.gz + ln -s /usr/local/go/bin/go /usr/bin/ + ln -s /usr/local/go/bin/godoc /usr/bin/ + ln -s /usr/local/go/bin/gofmt /usr/bin/ + + echo "Setting modules to load" echo 'rte_kni' >/etc/modules-load.d/dpdk echo 'igb_uio' >>/etc/modules-load.d/dpdk SHELL - v.vm.provision "shell", run: "always", inline: <<-SHELL + v.vm.provision "shell", run: "always", name: "Modprobe DPDK modules", inline: <<-SHELL modprobe rte_kni modprobe igb_uio SHELL if install_example_setup # example setup - v.vm.provision "shell", run: "always", inline: <<-SHELL + v.vm.provision "shell", run: "always", name: "Install and configure GLB director", inline: <<-SHELL ifdown eth1 dpdk-devbind --bind=igb_uio eth1 dpdk-devbind --status - apt install /vagrant/tmp/build/glb-director_*.deb - apt install /vagrant/tmp/build/glb-healthcheck_*.deb + DEBIAN_FRONTEND=noninteractive apt install /vagrant/tmp/build/glb-director_*.deb + DEBIAN_FRONTEND=noninteractive apt install /vagrant/tmp/build/glb-healthcheck_*.deb /vagrant/script/helpers/configure-vagrant-director.sh "#{ipv4_addr}" SHELL else # test setup - v.vm.provision "shell", run: "always", inline: <<-SHELL + v.vm.provision "shell", run: "always", name: "Configure IPv6", inline: <<-SHELL ip addr add #{ipv6_addr} dev eth1 || true SHELL end @@ -124,12 +142,22 @@ Vagrant.configure("2") do |config| v.vm.network "private_network", ip: ipv4_addr, virtualbox__intnet: "glb_datacenter_network" - v.vm.provision "shell", inline: <<-SHELL + v.vm.provision "shell", name: "Update Kernel", inline: <<-SHELL + apt-get update + DEBIAN_FRONTEND=noninteractive apt-get install -y linux-image-amd64 + DEBIAN_FRONTEND=noninteractive apt-get install -y apt-transport-https curl + SHELL + + # reload VM to pick up the new kernel so the correct header files can be installed + v.vm.provision :reload + v.vm.synced_folder ".", "/vagrant", type: "rsync" + + v.vm.provision "shell", name: "Install hello world HTML", inline: <<-SHELL DEBIAN_FRONTEND=noninteractive apt-get install -y nginx echo "hello world from #{name} via GLB" >/var/www/html/index.html SHELL - v.vm.provision "shell", run: "always", inline: <<-SHELL + v.vm.provision "shell", run: "always", name: "Configure Tunnel Interfaces", inline: <<-SHELL modprobe fou modprobe sit ip link set up dev tunl0 || true diff --git a/docs/README.md b/docs/README.md index 1e2e61f..67ae995 100644 --- a/docs/README.md +++ b/docs/README.md @@ -8,6 +8,7 @@ * [glb-director component configuration options](./setup/glb-director-configuration.md) - configuration options for the GLB Director and discussion of NIC/Port and CPU Core configuration. * [Forwarding table configuration & healthchecks](./setup/forwarding-table-config.md) - Configuring the GLB forwarding table, and the director->proxy healthcheck process. * [Backend proxy server setup](./setup/backend-proxy-setup.md) - Configuring the backend TCP/proxy tier servers. + * [Integrating with GoBGP](./setup/gobgp-integration.md) - Optional feature for announcing VIPs/Binds via GoBGP Some notable known limitations / design decisions of the current implementation: * The datacenter internal MTU is expected to be large enough to encapsulate any user packet inside a GUE header. We use jumbo frames (9000+ MTU) within the datacenter with a transit/internet MTU of 1500. GLB Director will not fragment packets if they are too large. diff --git a/docs/setup/forwarding-table-config.md b/docs/setup/forwarding-table-config.md index c7a732e..b82bc12 100644 --- a/docs/setup/forwarding-table-config.md +++ b/docs/setup/forwarding-table-config.md @@ -122,8 +122,43 @@ If `glb-healthcheck` is used, a backend will be considered down if either the `g "src": "/etc/glb/forwarding_table.src.json", "dst": "/etc/glb/forwarding_table.checked.json" }, - "reload_command": "glb-director-cli build-config /etc/glb/forwarding_table.checked.json /etc/glb/forwarding_table.checked.bin && systemctl reload glb-director" + "reload_command": "glb-director-cli build-config /etc/glb/forwarding_table.checked.json /etc/glb/forwarding_table.checked.bin && systemctl reload glb-director", + "gobgp_config": { + "address": "127.0.0.1:50051", + "nexthop": "192.168.50.6", + "nexthop_ipv6": "fdb4:98ce:52d4::1", + "communities": [ "65000:1234", "65000:5678" ], + }, } ``` +### `forwarding_table` + +_required_ + +specifies which forwarding tables are used for glb-healtcheck + +`src` the source forwarding table that is created by the user +`dst` the destination forwarding table that is generated by glb-healthcheck + +### `reload_command` + +_required_ This instructs the healthchecker to load `/etc/glb/forwarding_table.src.json`, perform any checks defined inside it, and keep a `/etc/glb/forwarding_table.checked.json` up to date with valid/live health state. Any time it changes the `dst` file, it also runs the reload command (which in this case compiles the table and reloads the director to pick up those changes). + +### `gobgp_config` + +_optional_ + +This instructs the health checker to integrate with a [GoBGP](https://github.com/osrg/gobgp) daemon. It communicates over +gRPC to announce the status of the GLB binds or VIPs. When a bind/VIP is healthy the path will be announced with the configured +next hop address. The setting `nexthop` is used for IPv4 bind/VIPs and `nexthop_ipv6` is used for IPv6 bind/VIPs. If the protocol +specific next hop is not configured, then it will not be able to announce the route. If the `address` is not configured (default) this feature will not be enabled. + +`address` _required_ The gRPC address for the GoBGP daemon. This typically is `172.0.0.1:50051` assuming you have the BGP daemon installed locally. + +`nexthop` _required_ The IPv4 next hop address to use for route announcements. This is required if you have IPv4 bind/VIPs. + +`nexthop_ipv6` _optional_ The IPv6 next hop address to use for route announcements. This is only required if you are using IPv6 binds/VIPs. + +`communities` _optional_ A list of BGP communities you wish to use for tagging routes \ No newline at end of file diff --git a/docs/setup/gobgp-integration.md b/docs/setup/gobgp-integration.md new file mode 100644 index 0000000..15f071d --- /dev/null +++ b/docs/setup/gobgp-integration.md @@ -0,0 +1,146 @@ +# GoBGP integration + +When using Github Load Balancer (GLB), you need to inform the upstream network +devices about which bind or VIPs that your services are listening on. In the provided +example Vagrant topology the BIRD BGP daemon is used for announcing routes for the available +bind/VIPs configured on GLB. This is an excellent solution for integrating with upstream routers +and announcing available VIPs. The drawback is that this is a static announcement that provides +no validation of the actual VIP is healthy. + +Within the glb-healthcheck service it provides all the available health checking to understand the +state for all the backends associated with a VIP. The glb-healthcheck service can to talk to a local +instance of [GoBGP](https://github.com/osrg/gobgp) and use that as the method for announcing the VIPs +to the upstream routers via BGP. This allows the state of the binds to determine if a route should be +announced or not. This prevents the GLB node from potentially black holing or dropping traffic to VIPs +that are not ready to serve traffic. + +## Enabling GoBGP integration + +To enable the integration with GoBGP you must configure the glb-healthcheck service to use the local GoBGP +daemon. The required configurtion must be set in the `healthcheck.conf` file, more details for the configuration +options can be found [here](./setup/forwarding-table-config.md). + +## Running GoBGP + +You must install the GoBGP daemon locally so glb-healthcheck is able to communicate with it. You can download the +[latest release](https://github.com/osrg/gobgp/releases) bundle. It includes gobgpd (daemon) and gobgp (tool to interact with the +daemon) in its release file. Place the binaries on your system and set it up as a systemd service. + +### Systemd service definition + +To enable GoBGP as a systemd service this service definition can be placed in `/lib/systemd/system/gobgp.service`. Once +added you will need to run `systemctl daemon-reload` to pickup the new service. The service definition below requires there +to be a local `gobgpd` user for the service to run as. This prevents it from needing to run as `root`. + +``` +[Unit] +Description=GoBGP Daemon +After=network.target network-online.target +Wants=network.target + +[Service] +Type=simple +Restart=always +Environment="PATH=/usr/local/bin:/usr/bin:/bin" +ExecStart=/usr/local/sbin/gobgpd --api-hosts=127.0.0.1:50051 -f /etc/gobgp/config.toml +ExecReload=/bin/kill -HUP $MAINPID +KillSignal=TERM +User=gobgpd +WorkingDirectory=/etc/gobgp +TimeoutStopSec=3 + +[Install] +WantedBy=multi-user.target +``` + +### Listening on low port without running as root + +To enable the service to listen on TCP port 179 without running as root we can enable the capacity directly on the binary. + +``` +# setcap cap_net_bind_service=+ep /usr/local/sbin/gobgpd +# chown gobgpd:gobgpd /usr/local/sbin/gobgpd +``` + +### Base GoBGP Configuration + +Below is a simple base configuration that will announce any routes that are added to GoBGP to its upstream +neighbor. There are many [configuration options](https://github.com/osrg/gobgp/blob/master/docs/sources/configuration.md) +available for GoBGP. Currently within glb-healthcheck GoBGP is only used for IPv4 or IPv6 route announcements. In the future +other features of GoBGP could be used such as flowspec integration. + +``` +[global.config] + as = 65000 + router-id = "1.1.1.1" + +# configure each remote neighbor +[[neighbors]] + [neighbors.config] + neighbor-address = "172.31.2.168" + peer-as = 65001 + [neighbors.apply-policy.config] # only export routes, do not recieve them + export-policy-list = ["export-all-ipv4", "export-all-ipv6"] + default-export-policy = "accept-route" + [[neighbors.afi-safis]] # enable upstream IPv4 + [neighbors.afi-safis.config] + afi-safi-name = "ipv4-unicast" + [[neighbors.afi-safis]] # enable upstream IPv6 + [neighbors.afi-safis.config] + afi-safi-name = "ipv6-unicast" + +# Prefix list to match any IPv4 address +[[defined-sets.prefix-sets]] + prefix-set-name = "any-ipv4" + [[defined-sets.prefix-sets.prefix-list]] + ip-prefix = "0.0.0.0/0" + +# Prefix list to match any IPv6 address +[[defined-sets.prefix-sets]] + prefix-set-name = "any-ipv6" + [[defined-sets.prefix-sets.prefix-list]] + ip-prefix = "::/0" + +# Export policy to export any IPv4 addresses +[[policy-definitions]] + name = "export-all-ipv4" + [[policy-definitions.statements]] + name = "export-ipv4-all-match" + [policy-definitions.statements.conditions.match-prefix-set] + prefix-set = "any-ipv4" + [policy-definitions.statements.actions] + route-disposition = "accept-route" + +# Export policy to export any IPv6 addresses +[[policy-definitions]] + name = "export-all-ipv6" + [[policy-definitions.statements]] + name = "export-ipv6-all-match" + [policy-definitions.statements.conditions.match-prefix-set] + prefix-set = "any-ipv6" + [policy-definitions.statements.actions] + route-disposition = "accept-route" +``` + +## How it works + +After every run of the glb-healthcheck the GoBGP integration will take the results and determine which binds to announce. It +will only announce routes for binds with healthy backends. The route will be refreshed for every successful health check cycle. +Once all of the backends for a specific bind have failed health checks, the route will be withdrawn automatically. + +If a bind is removed from one of the forwarding tables it will automatically be removed at the end of the next run. The state +of the routes is stored within glb-healthcheck. In the event that you want to gracefully retire a VIP you can drain each backend. Once +the backends are all set to `inactive` state then the routes will be automatically withdrawn. This prevents accidently dropping traffic +by sending traffic to a bind in which all backends are set to `inactive`. + +## Cleaning up routes + +If any announced routes get out of sync you can manually remove them from the GoBGP daemon. You can restart GoBGP and this will +remove any routes loaded. This will be disruptive as it will force your instance of GoBGP to reset all of its neighbor connections. +Alternatively you can delete routes using the control plane CLI tool `gobgp`. + +``` +# gobgp global rib del [-a
] +$ gobgp global rib del 1.1.1.1/32 +$ gobgp global rib del 2001:dead:beef::1/128 -a ipv6 +``` \ No newline at end of file diff --git a/script/Dockerfile.latest b/script/Dockerfile.latest new file mode 100644 index 0000000..e3d3528 --- /dev/null +++ b/script/Dockerfile.latest @@ -0,0 +1,10 @@ +FROM debian:latest + +RUN apt-get update && apt-get install -y build-essential debhelper wget pkg-config + +# golang +RUN apt-get update && apt-get install -y golang golang-glide + +# fpm for packaging +RUN apt-get update && apt-get install -y ruby ruby-dev rubygems build-essential +RUN gem install --no-ri --no-rdoc rake fpm \ No newline at end of file diff --git a/script/Dockerfile.stretch b/script/Dockerfile.stretch index 4f71e8e..cd31675 100644 --- a/script/Dockerfile.stretch +++ b/script/Dockerfile.stretch @@ -3,20 +3,15 @@ FROM debian:stretch RUN echo 'deb http://ftp.debian.org/debian stretch-backports main' >>/etc/apt/sources.list RUN apt-get update && apt-get -y install curl -# DPDK +# DPDK RUN curl -s https://packagecloud.io/install/repositories/github/unofficial-dpdk-stable/script.deb.sh | bash -RUN apt-get update && apt-get install -y build-essential dpdk dpdk-dev wget pkg-config libjansson-dev +RUN apt-get update && apt-get install -y build-essential dpdk dpdk-dev wget pkg-config libjansson-dev ruby ruby-dev # iptables / DKMS RUN apt-get update && apt-get install -y iptables-dev dkms debhelper libxtables-dev -# golang -RUN apt-get update && apt-get install -y golang golang-glide - -# fpm for packaging -RUN apt-get update && apt-get install -y ruby ruby-dev rubygems build-essential -RUN gem install --no-ri --no-rdoc rake fpm - # patch DKMS for source package generation https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=832558 ADD helpers/dkms.diff /root/dkms.diff -RUN patch -d /usr/sbin 0 { + comms := make([]uint32, 0, 1) + + for _, v := range hca.config.Communities { + c, err := hca.parseCommunity(v) + if err != nil { + // error parsing community + hca.logContext.WithFields(log.Fields{ + "community": v, + }).Debug(err) + + continue + } + comms = append(comms, c) + } + + commsAttr, _ := ptypes.MarshalAny(&gobgpapi.CommunitiesAttribute{ + Communities: comms, + }) + + pattrs = append(pattrs, commsAttr) + } + + // Return the correctly generated path + return &gobgpapi.Path{ + Pattrs: pattrs, + Nlri: newNLRI, + Family: &gobgpapi.Family{ + Afi: gobgpapi.Family_Afi(routeFamily), + Safi: gobgpapi.Family_SAFI_UNICAST, + }, + Identifier: identifier, + }, nil +} + +// parseCommunity parse a community string and return its value as the required uint32 +func (hca *HealthCheckerAnnounce) parseCommunity(arg string) (uint32, error) { + i, err := strconv.ParseUint(arg, 10, 32) + if err == nil { + return uint32(i), nil + } + + elems := regexpCommunity.FindStringSubmatch(arg) + if len(elems) == 3 { + fst, _ := strconv.ParseUint(elems[1], 10, 16) + snd, _ := strconv.ParseUint(elems[2], 10, 16) + return uint32(fst<<16 | snd), nil + } + for i, v := range bgp.WellKnownCommunityNameMap { + if arg == v { + return uint32(i), nil + } + } + return 0, errors.New("failed to parse %s as community") +} + +// helper functions + +// ipVersion return the IP protocol version +func ipVersion(ip string) (int, error) { + + ipAddr := net.ParseIP(ip) + + if isV4(ipAddr) { + return 4, nil + } else if isV6(ipAddr) { + return 6, nil + } else { + return 0, errors.New("unable to determine IP protocol Version") + } +} + +// isV4 tests if the IP is IPv4 +func isV4(ip net.IP) bool { + if ip.To4() != nil { + return true + } + return false +} + +// isV6 tests if the IP is IPv6 +func isV6(ip net.IP) bool { + if ip.To4() == nil { + return true + } + return false +} \ No newline at end of file diff --git a/src/glb-healthcheck/HealthCheckerAppContext.go b/src/glb-healthcheck/HealthCheckerAppContext.go index 6aba81e..01b5e6d 100644 --- a/src/glb-healthcheck/HealthCheckerAppContext.go +++ b/src/glb-healthcheck/HealthCheckerAppContext.go @@ -55,6 +55,7 @@ type HealthCheckConfigFile struct { } `json:"forwarding_table"` ReloadCommand *string `json:"reload_command"` + BGPConfig GoBGPConfig `json:"gobgp_config"` } type HealthCheckerAppContext struct { diff --git a/src/glb-healthcheck/Makefile b/src/glb-healthcheck/Makefile index 38651ee..df0211c 100644 --- a/src/glb-healthcheck/Makefile +++ b/src/glb-healthcheck/Makefile @@ -32,4 +32,4 @@ mkdeb: script/cibuild clean: - rm -rf glb-healthcheck_*.deb glb-healthcheck + rm -rf ${BUILDDIR}/glb-healthcheck_*.deb glb-healthcheck \ No newline at end of file diff --git a/src/glb-healthcheck/glide.lock b/src/glb-healthcheck/glide.lock index af41160..32bb82c 100644 --- a/src/glb-healthcheck/glide.lock +++ b/src/glb-healthcheck/glide.lock @@ -1,23 +1,93 @@ -hash: 243fb52be80990666d4d5c7a9e475596305c221146d2840e7b07d8845ba960a3 -updated: 2018-05-16T09:42:23.036243129+10:00 +hash: 75c007b7dd40769ea416110d459960788b6905c0f615e90f41000a084a44bdc4 +updated: 2019-07-25T14:21:19.853185-07:00 imports: - name: github.com/docopt/docopt-go version: 784ddc588536785e7299f7272f39101f7faccc3f +- name: github.com/golang/protobuf + version: e91709a02e0e8ff8b86b7aa913fdc9ae9498e825 + subpackages: + - proto + - ptypes + - ptypes/any + - ptypes/duration + - ptypes/empty + - ptypes/timestamp - name: github.com/google/gopacket - version: 11c65f1ca9081dfea43b4f9643f5c155583b73ba + version: 6d3e2615da4ed2ed2a349918fe74e7e6d03482fa subpackages: - layers +- name: github.com/osrg/gobgp + version: 07f0fd48d5ac2e83378222762cd0a98e01d3bf5e + subpackages: + - api + - pkg/packet/bgp - name: github.com/rs/xid version: 02dd45c33376f85d1064355dc790dcc4850596b1 - name: github.com/sirupsen/logrus - version: c155da19408a8799da419ed3eeb0cb5db0ad5dbc + version: 3e01752db0189b9157070a0e1668a620f9a85da2 - name: golang.org/x/crypto version: 1a580b3eff7814fc9b40602fd35256c63b50f491 subpackages: - ssh/terminal +- name: golang.org/x/net + version: f4e77d36d62c17c2336347bb2670ddbd02d092b7 + subpackages: + - context + - http/httpguts + - http2 + - http2/hpack + - idna + - internal/timeseries + - trace - name: golang.org/x/sys version: 7c87d13f8e835d2fb3a70a2912c811ed0c1d241b subpackages: - unix - windows +- name: golang.org/x/text + version: 342b2e1fbaa52c93f31447ad2c6abc048c63e475 + subpackages: + - secure/bidirule + - transform + - unicode/bidi + - unicode/norm +- name: google.golang.org/genproto + version: 54afdca5d873f7b529e2ce3def1a99df16feda90 + subpackages: + - googleapis/rpc/status +- name: google.golang.org/grpc + version: 045159ad57f3781d409358e3ade910a018c16b30 + subpackages: + - balancer + - balancer/base + - balancer/roundrobin + - binarylog/grpc_binarylog_v1 + - codes + - connectivity + - credentials + - credentials/internal + - encoding + - encoding/proto + - grpclog + - internal + - internal/backoff + - internal/balancerload + - internal/binarylog + - internal/channelz + - internal/envconfig + - internal/grpcrand + - internal/grpcsync + - internal/syscall + - internal/transport + - keepalive + - metadata + - naming + - peer + - resolver + - resolver/dns + - resolver/passthrough + - serviceconfig + - stats + - status + - tap testImports: [] diff --git a/src/glb-healthcheck/glide.yaml b/src/glb-healthcheck/glide.yaml index 7e967a8..6cdba66 100644 --- a/src/glb-healthcheck/glide.yaml +++ b/src/glb-healthcheck/glide.yaml @@ -14,3 +14,7 @@ import: - ssh/terminal - package: github.com/rs/xid version: ~1.1.0 +- package: google.golang.org/grpc + version: ^1.20.1 +- package: github.com/osrg/gobgp + version: ^2.6.0 diff --git a/src/glb-healthcheck/main.go b/src/glb-healthcheck/main.go index f6f484b..b18c2b9 100644 --- a/src/glb-healthcheck/main.go +++ b/src/glb-healthcheck/main.go @@ -77,6 +77,16 @@ Options: return } + // instantiate BGP integration + hca, err := NewHealthCheckerAnnounce(&ctx.config.BGPConfig, log.WithFields(log.Fields{ + "app": "glb-healthcheck", + "module": "announce", + })) + if err != nil { + hca.logContext.Fatalf("Unable to configure health announcing checker: %s\n", err) + return + } + // the check manager will run the HC loop and manage most of the HC part of the work ctx.checkManager = NewHealthCheckManager(HealthCheckTimeout, HealthCheckInterval) @@ -116,6 +126,17 @@ Options: for range healthRoundComplete { ctx.logContext.Debug("Health check round completed") ctx.SyncAndMaybeReload() + + // run route updates if the announce feature is enabled + if hca.enabled { + // fetch forwarding table for bind map validation + ctx.Lock() + ft := ctx.forwardingTableConfig + ctx.Unlock() + + // process the current health results and manage paths in GoBGP + go hca.Announce(ft, ctx.checkManager.GetResults()) + } } }() diff --git a/src/glb-healthcheck/packaging/version.sh b/src/glb-healthcheck/packaging/version.sh index e9f0653..ec8eb60 100644 --- a/src/glb-healthcheck/packaging/version.sh +++ b/src/glb-healthcheck/packaging/version.sh @@ -1 +1 @@ -GLB_HEALTHCHECK_VERSION="0.1.4" +GLB_HEALTHCHECK_VERSION="0.1.5" diff --git a/src/glb-redirect/Makefile b/src/glb-redirect/Makefile index b7aafd1..abc2aa8 100644 --- a/src/glb-redirect/Makefile +++ b/src/glb-redirect/Makefile @@ -1,6 +1,4 @@ KDIR?=/usr/src/linux-headers-$(shell uname -r) -BUILDDIR?=. - ROOT_DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) DKMS_MOD_VER:=$(shell grep 'PACKAGE_VERSION' dkms.conf | cut -d'=' -f2) @@ -15,7 +13,9 @@ kmod: clean: # we allow the following to fail since in our Docker build env we don't have a valid KDIR $(BUILD_VARS) make -C $(KDIR) M=$(ROOT_DIR) clean || true - rm -rf libxt_GLBREDIRECT.so $(BUILDDIR)/glb-redirect-iptables-dkms_$(DKMS_MOD_VER)_*.deb + rm -rf libxt_GLBREDIRECT.so + rm -rf glb-redirect-iptables-dkms-mkdeb + rm -rf ${BUILDDIR}/glb-redirect-iptables-dkms_$(DKMS_MOD_VER)_*.deb .PHONY: lib lib: libxt_GLBREDIRECT.so @@ -37,10 +37,12 @@ IPT_LDFLAGS=-lxtables -shared mkdeb: rm -rf glb-redirect-iptables-dkms-mkdeb cp -R /etc/dkms/template-dkms-mkdeb/ glb-redirect-iptables-dkms-mkdeb - chown : -R glb-redirect-iptables-dkms-mkdeb # Works around this bug: https://ubuntuforums.org/showthread.php?t=2234906 sed -i '/chmod 644/d' glb-redirect-iptables-dkms-mkdeb/Makefile sed -i '/^Depends:/ s/$$/, pkg-config, libxtables12 | libxtables10, libxtables-dev | libxtables10/' glb-redirect-iptables-dkms-mkdeb/debian/control sed -i 's/^Maintainer: .*/Maintainer: GitHub /' glb-redirect-iptables-dkms-mkdeb/debian/control dkms mkdeb --source-only + +ifneq "$(BUILDDIR)" "" mv ../glb-redirect-iptables-dkms_$(DKMS_MOD_VER)_*.deb $(BUILDDIR)/ +endif \ No newline at end of file