Skip to content
This repository has been archived by the owner on Nov 2, 2024. It is now read-only.

Commit

Permalink
feat: convert Terraform configuration from plain files to modules (#1054
Browse files Browse the repository at this point in the history
)

Replace 'loging' with 'login' in tutorial and README instructions and adds "create" command in markdown. (#1047)
Fixes errors (#1045) and refactors use of kustomize path in CLI.
Makes GKE+ASM provisioning a module.
Makes Online Boutique provisioning a module.
Creates a new 'main.tf' TF configuration to provision modules sequentially, because of the hard dependency there is no effective way to paralelize it.
Refactors "online-boutique" to replace with "microservices-demo".
  • Loading branch information
minherz committed Nov 25, 2023
1 parent 6153eae commit bb68acb
Show file tree
Hide file tree
Showing 23 changed files with 234 additions and 105 deletions.
48 changes: 0 additions & 48 deletions provisioning/terraform/asm.tf

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,15 @@ resource "google_monitoring_slo" "service_latency" {
]
}

data "google_project" "info" {
project_id = var.gcp_project_id
}

module "slo_service" {
count = length(local.slo_services)
source = "./slo_service"

project_number = var.gcp_project_number
project_number = data.google_project.info.number
name = local.slo_services[count.index].id
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,6 @@ variable "gcp_project_id" {
description = "The GCP project ID to apply this config to"
}

variable "gcp_project_number" {
type = string
description = "The GCP project number to apply this config to"
}

variable "enable_asm" {
type = bool
description = "Flags to provision ASM related resources"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ locals {
resource_labels = var.enable_asm ? { "mesh_id" = "proj-${data.google_project.info.number}" } : {}
}

data "google_project" "info" {
project_id = var.gcp_project_id
}

resource "google_container_cluster" "sandbox" {
name = var.gke_cluster_name
location = var.gke_cluster_location
Expand All @@ -35,7 +39,7 @@ resource "google_container_cluster" "sandbox" {

# Enables Workload Identity
workload_identity_config {
workload_pool = "${data.google_project.info.project_id}.svc.id.goog"
workload_pool = "${var.gcp_project_id}.svc.id.goog"
}

# Configures default node pool
Expand All @@ -61,10 +65,6 @@ resource "google_container_cluster" "sandbox" {
}
}
}

depends_on = [
module.enable_google_apis
]
}

module "gcloud" {
Expand All @@ -79,3 +79,37 @@ module "gcloud" {
# Use 'local.cluster_name' to enforce implicit dependency because 'depends_on' is not available for this module
create_cmd_body = "container clusters get-credentials ${resource.google_container_cluster.sandbox.name} ${local.location_label}=${resource.google_container_cluster.sandbox.location} --project=${var.gcp_project_id}"
}

resource "null_resource" "install_asm" {
count = var.enable_asm ? 1 : 0

triggers = {
project_id = var.gcp_project_id
cluster_name = google_container_cluster.sandbox.name
cluster_location = google_container_cluster.sandbox.location
}

provisioner "local-exec" {
interpreter = ["bash", "-exc"]
command = <<-EOT
${path.module}/scripts/install_asm.sh --project ${self.triggers.project_id} \
--channel ${var.asm_channel} \
--cluster_name ${self.triggers.cluster_name} \
--cluster_location ${self.triggers.cluster_location}
EOT
}

provisioner "local-exec" {
when = destroy
command = <<-EOT
gcloud container fleet memberships unregister ${self.triggers.cluster_name} \
--gke-cluster '${self.triggers.cluster_location}/${self.triggers.cluster_name}' \
--project=${self.triggers.project_id}
EOT
}

depends_on = [
resource.google_container_cluster.sandbox,
module.gcloud,
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.

module "monitoring" {
source = "./monitoring"
gcp_project_id = data.google_project.info.project_id
gcp_project_number = data.google_project.info.number
enable_asm = var.enable_asm
frontend_external_ip = data.kubernetes_service.frontend_external_service.status[0].load_balancer[0].ingress[0].ip
gke_cluster_name = var.gke_cluster_name
# re-use prefix to customize resources within the same project
name_suffix = length(var.state_prefix) > 0 ? "-${var.state_prefix}" : ""
output "certificate" {
value = google_container_cluster.sandbox.master_auth[0].cluster_ca_certificate
depends_on = [ module.gcloud.wait, null_resource.install_asm ]
}

depends_on = [
null_resource.wait_pods_are_ready,
]
output "endpoint" {
value = google_container_cluster.sandbox.endpoint
depends_on = [ module.gcloud.wait, null_resource.install_asm ]
}
70 changes: 70 additions & 0 deletions provisioning/terraform/k8s_cluster/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/**
* Copyright 2023 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.
*/

# Required input variables
variable "gcp_project_id" {
type = string
description = "The GCP project ID to apply this config to"
}

variable "gke_cluster_name" {
type = string
description = "Name given to the new GKE cluster"
}

variable "gke_cluster_location" {
type = string
description = "Region or zone of the new GKE cluster"
}

# Optional input variables
variable "asm_channel" {
type = string
description = "Defines one of the following managed ASM channels/revisions: 'rapid', 'regular' or stable'"
default = "stable"
validation {
condition = can(regex("^(rapid|regular|stable)$", var.asm_channel))
error_message = "ASM channel/revision can be only 'rapid', 'regular' or stable'"
}
}

variable "enable_asm" {
type = bool
description = "If true, installs Anthos Service Mesh (managed version of Istio) on the GKE cluster"
default = false
}

# Default values for node pool support connecting the cluster to ASM
# https://cloud.google.com/service-mesh/docs/unified-install/anthos-service-mesh-prerequisites#cluster_requirements
variable "gke_node_pool" {
type = object({
initial_node_count = number
labels = map(string)
machine_type = string

autoscaling = object({
max_node_count = number
min_node_count = number
})
})
description = "Initial settings and autoscale configuration of the GKE cluster's default node pool"
default = {
initial_node_count = 4
labels = {}
machine_type = "e2-standard-4"
autoscaling = null
}
}
49 changes: 49 additions & 0 deletions provisioning/terraform/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Copyright 2023 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
#
# https://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.


# ------------------------------------------
# Infra
module "k8s_cluster" {
source = "./k8s_cluster"
asm_channel = var.asm_channel
enable_asm = var.enable_asm
gcp_project_id = module.enable_google_apis.project_id
gke_cluster_location = var.gke_cluster_location
gke_cluster_name = var.gke_cluster_name
gke_node_pool = var.gke_node_pool
}

# ------------------------------------------
# Demo application
module "online_boutique" {
source = "./microservice_demo"
depends_on = [module.k8s_cluster]
enable_asm = var.enable_asm
filepath_manifest = var.filepath_manifest
gcp_project_id = module.enable_google_apis.project_id
}

# ------------------------------------------
# Cloud Ops configuration
module "cloud_ops" {
source = "./cloud-ops"
depends_on = [module.online_boutique]
enable_asm = var.enable_asm
frontend_external_ip = module.online_boutique.frontend_ip_address
gcp_project_id = var.gcp_project_id
gke_cluster_name = var.gke_cluster_name
# re-use prefix to customize resources within the same project
name_suffix = length(var.state_prefix) > 0 ? "-${var.state_prefix}" : ""
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@ locals {
namespace_name = "default"
}

data "google_project" "info" {
project_id = var.gcp_project_id
}

# Configure default compute SA to be used by K8s default SA in default ns
data "google_compute_default_service_account" "default" {
# ensure that default compute service account is provisioned
depends_on = [
module.gcloud,
]
}

resource "google_project_iam_binding" "default_compute_as_trace_agent" {
Expand Down Expand Up @@ -64,11 +65,6 @@ resource "null_resource" "online_boutique_kustomization" {
interpreter = ["bash", "-exc"]
command = "kubectl apply -k ${var.filepath_manifest} -n ${local.namespace_name}"
}

depends_on = [
module.gcloud,
null_resource.install_asm
]
}

# Wait condition for all resources to be ready before finishing
Expand All @@ -78,23 +74,14 @@ resource "null_resource" "wait_pods_are_ready" {
command = "kubectl wait --for=condition=ready pods --all -n ${local.namespace_name} --timeout=5m 2>/dev/null"
}

depends_on = [
null_resource.online_boutique_kustomization
]
depends_on = [null_resource.online_boutique_kustomization]
}

# waiting for external provisioning of LB
resource "null_resource" "wait_service_conditions" {
provisioner "local-exec" {
interpreter = ["bash", "-exc"]
command = <<EOF
while [[ -z $ip ]]; do \
ip=$(kubectl get svc ${local.service_name} \
-n ${local.namespace_name} \
--output='go-template={{range .status.loadBalancer.ingress}}{{.ip}}{{end}}'); \
sleep 1; \
done 2>/dev/null
EOF
command = "kubectl wait --for=jsonpath={.status.loadBalancer.ingress} service/${local.service_name} --timeout=5m 2>/dev/null"
}

depends_on = [
Expand Down
17 changes: 17 additions & 0 deletions provisioning/terraform/microservice_demo/output.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Copyright 2023 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
#
# https://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 "frontend_ip_address" {
value = data.kubernetes_service.frontend_external_service.status[0].load_balancer[0].ingress[0].ip
}
33 changes: 33 additions & 0 deletions provisioning/terraform/microservice_demo/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* Copyright 2023 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.
*/

# Required input variables
variable "gcp_project_id" {
type = string
description = "The GCP project ID to apply this config to"
}

variable "enable_asm" {
type = bool
description = "If true, installs Anthos Service Mesh (managed version of Istio) on the GKE cluster"
}

# Optional input variables
variable "filepath_manifest" {
type = string
description = "Path to Kubernetes resources, written using Kustomize"
default = "../kustomize/microservices-demo/"
}
Loading

0 comments on commit bb68acb

Please sign in to comment.