This fixes numerous issues

- Adds the CIDR to the VIP, needed for BGP
- Seperates the EIP association to a seperate function making leader Election code clearer
- Fixes to environment variable names
- Clean un-needed `fatalf` errors
- Added additional comments
This commit is contained in:
thebsdbox
2020-08-25 10:07:54 +01:00
parent b6e3434ee3
commit ea11c6fbbd
6 changed files with 110 additions and 50 deletions

View File

@@ -33,11 +33,15 @@ func init() {
//initConfig.Peers = append(initConfig.Peers, *localpeer)
kubeKubeadm.PersistentFlags().StringVar(&initConfig.Interface, "interface", "", "Name of the interface to bind to")
kubeKubeadm.PersistentFlags().StringVar(&initConfig.VIP, "vip", "", "The Virtual IP address")
kubeKubeadm.PersistentFlags().BoolVar(&initConfig.StartAsLeader, "startAsLeader", false, "Start this instance as the cluster leader")
kubeKubeadm.PersistentFlags().BoolVar(&initConfig.AddPeersAsBackends, "addPeersToLB", true, "The Virtual IP address")
kubeKubeadm.PersistentFlags().StringVar(&initConfig.VIPCIDR, "cidr", "", "The CIDR range for the virtual IP address")
kubeKubeadm.PersistentFlags().BoolVar(&initConfig.GratuitousARP, "arp", true, "Enable Arp for Vip changes")
// Clustering type (leaderElection/raft)
kubeKubeadm.PersistentFlags().BoolVar(&initConfig.EnableLeaderElection, "leaderElection", false, "Use the Kubernetes leader election mechanism for clustering")
kubeKubeadm.PersistentFlags().BoolVar(&initConfig.StartAsLeader, "startAsLeader", false, "Start this instance as the cluster leader")
kubeKubeadm.PersistentFlags().BoolVar(&initConfig.AddPeersAsBackends, "addPeersToLB", true, "Add raft peers to the load-balancer")
// Packet flags
kubeKubeadm.PersistentFlags().BoolVar(&initConfig.EnablePacket, "packet", false, "This will use the Packet API (requires the token ENV) to update the EIP <-> VIP")
kubeKubeadm.PersistentFlags().StringVar(&initConfig.PacketAPIKey, "packetKey", "", "The API token for authenticating with the Packet API")
kubeKubeadm.PersistentFlags().StringVar(&initConfig.PacketProject, "packetProject", "", "The name of project already created within Packet")
@@ -52,7 +56,6 @@ func init() {
// BGP flags
kubeKubeadm.PersistentFlags().BoolVar(&initConfig.EnableBGP, "bgp", false, "This will enable BGP support within kube-vip")
kubeKubeadm.PersistentFlags().StringVar(&initConfig.BGPConfig.RouterID, "bgpRouterID", "", "The routerID for the bgp server")
kubeKubeadm.PersistentFlags().Uint32Var(&initConfig.BGPConfig.AS, "localAS", 65000, "The local AS number for the bgp server")
kubeKubeadm.PersistentFlags().StringVar(&initConfig.BGPPeerConfig.Address, "peerAddress", "", "The address of a BGP peer")

View File

@@ -6,7 +6,6 @@ import (
"os"
"os/signal"
"path/filepath"
"strings"
"syscall"
"time"
@@ -88,6 +87,7 @@ func (cluster *Cluster) StartLeaderCluster(c *kubevip.Config, sm *Manager) error
if err != nil {
return err
}
log.Infof("Beginning cluster membership, namespace [%s], lock name [%s], id [%s]", namespace, plunderLock, id)
// we use the Lease lock type since edits to Leases are less common
@@ -202,58 +202,27 @@ func (cluster *Cluster) StartLeaderCluster(c *kubevip.Config, sm *Manager) error
log.Error(err)
}
} else {
projects, _, err := packetClient.Projects.List(nil)
// If not attempt to attach the EIP in the standard manner
log.Debugf("Attaching the Packet EIP through the API to this host")
err = packet.AttachEIP(packetClient, c, id)
if err != nil {
log.Error(err)
}
for _, p := range projects {
log.Println(p.ID, p.Name)
// Find our project
if p.Name == c.PacketProject {
ips, _, _ := packetClient.ProjectIPs.List(p.ID)
for _, ip := range ips {
// Find the device id for our EIP
if ip.Address == c.VIP {
log.Infof("Found EIP ->%s ID -> %s\n", ip.Address, ip.ID)
if len(ip.Assignments) != 0 {
hrefID := strings.Replace(ip.Assignments[0].Href, "/ips/", "", -1)
packetClient.DeviceIPs.Unassign(hrefID)
}
}
}
// Go through devices
dev, _, _ := packetClient.Devices.List(p.ID, &packngo.ListOptions{})
for _, d := range dev {
if d.Hostname == id {
log.Infof("Assigning EIP to -> %s\n", d.Hostname)
_, _, err := packetClient.DeviceIPs.Assign(d.ID, &packngo.AddressStruct{
Address: c.VIP,
})
if err != nil {
log.Errorln(err)
}
}
}
}
}
}
}
if c.EnableBGP {
// Lets start BGP
log.Debugf("Starting the BGP server to adverise VIP routes to VGP peers")
bgpServer, err = bgp.NewBGPServer(&c.BGPConfig)
// Lets advertise the EIP over BGP
err = bgpServer.AddHost(c.VIP)
// Lets advertise the EIP over BGP, the host needs to be passed using CIDR notation
cidrVip := fmt.Sprintf("%s/%s", c.VIP, c.VIPCIDR)
log.Debugf("Attempting to advertise the address [%s] over BGP", cidrVip)
err = bgpServer.AddHost(cidrVip)
if err != nil {
log.Fatal(err)
log.Error(err)
}
}
@@ -340,6 +309,7 @@ func (cluster *Cluster) StartLeaderCluster(c *kubevip.Config, sm *Manager) error
//<-signalChan
log.Infof("Shutting down Kube-Vip Leader Election cluster")
// Force a removal of the VIP (ignore the error if we don't have it)
cluster.network.DeleteIP()

