Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

windows support for cni server #1455

Merged
merged 1 commit into from
Apr 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
.vscode/*
.DS_Store
dist/images/kube-ovn-cmd
dist/images/kube-ovn.exe
dist/images/kube-ovn-webhook
dist/images/kube-ovn.exe
dist/images/kube-ovn-daemon.exe
test/e2e/ovnnb_db.*
test/e2e/ovnsb_db.*
kube-ovn.yaml
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ build-go:
build-go-windows:
go mod tidy
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -buildmode=pie -o $(CURDIR)/dist/images/kube-ovn.exe -ldflags $(GOLDFLAGS) -v ./cmd/windows/cni
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -buildmode=pie -o $(CURDIR)/dist/images/kube-ovn-daemon.exe -ldflags $(GOLDFLAGS) -v ./cmd/windows/daemon

.PHONY: build-go-arm
build-go-arm:
Expand Down
11 changes: 6 additions & 5 deletions cmd/daemon/cniserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"net/http"
_ "net/http/pprof" // #nosec
"os"
"path/filepath"
"strings"
"time"

Expand Down Expand Up @@ -75,21 +76,21 @@ func CmdMain() {
kubeovnInformerFactory.Start(stopCh)
go ctl.Run(stopCh)
go daemon.RunServer(config, ctl)
if err := mvCNIConf(config.CniConfName); err != nil {
if err := mvCNIConf(config.CniConfDir, config.CniConfFile, config.CniConfName); err != nil {
klog.Fatalf("failed to mv cni conf, %v", err)
}
http.Handle("/metrics", promhttp.Handler())
klog.Fatal(http.ListenAndServe(fmt.Sprintf("0.0.0.0:%d", config.PprofPort), nil))
}

func mvCNIConf(confName string) error {
data, err := os.ReadFile("/kube-ovn/01-kube-ovn.conflist")
func mvCNIConf(configDir, configFile, confName string) error {
data, err := os.ReadFile(configFile)
if err != nil {
return err
}

cniConfPath := fmt.Sprintf("/etc/cni/net.d/%s", confName)
return os.WriteFile(cniConfPath, data, 0444)
cniConfPath := filepath.Join(configDir, confName)
return os.WriteFile(cniConfPath, data, 0644)
}

func Retry(attempts int, sleep int, f func(configuration *daemon.Configuration) error, ctrl *daemon.Configuration) (err error) {
Expand Down
7 changes: 7 additions & 0 deletions cmd/windows/daemon/main_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package main

import "github.com/kubeovn/kube-ovn/cmd/daemon"

func main() {
daemon.CmdMain()
}
12 changes: 7 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ go 1.17
require (
github.com/Mellanox/sriovnet v1.0.3
github.com/Microsoft/go-winio v0.5.2
github.com/Microsoft/hcsshim v0.9.2
github.com/alauda/felix v3.6.6-0.20201207121355-187332daf314+incompatible
github.com/bhendo/go-powershell v0.0.0-20190719160123-219e7fb4e41e
github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08
github.com/containernetworking/cni v1.0.1
github.com/containernetworking/plugins v1.1.1
Expand All @@ -26,7 +28,7 @@ require (
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.7.0
github.com/vishvananda/netlink v1.1.1-0.20211101163509-b10eb8fe5cf6
golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad
google.golang.org/grpc v1.40.0
gopkg.in/k8snetworkplumbingwg/multus-cni.v3 v3.7.2
k8s.io/api v0.23.1
Expand All @@ -40,12 +42,11 @@ require (
)

require (
github.com/Microsoft/hcsshim v0.8.22 // indirect
github.com/armon/go-radix v1.0.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/buger/jsonparser v1.1.1 // indirect
github.com/cespare/xxhash/v2 v2.1.1 // indirect
github.com/containerd/cgroups v1.0.1 // indirect
github.com/containerd/cgroups v1.0.3 // indirect
github.com/coreos/prometheus-operator v0.38.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect
Expand All @@ -61,8 +62,8 @@ require (
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/glog v1.0.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/mock v1.5.0 // indirect
github.com/google/go-cmp v0.5.5 // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/google/go-cmp v0.5.6 // indirect
github.com/google/gofuzz v1.1.0 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/googleapis/gnostic v0.5.5 // indirect
Expand All @@ -71,6 +72,7 @@ require (
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/juju/errors v0.0.0-20220331221717-b38fca44723b // indirect
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect
github.com/kelseyhightower/envconfig v1.4.0 // indirect
github.com/kubernetes-csi/external-snapshotter/v2 v2.1.1 // indirect
Expand Down
48 changes: 40 additions & 8 deletions go.sum

Large diffs are not rendered by default.

98 changes: 20 additions & 78 deletions pkg/daemon/config.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package daemon

import (
"context"
"errors"
"flag"
"fmt"
"net"
Expand All @@ -13,7 +11,6 @@ import (

"github.com/sirupsen/logrus"
"github.com/spf13/pflag"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
Expand Down Expand Up @@ -42,6 +39,8 @@ type Configuration struct {
EncapChecksum bool
PprofPort int
NetworkType string
CniConfDir string
CniConfFile string
CniConfName string
DefaultProviderName string
DefaultInterfaceName string
Expand All @@ -52,20 +51,23 @@ type Configuration struct {
// TODO: validate configuration
func ParseFlags(nicBridgeMappings map[string]string) (*Configuration, error) {
var (
argNodeName = pflag.String("node-name", "", "Name of the node on which the daemon is running on.")
argIface = pflag.String("iface", "", "The iface used to inter-host pod communication, can be a nic name or a group of regex separated by comma (default the default route iface)")
argDPDKTunnelIface = pflag.String("dpdk-tunnel-iface", "br-phy", "Specifies the name of the dpdk tunnel iface.")
argMTU = pflag.Int("mtu", 0, "The MTU used by pod iface in overlay networks (default iface MTU - 100)")
argEnableMirror = pflag.Bool("enable-mirror", false, "Enable traffic mirror (default false)")
argMirrorNic = pflag.String("mirror-iface", "mirror0", "The mirror nic name that will be created by kube-ovn")
argBindSocket = pflag.String("bind-socket", "/run/openvswitch/kube-ovn-daemon.sock", "The socket daemon bind to.")
argBindSocket = pflag.String("bind-socket", defaultBindSocket, "The socket daemon bind to.")
argOvsSocket = pflag.String("ovs-socket", "", "The socket to local ovs-server")
argKubeConfigFile = pflag.String("kubeconfig", "", "Path to kubeconfig file with authorization and master location information. If not set use the inCluster token.")
argServiceClusterIPRange = pflag.String("service-cluster-ip-range", "10.96.0.0/12", "The kubernetes service cluster ip range")
argNodeLocalDnsIP = pflag.String("node-local-dns-ip", "", "If use nodelocaldns the local dns server ip should be set here.")
argEncapChecksum = pflag.Bool("encap-checksum", true, "Enable checksum")
argPprofPort = pflag.Int("pprof-port", 10665, "The port to get profiling data")

argsNetworkType = pflag.String("network-type", "geneve", "The ovn network type")
argsNetworkType = pflag.String("network-type", defaultNetworkType, "The ovn network type")
argCniConfDir = pflag.String("cni-conf-dir", util.DefaultCniConfigDir, "Path of the CNI config directory.")
argCniConfFile = pflag.String("cni-conf-file", util.DefaultCniConfigFile, "Path of the CNI config file.")
argsCniConfName = pflag.String("cni-conf-name", "01-kube-ovn.conflist", "Specify the name of kube ovn conflist name in dir /etc/cni/net.d/, default: 01-kube-ovn.conflist")
argsDefaultProviderName = pflag.String("default-provider-name", "provider", "The vlan or vxlan type default provider interface name")
argsDefaultInterfaceName = pflag.String("default-interface-name", "", "The default host interface name in the vlan/vxlan type")
Expand Down Expand Up @@ -93,11 +95,18 @@ func ParseFlags(nicBridgeMappings map[string]string) (*Configuration, error) {
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
pflag.Parse()

nodeName := os.Getenv(util.HostnameEnv)
nodeName := *argNodeName
if nodeName == "" {
klog.Errorf("env KUBE_NODE_NAME not exists")
return nil, fmt.Errorf("env KUBE_NODE_NAME not exists")
klog.Info("node name not specified in command line parameters, fall back to the environment variable")
if nodeName = os.Getenv(util.HostnameEnv); nodeName == "" {
klog.Info("node name not specified in environment variables, fall back to the hostname")
var err error
if nodeName, err = os.Hostname(); err != nil {
return nil, fmt.Errorf("failed to get hostname: %v", err)
}
}
}

config := &Configuration{
Iface: *argIface,
DPDKTunnelIface: *argDPDKTunnelIface,
Expand All @@ -108,11 +117,13 @@ func ParseFlags(nicBridgeMappings map[string]string) (*Configuration, error) {
OvsSocket: *argOvsSocket,
KubeConfigFile: *argKubeConfigFile,
PprofPort: *argPprofPort,
NodeName: nodeName,
NodeName: strings.ToLower(nodeName),
ServiceClusterIPRange: *argServiceClusterIPRange,
NodeLocalDnsIP: *argNodeLocalDnsIP,
EncapChecksum: *argEncapChecksum,
NetworkType: *argsNetworkType,
CniConfDir: *argCniConfDir,
CniConfFile: *argCniConfFile,
CniConfName: *argsCniConfName,
DefaultProviderName: *argsDefaultProviderName,
DefaultInterfaceName: *argsDefaultInterfaceName,
Expand All @@ -131,75 +142,6 @@ func ParseFlags(nicBridgeMappings map[string]string) (*Configuration, error) {
return config, nil
}

func (config *Configuration) initNicConfig(nicBridgeMappings map[string]string) error {
var (
iface *net.Interface
err error
encapIP string
)

// Support to specify node network card separately
node, err := config.KubeClient.CoreV1().Nodes().Get(context.Background(), config.NodeName, metav1.GetOptions{})
if err != nil {
klog.Errorf("Failed to find node info, err: %v", err)
return err
}
if nodeTunnelName := node.GetAnnotations()[util.TunnelInterfaceAnnotation]; nodeTunnelName != "" {
config.Iface = nodeTunnelName
klog.Infof("Find node tunnel interface name: %v", nodeTunnelName)
}

isDPDKNode := node.GetLabels()[util.OvsDpTypeLabel] == "userspace"
if isDPDKNode {
config.Iface = config.DPDKTunnelIface
}
if config.Iface == "" {
podIP, ok := os.LookupEnv(util.POD_IP)
if !ok || podIP == "" {
return errors.New("failed to lookup env POD_IP")
}
iface, err = getIfaceOwnPodIP(podIP)
if err != nil {
klog.Errorf("failed to find POD_IP iface %v", err)
return err
}
encapIP = podIP
} else {
tunnelNic := config.Iface
if brName := nicBridgeMappings[tunnelNic]; brName != "" {
klog.Infof("nic %s has been bridged to %s, use %s as the tunnel interface instead", tunnelNic, brName, brName)
tunnelNic = brName
}

iface, err = findInterface(tunnelNic)
if err != nil {
klog.Errorf("failed to find iface %s, %v", tunnelNic, err)
return err
}
addrs, err := iface.Addrs()
if err != nil {
return fmt.Errorf("failed to get iface addr. %v", err)
}
if len(addrs) == 0 {
return fmt.Errorf("iface %s has no ip address", tunnelNic)
}
encapIP = strings.Split(addrs[0].String(), "/")[0]
}

if config.MTU == 0 {
config.MTU = iface.MTU - util.GeneveHeaderLength
}

config.MSS = config.MTU - util.TcpIpHeaderLength
if !config.EncapChecksum {
if err := disableChecksum(); err != nil {
klog.Errorf("failed to set checksum offload, %v", err)
}
}

return setEncapIP(encapIP)
}

func findInterface(ifaceStr string) (*net.Interface, error) {
iface, err := net.InterfaceByName(ifaceStr)
if err == nil && iface != nil {
Expand Down
80 changes: 80 additions & 0 deletions pkg/daemon/config_linux.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,93 @@
package daemon

import (
"context"
"errors"
"fmt"
"net"
"os"
"strings"

"github.com/kubeovn/kube-ovn/pkg/util"
"github.com/vishvananda/netlink"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/klog/v2"
)

const (
defaultBindSocket = `/run/openvswitch/kube-ovn-daemon.sock`
defaultNetworkType = `geneve`
)

func (config *Configuration) initNicConfig(nicBridgeMappings map[string]string) error {
var (
iface *net.Interface
err error
encapIP string
)

// Support to specify node network card separately
node, err := config.KubeClient.CoreV1().Nodes().Get(context.Background(), config.NodeName, metav1.GetOptions{})
if err != nil {
klog.Errorf("Failed to find node info, err: %v", err)
return err
}
if nodeTunnelName := node.GetAnnotations()[util.TunnelInterfaceAnnotation]; nodeTunnelName != "" {
config.Iface = nodeTunnelName
klog.Infof("Find node tunnel interface name: %v", nodeTunnelName)
}

isDPDKNode := node.GetLabels()[util.OvsDpTypeLabel] == "userspace"
if isDPDKNode {
config.Iface = config.DPDKTunnelIface
}
if config.Iface == "" {
podIP, ok := os.LookupEnv(util.POD_IP)
if !ok || podIP == "" {
return errors.New("failed to lookup env POD_IP")
}
iface, err = getIfaceOwnPodIP(podIP)
if err != nil {
klog.Errorf("failed to find POD_IP iface %v", err)
return err
}
encapIP = podIP
} else {
tunnelNic := config.Iface
if brName := nicBridgeMappings[tunnelNic]; brName != "" {
klog.Infof("nic %s has been bridged to %s, use %s as the tunnel interface instead", tunnelNic, brName, brName)
tunnelNic = brName
}

iface, err = findInterface(tunnelNic)
if err != nil {
klog.Errorf("failed to find iface %s, %v", tunnelNic, err)
return err
}
addrs, err := iface.Addrs()
if err != nil {
return fmt.Errorf("failed to get iface addr. %v", err)
}
if len(addrs) == 0 {
return fmt.Errorf("iface %s has no ip address", tunnelNic)
}
encapIP = strings.Split(addrs[0].String(), "/")[0]
}

if config.MTU == 0 {
config.MTU = iface.MTU - util.GeneveHeaderLength
}

config.MSS = config.MTU - util.TcpIpHeaderLength
if !config.EncapChecksum {
if err := disableChecksum(); err != nil {
klog.Errorf("failed to set checksum offload, %v", err)
}
}

return setEncapIP(encapIP)
}

func getIfaceOwnPodIP(podIP string) (*net.Interface, error) {
links, err := netlink.LinkList()
if err != nil {
Expand Down
Loading