Skip to content

Commit

Permalink
Add Kubernetes on GCP templates (#394)
Browse files Browse the repository at this point in the history
* 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
scottslowe and cnunciato authored Oct 19, 2022
1 parent c1860f9 commit 2facf87
Show file tree
Hide file tree
Showing 14 changed files with 715 additions and 0 deletions.
14 changes: 14 additions & 0 deletions kubernetes-gcp-go/Pulumi.yaml
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
8 changes: 8 additions & 0 deletions kubernetes-gcp-go/go.mod
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
)
152 changes: 152 additions & 0 deletions kubernetes-gcp-go/main.go
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
})
}
2 changes: 2 additions & 0 deletions kubernetes-gcp-python/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.pyc
venv/
14 changes: 14 additions & 0 deletions kubernetes-gcp-python/Pulumi.yaml
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
122 changes: 122 additions & 0 deletions kubernetes-gcp-python/__main__.py
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)
2 changes: 2 additions & 0 deletions kubernetes-gcp-python/requirements.txt
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
2 changes: 2 additions & 0 deletions kubernetes-gcp-typescript/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/bin/
/node_modules/
14 changes: 14 additions & 0 deletions kubernetes-gcp-typescript/Pulumi.yaml
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
Loading

0 comments on commit 2facf87

Please sign in to comment.