Skip to content

Commit

Permalink
Changes to support IPv6 addresses on nodes
Browse files Browse the repository at this point in the history
These changes populate the Node object with the IPv6 address as well
as the IPv6 podCIDR. This is done only for clusters with stackType as
IPV4_IPV6
  • Loading branch information
Sudeep Modi committed Aug 20, 2021
1 parent 0cdff34 commit 5b7b4f2
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 9 deletions.
10 changes: 10 additions & 0 deletions providers/gce/gce.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,9 @@ type Cloud struct {
s *cloud.Service

metricsCollector loadbalancerMetricsCollector
// stackType indicates whether the cluster is a single stack IPv4, single
// stack IPv6 or a dual stack cluster
stackType string
}

// ConfigGlobal is the in memory representation of the gce.conf config data
Expand All @@ -180,6 +183,7 @@ type ConfigGlobal struct {
NetworkProjectID string `gcfg:"network-project-id"`
NetworkName string `gcfg:"network-name"`
SubnetworkName string `gcfg:"subnetwork-name"`
StackType string `gcfg:"stack-type"`
// DEPRECATED: Do not rely on this value as it may be incorrect.
// SecondaryRangeName is the name of the secondary range to allocate IP
// aliases. The secondary range must be present on the subnetwork the
Expand Down Expand Up @@ -235,6 +239,7 @@ type CloudConfig struct {
TokenSource oauth2.TokenSource
UseMetadataServer bool
AlphaFeatureGate *AlphaFeatureGate
StackType string
}

func init() {
Expand Down Expand Up @@ -392,6 +397,10 @@ func generateCloudConfig(configFile *ConfigFile) (cloudConfig *CloudConfig, err
cloudConfig.SecondaryRangeName = configFile.Global.SecondaryRangeName
}

if configFile != nil && configFile.Global.StackType != "" {
cloudConfig.StackType = configFile.Global.StackType
}

return cloudConfig, err
}

Expand Down Expand Up @@ -524,6 +533,7 @@ func CreateGCECloud(config *CloudConfig) (*Cloud, error) {
AlphaFeatureGate: config.AlphaFeatureGate,
nodeZones: map[string]sets.String{},
metricsCollector: newLoadBalancerMetrics(),
stackType: config.StackType,
}

gce.manager = &gceServiceManager{gce}
Expand Down
64 changes: 55 additions & 9 deletions providers/gce/gce_instances.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"time"

"cloud.google.com/go/compute/metadata"
computealpha "google.golang.org/api/compute/v0.alpha"
computebeta "google.golang.org/api/compute/v0.beta"
compute "google.golang.org/api/compute/v1"
"k8s.io/klog/v2"
Expand All @@ -44,6 +45,7 @@ import (
const (
defaultZone = ""
networkInterfaceIP = "instance/network-interfaces/%s/ip"
networkInterfaceIPV6 = "instance/network-interfaces/%s/ipv6s"
networkInterfaceAccessConfigs = "instance/network-interfaces/%s/access-configs"
networkInterfaceExternalIP = "instance/network-interfaces/%s/access-configs/%s/external-ip"
)
Expand Down Expand Up @@ -116,6 +118,27 @@ func (g *Cloud) NodeAddresses(ctx context.Context, nodeName types.NodeName) ([]v
}
nodeAddresses = append(nodeAddresses, v1.NodeAddress{Type: v1.NodeInternalIP, Address: internalIP})

if g.stackType == "IPV4_IPV6" {
// Handling only the internal v6 address. External v6 addresses will be handled once vendor apis are updated.
internalIPV6s, err := metadata.Get(fmt.Sprintf(networkInterfaceIPV6, nic))
if err != nil {
return nil, fmt.Errorf("couldn't get internal IPV6 addresses: %v", err)
}
internalIPV6Arr := strings.Split(internalIPV6s, "/\n")
var internalIPV6 string
for _, ip := range internalIPV6Arr {
if ip == "" {
continue
}
internalIPV6 = ip
break
}
if internalIPV6 != "" {
nodeAddresses = append(nodeAddresses, v1.NodeAddress{Type: v1.NodeInternalIP, Address: internalIPV6})
} else {
klog.Warningf("internal IPV6 range is empty")
}
}
acs, err := metadata.Get(fmt.Sprintf(networkInterfaceAccessConfigs, nic))
if err != nil {
return nil, fmt.Errorf("couldn't get access configs: %v", err)
Expand Down Expand Up @@ -159,12 +182,12 @@ func (g *Cloud) NodeAddresses(ctx context.Context, nodeName types.NodeName) ([]v
return nil, fmt.Errorf("couldn't get instance details: %v", err)
}

instance, err := g.c.Instances().Get(timeoutCtx, meta.ZonalKey(canonicalizeInstanceName(instanceObj.Name), instanceObj.Zone))
instance, err := g.c.AlphaInstances().Get(timeoutCtx, meta.ZonalKey(canonicalizeInstanceName(instanceObj.Name), instanceObj.Zone))
if err != nil {
return []v1.NodeAddress{}, fmt.Errorf("error while querying for instance: %v", err)
}

return nodeAddressesFromInstance(instance)
return g.nodeAddressesFromInstance(instance)
}

// NodeAddressesByProviderID will not be called from the node that is requesting this ID.
Expand All @@ -178,12 +201,12 @@ func (g *Cloud) NodeAddressesByProviderID(ctx context.Context, providerID string
return []v1.NodeAddress{}, err
}

instance, err := g.c.Instances().Get(timeoutCtx, meta.ZonalKey(canonicalizeInstanceName(name), zone))
instance, err := g.c.AlphaInstances().Get(timeoutCtx, meta.ZonalKey(canonicalizeInstanceName(name), zone))
if err != nil {
return []v1.NodeAddress{}, fmt.Errorf("error while querying for providerID %q: %v", providerID, err)
}

return nodeAddressesFromInstance(instance)
return g.nodeAddressesFromInstance(instance)
}

// instanceByProviderID returns the cloudprovider instance of the node
Expand Down Expand Up @@ -215,7 +238,7 @@ func (g *Cloud) InstanceShutdown(ctx context.Context, node *v1.Node) (bool, erro
return false, cloudprovider.NotImplemented
}

func nodeAddressesFromInstance(instance *compute.Instance) ([]v1.NodeAddress, error) {
func (g *Cloud) nodeAddressesFromInstance(instance *computealpha.Instance) ([]v1.NodeAddress, error) {
if len(instance.NetworkInterfaces) < 1 {
return nil, fmt.Errorf("could not find network interfaces for instanceID %q", instance.Id)
}
Expand All @@ -226,11 +249,27 @@ func nodeAddressesFromInstance(instance *compute.Instance) ([]v1.NodeAddress, er
for _, config := range nic.AccessConfigs {
nodeAddresses = append(nodeAddresses, v1.NodeAddress{Type: v1.NodeExternalIP, Address: config.NatIP})
}
if g.stackType == "IPV4_IPV6" {
ipv6Addr := getIPV6AddressFromInterface(nic)
if ipv6Addr != "" {
nodeAddresses = append(nodeAddresses, v1.NodeAddress{Type: v1.NodeInternalIP, Address: ipv6Addr})
}
}
}

return nodeAddresses, nil
}

func getIPV6AddressFromInterface(nic *computealpha.NetworkInterface) string {
ipv6Addr := nic.Ipv6Address
if ipv6Addr == "" && nic.Ipv6AccessType == "EXTERNAL" {
for _, r := range nic.Ipv6AccessConfigs {
ipv6Addr = r.ExternalIpv6
}
}
return ipv6Addr
}

// InstanceTypeByProviderID returns the cloudprovider instance type of the node
// with the specified unique providerID This method will not be called from the
// node that is requesting this ID. i.e. metadata service and other local
Expand Down Expand Up @@ -297,12 +336,12 @@ func (g *Cloud) InstanceMetadata(ctx context.Context, node *v1.Node) (*cloudprov
return nil, err
}

instance, err := g.c.Instances().Get(timeoutCtx, meta.ZonalKey(canonicalizeInstanceName(name), zone))
instance, err := g.c.AlphaInstances().Get(timeoutCtx, meta.ZonalKey(canonicalizeInstanceName(name), zone))
if err != nil {
return nil, fmt.Errorf("error while querying for providerID %q: %v", providerID, err)
}

addresses, err := nodeAddressesFromInstance(instance)
addresses, err := g.nodeAddressesFromInstance(instance)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -501,15 +540,22 @@ func (g *Cloud) AliasRangesByProviderID(providerID string) (cidrs []string, err
return nil, err
}

var res *computebeta.Instance
res, err = g.c.BetaInstances().Get(ctx, meta.ZonalKey(canonicalizeInstanceName(name), zone))
var res *computealpha.Instance
res, err = g.c.AlphaInstances().Get(ctx, meta.ZonalKey(canonicalizeInstanceName(name), zone))
if err != nil {
return
}

for _, networkInterface := range res.NetworkInterfaces {
for _, r := range networkInterface.AliasIpRanges {
cidrs = append(cidrs, r.IpCidrRange)
if g.stackType == "IPV4_IPV6" {
ipv6Addr := getIPV6AddressFromInterface(networkInterface)
// The podCIDR range is the first /112 subrange from the /96 assigned to
// the node
ipv6PodCIDR := fmt.Sprintf("%s/112", ipv6Addr)
cidrs = append(cidrs, ipv6PodCIDR)
}
}
}
return
Expand Down

0 comments on commit 5b7b4f2

Please sign in to comment.