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

gke deployer supports creating GKE Autopilot clusters #129

Merged
merged 1 commit into from
Apr 23, 2021
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
26 changes: 19 additions & 7 deletions kubetest2-gke/deployer/deployer.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,8 @@ import (
const Name = "gke"

const (
e2eAllow = "tcp:22,tcp:80,tcp:8080,tcp:30000-32767,udp:30000-32767"
defaultCreate = "container clusters create --quiet"
image = "cos"
e2eAllow = "tcp:22,tcp:80,tcp:8080,tcp:30000-32767,udp:30000-32767"
defaultImage = "cos"
)

type privateClusterAccessLevel string
Expand All @@ -52,12 +51,14 @@ const (
)

var (
// poolRe matches instance group URLs of the form `https://www.googleapis.com/compute/v1/projects/some-project/zones/a-zone/instanceGroupManagers/gke-some-cluster-some-pool-90fcb815-grp`. Match meaning:
// poolRe matches instance group URLs of the form `https://www.googleapis.com/compute/v1/projects/some-project/zones/a-zone/instanceGroupManagers/gke-some-cluster-some-pool-90fcb815-grp`
// or `https://www.googleapis.com/compute/v1/projects/some-project/zones/a-zone/instanceGroupManagers/gk3-some-cluster-some-pool-90fcb815-grp` for GKE in Autopilot mode.
// Match meaning:
// m[0]: path starting with zones/
// m[1]: zone
// m[2]: pool name (passed to e2es)
// m[3]: unique hash (used as nonce for firewall rules)
poolRe = regexp.MustCompile(`zones/([^/]+)/instanceGroupManagers/(gke-.*-([0-9a-f]{8})-grp)$`)
poolRe = regexp.MustCompile(`zones/([^/]+)/instanceGroupManagers/(gk[e|3]-.*-([0-9a-f]{8})-grp)$`)

urlRe = regexp.MustCompile(`https://.*/`)
defaultNodePool = gkeNodePool{
Expand Down Expand Up @@ -106,12 +107,17 @@ type deployer struct {
projectClustersLayout map[string][]cluster
nodes int
machineType string
imageType string
network string
subnetworkRanges []string
environment string
createCommandFlag string
gcpServiceAccount string

gcloudCommandGroup string
autopilot bool
gcloudExtraFlags string
createCommandFlag string

kubecfgPath string
testPrepared bool
// project -> cluster -> instance groups
Expand Down Expand Up @@ -209,9 +215,14 @@ func bindFlags(d *deployer) *pflag.FlagSet {
klog.Fatalf("unable to generate flags from deployer")
return nil
}

flags.StringVar(&d.gcloudCommandGroup, "gcloud-command-group", "", "gcloud command group, can be one of empty, alpha, beta")
flags.BoolVar(&d.autopilot, "autopilot", false, "Whether to create GKE Autopilot clusters or not")
flags.StringVar(&d.gcloudExtraFlags, "gcloud-extra-flags", "", "Extra gcloud flags to pass when creating the clusters")
flags.StringVar(&d.createCommandFlag, "create-command", "", "gcloud subcommand and additional flags used to create a cluster, such as `container clusters create --quiet`."+
"If it's specified, --gcloud-command-group, --autopilot, --gcloud-extra-flags will be ignored.")
flags.StringSliceVar(&d.clusters, "cluster-name", []string{}, "Cluster names separated by comma. Must be set. "+
"For multi-project profile, it should be in the format of clusterA:0,clusterB:1,clusterC:2, where the index means the index of the project.")
flags.StringVar(&d.createCommandFlag, "create-command", defaultCreate, "gcloud subcommand used to create a cluster. Modify if you need to pass arbitrary arguments to create.")
flags.StringVar(&d.gcpServiceAccount, "gcp-service-account", "", "Service account to activate before using gcloud")
flags.StringVar(&d.network, "network", "default", "Cluster network. Defaults to the default network if not provided. For multi-project use cases, this will be the Shared VPC network name.")
flags.StringSliceVar(&d.subnetworkRanges, "subnetwork-ranges", []string{}, "Subnetwork ranges as required for shared VPC setup as described in https://cloud.google.com/kubernetes-engine/docs/how-to/cluster-shared-vpc#creating_a_network_and_two_subnets."+
Expand All @@ -223,6 +234,7 @@ func bindFlags(d *deployer) *pflag.FlagSet {
flags.StringVar(&d.zone, "zone", "", "For use with gcloud commands to specify the cluster zone.")
flags.IntVar(&d.nodes, "num-nodes", defaultNodePool.Nodes, "For use with gcloud commands to specify the number of nodes for the cluster.")
flags.StringVar(&d.machineType, "machine-type", defaultNodePool.MachineType, "For use with gcloud commands to specify the machine type for the cluster.")
flags.StringVar(&d.imageType, "image-type", defaultImage, "The image type to use for the cluster.")
flags.BoolVar(&d.gcpSSHKeyIgnored, "ignore-gcp-ssh-key", true, "Whether the GCP SSH key should be ignored or not for bringing up the cluster.")
flags.BoolVar(&d.workloadIdentityEnabled, "enable-workload-identity", false, "Whether enable workload identity for the cluster or not.")
flags.StringVar(&d.privateClusterAccessLevel, "private-cluster-access-level", "", "Private cluster access level, if not empty, must be one of 'no', 'limited' or 'unrestricted'")
Expand Down
10 changes: 7 additions & 3 deletions kubetest2-gke/deployer/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ func transformNetworkName(projects []string, network string) string {

// Returns the sub network args needed for the cluster creation command.
// Reference: https://cloud.google.com/kubernetes-engine/docs/how-to/cluster-shared-vpc#creating_a_cluster_in_your_first_service_project
func subNetworkArgs(projects []string, region, network string, projectIndex int) []string {
func subNetworkArgs(autopilot bool, projects []string, region, network string, projectIndex int) []string {
// No sub network args need to be added for creating clusters in the host project.
if projectIndex == 0 {
return []string{}
Expand All @@ -179,12 +179,16 @@ func subNetworkArgs(projects []string, region, network string, projectIndex int)
hostProject := projects[0]
curtProject := projects[projectIndex]
subnetName := network + "-" + curtProject
return []string{
"--enable-ip-alias",
args := []string{
fmt.Sprintf("--subnetwork=projects/%s/regions/%s/subnetworks/%s", hostProject, region, subnetName),
fmt.Sprintf("--cluster-secondary-range-name=%s-pods", subnetName),
fmt.Sprintf("--services-secondary-range-name=%s-services", subnetName),
}
// GKE in Autopilot mode does not support --enable-ip-alias flag - https://cloud.google.com/sdk/gcloud/reference/container/clusters/create-auto
if !autopilot {
args = append(args, "--enable-ip-alias")
}
return args
}

func (d *deployer) setupNetwork() error {
Expand Down
35 changes: 28 additions & 7 deletions kubetest2-gke/deployer/up.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,22 +67,26 @@ func (d *deployer) Up() error {
loc := location(d.region, d.zone)
for i := range d.projects {
project := d.projects[i]
subNetworkArgs := subNetworkArgs(d.projects, d.region, d.network, i)
subNetworkArgs := subNetworkArgs(d.autopilot, d.projects, d.region, d.network, i)
for j := range d.projectClustersLayout[project] {
cluster := d.projectClustersLayout[project][j]
privateClusterArgs := privateClusterArgs(d.projects, d.network, d.privateClusterAccessLevel, d.privateClusterMasterIPRanges, cluster)
eg.Go(func() error {
// Create the cluster
args := make([]string, len(d.createCommand()))
copy(args, d.createCommand())
args := d.createCommand()
args = append(args,
"--project="+project,
loc,
"--machine-type="+d.machineType,
"--image-type="+image,
"--num-nodes="+strconv.Itoa(d.nodes),
"--network="+transformNetworkName(d.projects, d.network),
)
// A few args are not supported in GKE Autopilot cluster creation, so they should be left unset.
// https://cloud.google.com/sdk/gcloud/reference/container/clusters/create-auto
if !d.autopilot {
args = append(args, "--machine-type="+d.machineType)
args = append(args, "--num-nodes="+strconv.Itoa(d.nodes))
args = append(args, "--image-type="+d.imageType)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be worth refactoring all the argument builder logic somewhere as a follow up.


if d.workloadIdentityEnabled {
args = append(args, fmt.Sprintf("--workload-pool=%s.svc.id.goog", project))
}
Expand Down Expand Up @@ -127,7 +131,24 @@ func (d *deployer) Up() error {
}

func (d *deployer) createCommand() []string {
return strings.Fields(d.createCommandFlag)
// Use the --create-command flag if it's explicitly specified.
if d.createCommandFlag != "" {
return strings.Fields(d.createCommandFlag)
}

fs := make([]string, 0)
if d.gcloudCommandGroup != "" {
fs = append(fs, d.gcloudCommandGroup)
}
fs = append(fs, "container", "clusters")
if d.autopilot {
fs = append(fs, "create-auto")
} else {
fs = append(fs, "create")
}
fs = append(fs, "--quiet")
fs = append(fs, strings.Fields(d.gcloudExtraFlags)...)
return fs
}

func (d *deployer) IsUp() (up bool, err error) {
Expand Down