Regionale Notfallwiederherstellung für Azure Databricks-Cluster

Dieser Artikel enthält Informationen zu einer praktischen Notfallwiederherstellungsarchitektur für Azure Databricks-Cluster sowie die notwendigen Schritte.

Azure Databricks-Architektur

Wenn Sie über das Azure-Portal einen Azure Databricks-Arbeitsbereich erstellen, wird in Ihrem Abonnement eine verwaltete Anwendung als Azure-Ressource in der ausgewählten Azure-Region (beispielsweise „USA, Westen“) bereitgestellt. Diese Appliance wird in einem virtuellen Azure-Netzwerk mit einer Netzwerksicherheitsgruppe und einem in Ihrem Abonnement verfügbaren Azure Storage-Konto bereitgestellt. Das virtuelle Netzwerk bietet Sicherheit auf Umgebungsebene für den Databricks-Arbeitsbereich und wird durch die Netzwerksicherheitsgruppe geschützt. Innerhalb des Arbeitsbereichs erstellen Sie Databricks-Cluster, indem Sie den VM-Typ für Worker und Treiber sowie die Databricks-Laufzeitversion angeben. Die persistenten Daten sind in Ihrem Speicherkonto verfügbar. Nach der Clustererstellung können Sie Aufträge über Notebooks, REST-APIs oder ODBC/JDBC-Endpunkte ausführen, indem Sie sie an einen bestimmten Cluster anfügen.

Die Databricks-Steuerungsebene verwaltet und überwacht die Umgebung des Databricks-Arbeitsbereichs. Verwaltungsvorgänge wie etwa das Erstellen eines Clusters werden über die Steuerungsebene initiiert. Alle Metadaten, z. B. geplante Aufträge, werden in einer Azure-Datenbank gespeichert, und die Datenbanksicherungen werden automatisch in gekoppelte Regionen georepliziert, in denen sie implementiert werden.

Databricks architecture

Diese Architektur hat unter anderem den Vorteil, dass Benutzer Azure Databricks mit jeder beliebigen Speicherressource ihres Kontos verknüpfen können. Ein weiterer entscheidender Vorteil besteht darin, dass die Computekomponenten (Azure Databricks) und die Speicherkomponente unabhängig voneinander skaliert werden können.

Erstellen einer Topologie für die regionale Notfallwiederherstellung

In der vorangegangenen Architekturbeschreibung werden mehrere Komponenten für eine Big Data-Pipeline mit Azure Databricks verwendet. Dazu zählen unter anderem Azure Storage, Azure-Datenbank und andere Datenquellen. Azure Databricks ist die Computekomponente für die Big Data-Pipeline. Sie ist von Natur aus kurzlebig. Das bedeutet, Ihre Daten stehen weiterhin in Azure Storage zur Verfügung, die Computekomponente (Azure Databricks-Cluster) kann jedoch beendet werden, damit Sie nicht für Computefunktionen bezahlen müssen, wenn Sie sie nicht benötigen. Die Computekomponente (Azure Databricks) und die Speicherquellen müssen sich in der gleichen Region befinden, um lange Wartezeiten bei Aufträgen zu vermeiden.

Wenn Sie eine eigene Topologie für die regionale Notfallwiederherstellung erstellen möchten, gehen Sie wie folgt vor:

  1. Stellen Sie mehrere Azure Databricks-Arbeitsbereiche in separaten Azure-Regionen bereit. Erstellen Sie den primären Azure Databricks-Arbeitsbereich beispielsweise in „USA, Osten“. Erstellen Sie den sekundären Azure Databricks-Arbeitsbereich für die Notfallwiederherstellung in einer separaten Region (beispielsweise „USA, Westen“). Eine Liste der gekoppelten Azure-Regionen finden Sie unter Regionsübergreifende Replikation. Ausführliche Informationen zu Azure Databricks-Regionen finden Sie unter Unterstützte Regionen.

  2. Verwenden Sie georedundanten Speicher. Standardmäßig werden die mit Azure Databricks verknüpften Daten in Azure Storage und die Ergebnisse von Databricks-Aufträgen in Azure Blob Storage gespeichert. Dies gewährleistet die Dauerhaftigkeit der Daten und sorgt dafür, dass sie nach Beendigung des Clusters weiterhin hochverfügbar sind. Clusterspeicher und Auftragsspeicher befinden sich in der gleichen Verfügbarkeitszone. Zum Schutz vor regionaler Nichtverfügbarkeit wird von Azure Databricks-Arbeitsbereichen standardmäßig georedundanter Speicher verwendet. Bei georedundantem Speicher werden Daten in einer gekoppelten Azure-Region repliziert. Databricks empfiehlt, den standardmäßigen georedundanten Speicher beizubehalten. Wenn Sie jedoch stattdessen lokal redundanten Speicher verwenden müssen, können Sie storageAccountSkuName in der ARM-Vorlage für den Arbeitsbereich auf Standard_LRS festlegen.

  3. Nach Erstellung der sekundären Region müssen Sie Benutzer, Benutzerordner, Notebooks, Clusterkonfiguration, Auftragskonfiguration, Bibliotheken, Speicher und Initialisierungsskripts migrieren und die Zugriffssteuerung neu konfigurieren. Ausführlichere Informationen finden Sie im folgenden Abschnitt.

