Skip to content

Commit

Permalink
Multi Network support in the NEG controller
Browse files Browse the repository at this point in the history
  • Loading branch information
mmamczur committed Apr 7, 2023
1 parent 310ded4 commit 14322fc
Show file tree
Hide file tree
Showing 40 changed files with 2,243 additions and 267 deletions.
5 changes: 4 additions & 1 deletion cmd/glbc/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ import (
"context"
"encoding/json"
"fmt"
networkclient "k8s.io/cloud-provider-gcp/crd/client/network/clientset/versioned"
"math/rand"
"os"
"time"

networkclient "k8s.io/cloud-provider-gcp/crd/client/network/clientset/versioned"

flag "github.com/spf13/pflag"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/ingress-gce/pkg/frontendconfig"
Expand Down Expand Up @@ -350,6 +351,8 @@ func runControllers(ctx *ingctx.ControllerContext) {
ctx.NodeInformer,
ctx.EndpointSliceInformer,
ctx.SvcNegInformer,
ctx.NetworkInformer,
ctx.GKENetworkParamsInformer,
ctx.HasSynced,
ctx.ControllerMetrics,
ctx.L4Namer,
Expand Down
127 changes: 127 additions & 0 deletions pkg/multinetwork/multinetwork.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package multinetwork

import (
"fmt"
"strings"

"github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud"
"github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta"
apiv1 "k8s.io/api/core/v1"
"k8s.io/client-go/tools/cache"
networkv1 "k8s.io/cloud-provider-gcp/crd/apis/network/v1"
gkenetworkparamsetv1alpha1 "k8s.io/cloud-provider-gcp/crd/apis/network/v1alpha1"
)

const (
networkingGKEGroup = "networking.gke.io"
gkeNetworkParamSetKind = "gkenetworkparamset"
networkSelector = "networking.gke.io/network"
)

func ServiceNetwork(service *apiv1.Service, networkLister, gkeNetworkParamSetLister cache.Indexer, cloudProvider cloudNetworkProvider) (*NetworkInfo, error) {
if networkLister == nil || gkeNetworkParamSetLister == nil {
return nil, nil
}
networkName, ok := service.Spec.Selector[networkSelector]
if !ok || networkName == "" {
return nil, nil
}
obj, exists, err := networkLister.GetByKey(networkName)
if err != nil {
return nil, err
}
if !exists {
return nil, fmt.Errorf("network %s does not exist, networks available [%s]", networkName, strings.Join(networkLister.ListKeys(), ", "))
}
network := obj.(*networkv1.Network)
if network == nil {
return nil, fmt.Errorf("cannot convert to Network (%T)", obj)
}

parametersRef := network.Spec.ParametersRef
if !refersGKENetworkParamSet(parametersRef) {
return nil, fmt.Errorf("network.Spec.ParametersRef does not refer a GKENetworkParamSet resource")
}
if parametersRef.Namespace != nil {
return nil, fmt.Errorf("network.Spec.ParametersRef.namespace must not be set for GKENetworkParamSet reference as it is a cluster scope resource")
}
gkeParamsObj, exists, err := gkeNetworkParamSetLister.GetByKey(parametersRef.Name)
if err != nil {
return nil, err
}
if !exists {
return nil, fmt.Errorf("GKENetworkParamSet %s was not found", parametersRef.Name)
}
gkeNetworkParamSet := gkeParamsObj.(*gkenetworkparamsetv1alpha1.GKENetworkParamSet)
if network == nil {
return nil, fmt.Errorf("cannot convert to GKENetworkParamSet (%T)", gkeParamsObj)
}
return &NetworkInfo{
K8sNetwork: networkName,
VPC: gkeNetworkParamSet.Spec.VPC,
Subnetwork: gkeNetworkParamSet.Spec.VPCSubnet,
NetworkURL: networkURL(cloudProvider, gkeNetworkParamSet.Spec.VPC),
SubnetworkURL: subnetworkURL(cloudProvider, gkeNetworkParamSet.Spec.VPCSubnet),
}, nil
}

func refersGKENetworkParamSet(parametersRef *networkv1.NetworkParametersReference) bool {
return parametersRef != nil &&
parametersRef.Group == networkingGKEGroup &&
strings.ToLower(parametersRef.Kind) == gkeNetworkParamSetKind &&
parametersRef.Name != ""
}

type NetworkInfo struct {
IsDefault bool
// VPC is the VPC as specified in GKENetworkParamSet resource.
VPC string
// VPC is the VPCSubnet as specified in GKENetworkParamSet resource.
Subnetwork string
// K8sNetwork is the network name of the Network resource in the cluster.
K8sNetwork string
// NetworkURL is the GCE VPC URL (to be used in GCE LB resources).
NetworkURL string
// SubnetworkURL is the GCE subnetwork URL (to be used in GCE LB resources).
SubnetworkURL string
}

func networkURL(cloudProvider cloudNetworkProvider, vpc string) string {
key := meta.GlobalKey(vpc)
return cloud.SelfLink(meta.VersionGA, cloudProvider.NetworkProjectID(), "networks", key)
}

func subnetworkURL(cloudProvider cloudNetworkProvider, subnetwork string) string {
key := meta.RegionalKey(subnetwork, cloudProvider.Region())
return cloud.SelfLink(meta.VersionGA, cloudProvider.NetworkProjectID(), "subnetworks", key)
}

// IsConnectedToNetwork checks if the node is connected to the given network.
// It's based on the data from the 'networking.gke.io/north-interfaces' annotation.
func IsConnectedToNetwork(node *apiv1.Node, network string) bool {
return NodeIPForNetwork(node, network) != ""
}

// NodeIPForNetwork retrieves the IP of the interface of the node connected to the network.
// The addresses come from the 'networking.gke.io/north-interfaces' annotation.
func NodeIPForNetwork(node *apiv1.Node, network string) string {
northInterfacesAnnotation, ok := node.Annotations[networkv1.NorthInterfacesAnnotationKey]
if !ok || northInterfacesAnnotation == "" {
return ""
}
northInterfaces, err := networkv1.ParseNorthInterfacesAnnotation(northInterfacesAnnotation)
if err != nil {
return ""
}
for _, northInterface := range northInterfaces {
if northInterface.Network == network {
return northInterface.IpAddress
}
}
return ""
}

type cloudNetworkProvider interface {
NetworkProjectID() string
Region() string
}
Loading

0 comments on commit 14322fc

Please sign in to comment.