Rozpocznij pracę z rozproszonym akceleratorem dla magazynu w chmurze na platformie AKS (wersja zapoznawcza)

Ten przewodnik Szybki start umożliwia użycie rozproszonego akceleratora dla magazynu w chmurze (DACS) za pośrednictwem jego zarządzanego rozszerzenia na istniejącym klastrze Azure Kubernetes Service (AKS), przyznaje dostęp do odczytu do kontenera Azure Blob oraz weryfikuje, że powtarzane odczyty korzystają z pamięci podręcznej. Przykład obciążenia roboczego używa publicznego pakietu dacs-client==0.1.0.

Important

Rozproszony akcelerator do przechowywania w chmurze jest w wersji zapoznawczej. Funkcje w wersji zapoznawczej są udostępniane bez umowy dotyczącej poziomu usług i nie są zalecane w przypadku obciążeń produkcyjnych. Aby uzyskać więcej informacji, zobacz Warunki dodatkowe korzystania z testowych wersji Microsoft Azure.

Prerequisites

Przed rozpoczęciem potrzebne są następujące elementy:

  • Subskrypcja platformy Azure.
  • Istniejący klaster AKS spełniający wymagania wsparcia podglądowego DACS.
  • Pula węzłów pamięci podręcznej systemu Linux z lokalnymi dyskami danych NVMe, takimi jak rodzina maszyn wirtualnych Standard_L*s_v3.
  • Konto Azure Storage oraz kontener Blob zawierający reprezentatywne dane modelu.
  • Shell Bash z Azure CLI, kubectl, oraz Dockerem lub innym narzędziem do budowy obrazów kontenerowych. Wykonaj polecenia w tym szybkim starcie w tej samej sesji powłoki, aby zmienne pozostały dostępne.
  • Uprawnienia do instalacji rozszerzeń AKS, zarządzania zasobami Kubernetes, aktualizacji etykiet puli węzłów oraz przypisywania roli dostępu do danych pamięci masowej używanej w tym szybkim starcie.
  • Obraz obciążenia z Python 3.8 lub nowszym oraz glibc 2.35 lub nowszym. Ten przewodnik szybkiego startu korzysta z python:3.12-slim-bookworm i pakietu PyPI dacs-client==0.1.0 na węzłach x64.

Akcelerator rozproszony dla pamięci masowej w chmurze nie używa puli węzłów pamięci podręcznej jako trwałej pamięci. Azure Blob Storage pozostaje źródłem prawdy.

Wymagania dotyczące obsługi podglądu DACS

Requirement Obsługa podglądu DACS
Regiony Azure Wszystkie regiony chmury publicznej platformy Azure.
Wersje AKS Kubernetes 1.35 lub później.

Ustawianie zmiennych

Zamień wartości zastępcze, a następnie wykonaj następujące polecenia:

SUBSCRIPTION_ID=<subscription-id>
RESOURCE_GROUP=<resource-group>
CLUSTER_NAME=<aks-cluster-name>
CACHE_NODE_POOL=<nvme-node-pool>
STORAGE_ACCOUNT=<storage-account-name>
STORAGE_CONTAINER=<blob-container-name>
CACHE_NAMESPACE=dacs-cache-system
CACHE_NAME=cache-sample

az account set --subscription $SUBSCRIPTION_ID
az aks get-credentials \
  --resource-group $RESOURCE_GROUP \
  --name $CLUSTER_NAME

Upewnij się, że rozszerzenie AKS w wersji zapoznawczej jest zainstalowane

Podgląd DACS wymaga aks-preview wersji 22.0.0b9 lub nowszej wersji. Zainstaluj lub zaktualizuj rozszerzenie oraz rozszerzenia używane do zarządzania i inspekcji DAC-ów:

az extension add --name aks-preview --upgrade --yes
az extension show --name aks-preview --query version --output tsv
az extension add --name connectedk8s --upgrade --yes
az extension add --name k8s-extension --upgrade --yes

Nie musisz łączyć klastra AKS z Azure Arc. Jeśli już ręcznie zainstalowałeś kontroler DACS, postępuj zgodnie z instrukcjami w sekcji Przygotowanie do uaktualnień przed przejściem na zarządzane rozszerzenie. Nie używaj dwóch kontrolerów DACS na tym samym klastrze.

Zweryfikuj pulę węzłów cache