Regionale Notfälle

Um für regionale Notfälle gerüstet zu sein, müssen Sie explizit einen weiteren Satz von Azure Databricks-Arbeitsbereichen in einer sekundären Region verwalten. Siehe Notfallwiederherstellung.

Unsere empfohlenen Tools für die Notfallwiederherstellung sind hauptsächlich Terraform (für die Infrastrukturreplikation) und Delta Deep Clone (für die Datenreplikation).

Ausführliche Migrationsschritte

  1. Einrichten der Databricks-Befehlszeilenschnittstelle auf Ihrem Computer

    Dieser Artikel enthält eine Reihe von Codebeispielen, in denen für die meisten der automatisierten Schritte die Befehlszeilenschnittstelle verwendet wird, da es sich dabei um einen benutzerfreundlichen Wrapper für die REST-API von Azure Databricks handelt.

    Installieren Sie zunächst die Databricks-Befehlszeilenschnittstelle auf Ihrem Desktopcomputer oder auf einem virtuellen Computer, auf dem Sie die Migrationsschritte ausführen möchten. Weitere Informationen finden Sie in der Dokumentation zur Databricks-Befehlszeilenschnittstelle.

    pip install databricks-cli
    

    Hinweis

    Alle in diesem Artikel bereitgestellten Python-Skripts sollten für Python 2.7 und höher sowie 3.x geeignet sein.

  2. Konfigurieren zweier Profile

    Konfigurieren Sie ein Profil für den primären und ein Profil für den sekundären Arbeitsbereich:

    databricks configure --profile primary --token
    databricks configure --profile secondary --token
    

    Die Codeblöcke in diesem Artikel wechseln in jedem Folgeschritt mithilfe des entsprechenden Arbeitsbereichsbefehls zwischen den Profilen. Achten Sie darauf, die Namen der von Ihnen erstellten Profile in den einzelnen Codeblocks zu ersetzen.

    EXPORT_PROFILE = "primary"
    IMPORT_PROFILE = "secondary"
    

    Sie können bei Bedarf manuell über die Befehlszeile wechseln:

    databricks workspace ls --profile primary
    databricks workspace ls --profile secondary
    
  3. Microsoft Entra ID (früher Azure Active Directory)-Benutzer

    Fügen Sie dieselben Microsoft Entra ID-Benutzer*innen (früher Azure Active Directory) aus dem primären Arbeitsbereich manuell dem sekundären Arbeitsbereich hinzu.

  4. Migrieren der Benutzerordner und Notebooks

    Verwenden Sie den folgenden Python-Code, um die Sandbox-Benutzerumgebungen einschließlich der benutzerspezifischen geschachtelten Ordnerstruktur und Notebooks zu migrieren.

    Hinweis

    Bibliotheken werden in diesem Schritt nicht kopiert, da sie von der zugrunde liegenden API nicht unterstützt werden.

    Kopieren Sie das folgende Python-Skript, speichern Sie es in einer Datei, und führen Sie sie über die Databricks-Befehlszeile aus. Beispiel: python scriptname.py.

    import sys
    import os
    import subprocess
    from subprocess import call, check_output
    
    EXPORT_PROFILE = "primary"
    IMPORT_PROFILE = "secondary"
    
    # Get a list of all users
    user_list_out = check_output(["databricks", "workspace", "ls", "/Users", "--profile", EXPORT_PROFILE])
    user_list = (user_list_out.decode(encoding="utf-8")).splitlines()
    
    print (user_list)
    
    # Export sandboxed environment(folders, notebooks) for each user and import into new workspace.
    #Libraries are not included with these APIs / commands.
    
    for user in user_list:
      #print("Trying to migrate workspace for user ".decode() + user)
      print (("Trying to migrate workspace for user ") + user)
    
      subprocess.call(str("mkdir -p ") + str(user), shell = True)
      export_exit_status = call("databricks workspace export_dir /Users/" + str(user) + " ./" + str(user) + " --profile " + EXPORT_PROFILE, shell = True)
    
      if export_exit_status==0:
        print ("Export Success")
        import_exit_status = call("databricks workspace import_dir ./" + str(user) + " /Users/" + str(user) + " --profile " + IMPORT_PROFILE, shell=True)
        if import_exit_status==0:
          print ("Import Success")
        else:
          print ("Import Failure")
      else:
        print ("Export Failure")
    print ("All done")
    
  5. Migrieren der Clusterkonfigurationen

    Nach der Notebookmigration können Sie optional die Clusterkonfigurationen zum neuen Arbeitsbereich migrieren. Hierbei handelt es sich um einen nahezu vollständig automatisierten Schritt über die Databricks-Befehlszeilenschnittstelle (es sei denn, Sie möchten nur bestimmte Clusterkonfigurationen migrieren).

    Hinweis

    Leider gibt es keinen Endpunkt für die Clusterkonfigurationserstellung, und dieses Skript versucht, jeden Cluster sofort zu erstellen. Sollten in Ihrem Abonnement nicht genügend Kerne zur Verfügung stehen, ist die Clustererstellung unter Umständen nicht erfolgreich. Der Fehler kann ignoriert werden, solange die Konfiguration erfolgreich übertragen wurde.

    Das folgende Skript gibt eine Zuordnung zwischen alten und neuen Cluster-IDs aus, die später für die Auftragsmigration verwendet werden kann (für Aufträge, die zur Verwendung vorhandener Cluster konfiguriert sind).

    Kopieren Sie das folgende Python-Skript, speichern Sie es in einer Datei, und führen Sie sie über die Databricks-Befehlszeile aus. Beispiel: python scriptname.py.

    import sys
    import os
    import subprocess
    import json
    from subprocess import call, check_output
    
    EXPORT_PROFILE = "primary"
    IMPORT_PROFILE = "secondary"
    
    # Get all clusters info from old workspace
    clusters_out = check_output(["databricks", "clusters", "list",    "--profile", EXPORT_PROFILE])
    clusters_info_list = str(clusters_out.decode(encoding="utf-8")).   splitlines()
    print("Printting Cluster info List")
    print(clusters_info_list)
    
    # Create a list of all cluster ids
    clusters_list = []
    ##for cluster_info in clusters_info_list: clusters_list.append   (cluster_info.split(None, 1)[0])
    
    for cluster_info in clusters_info_list:
       if cluster_info != '':
          clusters_list.append(cluster_info.split(None, 1)[0])
    
    # Optionally filter cluster ids out manually, so as to create only required ones in new workspace
    
    # Create a list of mandatory / optional create request elements
    cluster_req_elems = ["num_workers","autoscale","cluster_name","spark_version","spark_conf","node_type_id","driver_node_type_id","custom_tags","cluster_log_conf","spark_env_vars","autotermination_minutes","enable_elastic_disk"]
    print("Printing Cluster element List")
    print (cluster_req_elems)
    print(str(len(clusters_list)) + " clusters found in the primary site" )
    
    print ("---------------------------------------------------------")
    # Try creating all / selected clusters in new workspace with same config as in old one.
    cluster_old_new_mappings = {}
    i = 0
    for cluster in clusters_list:
       i += 1
       print("Checking cluster " + str(i) + "/" + str(len(clusters_list)) + " : " +str(cluster))
       cluster_get_out_f = check_output(["databricks", "clusters", "get", "--cluster-id", str(cluster), "--profile", EXPORT_PROFILE])
       cluster_get_out=str(cluster_get_out_f.decode(encoding="utf-8"))
       print ("Got cluster config from old workspace")
       print (cluster_get_out)
        # Remove extra content from the config, as we need to build create request with allowed elements only
       cluster_req_json = json.loads(cluster_get_out)
       cluster_json_keys = cluster_req_json.keys()
    
       #Don't migrate Job clusters
       if cluster_req_json['cluster_source'] == u'JOB' :
          print ("Skipping this cluster as it is a Job cluster : " + cluster_req_json['cluster_id'] )
          print ("---------------------------------------------------------")
          continue
    
          #cluster_req_json.pop(key, None)
          for key in cluster_json_keys:
            if key not in cluster_req_elems:
             print (cluster_req_json)
             #cluster_del_item=cluster_json_keys .keys()
             cluster_req_json.popitem(key, None)
    
       # Create the cluster, and store the mapping from old to new cluster ids
    
       #Create a temp file to store the current cluster info as JSON
       strCurrentClusterFile = "tmp_cluster_info.json"
    
       #delete the temp file if exists
       if os.path.exists(strCurrentClusterFile) :
          os.remove(strCurrentClusterFile)
    
       fClusterJSONtmp = open(strCurrentClusterFile,"w+")
       fClusterJSONtmp.write(json.dumps(cluster_req_json))
       fClusterJSONtmp.close()
    
       #cluster_create_out = check_output(["databricks", "clusters", "create", "--json", json.dumps(cluster_req_json), "--profile", IMPORT_PROFILE])
       cluster_create_out = check_output(["databricks", "clusters", "create", "--json-file", strCurrentClusterFile , "--profile", IMPORT_PROFILE])
       cluster_create_out_json = json.loads(cluster_create_out)
       cluster_old_new_mappings[cluster] = cluster_create_out_json['cluster_id']
    
       print ("Cluster create request sent to secondary site workspace successfully")
       print ("---------------------------------------------------------")
    
       #delete the temp file if exists
       if os.path.exists(strCurrentClusterFile) :
          os.remove(strCurrentClusterFile)
    
    print ("Cluster mappings: " + json.dumps(cluster_old_new_mappings))
    print ("All done")
    print ("P.S. : Please note that all the new clusters in your secondary site are being started now!")
    print ("       If you won't use those new clusters at the moment, please don't forget terminating your new clusters to avoid charges")
    
  6. Migrieren der Auftragskonfiguration

    Wenn Sie im vorherigen Schritt Clusterkonfigurationen migriert haben, können Sie optional auch Auftragskonfigurationen zum neuen Arbeitsbereich migrieren. Hierbei handelt es sich um einen vollständig automatisierten Schritt über die Databricks-Befehlszeilenschnittstelle (es sei denn, Sie möchten nur bestimmte Auftragskonfigurationen migrieren).

    Hinweis

    Die Konfiguration für einen geplanten Auftrag enthält auch die Zeitplaninformationen, sodass standardmäßig der Auftrag nach der Migration gemäß dem konfigurierten Zeitplan ausgeführt wird. Der folgende Codeblock entfernt daher bei der Migration alle Zeitplaninformationen, um doppelte Ausführungen in alten und neuen Arbeitsbereichen zu vermeiden. Konfigurieren Sie die Zeitpläne für Aufträge dieser Art, wenn Sie für die Übernahme bereit sind.

    Die Auftragskonfiguration erfordert Einstellungen für einen neuen oder bereits vorhandenen Cluster. Bei Verwendung eines bereits vorhandenen Clusters versucht das folgende Skript bzw. der folgende Code, die alte Cluster-ID durch eine neue Cluster-ID zu ersetzen.

    Kopieren Sie das folgende Python-Skript, und speichern Sie es in einer Datei. Ersetzen Sie den Wert für old_cluster_id und new_cluster_id durch die Ausgabe der Clustermigration aus dem vorherigen Schritt. Führen Sie es über die Befehlszeile der Databricks-Befehlszeilenschnittstelle aus (Beispiel: python scriptname.py).

    import sys
    import os
    import subprocess
    import json
    from subprocess import call, check_output
    
    
    EXPORT_PROFILE = "primary"
    IMPORT_PROFILE = "secondary"
    
    # Please replace the old to new cluster id mappings from cluster migration output
    cluster_old_new_mappings = {"0227-120427-tryst214": "0229-032632-paper88"}
    
    # Get all jobs info from old workspace
    try:
      jobs_out = check_output(["databricks", "jobs", "list", "--profile", EXPORT_PROFILE])
      jobs_info_list = jobs_out.splitlines()
    except:
      print("No jobs to migrate")
      sys.exit(0)
    
    # Create a list of all job ids
    jobs_list = []
    for jobs_info in jobs_info_list:
      jobs_list.append(jobs_info.split(None, 1)[0])
    
    # Optionally filter job ids out manually, so as to create only required ones in new workspace
    
    # Create each job in the new workspace based on corresponding settings in the old workspace
    
    for job in jobs_list:
      print("Trying to migrate ") + job
    
      job_get_out = check_output(["databricks", "jobs", "get", "--job-id", job, "--profile", EXPORT_PROFILE])
      print("Got job config from old workspace")
    
      job_req_json = json.loads(job_get_out)
      job_req_settings_json = job_req_json['settings']
    
      # Remove schedule information so job doesn't start before proper cutover
      job_req_settings_json.pop('schedule', None)
    
      # Replace old cluster id with new cluster id, if job configured to run against an existing cluster
      if 'existing_cluster_id' in job_req_settings_json:
        if job_req_settings_json['existing_cluster_id'] in cluster_old_new_mappings:
          job_req_settings_json['existing_cluster_id'] = cluster_old_new_mappings[job_req_settings_json['existing_cluster_id']]
        else:
          print("Mapping not available for old cluster id ") + job_req_settings_json['existing_cluster_id']
          continue
    
      call(["databricks", "jobs", "create", "--json", json.dumps(job_req_settings_json), "--profile", IMPORT_PROFILE])
      print("Sent job create request to new workspace successfully")
    
    print("All done")
    
  7. Migrieren der Bibliotheken

    Bibliotheken können derzeit nicht ohne Weiteres zwischen Arbeitsbereichen migriert werden. Sie müssen stattdessen manuell im neuen Arbeitsbereich installiert werden. Es ist möglich, den Vorgang durch eine Kombination aus DBFS-CLI (zum Hochladen von benutzerdefinierten Bibliotheken in den Arbeitsbereich) und Bibliotheken-CLI zu automatisieren.

  8. Migrieren von Azure Blob Storage- und Azure Data Lake Storage-Einbindungen

    Binden Sie alle Azure Blob Storage- und Azure Data Lake Storage (Gen2)-Bereitstellungspunkte mithilfe einer notebookbasierten Lösung manuell ein. Die Speicherressourcen waren im primären Arbeitsbereich bereitgestellt, und dies muss im sekundären Arbeitsbereich wiederholt werden. Für Einbindungen steht keine externe API zur Verfügung.

  9. Migrieren von Clusterinitialisierungsskripts

    Clusterinitialisierungsskripts können mithilfe der DBFS-CLI vom alten zum neuen Arbeitsbereich migriert werden. Kopieren Sie zunächst die benötigten Skripts von dbfs:/dat abricks/init/.. auf Ihren lokalen Desktopcomputer oder auf Ihren virtuellen Computer. Kopieren Sie die Skripts anschließend an den gleichen Pfad im neuen Arbeitsbereich.

    // Primary to local
    dbfs cp -r dbfs:/databricks/init ./old-ws-init-scripts --profile primary
    
    // Local to Secondary workspace
    dbfs cp -r old-ws-init-scripts dbfs:/databricks/init --profile secondary
    
  10. Manuelles Konfigurieren und Anwenden der Zugriffssteuerung

    Wenn Ihr vorhandener primärer Arbeitsbereich für die Premium- oder Enterprise-Stufe (SKU) konfiguriert ist, verwenden Sie wahrscheinlich auch die Funktion Zugriffskontrolle.

    Wenn Sie das Zugriffssteuerungsfeature verwenden, wenden Sie die Zugriffssteuerung manuell auf die Ressourcen (Notebooks, Cluster, Aufträge, Tabellen) an.

Notfallwiederherstellung für Ihr Azure-Ökosystem

Wenn Sie andere Azure-Dienste verwenden, achten Sie darauf, bewährte Methoden für die Notfallwiederherstellung auch für diese Dienste zu implementieren. Wenn Sie z. B. eine externe Hive-Metastore-Instanz verwenden möchten, sollten Sie die Notfallwiederherstellung für Azure SQL-Datenbank, Azure HDInsight und/oder Azure Database for MySQL berücksichtigen. Allgemeine Informationen zur Notfallwiederherstellung finden Sie unter Notfallwiederherstellung für Azure-Anwendungen.

Nächste Schritte

Weitere Informationen finden Sie in der Dokumentation zu Azure Databricks.