Snowpark Container Services: Zusätzliche Hinweise zu Diensten und Jobs

Wichtig

Das Job-Feature von Snowpark Container Services befindet sich derzeit in der privaten Vorschau und unterliegt den Nutzungsbedingungen für Vorschau-Features unter https://snowflake.com/legal. Weitere Informationen dazu erhalten Sie bei Ihrem Snowflake-Ansprechpartner.

Verbinden mit Snowflake aus einem Container heraus

Wenn Sie einen Dienst oder Job starten, stellt Snowflake den aktiven Containern Anmeldeinformationen zur Verfügung, damit Ihr Containercode Treiber für die Verbindung zu Snowflake und das Ausführen von SQL verwenden kann (ähnlich wie jeder andere Code auf Ihrem Computer, der sich mit Snowflake verbindet). Die angegebenen Anmeldeinformationen authentifizieren sich als Dienstrolle. Snowflake stellt einige der Informationen als Umgebungsvariablen in Ihren Containern bereit.

Jedes Objekt in Snowflake hat eine Eigentümerrolle. Im Falle eines Dienstes oder Jobs hat Snowflake ein Konzept, das als Dienstrolle bezeichnet wird (dieser Begriff gilt sowohl für Dienste als auch für Jobs). Die Dienstrolle bestimmt, welche Funktionen Ihr Dienst bei der Interaktion mit Snowflake ausführen darf. Dazu gehören das Ausführen von SQL, der Zugriff auf Stagingbereiche und die Vernetzung zwischen Diensten.

Bemerkung

In der derzeitigen Implementierung ist die Dienstrolle mit der Eigentümerrolle identisch.

So erstellen Sie beispielsweise die Rolle test_role als Teil der grundlegenden Einrichtung für die Tutorials. Sie erteilen der Rolle die erforderlichen Berechtigungen und verwenden die Rolle dann beim Erstellen eines Dienstes und Jobs. Diese Rolle ist sowohl die Eigentümerrolle des Dienstes oder Jobs als auch die Dienstrolle, die die Berechtigungen des Dienstes oder Jobs bestimmt.

Bemerkung

Dienstrollen können keine der Rollen mit weitreichenden Berechtigungen wie ACCOUNTADMIN, SECURITYADMIN und ORGADMIN sein.

Wenn Sie einen Dienst erstellen, erstellt Snowflake auch einen „Dienstbenutzer“ für diesen Dienst. Wenn der Dienst eine Abfrage ausführt, führt er die Abfrage als der Dienstbenutzer aus. Was der Dienstbenutzer tun kann, wird durch die Dienstrolle bestimmt.

Verbinden mit Snowflake

Snowflake stellt die folgenden Umgebungsvariablen zur Verfügung, mit denen Sie einen Snowflake-Client in Ihrem Dienst-/Jobcode konfigurieren können:

  • SNOWFLAKE_ACCOUNT: Gibt den Namen des Snowflake-Kontos an, unter dem der Dienst derzeit ausgeführt wird.

  • SNOWFLAKE_HOST: Gibt den Hostnamen an, der für die Verbindung zu Snowflake verwendet wird.

Snowflake stellt auch ein OAuth-Token im Container in einer Datei namens /snowflake/session/token bereit. Wenn Sie eine Verbindung herstellen, geben Sie dieses Token an den Konnektor weiter.

Wenn Sie eine Verbindung zu Snowflake von einem Container aus erstellen, müssen Sie SNOWFLAKE_HOST, SNOWFLAKE_ACCOUNT und das OAuth-Token verwenden. Sie können das OAuth-Token nur verwenden, wenn Sie auch SNOWFLAKE_HOST verwenden, und Sie können das OAuth-Token nicht außerhalb von Snowpark Container Services verwenden. Weitere Informationen dazu finden Sie unter Verwenden eines OAuth-Tokens zum Ausführen von SQL.

