Add Portworx CSI driver for Pure Storage FlashArray

- Deploy Portworx Operator + CSI driver via ArgoCD
- Support both iSCSI block and NFS file storage from FlashArray
- Integrate with 1Password External Secrets for FlashArray credentials
- Include comprehensive deployment documentation and validation script
- Storage classes: pure-block (iSCSI) and pure-file (NFS)
- Talos Linux compatible with iSCSI/multipath configuration
This commit is contained in:
Hermes Agent service account
2026-06-18 23:08:23 -05:00
parent a4a68eeb5a
commit 459dbc5d18
13 changed files with 2694 additions and 0 deletions

View File

@@ -0,0 +1,466 @@
# Portworx CSI Deployment Checklist
Pre-deployment checklist for Portworx CSI driver on Talos Linux with Pure Storage FlashArray.
## Phase 1: FlashArray Preparation
- [ ] **Create FlashArray storage admin user**
- Username: `portworx-csi`
- Role: Storage Admin
- Password: Set in FlashArray UI
- [ ] **Generate FlashArray API token**
- User: `portworx-csi`
- Expiration: None (non-expiring)
- Token format: `XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX`
- **Save token immediately** (cannot be retrieved later)
- [ ] **Verify FlashArray management endpoint**
- Test connectivity: `ping flasharray.mk-labs.cloud`
- Test HTTPS: `curl -k https://flasharray.mk-labs.cloud`
- Record IP/hostname: _______________________
- [ ] **Configure iSCSI targets on FlashArray**
- Navigate to: **Settings → Network**
- Verify iSCSI interfaces are enabled
- Test discovery from Talos node:
```bash
talosctl -n <node> exec -- iscsiadm -m discovery -t st -p <flasharray-ip>
```
- [ ] **(Optional) Enable FlashArray File Services for NFS**
- Enable File Services: **Settings → File Services**
- Create filesystem: `fastpass-nfs`
- Create NFS policy with user mapping **disabled**
- Record NFS endpoint: _______________________
## Phase 2: 1Password Secret Configuration
- [ ] **Create 1Password item**
- Vault: `homelab`
- Item name: `pure-flasharray-fastpass`
- Category: Secure Note or API Credential
- [ ] **Add pure.json field to 1Password item**
- Field name: `pure.json`
- Field type: Text
- Content format: JSON (see below)
- [ ] **Populate pure.json content**
```json
{
"FlashArrays": [
{
"MgmtEndPoint": "flasharray.mk-labs.cloud",
"APIToken": "paste-api-token-here",
"NFSEndPoint": "flasharray-nfs.mk-labs.cloud"
}
]
}
```
- Replace `flasharray.mk-labs.cloud` with actual endpoint
- Replace `paste-api-token-here` with FlashArray API token
- Remove `NFSEndPoint` line if not using File Services
- [ ] **Validate JSON syntax**
```bash
# Copy content from 1Password and validate
echo '<paste-json>' | jq .
```
- [ ] **Verify 1Password Connect can access item**
```bash
# From a pod with op CLI or via 1Password UI
# Confirm item exists in homelab vault
```
## Phase 3: Talos Node Configuration
- [ ] **Edit talconfig.yaml**
- File: `~/git/homelab/talos/talhelper/talconfig.yaml`
- Add patches from `cluster/platform/portworx-csi/talos-config-reference.yaml`
- Sections to add:
- [ ] System extensions (iscsi-tools, util-linux-tools)
- [ ] Kernel modules (iscsi_tcp, dm_multipath, dm_round_robin)
- [ ] /etc/multipath.conf file
- [ ] /etc/udev/rules.d/99-pure-storage.rules file
- [ ] kubelet extraMounts for /var/lib/iscsi
- [ ] **Generate updated Talos configs**
```bash
cd ~/git/homelab/talos/talhelper
talhelper genconfig
```
- [ ] **Apply Talos configuration to all worker nodes**
```bash
# For each worker node:
talosctl apply-config \
--file clusterconfig/<node-name>.yaml \
--nodes <node-ip>
```
Nodes:
- [ ] Node 1: _________________ (IP: _____________)
- [ ] Node 2: _________________ (IP: _____________)
- [ ] Node 3: _________________ (IP: _____________)
- [ ] **Reboot all worker nodes**
```bash
# Reboot nodes one at a time to load kernel modules
talosctl reboot --nodes <node-ip>
# Wait for node to come back online
kubectl get nodes
```
- [ ] **Verify iSCSI initiator on each node**
```bash
talosctl -n <node-ip> get service iscsid
# Expected: iscsid service running
```
- [ ] **Verify multipath on each node**
```bash
talosctl -n <node-ip> exec -- multipath -ll
# Expected: multipath running (may show no paths yet)
```
- [ ] **Verify unique iSCSI initiator names**
```bash
# For each node:
talosctl -n <node-ip> read /etc/iscsi/initiatorname.iscsi
# Record initiator names (must be unique):
# Node 1: iqn.1994-05.com.redhat:_______________
# Node 2: iqn.1994-05.com.redhat:_______________
# Node 3: iqn.1994-05.com.redhat:_______________
```
- [ ] **Verify kernel modules loaded**
```bash
talosctl -n <node-ip> exec -- lsmod | grep -E "iscsi|dm_multipath"
# Expected: iscsi_tcp, dm_multipath, dm_round_robin
```
- [ ] **Test iSCSI discovery from each node**
```bash
talosctl -n <node-ip> exec -- \
iscsiadm -m discovery -t st -p <flasharray-ip>
# Expected: List of iSCSI targets from FlashArray
```
## Phase 4: GitOps Deployment
- [ ] **Review manifests**
- [ ] `cluster/platform/portworx-csi/application.yaml`
- [ ] `cluster/platform/portworx-csi/operator-values.yaml`
- [ ] `cluster/platform/portworx-csi/storagecluster.yaml`
- [ ] `cluster/platform/portworx-csi/externalsecret.yaml`
- [ ] `cluster/platform/portworx-csi/storageclass-block.yaml`
- [ ] `cluster/platform/portworx-csi/storageclass-file.yaml`
- [ ] **Customize for your environment**
- Update FlashArray endpoints if different from defaults
- Adjust resource limits if needed
- Review sync wave (currently: 2)
- [ ] **Commit to Git**
```bash
cd ~/git/homelab
git add cluster/platform/portworx-csi/
git commit -m "Add Portworx CSI driver for Pure FlashArray"
git push origin main
```
- [ ] **Verify ArgoCD auto-sync or trigger manual sync**
```bash
# Check ArgoCD application status
kubectl get application -n argocd portworx-csi
# Manual sync if needed
argocd app sync portworx-csi
```
## Phase 5: Deployment Verification
- [ ] **Verify ArgoCD application is healthy**
```bash
kubectl get application -n argocd portworx-csi
# Expected: STATUS=Synced, HEALTH=Healthy
```
- [ ] **Check namespace created**
```bash
kubectl get namespace portworx
```
- [ ] **Verify ExternalSecret synced**
```bash
kubectl get externalsecret -n portworx px-pure-secret
# Expected: STATUS=SecretSynced
kubectl get secret -n portworx px-pure-secret
# Expected: Secret exists with pure.json key
```
- [ ] **Validate secret content**
```bash
kubectl get secret -n portworx px-pure-secret \
-o jsonpath='{.data.pure\.json}' | base64 -d | jq .
# Expected: Valid JSON with FlashArray config
```
- [ ] **Check Portworx Operator deployed**
```bash
kubectl get deployment -n portworx portworx-operator
kubectl get pods -n portworx -l app=portworx-operator
# Expected: 1/1 pods running
```
- [ ] **Verify StorageCluster created**
```bash
kubectl get storagecluster -n portworx px-cluster-fastpass
# Expected: STATUS=Running or Initializing
```
- [ ] **Check PX-CSI pods running**
```bash
kubectl get pods -n portworx
# Expected pods:
# - portworx-operator-...
# - px-csi-controller-...
# - px-csi-node-... (one per node)
```
- [ ] **Verify CSI driver registered**
```bash
kubectl get csidrivers
# Expected: pxd.portworx.com
kubectl get csinode
# Expected: One CSINode per Kubernetes node
```
- [ ] **Check StorageClasses created**
```bash
kubectl get storageclass pure-block pure-file
# Expected: Both StorageClasses exist
```
- [ ] **Review PX-CSI logs for errors**
```bash
# Controller logs
kubectl logs -n portworx -l app=px-csi-controller --tail=50
# Node driver logs (on each node)
kubectl logs -n portworx -l app=px-csi-node --tail=50
```
## Phase 6: Functional Testing
- [ ] **Create test PVC with block storage**
```bash
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: test-pure-block
namespace: default
spec:
accessModes:
- ReadWriteOnce
storageClassName: pure-block
resources:
requests:
storage: 1Gi
EOF
```
- [ ] **Verify PVC bound**
```bash
kubectl get pvc test-pure-block
# Expected: STATUS=Bound
```
- [ ] **Verify PV created on FlashArray**
```bash
kubectl get pv
# Look for PV bound to test-pure-block
# Check FlashArray UI or API:
# Volumes should show new volume created
```
- [ ] **Create test pod using PVC**
```bash
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: test-pure-block-pod
namespace: default
spec:
containers:
- name: test
image: nginx:latest
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
persistentVolumeClaim:
claimName: test-pure-block
EOF
```
- [ ] **Verify pod is running**
```bash
kubectl get pod test-pure-block-pod
# Expected: STATUS=Running
```
- [ ] **Verify volume mounted in pod**
```bash
kubectl exec test-pure-block-pod -- df -h /data
# Expected: Mount point shows 1Gi volume
```
- [ ] **Test write to volume**
```bash
kubectl exec test-pure-block-pod -- \
sh -c 'echo "test data" > /data/test.txt'
kubectl exec test-pure-block-pod -- cat /data/test.txt
# Expected: "test data"
```
- [ ] **Verify iSCSI session established**
```bash
# On node running test pod
talosctl -n <node-ip> exec -- iscsiadm -m session
# Expected: Active iSCSI session to FlashArray
```
- [ ] **Clean up test resources**
```bash
kubectl delete pod test-pure-block-pod
kubectl delete pvc test-pure-block
```
- [ ] **(Optional) Test NFS file storage**
- Repeat above steps with `storageClassName: pure-file`
- Verify NFS export created on FlashArray
## Phase 7: Monitoring Setup
- [ ] **Verify Prometheus ServiceMonitor created**
```bash
kubectl get servicemonitor -n portworx
```
- [ ] **Check Prometheus targets**
- Navigate to Prometheus UI → Targets
- Look for `portworx` or `px-csi` targets
- Status should be UP
- [ ] **Query basic metrics**
```promql
# In Prometheus UI
portworx_cluster_status
portworx_volume_capacity_bytes
```
- [ ] **(Optional) Create Grafana dashboard**
- Import Portworx dashboard from Grafana.com
- Or create custom dashboard
## Phase 8: Documentation & Handoff
- [ ] **Update homelab documentation**
- Add FlashArray details to infrastructure docs
- Document storage classes and use cases
- [ ] **Record credentials securely**
- FlashArray management URL: ___________________
- API token stored in: 1Password → homelab → pure-flasharray-fastpass
- Portworx namespace: `portworx`
- [ ] **Create runbook for common tasks**
- Volume expansion procedure
- Snapshot creation/restore
- Troubleshooting steps
- [ ] **Schedule follow-up review**
- Date: _______________
- Review metrics and performance
- Adjust resource limits if needed
## Rollback Plan
If deployment fails, rollback procedure:
1. [ ] Delete ArgoCD application:
```bash
kubectl delete application -n argocd portworx-csi
```
2. [ ] Delete namespace (if needed):
```bash
kubectl delete namespace portworx
```
3. [ ] Delete StorageClasses:
```bash
kubectl delete storageclass pure-block pure-file
```
4. [ ] Delete CRDs (if needed):
```bash
kubectl delete crd storageclusters.core.libopenstorage.org
```
5. [ ] Revert Talos configuration (if needed):
```bash
# Remove portworx-csi patches from talconfig.yaml
talhelper genconfig
talosctl apply-config --file clusterconfig/<node>.yaml --nodes <node-ip>
```
## Success Criteria
Deployment is successful when:
- [ ] All pods in `portworx` namespace are Running
- [ ] StorageClasses `pure-block` and `pure-file` are available
- [ ] Test PVC successfully binds to a PV
- [ ] Test pod can mount and write to volume
- [ ] iSCSI sessions are established on nodes
- [ ] No errors in PX-CSI controller/node logs
- [ ] Prometheus metrics are being scraped
- [ ] ArgoCD application shows Healthy and Synced
## Notes
**Deployment Date:** _______________
**Deployed By:** _______________
**FlashArray Model:** _______________
**Purity Version:** _______________
**Issues Encountered:**
-
-
-
**Resolutions:**
-
-
-
**Follow-up Items:**
-
-
-