Google Cloud with Google Cloud NetApp Volumes - Configuration
OpenShift Virtualization Storage Configuration for Google Cloud NetApp Volumes (GCNV)
Applicable to: OpenShift Virtualization 4.21.2+ on Red Hat OpenShift Container Platform 4.21+ (GCP) with NetApp Trident CSI driver.
Overview
Google Cloud NetApp Volumes (GCNV) provides NFS-based shared storage for OpenShift Virtualization workloads on Google Cloud. GCNV supports ReadWriteMany (RWX) in Filesystem mode, which enables VM live migration, and is provisioned through the NetApp Trident CSI driver.
Important: This guide covers the Flex File service level only. When creating storage pools, select the File storage type (not "Unified"). Flex Unified (which adds iSCSI/block support) is not covered in this release.
This guide walks you through Trident installation and configuration on an OpenShift cluster that already has GCNV resources provisioned on the Google Cloud side.
What you will do in this guide:
- Install Trident
- Create a TridentBackendConfig for GCNV
- Create the StorageClass
- Create a VolumeSnapshotClass
- Set the filesystem overhead
- Verify the setup
Prerequisites
- Red Hat OpenShift Container Platform 4.21+ deployed on Google Cloud (including OpenShift Dedicated)
- OpenShift Virtualization 4.21.2+ installed with the HyperConverged resource created (default settings)
- Cluster admin access (
oc loginaskubeadminor equivalent) - A GCP project with the Content from cloud.google.com is not included.Google Cloud NetApp Volumes API enabled
- A GCP service account with the Google Cloud NetApp Volumes Admin (
roles/netapp.admin) role and a JSON key file (referred to astrident-admin.jsonthroughout this guide) - see Content from docs.netapp.com is not included.Prepare to configure a GCNV backend - Private Service Access (PSA) configured on the cluster's VPC network - see Content from docs.cloud.google.com is not included.Networking overview
- One or more GCNV storage pools - see Content from docs.cloud.google.com is not included.Create a storage pool. Flex pools can be zonal (created in the same zone as your worker nodes) or regional (replicates volumes across zones). Regional pools only support default performance (not custom). For zonal pools, specify the zone in the TridentBackendConfig
locationfield; for regional pools, specify the region.
Storage pool sizing: GCNV Flex pools are limited to 50 volumes per pool (Content from docs.cloud.google.com is not included.GCNV storage pool limits). Each Flex pool has a minimum capacity of 1 TiB. Create multiple pools and list them all in the TridentBackendConfig - Trident distributes volumes across pools automatically. For example, 4 pools support ~200 volumes, 16 pools support ~800 volumes.
For the full GCNV preparation checklist (service account, PSA, storage pools, API key), see Content from docs.netapp.com is not included.Prepare to configure a GCNV backend.
Configuration Steps
Step 1: Install Trident
Choose one of the two options below.
Option A: Via the OpenShift Web Console (operator)
- Navigate to Ecosystem > Software Catalog and search for "Trident"
- Install the NetApp Trident operator (version 26.02.0 or later)
- Once installed, go to Installed Operators and open Trident
- Click Create TridentOrchestrator
- Switch to YAML view, ensure the full CR looks like the following (add
enableConcurrency: true), and click Create:
kind: TridentOrchestrator
apiVersion: trident.netapp.io/v1
metadata:
name: trident
spec:
IPv6: false
debug: true
nodePrep: []
imagePullSecrets: []
imageRegistry: ''
namespace: trident
silenceAutosupport: false
enableConcurrency: true
For full details, see Content from docs.netapp.com is not included.Manually deploy the Trident operator.
Option B: Via tridentctl (CLI)
Download the Trident installer and run tridentctl install:
export TRIDENT_VERSION="26.02.0"
wget "https://github.com/NetApp/trident/releases/download/v${TRIDENT_VERSION}/trident-installer-${TRIDENT_VERSION}.tar.gz"
tar -xf "trident-installer-${TRIDENT_VERSION}.tar.gz"
cd trident-installer
./tridentctl install --enable-concurrency -n trident --kubeconfig "${KUBECONFIG}"
For full details, see Content from docs.netapp.com is not included.Install using tridentctl.
You can also install Trident using Helm. See Content from docs.netapp.com is not included.Use Trident Helm Chart for details.
Verify
Regardless of which option you chose, verify Trident is running:
oc get torc trident -o jsonpath='{.status.status}'
Expected output: Installed. Verify the pods:
oc get pods -n trident
You should see a trident-controller, trident-node-linux DaemonSet pods, and the trident-operator pod all in Running state.
Step 2: Create the Credentials Secret and TridentBackendConfig
This step creates the Secret and TridentBackendConfig together, following the pattern from the Content from docs.netapp.com is not included.official NetApp GCNV examples. The Secret holds the sensitive credential fields (private_key and private_key_id) from your trident-admin.json key file, and the TridentBackendConfig references it via credentials.name.
List all of your storage pools in the storagePools array - Trident will distribute volumes across them, which is critical given the 50-volume-per-pool limit. For the full list of backend configuration parameters, see Content from docs.netapp.com is not included.GCNV backend configuration options.
Get your GCP project number:
gcloud projects describe "${GCP_PROJECT_ID}" --format="value(projectNumber)"
Create a file named gcnv-backend-flex.yaml with the following content. Replace all <placeholder> values:
---
apiVersion: v1
kind: Secret
metadata:
name: trident-admin
namespace: trident
type: Opaque
stringData:
private_key_id: "<private_key_id from trident-admin.json>"
private_key: |
-----BEGIN PRIVATE KEY-----
<private_key from trident-admin.json>
-----END PRIVATE KEY-----
---
apiVersion: trident.netapp.io/v1
kind: TridentBackendConfig
metadata:
name: gcnv-backend-flex
namespace: trident
spec:
version: 1
storageDriverName: google-cloud-netapp-volumes
backendName: gcnv-flex
projectNumber: "<your-project-number>"
location: "<worker-node-zone>"
storage:
- labels:
performance: flex
serviceLevel: flex
storagePools:
- <pool-prefix>-flex-pool-1
- <pool-prefix>-flex-pool-2
- <pool-prefix>-flex-pool-3
- <pool-prefix>-flex-pool-4
apiKey:
type: service_account
project_id: "<your-gcp-project-id>"
client_email: "<your-service-account>@<your-gcp-project-id>.iam.gserviceaccount.com"
client_id: "<client-id-from-json>"
auth_uri: https://accounts.google.com/o/oauth2/auth
token_uri: https://oauth2.googleapis.com/token
auth_provider_x509_cert_url: https://www.googleapis.com/oauth2/v1/certs
client_x509_cert_url: "https://www.googleapis.com/robot/v1/metadata/x509/<your-service-account>%40<your-gcp-project-id>.iam.gserviceaccount.com"
credentials:
name: trident-admin
Tip: All the
apiKeyfields and the SecretstringDatavalues come from yourtrident-admin.jsonfile. You can extract the non-sensitiveapiKeyportion with:jq 'del(.private_key_id, .private_key)' trident-admin.json
Note:
backendNameis a user-chosen friendly name for Trident's internal identification (visible intridentctl get backend). It does not reference any external GCP resource. The StorageClass selects this backend via theselector: "performance=flex"parameter, which matches thelabels.performance: flexdefined in thestoragesection above.
Important: For Flex zonal pools,
locationmust be the zone (e.g.us-central1-a). For Flex regional pools or Standard/Premium/Extreme, use the region (e.g.us-central1).
Note: The
storagePoolslist is optional. If omitted, Trident will use any pool with the matching service level in the configured location. Explicitly listing pools is only necessary if you want to restrict which pools Trident uses (e.g. when pools in the same project/location are shared across clusters).
Apply both resources:
oc apply -f gcnv-backend-flex.yaml
Wait for the backend to become ready:
oc get tridentbackendconfig gcnv-backend-flex -n trident -o jsonpath='{.status.lastOperationStatus}'
Expected output: Success. If it shows Failed, check the backend details:
oc describe tridentbackendconfig gcnv-backend-flex -n trident
For more examples (virtual pools, SMB, topology), see Content from docs.netapp.com is not included.GCNV backend configuration examples.
Adding More Pools Later
When you need more volume capacity, Content from docs.cloud.google.com is not included.create additional storage pools in GCP and add their names to the storagePools list in the TridentBackendConfig:
oc edit tridentbackendconfig gcnv-backend-flex -n trident
Add the new pool name to spec.storagePools and save. Trident picks up the change automatically.
Step 3: Create the StorageClass
Create a StorageClass that uses the Trident backend. This is what users and CDI will reference when creating PVCs.
Create a file named gcnv-flex-storageclass.yaml with the following content:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: gcnv-flex
annotations:
storageclass.kubernetes.io/is-default-class: "true"
storageclass.kubevirt.io/is-default-virt-class: "true"
provisioner: csi.trident.netapp.io
parameters:
backendType: "google-cloud-netapp-volumes"
selector: "performance=flex"
allowVolumeExpansion: true
Apply:
oc apply -f gcnv-flex-storageclass.yaml
If the cluster already has a default StorageClass (e.g. standard-csi), remove the default annotation:
oc annotate storageclass standard-csi storageclass.kubernetes.io/is-default-class-
Verify only gcnv-flex is the default:
oc get storageclass
You should see gcnv-flex (default) in the output.
Step 4: Create the VolumeSnapshotClass
A VolumeSnapshotClass is required for VM snapshot and restore operations.
Create a file named gcnv-csi-snapclass.yaml with the following content:
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
name: gcnv-csi-snapclass
driver: csi.trident.netapp.io
deletionPolicy: Delete
Apply:
oc apply -f gcnv-csi-snapclass.yaml
Step 5: Set the Filesystem Overhead
NFS volumes consume part of their provisioned capacity for filesystem metadata. The recommended filesystem overhead for GCNV is 10%. Without this, CDI may provision PVCs that are too small for operations that need temporary space (e.g. gzipped exports). See This content is not included.ONTAP Volume Space Reporting for details.
Patch the HyperConverged CR to set the overhead for the gcnv-flex StorageClass:
oc patch hyperconverged kubevirt-hyperconverged -n openshift-cnv --type=merge -p '
{
"spec": {
"filesystemOverhead": {
"storageClass": {
"gcnv-flex": "0.10"
}
}
}
}'
Verify CDI picked up the new value:
oc get cdiconfig -o jsonpath='{.items[0].status.filesystemOverhead}'
You should see gcnv-flex listed with 0.10.
Verification
Run through these checks to confirm everything is working:
1. Trident pods are running:
oc get pods -n trident
All pods should be Running.
2. Backend is healthy:
oc get tridentbackendconfig -n trident
Status should show Bound and Success.
3. StorageClass exists and is default:
oc get storageclass gcnv-flex
4. VolumeSnapshotClass exists:
oc get volumesnapshotclass gcnv-csi-snapclass
5. Create a test PVC:
Create a file named gcnv-test-pvc.yaml with the following content:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: gcnv-test-pvc
namespace: default
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi
storageClassName: gcnv-flex
Apply:
oc apply -f gcnv-test-pvc.yaml
Wait for it to bind:
oc get pvc gcnv-test-pvc -n default
Status should be Bound. Clean up:
oc delete pvc gcnv-test-pvc -n default
Quick Reference
| Resource | Name | Purpose |
|---|---|---|
| Namespace | trident | Trident operator and controller pods |
| Secret | trident-admin | GCP service account credentials |
| TridentBackendConfig | gcnv-backend-flex | Connects Trident to GCNV storage pools |
| StorageClass | gcnv-flex | Default StorageClass for VM disks |
| VolumeSnapshotClass | gcnv-csi-snapclass | Enables VM snapshot/restore |
| HyperConverged patch | filesystemOverhead: gcnv-flex: "0.10" | 10% NFS filesystem overhead for CDI |
Key Limitations
For known errors, quotas, and platform-level constraints, see Google Cloud with Google Cloud NetApp Volumes - Known errors and limits.
| Limit | Value | Notes |
|---|---|---|
| Minimum volume size | 1 GiB | Use minimumSupportedPvcSize in StorageProfile |
| Volumes per Flex pool | 50 | Use multiple pools in TridentBackendConfig |
| Volume mode | Filesystem only | No block mode support (NFS backend) |
| Access modes | RWO, RWX, ROX | All in Filesystem mode |
| fstrim / discard | Not supported | NFS does not support TRIM |
External References
- Content from docs.netapp.com is not included.NetApp Trident documentation
- Content from docs.netapp.com is not included.Deploy Trident with the operator
- Content from docs.netapp.com is not included.GCNV backend preparation
- Content from docs.netapp.com is not included.GCNV backend configuration options and examples
- Content from docs.cloud.google.com is not included.GCNV quotas and limits
- Content from docs.cloud.google.com is not included.Create a GCNV storage pool