Files
kubernetes/seagate
2025-08-26 22:00:11 +02:00
..
2025-08-26 22:00:11 +02:00
2025-08-26 22:00:11 +02:00
2025-08-26 22:00:11 +02:00
2025-08-26 22:00:11 +02:00
2025-08-26 22:00:11 +02:00
2025-08-26 22:00:11 +02:00
2025-08-26 22:00:11 +02:00
2025-08-26 22:00:11 +02:00
2025-08-26 22:00:11 +02:00

Seagate Exos X CSI (ME5 dualsite) — 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 (sitea y siteb) 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:

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:

sudo systemctl restart multipathd
sudo multipath -r
  1. 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 nodeserver aparezcan en el host:

sudo mount --make-rshared /

# systemd dropin 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:

sudo findmnt -o TARGET,PROPAGATION /
sudo findmnt -o TARGET,PROPAGATION /var/lib/kubelet
  1. Etiquetas de topología en nodos

Etiquetar cada nodo con su zona:

kubectl label nodes <nodo-del-site-a> topology.kubernetes.io/zone=site-a --overwrite
kubectl label nodes <nodo-del-site-b> topology.kubernetes.io/zone=site-b --overwrite

2) Despliegue del Driver con Helm

2.1. Namespace y valores

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

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:

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=<old-release>

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.

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 sitea, dg02 para siteb)
  • 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:

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 sitea

  • PVC: pvc-a con storageClassName: sc-me5-site-a
  • Pod: pod-a con nodeSelector: topology.kubernetes.io/zone=site-a
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 sitea.

5.2. Verificaciones útiles

  • iSCSI nodes vistos:
sudo iscsiadm -m node | sort
  • Multipath:
sudo multipath -ll
  • Eventos del PVC:
kubectl describe pvc <nombre>
  • Logs del controller: (búsqueda de credenciales / errores de provisión)
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 nodeserver:

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 dmname de portales inaccesibles. Revisa topologías, conectividad y que solo se prueben portales de la zona activa.

Para validar zonaB, 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):

kubectl delete -f pod-a.yaml
kubectl delete -f pvc-pod-a.yaml

Si quisieras limpiar todo el despliegue del driver:

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):
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.