-
Notifications
You must be signed in to change notification settings - Fork 303
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Multi Network support in the NEG controller
- Loading branch information
Showing
40 changed files
with
2,256 additions
and
206 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
Oops, something went wrong.