Beispiele

  • In Tutorial 2 (siehe main.py) liest der Code die Umgebungsvariablen wie folgt:

    SNOWFLAKE_ACCOUNT = os.getenv('SNOWFLAKE_ACCOUNT')
    SNOWFLAKE_HOST = os.getenv('SNOWFLAKE_HOST')
    
    Copy

    Der Code übergibt diese Variablen an einen Verbindungserstellungscode für den Snowflake-Client Ihrer Wahl. Der Container verwendet diese Anmeldeinformationen, um eine neue Sitzung mit der Dienstrolle als Primärrolle zu erstellen, um Abfragen auszuführen. Der folgende Beispielcode zeigt, was mindestens zum Erstellen einer Snowflake-Verbindung in Python erforderlich ist:

    def get_login_token():
      with open('/snowflake/session/token', 'r') as f:
        return f.read()
    
    conn = snowflake.connector.connect(
      host = os.getenv('SNOWFLAKE_HOST'),
      account = os.getenv('SNOWFLAKE_ACCOUNT'),
      token = get_login_token(),
      authenticator = 'oauth'
    )
    
    Copy
  • Wenn Sie den Standard-Host verwenden (d. h. Sie geben das Argument host beim Erstellen einer Verbindung nicht an), wird die Verbindung zu Snowflake mit anderen Formen der Authentifizierung (z. B. Benutzername und Kennwort) unterstützt. Bei der folgenden Verbindung werden zur Authentifizierung beispielsweise Benutzername und Kennwort angegeben:

    conn = snowflake.connector.connect(
      account = os.getenv('SNOWFLAKE_ACCOUNT'),
      user = '<user-name>',
      password = <password>
    )
    
    Copy

    Die Verwendung eines Standard-Hosts erfordert eine Integration für den externen Zugriff mit einer Netzwerkregel, die den Zugriff von Ihrem Dienst auf den Snowflake-Hostnamen Ihres Kontos erlaubt. Wenn Ihr Kontoname beispielsweise MyAccount ist, lautet der Hostname myaccount.snowflakecomputing.com. Weitere Informationen dazu finden Sie unter Ausgehender Netzwerk-Datenverkehr.

    • Erstellen Sie eine Netzwerkregel, die einen Abgleich mit Snowflake-API-Hostnamen Ihres Kontos vornimmt:

      CREATE OR REPLACE NETWORK RULE snowflake_egress_access
        MODE = EGRESS
        TYPE = HOST_PORT
        VALUE_LIST = ('myaccount.snowflakecomputing.com');
      
      Copy
    • Erstellen Sie eine Integration unter Verwendung der obigen Netzwerkregel:

      CREATE EXTERNAL ACCESS INTEGRATION snowflake_egress_access_integration
        ALLOWED_NETWORK_RULES = (snowflake_egress_access)
        ENABLED = true;
      
      Copy

Konfigurieren des Datenbank- und Schemakontextes für das Ausführen von SQL

In diesem Abschnitt werden zwei Konzepte erläutert:

  • Die Logik, mit der Snowflake Datenbank und Schema bestimmt, in dem Ihr Dienst/Job erstellt werden soll.

  • Die Methode, mit der Snowflake diese Informationen an Ihre Container weitergibt, sodass der Containercode SQL im gleichen Datenbank- und Schemakontext ausführen kann.

Snowflake verwendet die folgende Logik, um die Datenbank und das Schema zu bestimmen, in denen ein Dienst/Job erstellt werden soll:

  • Bei einem Dienst verwendet Snowflake den im Befehl CREATE SERVICE angegebenen Dienstnamen, um den Datenbank- und Schemakontext für den Dienst zu ermitteln:

    • Beispiel 1: Der folgende Befehl CREATE SERVICE spezifiziert test_service als den Dienstnamen:

      CREATE SERVICE test_service IN COMPUTE POOL ...
      
      Copy

      Snowflake platziert diesen Dienst in der aktuellen Datenbank und im aktuellen Schema.

    • Beispiel 2: Der folgende Befehl CREATE SERVICE spezifiziert einen vollqualifizierten Dienstnamen:

      CREATE SERVICE test_db.test_schema.test_service IN COMPUTE POOL ...
      
      Copy

      Snowflake platziert den Dienst in der angegebenen Datenbank (test_db) und dem angegebenen Schema (test_schema), unabhängig vom aktuellen Schema.

  • Bei einem Job geben Sie beim Erstellen des Jobs mit dem Befehl EXECUTE SERVICE keinen Jobnamen an:

    EXECUTE SERVICE IN COMPUTE POOL ..
    
    Copy

    In diesem Fall haben Sie keine Möglichkeit, den Job irgendwo zu platzieren. Daher platziert Snowflake den Job in der aktuellen Datenbank und im aktuellen Schema. Wenn Sie möchten, dass ein Job SQL-Anweisungen in verschiedenen Schemas ausführt, können Sie den Job in verschiedenen Schemakontexten ausführen. Beispiel:

    USE ROLE test_role;
    USE DATABASE tutorial_db;
    
    USE SCHEMA schema1;
    -- Execute using tutorial_db and schema1
    EXECUTE SERVICE IN COMPUTE POOL ...
    
    USE SCHEMA schema2;
    -- execute service again, using schema2
    EXECUTE SERVICE IN COMPUTE POOL ...
    
    Copy

Wenn Snowflake einen Dienst/Job startet, werden den ausgeführten Containern die Datenbank- und Schemainformationen über die folgenden Umgebungsvariablen zur Verfügung gestellt:

  • SNOWFLAKE_DATABASE

  • SNOWFLAKE_SCHEMA

Ihr Containercode kann Umgebungsvariablen im Verbindungscode verwenden, um die zu verwendende Datenbank und das Schema zu bestimmen, wie im folgenden Beispiel gezeigt:

