Le webhook de mutation de Fluid injecte des règles d'affinité dans les spécifications des pods afin que le planificateur kube-scheduler place les pods d'application sur les nœuds contenant les données mises en cache. Si aucun nœud disposant du cache n'est disponible, les pods sont placés sur des nœuds situés dans la même zone ou la même région que le cache. Avec Fluid, vous pouvez :
Planifier les pods sur le nœud contenant les données mises en cache (affinité de nœud, pondération 100)
Planifier les pods sur n'importe quel nœud de la même zone que le cache (affinité de zone, pondération 50)
Planifier les pods sur n'importe quel nœud de la même région que le cache (affinité de région, pondération 20)
Forcer le placement des pods sur les nœuds contenant le cache lorsque la localité des données est critique (affinité requise)
Éloigner les pods qui n'utilisent pas de datasets des nœuds contenant le cache pour réduire la contention des ressources
Limites
Prise en charge uniquement sur les clusters ACK Pro.
Incompatible avec la planification basée sur Elastic Container Instance et la planification des ressources basée sur la priorité.
Si
spec.affinityouspec.nodeSelectorest déjà défini dans la spécification d'un pod, Fluid ignore l'injection d'affinité pour ce pod.
Prérequis
Avant de commencer, assurez-vous d'avoir :
Un cluster ACK Pro exécutant Kubernetes 1.18 ou une version ultérieure. Pour plus d'informations, consultez la rubrique Créer un cluster ACK Pro.
-
La suite AI cloud-native et ack-fluid 1.0.6 ou une version ultérieure déployées dans le cluster. Pour plus d'informations, consultez la rubrique Déployer la suite AI cloud-native.
ImportantSi Fluid open source est déjà installé, désinstallez-le avant de déployer le composant ack-fluid.
Un client kubectl connecté au cluster. Pour plus d'informations, consultez la rubrique Obtenir le fichier kubeconfig d'un cluster et utiliser kubectl pour se connecter au cluster.
Fonctionnement
Lors de la création d'un pod, le webhook de mutation de Fluid lit les étiquettes du pod et le Dataset référencé, puis injecte des règles nodeAffinity dans la spécification du pod avant que kube-scheduler n'évalue le placement. Par défaut, les règles injectées utilisent preferredDuringSchedulingIgnoredDuringExecution (affinité souple). Pour forcer un placement strict sur les nœuds contenant le cache, ajoutez l'étiquette fluid.io/dataset.<dataset_name>.sched: required au pod.
L'ordre de repli est le suivant : nœud → zone → région. Si un pod ne peut pas être placé sur un nœud contenant les données mises en cache, kube-scheduler se rabat sur un nœud de la même zone, puis de la même région, en fonction des pondérations configurées.
Les pods qui ne référencent pas de dataset sont gérés par le plugin PreferNodesWithoutCache qui les éloigne des nœuds réservés à la mise en cache des données.
Configurer la politique de planification
Configuration par défaut
La politique de planification est stockée dans la ConfigMap webhook-plugins du namespace fluid-system. Pour l'inspecter :
kubectl get cm -n fluid-system webhook-plugins -oyaml
Sortie attendue :
apiVersion: v1
data:
pluginsProfile: |
pluginConfig:
- args: |
preferred:
# fluid.io/node: built-in, name cannot be changed. Schedules pods to the node holding cached data.
- name: fluid.io/node
weight: 100
# topology.kubernetes.io/zone: schedules pods to nodes in the same zone as the cache. Adjust key for your cluster.
- name: topology.kubernetes.io/zone
weight: 50
# topology.kubernetes.io/region: schedules pods to nodes in the same region as the cache. Adjust key for your cluster.
- name: topology.kubernetes.io/region
weight: 20
# required: applies when a pod carries the label fluid.io/dataset.{dataset name}.sched=required
required:
- fluid.io/node
name: NodeAffinityWithCache
plugins:
serverful:
withDataset:
- RequireNodeWithFuse
- NodeAffinityWithCache
- MountPropagationInjector
withoutDataset:
- PreferNodesWithoutCache
serverless:
withDataset:
- FuseSidecar
withoutDataset: []
La liste preferred contrôle les pondérations de l'affinité souple. La liste required définit quelle étiquette doit correspondre lorsqu'un pod opte pour une planification stricte. Le nom fluid.io/node dans les deux sections ne peut pas être modifié.
Configuration personnalisée
Les clusters ACK peuvent utiliser différentes étiquettes de nœud pour représenter la topologie. Pour ajouter, supprimer ou remplacer des clés de topologie :
-
Modifiez la ConfigMap :
kubectl edit -n fluid-system cm webhook-plugins -
Modifiez la liste
preferred. Deux scénarios courants sont décrits ci-dessous. Exemple : Ignorer l'affinité de cache au niveau du nœud Mettez en commentairefluid.io/nodepour supprimer la préférence de placement au niveau du nœud. Fluid privilégie toujours l'affinité de zone et de région.preferred: # - name: fluid.io/node # commented out: node affinity disabled # weight: 100 - name: topology.kubernetes.io/zone weight: 50 - name: topology.kubernetes.io/region weight: 20Exemple : Ajouter une affinité de pool de nœuds Insérez une clé de topologie personnalisée entre l'affinité au niveau du nœud et celle au niveau de la zone pour privilégier la planification au sein du même pool de nœuds.
preferred: - name: fluid.io/node weight: 100 - name: alibabacloud.com/nodepool-id # custom topology key weight: 80 - name: topology.kubernetes.io/zone weight: 50 - name: topology.kubernetes.io/region weight: 20 -
Redémarrez le webhook Fluid pour appliquer les modifications :
kubectl rollout restart deployment -n fluid-system fluid-webhook
Exemples
Exemple 1 : Affinité de nœud préférée (planification souple)
Cet exemple planifie un pod sur le nœud contenant les données mises en cache. Si aucun nœud disposant du cache n'est planifiable, kube-scheduler se rabat sur l'affinité de zone et de région en fonction des pondérations configurées.
-
Créez un Secret avec vos identifiants OSS :
apiVersion: v1 kind: Secret metadata: name: mysecret stringData: fs.oss.accessKeyId: <ACCESS_KEY_ID> fs.oss.accessKeySecret: <ACCESS_KEY_SECRET> -
Créez un Dataset et un JindoRuntime :
ImportantCet exemple utilise JindoRuntime. Pour utiliser d'autres runtimes de cache, consultez la rubrique Utiliser EFC pour accélérer l'accès à NAS ou CPFS. Pour l'accélération JindoFS et Object Storage Service (OSS), consultez la rubrique Utiliser JindoFS pour accélérer l'accès à OSS.
apiVersion: data.fluid.io/v1alpha1 kind: Dataset metadata: name: demo-dataset spec: mounts: - mountPoint: oss://<oss_bucket>/<bucket_dir> options: fs.oss.endpoint: <oss_endpoint> name: hadoop path: "/" encryptOptions: - name: fs.oss.accessKeyId valueFrom: secretKeyRef: name: mysecret key: fs.oss.accessKeyId - name: fs.oss.accessKeySecret valueFrom: secretKeyRef: name: mysecret key: fs.oss.accessKeySecret --- apiVersion: data.fluid.io/v1alpha1 kind: JindoRuntime metadata: name: demo-dataset spec: replicas: 2 tieredstore: levels: - mediumtype: MEM path: /dev/shm quota: 10G high: "0.99" low: "0.8" -
Créez le pod d'application avec l'injection d'affinité activée :
apiVersion: v1 kind: Pod metadata: name: nginx labels: fuse.serverful.fluid.io/inject: "true" # enables Fluid affinity injection spec: containers: - name: nginx image: registry.openanolis.cn/openanolis/nginx:1.14.1-8.6 volumeMounts: - mountPath: /data name: data-vol volumes: - name: data-vol persistentVolumeClaim: claimName: demo-dataset # PVC auto-created by Fluid, named after the Dataset -
Vérifiez que Fluid a injecté la règle d'affinité :
kubectl get pod nginx -oyamlLa spécification du pod doit contenir une règle
preferredDuringSchedulingIgnoredDuringExecutionciblant le nœud contenant le cache :spec: affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - preference: matchExpressions: - key: fluid.io/s-default-demo-dataset operator: In values: - "true" weight: 100 -
Confirmez que le pod a été planifié sur un nœud contenant le cache :
kubectl get pod nginx -o custom-columns=NAME:metadata.name,NODE:.spec.nodeNameLe nœud indiqué doit être l'un des nœuds de travail JindoRuntime où les données sont mises en cache.
Exemple 2 : Affinité de zone préférée (planification souple)
Cet exemple planifie les pods sur n'importe quel nœud de la zone où résident les données mises en cache. Les règles d'affinité au niveau du nœud et de la zone sont toutes deux injectées, de sorte que kube-scheduler tente d'abord de placer les pods sur les nœuds contenant le cache, puis sur les autres nœuds de la même zone.
Pour activer l'affinité de zone, épinglez le Dataset et le maître JindoRuntime sur une zone spécifique.
-
Créez un Secret (identique à l'exemple 1) :
apiVersion: v1 kind: Secret metadata: name: mysecret stringData: fs.oss.accessKeyId: <ACCESS_KEY_ID> fs.oss.accessKeySecret: <ACCESS_KEY_SECRET> -
Créez un Dataset et un JindoRuntime, tous deux épinglés sur la zone cible :
apiVersion: data.fluid.io/v1alpha1 kind: Dataset metadata: name: demo-dataset spec: nodeAffinity: required: nodeSelectorTerms: - matchExpressions: - key: topology.kubernetes.io/zone operator: In values: - "<ZONE_ID>" # e.g., cn-beijing-i mounts: - mountPoint: oss://<oss_bucket>/<bucket_dir> options: fs.oss.endpoint: <oss_endpoint> name: hadoop path: "/" encryptOptions: - name: fs.oss.accessKeyId valueFrom: secretKeyRef: name: mysecret key: fs.oss.accessKeyId - name: fs.oss.accessKeySecret valueFrom: secretKeyRef: name: mysecret key: fs.oss.accessKeySecret --- apiVersion: data.fluid.io/v1alpha1 kind: JindoRuntime metadata: name: demo-dataset spec: replicas: 2 master: nodeSelector: topology.kubernetes.io/zone: <ZONE_ID> # e.g., cn-beijing-i tieredstore: levels: - mediumtype: MEM path: /dev/shm quota: 10G high: "0.99" low: "0.8"La contrainte
nodeAffinity.required.nodeSelectorTermssur le Dataset indique à Fluid dans quelle zone se trouve le cache. Fluid lit cette information pour générer la règle d'affinité au niveau de la zone injectée dans les pods d'application. -
Créez le pod d'application :
apiVersion: v1 kind: Pod metadata: name: nginx labels: fuse.serverful.fluid.io/inject: "true" spec: containers: - name: nginx image: registry.openanolis.cn/openanolis/nginx:1.14.1-8.6 volumeMounts: - mountPath: /data name: data-vol volumes: - name: data-vol persistentVolumeClaim: claimName: demo-dataset -
Vérifiez les règles d'affinité injectées :
kubectl get pod nginx -oyamlUne règle d'affinité au niveau du nœud et une autre au niveau de la zone doivent apparaître :
spec: affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - preference: matchExpressions: - key: fluid.io/s-default-demo-dataset operator: In values: - "true" weight: 100 - preference: matchExpressions: - key: topology.kubernetes.io/zone operator: In values: - <ZONE_ID> # e.g., cn-beijing-i weight: 50 -
Confirmez que le pod a été planifié sur un nœud de la zone cible :
kubectl get pod nginx -o custom-columns=NAME:metadata.name,NODE:.spec.nodeName kubectl get node <node_name> --show-labels | grep topology.kubernetes.io/zoneLe nœud doit porter l'étiquette
topology.kubernetes.io/zone=<ZONE_ID>.
Exemple 3 : Affinité de nœud requise (planification stricte)
Cet exemple force le placement du pod sur un nœud contenant les données mises en cache. Si aucun nœud disposant du cache n'est planifiable, le pod reste en attente. Utilisez cette option lorsque la localité des données est non négociable, par exemple pour des travaux d'entraînement sensibles à la latence.
-
Créez un Secret (identique à l'exemple 1) :
apiVersion: v1 kind: Secret metadata: name: mysecret stringData: fs.oss.accessKeyId: <ACCESS_KEY_ID> fs.oss.accessKeySecret: <ACCESS_KEY_SECRET> -
Créez un Dataset et un JindoRuntime (identiques à l'exemple 1) :
apiVersion: data.fluid.io/v1alpha1 kind: Dataset metadata: name: demo-dataset spec: mounts: - mountPoint: oss://<oss_bucket>/<bucket_dir> options: fs.oss.endpoint: <oss_endpoint> name: hadoop path: "/" encryptOptions: - name: fs.oss.accessKeyId valueFrom: secretKeyRef: name: mysecret key: fs.oss.accessKeyId - name: fs.oss.accessKeySecret valueFrom: secretKeyRef: name: mysecret key: fs.oss.accessKeySecret --- apiVersion: data.fluid.io/v1alpha1 kind: JindoRuntime metadata: name: demo-dataset spec: replicas: 2 tieredstore: levels: - mediumtype: MEM path: /dev/shm quota: 10G high: "0.99" low: "0.8" -
Créez le pod d'application avec l'étiquette de planification requise :
apiVersion: v1 kind: Pod metadata: name: nginx labels: fuse.serverful.fluid.io/inject: "true" fluid.io/dataset.demo-dataset.sched: required # forces hard affinity for demo-dataset spec: containers: - name: nginx image: registry.openanolis.cn/openanolis/nginx:1.14.1-8.6 volumeMounts: - mountPath: /data name: data-vol volumes: - name: data-vol persistentVolumeClaim: claimName: demo-datasetLe format de l'étiquette est
fluid.io/dataset.<dataset_name>.sched: required. Remplacez<dataset_name>par le nom de votre Dataset. -
Vérifiez la règle d'affinité injectée :
kubectl get pod nginx -oyamlUne règle
requiredDuringSchedulingIgnoredDuringExecutiondoit apparaître, empêchant le pod d'être planifié sur tout nœud ne contenant pas les données mises en cache :spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: fluid.io/s-default-demo-dataset operator: In values: - "true" -
Confirmez que le pod a été planifié sur un nœud contenant le cache :
kubectl get pod nginx -o custom-columns=NAME:metadata.name,NODE:.spec.nodeNameLe nœud indiqué doit être l'un des nœuds de travail JindoRuntime. Si aucun nœud de ce type n'est disponible, le pod reste dans l'état
Pendingjusqu'à ce qu'un nœud contenant le cache devienne planifiable.