This guide is a quick-start walkthrough for connecting OpenShift 4.x to Everpure FlashArray over Fibre Channel using Portworx. It covers prerequisite checks, FC host and multipath validation, worker-node MachineConfig setup, Portworx operator and StorageCluster deployment, FlashArray API integration, and end-to-end validation with a StorageClass, PVC, and test workload to confirm the storage path is working properly.
Scope and Assumptions
| Assumption |
Detail |
| OpenShift cluster |
OpenShift 4.x already deployed and healthy. |
|
Nodes
|
Worker nodes are Ready, schedulable, and have physical FC HBAs installed. |
| FlashArray |
Configured and reachable for management. FC target ports are active. |
| FC Fabric |
Dual FC fabrics (Fabric A and Fabric B) are cabled and operational. |
| Zoning |
FC zoning is configured between worker WWPN(s) and FlashArray FC target WWPNs. |
| Access |
cluster-admin rights on OpenShift. Storage admin privileges on FlashArray. |
| Host identity |
Each worker node is uniquely identified by its HBA WWPN(s). |
Pre‑Flight Validation Commands
Run these checks before applying any MachineConfigs or deploying Portworx. These commands confirm prerequisites — they do not configure anything.
Cluster and Node Health (from any oc client)
# The below command check overall cluster operators & all operators should show Available=True, Degraded=False
oc get co
# The below command check overall and their status & all participating worker nodes should show Ready
oc get nodes
Management Connectivity to FlashArray (from a worker or bastion)
# Enter a node through debug mode to check connectivity
oc get nodes
oc debug node/<worker-node-name>
# enter host binaries
chroot /host
# Basic reachability (if ICMP is permitted)
ping <flasharray-mgmt-ip>
# TCP reachability on management port 443
socat connects and hangs on success; errors indicate unreachable
socat - TCP:<flasharray-mgmt-ip>:443
FC Pre-Flight
# Enter a node through debug mode to check connectivity
oc get nodes
oc debug node/<worker-node-name>
# enter host binaries
chroot /host
## Confirm FC HBAs are visible to the OS
ls /sys/class/fc_host
# Expected: host0 host1
# host object creation
# Check fabric login state — must show logged in
cat /sys/class/fc_host/host*/symbolic_name
fnic v1.8.0.2 over fnic0
fnic v1.8.0.2 over fnic1
# Confirm multipathd is running
systemctl status multipathd
- Connecting OpenShift Workers to FlashArray
Worker Node Expectations
Basic connectivity verification can be performed from any worker node once the FlashArray has been configured with host objects, zoning is active, and volumes are connected to the host group.
- Verify multipath devices : multipath -ll
Example Output:
3624a937054f3fecfb2834edc09d7f042 dm-1 PURE,FlashArray
size=1.0T features='0' hwhandler='1 alua' wp=rw
`-+- policy='service-time 0' prio=50 status=active
|- 0:0:33:1 sda 8:0 active ready running
|- 0:0:35:1 sde 8:64 active ready running
|- 1:0:36:1 sdk 8:160 active ready running
`- 1:0:9:1 sdi 8:128 active ready running
- MachineConfig: Configure Transport Protocol
FC MachineConfig
In the OpenShift web console:
- Go to Compute > MachineConfigs
- Click Create MachineConfig
- Switch to YAML view
- Paste the MachineConfig
{
user_friendly_names no
polling_interval 10
find_multipaths yes
}
devices {
device {
vendor "PURE"
product "FlashArray"
path_selector "service-time 0"
hardware_handler "1 alua"
path_grouping_policy group_by_prio
prio alua
failback immediate
path_checker tur
user_friendly_names no
no_path_retry 0
features 0
dev_loss_tmo 600
}
}
blacklist_exceptions {
property "(SCSI_IDENT_|ID_WWN)"
}
blacklist {
devnode "^pxd[0-9]*"
devnode "^pxd*"
}
This is the encoded text below. It has been urlencoded, other encoding methods such as base64 can be used.
apiVersion: machineconfiguration.openshift.io/v1
kind: MachineConfig
metadata:
name: 99-worker-fc-pure
labels:
machineconfiguration.openshift.io/role: worker
spec:
config:
ignition:
version: 3.2.0
storage:
files:
# /etc/multipath.conf tuned for Pure FlashArray (SCSI-FC)
- path: /etc/multipath.conf
mode: 0644
overwrite: true
contents:
source: data:,defaults%20%7B%0A%20%20%20%20user_friendly_names%20no%0A%20%20%20%20polling_interval%2010%0A%20%20%20%20find_multipaths%20yes%0A%7D%0Adevices%20%7B%0A%20%20%20%20device%20%7B%0A%20%20%20%20%20%20%20%20vendor%20%22PURE%22%0A%20%20%20%20%20%20%20%20product%20%22FlashArray%22%0A%20%20%20%20%20%20%20%20path_selector%20%22service-time%200%22%0A%20%20%20%20%20%20%20%20hardware_handler%20%221%20alua%22%0A%20%20%20%20%20%20%20%20path_grouping_policy%20group_by_prio%0A%20%20%20%20%20%20%20%20prio%20alua%0A%20%20%20%20%20%20%20%20failback%20immediate%0A%20%20%20%20%20%20%20%20path_checker%20tur%0A%20%20%20%20%20%20%20%20user_friendly_names%20no%0A%20%20%20%20%20%20%20%20no_path_retry%200%0A%20%20%20%20%20%20%20%20features%200%0A%20%20%20%20%20%20%20%20dev_loss_tmo%20600%0A%20%20%20%20%7D%0A%7D%0Ablacklist_exceptions%20%7B%0A%20%20%20%20property%20%22(SCSI_IDENT_%7CID_WWN)%22%0A%7D%0Ablacklist%20%7B%0A%20%20%20%20devnode%20%22%5Epxd%5B0-9%5D*%22%0A%20%20%20%20devnode%20%22%5Epxd*%22%0A%7D
# Optional: udev rules for Pure FlashArray SCSI devices
- path: /etc/udev/rules.d/99-pure-storage-fc.rules
mode: 0644
overwrite: true
contents:
source: data:,ACTION%3D%3D%22add%7Cchange%22%2C%20KERNEL%3D%3D%22sd*%5B!0-9%5D%22%2C%20SUBSYSTEM%3D%3D%22block%22%2C%20ENV%7BID_VENDOR%7D%3D%3D%22PURE%22%2C%20OPTIONS%3D%22nowatch%22%2C%20ATTR%7Bqueue%2Fscheduler%7D%3D%22none%22
systemd:
units:
- name: multipathd.service
enabled: true
- Click Create
- Validation
Expected output — all columns should reflect consistent counts with UPDATED=True, DEGRADED=False:
C:\oc>oc get mcp worker
NAME CONFIG UPDATED UPDATING DEGRADED MACHINECOUN READYMACHINECOUNT UPDATEDMACHINECOUNT DEGRADEDMACHINECOUNT AGE
worker rendered-worker-9bff717bea674e806f07303ab142f402 True False False 3 3 3 0 35d
- Verify MachineConfig in the GUI
Go to
Compute >
MachineConfigPools > worker and confirm the pool returns to a healthy state with:
-
Updated = True
-
Updating = False
-
Degraded = False
- Installing the Portworx Operator
- Create a dedicated namespace to host the Portworx Operator and cluster components.
In the OpenShift web console:
-
Go to Home > Projects
-
Click Create Project
-
Enter portworx
-
Click Create
- Install from the OpenShift UI
For current OpenShift versions, use Ecosystem > Software Catalog; older versions use OperatorHub.
-
Go to Ecosystem > Software Catalog
-
Search for Portworx Operator or Portworx Certified
-
Open the operator page and click Install
-
Choose the target namespace
-
Optionally Enable the Console plugin if you want Portworx management integrated into the OpenShift console
-
Complete the installation
-
Find Portworx in Software Catalogue
-
Navigate to Ecosystem → Software Catalogue, search for Portworx, and locate the Portworx Certified tile, which is the supported production operator from the Red Hat catalog
- Install the Operator
Click the Portworx Certified tile to open the detail page. Review the description and supported versions, then click Install.On the installation options screen, confirm the namespace is set to openshift-operators and Install Mode is set to All namespaces. Leave Install Plan Approval as Automatic.
- Confirm Operator Status
Confirm the Portworx Certified operator shows Status: Succeeded. This confirms the operator is installed and its CRDs are registered.