View File

@@ -29,6 +29,9 @@ const (
//vipAddress - defines the address that the vip will expose
vipAddress = "vip_address"
//vipCidr - defines the cidr that the vip will use
vipCidr = "vip_cidr"
//vipSingleNode - defines the vip start as a single node cluster
vipSingleNode = "vip_singlenode"
@@ -56,7 +59,7 @@ const (
//bgpEnable defines if BGP should be enabled
bgpEnable = "bgp_enable"
//bgpRouterID defines the routerID for the BGP server
bgpRouterID = "bgp_routerID"
bgpRouterID = "bgp_routerid"
//bgpRouterAS defines the AS for the BGP server
bgpRouterAS = "bgp_as"
//bgpPeerAddress defines the address for a BGP peer
@@ -115,6 +118,13 @@ func ParseEnvironment(c *Config) error {
c.VIP = env
}
// Find vip address cidr range
env = os.Getenv(c.VIPCIDR)
if env != "" {
// TODO - parse address net.Host()
c.VIPCIDR = env
}
// Find Single Node
env = os.Getenv(vipSingleNode)
if env != "" {
@@ -360,6 +370,20 @@ func GenerateManifestFromConfig(c *Config, imageVersion string) string {
},
}
// If a CIDR is used add it to the manifest
if c.VIPCIDR != "" {
// build environment variables
cidr := []appv1.EnvVar{
{
Name: vipCidr,
Value: c.VIPCIDR,
},
}
newEnvironment = append(newEnvironment, cidr...)
}
// If Leader election is enabled then add the configuration to the manifest
if !c.EnableLeaderElection {
raft := []appv1.EnvVar{
{
@@ -378,6 +402,8 @@ func GenerateManifestFromConfig(c *Config, imageVersion string) string {
newEnvironment = append(newEnvironment, raft...)
}
// If Packet is enabled then add it to the manifest
if c.EnablePacket {
packet := []appv1.EnvVar{
{
@@ -397,6 +423,7 @@ func GenerateManifestFromConfig(c *Config, imageVersion string) string {
}
// If BGP is enabled then add it to the manifest
if c.EnableBGP {
bgp := []appv1.EnvVar{
{
@@ -424,6 +451,7 @@ func GenerateManifestFromConfig(c *Config, imageVersion string) string {
}
// If the load-balancer is enabled then add the configuration to the manifest
if c.EnableLoadBalancer {
lb := []appv1.EnvVar{
{

View File

@@ -24,6 +24,9 @@ type Config struct {
// VIP is the Virtual IP address exposed for the cluster
VIP string `yaml:"vip"`
// VIPCIDR is cidr range for the VIP (primarily needed for BGP)
VIPCIDR string `yaml:"vipCidr"`
// GratuitousARP will broadcast an ARP update when the VIP changes host
GratuitousARP bool `yaml:"gratuitousARP"`

View File

@@ -17,18 +17,24 @@ func BGPLookup(c *packngo.Client, k *kubevip.Config) error {
}
thisDevice := findSelf(c, proj.ID)
if thisDevice == nil {
return fmt.Errorf("Unable to find correct device")
return fmt.Errorf("Unable to find local/this device in packet API")
}
fmt.Printf("Querying BGP settings for [%s]", thisDevice.Hostname)
neighbours, _, _ := c.Devices.ListBGPNeighbors(thisDevice.ID, &packngo.ListOptions{})
if len(neighbours) > 1 {
return fmt.Errorf("There are [%s] neighbours, only designed to manage one", len(neighbours))
return fmt.Errorf("There are [%d] neighbours, only designed to manage one", len(neighbours))
}
k.BGPConfig.RouterID = neighbours[0].CustomerIP
k.BGPConfig.AS = uint32(neighbours[0].CustomerAs)
// Add the peer
k.BGPConfig.Peers = []bgp.Peer{bgp.Peer{Address: neighbours[0].PeerIps[0], AS: uint32(neighbours[0].PeerAs)}}
k.BGPConfig.Peers = []bgp.Peer{
{
Address: neighbours[0].PeerIps[0],
AS: uint32(neighbours[0].PeerAs),
},
}
return nil
}

View File

@@ -1 +1,51 @@
package packet
import (
"fmt"
"strings"
"github.com/packethost/packngo"
"github.com/plunder-app/kube-vip/pkg/kubevip"
log "github.com/sirupsen/logrus"
)
// AttachEIP will use the packet APIs to move an EIP and attach to a host
func AttachEIP(c *packngo.Client, k *kubevip.Config, hostname string) error {
// Find our project
proj := findProject(k.PacketProject, c)
if proj == nil {
return fmt.Errorf("Unable to find Project [%s]", k.PacketProject)
}
ips, _, _ := c.ProjectIPs.List(proj.ID)
for _, ip := range ips {
// Find the device id for our EIP
if ip.Address == k.VIP {
log.Infof("Found EIP ->%s ID -> %s\n", ip.Address, ip.ID)
// If attachements already exist then remove them
if len(ip.Assignments) != 0 {
hrefID := strings.Replace(ip.Assignments[0].Href, "/ips/", "", -1)
c.DeviceIPs.Unassign(hrefID)
}
}
}
// Lookup this server through the packet API
thisDevice := findSelf(c, proj.ID)
if thisDevice == nil {
return fmt.Errorf("Unable to find local/this device in packet API")
}
// Assign the EIP to this device
log.Infof("Assigning EIP to -> %s\n", thisDevice.Hostname)
_, _, err := c.DeviceIPs.Assign(thisDevice.ID, &packngo.AddressStruct{
Address: k.VIP,
})
if err != nil {
return err
}
return nil
}