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

Rewrite ASM module #1140

Merged
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
285dd05
Remove previous ASM module and add initial implementation of new
Jan 21, 2022
912ca06
Move from kubernetes_manifest to bash CPR creation
Jan 26, 2022
afed279
Add meshconfig.googleapis.com service
Jan 26, 2022
88f7600
Add namespace to CPR creation script wait
Jan 26, 2022
0905359
Change example to use google_container_cluster
Jan 26, 2022
8538e86
Improve CPR status wait duration
Jan 26, 2022
11f9d90
Use retries rather than sleeping to wait for CPR CRD existence
Feb 2, 2022
56240f1
Enable servicemesh feature in module
Feb 2, 2022
5235884
Revert changes to examples
Feb 2, 2022
c61787a
Fix enable_mdp to just enable CNI
Feb 2, 2022
f5b65bd
Lint
Feb 2, 2022
4818dc6
minor fixes
Feb 7, 2022
8ce0635
Bump timeout on status wait
Feb 9, 2022
c961aaa
Don't create MeshConfig if unset
Feb 10, 2022
7ad8320
Fix ASM sample
Feb 10, 2022
e4e81d6
Update README autogen
Feb 11, 2022
7f1b0e2
Minor fixes
Feb 12, 2022
22dbbea
Remove meshConfig from module
Feb 12, 2022
3f0e6b2
fix end to end tests
Feb 15, 2022
83a1112
lint fixes
Feb 15, 2022
a787940
Remove enable_mdp, add enable_vpc_sc and fleet_id
Feb 15, 2022
3be283c
move VPC-SC from labels to annotations
Feb 15, 2022
5af57bf
update README
Feb 15, 2022
347c75a
use default node pool size
Feb 15, 2022
1bc68e4
use wip for exmaple cluster creation
Feb 15, 2022
3801f7b
add feature enablement back to module
Feb 15, 2022
9e63a53
lint
Feb 15, 2022
c963e4c
remove feature enablement from module
Feb 16, 2022
aea6fe5
remove depends_on
Feb 16, 2022
30ea4ba
fix unspecified channel bug
Feb 23, 2022
3ae8025
minor fixes
Feb 23, 2022
7a4867e
add more testing
Feb 23, 2022
f92c91e
update docs
Feb 23, 2022
33c742d
change required module version
Feb 23, 2022
036ecc8
fix cclb
Feb 24, 2022
04484ee
change registry source to run in CI
Feb 24, 2022
d46465a
update CROSS_CLUSTER_SERVICE_DISCOVERY to multicluster_mode
Feb 24, 2022
3848a0d
update README
Feb 25, 2022
d195981
fix test
Mar 1, 2022
6faadcf
fix wording
Mar 1, 2022
a8e32f5
remove from README
Mar 1, 2022
bc7449d
iterate on comments
Mar 2, 2022
396776a
Merge branch 'master' into rewrite-asm-module
kaariger Mar 2, 2022
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
24 changes: 17 additions & 7 deletions examples/simple_zonal_with_asm/hub.tf
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,21 @@
* limitations under the License.
*/