conn = snowflake.connector.connect(
  host = os.getenv('SNOWFLAKE_HOST'),
  account = os.getenv('SNOWFLAKE_ACCOUNT'),
  token = get_login_token(),
  authenticator = 'oauth',
  database = os.getenv('SNOWFLAKE_DATABASE'),
  schema = os.getenv('SNOWFLAKE_SCHEMA')
)
Copy

Beispiel

In Tutorial 2 erstellen Sie einen Snowflake-Job, der sich mit Snowflake verbindet und SQL-Anweisungen ausführt. Die folgenden Schritte fassen zusammen, wie der Tutorial-Code die Umgebungsvariablen verwendet:

  1. Bei der grundlegenden Einrichtung (siehe Abschnitt Grundlegende Einrichtung) erstellen Sie Ressourcen, einschließlich einer Datenbank und eines Schemas. Sie legen auch die aktuelle Datenbank und das aktuelle Schema für die Sitzung fest:

    USE DATABASE tutorial_db;
    ...
    USE SCHEMA data_schema;
    
    Copy
  2. Nachdem Sie einen Job erstellt haben (durch Ausführen von EXECUTE SERVICE), startet Snowflake den Container und setzt die folgenden Umgebungsvariablen im Container auf die aktuelle Datenbank und das aktuelle Schema der Sitzung:

    • SNOWFLAKE_DATABASE ist auf „TUTORIAL_DB“ gesetzt.

    • SNOWFLAKE_SCHEMA ist auf „DATA_SCHEMA“ gesetzt.

  3. Der Jobcode (siehe main.py in Tutorial 2) liest diese Umgebungsvariablen aus:

    SNOWFLAKE_DATABASE = os.getenv('SNOWFLAKE_DATABASE')
    SNOWFLAKE_SCHEMA = os.getenv('SNOWFLAKE_SCHEMA')
    
    Copy
  4. Der Jobcode legt die Datenbank und das Schema als Kontext fest, in dem die SQL-Anweisungen ausgeführt werden (Funktion run_job() in main.py):

    {
       "account": SNOWFLAKE_ACCOUNT,
       "host": SNOWFLAKE_HOST,
       "authenticator": "oauth",
       "token": get_login_token(),
       "warehouse": SNOWFLAKE_WAREHOUSE,
       "database": SNOWFLAKE_DATABASE,
       "schema": SNOWFLAKE_SCHEMA
    }
    ...
    
    Copy

Verwenden eines OAuth-Tokens zum Ausführen von SQL

Alle von Snowflake bereitgestellten Clients unterstützen OAuth als Authentifizierungsoption. Auch Dienst-/Jobcontainer verwenden den OAuth-Mechanismus zur Authentifizierung bei Snowflake. Wenn ein Container zum Beispiel SQL ausführen möchte, stellt er eine Verbindung zu Snowflake her, ähnlich wie jeder andere Snowflake-Client:

def get_login_token():
  with open('/snowflake/session/token', 'r') as f:
    return f.read()

conn = snowflake.connector.connect(
  host = os.getenv('SNOWFLAKE_HOST'),
  account = os.getenv('SNOWFLAKE_ACCOUNT'),
  token = get_login_token(),
  authenticator = 'oauth'
)
Copy

Wenn Sie einen Dienst/Job erstellen, führt Snowflake die Container aus und stellt den Containern ein OAuth-Token zur Verfügung, das an der folgendem Speicherort innerhalb des Containers verwendet wird: /snowflake/session/token.

Beachten Sie die folgenden Details zu diesem OAuth-Token:

  • Sie müssen den Inhalt der Datei /snowflake/session/token unmittelbar vor der Verwendung lesen, da der Inhalt innerhalb von 10 Minuten abläuft, und Snowflake diese Datei alle paar Minuten aktualisiert. Nachdem sich ein Container erfolgreich mit Snowflake verbunden hat, gilt die Ablaufzeit nicht mehr für die Verbindung (wie bei allen Sitzungen, die Benutzer direkt erstellen).

  • Dieses OAuth-Token ist nur innerhalb des jeweiligen Snowflake-Dienstes/Jobs gültig. Sie können das OAuth-Token nicht kopieren und außerhalb des Dienstes/Jobs verwenden.

  • Unter Verwendung des OAuth-Tokens verbinden sich die Container mit Snowflake als Benutzer und Dienst-/Jobrolle wie folgt:

    • Der Benutzer ist die Person, die den Dienst/Job erstellt hat.

    • Die Rolle ist die Dienstrolle für den Dienst/Job, und dies ist die einzige unterstützte Rolle. Sie können die Rolle nicht ändern.

  • Die Verwendung des OAuth-Tokens zum Herstellen einer Verbindung führt zu einer neuen Sitzung. Das OAuth-Token ist mit keiner bestehenden SQL-Sitzung verbunden.

    Bemerkung

    Ein wesentlicher Unterschied zwischen dem Ausführen von gespeicherten Prozeduren und dem Ausführen eines Dienstes/Jobs besteht darin, dass gespeicherte Prozeduren in der gleichen Sitzung ausgeführt werden wie der SQL-Code, der sie ausführt. Aber jedes Mal, wenn ein Container eine neue Verbindung aufbaut, wird eine neue Sitzung erstellt.

