Snowpark Container Services : considérations supplémentaires pour les services et les tâches¶
Important
La fonction de tâches Snowpark Container Services est actuellement disponible en avant-première privée et est soumise aux conditions d’utilisation de l’avant-première disponibles à https://snowflake.com/legal. Contactez votre représentant Snowflake pour plus d’informations.
Connexion à Snowflake depuis l’intérieur d’un conteneur¶
Lorsque vous démarrez un service ou une tâche, Snowflake fournit des identifiants de connexion aux conteneurs en cours d’exécution, ce qui permet au code de votre conteneur d’utiliser des pilotes pour se connecter à Snowflake et exécuter SQL (comme tout autre code sur votre ordinateur se connectant à Snowflake). Les identifiants de connexion fournis permettent de s’authentifier en tant que rôle du service. Snowflake fournit certaines informations sous forme de variables d’environnement dans vos conteneurs.
Chaque objet dans Snowflake a un rôle de propriétaire. Dans le cas d’un service ou d’une tâche, Snowflake dispose d’un concept appelé rôle de service (ce terme s’applique à la fois aux services et aux tâches). Le rôle du service détermine les capacités que votre service est autorisé à exécuter lorsqu’il interagit avec Snowflake. Cela comprend l’exécution de SQL, l’accès à des zones de préparation et la mise en réseau de service à service.
Note
Dans la version actuelle, le rôle du service est le même que celui du propriétaire.
Par exemple, vous créez un test_role
dans le cadre de la configuration commune pour les tutoriels. Vous accordez les privilèges nécessaires au rôle, puis vous utilisez le rôle lors de la création d’un service et d’une tâche. Ce rôle est à la fois le rôle de propriétaire du service et de la tâche et le rôle de service qui détermine les capacités du service et de la tâche.
Note
Les rôles de service ne peuvent être aucun des rôles privilégiés, comme ACCOUNTADMIN, SECURITYADMIN et ORGADMIN.
Lorsque vous créez un service, Snowflake crée également un « utilisateur de service » spécifique à ce service. Lorsque le service exécute une requête, il le fait en tant qu’utilisateur du service. Ce que l’utilisateur du service peut faire est déterminé par le rôle du service.
Connexion à Snowflake¶
Snowflake fournit les variables d’environnement suivantes pour vous permettre de configurer un client Snowflake dans le code de votre service/tâche :
SNOWFLAKE_ACCOUNT : fournit le nom du compte Snowflake sous lequel le service est actuellement exécuté.
SNOWFLAKE_HOST : fournit le nom d’hôte utilisé pour se connecter à Snowflake.
Snowflake fournit également un jeton OAuth dans le conteneur dans un fichier nommé /snowflake/session/token
. Lors de la création d’une connexion, vous fournissez ce jeton au connecteur.
Lorsque vous créez une connexion à Snowflake à partir d’un conteneur, vous devez utiliser les jetons SNOWFLAKE_HOST, SNOWFLAKE_ACCOUNT et OAuth. Vous ne pouvez pas utiliser le jeton OAuth sans utiliser également SNOWFLAKE_HOST, et vous ne pouvez pas utiliser le jeton OAuth en dehors de Snowpark Container Services. Pour plus d’informations, voir Utilisation d’un jeton OAuth pour exécuter SQL.
Exemples
Dans le tutoriel 2 (voir
main.py
), le code lit les variables d’environnement comme suit :SNOWFLAKE_ACCOUNT = os.getenv('SNOWFLAKE_ACCOUNT') SNOWFLAKE_HOST = os.getenv('SNOWFLAKE_HOST')
Le code transmet ces variables à un code de création de connexion pour le client Snowflake choisi. Le conteneur utilise ces identifiants de connexion pour créer une nouvelle session, avec le rôle de service comme rôle principal, afin d’exécuter des requêtes. L’exemple de code suivant est le minimum requis pour créer une connexion Snowflake en Python :
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' )
Lorsque vous utilisez l’hôte par défaut (c’est-à-dire que vous n’incluez pas l’argument
host
lors de la création d’une connexion), la connexion à Snowflake en utilisant d’autres formes d’authentification (telles que le nom d’utilisateur et le mot de passe) est prise en charge. Par exemple, la connexion suivante spécifie le nom d’utilisateur et le mot de passe pour l’authentification :conn = snowflake.connector.connect( account = os.getenv('SNOWFLAKE_ACCOUNT'), user = '<user-name>', password = <password> )
L’utilisation d’un hôte par défaut nécessite l’intégration d’accès externe avec une règle de réseau permettant l’accès de votre service au nom d’hôte Snowflake pour votre compte. Par exemple, si le nom de votre compte est MyAccount, le nom d’hôte sera moncompte.snowflakecomputing.com. Pour plus d’informations, voir Sortie réseau.
Créez une règle de réseau qui correspond au nom d’hôte d’API Snowflake de votre compte :
CREATE OR REPLACE NETWORK RULE snowflake_egress_access MODE = EGRESS TYPE = HOST_PORT VALUE_LIST = ('myaccount.snowflakecomputing.com');
Créez une intégration à l’aide de la règle de réseau précédente :
CREATE EXTERNAL ACCESS INTEGRATION snowflake_egress_access_integration ALLOWED_NETWORK_RULES = (snowflake_egress_access) ENABLED = true;
Configuration de la base de données et du contexte du schéma pour l’exécution de SQL¶
Cette section présente deux concepts :
La logique utilisée par Snowflake pour déterminer la base de données et le schéma dans lesquels créer votre service/tâche.
La méthode par laquelle Snowflake transmet cette information à vos conteneurs, permettant ainsi au code du conteneur d’exécuter SQL dans le même contexte de base de données et de schéma.
Snowflake utilise la logique suivante pour déterminer la base de données et le schéma dans lesquels créer un service/une tâche :
Pour un service, Snowflake utilise le nom du service fourni dans la commande CREATE SERVICE afin de déterminer la base de données et le contexte du schéma pour le service :
Exemple 1 : la commande CREATE SERVICE suivante spécifie
test_service
comme nom de service :CREATE SERVICE test_service IN COMPUTE POOL ...
Snowflake place ce service dans la base de données et le schéma actuels.
Exemple 2 : la commande CREATE SERVICE suivante spécifie un nom de service entièrement qualifié :
CREATE SERVICE test_db.test_schema.test_service IN COMPUTE POOL ...
Snowflake place le service dans la base de données (
test_db
) et le schéma (test_schema
) spécifiés, quel que soit le schéma actuel.
Pour une tâche, vous n’indiquez pas de nom de travail lorsque vous créez une tâche à l’aide de la commande EXECUTE SERVICE :
EXECUTE SERVICE IN COMPUTE POOL ..
Dans ce cas, vous n’avez pas la possibilité de placer la tâche n’importe où. Par conséquent, Snowflake place la tâche dans la base de données et le schéma actuels. Si vous souhaitez qu’une tâche exécute des instructions SQL dans différents schémas, vous pouvez la lancer en utilisant différents contextes de schéma. Par exemple :
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 ...
Lorsque Snowflake démarre un service/une tâche, Snowflake fournit les informations relatives à la base de données et au schéma aux conteneurs en cours d’exécution en utilisant les variables d’environnement suivantes :
SNOWFLAKE_DATABASE
SNOWFLAKE_SCHEMA
Le code de votre conteneur peut utiliser des variables d’environnement dans le code de connexion pour déterminer la base de données et le schéma à utiliser, comme le montre cet exemple :
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')
)
Exemple
Dans le tutoriel 2, vous créez une tâche Snowflake qui se connecte à Snowflake et exécute des instructions SQL. Les étapes suivantes résument la manière dont le code du tutoriel utilise les variables d’environnement :
Dans la configuration commune (voir la section Configuration commune), vous créez des ressources, notamment une base de données et un schéma. Vous définissez également la base de données et le schéma actuels pour la session :
USE DATABASE tutorial_db; ... USE SCHEMA data_schema;
Après avoir créé une tâche (exécution de EXECUTE SERVICE), Snowflake démarre le conteneur et définit les variables d’environnement suivantes dans le conteneur en fonction de la base de données et du schéma actuels de la session :
SNOWFLAKE_DATABASE est défini sur « TUTORIAL_DB »
SNOWFLAKE_SCHEMA est défini sur « DATA_SCHEMA »
Le code de la tâche (voir
main.py
dans le tutoriel 2) lit ces variables d’environnement :SNOWFLAKE_DATABASE = os.getenv('SNOWFLAKE_DATABASE') SNOWFLAKE_SCHEMA = os.getenv('SNOWFLAKE_SCHEMA')
Le code de la tâche définit la base de données et le schéma comme le contexte dans lequel exécuter les instructions SQL (fonction
run_job()
dansmain.py
) :{ "account": SNOWFLAKE_ACCOUNT, "host": SNOWFLAKE_HOST, "authenticator": "oauth", "token": get_login_token(), "warehouse": SNOWFLAKE_WAREHOUSE, "database": SNOWFLAKE_DATABASE, "schema": SNOWFLAKE_SCHEMA } ...
Utilisation d’un jeton OAuth pour exécuter SQL¶
Tous les clients fournis par Snowflake prennent en charge OAuth comme moyen d’authentification. Les conteneurs de services/tâches utilisent également le mécanisme OAuth pour s’authentifier auprès de Snowflake. Par exemple, lorsqu’un conteneur veut exécuter SQL, il crée une connexion à Snowflake, comme n’importe quel autre client Snowflake :
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'
)
Lorsque vous créez un service/une tâche, Snowflake exécute les conteneurs et fournit un jeton Oauth pour les conteneurs à utiliser à l’emplacement suivant dans le conteneur : /snowflake/session/token
.
Notez les détails suivants concernant ce jeton OAuth :
Vous devez lire le contenu du fichier
/snowflake/session/token
immédiatement avant de l’utiliser, car le contenu expire au bout de 10 minutes, et Snowflake actualise ce fichier toutes les quelques minutes. Une fois qu’un conteneur s’est connecté avec succès à Snowflake, le délai d’expiration ne s’applique pas à la connexion (comme pour les sessions créées directement par les utilisateurs).Ce jeton OAuth n’est valable que pour la tâche ou le service Snowflake concerné. Vous ne pouvez pas copier le jeton OAuth et l’utiliser en dehors du service/de la tâche.
En utilisant le jeton OAuth, les conteneurs se connectent à Snowflake en tant qu’utilisateur et rôle du service/de la tâche comme suit :
L’utilisateur est la personne qui a créé le service/la tâche.
Le rôle est le rôle de service pour le service/la tâche, et c’est le seul rôle pris en charge. Vous ne pouvez pas modifier le rôle.
L’utilisation du jeton OAuth pour se connecter créera une nouvelle session. Le jeton OAuth n’est associé à aucune session SQL existante.
Note
Une différence importante entre l’exécution de procédures stockées et l’exécution d’un service/d’une tâche est que les procédures stockées s’exécutent dans la même session que le SQL qui les exécute. Mais chaque fois qu’un conteneur établit une nouvelle connexion, vous créez une nouvelle session.
Configuration des capacités réseau¶
Les sections suivantes expliquent comment configurer les capacités réseau (entrée et sortie réseau) pour votre service et votre tâche.
Entrée réseau¶
Pour permettre à quiconque d’interagir avec votre service depuis Internet, vous déclarez les ports réseau sur lesquels votre service écoute en tant que points de terminaison dans le fichier de spécification du service. Ces points de terminaison contrôlent l’entrée.
Par défaut, les points de terminaison de service sont privés. Seules les fonctions de service et les communications de service à service peuvent adresser des requêtes aux points de terminaison privés. Vous pouvez déclarer un point de terminaison comme étant public afin d’autoriser les requêtes vers un point de terminaison depuis Internet. Le rôle qui crée le service (avec un point de terminaison public) doit avoir le privilège BIND SERVICE ENDPOINT sur le compte.
endpoints:
- name: <endpoint name>
port: <port number>
protocol : < TCP / HTTP / HTTPS >
public: true
Pour un exemple, voir le tutoriel 1.
Note
Actuellement, seuls les services, et non les tâches, prennent en charge l’entrée réseau.
Sortie réseau¶
Le code de votre application (tâche ou service) peut nécessiter un accès à Internet. Par défaut, les conteneurs d’application n’ont pas la permission d’accéder à Internet. Vous devez activer l’accès à Internet en utilisant les intégrations d’accès externe (EAIs).
En règle générale, vous souhaitez qu’un administrateur de compte crée des EAIs pour gérer l’accès externe autorisé à partir des tâches et des services. Les administrateurs de comptes peuvent alors accorder l’utilisation d’EAI à des rôles spécifiques que les développeurs utilisent pour exécuter des tâches ou des services.
L’exemple suivant décrit les étapes de la création d’une EAI qui autorise le trafic de sortie vers des destinations spécifiques spécifiées à l’aide de règles de réseau. Vous vous référez ensuite au EAI lorsque vous créez une tâche ou un service pour autoriser des requêtes vers des destinations Internet spécifiques.
Exemple
Supposons que vous souhaitiez que le code de votre application (tâche ou service) envoie des requêtes aux destinations suivantes :
Requêtes HTTPS vers translation.googleapis.com
Requêtes HTTP et HTTPS vers google.com
Suivez ces étapes pour permettre à votre tâche ou service d’accéder à ces domaines sur Internet :
Créez une intégration d’accès externe (EAI). Pour ce faire, il faut disposer des autorisations nécessaires. Par exemple, vous pouvez utiliser le rôle ACCOUNTADMIN pour créer une EAI. Il s’agit d’un processus en deux étapes :
Utilisez la commande CREATE NETWORK RULE pour créer une ou plusieurs règles de réseau de sortie répertoriant les destinations externes auxquelles vous souhaitez autoriser l’accès. Vous pouvez réaliser cet exemple avec une seule règle de réseau, mais pour l’illustration, nous créons deux règles de réseau :
Créez une règle de réseau nommée
translate_network_rule
:CREATE OR REPLACE NETWORK RULE translate_network_rule MODE = EGRESS TYPE = HOST_PORT VALUE_LIST = ('translation.googleapis.com');
Cette règle autorise les connexions TCP vers la destination
translation.googleapis.com
. Le domaine dans la propriété VALUE_LIST ne spécifie pas le numéro de port optionnel, de sorte que le port par défaut 443 (HTTPS) est supposé. Cela permet à votre application de se connecter à n’importe quelle URL qui commence parhttps://translation.googleapis.com/
.Créez une règle de réseau nommée
google_network_rule
:CREATE OR REPLACE NETWORK RULE google_network_rule MODE = EGRESS TYPE = HOST_PORT VALUE_LIST = ('google.com:80', 'google.com:443');
Cela permet à votre application de se connecter à n’importe quelle URL qui commence par
http://google.com/
ouhttps://google.com/
.
Snowpark Container Services ne prend en charge que les règles de réseau qui autorisent les ports 22, 80, 443 et 1024+. Si une règle de réseau référencée autorise l’accès à d’autres ports, la création du service échouera. Contactez votre représentant de compte si vous avez besoin d’utiliser des ports supplémentaires.
Note
Pour permettre à votre tâche ou service d’envoyer des requêtes HTTP ou HTTPS à n’importe quelle destination sur Internet, vous spécifiez « 0.0.0.0 » comme domaine dans la propriété VALUE_LIST. La règle de réseau suivante permet d’envoyer des requêtes « HTTP » et « HTTPS » n’importe où sur Internet. Seuls les ports 80 ou 443 sont pris en charge avec « 0.0.0.0 ».
CREATE NETWORK RULE allow_all_rule TYPE = 'HOST_PORT' MODE= 'EGRESS' VALUE_LIST = ('0.0.0.0:443','0.0.0.0:80');
Créez une intégration d’accès externe (EAI) qui spécifie que les deux règles de réseau de sortie précédentes sont autorisées :
CREATE EXTERNAL ACCESS INTEGRATION google_apis_access_integration ALLOWED_NETWORK_RULES = (translate_network_rule, google_network_rule) ENABLED = true;
L’administrateur du compte peut désormais accorder l’utilisation de l’intégration aux développeurs pour leur permettre d’exécuter une tâche/un service qui peut accéder à des destinations spécifiques sur Internet.
GRANT USAGE ON INTEGRATION google_apis_access_integration TO ROLE test_role;
Créez le service ou la tâche en fournissant l’EAI comme indiqué dans les exemples suivants. Le rôle qui crée le service ou la tâche a besoin du privilège d’utilisation sur l’EAI et du privilège de lecture sur les secrets référencés. Notez que vous ne pouvez pas utiliser le rôle ACCOUNTADMIN pour créer un service ou une tâche.
Créez un service :
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);
Cet exemple de requête CREATE SERVICE utilise une spécification de service en ligne et spécifie la propriété facultative EXTERNAL_ACCESS_INTEGRATIONS pour inclure l’EAI. L’EAI spécifie les règles de réseau qui autorisent le trafic de sortie du service vers les destinations spécifiques.
Créez une tâche :
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);
Cet exemple de commande EXECUTE SERVICE spécifie la spécification en ligne et la propriété facultative EXTERNAL_ACCESS_INTEGRATIONS pour inclure l’EAI. Cela autorise le trafic de sortie de la tâche vers les destinations spécifiées dans les règles de réseau que l’EAI autorise.
Communications réseau entre les conteneurs¶
Il y a deux considérations à prendre en compte :
Communications entre les conteneurs d’une instance de service : si une instance de service utilise plusieurs conteneurs, ces conteneurs peuvent communiquer entre eux via localhost (il n’est pas nécessaire de définir des points de terminaison dans la spécification du service).
Les conteneurs appartenant à différents services/différentes tâches ou de plusieurs instances de services : les conteneurs appartenant à différents services (ou à différentes instances d’un même service) peuvent communiquer en utilisant des points de terminaison définis dans des fichiers de spécification. Pour plus d’informations, voir Communications de service à service.
Utilisation des secrets Snowflake pour transmettre des identifiants de connexion à un conteneur¶
Si votre service ou votre tâche communique avec des points de terminaison externes (en dehors de Snowflake), vous devrez fournir des identifiants de connexion dans votre conteneur pour que votre code d’application puisse les utiliser. Pour ce faire, stockez d’abord vos identifiants de connexion dans des objets secrets Snowflake. Ensuite, dans le fichier de spécification du service ou de la tâche, incluez le champ containers.secrets
pour transmettre ces secrets aux conteneurs.
Vous pouvez soit transmettre ces identifiants de connexion à des variables d’environnement dans les conteneurs, soit les rendre disponibles dans des fichiers locaux dans les conteneurs. En fonction de votre choix, le fichier de spécification fournit des constructions, comme expliqué dans les sections suivantes.
Transmission de secrets en tant que variables d’environnement¶
Pour transmettre des secrets de conteneurs Snowflake en tant que variables d’environnement, incluez un champ containers.secrets
:
containers:
- name: main
image: <url>
secrets:
- snowflakeSecret: <snowflake-secret-name>
secretKeyRef: <secret-key-reference>
envVarName: <env-variable-name>
secretKeyRef
: cette valeur dépend du type de secret Snowflake. Valeurs possibles :
username
oupassword
si le secret Snowflake est de typepassword
.secret_string
si le secret Snowflake est de typegeneric_string
.access_token
si le secret Snowflake est de typeoauth2
.
Note
Les secrets transmis en tant que variables d’environnement ne peuvent pas être mis à jour après la création d’un service (ou d’une tâche).
Exemple 1 : transmission de secrets de type password comme variables d’environnement¶
Dans cet exemple, vous créez l’objet secret Snowflake suivant de type password
:
CREATE SECRET testdb.testschema.my_secret_object
TYPE = password
USERNAME = 'snowman'
PASSWORD = '1234abc';
Pour fournir cet objet secret Snowflake aux variables d’environnement (par exemple, LOGIN_USER
et LOGIN_PASSWORD
) dans votre conteneur, ajoutez le champ containers.secrets
suivant dans le fichier de spécification :
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
Dans cet exemple, le champ containers.secrets
est une liste de deux objets snowflakeSecret
:
Le premier objet fait correspondre
username
de l’objet secret de Snowflake à la variable d’environnementLOGIN_USER
de votre conteneur.Le second objet fait correspondre
password
de l’objet secret de Snowflake à la variable d’environnementLOGIN_PASSWORD
de votre conteneur.
Exemple 2 : passer des secrets de type generic_string comme variables d’environnement¶
Dans cet exemple, vous créez l’objet secret Snowflake suivant de type generic_string
:
CREATE SECRET testdb.testschema.my_secret
TYPE=generic_string
SECRET_STRING='
some_magic: config
';
Pour fournir cet objet secret Snowflake aux variables d’environnement (par exemple, GENERIC_SECRET) dans votre conteneur, vous ajoutez le champ containers.secrets
suivant dans le fichier de spécification :
containers:
- name: main
image: <url>
secrets:
- snowflakeSecret: testdb.testschema.my_secret
secretKeyRef: secret_string
envVarName: GENERIC_SECRET
À propos de la transmission de secrets de type oauth2 à des variables d’environnement¶
Ce scénario n’est pas utile, car lorsque les jetons OAuth expirent, un nouveau jeton doit être transmis au conteneur. Mais les secrets transmis en tant que variables d’environnement ne peuvent pas être mis à jour, il ne faut donc pas transmettre de secrets de type « oauth2 » en tant que variables d’environnement.
Transmission de secrets dans des fichiers de conteneurs locaux¶
Pour que les secrets de Snowflake soient accessibles à votre conteneur d’application dans les fichiers locaux du conteneur, incluez un champ containers.secrets
:
containers:
- name: <name>
image: <url>
...
secrets:
- snowflakeSecret: <snowflake-secret-name>
directoryPath: '<local directory path in the container>'
directoryPath
: Snowflake remplit un fichier pour chaque clé secrète dans le répertoire spécifié ; il n’est pas nécessaire de spécifier secretKeyRef
.
Note
Après la création d’un service (ou d’une tâche), si l’objet secret de Snowflake est mis à jour, Snowflake mettra à jour les fichiers secrets correspondants dans les conteneurs en cours d’exécution.
Exemple 1 : transmission de secrets de type password dans des fichiers de conteneurs locaux¶
Dans cet exemple, vous créez l’objet secret Snowflake suivant de type password
:
CREATE SECRET testdb.testschema.my_secret_object
TYPE = password
USERNAME = 'snowman'
PASSWORD = '1234abc';
Pour que ces identifiants de connexion soient disponibles dans les fichiers conteneurs locaux, ajoutez le champ containers.secrets
suivant dans le fichier de spécification :
containers:
- name: main
image: <url>
secrets:
- snowflakeSecret: testdb.testschema.my_secret_object
directoryPath: '/usr/local/creds'
Lorsque vous démarrez votre service ou votre tâche, Snowflake crée deux fichiers à l’intérieur des conteneurs : /usr/local/creds/username
et /usr/local/creds/password
. Votre code d’application peut alors lire ces fichiers.
Exemple 2 : transmission de secrets de type oauth2 dans des fichiers de conteneurs locaux¶
Dans cet exemple, vous créez l’objet secret Snowflake suivant de type 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;
Pour que ces identifiants de connexion soient disponibles dans les fichiers conteneurs locaux, ajoutez le champ containers.secrets
suivant dans le fichier de spécification :
containers:
- name: main
image: <url>
secrets:
- snowflakeSecret: testdb.testschema.oauth_secret
directoryPath: '/usr/local/creds'
Snowflake récupère le jeton d’accès de l’objet secret OAuth et crée /usr/local/creds/access_token
dans les conteneurs.
Lorsqu’une tâche ou un service utilise des secrets de type Outh2, la tâche ou le service est censé utiliser ce secret pour accéder à une destination Internet. Un secret oauth doit être autorisé par l’intégration d’accès externe (EAI) ; sinon CREATE SERVICE ou EXECUTE SERVICE échoueront. Cette exigence d’EAI supplémentaire ne s’applique qu’aux secrets de type oauth2 et non aux autres types de secrets.
En résumé, les étapes typiques de la création d’un tel service sont les suivantes :
Créez un secret de type oauth2 (voir plus haut).
Créez un EAI pour permettre l’utilisation du secret par un service ou une tâche. Par exemple :
CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION example_eai ALLOWED_NETWORK_RULES = (<name>) ALLOWED_AUTHENTICATION_SECRETS = (testdb.testschema.oauth_secret) ENABLED = true;
Créez un service ou une tâche qui inclut un champ
containers.secrets
dans la spécification. Il spécifie également la propriété facultative EXTERNAL_ACCESS_INTEGRATIONS pour inclure un EAI afin de permettre l’utilisation du secret oauth2.Exemple de commande CREATE SERVICE (avec spécification en ligne) :
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);
Pour plus d’informations sur la sortie, voir Sortie réseau.
Lignes directrices et limitations¶
Exigences en matière de plateforme pour les images : actuellement, Snowpark Container Services nécessite des images de plateforme linux/amd64.
Les conteneurs de services/tâches ne sont pas privilégiés : les conteneurs de services/tâches ne s’exécutent pas avec des privilèges et ne peuvent donc pas modifier la configuration du matériel sur l’hôte et ne peuvent modifier que des configurations OS limitées. Les conteneurs de services/tâches ne peuvent effectuer que les configurations du système d’exploitation qu’un utilisateur normal (c’est-à-dire un utilisateur qui n’a pas besoin d’être rooté) peut effectuer.
Renommage de la base de données et du schéma :
Ne renommez pas les bases de données et les schémas pour lesquels vous avez déjà créé un service. Renommer revient à déplacer un service vers une autre base de données et un autre schéma, ce qui n’est pas pris en charge. Par exemple :
Le nom du service DNS continuera à refléter l’ancien nom de la base de données et du schéma.
Les informations sur les bases de données et les schémas fournies par Snowflake aux conteneurs de service en cours d’exécution continueront à se référer aux anciens noms.
Les nouveaux journaux que les services intègrent dans la table d’événements continueront à faire référence aux anciens noms de base de données et de schéma.
La fonction de service continuera à référencer le service dans l’ancienne base de données et l’ancien schéma, et lorsque vous appellerez la fonction de service, elle échouera.
Une spécification de service peut faire référence à des objets tels que des zones de préparation de Snowflake et les référentiels d’images. Si vous renommez les noms des bases de données ou des schémas dans lesquels résident ces objets, vous devez mettre à jour manuellement les noms des bases de données et des schémas des objets référencés dans la spécification de service.
Suppression et annulation de la suppression d’une base de données et d’un schéma :
Lorsque vous supprimez la base de données ou le schéma parent, les services sont supprimés de manière asynchrone. Cela signifie qu’un service peut continuer à fonctionner pendant un certain temps avant que des processus internes ne le suppriment.
Si vous tentez d’annuler la suppression d’une base de données ou d’un schéma précédemment supprimé, il n’y a aucune garantie que les services seront restaurés.
Transfert de propriété : le transfert de propriété pour les services et les tâches n’est pas pris en charge.
Réplication : en ce qui concerne la réplication dans Snowflake, notez ce qui suit :
Les objets Snowpark Container Services, comme les services, les tâches, les pools de calcul et les référentiels, ne peuvent pas être répliqués.
Si vous créez un référentiel au sein d’une base de données, la base de données entière ne peut pas être répliquée. Si la base de données contient d’autres ressources, comme des services, des tâches ou des pools de calcul, le processus de réplication de base de données aboutira, mais ces objets individuels au sein de la base de données ne seront pas répliqués.
Délai d’expiration des tâches : les tâches Snowpark Container Services s’exécutent de manière synchrone. En cas d’expiration d’une instruction, la tâche est annulée. Le délai d’expiration par défaut d’une instruction est de deux jours. Les clients peuvent modifier le délai d’expiration en définissant le paramètre STATEMENT_TIMEOUT_IN_SECONDS à l’aide de ALTER SESSION.
ALTER SESSION SET statement_timeout_in_seconds=<time>
Il doit être défini avant l’exécution de la commande EXECUTE SERVICE.