Todos los productos
Search
Centro de documentos

Container Service for Kubernetes:Enable disk parallel mounting to accelerate pod startups

Última actualización: Sep 21, 2026

Cuando varios pods comparten un nodo y cada uno requiere múltiples discos, algo común en cargas de trabajo de bases de datos, integración continua (CI) y procesamiento por lotes, el montaje en serie predeterminado aumenta el tiempo de inicio de los pods. El montaje paralelo de discos adjunta los discos de forma simultánea, lo que reduce la latencia de arranque.

Requisitos previos

Notas de uso

  • El montaje paralelo solo es compatible con discos que tienen números de serie. Para obtener más información sobre cómo consultar el número de serie de un disco, consulte Query serial number.

    Los discos creados antes del 10 de junio de 2020 no tienen números de serie reconocibles. Si habilita el montaje paralelo para estos discos, el proceso fallará.

  • Cuando se desmontan varios discos del mismo nodo, las operaciones de desmontaje se ejecutan en modo serie.

  • Después de habilitar el montaje paralelo, los campos Device que devuelve la API, como ECS DescribeDisks, y el destino de montaje que se muestra en la consola pueden ser inexactos. No dependa de esta ruta de montaje en sus cargas de trabajo. Utilice el número de serie del disco para determinar la ruta de montaje real.

Procedimiento

Para habilitar el montaje paralelo de discos, utilice el script automatizado o siga el procedimiento manual a continuación.

Usar un script automatizado

  1. Guarde el siguiente script en un archivo llamado enable_parallel_attach.sh.

    Ver el script

    #!/bin/bash
    
    set -e
    set -o pipefail
    
    readonly REQUIRED_VERSION="v1.30.4"
    CLUSTER_ID=$1
    
    if [ -z "$CLUSTER_ID" ]; then
        echo "Usage: enable_parallel_attach.sh <cluster-id>"
        exit 1
    fi
    
    check_version() {
        local ADDONS VERSION
        ADDONS=$(aliyun cs GET "/clusters/${CLUSTER_ID}/addon_instances")
    
        VERSION=$(echo "$ADDONS" | jq -r '.addons[] | select(.name=="csi-plugin") | .version')
        if !  printf "%s\n" "$REQUIRED_VERSION" "$VERSION" | sort -V -C; then
            echo "csi-plugin version $VERSION is not supported, please upgrade to $REQUIRED_VERSION or later"
            exit 1
        fi
    
        PROVISIONER=managed-csiprovisioner
        VERSION=$(echo "$ADDONS" | jq -r '.addons[] | select(.name=="managed-csiprovisioner") | .version')
        if [ -z "$VERSION" ]; then
            PROVISIONER=csi-provisioner
            VERSION=$(echo "$ADDONS" | jq -r '.addons[] | select(.name=="csi-provisioner") | .version')
        fi
        if !  printf "%s\n" "$REQUIRED_VERSION" "$VERSION" | sort -V -C; then
            echo "$PROVISIONER version $VERSION is not supported, please upgrade to $REQUIRED_VERSION or later"
            exit 1
        fi
    }
    
    update_node_pool() {
        local NODE_POOL_DOC
        NODE_POOL_DOC=$(aliyun cs GET "/clusters/${CLUSTER_ID}/nodepools/$1")
    
        if [ -n "$(echo "$NODE_POOL_DOC" | jq -r '(.scaling_group.tags // [])[] | select(.key=="supportConcurrencyAttach")')" ]; then
            echo "node pool already has supportConcurrencyAttach tag"
            return
        fi
    
        aliyun cs PUT "/clusters/${CLUSTER_ID}/nodepools/$1" --header "Content-Type=application/json" \
            --body "$(echo "$NODE_POOL_DOC" | jq -c '{
        "scaling_group": {
            "tags": ((.scaling_group.tags // []) + [{
                "key": "supportConcurrencyAttach",
                "value": "true"
            }])
        }
    }')"
    }
    
    # Configure existing nodes.
    update_nodes() {
        local PAGE=1
        local IDX TOTAL NODES_DOC ARGS
        while :; do
            echo "tagging nodes, page $PAGE"
            NODES_DOC=$(aliyun cs GET "/clusters/${CLUSTER_ID}/nodes" --pageSize 50 --pageNumber $PAGE)
            TOTAL=$(echo "$NODES_DOC" | jq -r '.page.total_count')
    
            ARGS=()
            IDX=0
            for node in $(echo "$NODES_DOC" | jq -r '.nodes[] | select(.is_aliyun_node) | .instance_id'); do
                IDX=$((IDX+1))
                ARGS+=("--ResourceId.$IDX" "$node")
            done
            if [ "$IDX" != "0" ]; then
                aliyun ecs TagResources --region "$ALIBABA_CLOUD_REGION_ID" --ResourceType Instance "${ARGS[@]}" \
                    --Tag.1.Key supportConcurrencyAttach --Tag.1.Value true
                echo "finished nodes $(( (PAGE-1)*50+IDX ))/$TOTAL"
            fi
    
            if [[ $(( PAGE*50 )) -ge $TOTAL ]]; then
                break
            fi
            PAGE=$((PAGE+1))
        done
    }
    
    update_addon() {
        local ADDON=$1
        shift
        local CONFIG STATE
        CONFIG=$(aliyun cs GET "/clusters/${CLUSTER_ID}/addon_instances/${ADDON}" | \
            jq -c '.config | fromjson | (.FeatureGate // "" | split(",")) as $fg | .FeatureGate = ($fg + $ARGS.positional | unique | join(",")) | {config: . | tojson}' --args "$@")
    
        aliyun cs POST "/clusters/${CLUSTER_ID}/components/${ADDON}/config" --header "Content-Type=application/json" --body "$CONFIG"
    
        echo "Waiting for $ADDON config to complete"
        while true; do
            STATE=$(aliyun --secure cs GET "/clusters/${CLUSTER_ID}/addon_instances/${ADDON}" | jq -r '.state')
            echo "state: $STATE"
            if [ "$STATE" != "updating" ]; then
                break
            fi
            sleep 5
        done
        if [ "$STATE" != "active" ]; then
            echo "Failed to update $ADDON config"
            return 1
        fi
    }
    
    check_version
    
    aliyun cs GET "/clusters/${CLUSTER_ID}/nodepools" | jq -r '.nodepools[]|.nodepool_info|"\(.nodepool_id)\t\(.name)"' | \
    while read -r NODE_POOL_ID NODE_POOL_NAME; do
        echo "Updating tags for node pool $NODE_POOL_NAME ($NODE_POOL_ID)"
        update_node_pool "$NODE_POOL_ID"
    done
    
    ALIBABA_CLOUD_REGION_ID=$(aliyun cs GET "/clusters/${CLUSTER_ID}" | jq -r .region_id)
    
    update_nodes
    
    update_addon $PROVISIONER DiskADController=true DiskParallelAttach=true
    update_addon csi-plugin DiskADController=true
    
    echo "All done!  Now the disks can be attached concurrently to the same node."
  2. Ejecute el script para montar los discos en modo paralelo.

    bash enable_parallel_attach.sh <Cluster ID>

