Skip to content

Commit

Permalink
Add support for unicast keepalived
Browse files Browse the repository at this point in the history
With this PR keepalived capability extended to support both unicast and multicast modes.

The following components were updated to support unicast mode:

- A simple server that will return node's non-virtual IP address, this server will be used
  by the master nodes to retrieve the bootstrap node IP address. One should contact the server on port 64444.

- keepalived-monitor can render conf file to support unicast or multicast mode, based on configuration.
  • Loading branch information
bcrochet authored and yboaronn committed Jul 6, 2020
1 parent 6e6f39f commit 4708d30
Show file tree
Hide file tree
Showing 7 changed files with 289 additions and 23 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -48,3 +48,4 @@ network_closure.sh
/monitor
/dynkeepalived
/corednsmonitor
/unicastipserver
2 changes: 2 additions & 0 deletions Dockerfile
Expand Up @@ -5,12 +5,14 @@ RUN GO111MODULE=on go build --mod=vendor -o runtimecfg ./cmd/runtimecfg
RUN GO111MODULE=on go build --mod=vendor cmd/dynkeepalived/dynkeepalived.go
RUN GO111MODULE=on go build --mod=vendor cmd/corednsmonitor/corednsmonitor.go
RUN GO111MODULE=on go build --mod=vendor cmd/monitor/monitor.go
RUN GO111MODULE=on go build --mod=vendor cmd/unicastipserver/unicastipserver.go

