Tech ONTAP Blogs

Exploring Trident Support on the NetApp AFX Platform

hnikhil
NetApp
26 Views

Introducing the NetApp AFX Systems

Before we begin, Let's explore what NetApp AFX systems are and gain a high-level understanding of what they provide. AFX systems, which include the NetApp AFX 1K model, delivers a unified hardware and software solution that creates a simplified experience specific to the needs of high-performance NAS and S3 customers. One of the key differentiators of the AFX systems is their disaggregated architecture. Unlike traditional systems, they don’t expose the concept of aggregates to the user. The performance and scalability are specifically designed to meet the requirements of AI and ML workloads. AFX provides a simplified user experience enabling it to be administered by both storage specialists and non-specialists.

 

NetApp Trident and CSI integration

To enable integration with AFX systems, NetApp Tridentsoftware, NetApp's Container Storage Interface (CSI)–compliant storage orchestrator, now supports provisioning file mode storage using the NFS protocol starting with its 25.10 release. The best part is that if you’re an existing Trident customer, you can seamlessly transition to using AFX systems with minimal changes. All you need to do is provide the right credentials in the Trident backend, and everything else is dynamically determined.

 

Simple provisioning process

Whether you’re a new Trident user or an existing one, the process of provisioning storage with Trident is straightforward. Here are the simple steps.