- Verify Pods Status
- Verify Operator Pod and CRDs
After a short time, verify that the Operator is up and that the necessary CRDs have been registered.
Check Operator Pod Status:
# List Portworx operator pods in the cluster-wide operator namespace
oc get pods -n openshift-operators | grep portworx
You should see something similar to:
portworx-operator-c95c9b4d4-fhjqx 1/1 Running 1 (37d ago) 37d
If the pod is not Running, inspect the logs:
oc logs -n openshift-operators deploy/portworx-operator
Resolve any issues before you continue.
- Verify CRDs (StorageCluster and Related Types)
Confirm the StorageCluster CRD is present:
oc get crd | grep storagecluster
purestorageclusters.core.libopenstorage.org 2026-03-10T20:44:51Z
storageclusters.core.libopenstorage.org 2026-03-10T20:44:31Z
- Integrating Portworx with FlashArray
- Create a dedicated user with storage admin privileges and generate an API token. Navigate to Settings > Access > Users, create a user (e.g. px-portworx), assign the Storage Admin role
- Copy & store the API token
- Create a pure.json file containing:
- Next, store the pure.json file in a Kubernetes secret that Portworx can read. This secret must be created in the same namespace where your StorageCluster will live (for example, portworx)
From your workstation:
oc create secret generic px-pure-secret -n portworx --from-file=pure.json=./pure.json
- Deploy StorageCluster for Everpure FlashArray
- Open Portworx Central
- Start the Generate Spec workflow
- Choose:
- After the operator is installed successfully, navigate to Operators > Installed Operators > Portworx
- Select Create StorageCluster
- Toggle to the YAML view
- Paste the spec that was generated
- Finalize by clicking Create
kind: StorageCluster
apiVersion: core.libopenstorage.org/v1
metadata:
name: px-cluster-80d8e0d4-7151-4f65-bf98-918559edc5f3
namespace: portworx
annotations:
portworx.io/install-source: "https://install.portworx.com/26.1?oem=px-csi&operator=true&ce=pure&csi=true&stork=false&mon=true&promop=true&kbver=1.34.5&ns=portworx&osft=true&c=px-cluster-80d8e0d4-7151-4f65-bf98-918559edc5f3&pureSanType=FC&tel=true"
portworx.io/is-openshift: "true"
portworx.io/misc-args: "--oem px-csi"
spec:
image: portworx/px-pure-csi-driver:26.1.2
imagePullPolicy: Always
csi:
enabled: true
monitoring:
telemetry:
enabled: true
prometheus:
enabled: true
exportMetrics: true
env:
- name: PURE_FLASHARRAY_SAN_TYPE
value: "FC"
- To Apply and Monitor, go to Operators > Installed Operators > Portworx in the GUI
- Open the Storage Cluster tab
- Confirm the cluster progresses to a healthy state
- Check the
StorageCluster status:
oc get storagecluster -n portworx
- Then, monitor Portworx pods:
- If pods are not progressing to Running:
Check Operator logs:
oc logs -n openshift-operators deploy/portworx-operator
Check an individual Portworx pod's logs:
oc logs -n portworx <portworx-pod-name>
Do not proceed to creating StorageClasses or PVCs until the StorageCluster is healthy and all Portworx pods in portworx namespace are in Running state.
- Validation with OpenShift Virtualization
- Create a Portworx + FlashArray StorageClass, in the OpenShift web console: go to Storage > StorageClasses
- Click Create StorageClass
- Switch to YAML view
- Paste the StorageClass configuration below
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: px-pure-fc-sc
annotations:
storageclass.kubernetes.io/is-default-class: "true"
provisioner: pxd.portworx.com
parameters:
backend: pure_block
allowVolumeExpansi�on: true