Habilitar la función manualmente

  1. Agregue ECS Tags al node pool del clúster. Establezca la clave de la etiqueta en supportConcurrencyAttach y su valor en true. Asegúrese de que la etiqueta se agregue a una nueva instancia de ECS.

    1. Inicie sesión en la consola de ACK. En el panel de navegación izquierdo, haga clic en Clusters.

    2. En la página Clusters, haga clic en el nombre de su clúster. En el panel de navegación izquierdo, seleccione Nodes > Node Pools.

    3. En la página Node Pools, busque el node pool que desea modificar y haga clic en Edit dentro de la columna Actions.

    4. En la parte inferior de la página, ubique la sección Advanced y agregue una etiqueta en ECS Tags. Establezca la clave en supportConcurrencyAttach y el valor en true.

  2. Agregue una etiqueta a las instancias de ECS de todos los nodos existentes en el clúster. Establezca la clave en supportConcurrencyAttach y el valor en true. Para obtener más información, consulte Add a custom tag.

  3. En el panel de navegación izquierdo, haga clic en Components and Add-ons. Seleccione la pestaña Storage, busque el complemento csi-provisioner, haga clic en Configuration en la esquina inferior derecha del componente y establezca el parámetro FeatureGate en DiskADController=true,DiskParallelAttach=true.

    Nota

    Después de especificar DiskADController=true, csi-provisioner ejecuta las operaciones attach y detach relacionadas con los discos. Al especificar DiskParallelAttach=true, se habilita la función de montaje paralelo de discos.

  4. Una vez configurado csi-provisioner, establezca el parámetro FeatureGate de csi-plugin en DiskADController=true.

Comprobar el rendimiento del montaje paralelo de discos

En este ejemplo, se crean pods con una gran cantidad de discos montados en el mismo nodo. Esto permite comprobar la aceleración en el inicio de los pods tras habilitar el montaje paralelo.

Importante