Note: For existing Trident users, Please upgrade Trident to 25.10. Please find the steps to upgrade Trident here.

 

  • Step 1: Create a Trident backend. Start by creating a Trident backend with the storage driver ontap-nas. You can do this either by configuring the TridentBackendConfig (TBC) custom resource definition using the Kubernetes-native approach or by using a custom JSON file with tridentctl, a command-line utility for managing Trident. The configuration is similar to any other ontap-nas NFS backend, with the only changes being the user name and password. You can either use cluster management IP with administrator credentials or specify a specific a storage virtual machine (SVM) with its management IP and credentials. For more information, please refer to this document.
     # Kubernetes secret required for creating Trident backend from TBC
    [root@scs000887790-1 afx]# cat secret.yaml 
    apiVersion: v1
    kind: Secret
    metadata:
      name: afx-secret
      namespace: trident
    type: Opaque
    stringData:
      username: <username>
      password: <password>
    
    [root@scs000887790-1 afx]# kubectl create -f secret.yaml 
    secret/afx-secret created
    
    [root@scs000887790-1 afx]# kubectl get secret afx-secret -n trident
    NAME         TYPE     DATA   AGE
    afx-secret   Opaque   2      20s
    
    # Kubernetes CR TridentBackendConfig (TBC)
    [root@scs000887790-1 afx]# cat tbc.yaml 
    apiVersion: trident.netapp.io/v1
    kind: TridentBackendConfig
    metadata:
      name: afx-backend-tbc
      namespace: trident
    spec:
      version: 1
      backendName: afx-backend
      storageDriverName: ontap-nas
      managementLIF: 1.1.1.1
      svm: svm0
      credentials:
        name: afx-secret
    
    # Or, Trident backend json
    [root@scs000887790-1 afx]# cat backend.json 
    {
        "version": 1,
        "storageDriverName": "ontap-nas",
        "managementLIF": "1.1.1.1",
        "backendName": "afx-backend",
        "svm": "svm0",
        "username": "<username>",
        "password": "<password>"
    }
    
    # Create Trident Backend via kubectl
    [root@scs000887790-1 afx]# kubectl create -f tbc.yaml 
    tridentbackendconfig.trident.netapp.io/afx-backend-tbc created
    
    [root@scs000887790-1 afx]# kubectl get tbc afx-backend-tbc -n trident
    NAME              BACKEND NAME   BACKEND UUID                           PHASE   STATUS
    afx-backend-tbc   afx-backend    abf2df43-5789-41b0-9b36-d0c1b1660a00   Bound   Success
    
    [root@scs000887790-1 afx]# tridentctl get backend afx-backend -n trident
    +-------------+----------------+--------------------------------------+--------+------------+---------+
    |    NAME     | STORAGE DRIVER |                 UUID                 | STATE  | USER-STATE | VOLUMES |
    +-------------+----------------+--------------------------------------+--------+------------+---------+
    | afx-backend | ontap-nas      | abf2df43-5789-41b0-9b36-d0c1b1660a00 | online | normal     |       0 |
    +-------------+----------------+--------------------------------------+--------+------------+---------+
    
    # Or, create Trident Backend via tridentctl
    [root@scs000887790-1 afx]# tridentctl -n trident create backend -f backend.json 
    +-------------+----------------+--------------------------------------+--------+------------+---------+
    |    NAME     | STORAGE DRIVER |                 UUID                 | STATE  | USER-STATE | VOLUMES |
    +-------------+----------------+--------------------------------------+--------+------------+---------+
    | afx-backend | ontap-nas      | 66abe907-92c3-4958-99bf-1d5d1856a9bc | online | normal     |       0 |
    +-------------+----------------+--------------------------------------+--------+------------+---------+

  • Step 2: Define a storage class. Create a storage class that corresponds to the type of storage driver you require. This step allows you to define the characteristics of the storage you want to dynamically provision.
    [root@scs000887790-1 afx]# cat sc.yaml 
    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: afx-sc
    parameters:
      backendType: ontap-nas
      storagePools: "afx-backend:.*"
    provisioner: csi.trident.netapp.io
    
    [root@scs000887790-1 afx]# kubectl create -f sc.yaml 
    storageclass.storage.k8s.io/afx-sc created
    
    [root@scs000887790-1 afx]# kubectl get sc afx-sc
    NAME     PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
    afx-sc   csi.trident.netapp.io   Delete          Immediate           false                  12s

    Now that everything is ready for dynamic provisioning of storage on the AFX system, let's see an example of how to use it.

  • Step 3: Create a PVC. Define a PersistentVolumeClaim (PVC) that specifies the amount of storage you need and references the appropriate storage class. This step ensures that your Kubernetes application has access to the required block storage.
    [root@scs000887790-1 afx]# cat pvc.yaml 
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: afx-pvc
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 1Gi
      storageClassName: afx-sc
    
    [root@scs000887790-1 afx]# kubectl create -f pvc.yaml 
    persistentvolumeclaim/afx-pvc created

     

    Step 4: Confirm PVC binding. After the PVC is created, verify that it’s successfully bound to a persistent volume (PV). This confirmation ensures that the file storage is ready for use by your applications.

    [root@scs000887790-1 afx]# kubectl get pvc afx-pvc
    NAME      STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
    afx-pvc   Bound    pvc-0369d050-3229-43fe-8f46-a75bc25acf29   1Gi        RWO            afx-sc         <unset>                 24s


    Step 5: Use the PVC.
    Congratulations! You’re now ready to use the PVC in any pod of your choice. Mount the PVC in your pod's specification, and your application will have seamless access to the high-performance file storage provided by the AFX systems using NFS protocol.

    [root@scs000887790-1 afx]# cat pod.yaml 
    apiVersion: v1
    kind: Pod
    metadata:
      name: afx-pod
    spec:
      containers:
      - image: nginx:alpine
        name: nginx
        volumeMounts:
        - mountPath: mnt/pvc
          name: local-storage
      nodeSelector:
        kubernetes.io/arch: amd64
        kubernetes.io/os: linux
      volumes:
      - name: local-storage
        persistentVolumeClaim:
          claimName: afx-pvc
    
    [root@scs000887790-1 afx]# kubectl create -f pod.yaml 
    pod/afx-pod created
    
    [root@scs000887790-1 afx]# kubectl get pod afx-pod
    NAME      READY   STATUS    RESTARTS   AGE
    afx-pod   1/1     Running   0          10s
    
    [root@scs000887790-1 afx]# kubectl exec -it afx-pod -- /bin/ash -c "df -H /mnt/pvc"
    Filesystem                Size      Used Available Use% Mounted on
    2.2.2.2:/trident_pvc_0369d050_3229_43fe_8f46_a75bc25acf29
                              1.0G    320.0K   1023.7M   0% /mnt/pvc

 

