Skip to content

Commit

Permalink
feat: support advertise subnet route
Browse files Browse the repository at this point in the history
  • Loading branch information
oilbeater committed Dec 7, 2020
1 parent 27c5718 commit 2ef6656
Show file tree
Hide file tree
Showing 50 changed files with 732 additions and 1,718 deletions.
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,16 @@ build-go:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o $(PWD)/dist/images/kube-ovn-daemon -ldflags $(GOLDFLAGS) -v ./cmd/daemon
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o $(PWD)/dist/images/kube-ovn-pinger -ldflags $(GOLDFLAGS) -v ./cmd/pinger
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o $(PWD)/dist/images/kube-ovn-monitor -ldflags $(GOLDFLAGS) -v ./cmd/ovn_monitor
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o $(PWD)/dist/images/kube-ovn-speaker -ldflags $(GOLDFLAGS) -v ./cmd/speaker


build-go-arm:
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o $(PWD)/dist/images/kube-ovn -ldflags $(GOLDFLAGS) -v ./cmd/cni
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o $(PWD)/dist/images/kube-ovn-controller -ldflags $(GOLDFLAGS) -v ./cmd/controller
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o $(PWD)/dist/images/kube-ovn-daemon -ldflags $(GOLDFLAGS) -v ./cmd/daemon
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o $(PWD)/dist/images/kube-ovn-pinger -ldflags $(GOLDFLAGS) -v ./cmd/pinger
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o $(PWD)/dist/images/kube-ovn-monitor -ldflags $(GOLDFLAGS) -v ./cmd/ovn_monitor
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o $(PWD)/dist/images/kube-ovn-speaker -ldflags $(GOLDFLAGS) -v ./cmd/speaker

release: lint build-go
docker buildx build --cache-from "type=local,src=/tmp/.buildx-cache" --cache-to "type=local,dest=/tmp/.buildx-cache" --platform linux/amd64 --build-arg ARCH=amd64 --build-arg RPM_ARCH=x86_64 -t ${REGISTRY}/kube-ovn:${RELEASE_TAG} -o type=docker -f dist/images/Dockerfile dist/images/
Expand Down
1 change: 1 addition & 0 deletions dist/images/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,4 @@ COPY kube-ovn /kube-ovn/kube-ovn
COPY kube-ovn-daemon /kube-ovn/kube-ovn-daemon
COPY kube-ovn-controller /kube-ovn/kube-ovn-controller
COPY kube-ovn-monitor /kube-ovn/kube-ovn-monitor
COPY kube-ovn-speaker /kube-ovn/kube-ovn-speaker
22 changes: 17 additions & 5 deletions docs/bgp.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# BGP support

Kube-OVN supports broadcast pod ips to external networks by BGP protocol.
To enable BGP announce function, you need to install kube-ovn-speaker and annotate pods that need to be exposed.
Kube-OVN supports advertise pod/subnet ips to external networks by BGP protocol.
To enable BGP advertise function, you need to install kube-ovn-speaker and annotate pods/subnets that need to be exposed.

## Install kube-ovn-speaker

Expand All @@ -25,12 +25,24 @@ wget https://github.com/alauda/kube-ovn/blob/master/yamls/speaker.yaml
kubectl apply -f speaker.yaml
```

## Annotate pods that need to be exposed
4. Label nodes that host the BGP speaker and act as overlay to underlay gateway
```bash
kubectl label nodes speaker-node-1 ovn.kubernetes.io/bgp=true
kubectl label nodes speaker-node-2 ovn.kubernetes.io/bgp=true
```

*NOTE*: When more than one node host speaker, the upstream router need to support multiple path routes to act ECMP.

## Annotate pods/subnet that need to be exposed

The subnet of pods and subnets need to be advertised should set `natOutgoing` to `false`

```bash
# Enable BGP
# Enable BGP advertise
kubectl annotate pod sample ovn.kubernetes.io/bgp=true
kubectl annotate subnet ovn-default ovn.kubernetes.io/bgp=true

