Skip to content

Commit be09950

Browse files
authored
feat: (PSKD-709) Add Support for Google NetApp Volumes (#224)
* feat: (PSKD-709) Add support for Google NetApp volumes Signed-off-by: Ritika Patil <[email protected]>
1 parent db9de7d commit be09950

File tree

13 files changed

+246
-13
lines changed

13 files changed

+246
-13
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ This project contains Terraform scripts to provision Google Cloud infrastructure
88
>- Managed Google Kubernetes Engine (GKE) cluster
99
>- System and User GKE Node pools with required Labels and Taints
1010
>- Infrastructure to deploy SAS Viya platform CAS in SMP or MPP mode
11-
>- Shared Storage options for SAS Viya platform - Google Filestore (ha) or NFS Server (standard)
11+
>- Shared Storage options for SAS Viya platform - Google Filestore (ha), Google NetApp Volumes (ha) or NFS Server (standard)
1212
>- Google Cloud SQL for PostgreSQL instance, optional
1313
1414
[<img src="./docs/images/viya4-iac-gcp-diag.png" alt="Architecture Diagram" width="750"/>](./docs/images/viya4-iac-gcp-diag.png?raw=true)

docs/CONFIG-VARS.md

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ Supported configuration variables are listed in the table below. All variables
1717
- [Additional Nodepools](#additional-nodepools)
1818
- [Storage](#storage)
1919
- [For `storage_type=standard` only (NFS server VM)](#for-storage_typestandard-only-nfs-server-vm)
20-
- [For `storage_type=ha` only (Google Filestore)](#for-storage_typeha-only-google-filestore)
20+
- [For `storage_type=ha` with Google Filestore](#for-storage_typeha-with-google-filestore)
21+
- [For `storage_type=ha` with Google NetApp Volumes](#for-storage_typeha-with-google-netapp-volumes)
2122
- [Google Artifact Registry (GAR) and Google Container Registry (GCR)](#google-artifact-registry-gar-and-google-container-registry-gcr)
2223
- [Postgres Servers](#postgres-servers)
2324
- [Monitoring](#monitoring)
@@ -69,6 +70,7 @@ You can use `default_public_access_cidrs` to set a default range for all created
6970
| misc_subnet_cidr | Address space for the the auxiliary resources (Jump VM and optionally NFS VM) subnet | string | "192.168.2.0/24" | This variable is ignored when `subnet_names` is set (aka bring your own subnet) |
7071
| filestore_subnet_cidr | Address space for Google Filestore subnet | string | "192.168.3.0/29" | Needs to be at least a /29 range. Only used when `storage_type="ha"` |
7172
| database_subnet_cidr | Address space for Google Cloud SQL Postgres subnet | string | "192.168.4.0/23" | Only used with external postgres |
73+
| netapp_subnet_cidr | Address space for Google Cloud NetApp Volumes subnet | string | "192.168.5.0/24" | Needs to be at least a /24 range. Only used when `storage_type="ha"` and `storage_type_backend="netapp"` |
7274

7375
### Use Existing
7476

@@ -212,6 +214,7 @@ stateful = {
212214
| Name | Description | Type | Default | Notes |
213215
| :--- | ---: | ---: | ---: | ---: |
214216
| storage_type | Type of Storage. Valid Values: "standard", "ha" | string | "standard" | "standard" creates NFS server VM, "ha" Google Filestore instance |
217+
| storage_type_backend | The storage backend for the chosen `storage_type`. | string | If `storage_type=standard` the default is "nfs";<br>If `storage_type=ha` the default is "filestore" | Valid Values: "nfs" if `storage_type=standard`; "filestore" or "netapp" if `storage_type=ha` |
215218

216219
### For `storage_type=standard` only (NFS server VM)
217220

@@ -221,13 +224,27 @@ stateful = {
221224
| nfs_vm_admin | OS Admin User for the NFS server VM | string | "nfsuser" | The NFS server VM is only created when storage_type="standard" |
222225
| nfs_raid_disk_size | Size in Gb for each disk of the RAID5 cluster on the NFS server VM | number | 1000 | The NFS server VM is only created when storage_type="standard" |
223226

224-
### For `storage_type=ha` only (Google Filestore)
227+
### For `storage_type=ha` with Google Filestore
225228

226229
| Name | Description | Type | Default | Notes |
227230
| :--- | ---: | ---: | ---: | ---: |
228231
| filestore_tier | The service tier for the Google Filestore Instance | string | "BASIC_HDD" | Valid Values: "BASIC_HDD", "BASIC_SSD" (previously called "STANDARD" and "PREMIUM" respectively.) |
229232
| filestore_size_in_gb | Size in GB of Filesystem in the Google Filestore Instance | number | 1024 for BASIC_HDD, 2560 for BASIC_SDD | 2560 GB is the minimum size for the BASIC_SSD tier. The BASIC_HDD tier allows a minimum size of 1024 GB. |
230233

234+
### For `storage_type=ha` with Google NetApp Volumes
235+
236+
When `storage_type=ha` and `storage_type_backend=netapp` are specified, [Google NetApp Volumes](https://cloud.google.com/netapp/volumes/docs/discover/overview) service is created. Before using this storage option,
237+
- Enable the Google Cloud NetApp Volumes API for your project, see how to enable [here](https://cloud.google.com/netapp/volumes/docs/get-started/configure-access/initiate-console-settings#enable_the_api).
238+
- Grant access to NetApp Volumes operations by granting IAM roles to users. The two predefined roles are `roles/netapp.admin` and `roles/netapp.viewer`. You can assign these roles to specific users or service accounts.
239+
- NetApp Volumes is available in several regions. For details about region availability, see [NetApp Volumes locations](https://cloud.google.com/netapp/volumes/docs/locations).
240+
241+
| Name | Description | Type | Default | Notes |
242+
| :--- | ---: | ---: | ---: | ---: |
243+
| netapp_service_level | The service level of the storage pool. | string | "PREMIUM" | Valid Values are: PREMIUM, EXTREME, STANDARD, FLEX. |
244+
| netapp_protocols | The target volume protocol expressed as a list. | list(string) | ["NFSV3"] | Each value may be one of: NFSV3, NFSV4, SMB. Currently, only NFSV3 is supported by SAS Viya Platform. |
245+
| netapp_capacity_gib | Capacity of the storage pool (in GiB). Storage Pool capacity specified must be between 2048 GiB and 10485760 GiB. | string | "2048" | |
246+
| netapp_volume_path | A unique file path for the volume. Used when creating mount targets. Needs to be unique per location.| string | | |
247+
231248
## Google Artifact Registry (GAR) and Google Container Registry (GCR)
232249

233250
| Name | Description | Type | Default | Notes |

docs/user/TerraformGCPAuthentication.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ The Service Account will need the following [IAM roles](https://cloud.google.com
3939
| `roles/container.admin` | Kubernetes Engine Admin | Cluster creation |
4040
| `roles/container.clusterAdmin` | Kubernetes Engine Cluster Admin | Terraform Kubernetes Engine Module |
4141
| `roles/container.developer` | Kubernetes Engine Developer | Cluster creation |
42-
| `roles/file.editor` | Cloud Filestore Editor | Needed for [`storage_type=="HA"`](../CONFIG-VARS.md#storage) |
42+
| `roles/file.editor` | Cloud Filestore Editor | Needed for [`storage_type=="ha" && storage_type_backend = "filestore"`](../CONFIG-VARS.md#storage) |
43+
| `roles/netapp.admin` | NetApp Admin | Needed for [`storage_type=="ha" && storage_type_backend = "netapp"`](../CONFIG-VARS.md#storage) |
44+
| `roles/netapp.viewer` | NetApp Viewer | Needed for [`storage_type=="ha" && storage_type_backend = "netapp"`](../CONFIG-VARS.md#storage) |
4345
| `roles/iam.serviceAccountAdmin` | Service Account Admin | Terraform Kubernetes Engine Module |
4446
| `roles/iam.serviceAccountUser` | Service Account User | Terraform Kubernetes Engine Module |
4547
| `roles/resourcemanager.projectIamAdmin` | Project IAM Admin | Terraform Kubernetes Engine Module |
@@ -59,6 +61,8 @@ gcloud projects add-iam-policy-binding $PROJECT --member serviceAccount:${SA_NAM
5961
gcloud projects add-iam-policy-binding $PROJECT --member serviceAccount:${SA_NAME}@${PROJECT}.iam.gserviceaccount.com --role roles/container.clusterAdmin
6062
gcloud projects add-iam-policy-binding $PROJECT --member serviceAccount:${SA_NAME}@${PROJECT}.iam.gserviceaccount.com --role roles/container.developer
6163
gcloud projects add-iam-policy-binding $PROJECT --member serviceAccount:${SA_NAME}@${PROJECT}.iam.gserviceaccount.com --role roles/file.editor
64+
gcloud projects add-iam-policy-binding $PROJECT --member serviceAccount:${SA_NAME}@${PROJECT}.iam.gserviceaccount.com --role roles/netapp.admin
65+
gcloud projects add-iam-policy-binding $PROJECT --member serviceAccount:${SA_NAME}@${PROJECT}.iam.gserviceaccount.com --role roles/netapp.viewer
6266
gcloud projects add-iam-policy-binding $PROJECT --member serviceAccount:${SA_NAME}@${PROJECT}.iam.gserviceaccount.com --role roles/iam.serviceAccountAdmin
6367
gcloud projects add-iam-policy-binding $PROJECT --member serviceAccount:${SA_NAME}@${PROJECT}.iam.gserviceaccount.com --role roles/iam.serviceAccountUser
6468
gcloud projects add-iam-policy-binding $PROJECT --member serviceAccount:${SA_NAME}@${PROJECT}.iam.gserviceaccount.com --role roles/resourcemanager.projectIamAdmin

examples/sample-input-ha.tfvars

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,5 +94,6 @@ jump_vm_admin = "jumpuser"
9494
# Storage for Viya Compute Services
9595
# Supported storage_type values
9696
# "standard" - Custom managed NFS Server VM and disks
97-
# "ha" - Google Filestore
97+
# "ha" - Google Filestore or Google NetApp Volumes
9898
storage_type = "ha"
99+
storage_type_backend = "filestore" # "filestore" is the default, use "netapp" to create Google NetApp Volumes

locals.tf

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ locals {
2525
: null
2626
)
2727

28+
# Storage
29+
storage_type_backend = (var.storage_type == "none" ? "none"
30+
: var.storage_type == "standard" ? "nfs"
31+
: var.storage_type == "ha" && var.storage_type_backend == "netapp" ? "netapp"
32+
: var.storage_type == "ha" ? "filestore" : "none")
33+
2834
# Kubernetes
2935
kubeconfig_path = var.iac_tooling == "docker" ? "/workspace/${var.prefix}-gke-kubeconfig.conf" : "${var.prefix}-gke-kubeconfig.conf"
3036

main.tf

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ EOT
6666

6767
resource "google_filestore_instance" "rwx" {
6868
name = "${var.prefix}-rwx-filestore"
69-
count = var.storage_type == "ha" ? 1 : 0
69+
count = var.storage_type == "ha" && local.storage_type_backend == "filestore" ? 1 : 0
7070
tier = upper(var.filestore_tier)
7171
location = local.zone
7272
labels = var.tags
@@ -301,3 +301,19 @@ module "sql_proxy_sa" {
301301
project_roles = ["${var.project}=>roles/cloudsql.admin"]
302302
display_name = "IAC-managed service account for cluster ${var.prefix} and sql-proxy integration."
303303
}
304+
305+
module "google_netapp" {
306+
source = "./modules/google_netapp"
307+
308+
count = var.storage_type == "ha" && local.storage_type_backend == "netapp" ? 1 : 0
309+
310+
prefix = var.prefix
311+
region = local.region
312+
network = module.vpc.network_name
313+
netapp_subnet_cidr = var.netapp_subnet_cidr
314+
service_level = var.netapp_service_level
315+
capacity_gib = var.netapp_capacity_gib
316+
protocols = var.netapp_protocols
317+
volume_path = "${var.prefix}-${var.netapp_volume_path}"
318+
allowed_clients = join(",", [local.gke_subnet_cidr, local.misc_subnet_cidr])
319+
}

modules/google_netapp/main.tf

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Copyright © 2021-2024, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
#
4+
# Terraform Registry : https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/netapp_volume
5+
# GitHub Repository : https://github.com/terraform-google-modules
6+
#
7+
8+
# Reserve compute address CIDR for NetApp Volumes to use
9+
resource "google_compute_global_address" "private_ip_alloc" {
10+
name = "${var.network}-ip-range"
11+
purpose = "VPC_PEERING"
12+
address_type = "INTERNAL"
13+
address = split("/", var.netapp_subnet_cidr)[0]
14+
prefix_length = split("/", var.netapp_subnet_cidr)[1]
15+
network = var.network
16+
}
17+
18+
# Create the PSA peering
19+
resource "google_service_networking_connection" "default" {
20+
network = var.network
21+
service = "netapp.servicenetworking.goog"
22+
reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name]
23+
24+
deletion_policy = "ABANDON"
25+
}
26+
27+
# Modify the PSA Connection to allow import/export of custom routes
28+
resource "google_compute_network_peering_routes_config" "route_updates" {
29+
peering = google_service_networking_connection.default.peering
30+
network = var.network
31+
32+
import_custom_routes = true
33+
export_custom_routes = true
34+
}
35+
36+
resource "google_netapp_storage_pool" "netapp-tf-pool" {
37+
name = "${var.prefix}-netapp-storage-pool"
38+
location = var.region
39+
service_level = var.service_level
40+
capacity_gib = var.capacity_gib
41+
network = var.network
42+
43+
lifecycle {
44+
ignore_changes = [network]
45+
}
46+
}
47+
48+
resource "google_netapp_volume" "netapp-nfs-volume" {
49+
location = var.region
50+
name = "${var.prefix}-netapp-volume"
51+
capacity_gib = var.capacity_gib # Size can be up to space available in pool
52+
share_name = var.volume_path
53+
storage_pool = google_netapp_storage_pool.netapp-tf-pool.name
54+
protocols = var.protocols
55+
unix_permissions = "0777"
56+
export_policy {
57+
rules {
58+
access_type = "READ_WRITE"
59+
allowed_clients = var.allowed_clients
60+
has_root_access = true
61+
nfsv3 = contains(var.protocols, "NFSV3") ? true : false
62+
nfsv4 = contains(var.protocols, "NFSV4") ? true : false
63+
}
64+
}
65+
66+
depends_on = [
67+
google_netapp_storage_pool.netapp-tf-pool,
68+
google_service_networking_connection.default
69+
]
70+
}

modules/google_netapp/outputs.tf

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
output "mountpath" {
2+
value = google_netapp_volume.netapp-nfs-volume.mount_options[0].export
3+
}
4+
5+
output "export_ip" {
6+
value = split(":", google_netapp_volume.netapp-nfs-volume.mount_options[0].export_full)[0]
7+
}

modules/google_netapp/variables.tf

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Copyright © 2021-2024, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
variable "prefix" {
5+
description = "A prefix used in the name for all cloud resources created by this script. The prefix string must start with lowercase letter and contain only lowercase alphanumeric characters and hyphen or dash(-), but can not start or end with '-'."
6+
type = string
7+
}
8+
9+
variable "region" {
10+
description = "The region to create the VM in"
11+
type = string
12+
}
13+
14+
variable "service_level" {
15+
description = "Service level of the storage pool. Possible values are: PREMIUM, EXTREME, STANDARD, FLEX."
16+
type = string
17+
default = "PREMIUM"
18+
}
19+
20+
variable "protocols" {
21+
description = "The target volume protocol expressed as a list. Allowed combinations are ['NFSV3'], ['NFSV4'], ['SMB'], ['NFSV3', 'NFSV4'], ['SMB', 'NFSV3'] and ['SMB', 'NFSV4']. Each value may be one of: NFSV3, NFSV4, SMB."
22+
type = list(string)
23+
default = ["NFSV3"]
24+
}
25+
26+
variable "capacity_gib" {
27+
description = "Capacity of the storage pool (in GiB)."
28+
type = string
29+
default = 2048
30+
}
31+
32+
variable "volume_path" {
33+
description = "A unique file path for the volume. Used when creating mount targets. Needs to be unique per location."
34+
type = string
35+
default = "export"
36+
}
37+
38+
variable "network" {
39+
description = "VPC network name with format: `projects/{{project}}/global/networks/{{network}}`"
40+
type = string
41+
}
42+
43+
44+
variable "allowed_clients" {
45+
description = "CIDR blocks allowed to mount nfs exports"
46+
type = string
47+
default = "0.0.0.0/0"
48+
}
49+
50+
variable "netapp_subnet_cidr" {
51+
description = "Address space for Google Cloud NetApp Volumes subnet"
52+
type = string
53+
default = "192.168.5.0/24"
54+
}

network.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ resource "google_service_networking_connection" "private_vpc_connection" {
7272
# required as of hashicorp/google v5.12.0 when using google_service_networking_connection in
7373
# conjunction with CloudSQL instances in order to cleanly delete resources
7474
# https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/service_networking_connection
75-
deletion_policy = "ABANDON"
75+
deletion_policy = "ABANDON"
7676
}
7777

7878
resource "google_compute_firewall" "nfs_vm_cluster_firewall" {

0 commit comments

Comments
 (0)