- Verify:
oc get storageclass
Output:
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE px-pure-fc-sc (default) pxd.portworx.com Delete Immediate true 50d
�
- Deploy a VM Using the FlashArray StorageClass
- In the OpenShift GUI, go to Home > Projects
- Click Create Project
- Enter px-test
- Click Create
- Create a PVC using the Portworx + FlashArray StorageClass, navigate to Storage > PersistentVolumeClaims
- Switch to the px-test project
- Click Create PersistentVolumeClaim
- Configure the following settings:
- Click Create
- Use YAML:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: px-test-pvc
namespace: px-test
spec:
accessModes:
- ReadWriteOnce
storageClassName: px-pure-fc-sc
resources:
requests:
storage: 5Gi
oc apply -f px-test-pvc.yaml
oc get pvc px-test-pvc -n px-test
Validation
C:\oc>oc get pvc px-test-pvc -n px-test
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
px-test-pvc Bound pvc-4c04e712-f9ba-481c-b5f7-19e43372b4d8 5Gi RWO px-pure-fc-sc <unset> 6m28s
- Create a simple pod that mounts it and runs I/O, in the OpenShift web console go to Workloads > Pods
- Click Create Pod
- Switch to YAML view
- Paste the configuration below
apiVersion: v1
kind: Pod
metadata:
name: px-test-pod
namespace: px-test
spec:
containers:
- name: app
image: registry.access.redhat.com/ubi9/ubi-minimal
command: ["sleep", "3600"]
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
persistentVolumeClaim:
claimName: px-test-pvc
- Click Create
C:\oc>oc get pod px-test-pod -n px-test
NAME READY STATUS RESTARTS AGE
px-test-pod 1/1 Running 0 29s
Key Commands Cheat Sheet
| Command |
Purpose |
| oc get co |
Check cluster operator health |
| oc get nodes |
List nodes and readiness status |
| ls /sys/class/fc_host |
Confirm FC HBAs visible to OS |
| cat /sys/class/fc_host/host*/port_name |
Display HBA WWPNs |
| systemctl status multipathd |
Verify multipath daemon is active |
| multipath -ll |
List active multipath devices |
| oc get mcp worker |
Monitor MachineConfig rollout |
| oc get storagecluster -n portworx |
Check Portworx StorageCluster status |
| oc get pods -n portworx |
List all Portworx pods |
| oc get storageclass |
List registered StorageClasses |
| oc get pvc -n px-test |
Check PVC binding status |
Troubleshooting Guide
| Symptom |
Likely Cause |
Resolution |
| multipath -ll shows no Pure devices |
FC zoning not active or HBA not logged in |
Check /sys/class/fc_host/host*/port_state and verify zoning |
| MCP worker stuck Updating |
Node drain or reboot issue |
Inspect oc describe mcp worker and individual node events |
| Portworx pod CrashLoopBackOff |
px-pure-secret missing or malformed |
Verify oc get secret px-pure-secret -n portworx and review pod logs |
| PVC stuck in Pending |
StorageCluster not healthy |
Check oc get storagecluster -n portworx and resolve errors first |
| No FC paths in multipath -ll |
HBA not logged into fabric |
Check symbolic_name and port_state in /sys/class/fc_host |