# Disable BGP
# Disable BGP advertise
kubectl annotate pod perf-ovn-xzvd4 ovn.kubernetes.io/bgp-
kubectl annotate subnet ovn-default ovn.kubernetes.io/bgp-
```
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ require (
github.com/intel/multus-cni v0.0.0-20200313031649-eaf6ff6e20bb
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect
github.com/kelseyhightower/envconfig v1.4.0 // indirect
github.com/kubesphere/porter v0.1.1
github.com/moul/http2curl v1.0.0 // indirect
github.com/neverlee/keymutex v0.0.0-20171121013845-f593aa834bf9
github.com/oilbeater/go-ping v0.0.0-20200413021620-332b7197c5b5
Expand Down
96 changes: 4 additions & 92 deletions go.sum

Large diffs are not rendered by default.

File renamed without changes.
File renamed without changes.
File renamed without changes.
18 changes: 15 additions & 3 deletions pkg/speaker/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"errors"
"flag"
"fmt"
clientset "github.com/alauda/kube-ovn/pkg/client/clientset/versioned"
api "github.com/osrg/gobgp/api"
gobgp "github.com/osrg/gobgp/pkg/server"
"github.com/spf13/pflag"
Expand All @@ -23,10 +24,12 @@ type Configuration struct {
RouterId string
NeighborAddress string
NeighborAs uint32
AuthPassword string
BgpServer *gobgp.BgpServer

KubeConfigFile string
KubeClient kubernetes.Interface
KubeOvnClient clientset.Interface

PprofPort uint32
}
Expand All @@ -39,13 +42,11 @@ func ParseFlags() (*Configuration, error) {
argRouterId = pflag.String("router-id", "", "The address for the speaker to use as router id, default the node ip")
argNeighborAddress = pflag.String("neighbor-address", "", "The router address the speaker connects to.")
argNeighborAs = pflag.Uint32("neighbor-as", 65001, "The router as number, default 65001")
argAuthPassword = pflag.String("auth-password", "", "bgp peer auth password")
argPprofPort = pflag.Uint32("pprof-port", 10667, "The port to get profiling data, default: 10667")
argKubeConfigFile = pflag.String("kubeconfig", "", "Path to kubeconfig file with authorization and master location information. If not set use the inCluster token.")
)

if err := flag.Set("alsologtostderr", "true"); err != nil {
klog.Fatalf("failed to set flag, %v", err)
}
klogFlags := flag.NewFlagSet("klog", flag.ExitOnError)
klog.InitFlags(klogFlags)

Expand All @@ -71,6 +72,7 @@ func ParseFlags() (*Configuration, error) {
RouterId: *argRouterId,
NeighborAddress: *argNeighborAddress,
NeighborAs: *argNeighborAs,
AuthPassword: *argAuthPassword,
PprofPort: *argPprofPort,
KubeConfigFile: *argKubeConfigFile,
}
Expand Down Expand Up @@ -113,6 +115,13 @@ func (config *Configuration) initKubeClient() error {
cfg.QPS = 1000
cfg.Burst = 2000

kubeOvnClient, err := clientset.NewForConfig(cfg)
if err != nil {
klog.Errorf("init kubeovn client failed %v", err)
return err
}
config.KubeOvnClient = kubeOvnClient

cfg.ContentType = "application/vnd.kubernetes.protobuf"
cfg.AcceptContentTypes = "application/vnd.kubernetes.protobuf,application/json"
kubeClient, err := kubernetes.NewForConfig(cfg)
Expand Down Expand Up @@ -149,6 +158,9 @@ func (config *Configuration) initBgpServer() error {
PeerAs: config.NeighborAs,
},
}
if config.AuthPassword != "" {
peer.Conf.AuthPassword = config.AuthPassword
}

if err := s.AddPeer(context.Background(), &api.AddPeerRequest{
Peer: peer,
Expand Down
49 changes: 25 additions & 24 deletions pkg/speaker/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package speaker

import (
kubeovnv1 "github.com/alauda/kube-ovn/pkg/apis/kubeovn/v1"
kubeovninformer "github.com/alauda/kube-ovn/pkg/client/informers/externalversions"
kubeovnlister "github.com/alauda/kube-ovn/pkg/client/listers/kubeovn/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
Expand All @@ -14,7 +16,6 @@ import (
listerv1 "k8s.io/client-go/listers/core/v1"
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/tools/record"
"k8s.io/client-go/util/workqueue"
"k8s.io/klog"
)

Expand All @@ -23,14 +24,14 @@ const controllerAgentName = "ovn-speaker"
type Controller struct {
config *Configuration

podsLister listerv1.PodLister
podsSynced cache.InformerSynced
podsLister listerv1.PodLister
podsSynced cache.InformerSynced
subnetsLister kubeovnlister.SubnetLister
subnetSynced cache.InformerSynced

addPodQueue workqueue.RateLimitingInterface
deletePodQueue workqueue.RateLimitingInterface

informerFactory kubeinformers.SharedInformerFactory
recorder record.EventRecorder
informerFactory kubeinformers.SharedInformerFactory
kubeovnInformerFactory kubeovninformer.SharedInformerFactory
recorder record.EventRecorder
}

func NewController(config *Configuration) *Controller {
Expand All @@ -45,41 +46,41 @@ func NewController(config *Configuration) *Controller {
kubeinformers.WithTweakListOptions(func(listOption *metav1.ListOptions) {
listOption.AllowWatchBookmarks = true
}))
kubeovnInformerFactory := kubeovninformer.NewSharedInformerFactoryWithOptions(config.KubeOvnClient, 0,
kubeovninformer.WithTweakListOptions(func(listOption *metav1.ListOptions) {
listOption.AllowWatchBookmarks = true
}))

podInformer := informerFactory.Core().V1().Pods()
subnetInformer := kubeovnInformerFactory.Kubeovn().V1().Subnets()
controller := &Controller{
config: config,

podsLister: podInformer.Lister(),
podsSynced: podInformer.Informer().HasSynced,
addPodQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "AddPod"),
deletePodQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "DeletePod"),
podsLister: podInformer.Lister(),
podsSynced: podInformer.Informer().HasSynced,
subnetsLister: subnetInformer.Lister(),
subnetSynced: subnetInformer.Informer().HasSynced,

informerFactory: informerFactory,
recorder: recorder,
informerFactory: informerFactory,
kubeovnInformerFactory: kubeovnInformerFactory,
recorder: recorder,
}
podInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: controller.enqueueAddPod,
DeleteFunc: controller.enqueueDeletePod,
UpdateFunc: controller.enqueueUpdatePod,
})

return controller
}

func (c *Controller) Run(stopCh <-chan struct{}) {
defer utilruntime.HandleCrash()
defer c.addPodQueue.ShutDown()
defer c.deletePodQueue.ShutDown()
c.informerFactory.Start(stopCh)
c.kubeovnInformerFactory.Start(stopCh)

if ok := cache.WaitForCacheSync(stopCh, c.podsSynced); !ok {
if ok := cache.WaitForCacheSync(stopCh, c.podsSynced, c.subnetSynced); !ok {
klog.Fatalf("failed to wait for caches to sync")
return
}

klog.Info("Started workers")
go wait.Until(c.runAddPodWorker, time.Second, stopCh)
go wait.Until(c.runDeletePodWorker, 3*time.Second, stopCh)
go wait.Until(c.syncSubnetRoutes, 5*time.Second, stopCh)

<-stopCh
klog.Info("Shutting down workers")
Expand Down
Loading

0 comments on commit 2ef6656

Please sign in to comment.