Los resultados de las pruebas de este tema son valores de referencia. Los resultados reales pueden variar según su entorno.

  1. Agregue un nodo compatible con múltiples discos a un clúster de ACK. Por ejemplo, una instancia ecs.g7se.16xlarge admite hasta 56 discos.

  2. Cree un archivo de prueba llamado attach-stress.yaml y copie en él el siguiente contenido. Reemplace <YOUR-HOSTNAME> por el nombre real del nodo.

    Ver el archivo attach-stress.yaml

    ---
    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: alibabacloud-disk
    provisioner: diskplugin.csi.alibabacloud.com
    parameters:
      type: cloud_auto
    volumeBindingMode: WaitForFirstConsumer
    reclaimPolicy: Delete
    allowVolumeExpansion: true
    ---
    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: attach-stress
    spec:
      selector:
        matchLabels:
          app: attach-stress
      serviceName: attach-stress
      replicas: 1
      podManagementPolicy: Parallel
      persistentVolumeClaimRetentionPolicy:
        whenScaled: Retain
        whenDeleted: Delete
      template:
        metadata:
          labels:
            app: attach-stress
        spec:
          affinity:
            nodeAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
                nodeSelectorTerms:
                - matchExpressions:
                  - key: kubernetes.io/hostname
                    operator: In
                    values:
                    - <YOUR-HOSTNAME> # Replace this parameter with the actual name of the node. 
          hostNetwork: true
          containers:
          - name: attach-stress
            image: registry-cn-hangzhou.ack.aliyuncs.com/acs/busybox
            command: ["/bin/sh", "-c", "trap exit TERM; while true; do date > /mnt/0/data; sleep 1; done"]
            volumeMounts:
            - name: volume-0
              mountPath: /mnt/0
            - name: volume-1
              mountPath: /mnt/1
      volumeClaimTemplates:
      - metadata:
          name: volume-0
        spec:
          accessModes: [ "ReadWriteOnce" ]
          storageClassName: alibabacloud-disk
          resources:
            requests:
              storage: 1Gi
      - metadata:
          name: volume-1
        spec:
          accessModes: [ "ReadWriteOnce" ]
          storageClassName: alibabacloud-disk
          resources:
            requests:
              storage: 1Gi
  3. Ejecute el siguiente comando para confirmar que la aplicación inicia correctamente. Después, escale el número de réplicas a 0 para preparar las pruebas de montaje por lotes.

    kubectl apply -f attach-stress.yaml
    kubectl rollout status sts attach-stress
    kubectl scale sts attach-stress --replicas 0

    Resultado esperado:

    storageclass.storage.k8s.io/alibabacloud-disk created
    statefulset.apps/attach-stress created
    partitioned roll out complete: 1 new pods have been updated...
    statefulset.apps/attach-stress scaled
  4. Ejecute los siguientes comandos para iniciar la prueba de montaje por lotes y medir el tiempo de arranque de los pods:

    Nota

    En este caso, el montaje paralelo está deshabilitado para el clúster. Ajuste la cantidad de pods de la prueba según el número máximo de discos que admite su nodo.

    date && \
      kubectl scale sts attach-stress --replicas 28 && \
      kubectl rollout status sts attach-stress && \
      date

    Resultado esperado:

    Tuesday October 15 19:21:36 CST 2024
    statefulset.apps/attach-stress scaled
    Waiting for 28 pods to be ready...
    Waiting for 27 pods to be ready...
    <Omitted...>
    Waiting for 3 pods to be ready...
    Waiting for 2 pods to be ready...
    Waiting for 1 pods to be ready...
    partitioned roll out complete: 28 new pods have been updated...
    Tuesday October 15 19:24:55 CST 2024

    El resultado indica que se necesitan más de 3 minutos para iniciar los 28 pods cuando el montaje paralelo está deshabilitado.

  5. Habilite el montaje paralelo siguiendo las instrucciones de la sección Procedure.

  6. Ejecute el siguiente comando para eliminar los pods anteriores y preparar la siguiente ronda de pruebas:

    Nota

    Supervise los recursos volumeattachments del clúster. Una vez eliminados estos recursos, los discos se desmontarán. Este proceso tarda unos minutos.

    kubectl scale sts attach-stress --replicas 0
  7. Vuelva a ejecutar el siguiente comando para calcular el tiempo necesario para iniciar los pods con el montaje paralelo habilitado. Se espera que tarde aproximadamente 40 segundos, mucho menos que los 3 minutos requeridos sin esta función.

    date && \
      kubectl scale sts attach-stress --replicas 28 && \
      kubectl rollout status sts attach-stress && \
      date

    Resultado esperado:

    Tuesday October 15 20:02:54 CST 2024
    statefulset.apps/attach-stress scaled
    Waiting for 28 pods to be ready...
    Waiting for 27 pods to be ready...
    <Omitted...>
    Waiting for 3 pods to be ready...
    Waiting for 2 pods to be ready...
    Waiting for 1 pods to be ready...
    partitioned roll out complete: 28 new pods have been updated...
    Tuesday October 15 20:03:31 CST 2024
  1. Ejecute el siguiente comando para eliminar las aplicaciones de prueba del clúster:

    kubectl delete -f attach-stress.yaml