-
Notifications
You must be signed in to change notification settings - Fork 67
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Kubernetes on GCP templates (#394)
* Add Kubernetes on GCP templates Add templates to stand up Kubernetes on GCP (GKE) in Go, Python, TypeScript, and YAML Signed-off-by: Scott Lowe <[email protected]> * Update Kubernetes on GCP templates Remove hard-coded names to allow dynamic naming to take place. Removed references to GCP project to allow provider configuration to handle it. Removed references to region or location where possible. Improved comments in the code. Signed-off-by: Scott Lowe <[email protected]> * Update Kubernetes on GCP templates Incorporate feedback from code reviewers. Signed-off-by: Scott Lowe <[email protected]> * Fix Python formatting Address PEP8 formatting issues in Python template Signed-off-by: Scott Lowe <[email protected]> * Update YAML to treat Kubeconfig as a secret For consistency with the behavior of other languages, update YAML to treat Kubeconfig output as a secret Signed-off-by: Scott Lowe <[email protected]> * Add Kubernetes on GCP templates Add templates to stand up Kubernetes on GCP (GKE) in Go, Python, TypeScript, and YAML Signed-off-by: Scott Lowe <[email protected]> * Update Kubernetes on GCP templates Remove hard-coded names to allow dynamic naming to take place. Removed references to GCP project to allow provider configuration to handle it. Removed references to region or location where possible. Improved comments in the code. Signed-off-by: Scott Lowe <[email protected]> * Update Kubernetes on GCP templates Incorporate feedback from code reviewers. Signed-off-by: Scott Lowe <[email protected]> * Fix Python formatting Address PEP8 formatting issues in Python template Signed-off-by: Scott Lowe <[email protected]> * Update YAML to treat Kubeconfig as a secret For consistency with the behavior of other languages, update YAML to treat Kubeconfig output as a secret Signed-off-by: Scott Lowe <[email protected]> Signed-off-by: Scott Lowe <[email protected]> Co-authored-by: Christian Nunciato <[email protected]>
- Loading branch information
1 parent
c1860f9
commit 2facf87
Showing
14 changed files
with
715 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
name: ${PROJECT} | ||
description: ${DESCRIPTION} | ||
runtime: go | ||
template: | ||
description: A Go program to create a Kubernetes cluster on Google Cloud | ||
config: | ||
gcp:project: | ||
description: The Google Cloud project to deploy into | ||
gcp:region: | ||
default: us-central1 | ||
description: The Google Cloud region to deploy into | ||
nodesPerZone: | ||
default: 1 | ||
description: The desired number of nodes PER ZONE in the nodepool |
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,8 @@ | ||
module tmp | ||
|
||
go 1.17 | ||
|
||
require ( | ||
github.com/pulumi/pulumi/sdk/v3 v3.30.0 | ||
github.com/pulumi/pulumi-gcp/sdk/v6 v6.39.0 | ||
) |
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,152 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/pulumi/pulumi-gcp/sdk/v6/go/gcp/compute" | ||
"github.com/pulumi/pulumi-gcp/sdk/v6/go/gcp/container" | ||
"github.com/pulumi/pulumi-gcp/sdk/v6/go/gcp/serviceaccount" | ||
"github.com/pulumi/pulumi/sdk/v3/go/pulumi" | ||
"github.com/pulumi/pulumi/sdk/v3/go/pulumi/config" | ||
) | ||
|
||
func main() { | ||
pulumi.Run(func(ctx *pulumi.Context) error { | ||
// Get some provider-namespaced configuration values | ||
providerCfg := config.New(ctx, "gcp") | ||
gcpProject := providerCfg.Require("project") | ||
gcpRegion, err := providerCfg.Try("region") | ||
if err != nil { | ||
gcpRegion = "us-central1" | ||
} | ||
// Get some additional configuration values or use defaults | ||
cfg := config.New(ctx, "") | ||
nodesPerZone, err := cfg.TryInt("nodesPerZone") | ||
if err != nil { | ||
nodesPerZone = 1 | ||
} | ||
|
||
// Create a new network | ||
gkeNetwork, err := compute.NewNetwork(ctx, "gke-network", &compute.NetworkArgs{ | ||
AutoCreateSubnetworks: pulumi.Bool(false), | ||
Description: pulumi.String("A virtual network for your GKE cluster(s)"), | ||
}) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// Create a subnet in the network | ||
gkeSubnet, err := compute.NewSubnetwork(ctx, "gke-subnet", &compute.SubnetworkArgs{ | ||
IpCidrRange: pulumi.String("10.128.0.0/12"), | ||
Network: gkeNetwork.ID(), | ||
PrivateIpGoogleAccess: pulumi.Bool(true), | ||
}) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// Create a new GKE cluster | ||
gkeCluster, err := container.NewCluster(ctx, "gke-cluster", &container.ClusterArgs{ | ||
AddonsConfig: &container.ClusterAddonsConfigArgs{ | ||
DnsCacheConfig: &container.ClusterAddonsConfigDnsCacheConfigArgs{ | ||
Enabled: pulumi.Bool(true), | ||
}, | ||
}, | ||
BinaryAuthorization: &container.ClusterBinaryAuthorizationArgs{ | ||
EvaluationMode: pulumi.String("PROJECT_SINGLETON_POLICY_ENFORCE"), | ||
}, | ||
DatapathProvider: pulumi.String("ADVANCED_DATAPATH"), | ||
Description: pulumi.String("A GKE cluster"), | ||
InitialNodeCount: pulumi.Int(1), | ||
IpAllocationPolicy: &container.ClusterIpAllocationPolicyArgs{ | ||
ClusterIpv4CidrBlock: pulumi.String("/14"), | ||
ServicesIpv4CidrBlock: pulumi.String("/20"), | ||
}, | ||
Location: pulumi.String(gcpRegion), | ||
MasterAuthorizedNetworksConfig: &container.ClusterMasterAuthorizedNetworksConfigArgs{ | ||
CidrBlocks: container.ClusterMasterAuthorizedNetworksConfigCidrBlockArray{ | ||
&container.ClusterMasterAuthorizedNetworksConfigCidrBlockArgs{ | ||
CidrBlock: pulumi.String("0.0.0.0/0"), | ||
DisplayName: pulumi.String("All networks"), | ||
}, | ||
}, | ||
}, | ||
Network: gkeNetwork.Name, | ||
NetworkingMode: pulumi.String("VPC_NATIVE"), | ||
PrivateClusterConfig: &container.ClusterPrivateClusterConfigArgs{ | ||
EnablePrivateNodes: pulumi.Bool(true), | ||
EnablePrivateEndpoint: pulumi.Bool(false), | ||
MasterIpv4CidrBlock: pulumi.String("10.100.0.0/28"), | ||
}, | ||
RemoveDefaultNodePool: pulumi.Bool(true), | ||
ReleaseChannel: &container.ClusterReleaseChannelArgs{ | ||
Channel: pulumi.String("STABLE"), | ||
}, | ||
Subnetwork: gkeSubnet.Name, | ||
WorkloadIdentityConfig: &container.ClusterWorkloadIdentityConfigArgs{ | ||
WorkloadPool: pulumi.String(fmt.Sprintf("%v.svc.id.goog", gcpProject)), | ||
}, | ||
}) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// Create a GCP Service Account for the node pool | ||
gkeNodepoolSa, err := serviceaccount.NewAccount(ctx, "gke-nodepool-sa", &serviceaccount.AccountArgs{ | ||
AccountId: pulumi.Sprintf("%v-np-1-sa", gkeCluster.Name), | ||
DisplayName: pulumi.String("Nodepool 1 Service Account"), | ||
}) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// Create a new node pool | ||
_, err = container.NewNodePool(ctx, "gke-nodepool", &container.NodePoolArgs{ | ||
Cluster: gkeCluster.ID(), | ||
NodeCount: pulumi.Int(nodesPerZone), | ||
NodeConfig: &container.NodePoolNodeConfigArgs{ | ||
OauthScopes: pulumi.StringArray{ | ||
pulumi.String("https://www.googleapis.com/auth/cloud-platform"), | ||
}, | ||
ServiceAccount: gkeNodepoolSa.Email, | ||
}, | ||
}) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// Build Kubeconfig for accessing the cluster | ||
clusterKubeconfig := pulumi.Sprintf(`apiVersion: v1 | ||
clusters: | ||
- cluster: | ||
certificate-authority-data: %[3]s | ||
server: https://%[2]s | ||
name: %[1]s | ||
contexts: | ||
- context: | ||
cluster: %[1]s | ||
user: %[1]s | ||
name: %[1]s | ||
current-context: %[1]s | ||
kind: Config | ||
preferences: {} | ||
users: | ||
- name: %[1]s | ||
user: | ||
exec: | ||
apiVersion: client.authentication.k8s.io/v1beta1 | ||
command: gke-gcloud-auth-plugin | ||
installHint: Install gke-gcloud-auth-plugin for use with kubectl by following | ||
https://cloud.google.com/blog/products/containers-kubernetes/kubectl-auth-changes-in-gke | ||
provideClusterInfo: true | ||
`, gkeCluster.Name, gkeCluster.Endpoint, gkeCluster.MasterAuth.ClusterCaCertificate().Elem()) | ||
|
||
// Export some values for use elsewhere | ||
ctx.Export("networkName", gkeNetwork.Name) | ||
ctx.Export("networkId", gkeNetwork.ID()) | ||
ctx.Export("clusterName", gkeCluster.Name) | ||
ctx.Export("clusterId", gkeCluster.ID()) | ||
ctx.Export("kubeconfig", clusterKubeconfig) | ||
return nil | ||
}) | ||
} |
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,2 @@ | ||
*.pyc | ||
venv/ |
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,14 @@ | ||
name: ${PROJECT} | ||
description: ${DESCRIPTION} | ||
runtime: python | ||
template: | ||
description: A Python program to create a Kubernetes cluster on Google Cloud | ||
config: | ||
gcp:project: | ||
description: The Google Cloud project to deploy into | ||
gcp:region: | ||
default: us-central1 | ||
description: The Google Cloud region to deploy into | ||
nodesPerZone: | ||
default: 1 | ||
description: The desired number of nodes PER ZONE in the nodepool |
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,122 @@ | ||
import pulumi | ||
import pulumi_gcp as gcp | ||
|
||
# Get some provider-namespaced configuration values | ||
provider_cfg = pulumi.Config("gcp") | ||
gcp_project = provider_cfg.require("project") | ||
gcp_region = provider_cfg.get("region", "us-central1") | ||
# Get some additional configuration values | ||
config = pulumi.Config() | ||
nodes_per_zone = config.get_float("nodesPerZone", 1) | ||
|
||
# Create a new network | ||
gke_network = gcp.compute.Network( | ||
"gke-network", | ||
auto_create_subnetworks=False, | ||
description="A virtual network for your GKE cluster(s)" | ||
) | ||
|
||
# Create a subnet in the new network | ||
gke_subnet = gcp.compute.Subnetwork( | ||
"gke-subnet", | ||
ip_cidr_range="10.128.0.0/12", | ||
network=gke_network.id, | ||
private_ip_google_access=True | ||
) | ||
|
||
# Create a cluster in the new network and subnet | ||
gke_cluster = gcp.container.Cluster( | ||
"gke-cluster", | ||
addons_config=gcp.container.ClusterAddonsConfigArgs( | ||
dns_cache_config=gcp.container.ClusterAddonsConfigDnsCacheConfigArgs( | ||
enabled=True | ||
), | ||
), | ||
binary_authorization=gcp.container.ClusterBinaryAuthorizationArgs( | ||
evaluation_mode="PROJECT_SINGLETON_POLICY_ENFORCE" | ||
), | ||
datapath_provider="ADVANCED_DATAPATH", | ||
description="A GKE cluster", | ||
initial_node_count=1, | ||
ip_allocation_policy=gcp.container.ClusterIpAllocationPolicyArgs( | ||
cluster_ipv4_cidr_block="/14", | ||
services_ipv4_cidr_block="/20" | ||
), | ||
location=gcp_region, | ||
master_authorized_networks_config=gcp.container.ClusterMasterAuthorizedNetworksConfigArgs( | ||
cidr_blocks=[gcp.container.ClusterMasterAuthorizedNetworksConfigCidrBlockArgs( | ||
cidr_block="0.0.0.0/0", | ||
display_name="All networks" | ||
)] | ||
), | ||
network=gke_network.name, | ||
networking_mode="VPC_NATIVE", | ||
private_cluster_config=gcp.container.ClusterPrivateClusterConfigArgs( | ||
enable_private_nodes=True, | ||
enable_private_endpoint=False, | ||
master_ipv4_cidr_block="10.100.0.0/28" | ||
), | ||
remove_default_node_pool=True, | ||
release_channel=gcp.container.ClusterReleaseChannelArgs( | ||
channel="STABLE" | ||
), | ||
subnetwork=gke_subnet.name, | ||
workload_identity_config=gcp.container.ClusterWorkloadIdentityConfigArgs( | ||
workload_pool=f"{gcp_project}.svc.id.goog" | ||
) | ||
) | ||
|
||
# Create a GCP service account for the nodepool | ||
gke_nodepool_sa = gcp.serviceaccount.Account( | ||
"gke-nodepool-sa", | ||
account_id=pulumi.Output.concat(gke_cluster.name, "-np-1-sa"), | ||
display_name="Nodepool 1 Service Account" | ||
) | ||
|
||
# Create a nodepool for the cluster | ||
gke_nodepool = gcp.container.NodePool( | ||
"gke-nodepool", | ||
cluster=gke_cluster.id, | ||
node_count=nodes_per_zone, | ||
node_config=gcp.container.NodePoolNodeConfigArgs( | ||
oauth_scopes=["https://www.googleapis.com/auth/cloud-platform"], | ||
service_account=gke_nodepool_sa.email | ||
) | ||
) | ||
|
||
# Build a Kubeconfig to access the cluster | ||
cluster_kubeconfig = pulumi.Output.all( | ||
gke_cluster.master_auth.cluster_ca_certificate, | ||
gke_cluster.endpoint, | ||
gke_cluster.name).apply(lambda l: | ||
f"""apiVersion: v1 | ||
clusters: | ||
- cluster: | ||
certificate-authority-data: {l[0]} | ||
server: https://{l[1]} | ||
name: {l[2]} | ||
contexts: | ||
- context: | ||
cluster: {l[2]} | ||
user: {l[2]} | ||
name: {l[2]} | ||
current-context: {l[2]} | ||
kind: Config | ||
preferences: {{}} | ||
users: | ||
- name: {l[2]} | ||
user: | ||
exec: | ||
apiVersion: client.authentication.k8s.io/v1beta1 | ||
command: gke-gcloud-auth-plugin | ||
installHint: Install gke-gcloud-auth-plugin for use with kubectl by following | ||
https://cloud.google.com/blog/products/containers-kubernetes/kubectl-auth-changes-in-gke | ||
provideClusterInfo: true | ||
""") | ||
|
||
# Export some values for use elsewhere | ||
pulumi.export("networkName", gke_network.name) | ||
pulumi.export("networkId", gke_network.id) | ||
pulumi.export("clusterName", gke_cluster.name) | ||
pulumi.export("clusterId", gke_cluster.id) | ||
pulumi.export("kubeconfig", cluster_kubeconfig) |
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,2 @@ | ||
pulumi>=3.0.0,<4.0.0 | ||
pulumi-gcp==6.39.0 |
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,2 @@ | ||
/bin/ | ||
/node_modules/ |
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,14 @@ | ||
name: ${PROJECT} | ||
description: ${DESCRIPTION} | ||
runtime: nodejs | ||
template: | ||
description: A TypeScript program to create a Kubernetes cluster on Google Cloud | ||
config: | ||
gcp:project: | ||
description: The Google Cloud project to deploy into | ||
gcp:region: | ||
default: us-central1 | ||
description: The Google Cloud region to deploy into | ||
nodesPerZone: | ||
default: 1 | ||
description: The desired number of nodes PER ZONE in the nodepool |
Oops, something went wrong.