Konfigurieren der Netzwerkeigenschaften

In den folgenden Abschnitten wird erläutert, wie Sie die Netzwerkeigenschaften (eingehender/ausgehender Datenverkehr) für Ihren Dienst und Job konfigurieren.

Eingehender Netzwerk-Datenverkehr

Um eine Interaktion mit Ihrem Dienst vom Internet aus zu ermöglichen, deklarieren Sie die Netzwerkports, die von Ihrem Dienst überwacht werden, als Endpunkte in der Dienstspezifikationsdatei. Diese Endpunkte kontrollieren den eingehenden Datenverkehr.

Standardmäßig sind die Dienstendpunkte privat. Nur Dienstfunktionen und die Dienst-zu-Dienst-Kommunikation können Anforderungen an die privaten Endpunkte senden. Sie können einen Endpunkt als öffentlich deklarieren, um Anforderungen an einen Endpunkt aus dem Internet zuzulassen. Die Rolle, die den Dienst (mit einem öffentlichen Endpunkt) erstellt, muss über die Berechtigung BIND SERVICE ENDPOINT für das Konto verfügen.

endpoints:
- name: <endpoint name>
  port: <port number>
  protocol : < TCP / HTTP / HTTPS >
  public: true
Copy

Ein Beispiel dazu finden Sie unter Tutorial 1.

Bemerkung

Derzeit unterstützen nur Dienste, nicht aber Jobs, den Netzwerkzugang (eingehende Daten).

Ausgehender Netzwerk-Datenverkehr

Der Code Ihrer Anwendung (Job oder Dienst) erfordert möglicherweise einen Zugang zum Internet. Standardmäßig haben Anwendungscontainer keine Berechtigung für den Zugriff auf das Internet. Sie müssen daher den Internetzugang über Integrationen für den externen Zugriff (External Access Integrations, EAIs) aktivieren.

In der Regel werden EAIs von einem Kontoadministrator erstellt, um den von Jobs und Diensten erlaubten externen Zugriff zu verwalten. Kontoadministratoren können dann die EAI-Nutzung bestimmten Rollen erlauben, mit denen Entwickler dann Jobs oder Diensten ausführen können.

Im folgenden Beispiel werden die Schritte zum Erstellen einer EAI beschrieben, die ausgehenden Datenverkehr zu bestimmten Zielen zulässt, die mithilfe von Netzwerkregeln spezifiziert werden. Sie können sich dann auf diese EAI beziehen, wenn Sie einen Job oder Dienst erstellen, um Anforderungen an bestimmte Internetziele zuzulassen.

Beispiel

Angenommen, Sie möchten, dass Ihr Anwendungscode (Job oder Dienst) Anforderungen an die folgenden Ziele sendet:

  • HTTPS-Anforderung an translation.googleapis.com

  • HTTP- und HTTPS-Anforderung an google.com