Potwierdź, że wybrana pula węzłów korzysta z systemu Linux i ma rozmiar maszyny wirtualnej z lokalnymi dyskami danych NVMe:

az aks nodepool show \
  --resource-group $RESOURCE_GROUP \
  --cluster-name $CLUSTER_NAME \
  --name $CACHE_NODE_POOL \
  --query '{osType:osType,vmSize:vmSize,count:count,powerState:powerState.code}' \
  --output table

Jeśli chodzi o rozproszone akceleratory do przechowywania w chmurze, użyj dedykowanej puli węzłów cache lub upewnij się, że inne oprogramowanie nie używa ani nie formatuje tych samych lokalnych dysków NVMe.

Oznacz pulę węzłów cache na poziomie puli węzłów, aby etykieta przetrwała wymianę węzłów. Jeśli pula już ma niestandardowe etykiety, uwzględnij je w aktualizacji, aby je zachować:

az aks nodepool update \
  --resource-group $RESOURCE_GROUP \
  --cluster-name $CLUSTER_NAME \
  --name $CACHE_NODE_POOL \
  --labels dacs.azure.com/processing-unit=cpu

Caution

Włączanie DACS instaluje wymagany DaemonSet, który wykrywa, formatuje i montuje lokalne dyski NVMe na oznaczonych węzłach cache. Oznaczaj tylko węzły z dyskami dedykowanymi do pamięci podręcznej.

Włącz rozproszony akcelerator dla pamięci masowej w chmurze

Włącz DACS, przekazując samo distributedAccelerator. Wymagana jest wielka literaA:

az aks update \
  --resource-group $RESOURCE_GROUP \
  --name $CLUSTER_NAME \
  --enable-azure-container-storage distributedAccelerator

Polecenie instaluje distributedaccelerator rozszerzenie zarządzane, kontroler DACS oraz zestaw DaemonSet wymagany przez NVMe w kube-system, a także niestandardową definicję zasobów caches.storage.azure.com (CRD). Nie instalujesz osobnego chartu zależności ani samodzielnie nie zarządzasz wydaniem Helm rozszerzenia. Stwórz osobno zasób pamięci podręcznej, jak pokazano później.

Weryfikowanie rozszerzenia

az k8s-extension show \
  --cluster-type managedClusters \
  --cluster-name $CLUSTER_NAME \
  --resource-group $RESOURCE_GROUP \
  --name distributedaccelerator \
  --query '{extensionType:extensionType,provisioningState:provisioningState,currentVersion:currentVersion,releaseTrain:releaseTrain}' \
  --output table

Potwierdź, że typ rozszerzenia to microsoft.distributedaccelerator, a stan aprowizacji to Succeeded. Zainstalowana wersja serwera jest podawana przez currentVersion; nie wnioskuj jej z wersji pakietu klienta ani z publicznego tagu obrazu.

Zanotuj tę wersję do diagnostyki, a następnie zweryfikuj kontroler i CRD:

DACS_VERSION=$(az k8s-extension show \
  --cluster-type managedClusters \
  --cluster-name $CLUSTER_NAME \
  --resource-group $RESOURCE_GROUP \
  --name distributedaccelerator \
  --query currentVersion --output tsv)

echo "$DACS_VERSION"
kubectl rollout status deployment/dacs-manager --namespace kube-system --timeout=5m
kubectl get crd caches.storage.azure.com

Kontynuuj dopiero po tym, jak rozszerzenie jest w stanie Succeeded i kontroler jest gotowy. Jeśli sprawdzanie instalacji lub gotowości zakończy się niepowodzeniem, zobacz Rozwiązywanie problemów z rozproszonym akceleratorem dla magazynu w chmurze.

Skonfiguruj pamięć podręczną

Weryfikacja lokalnego przygotowania NVMe

Zarządzane rozszerzenie przygotowuje lokalne dyski NVMe za pomocą swojego wymaganego DaemonSet. Nie wdrażaj zduplikowanego zadania konfiguracji dysku ani nie instaluj innego pakietu wymagań wstępnych.

kubectl rollout status daemonset/dacs-prereq \
  --namespace kube-system --timeout=10m

kubectl get daemonset dacs-prereq --namespace kube-system
kubectl get pods --namespace kube-system --selector app.kubernetes.io/name=dacs-prereq --output wide