FROM registry.svc.ci.openshift.org/openshift/origin-v4.0:base
COPY --from=builder /go/src/github.com/openshift/baremetal-runtimecfg/runtimecfg /usr/bin/
COPY --from=builder /go/src/github.com/openshift/baremetal-runtimecfg/monitor /usr/bin
COPY --from=builder /go/src/github.com/openshift/baremetal-runtimecfg/dynkeepalived /usr/bin
COPY --from=builder /go/src/github.com/openshift/baremetal-runtimecfg/corednsmonitor /usr/bin
COPY --from=builder /go/src/github.com/openshift/baremetal-runtimecfg/unicastipserver /usr/bin
COPY --from=builder /go/src/github.com/openshift/baremetal-runtimecfg/scripts/* /usr/bin/

ENTRYPOINT ["/usr/bin/runtimecfg"]
Expand Down
46 changes: 46 additions & 0 deletions cmd/unicastipserver/unicastipserver.go
@@ -0,0 +1,46 @@
package main

import (
"fmt"
"os"

"github.com/openshift/baremetal-runtimecfg/pkg/monitor"
"github.com/spf13/cobra"
)

func main() {
var rootCmd = &cobra.Command{
Use: "unicastipserver [path to kubeconfig] [api-vip] [dns-vip] [ingress-vip] [api-provisioning-vip]",
Short: "baremetal-runtimecfg discovers OpenShift cluster and node configuration and renders Go templates",
RunE: func(cmd *cobra.Command, args []string) error {
apiVip, err := cmd.Flags().GetIP("api-vip")
if err != nil {
apiVip = nil
}
ingressVip, err := cmd.Flags().GetIP("ingress-vip")
if err != nil {
ingressVip = nil
}
dnsVip, err := cmd.Flags().GetIP("dns-vip")
if err != nil {
dnsVip = nil
}
unicastipServerPort, err := cmd.Flags().GetUint16("unicastip-server-port")
if err != nil {
return err
}

return monitor.UnicastIPServer(apiVip, ingressVip, dnsVip, unicastipServerPort)
},
}

rootCmd.Flags().IP("api-vip", nil, "Virtual IP Address to reach the OpenShift API")
rootCmd.Flags().IP("ingress-vip", nil, "Virtual IP Address to reach the OpenShift Ingress Routers")
rootCmd.Flags().IP("dns-vip", nil, "Virtual IP Address to reach an OpenShift node resolving DNS server")
rootCmd.Flags().Uint16("unicastip-server-port", 64444, "Port where the OpenShift API listens at")

if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
1 change: 1 addition & 0 deletions go.sum
Expand Up @@ -37,6 +37,7 @@ github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d h1:7XGaL1e6bYS1
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4=
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
Expand Down
83 changes: 76 additions & 7 deletions pkg/config/node.go
Expand Up @@ -10,6 +10,7 @@ import (
"os"
"sort"
"strings"
"time"

"github.com/ghodss/yaml"
"github.com/sirupsen/logrus"
Expand All @@ -22,6 +23,7 @@ import (
"github.com/openshift/installer/pkg/types"
)

const bootstrapIpServerPort string = "64444"
const localhostKubeApiServerUrl string = "https://localhost:6443"

var log = logrus.New()
Expand Down Expand Up @@ -57,6 +59,10 @@ type ApiLBConfig struct {
FrontendAddr string
}

type IngressConfig struct {
Peers []string
}

type Node struct {
Cluster Cluster
LBConfig ApiLBConfig
Expand All @@ -65,6 +71,9 @@ type Node struct {
EtcdShortHostname string
VRRPInterface string
DNSUpstreams []string
BootstrapIP string
IngressConfig IngressConfig
EnableUnicast bool
}

func getDNSUpstreams(resolvConfPath string) (upstreams []string, err error) {
Expand Down Expand Up @@ -172,6 +181,67 @@ func (c *Cluster) PopulateVRIDs() error {
}
return nil
}
func GetBootstrapIP(apiVip string) (bootstrapIP string, err error) {
conn, err := net.DialTimeout("tcp", net.JoinHostPort(apiVip, bootstrapIpServerPort), 10*time.Second)
if err != nil {
log.Infof("An error occurred on dial: %v", err)
return "", err
}
defer conn.Close()

bootstrapIP, err = bufio.NewReader(conn).ReadString('\n')
if err != nil {
log.Infof("An error occurred on read: %v", err)
return "", err
}

bootstrapIP = strings.TrimSpace(bootstrapIP)

log.Infof("Got bootstrap IP %v", bootstrapIP)

return bootstrapIP, err
}

func GetVRRPConfig(apiVip, ingressVip, dnsVip net.IP) (vipIface net.Interface, nonVipAddr *net.IPNet, err error) {
vips := make([]net.IP, 0)
if apiVip != nil {
vips = append(vips, apiVip)
}
if ingressVip != nil {
vips = append(vips, ingressVip)
}
if dnsVip != nil {
vips = append(vips, dnsVip)
}
return getInterfaceAndNonVIPAddr(vips)
}

func GetIngressConfig(kubeconfigPath string) (ingressConfig IngressConfig, err error) {
config, err := clientcmd.BuildConfigFromFlags("", kubeconfigPath)
if err != nil {
return ingressConfig, err
}

clientset, err := kubernetes.NewForConfig(config)
if err != nil {
return ingressConfig, err
}

nodes, err := clientset.CoreV1().Nodes().List(metav1.ListOptions{})
if err != nil {
return ingressConfig, err
}

for _, node := range nodes.Items {
for _, address := range node.Status.Addresses {
if address.Type == v1.NodeInternalIP {
ingressConfig.Peers = append(ingressConfig.Peers, address.Address)
}
}
}

return ingressConfig, nil
}

func GetConfig(kubeconfigPath, clusterConfigPath, resolvConfPath string, apiVip net.IP, ingressVip net.IP, dnsVip net.IP, apiPort, lbPort, statPort uint16) (node Node, err error) {
// Try cluster-config.yml first
Expand Down Expand Up @@ -207,12 +277,9 @@ func GetConfig(kubeconfigPath, clusterConfigPath, resolvConfPath string, apiVip
if err != nil {
return node, err
}

vips := make([]net.IP, 0)
node.Cluster.APIVIPRecordType = "A"
node.Cluster.APIVIPEmptyType = "AAAA"
if apiVip != nil {
vips = append(vips, apiVip)
node.Cluster.APIVIP = apiVip.String()
if apiVip.To4() == nil {
node.Cluster.APIVIPRecordType = "AAAA"
Expand All @@ -222,23 +289,26 @@ func GetConfig(kubeconfigPath, clusterConfigPath, resolvConfPath string, apiVip
node.Cluster.IngressVIPRecordType = "A"
node.Cluster.IngressVIPEmptyType = "AAAA"
if ingressVip != nil {
vips = append(vips, ingressVip)
node.Cluster.IngressVIP = ingressVip.String()
if ingressVip.To4() == nil {
node.Cluster.IngressVIPRecordType = "AAAA"
node.Cluster.IngressVIPEmptyType = "A"
}
}
if dnsVip != nil {
vips = append(vips, dnsVip)
node.Cluster.DNSVIP = dnsVip.String()
}
vipIface, nonVipAddr, err := getInterfaceAndNonVIPAddr(vips)
vipIface, nonVipAddr, err := GetVRRPConfig(apiVip, ingressVip, dnsVip)
if err != nil {
return node, err
}
node.NonVirtualIP = nonVipAddr.IP.String()

node.EnableUnicast = false
if os.Getenv("ENABLE_UNICAST") == "yes" {
node.EnableUnicast = true
}

resolvConfUpstreams, err := getDNSUpstreams(resolvConfPath)
if err != nil {
return node, err
Expand Down Expand Up @@ -346,7 +416,6 @@ func GetLBConfig(kubeconfigPath string, apiPort, lbPort, statPort uint16, apiVip
return config, err
}
}

// The backends port is the Etcd one, but we need to loadbalance the API one
for i := 0; i < len(backends); i++ {
backends[i].Port = apiPort
Expand Down

0 comments on commit 4708d30

Please sign in to comment.