Führen Sie die folgenden Schritte aus, damit Ihr Job oder Dienst auf diese Domänen im Internet zugreifen kann:

  1. Erstellen Sie eine Integration für den externen Zugriff (EAI). Dafür sind die entsprechenden Berechtigungen erforderlich. Sie können zum Beispiel die Rolle ACCOUNTADMIN verwenden, um eine EAI zu erstellen. Dies ist ein zweistufiger Prozess:

    1. Verwenden Sie den Befehl CREATE NETWORK RULE, um eine oder mehrere Netzwerkregeln für den ausgehenden Datenverkehr zu erstellen, wobei in den Regeln die externen Ziele aufgeführt sind, für die Sie den Zugriff erlauben möchten. Sie können benötigen für dieses Beispiel normalerweise nur eine Netzwerkregel, aber zur Veranschaulichung erstellen wir hier zwei Netzwerkregeln:

      1. Erstellen Sie eine Netzwerkregel namens translate_network_rule.

        CREATE OR REPLACE NETWORK RULE translate_network_rule
          MODE = EGRESS
          TYPE = HOST_PORT
          VALUE_LIST = ('translation.googleapis.com');
        
        Copy

        Diese Regel erlaubt TCP-Verbindungen zum Ziel translation.googleapis.com. Die Domäne in der Eigenschaft VALUE_LIST gibt keine optionale Portnummer an, sodass der Standardport 443 (HTTPS) angenommen wird. Dadurch kann Ihre Anwendung eine Verbindung zu jeder URL herstellen, die mit https://translation.googleapis.com/ beginnt.

      2. Erstellen Sie eine Netzwerkregel namens google_network_rule.

        CREATE OR REPLACE NETWORK RULE google_network_rule
          MODE = EGRESS
          TYPE = HOST_PORT
          VALUE_LIST = ('google.com:80', 'google.com:443');
        
        Copy

        Dadurch kann Ihre Anwendung eine Verbindung zu jeder URL herstellen, die mit http://google.com/ oder https://google.com/ beginnt.

      Snowpark Container Services unterstützt nur die Netzwerkregeln, die die Ports 22, 80, 443 und 1024+ erlauben. Wenn eine referenzierte Netzwerkregel den Zugriff auf andere Ports zulässt, schlägt das Erstellen des Dienstes fehl. Wenden Sie sich an Ihren Kundenbetreuer, wenn Sie zusätzliche Ports benötigen.

      Bemerkung

      Damit Ihr Job oder Dienst HTTP- oder HTTPS-Anforderungen an ein beliebiges Ziel im Internet senden kann, geben Sie in der VALUE_LIST-Eigenschaft „0.0.0.0“ als Domäne an. Die folgende Netzwerkregel erlaubt es, sowohl „HTTP“- als auch „HTTPS“-Anforderungen an beliebige Ziele im Internet zu senden. Mit „0.0.0.0“ werden nur die Ports 80 oder 443 unterstützt.

      CREATE NETWORK RULE allow_all_rule
        TYPE = 'HOST_PORT'
        MODE= 'EGRESS'
        VALUE_LIST = ('0.0.0.0:443','0.0.0.0:80');
      
      Copy
    2. Erstellen Sie eine Integration für den externe Zugriff (EAI), die festlegt, dass die beiden obigen Netzwerkregeln für ausgehenden Datenverkehr zulässig sind:

      CREATE EXTERNAL ACCESS INTEGRATION google_apis_access_integration
        ALLOWED_NETWORK_RULES = (translate_network_rule, google_network_rule)
        ENABLED = true;
      
      Copy

      Nun kann der Kontoadministrator Entwicklern die Nutzung (USAGE) der Integration gestatten, damit diese einen Job/Dienst ausführen können, der auf bestimmte Ziele im Internet zugreifen kann.

      GRANT USAGE ON INTEGRATION google_apis_access_integration TO ROLE test_role;
      
      Copy
  2. Erstellen Sie den Dienst oder einen Job durch Angabe der EAI wie in den folgenden Beispielen gezeigt. Die Rolle, die den Dienst oder Job erstellt, benötigt die Nutzungsberechtigung (USAGE) für die EAI und die Leseberechtigung (READ) für die referenzierten Geheimnisse. Beachten Sie, dass Sie mit der Rolle ACCOUNTADMIN keine Dienste oder Jobs erstellen können.

    • Erstellen Sie einen Dienst:

      USE ROLE test_role;
      
      CREATE SERVICE eai_service
        IN COMPUTE POOL MYPOOL
        FROM SPECIFICATION
        $$
        spec:
          containers:
            - name: main
              image: /db/data_schema/tutorial_repository/my_echo_service_image:tutorial
              env:
                TEST_FILE_STAGE: source_stage/test_file
              args:
                - read_secret.py
          endpoints:
            - name: read
              port: 8080
        $$
        EXTERNAL_ACCESS_INTEGRATIONS = (google_apis_access_integration);
      
      Copy

      Diese CREATE SERVICE-Beispielanforderung verwendet eine Inline-Dienstspezifikation und gibt die optionale Eigenschaft EXTERNAL_ACCESS_INTEGRATIONS an, um die EAI einzuschließen. Die EAI gibt die Netzwerkregeln an, die den ausgehenden Datenverkehr vom Dienst zu den spezifischen Zielen erlauben.

    • Erstellen Sie einen Job:

      EXECUTE SERVICE
        IN COMPUTE POOL tt_cp
        FROM SPECIFICATION $$
        spec:
          container:
          - name: curl
            image: /tutorial_db/data_schema/tutorial_repo/alpine-curl:latest
            command:
            - "curl"
            - "http://google.com/"
        $$
        EXTERNAL_ACCESS_INTEGRATIONS = (google_apis_access_integration);
      
      Copy

      Dieser EXECUTE SERVICE-Beispielbefehl gibt die Inline-Spezifikation und die optionale Eigenschaft EXTERNAL_ACCESS_INTEGRATIONS an, um die EAI einzuschließen. Dadurch wird der ausgehende Datenverkehr vom Job zu den in den Netzwerkregeln angegebenen Zielen zugelassen, die die EAI zulässt.

Netzwerkkommunikation zwischen Containern