Potwierdź, że DaemonSet ma pod Ready na każdym oznaczonym węźle cache. Punkt montażu to /var/lib/ssd/cacheserver i musi odpowiadać zasobowi pamięci podręcznej spec.storage.hostPath.nodeCacheFolderPath. Jeśli brakuje obiektu DaemonSet lub nie jest on gotowy, zatrzymaj się i sprawdź wersję rozszerzenia oraz zdarzenia poda wymagań wstępnych, zamiast instalować osobny chart.

Stwórz dedykowaną przestrzeń nazw dla pamięci podręcznej i testuj obciążenie:

kubectl create namespace "$CACHE_NAMESPACE"

Utworzenie zasobu pamięci podręcznej

Stwórz zasób Cache. Przykład konfiguruje trzy serwery pamięci podręcznej, po jednym na każdy oznaczony węzeł NVMe, i wymaga co najmniej trzech uprawnionych węzłów. Dostosuj liczbę serwerów, rozmiar pamięci podręcznej, procesor i pamięć do potrzeb puli węzłów.

cat <<EOF | kubectl apply -f -
apiVersion: storage.azure.com/v1
kind: Cache
metadata:
  name: $CACHE_NAME
  namespace: $CACHE_NAMESPACE
spec:
  scaling:
    static:
      numServers: 3
  serverSizeInGB: 1000
  serverThreads: 80
  cpuLimit: 4
  memoryLimitMB: 32000
  port: 9065
  metricsPort: 9096
  nodeSelectorKey: dacs.azure.com/processing-unit
  nodeSelectorValue: cpu
  storage:
    hostPath:
      nodeCacheFolderPath: /var/lib/ssd/cacheserver
EOF

Weryfikacja gotowości cache

Czekaj na nazwany zasób cache zamiast wybierać pierwszy cache w klastrze:

kubectl wait \
  --namespace $CACHE_NAMESPACE \
  --for=condition=Ready \
  cache/$CACHE_NAME \
  --timeout=10m

kubectl get cache,pods \
  --namespace $CACHE_NAMESPACE \
  --output wide

Sprawdź, czy aktualna i pożądana liczba serwerów pamięci podręcznej się zgadzają oraz czy każdy moduł serwera pamięci podręcznej działa na węźle NVMe.

Uzyskaj nazwę hosta discovery używaną przez klientów obciążenia:

CACHE_DISCOVERY_URL=$(kubectl get cache $CACHE_NAME \
  --namespace $CACHE_NAMESPACE \
  -o jsonpath='{.status.discoveryURL}')

echo $CACHE_DISCOVERY_URL

Przyznaj dostęp do odczytu danych modelu

Ten szybki start korzysta z zarządzanej tożsamości AKS kubelet. Uzyskaj ID obiektu oraz ID zasobu konta magazynowego:

KUBELET_OBJECT_ID=$(az aks show \
  --resource-group $RESOURCE_GROUP \
  --name $CLUSTER_NAME \
  --query identityProfile.kubeletidentity.objectId \
  --output tsv)

KUBELET_CLIENT_ID=$(az aks show \
  --resource-group $RESOURCE_GROUP \
  --name $CLUSTER_NAME \
  --query identityProfile.kubeletidentity.clientId \
  --output tsv)

STORAGE_ID=$(az storage account show \
  --resource-group $RESOURCE_GROUP \
  --name $STORAGE_ACCOUNT \
  --query id \
  --output tsv)

Przypisz rolę odczytu o najmniejszych uprawnieniach w zakresie kontenera:

az role assignment create \
  --assignee-object-id $KUBELET_OBJECT_ID \
  --assignee-principal-type ServicePrincipal \
  --role "Storage Blob Data Reader" \
  --scope "$STORAGE_ID/blobServices/default/containers/$STORAGE_CONTAINER"

Przydziały ról mogą trwać kilka minut, by się rozprzestrzenić. Aby użyć tożsamości kubelet, ustaw wszystkie trzy zmienne zarządzanej tożsamości pokazane w specyfikacji poda: AZURE_CLIENT_ID, MSI_ENDPOINT oraz niepuste MSI_SECRET. Samo ustawienie AZURE_CLIENT_ID nie wystarczy dla tej konfiguracji klienta.

Dodaj klienta do obrazu obciążenia roboczego

Stwórz plik o nazwie Dockerfile w swoim katalogu budowania z następującą zawartością. Nazwa dystrybucji to dacs-client, a przestrzeń nazw importu Python to py_dacs_client:

