From 2a3eaff0f9fd3643a815cb5407449bb7aa1bb834 Mon Sep 17 00:00:00 2001 From: RouxAntoine Date: Wed, 4 May 2022 16:55:50 +0200 Subject: [PATCH] feat: cilium add-mode support when cni management by kilo is disable, we can use existing cluster's cni setup thanks to add-on mode https://kilo.squat.ai/docs/introduction#add-on-mode --- cmd/kg/main.go | 2 + pkg/encapsulation/cilium.go | 108 ++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 pkg/encapsulation/cilium.go diff --git a/cmd/kg/main.go b/cmd/kg/main.go index c1b4870..1834653 100644 --- a/cmd/kg/main.go +++ b/cmd/kg/main.go @@ -213,6 +213,8 @@ func runRoot(_ *cobra.Command, _ []string) error { switch compatibility { case "flannel": enc = encapsulation.NewFlannel(e) + case "cilium": + enc = encapsulation.NewCilium(e) default: enc = encapsulation.NewIPIP(e) } diff --git a/pkg/encapsulation/cilium.go b/pkg/encapsulation/cilium.go new file mode 100644 index 0000000..84065d6 --- /dev/null +++ b/pkg/encapsulation/cilium.go @@ -0,0 +1,108 @@ +// Copyright 2019 the Kilo authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package encapsulation + +import ( + "fmt" + "net" + "sync" + + "github.com/squat/kilo/pkg/iptables" + "github.com/vishvananda/netlink" +) + +const ciliumDeviceName = "cilium_host" + +type cilium struct { + iface int + strategy Strategy + ch chan netlink.LinkUpdate + done chan struct{} + // mu guards updates to the iface field. + mu sync.Mutex +} + +// NewCilium returns an encapsulator that uses Cilium. +func NewCilium(strategy Strategy) Encapsulator { + return &cilium{ + ch: make(chan netlink.LinkUpdate), + done: make(chan struct{}), + strategy: strategy, + } +} + +// CleanUp is a no-op. +func (f *cilium) CleanUp() error { + close(f.done) + return nil +} + +// Gw returns the correct gateway IP associated with the given node. +func (f *cilium) Gw(_, _ net.IP, subnet *net.IPNet) net.IP { + return subnet.IP +} + +// Index returns the index of the Cilium interface. +func (f *cilium) Index() int { + return f.iface +} + +// Init finds the Cilium interface index. +func (f *cilium) Init(_ int) error { + if err := netlink.LinkSubscribe(f.ch, f.done); err != nil { + return fmt.Errorf("failed to subscribe to updates to %s: %v", ciliumDeviceName, err) + } + go func() { + var lu netlink.LinkUpdate + for { + select { + case lu = <-f.ch: + if lu.Attrs().Name == ciliumDeviceName { + f.mu.Lock() + f.iface = lu.Attrs().Index + f.mu.Unlock() + } + case <-f.done: + return + } + } + }() + i, err := netlink.LinkByName(ciliumDeviceName) + if _, ok := err.(netlink.LinkNotFoundError); ok { + return nil + } + if err != nil { + return fmt.Errorf("failed to query for Cilium interface: %v", err) + } + f.mu.Lock() + f.iface = i.Attrs().Index + f.mu.Unlock() + return nil +} + +// Rules is a no-op. +func (f *cilium) Rules(_ []*net.IPNet) []iptables.Rule { + return nil +} + +// Set is a no-op. +func (f *cilium) Set(_ *net.IPNet) error { + return nil +} + +// Strategy returns the configured strategy for encapsulation. +func (f *cilium) Strategy() Strategy { + return f.strategy +}