Es gibt zwei Konzepte:

  • Kommunikation zwischen Containern einer Dienstinstanz: Wenn eine Dienstinstanz mehrere Container ausführt, können diese Container über „localhost“ miteinander kommunizieren (es ist nicht erforderlich, in der Dienstspezifikation Endpunkte zu definieren).

  • Kommunikation zwischen Containern verschiedener Dienste/Jobs oder mehrerer Dienstinstanzen: Container, die zu verschiedenen Diensten (oder verschiedenen Instanzen desselben Dienstes) gehören, können über Endpunkte kommunizieren, die in Spezifikationsdateien definiert sind. Weitere Informationen dazu finden Sie unter Dienst-zu-Dienst-Kommunikation.

Verwenden von Snowflake-Geheimnissen zur Übergabe von Anmeldeinformationen an einen Container

Wenn Ihr Dienst oder Job mit externen Endpunkten (außerhalb von Snowflake) kommuniziert, müssen Sie in Ihrem Container Anmeldeinformationen bereitstellen, die Ihr Anwendungscode verwenden kann. Speichern Sie dazu zunächst Ihre Anmeldeinformationen in Snowflake-Geheimnisobjekten. Als Nächstes fügen Sie in der Dienst- oder Jobspezifikationsdatei das Feld containers.secrets ein, um diese Geheimnisse an die Container zu übergeben.

Sie können diese Anmeldeinformationen entweder an Umgebungsvariablen in den Containern übergeben oder sie in lokalen Dateien in den Containern verfügbar machen. Je nachdem, welche Option Sie wählen, bietet die Spezifikationsdatei Konstrukte, die in den folgenden Abschnitten erläutert werden.

Übergeben von Geheimnissen als Umgebungsvariablen

Um Snowflake-Geheimnisse für Container als Umgebungsvariablen zu übergeben, fügen Sie ein containers.secrets-Feld ein:

containers:
- name: main
  image: <url>
  secrets:
  - snowflakeSecret: <snowflake-secret-name>
    secretKeyRef: <secret-key-reference>
    envVarName: <env-variable-name>
Copy

secretKeyRef: Dieser Wert hängt vom Typ des Snowflake-Geheimnisses ab. Mögliche Werte:

  • username oder password, wenn das Snowflake-Geheimnis vom Typ password ist.

  • secret_string, wenn das Snowflake-Geheimnis vom Typ generic_string ist.

  • access_token, wenn das Snowflake-Geheimnis vom Typ oauth2 ist.

Bemerkung

Geheimnisse, die als Umgebungsvariablen übergeben werden, können nicht mehr aktualisiert werden, nachdem ein Dienst (oder Job) erstellt wurde.

Beispiel 1: Übergeben von Geheimnissen des Typs password als Umgebungsvariable

In diesem Beispiel erstellen Sie das folgende Snowflake-Geheimnisobjekt vom Typ password:

CREATE SECRET testdb.testschema.my_secret_object
  TYPE = password
  USERNAME = 'snowman'
  PASSWORD = '1234abc';
Copy

Um dieses Snowflake-Geheimnisobjekt den Umgebungsvariablen (z. B. LOGIN_USER und LOGIN_PASSWORD) in Ihrem Container zur Verfügung zu stellen, fügen Sie das folgende Feld containers.secrets in die Spezifikationsdatei ein:

containers:
- name: main
  image: <url>
  secrets:
  - snowflakeSecret: testdb.testschema.my_secret_object
    secretKeyRef: username
    envVarName: LOGIN_USER
  - snowflakeSecret: testdb.testschema.my_secret_object
    secretKeyRef: password
    envVarName: LOGIN_PASSWORD
Copy

Das Feld containers.secrets in diesem Beispiel ist eine Liste mit zwei snowflakeSecret-Objekten:

  • Mit dem ersten Objekt wird username im Snowflake-Geheimnisobjekt der Umgebungsvariablen LOGIN_USER in Ihrem Container zugeordnet.

  • Mit dem zweiten Objekt wird password im Snowflake-Geheimnisobjekt der Umgebungsvariablen LOGIN_PASSWORD in Ihrem Container zugeordnet.

Beispiel 2: Übergeben von Geheimnissen vom Typ generic_string als Umgebungsvariable

In diesem Beispiel erstellen Sie das folgende Snowflake-Geheimnisobjekt vom Typ generic_string:

CREATE SECRET testdb.testschema.my_secret
  TYPE=generic_string
  SECRET_STRING='
       some_magic: config
  ';
Copy

Um dieses Snowflake-Geheimnisobjekt den Umgebungsvariablen (z. B. GENERIC_SECRET) in Ihrem Container zur Verfügung zu stellen, fügen Sie das folgende Feld containers.secrets in die Spezifikationsdatei ein:

containers:
- name: main
  image: <url>
  secrets:
  - snowflakeSecret: testdb.testschema.my_secret
    secretKeyRef: secret_string
    envVarName: GENERIC_SECRET
