From 33aced03a0f6517018f1dd531bee7d977e046e8e Mon Sep 17 00:00:00 2001 From: xguefer Date: Tue, 26 Aug 2025 22:00:11 +0200 Subject: [PATCH] =?UTF-8?q?a=C3=B1adido=20driver=20seagate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kubectl | 0 seagate/csi-exos-x-csidriver.yaml | 13 ++ seagate/namespace.yaml | 6 + seagate/pod-a.yaml | 18 ++ seagate/pvc-pod-a.yaml | 8 + seagate/readme.md | 316 ++++++++++++++++++++++++++++++ seagate/sc-me5-site-a.yaml | 22 +++ seagate/sc-me5-site-b.yaml | 22 +++ seagate/secret-me5-site-a.yaml | 10 + seagate/secret-me5-site-b.yaml | 10 + seagate/values.yaml | 64 ++++++ 11 files changed, 489 insertions(+) delete mode 100644 kubectl create mode 100644 seagate/csi-exos-x-csidriver.yaml create mode 100644 seagate/namespace.yaml create mode 100644 seagate/pod-a.yaml create mode 100644 seagate/pvc-pod-a.yaml create mode 100644 seagate/readme.md create mode 100644 seagate/sc-me5-site-a.yaml create mode 100644 seagate/sc-me5-site-b.yaml create mode 100644 seagate/secret-me5-site-a.yaml create mode 100644 seagate/secret-me5-site-b.yaml create mode 100644 seagate/values.yaml diff --git a/kubectl b/kubectl deleted file mode 100644 index e69de29..0000000 diff --git a/seagate/csi-exos-x-csidriver.yaml b/seagate/csi-exos-x-csidriver.yaml new file mode 100644 index 0000000..5dad6a4 --- /dev/null +++ b/seagate/csi-exos-x-csidriver.yaml @@ -0,0 +1,13 @@ +apiVersion: storage.k8s.io/v1 +kind: CSIDriver +metadata: + name: csi-exos-x.seagate.com +spec: + attachRequired: true + podInfoOnMount: false + requiresRepublish: false + fsGroupPolicy: File + seLinuxMount: false + storageCapacity: false + volumeLifecycleModes: + - Persistent diff --git a/seagate/namespace.yaml b/seagate/namespace.yaml new file mode 100644 index 0000000..71b21ad --- /dev/null +++ b/seagate/namespace.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: seagate + labels: + app.kubernetes.io/name: seagate \ No newline at end of file diff --git a/seagate/pod-a.yaml b/seagate/pod-a.yaml new file mode 100644 index 0000000..c699d47 --- /dev/null +++ b/seagate/pod-a.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Pod +metadata: + name: pod-a +spec: + nodeSelector: + topology.kubernetes.io/zone: site-a + containers: + - name: app + image: busybox:1.36 + command: ["sh","-c","sleep 3600"] + volumeMounts: + - name: data + mountPath: /data + volumes: + - name: data + persistentVolumeClaim: + claimName: pvc-a diff --git a/seagate/pvc-pod-a.yaml b/seagate/pvc-pod-a.yaml new file mode 100644 index 0000000..b6ae1f8 --- /dev/null +++ b/seagate/pvc-pod-a.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: pvc-a +spec: + accessModes: ["ReadWriteOnce"] + resources: { requests: { storage: 10Gi } } + storageClassName: sc-me5-site-a diff --git a/seagate/readme.md b/seagate/readme.md new file mode 100644 index 0000000..d3d675e --- /dev/null +++ b/seagate/readme.md @@ -0,0 +1,316 @@ +# Seagate Exos X CSI (ME5 dual‑site) — Guía de instalación y operación + +Este README documenta cómo he dejado **reproducible** la instalación del *Seagate Exos X CSI Driver* (soporta ME5) en un clúster Kubernetes con **dos cabinas / dos zonas** (site‑a y site‑b) usando iSCSI + multipath y *topología por zona*. + +> **Objetivo** +> +> * Un único despliegue del driver (Helm). +> * **Dos StorageClass** (uno por sitio) con `allowedTopologies` y credenciales (Secret) separadas. +> * *WaitForFirstConsumer* para que el volumen se cree en la **misma zona** del pod. +> * Montajes iSCSI rápidos gracias a multipath bien configurado (modo `greedy`). + +--- + +## 1) Prerrequisitos en los nodos + +1. **Multipath** y **iSCSI** instalados/activos. + +2. **/etc/multipath.conf** — opciones relevantes usadas: + +```conf +defaults { + user_friendly_names "no" + find_multipaths "greedy" + no_path_retry "queue" +} + +devices { + device { + vendor "DellEMC" + product "ME5" + path_grouping_policy "multibus" + path_checker "tur" + prio "alua" + } +} +``` + +> **Por qué `greedy`?** +> +> * `find_multipaths "greedy"` evita crear *maps* hasta que haya más de un camino **o** el dispositivo sea claramente multipath, reduciendo falsos positivos y estabilizando el *udev settle*. Mejora tiempos de descubrimiento y evita *flapping*. + +Reiniciar servicios y refrescar paths tras cambiar multipath: + +```bash +sudo systemctl restart multipathd +sudo multipath -r +``` + +3. **Propagación de montajes (rshared)** + +Asegurar que `/` y `/var/lib/kubelet` están en **rshared** para que los montajes hechos por el plugin dentro del pod del *node‑server* aparezcan en el host: + +```bash +sudo mount --make-rshared / + +# systemd drop‑in para kubelet +sudo install -d /etc/systemd/system/kubelet.service.d +cat <<'EOF' | sudo tee /etc/systemd/system/kubelet.service.d/10-mount-propagation.conf +[Service] +MountFlags= +ExecStartPre=/bin/mkdir -p /var/lib/kubelet +ExecStartPre=/bin/mount --bind /var/lib/kubelet /var/lib/kubelet +ExecStartPre=/bin/mount --make-rshared /var/lib/kubelet +EOF + +sudo systemctl daemon-reload +sudo systemctl restart kubelet +``` + +Comprobar: + +```bash +sudo findmnt -o TARGET,PROPAGATION / +sudo findmnt -o TARGET,PROPAGATION /var/lib/kubelet +``` + +4. **Etiquetas de topología en nodos** + +Etiquetar cada nodo con su zona: + +```bash +kubectl label nodes topology.kubernetes.io/zone=site-a --overwrite +kubectl label nodes topology.kubernetes.io/zone=site-b --overwrite +``` + +--- + +## 2) Despliegue del Driver con Helm + +### 2.1. Namespace y valores + +```bash +kubectl apply -f namespace.yaml # namespace: seagate +``` + +**values.yaml** (resumen de lo usado): + +* Imagen del driver: `ghcr.io/seagate/seagate-exos-x-csi:v1.10.0` +* Sidecars: + + * `csi-provisioner v5.0.1` (timeout 60s) + * `csi-attacher v4.6.1` + * `csi-resizer v1.11.1` + * `csi-snapshotter v8.0.1` + * `csi-node-driver-registrar v2.9.0` +* `controller.extraArgs: ["-v=2"]` +* `node.extraArgs: ["-v=2"]` + +> **Nota:** no es necesario tocar `CSIDriver` para topología; la topología se maneja desde los `StorageClass` + etiquetas de nodo. + +### 2.2. Instalación + +```bash +helm upgrade --install exos-x-csi \ + -n seagate --create-namespace \ + ./seagate-exos-x-csi \ + -f ./values.yaml +``` + +#### Si hay residuos de una instalación anterior (RBAC) + +Si aparece un error de *invalid ownership metadata* con recursos tipo `ClusterRole/ClusterRoleBinding` de un release previo (p.ej. `exosx-csi`), eliminarlos: + +```bash +kubectl delete clusterrole external-provisioner-runner-systems +kubectl delete clusterrolebinding csi-provisioner-role-systems +# (si hubiera más, listarlos por label y borrarlos) +# kubectl get clusterrole,clusterrolebinding -A -l app.kubernetes.io/instance= +``` + +Reintentar `helm upgrade --install`. + +--- + +## 3) Secret por cabina (A y B) + +Un `Secret` por sitio en el *namespace* `seagate` con `apiAddress`, `username`, `password` en Base64. + +```bash +kubectl apply -f secret-me5-site-a.yaml +kubectl apply -f secret-me5-site-b.yaml +``` + +> **Importante:** Los `StorageClass` deben usar las **claves estándar CSI** para que el provisioner pase el Secret al driver: +> +> * `csi.storage.k8s.io/provisioner-secret-name|namespace` +> * `csi.storage.k8s.io/controller-publish-secret-name|namespace` +> * `csi.storage.k8s.io/controller-expand-secret-name|namespace` +> * `csi.storage.k8s.io/node-stage-secret-name|namespace` *(si aplica)* +> * `csi.storage.k8s.io/node-publish-secret-name|namespace` *(si aplica)* + +El síntoma de no usar estos nombres es: `missing API credentials` en el evento del PVC. + +--- + +## 4) StorageClass por zona (topología) + +Se definen **dos** `StorageClass` idénticos salvo: + +* Secret (A o B) +* `pool` (p. ej., `dg01` para site‑a, `dg02` para site‑b) +* `volPrefix` (ej. `sza` / `szb` para identificar site en el nombre de LUN) +* `allowedTopologies` con la zona correspondiente +* `volumeBindingMode: WaitForFirstConsumer` + +> Con WFFC, el PVC **no** se enlaza hasta que exista un Pod consumidor; el scheduler elige un nodo, y el provisioner crea el volumen en la **zona del nodo**. + +Aplicar ambos `StorageClass`: + +```bash +kubectl apply -f sc-me5-site-a.yaml +kubectl apply -f sc-me5-site-b.yaml +``` + +--- + +## 5) Prueba de extremo a extremo + +### 5.1. PVC + Pod en site‑a + +* PVC: `pvc-a` con `storageClassName: sc-me5-site-a` +* Pod: `pod-a` con `nodeSelector: topology.kubernetes.io/zone=site-a` + +```bash +kubectl apply -f pvc-pod-a.yaml +kubectl apply -f pod-a.yaml +kubectl get pvc,pod +``` + +Deberías ver el Pod en *Running* y el volumen creado/montado en la ME5 del site‑a. + +### 5.2. Verificaciones útiles + +* **iSCSI nodes vistos:** + +```bash +sudo iscsiadm -m node | sort +``` + +* **Multipath:** + +```bash +sudo multipath -ll +``` + +* **Eventos del PVC:** + +```bash +kubectl describe pvc +``` + +* **Logs del controller:** (búsqueda de credenciales / errores de provisión) + +```bash +kubectl -n seagate logs deploy/seagate-exos-x-csi-controller-server \ + -c seagate-exos-x-csi-controller | grep -i -E 'cred|secret|error' +``` + +--- + +## 6) Medir el tiempo de *NodePublish* (montaje) + +Para medir cuánto tarda el montaje (fase *NodePublishVolume*) desde el *node‑server*: + +```bash +kubectl -n seagate logs -l name=seagate-exos-x-csi-node-server \ + -c seagate-exos-x-csi-node --tail=10000 \ +| grep "NodePublishVolume" \ +| grep "ROUTINE END" \ +| sed -E 's/.*NodePublishVolume.*<([^>]*)>.*/\1/' +``` + +* Valores \~**< 2 min** indican que el montaje completa dentro de la ventana de kubelet, evitando `DeadlineExceeded`. +* Si ves \~**4m34s** constantes: el driver está esperando a que aparezcan *dm‑name* de portales inaccesibles. Revisa topologías, conectividad y que solo se prueben portales de la zona activa. + +> Para validar zona‑B, lanza un Pod/PVC análogo en `site-b` y repite el grep anterior en los logs. + +--- + +## 7) Solución de problemas + +* **`missing API credentials` al provisionar** + + * Asegúrate de usar las **claves CSI** en `parameters:` del `StorageClass` (ver §3). + +* **Errores Helm de *invalid ownership metadata*** + + * Borra los `ClusterRole/ClusterRoleBinding` residuales del release antiguo (ver §2.2). + +* **`DeadlineExceeded` durante montaje** + + * Comprueba: + + * `find_multipaths "greedy"` y resto de multipath según §1.2. + * Etiquetas de zona en el nodo donde programa el Pod. + * Que el `StorageClass` correcto tenga `allowedTopologies` de esa zona. + +* **Ver puertos/portales iSCSI efectivos** + + * `sudo iscsiadm -m node | sort` para ver a qué destinos quedó configurado el nodo. Con topología bien aplicada, deben ser los del sitio correspondiente. + +--- + +## 8) Limpieza y reintentos + +Para repetir la prueba desde cero (manteniendo el driver): + +```bash +kubectl delete -f pod-a.yaml +kubectl delete -f pvc-pod-a.yaml +``` + +Si quisieras limpiar *todo el despliegue* del driver: + +```bash +helm uninstall exos-x-csi -n seagate +# Si quedaron RBAC de releases previos: +kubectl delete clusterrole external-provisioner-runner-systems || true +kubectl delete clusterrolebinding csi-provisioner-role-systems || true +``` + +--- + +## 9) Resumen de lo que quedó en repo (carpeta `seagate/`) + +* `namespace.yaml` — Namespace `seagate`. +* `secret-me5-site-a.yaml` / `secret-me5-site-b.yaml` — Credenciales por sitio. +* `values.yaml` — Valores de Helm usados para el driver v1.10.0. +* `sc-me5-site-a.yaml` / `sc-me5-site-b.yaml` — StorageClass con `allowedTopologies`, `pool`, `volPrefix`, claves CSI de Secret y `WaitForFirstConsumer`. +* `pvc-pod-a.yaml` + `pod-a.yaml` — Manifests de prueba en `site-a`. +* *(Opcional)* `csi-exos-x-csidriver.yaml` — no es necesario modificarlo para topología en esta versión. + +--- + +## 10) Anexos — Comandos útiles ejecutados + +* Reinicio multipath/kubelet y propagación de montajes. +* Limpieza iSCSI/multipath (cuando se rehizo la prueba): + +```bash +sudo iscsiadm -m node -u || true +sudo iscsiadm -m node -o delete || true +sudo multipath -F || true +sudo multipath -r +``` + +* Despliegue Helm + manejo de residuos RBAC (ver §2.2). +* Aplicación secuencial de `namespace`, `secrets`, `StorageClass`, `PVC` y `Pod`. + +--- + +### Resultado + +* **Reproducible**: con esta receta, el volumen se crea en la cabina de su zona y el Pod arranca. +* **Tiempos de montaje**: bajan de \~4m34s a **≈1m30s** (observado), dentro del presupuesto de kubelet. +* **Aislamiento por zona**: cada StorageClass limita portales iSCSI a su sitio gracias a `allowedTopologies` + etiquetas de nodo. diff --git a/seagate/sc-me5-site-a.yaml b/seagate/sc-me5-site-a.yaml new file mode 100644 index 0000000..ae3d078 --- /dev/null +++ b/seagate/sc-me5-site-a.yaml @@ -0,0 +1,22 @@ +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + name: sc-me5-site-a +provisioner: csi-exos-x.seagate.com +volumeBindingMode: WaitForFirstConsumer +allowVolumeExpansion: true +parameters: + csi.storage.k8s.io/provisioner-secret-name: seagate-me5-site-a + csi.storage.k8s.io/provisioner-secret-namespace: seagate + csi.storage.k8s.io/controller-publish-secret-name: seagate-me5-site-a + csi.storage.k8s.io/controller-publish-secret-namespace: seagate + csi.storage.k8s.io/controller-expand-secret-name: seagate-me5-site-a + csi.storage.k8s.io/controller-expand-secret-namespace: seagate + csi.storage.k8s.io/fstype: ext4 + pool: dg01 # pool de la ME5 del Site A + volPrefix: sza # prefijo corto para identificar Site A + storageProtocol: iscsi +allowedTopologies: +- matchLabelExpressions: + - key: topology.kubernetes.io/zone + values: ["site-a"] diff --git a/seagate/sc-me5-site-b.yaml b/seagate/sc-me5-site-b.yaml new file mode 100644 index 0000000..a34d340 --- /dev/null +++ b/seagate/sc-me5-site-b.yaml @@ -0,0 +1,22 @@ +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + name: sc-me5-site-b +provisioner: csi-exos-x.seagate.com +volumeBindingMode: WaitForFirstConsumer +allowVolumeExpansion: true +parameters: + csi.storage.k8s.io/provisioner-secret-name: seagate-me5-site-b + csi.storage.k8s.io/provisioner-secret-namespace: seagate + csi.storage.k8s.io/controller-publish-secret-name: seagate-me5-site-b + csi.storage.k8s.io/controller-publish-secret-namespace: seagate + csi.storage.k8s.io/controller-expand-secret-name: seagate-me5-site-b + csi.storage.k8s.io/controller-expand-secret-namespace: seagate + csi.storage.k8s.io/fstype: ext4 + pool: dg02 + volPrefix: szb + storageProtocol: iscsi +allowedTopologies: +- matchLabelExpressions: + - key: topology.kubernetes.io/zone + values: ["site-b"] diff --git a/seagate/secret-me5-site-a.yaml b/seagate/secret-me5-site-a.yaml new file mode 100644 index 0000000..98944da --- /dev/null +++ b/seagate/secret-me5-site-a.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Secret +metadata: + name: seagate-me5-site-a + namespace: seagate +type: Opaque +data: + apiAddress: aHR0cHM6Ly9hZG1pbi5wb3dlcnZhdWx0MS5jMmV0Lm5ldA== # https://admin.powervault1.c2et.net + username: YWRtaW4uYzNz # admin.c3s + password: UG96dWVsby4xMjM0NQ== # Pozuelo.12345 diff --git a/seagate/secret-me5-site-b.yaml b/seagate/secret-me5-site-b.yaml new file mode 100644 index 0000000..7f14d34 --- /dev/null +++ b/seagate/secret-me5-site-b.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Secret +metadata: + name: seagate-me5-site-b + namespace: seagate +type: Opaque +data: + apiAddress: aHR0cHM6Ly9hZG1pbi5wb3dlcnZhdWx0Mi5jMmV0Lm5ldA== # https://admin.powervault2.c2et.net + username: YWRtaW4uYzNz + password: UG96dWVsby4xMjM0NQ== diff --git a/seagate/values.yaml b/seagate/values.yaml new file mode 100644 index 0000000..e63cbe7 --- /dev/null +++ b/seagate/values.yaml @@ -0,0 +1,64 @@ +kubeletPath: /var/lib/kubelet +pspAdmissionControllerEnabled: false + +image: + repository: ghcr.io/seagate/seagate-exos-x-csi + tag: "v1.10.0" + pullPolicy: IfNotPresent + +csiProvisioner: + image: + repository: registry.k8s.io/sig-storage/csi-provisioner + tag: v5.0.1 + timeout: 60s + extraArgs: [] + +csiAttacher: + image: + repository: registry.k8s.io/sig-storage/csi-attacher + tag: v4.6.1 + timeout: 60s + extraArgs: [] + +csiResizer: + image: + repository: registry.k8s.io/sig-storage/csi-resizer + tag: v1.11.1 + extraArgs: [] + +csiSnapshotter: + image: + repository: registry.k8s.io/sig-storage/csi-snapshotter + tag: v8.0.1 + extraArgs: [] + +csiNodeRegistrar: + image: + repository: registry.k8s.io/sig-storage/csi-node-driver-registrar + tag: v2.9.0 + extraArgs: [] + +controller: + extraArgs: ["-v=2"] + +node: + extraArgs: ["-v=2"] + +multipathd: + extraArgs: [] + +nodeLivenessProbe: + image: + repository: registry.k8s.io/sig-storage/livenessprobe + tag: v2.12.0 + extraArgs: [] + +nodeServer: + nodeSelector: {} + nodeAffinity: {} + +podMonitor: + enabled: false + +serviceMonitor: + enabled: false