FROM python:3.12-slim-bookworm
RUN python3 -m pip install --no-cache-dir "dacs-client==0.1.0"

Zbuduj i wyślij obraz do rejestru, z którego może pobierać twój klaster AKS. W przypadku Azure Container Registry (ACR) zaloguj się przed wypchnięciem i upewnij się, że tożsamość kubeleta ma dostęp do pobierania obrazów. Dla rejestru korzystającego z RBAC Registry Permissions, przyznaj AcrPull w zakresie rejestru. W przypadku rejestru obsługującego ABAC należy zamiast tego użyć odpowiedniej roli repository-reader. Szczegóły znajdziesz w artykule Uwierzytelnianie w usłudze Azure Container Registry z poziomu usługi Azure Kubernetes Service.

WORKLOAD_IMAGE=<registry-name>.azurecr.io/dacs-test:0.1.0

docker build \
  --tag $WORKLOAD_IMAGE .
docker push $WORKLOAD_IMAGE

Wdróż test tylko do odczytu

Wybierz istniejący model blob i wyznacz jego ścieżkę:

MODEL_BLOB=<path-to-model-blob>

Utwórz testowy pod. Kapsuła odczytuje do 4 MiB z blobu pięć razy, z jednosekundową przerwą między odczytami, i weryfikuje, że wszystkie odczyty zwracają tę samą sumę kontrolną SHA-256. Zapełnianie pamięci podręcznej odbywa się asynchronicznie, więc natychmiastowy drugi odczyt może nie trafić do pamięci podręcznej. Interwały te dają czas na ukończenie przesyłania w tle; używaj metryk klienta i liczników serwera do potwierdzenia trafień do pamięci podręcznej, zamiast zakładać, że dany odczyt jest trafieniem w pamięci podręcznej. Aby porównać liczniki serwera, zarejestruj linię bazową przed utworzeniem podu, postępując zgodnie z instrukcjami w Weryfikowanie ścieżki żądania DACS.

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: dacs-test
  namespace: $CACHE_NAMESPACE
spec:
  restartPolicy: Never
  containers:
    - name: test
      image: $WORKLOAD_IMAGE
      env:
        - name: CACHE_DISCOVERY_URL
          value: "$CACHE_DISCOVERY_URL"
        - name: CACHE_SERVER_PORT
          value: "9065"
        - name: DACS_CPU_CORES
          value: "2"
        - name: DACS_MEMORY_MB
          value: "512"
        - name: AZURE_CLIENT_ID
          value: "$KUBELET_CLIENT_ID"
        - name: MSI_ENDPOINT
          value: "http://169.254.169.254/metadata/identity/oauth2/token"
        - name: MSI_SECRET
          value: "required-nonempty-value"
        - name: MODEL_PATH
          value: "az://$STORAGE_ACCOUNT.blob.core.windows.net/$STORAGE_CONTAINER/$MODEL_BLOB"
      command: ["python3", "-c"]
      resources:
        requests:
          cpu: "1"
          memory: 512Mi
        limits:
          cpu: "2"
          memory: 1Gi
      args:
        - |
          import asyncio
          import ctypes
          import hashlib
          import os
          import time

          from py_dacs_client.dacs_client import DACSCacheClient
          from py_dacs_client.dacs_utils import BoundedBufferManager

          async def main():
              path = os.environ["MODEL_PATH"]
              client = DACSCacheClient()
              buffers = BoundedBufferManager(max_memory_limit=64 * 1024 * 1024)
              try:
                  size = min(await client.get_file_size(path), 4 * 1024 * 1024)
                  if size == 0:
                      raise ValueError("Choose a nonempty model blob")
                  first_digest = None
                  for attempt in range(1, 6):
                      start = time.perf_counter()
                      buffer = await buffers.acquire_buffer(size)
                      try:
                          count = await client.read_blob(path, buffer, size, 0)
                          if count != size:
                              raise RuntimeError(f"Expected {size} bytes, received {count}")
                          digest = hashlib.sha256(ctypes.string_at(buffer, count)).hexdigest()
                          if first_digest is not None and digest != first_digest:
                              raise RuntimeError("Repeated reads returned different data")
                          first_digest = digest
                      finally:
                          await buffers.release_buffer(buffer)
                      elapsed = time.perf_counter() - start
                      print(f"read {attempt}: {count} bytes in {elapsed:.3f}s; sha256={digest}")
                      if attempt < 5:
                          await asyncio.sleep(1)
              finally:
                  await client.shutdown()

          asyncio.run(main())