module "hub" {
source = "../../modules/hub"
project_id = var.project_id
location = module.gke.location
cluster_name = module.gke.name
cluster_endpoint = module.gke.endpoint
gke_hub_membership_name = "gke-asm-membership"
resource "google_gke_hub_feature" "mesh_feature" {
Monkeyanator marked this conversation as resolved.
Show resolved Hide resolved
name = "servicemesh"
project = var.project_id
location = "global"
provider = google-beta
}

resource "google_gke_hub_membership" "cluster_membership" {
provider = google-beta
project = var.project_id
membership_id = "gke-asm-membership"
endpoint {
gke_cluster {
resource_link = "//container.googleapis.com/${module.gke.cluster_id}"
}
}
}

18 changes: 6 additions & 12 deletions examples/simple_zonal_with_asm/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -57,16 +57,10 @@ module "gke" {
}

module "asm" {
source = "../../modules/asm"
cluster_name = module.gke.name
cluster_endpoint = module.gke.endpoint
project_id = var.project_id
location = module.gke.location
enable_cluster_roles = true
enable_cluster_labels = true
enable_gcp_apis = true
enable_gcp_components = true
enable_namespace_creation = true
options = ["envoy-access-log"]
outdir = "./${module.gke.name}-outdir"
source = "../../modules/asm"
project_id = var.project_id
cluster_name = module.gke.name
cluster_location = module.gke.location
enable_cross_cluster_service_discovery = true
enable_cni = true
}
76 changes: 7 additions & 69 deletions modules/asm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,87 +2,25 @@

This module installs [Anthos Service Mesh](https://cloud.google.com/service-mesh/docs) (ASM) in a Kubernetes Engine (GKE) cluster.

Specifically, this module automates installing the ASM Istio Operator on your cluster ([installing ASM](https://cloud.google.com/service-mesh/docs/install)).

## Usage

There is a [full example](../../examples/simple_zonal_with_asm) provided. Detailed usage example is as follows:

```tf
Monkeyanator marked this conversation as resolved.
Show resolved Hide resolved
module "asm" {
source = "terraform-google-modules/kubernetes-engine/google//modules/asm"

project_id = "my-project-id"
cluster_name = "my-cluster-name"
location = module.gke.location
cluster_endpoint = module.gke.endpoint
enable_all = false
enable_cluster_roles = true
enable_cluster_labels = false
enable_gcp_apis = false
enable_gcp_iam_roles = true
enable_gcp_components = true
enable_registration = false
managed_control_plane = false
options = ["envoy-access-log,egressgateways"]
custom_overlays = ["./custom_ingress_gateway.yaml"]
skip_validation = true
outdir = "./${module.gke.name}-outdir-${var.asm_version}"
}
```

To deploy this config:

1. Run `terraform apply`

## Requirements

- Anthos Service Mesh on GCP no longer requires an active Anthos license. You can use Anthos Service Mesh as a standalone product on GCP (on GKE) or as part of your Anthos subscription for hybrid and multi-cloud architectures.
- GKE cluster must have minimum four nodes.
- Minimum machine type is `e2-standard-4`.
- GKE cluster must be enrolled in a release channel. ASM does not support static version.
- ASM on a private GKE cluster requires adding a firewall rule to open port 15017 if you want to use [automatic sidecar injection](https://cloud.google.com/service-mesh/docs/proxy-injection).
- One ASM mesh per Google Cloud project is supported.

<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| asm\_git\_tag | ASM git tag to deploy. This module supports versions `1.8`, `1.9` and `1.10`. You can get the exact `asm_git_tag` by running the command `install_asm --version`. The ASM git tab should be of the form `1.9.3-asm.2+config5`. You can also see all ASM git tags by running `curl https://storage.googleapis.com/csm-artifacts/asm/STABLE_VERSIONS`. You must provide the full and exact git tag. This variable is optional. Leaving it empty (default) will download the latest `install_asm` script for the version provided by the `asm_version` variable. | `string` | `""` | no |
| asm\_version | ASM version to deploy. This module supports versions `1.8`, `1.9` and `1.10`. Available versions are documented in https://github.com/GoogleCloudPlatform/anthos-service-mesh-packages | `string` | `"1.9"` | no |
| ca | Sets CA option. Possible values are `meshca` or `citadel`. Additional documentation on Citadel is available at https://cloud.google.com/service-mesh/docs/scripted-install/gke-install#installation_with_citadel_as_the_ca. | `string` | `"meshca"` | no |
| ca\_certs | Sets CA certificate file paths when `ca` is set to `citadel`. These values must be provided when using Citadel as CA. Additional documentation on Citadel is available at https://cloud.google.com/service-mesh/docs/scripted-install/gke-install#installation_with_citadel_as_the_ca. | `map(any)` | `{}` | no |
| cluster\_endpoint | The GKE cluster endpoint. | `string` | n/a | yes |
| channel | The channel to use for this ASM installation. | `string` | `""` | no |
| cluster\_location | The cluster location for this ASM installation. | `string` | n/a | yes |
| cluster\_name | The unique name to identify the cluster in ASM. | `string` | n/a | yes |
| custom\_overlays | Comma separated list of custom\_overlay file paths. Works with in-cluster control plane only. Additional documentation available at https://cloud.google.com/service-mesh/docs/scripted-install/gke-install#installation_with_an_overlay_file | `list(any)` | `[]` | no |
| enable\_all | Sets `--enable_all` option if true. | `bool` | `false` | no |
| enable\_cluster\_labels | Sets `--enable_cluster_labels` option if true. | `bool` | `false` | no |
| enable\_cluster\_roles | Sets `--enable_cluster_roles` option if true. | `bool` | `false` | no |
| enable\_gcp\_apis | Sets `--enable_gcp_apis` option if true. | `bool` | `false` | no |
| enable\_gcp\_components | Sets --enable\_gcp\_components option if true. Can be true or false. Available versions are documented in https://github.com/GoogleCloudPlatform/anthos-service-mesh-packages | `bool` | `false` | no |
| enable\_gcp\_iam\_roles | Grants IAM roles required for ASM if true. If enable\_gcp\_iam\_roles, one of impersonate\_service\_account, service\_account, or iam\_member must be set. | `bool` | `false` | no |
| enable\_namespace\_creation | Sets `--enable_namespace_creation` option if true. | `bool` | `false` | no |
| enable\_registration | Sets `--enable_registration` option if true. | `bool` | `false` | no |
| gcloud\_sdk\_version | The gcloud sdk version to use. Minimum required version is 293.0.0 | `string` | `"296.0.1"` | no |
| iam\_member | The GCP member email address to grant IAM roles to. If impersonate\_service\_account or service\_account is set, roles are granted to that SA. | `string` | `""` | no |
| impersonate\_service\_account | An optional service account to impersonate for gcloud commands. If this service account is not specified, the module will use Application Default Credentials. | `string` | `""` | no |
| key\_file | The GCP Service Account credentials file path used to deploy ASM. | `string` | `""` | no |
| location | The location (zone or region) this cluster has been created in. | `string` | n/a | yes |
| managed\_control\_plane | ASM managed control plane boolean. Determines whether to install ASM managed control plane. Installing ASM managed control plane does not install gateways. Documentation on how to install gateways with ASM MCP can be found at https://cloud.google.com/service-mesh/docs/managed-control-plane#install_istio_gateways_optional. | `bool` | `false` | no |
| mode | ASM mode for deployment. Supported modes are `install` and `upgrade`. | `string` | `"install"` | no |
| options | Comma separated list of options. Works with in-cluster control plane only. Supported options are documented in https://cloud.google.com/service-mesh/docs/enable-optional-features. | `list(any)` | `[]` | no |
| outdir | Sets `--outdir` option. | `string` | `"none"` | no |
| enable\_cni | Determines whether to enable CNI for this ASM installation. | `bool` | `false` | no |
| enable\_cross\_cluster\_service\_discovery | Determines whether to enable cross-cluster service discovery between this cluster and other clusters in the fleet. | `bool` | `false` | no |
| enable\_mdp | Determines whether to enable Managed Data Plane (MDP) for this ASM installation. | `bool` | `false` | no |
| project\_id | The project in which the resource belongs. | `string` | n/a | yes |
| revision\_name | Sets `--revision-name` option. | `string` | `"none"` | no |
| service\_account | The GCP Service Account email address used to deploy ASM. | `string` | `""` | no |
| service\_account\_key\_file | Path to service account key file to auth as for running `gcloud container clusters get-credentials`. | `string` | `""` | no |
| skip\_validation | Sets `_CI_NO_VALIDATE` variable. Determines whether the script should perform validation checks for prerequisites such as IAM roles, Google APIs etc. | `bool` | `false` | no |

## Outputs

| Name | Description |
|------|-------------|
| asm\_wait | An output to use when you want to depend on ASM finishing |
| revision\_name | The name of the installed managed ASM revision. |

<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
120 changes: 41 additions & 79 deletions modules/asm/main.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright 2018 Google LLC
* Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -14,95 +14,57 @@
* limitations under the License.
*/

data "google_project" "asm_project" {
project_id = var.project_id
}

locals {
options_string = length(var.options) > 0 ? join(",", var.options) : "none"
custom_overlays_string = length(var.custom_overlays) > 0 ? join(",", var.custom_overlays) : "none"
asm_git_tag_string = (var.asm_git_tag == "" ? "none" : var.asm_git_tag)
service_account_string = (var.service_account == "" ? "none" : var.service_account)
key_file_string = (var.key_file == "" ? "none" : var.key_file)
ca_cert = lookup(var.ca_certs, "ca_cert", "none")
ca_key = lookup(var.ca_certs, "ca_key", "none")
root_cert = lookup(var.ca_certs, "root_cert", "none")
cert_chain = lookup(var.ca_certs, "cert_chain", "none")
revision_name_string = (var.revision_name == "" ? "none" : var.revision_name)
asm_minor_version = tonumber(split(".", var.asm_version)[1])
# https://github.com/GoogleCloudPlatform/anthos-service-mesh-packages/blob/1cf61b679cd369f42a0e735f8e201de1a6a6433b/scripts/asm-installer/install_asm#L1970
iam_roles = [
"roles/container.admin",
"roles/meshconfig.admin",
"roles/gkehub.admin",
]
# https://github.com/GoogleCloudPlatform/anthos-service-mesh-packages/blob/1cf61b679cd369f42a0e735f8e201de1a6a6433b/scripts/asm-installer/install_asm#L1958
mcp_iam_roles = [
"roles/serviceusage.serviceUsageConsumer",
"roles/container.admin",
"roles/monitoring.metricWriter",
"roles/logging.logWriter",
"roles/gkehub.viewer",
"roles/gkehub.gatewayAdmin",
]
# if enable_gcp_iam_roles is set, grant IAM roles to first non null principal in the order below
asm_iam_member = var.enable_gcp_iam_roles ? coalesce(var.impersonate_service_account, var.service_account, var.iam_member) : ""
# compute any additonal resources that ASM provisioner should depend on
additional_depends_on = concat(var.enable_gcp_apis ? [module.asm-services[0].project_id] : [], local.asm_iam_member != "" ? [for k, v in google_project_iam_member.asm_iam : v.etag] : [])
# base command template for ASM installation
kubectl_create_command_base = "${path.module}/scripts/install_asm.sh ${var.project_id} ${var.cluster_name} ${var.location} ${var.asm_version} ${var.mode} ${var.managed_control_plane} ${var.skip_validation} ${local.options_string} ${local.custom_overlays_string} ${var.enable_all} ${var.enable_cluster_roles} ${var.enable_cluster_labels} ${var.enable_gcp_components} ${var.enable_registration} ${var.outdir} ${var.ca} ${local.ca_cert} ${local.ca_key} ${local.root_cert} ${local.cert_chain} ${local.service_account_string} ${local.key_file_string} ${local.asm_git_tag_string} ${local.revision_name_string}"
// GKE release channel is a list with max length 1 https://github.com/hashicorp/terraform-provider-google/blob/9d5f69f9f0f74f1a8245f1a52dd6cffb572bbce4/google/resource_container_cluster.go#L954
gke_release_channel = data.google_container_cluster.asm.release_channel != null ? data.google_container_cluster.asm.release_channel[0].channel : ""
Monkeyanator marked this conversation as resolved.
Show resolved Hide resolved
// In order or precedence, use (1) user specified channel, (2) GKE release channel, and (3) regular channel
channel = lower(coalesce(var.channel, local.gke_release_channel, "regular"))
revision_name = "asm-managed${local.channel == "regular" ? "" : "-${local.channel}"}"
// CNI should be enabled if either enable_cni or enable_mdp are set
enable_cni = var.enable_cni || var.enable_mdp
}

resource "google_project_iam_member" "asm_iam" {
for_each = toset(local.asm_iam_member != "" ? (var.managed_control_plane ? local.mcp_iam_roles : local.iam_roles) : [])
data "google_container_cluster" "asm" {
project = var.project_id
role = each.value
member = "serviceAccount:${local.asm_iam_member}"
name = var.cluster_name
location = var.cluster_location
}

module "asm-services" {
source = "terraform-google-modules/project-factory/google//modules/project_services"
version = "~> 11.3"

count = var.enable_gcp_apis ? 1 : 0
resource "kubernetes_namespace" "system" {
metadata {
name = "istio-system"
}
}

project_id = var.project_id
disable_services_on_destroy = false
disable_dependent_services = false
resource "kubernetes_config_map" "asm_options" {
metadata {
name = "asm-options"
namespace = kubernetes_namespace.system.metadata[0].name
}

# https://github.com/GoogleCloudPlatform/anthos-service-mesh-packages/blob/1cf61b679cd369f42a0e735f8e201de1a6a6433b/scripts/asm-installer/install_asm#L2005
activate_apis = [
"container.googleapis.com",
"monitoring.googleapis.com",
"logging.googleapis.com",
"cloudtrace.googleapis.com",
"meshtelemetry.googleapis.com",
"meshconfig.googleapis.com",
"meshca.googleapis.com",
"iamcredentials.googleapis.com",
"gkeconnect.googleapis.com",
"gkehub.googleapis.com",
"cloudresourcemanager.googleapis.com",
"stackdriver.googleapis.com",
]
data = {
CROSS_CLUSTER_SERVICE_DISCOVERY = var.enable_cross_cluster_service_discovery ? "ON" : "OFF"
}
}

module "asm_install" {
source = "terraform-google-modules/gcloud/google//modules/kubectl-wrapper"
version = "~> 3.1"
# TODO(Monkeyanator) due to a bug in the gke_hub_feature resource implementation this fails when enabling an enabled
Monkeyanator marked this conversation as resolved.
Show resolved Hide resolved
# feature (i.e. running the module twice) and does not disable the feature upon TF destroy.
#resource "google_gke_hub_feature" "mesh_feature" {
# name = "servicemesh"
# project = var.project_id
# location = "global"
# provider = google-beta
#}

module "cpr" {
source = "terraform-google-modules/gcloud/google//modules/kubectl-wrapper"
Monkeyanator marked this conversation as resolved.
Show resolved Hide resolved

module_depends_on = concat([var.cluster_endpoint], local.additional_depends_on)
project_id = var.project_id
cluster_name = var.cluster_name
cluster_location = var.cluster_location

gcloud_sdk_version = var.gcloud_sdk_version
upgrade = true
additional_components = ["kubectl", "kpt", "beta"]
cluster_name = var.cluster_name
cluster_location = var.location
project_id = var.project_id
service_account_key_file = var.service_account_key_file
impersonate_service_account = var.impersonate_service_account
kubectl_create_command = "${path.module}/scripts/create_cpr.sh ${local.revision_name} ${local.channel} ${local.enable_cni}"
kubectl_destroy_command = "${path.module}/scripts/destroy_cpr.sh ${local.revision_name}"

# enable_namespace_creation flag is only available starting 1.10
kubectl_create_command = (local.asm_minor_version > 9 ? "${local.kubectl_create_command_base} ${var.enable_namespace_creation}" : local.kubectl_create_command_base)
kubectl_destroy_command = "${path.module}/scripts/destroy_asm.sh"
module_depends_on = [kubernetes_config_map.asm_options]
}
8 changes: 4 additions & 4 deletions modules/asm/outputs.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright 2018 Google LLC
* Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -14,7 +14,7 @@
* limitations under the License.
*/

output "asm_wait" {
Monkeyanator marked this conversation as resolved.
Show resolved Hide resolved
description = "An output to use when you want to depend on ASM finishing"
value = module.asm_install.wait
output "revision_name" {
value = local.revision_name
description = "The name of the installed managed ASM revision."
}
1 change: 0 additions & 1 deletion modules/asm/scripts/.gitignore

This file was deleted.

56 changes: 56 additions & 0 deletions modules/asm/scripts/create_cpr.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#!/usr/bin/env bash

# Copyright 2022 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.

set -e

if [ "$#" -lt 3 ]; then
Monkeyanator marked this conversation as resolved.
Show resolved Hide resolved
>&2 echo "Not all expected arguments set."
exit 1
fi

REVISION_NAME=$1; shift
CHANNEL=$1; shift
ENABLE_CNI=$1; shift

# Wait for the CRD to get created before creating the CPR. Not possible to use `kubectl --wait ...` here since
# the CRD won't exist at the time of checking (https://stackoverflow.com/questions/57115602/how-to-kubectl-wait-for-crd-creation)
readonly CPR_RESOURCE=controlplanerevisions.mesh.cloud.google.com
for _i in {1..18}; do
echo "Ensuring ControlPlaneRevision exists in cluster... attempt ${_i}"
if kubectl get crd "${CPR_RESOURCE}"
then
break
else
sleep 10
fi
done

kubectl wait --for condition=established --timeout=60s crd/"${CPR_RESOURCE}"

cat <<EOF | kubectl apply -f -
apiVersion: mesh.cloud.google.com/v1beta1
kind: ControlPlaneRevision
metadata:
name: "${REVISION_NAME}"
namespace: istio-system
labels:
mesh.cloud.google.com/managed-cni-enabled: "${ENABLE_CNI}"
spec:
type: managed_service
channel: "${CHANNEL}"
EOF

kubectl wait -n istio-system --for=condition=Reconciled controlplanerevision/"${REVISION_NAME}" --timeout 10m
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env bash

# Copyright 2021 Google LLC
# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand All @@ -16,5 +16,13 @@

set -e

kubectl delete ns asm-system istio-system --ignore-not-found
kubectl label namespaces --all istio-injection-
if [ "$#" -lt 1 ]; then
>&2 echo "Not all expected arguments set."
exit 1
fi

REVISION_NAME=$1; shift

if ! kubectl delete controlplanerevision -n istio-system "${REVISION_NAME}" ; then
echo "ControlPlaneRevision ${REVISION_NAME} not found"
fi
Loading