Troubleshooting made easy

If you encounter any issues, we've got you covered with some handy commands for troubleshooting. Use kubectl describe on the problematic resource to gather detailed information. For more insights into the system's behavior, you can check the Trident logs by using kubectl or tridentctl.

[root@scs000887790-1 afx]# kubectl get pvc afx-pvc
NAME      STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
afx-pvc   Bound    pvc-0369d050-3229-43fe-8f46-a75bc25acf29   1Gi        RWO            afx-sc         <unset>                 11m

[root@scs000887790-1 afx]# kubectl describe pvc afx-pvc
Name:          afx-pvc
Namespace:     default
StorageClass:  afx-sc
Status:        Bound
Volume:        pvc-0369d050-3229-43fe-8f46-a75bc25acf29
Labels:        <none>
Annotations:   pv.kubernetes.io/bind-completed: yes
               pv.kubernetes.io/bound-by-controller: yes
               volume.beta.kubernetes.io/storage-provisioner: csi.trident.netapp.io
               volume.kubernetes.io/storage-provisioner: csi.trident.netapp.io
Finalizers:    [kubernetes.io/pvc-protection]
Capacity:      1Gi
Access Modes:  RWO
VolumeMode:    Filesystem
Used By:       afx-pod
Events:
  Type    Reason                 Age                From                                                                                            Message
  ----    ------                 ----               ----                                                                                            -------
  Normal  Provisioning           12m                csi.trident.netapp.io_trident-controller-5c487b5b6b-92k5l_130f1ac0-75c2-41be-b0e6-45908828c6b3  External provisioner is provisioning volume for claim "default/afx-pvc"
  Normal  ExternalProvisioning   12m (x3 over 12m)  persistentvolume-controller                                                                     Waiting for a volume to be created either by the external provisioner 'csi.trident.netapp.io' or manually by the system administrator. If volume creation is delayed, please verify that the provisioner is running and correctly registered.
  Normal  ProvisioningSuccess    12m                csi.trident.netapp.io                                                                           provisioned a volume
  Normal  ProvisioningSucceeded  12m                csi.trident.netapp.io_trident-controller-5c487b5b6b-92k5l_130f1ac0-75c2-41be-b0e6-45908828c6b3  Successfully provisioned volume pvc-0369d050-3229-43fe-8f46-a75bc25acf29

[root@scs000887790-1 afx]# kubectl get pod -n trident
NAME                                  READY   STATUS    RESTARTS   AGE
trident-controller-5c487b5b6b-92k5l   6/6     Running   0          40m
trident-node-linux-8xfnz              2/2     Running   0          40m
trident-node-linux-pxqn9              2/2     Running   0          40m
trident-node-linux-rq9gc              2/2     Running   0          40m

[root@scs000887790-1 afx]# kubectl logs trident-controller-5c487b5b6b-92k5l -n trident
Defaulted container "trident-main" out of: trident-main, trident-autosupport, csi-provisioner, csi-attacher, csi-resizer, csi-snapshotter


[root@scs000887790-1 afx]# tridentctl -n trident logs
trident-controller log:
time="2025-11-07T06:12:00Z" level=debug msg=Environment PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
time="2025-11-07T06:12:00Z" level=debug msg=Environment HOSTNAME=trident-controller-5c487b5b6b-92k5l

 

Conclusion

NetApp AFX storage system stands out as a versatile and powerful solution for modern data management needs. Its disaggregated hardware and software architecture is specifically tailored to support high-performance NAS environments, ensuring optimal performance and scalability for AI and ML workloads. This makes AFX an ideal choice for Kubernetes deployments, where the demands of AI and ML applications require robust and efficient storage solutions. Happy configuring, and may your Kubernetes journey be smooth and successful.

Public