Copy

Anmerkung zum Übergeben von Geheimnissen des Typs oauth2 an Umgebungsvariablen

Dies ist kein sinnvolles Szenario, denn wenn OAuth-Token ablaufen, muss ein neues Token an den Container übergeben werden. Aber Geheimnisse, die als Umgebungsvariablen übergeben werden, können nicht aktualisiert werden. Daher sollten Sie keine Geheimnisse vom Typ „oauth2“ als Umgebungsvariablen übergeben.

Übergeben von Geheimnissen mithilfe von lokalen Containerdateien

Um Snowflake-Geheimnisse für Ihren Anwendungscontainer in lokalen Containerdateien zur Verfügung zu stellen, fügen Sie ein containers.secrets-Feld ein:

containers:
- name: <name>
  image: <url>
  ...
  secrets:
  - snowflakeSecret: <snowflake-secret-name>
    directoryPath: '<local directory path in the container>'
Copy

directoryPath: Snowflake erstellt für jeden Geheimnisschlüssel im angegebenen Verzeichnis eine Datei, wobei die Angabe von secretKeyRef nicht erforderlich ist.

Bemerkung

Wenn nach dem Erstellen eines Dienstes (oder Jobs) das Snowflake-Geheimnisobjekt aktualisiert wird, aktualisiert Snowflake die entsprechenden Geheimnisdateien in den aktiven Containern.

Beispiel 1: Übergeben von Geheimnissen des Typs password mithilfe von lokalen Containerdateien

In diesem Beispiel erstellen Sie das folgende Snowflake-Geheimnisobjekt vom Typ password:

CREATE SECRET testdb.testschema.my_secret_object
  TYPE = password
  USERNAME = 'snowman'
  PASSWORD = '1234abc';
Copy

Um diese Anmeldeinformationen in lokalen Containerdateien zur Verfügung zu stellen, fügen Sie das folgende containers.secrets-Feld in die Spezifikationsdatei ein:

containers:
- name: main
  image: <url>
  secrets:
  - snowflakeSecret: testdb.testschema.my_secret_object
    directoryPath: '/usr/local/creds'
Copy

Wenn Sie Ihren Dienst oder Job starten, erstellt Snowflake zwei Dateien innerhalb der Container: /usr/local/creds/username und /usr/local/creds/password. Ihr Anwendungscode kann dann diese Dateien lesen.

Beispiel 2: Übergeben von Geheimnissen des Typs oauth2 mithilfe von lokalen Containerdateien

In diesem Beispiel erstellen Sie das folgende Snowflake-Geheimnisobjekt vom Typ oauth2:

CREATE SECRET testdb.testschema.oauth_secret
  TYPE = OAUTH2
  OAUTH_REFRESH_TOKEN = '34n;vods4nQsdg09wee4qnfvadH'
  OAUTH_REFRESH_TOKEN_EXPIRY_TIME = '2023-12-31 20:00:00'
  API_AUTHENTICATION = my_integration;
Copy

Um diese Anmeldeinformationen in lokalen Containerdateien zur Verfügung zu stellen, fügen Sie das folgende containers.secrets-Feld in die Spezifikationsdatei ein:

containers:
- name: main
  image: <url>
  secrets:
  - snowflakeSecret: testdb.testschema.oauth_secret
    directoryPath: '/usr/local/creds'
Copy

Snowflake ruft das Zugriffstoken aus dem OAuth-Geheimnisobjekt ab und erstellt /usr/local/creds/access_token in den Containern.

Wenn ein Job oder Dienst Geheimnisse des „oauth2“-Typs verwendet, wird erwartet, dass der Dienst oder Job dieses Geheimnis für den Zugriff auf ein Internetziel verwendet. Ein OAuth-Geheimnis muss von einer Integration für den externe Zugriff (EAI) erlaubt werden, da sonst CREATE SERVICE und EXECUTE SERVICE fehlschlagen. Diese zusätzliche EAI-Anforderung gilt nur für Geheimnisse des „oauth2“-Typs und nicht für andere Typen von Geheimnissen.

Zusammenfassend sind folgende allgemeine Schritte zum Erstellen eines solchen Dienstes erforderlich:

  1. Erstellen Sie ein Geheimnis vom Typ „oauth2“ (siehe oben).

  2. Erstellen Sie eine EAI, um die Verwendung des Geheimnisses durch einen Dienst oder einen Job zu erlauben. Beispiel:

    CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION example_eai
      ALLOWED_NETWORK_RULES = (<name>)
      ALLOWED_AUTHENTICATION_SECRETS = (testdb.testschema.oauth_secret)
      ENABLED = true;
    
    Copy
  3. Erstellen Sie einen Dienst oder Job, der ein containers.secrets-Feld in der Spezifikation enthält. Darin wird auch die optionale Eigenschaft EXTERNAL_ACCESS_INTEGRATIONS mit einer EAI angegeben, um die Verwendung des OAuth2-Geheimnisses zuzulassen.

    Beispiel für einen CREATE SERVICE-Befehl (mit Inline-Spezifikation):

    CREATE SERVICE eai_service
      IN COMPUTE POOL MYPOOL
      FROM SPECIFICATION
      $$
      spec:
        containers:
          - name: main
            image: <url>
            secrets:
            - snowflakeSecret: testdb.testschema.oauth_secret
              directoryPath: '/usr/local/creds'
        endpoints:
          - name: api
            port: 8080
      $$
      EXTERNAL_ACCESS_INTEGRATIONS = (example_eai);
    
    Copy

