diff --git a/cluster/gce/container-linux/configure-helper.sh b/cluster/gce/container-linux/configure-helper.sh index 1e98e2a764c..7263677fcdf 100755 --- a/cluster/gce/container-linux/configure-helper.sh +++ b/cluster/gce/container-linux/configure-helper.sh @@ -184,6 +184,11 @@ token-body = ${TOKEN_BODY} project-id = ${PROJECT_ID} network-name = ${NODE_NETWORK} EOF + if [[ -n "${NODE_SUBNETWORK:-}" ]]; then + cat <>/etc/gce.conf +subnetwork-name = ${NODE_SUBNETWORK} +EOF + fi fi if [[ -n "${NODE_INSTANCE_PREFIX:-}" ]]; then use_cloud_config="true" diff --git a/cluster/gce/gci/configure-helper.sh b/cluster/gce/gci/configure-helper.sh index 261229486ab..e6d2ef7b94c 100644 --- a/cluster/gce/gci/configure-helper.sh +++ b/cluster/gce/gci/configure-helper.sh @@ -326,6 +326,11 @@ token-body = ${TOKEN_BODY} project-id = ${PROJECT_ID} network-name = ${NODE_NETWORK} EOF + if [[ -n "${NODE_SUBNETWORK:-}" ]]; then + cat <>/etc/gce.conf +subnetwork-name = ${NODE_SUBNETWORK} +EOF + fi fi if [[ -n "${NODE_INSTANCE_PREFIX:-}" ]]; then use_cloud_config="true" diff --git a/pkg/cloudprovider/providers/gce/gce.go b/pkg/cloudprovider/providers/gce/gce.go index 1200fdc8d60..64004fa9440 100644 --- a/pkg/cloudprovider/providers/gce/gce.go +++ b/pkg/cloudprovider/providers/gce/gce.go @@ -86,6 +86,7 @@ type GCECloud struct { localZone string // The zone in which we are running managedZones []string // List of zones we are spanning (for multi-AZ clusters, primarily when running on master) networkURL string + subnetworkURL string nodeTags []string // List of tags to use on firewall rules for load balancers nodeInstancePrefix string // If non-"", an advisory prefix for all nodes in the cluster useMetadataServer bool @@ -98,6 +99,7 @@ type Config struct { TokenBody string `gcfg:"token-body"` ProjectID string `gcfg:"project-id"` NetworkName string `gcfg:"network-name"` + SubnetworkName string `gcfg:"subnetwork-name"` NodeTags []string `gcfg:"node-tags"` NodeInstancePrefix string `gcfg:"node-instance-prefix"` Multizone bool `gcfg:"multizone"` @@ -134,6 +136,7 @@ func newGCECloud(config io.Reader) (*GCECloud, error) { return nil, err } networkURL := gceNetworkURL(projectID, networkName) + subnetworkURL := "" // By default, Kubernetes clusters only run against one zone managedZones := []string{zone} @@ -158,6 +161,13 @@ func newGCECloud(config io.Reader) (*GCECloud, error) { networkURL = gceNetworkURL(cfg.Global.ProjectID, cfg.Global.NetworkName) } } + if cfg.Global.SubnetworkName != "" { + if strings.Contains(cfg.Global.SubnetworkName, "/") { + subnetworkURL = cfg.Global.SubnetworkName + } else { + subnetworkURL = gceSubnetworkURL(cfg.Global.ProjectID, region, cfg.Global.SubnetworkName) + } + } if cfg.Global.TokenURL != "" { tokenSource = NewAltTokenSource(cfg.Global.TokenURL, cfg.Global.TokenBody) } @@ -168,15 +178,15 @@ func newGCECloud(config io.Reader) (*GCECloud, error) { } } - return CreateGCECloud(projectID, region, zone, managedZones, networkURL, nodeTags, - nodeInstancePrefix, tokenSource, true /* useMetadataServer */) + return CreateGCECloud(projectID, region, zone, managedZones, networkURL, subnetworkURL, + nodeTags, nodeInstancePrefix, tokenSource, true /* useMetadataServer */) } // Creates a GCECloud object using the specified parameters. // If no networkUrl is specified, loads networkName via rest call. // If no tokenSource is specified, uses oauth2.DefaultTokenSource. // If managedZones is nil / empty all zones in the region will be managed. -func CreateGCECloud(projectID, region, zone string, managedZones []string, networkURL string, nodeTags []string, +func CreateGCECloud(projectID, region, zone string, managedZones []string, networkURL, subnetworkURL string, nodeTags []string, nodeInstancePrefix string, tokenSource oauth2.TokenSource, useMetadataServer bool) (*GCECloud, error) { client, err := newOauthClient(tokenSource) @@ -229,6 +239,7 @@ func CreateGCECloud(projectID, region, zone string, managedZones []string, netwo localZone: zone, managedZones: managedZones, networkURL: networkURL, + subnetworkURL: subnetworkURL, nodeTags: nodeTags, nodeInstancePrefix: nodeInstancePrefix, useMetadataServer: useMetadataServer, @@ -293,6 +304,10 @@ func gceNetworkURL(project, network string) string { return fmt.Sprintf("https://www.googleapis.com/compute/v1/projects/%s/global/networks/%s", project, network) } +func gceSubnetworkURL(project, region, subnetwork string) string { + return fmt.Sprintf("https://www.googleapis.com/compute/v1/projects/%s/regions/%s/subnetworks/%s", project, region, subnetwork) +} + func getNetworkNameViaMetadata() (string, error) { result, err := metadata.Get("instance/network-interfaces/0/network") if err != nil { diff --git a/test/e2e/e2e.go b/test/e2e/e2e.go index 5df6943cea6..37b76c85ae4 100644 --- a/test/e2e/e2e.go +++ b/test/e2e/e2e.go @@ -77,7 +77,9 @@ func setupProviderConfig() error { if !framework.TestContext.CloudConfig.MultiZone { managedZones = []string{zone} } - cloudConfig.Provider, err = gcecloud.CreateGCECloud(framework.TestContext.CloudConfig.ProjectID, region, zone, managedZones, "" /* networkUrl */, nil /* nodeTags */, "" /* nodeInstancePerfix */, nil /* tokenSource */, false /* useMetadataServer */) + cloudConfig.Provider, err = gcecloud.CreateGCECloud(framework.TestContext.CloudConfig.ProjectID, + region, zone, managedZones, "" /* networkUrl */, "" /* subnetworkUrl */, nil, /* nodeTags */ + "" /* nodeInstancePerfix */, nil /* tokenSource */, false /* useMetadataServer */) if err != nil { return fmt.Errorf("Error building GCE/GKE provider: %v", err) }