Flux CD Flux CD

Configura multi-tenancy con Flux

Da a cada equipo su propio namespace y repositorio, y aplica el aislamiento con RBAC de Kubernetes.

15 min Avanzado

Cuando varios equipos comparten un clúster, quieres que cada uno despliegue sus propias aplicaciones sin poder tocar las de nadie más. Flux construye esto sobre primitivas de Kubernetes: cada tenant recibe un namespace, una service account y un role binding, y Flux aplica los manifiestos del tenant haciéndose pasar por esa service account. El aislamiento lo aplica el RBAC de Kubernetes, sin necesidad de un motor de políticas aparte. Esta guía configura un tenant llamado dev-team.

Los dos roles

  • Los administradores de plataforma son dueños del clúster y de la instalación de Flux. Crean tenants y deciden a qué puede acceder cada uno.
  • Los tenants son dueños de sus aplicaciones. Hacen commit de manifiestos en su propio repositorio, y Flux los aplica solo dentro del namespace del tenant.

Crea el tenant

La CLI genera el namespace, la service account y el RBAC por ti. Ejecútalo en un clon del repositorio de plataforma:

mkdir -p tenants/base/dev-team
flux create tenant dev-team \
  --with-namespace=apps \
  --export > tenants/base/dev-team/rbac.yaml

El YAML generado contiene un Namespace llamado apps, una ServiceAccount llamada dev-team y un RoleBinding que concede a esa service account el rol cluster-admin solo dentro del namespace apps. No puede hacer nada fuera de él.

Conecta el repositorio del tenant

Crea un source y una Kustomization para el repositorio propio del tenant, en el namespace del tenant:

flux create source git dev-team \
  --namespace=apps \
  --url=https://github.com/your-org/dev-team-apps \
  --branch=main \
  --export > tenants/base/dev-team/sync.yaml

flux create kustomization dev-team \
  --namespace=apps \
  --service-account=dev-team \
  --source=GitRepository/dev-team \
  --path="./" \
  --prune=true --interval=5m \
  --export >> tenants/base/dev-team/sync.yaml

La línea importante es serviceAccountName: dev-team en la Kustomization. Hace que kustomize-controller aplique los manifiestos del tenant como esa service account, así que cualquier intento de crear recursos fuera de apps, o recursos de ámbito de clúster como un ClusterRole, es rechazado por la API de Kubernetes. El mismo campo existe en HelmRelease.

Añade un kustomization.yaml en tenants/base/dev-team/ que liste rbac.yaml y sync.yaml, y referencia el tenant desde la carpeta del clúster, por ejemplo mediante una Kustomization de Flux en clusters/production/tenants.yaml con path: ./tenants/production. Haz commit y push. Flux crea el namespace, el RBAC y la sincronización del tenant, y el repositorio propio del equipo toma el relevo desde ahí.

Para un repositorio de tenant privado, crea las credenciales en el namespace del tenant para que solo los objetos de ese tenant las referencien:

flux create secret git dev-team-auth \
  --namespace=apps \
  --url=https://github.com/your-org/dev-team-apps \
  --username=git --password=<token>

Luego añade --secret-ref=dev-team-auth al source.

Bloquea los controladores

Las service accounts solo ayudan si los tenants no pueden esquivarlas. Configura los controladores para que apliquen las reglas parcheando la instalación de Flux en clusters/<env>/flux-system/kustomization.yaml:

patches:
  - patch: |
      - op: add
        path: /spec/template/spec/containers/0/args/-
        value: --no-cross-namespace-refs=true
      - op: add
        path: /spec/template/spec/containers/0/args/-
        value: --default-service-account=default
    target:
      kind: Deployment
      name: "(kustomize-controller|helm-controller)"
  - patch: |
      - op: add
        path: /spec/template/spec/containers/0/args/-
        value: --no-cross-namespace-refs=true
    target:
      kind: Deployment
      name: "(notification-controller|image-reflector-controller|image-automation-controller)"

Qué hacen estos flags:

  • --no-cross-namespace-refs=true impide que la Kustomization de un tenant haga referencia a un source de otro namespace, de modo que los tenants no puedan usar los repositorios ni las credenciales de otros.
  • --default-service-account=default hace que los controladores se hagan pasar por la service account default del namespace del objeto cuando no se define ninguna. Un tenant que olvida serviceAccountName obtiene casi ningún permiso en lugar de la identidad cluster-admin de Flux.

Haz commit de los parches en el kustomization.yaml que generó bootstrap en esa carpeta. Volver a ejecutar bootstrap conserva las personalizaciones que añadas a ese archivo. Consulta la documentación actual de multi-tenancy de Flux para el parche exacto de tu versión.

Restringe lo que pueden hacer los tenants

Más allá del límite del namespace, considera controles adicionales:

  • RBAC con ámbito de namespace. Reemplaza el role binding cluster-admin generado por un rol más estrecho si los tenants no deben crear, por ejemplo, Roles o NetworkPolicies.
  • Política de admisión. Usa Kyverno o una ValidatingAdmissionPolicy para imponer registros de imágenes, límites de recursos o prohibir Pods privilegiados.
  • Cuotas. Añade un ResourceQuota y un LimitRange al namespace del tenant, junto con el RBAC.
  • Aislamiento de red. Añade objetos NetworkPolicy default-deny para que los namespaces de los tenants no puedan hablar entre sí.

Verifica el aislamiento

Añade al repositorio del tenant un manifiesto que cree algo fuera del namespace del tenant, como un ClusterRole, y haz push. Luego comprueba:

flux get kustomizations -n apps
kubectl describe kustomization dev-team -n apps

La Kustomization falla con un error forbidden que nombra la service account, que es exactamente lo que quieres. Elimina el manifiesto incorrecto y Flux se recupera por sí solo.

Cómo se compara con la tenencia basada en proyectos

Algunas herramientas modelan los tenants como proyectos con sus propios objetos de política. Flux no tiene tal concepto. Un tenant es simplemente un namespace más una service account de la que Flux se hace pasar, lo que significa que el API server de Kubernetes es el único lugar donde se aplican los permisos.

Guías populares