EOF

kubectl wait \
  --namespace "$CACHE_NAMESPACE" \
  --for=jsonpath='{.status.phase}'=Succeeded \
  pod/dacs-test \
  --timeout=5m

kubectl logs dacs-test --namespace "$CACHE_NAMESPACE"

Zweryfikuj ścieżkę żądań DACS

Sam fakt udanego odczytu lub szybszego drugiego odczytu nie stanowi dowodu na to, że żądanie dotarło do usługi DACS, ponieważ klient może przełączyć się awaryjnie na Azure Blob Storage. Ustaw zarówno CACHE_DISCOVERY_URL, jak i CACHE_SERVER_PORT. Jeśli któregoś z nich brakuje, klient zapisuje w logach Cache not configured. Working in Remote Blob mode only.

Sprawdź logi podu pod kątem metryk wyłączenia klienta cache_client_download_cache_hits i cache_client_download_cache_misses. Niezerowa liczba trafień w cache oznacza, że żądanie zostało obsłużone z pamięci podręcznej. Liczniki klientów mogą zawierać wewnętrzne żądania i niekoniecznie odpowiadają liczbie odczytów aplikacji.

Porównaj także liczniki żądań serwera pamięci podręcznej przed i po uruchomieniu testu. Sprawdź każdy pod serwera cache, ponieważ żądanie może być obsługiwane przez dowolny serwer, niekoniecznie przez pierwszy pod. Aby sprawdzić jeden serwer:

CACHE_POD=$(kubectl get pods \
  --namespace $CACHE_NAMESPACE \
  --selector app=cacheserver \
  -o jsonpath='{.items[0].metadata.name}')

kubectl port-forward \
  --namespace $CACHE_NAMESPACE \
  pod/$CACHE_POD 9096:9096

W innym terminalu pobierz metryki i sprawdź licznik żądań:

curl --fail --silent --show-error http://localhost:9096/metrics > dacs-metrics.txt
grep '^cache_server_request_counter' dacs-metrics.txt

Potwierdź wzrost liczby żądań pobierania za pomocą request_type="Download" i status="Success", a nie tylko obecność serii liczników, która może występować przy wartości zero. Wartości etykiet rozróżniają wielkość liter. Zatrzymaj przekierowanie portów i powtórz to dla innych podów cache-server w razie potrzeby. Koreluj metryki trafień pamięci podręcznej klienta z licznikami serwera i telemetrią Azure Blob, aby rozróżnić trafienia pamięci podręcznej, ruch do serwera źródłowego i działanie mechanizmu awaryjnego.

Pełne informacje o metrykach i konfiguracji scrape można znaleźć w Monitorowanie rozproszonego akceleratora dla pamięci masowej w chmurze.

Wyczyść test

kubectl delete pod dacs-test --namespace "$CACHE_NAMESPACE"

Jeśli już nie potrzebujesz pamięci podręcznej, usuń zasób Cache podczas działania kontrolera:

kubectl delete cache "$CACHE_NAME" --namespace "$CACHE_NAMESPACE" --wait=true
kubectl get cache -A

Usuń przestrzeń nazw tylko wtedy, gdy była dedykowana temu Szybkiemu startowi i nie zawiera żadnych zasobów, które musisz zachować:

kubectl delete namespace "$CACHE_NAMESPACE"

Po usunięciu wszystkich zasobów pamięci podręcznej i zależnych obciążeń wyłącz zarządzane rozszerzenie:

az aks update \
  --resource-group $RESOURCE_GROUP \
  --name $CLUSTER_NAME \
  --disable-azure-container-storage distributedAccelerator

Wyłączenie DACS usuwa zarządzane rozszerzenie, kontroler oraz wymagany DaemonSet, ale zachowuje CRD pamięci podręcznej. Nie usuwaj zarządzanych zależności wstępnych osobno, nie odinstalowuj bezpośrednio wydania Helm rozszerzenia ani nie usuwaj ręcznie CRD. Usuń wszelkie przypisania ról lub etykiety puli węzłów dodane wyłącznie dla tego szybkiego startu dopiero po potwierdzeniu, że żadne inne obciążenie tego nie wymaga.

Więcej informacji można znaleźć w artykule Usuń rozproszony akcelerator dla przechowywania w chmurze.

Następne kroki