Weitere Informationen zu ausgehendem Datenverkehr finden Sie unter Ausgehender Netzwerk-Datenverkehr.

Richtlinien und Einschränkungen

  • Anforderungen an Plattformimages: Snowpark Container Services benötigt derzeit Images der linux/amd64-Plattform.

  • Dienst-/Jobcontainer haben keine Berechtigungen: Dienst-/Jobcontainer werden derzeit ohne weitreichende Berechtigungen ausgeführt, d. h. sie können die Konfiguration der Hardware auf dem Host nicht ändern und können BS-Konfigurationen nur begrenzt ändern. Dienst-/Jobcontainer können nur Betriebssystemkonfigurationen ausführen, die auch ein normaler Benutzer (d. h. ein Benutzer, der keine Root-Berechtigung benötigt) ausführen kann.

  • Umbenennen von Datenbank und Schema:

    • Benennen Sie keine Datenbanken und Schemas um, für die Sie bereits einen Dienst erstellt haben. Das Umbenennen bedeutet im Grunde, dass ein Dienst in eine andere Datenbank und ein anderes Schema verschoben wird, was nicht unterstützt wird. Beispiel:

      • Der DNS-Name des Dienstes wird weiterhin den alten Datenbank- und Schemanamen verwenden.

      • Datenbank- und Schemainformationen, die Snowflake den aktiven Dienstcontainern zur Verfügung stellt, beziehen sich weiterhin auf die alten Namen.

      • Neue Protokolleinträge, die von Diensten in die Ereignistabelle aufgenommen werden, beziehen sich weiterhin auf die alten Datenbank- und Schemanamen.

      • Die Dienstfunktion wird weiterhin auf den Dienst in der alten Datenbank und dem alten Schema verweisen, und wenn Sie die Dienstfunktion aufrufen, wird sie fehlschlagen.

    • Eine Dienstspezifikation kann auf Objekte wie Snowflake-Stagingbereiche und Image-Repositorys verweisen. Wenn Sie den Namen von Datenbank oder Schema umbenennen, in denen sich diese Objekte befinden, müssen Sie die Datenbank- und Schemanamen der referenzierten Objekte in der Dienstspezifikation manuell aktualisieren.

  • Löschen und Wiederherstellen von Datenbank und Schema:

    • Wenn Sie die übergeordnete Datenbank oder das übergeordnete Schema löschen, werden die Dienste asynchron gelöscht. Das bedeutet, dass ein Dienst noch einige Zeit weiter ausgeführt wird, bevor er durch interne Prozesse entfernt wird.

    • Wenn Sie versuchen, eine zuvor gelöschte Datenbank oder ein Schema wiederherzustellen, gibt es keine Garantie, dass die Dienste wiederhergestellt werden.

  • Übertragen der Eigentümerschaft: Das Übertragen der Eigentümerschaft von Diensten und Jobs wird nicht unterstützt.

  • Replikation: Bei der Replikation in Snowflake ist Folgendes zu beachten:

    • Snowpark Container Services-Objekte wie Dienste, Jobs, Computepools und Repositorys können nicht repliziert werden.

    • Wenn Sie ein Repository innerhalb einer Datenbank erstellen, kann nicht die gesamte Datenbank repliziert werden. In Fällen, in denen die Datenbank andere Ressourcen enthält, wie z. B. Dienste, Jobs oder Computepools, wird der Replikationsprozess der Datenbank erfolgreich sein, aber diese einzelnen Objekte innerhalb der Datenbank werden nicht repliziert.

  • Timeout von Jobs: Snowpark Container Services-Jobs werden synchron ausgeführt. Wenn eine Anweisung ein Zeitlimit überschreitet, wird der Job abgebrochen. Das Standard-Timeout für Anweisungen beträgt zwei Tage. Kunden können den Timeout-Wert ändern, indem sie den Parameter STATEMENT_TIMEOUT_IN_SECONDS mit ALTER SESSION einstellen.

    ALTER SESSION SET statement_timeout_in_seconds=<time>
    
    Copy

    Stellen Sie ihn ein, bevor Sie den Befehl EXECUTE SERVICE ausführen.