diff --git a/anthos-attached-clusters/kind/README.md b/anthos-attached-clusters/kind/README.md new file mode 100644 index 00000000..732629fb --- /dev/null +++ b/anthos-attached-clusters/kind/README.md @@ -0,0 +1,55 @@ +# Sandbox Example to Attach a [kind](https://kind.sigs.k8s.io/) Cluster using Terraform + +## Prerequisites +The sample is meant just to provide a local example for experimentation. It assumes an environment where [`kind`](https://kind.sigs.k8s.io/) is available and could otherwise be run on the command line, e.g. `kind create cluster`. + +## A note on providers + +The other examples and module limit dependancies to terraform core providers, but this example takes advantage of some community supplied [providers](provider.tf). They're widely used for their purpose, but please review and consider. + +## Usage + +1. Edit the values in the terraform.tfvars file to suit your needs. Descriptions for each variable + can be found in `variables.tf`. Additional optional features are also available and commented out + in the `google_container_attached_cluster` resource in `main.tf`. + + If you modify the cluster creation, ensure it meets + [Cluster Prerequisites](https://cloud.google.com/anthos/clusters/docs/multi-cloud/attached/eks/reference/cluster-prerequisites). +1. Initialize Terraform: + ```bash + terraform init + ``` +1. Create and apply the plan: + ```bash + terraform apply + ``` + Terraform may give a warning along the lines of `Warning: Content-Type is not recognized as a text type, got "application/jwk-set+json"` but this is ok and just a side effect of the `http` provider we're using and the content type the cluster returns for the `jwks` content. +1. The process should take about a few short minutes to complete. +1. Set some variables based on the terraform porjects values and use them to generate RBAC for the cluster and credentials to login: + ```bash + + PROJECT=$(echo google_container_attached_cluster.primary.project | terraform console | tr -d '"') + CLUSTER=$(echo google_container_attached_cluster.primary.name | terraform console | tr -d '"') + KUBECONFIG=$(echo kind_cluster.cluster.kubeconfig_path | terraform console | tr -d '"') + + # set this to whomever you'd like to grant access + PRINCIPAL=update.this@example.com + # set this whatever role you intend + ROLE=clusterrole/cluster-admin + + gcloud container fleet memberships generate-gateway-rbac --apply \ + --kubeconfig ${KUBECONFIG} --context=kind-${CLUSTER} \ + --project=${PROJECT} \ + --membership=${CLUSTER} \ + --role=${ROLE} \ + --users=${PRINCIPAL} + + gcloud container fleet memberships get-credentials ${CLUSTER} --project ${PROJECT} + + kubectl get ns + + ``` + This will allow you to access the cluster using kubectl as you would other GKE Enterprise clusters, regardless of location (ie in GCP, other clouds, or on prem). + + + diff --git a/anthos-attached-clusters/kind/main.tf b/anthos-attached-clusters/kind/main.tf new file mode 100644 index 00000000..f6ff55d6 --- /dev/null +++ b/anthos-attached-clusters/kind/main.tf @@ -0,0 +1,123 @@ +/** + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +// This is an example of how you might use the attached module with a local kind cluster + +locals { + cluster_name = "${var.name_prefix}-cluster" +} + +resource "kind_cluster" "cluster" { + name = local.cluster_name + node_image = var.kind_node_image + + kubeconfig_path = "${path.root}/.tmp/kube/${local.cluster_name}" + + wait_for_ready = true + + kind_config { + kind = "Cluster" + api_version = "kind.x-k8s.io/v1alpha4" + feature_gates = { + KubeletInUserNamespace : "true" + } + } +} + +provider "helm" { + alias = "bootstrap_installer" + kubernetes { + host = kind_cluster.cluster.endpoint + client_certificate = kind_cluster.cluster.client_certificate + client_key = kind_cluster.cluster.client_key + cluster_ca_certificate = kind_cluster.cluster.cluster_ca_certificate + } +} + +module "attached_install_manifest" { + source = "../modules/attached-install-manifest" + attached_cluster_name = local.cluster_name + attached_cluster_fleet_project = data.google_project.project.project_id + gcp_location = var.gcp_location + platform_version = var.platform_version + providers = { + helm = helm.bootstrap_installer + } + depends_on = [ + kind_cluster.cluster + ] +} + +data "google_project" "project" { + project_id = var.gcp_project_id +} + + + +module "oidc" { + source = "./oidc" + + endpoint = kind_cluster.cluster.endpoint + cluster_ca_certificate = kind_cluster.cluster.cluster_ca_certificate + client_certificate = kind_cluster.cluster.client_certificate + client_key = kind_cluster.cluster.client_key +} + + +resource "google_container_attached_cluster" "primary" { + name = local.cluster_name + project = data.google_project.project.project_id + location = var.gcp_location + description = "Kind attached cluster example" + distribution = "generic" + platform_version = var.platform_version + oidc_config { + issuer_url = module.oidc.issuer + jwks = module.oidc.jwks + } + fleet { + project = "projects/${data.google_project.project.number}" + } + + # Optional: + # logging_config { + # component_config { + # enable_components = ["SYSTEM_COMPONENTS", "WORKLOADS"] + # } + # } + + # Optional: + # monitoring_config { + # managed_prometheus_config { + # enabled = true + # } + # } + + # Optional: + # authorization { + # admin_users = ["user1@google.com", ] + # admin_groups = ["group1@example.com", "group2@example.com"] + # } + + depends_on = [ + module.attached_install_manifest + ] +} + + + + diff --git a/anthos-attached-clusters/kind/oidc/main.tf b/anthos-attached-clusters/kind/oidc/main.tf new file mode 100644 index 00000000..9e85a79b --- /dev/null +++ b/anthos-attached-clusters/kind/oidc/main.tf @@ -0,0 +1,50 @@ +/** + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// this is a local library to manage getting OIDC info from the cluster + +data "http" "issuer" { + + provider = http-full + + url = "${var.endpoint}/.well-known/openid-configuration" + request_headers = { + content-type = "application/json" + } + + ca = var.cluster_ca_certificate + client_crt = var.client_certificate + client_key = var.client_key +} + +locals { + issuer_json = jsondecode(data.http.issuer.response_body) +} + +data "http" "jwks" { + + provider = http-full + + url = local.issuer_json.jwks_uri + request_headers = { + content-type = "application/json" + } + + ca = var.cluster_ca_certificate + client_crt = var.client_certificate + client_key = var.client_key +} + diff --git a/anthos-attached-clusters/kind/oidc/outputs.tf b/anthos-attached-clusters/kind/oidc/outputs.tf new file mode 100644 index 00000000..29a14d2d --- /dev/null +++ b/anthos-attached-clusters/kind/oidc/outputs.tf @@ -0,0 +1,23 @@ +/** + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +output "issuer" { + value = local.issuer_json.issuer +} + +output "jwks" { + value = base64encode(data.http.jwks.response_body) +} diff --git a/anthos-attached-clusters/kind/oidc/providers.tf b/anthos-attached-clusters/kind/oidc/providers.tf new file mode 100644 index 00000000..726642e2 --- /dev/null +++ b/anthos-attached-clusters/kind/oidc/providers.tf @@ -0,0 +1,24 @@ +/** + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +terraform { + required_providers { + http-full = { + source = "salrashid123/http-full" + } + } +} + diff --git a/anthos-attached-clusters/kind/oidc/variables.tf b/anthos-attached-clusters/kind/oidc/variables.tf new file mode 100644 index 00000000..8605d4c4 --- /dev/null +++ b/anthos-attached-clusters/kind/oidc/variables.tf @@ -0,0 +1,34 @@ +/** + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +variable "endpoint" { + type = string +} + + +variable "cluster_ca_certificate" { + type = string +} + +variable "client_certificate" { + type = string +} + +variable "client_key" { + type = string +} + + diff --git a/anthos-attached-clusters/kind/provider.tf b/anthos-attached-clusters/kind/provider.tf new file mode 100644 index 00000000..0c161a4d --- /dev/null +++ b/anthos-attached-clusters/kind/provider.tf @@ -0,0 +1,24 @@ +/** + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +terraform { + required_providers { + kind = { + source = "tehcyx/kind" + } + } +} + diff --git a/anthos-attached-clusters/kind/variables.tf b/anthos-attached-clusters/kind/variables.tf new file mode 100644 index 00000000..c610a5fe --- /dev/null +++ b/anthos-attached-clusters/kind/variables.tf @@ -0,0 +1,47 @@ +/** + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +variable "name_prefix" { + description = "Common prefix to use for generating names" + type = string +} + +variable "gcp_project_id" { + description = "The GCP project id where the cluster will be registered" + type = string +} + +variable "gcp_location" { + description = "GCP location to create the attached resource in" + type = string + default = "us-west1" +} + +variable "platform_version" { + description = "Platform version of the attached cluster resource" + type = string + default = "1.28.0-gke.3" +} + + +variable "kind_node_image" { + description = "The image used for the kind cluster" + type = string + default = "kindest/node:v1.28.0" +} + + +