Snowpark Container Services: サービスおよびジョブに関するその他の考慮事項¶
重要
Snowpark Container Servicesのジョブ機能は現在プライベートプレビュー中であり、 https://snowflake.com/legal のプレビュー規約に従うものとします。詳細については、Snowflakeの担当者にお問い合わせください。
コンテナー内部からのSnowflakeへの接続¶
サービスまたはジョブを開始すると、Snowflakeは実行中のコンテナーに認証情報を提供し、コンテナーコードがSnowflakeに接続して SQL を実行するためのドライバーを使用できるようにします(Snowflakeに接続するコンピューター上の他のコードと同様)。提供された認証情報は、サービスロールとして認証されます。Snowflakeは、情報の一部をコンテナーの環境変数として提供します。
Snowflakeのすべてのオブジェクトには、所有者ロールがあります。サービスまたはジョブの場合、Snowflakeには サービスロール と呼ばれる概念があります(この用語はサービスとジョブの両方に適用されます)。サービスロールは、Snowflakeと相互作用する際に、サービスが実行できる機能を決定します。これには SQL の実行、ステージへのアクセス、サービス間のネットワーキングが含まれます。
注釈
現在の実装では、サービスロールは所有者ロールと同一です。
たとえば、チュートリアル用の 共通セットアップ の一部として test_role
を作成します。ロールに必要な権限を付与し、サービスやジョブを作成する際にそのロールを使用します。このロールは、サービスやジョブの所有者ロールであり、サービスやジョブの能力を決定するサービスロールでもあります。
注釈
サービスロールは、 ACCOUNTADMIN、 SECURITYADMIN、 ORGADMIN など、いずれの権限ロールになることもできません。
サービスを作成すると、Snowflakeはそのサービス専用の「サービスユーザー」も作成します。サービスがクエリを実行すると、サービスユーザーとしてクエリを実行します。サービスユーザーができることは、サービスロールによって決まります。
Snowflakeへの接続¶
Snowflakeは、サービス/ジョブコード内でSnowflakeクライアントを構成するために、以下の環境変数を提供します。
SNOWFLAKE_ACCOUNT: サービスが現在実行されているSnowflakeアカウントの名前を提供します。
SNOWFLAKE_HOST: Snowflakeへの接続に使用するホスト名を指定します。
また、Snowflakeはコンテナー内の OAuth トークンを /snowflake/session/token
という名前のファイルで提供します。接続を作成する場合は、このトークンをコネクタに提供します。
コンテナーからSnowflakeへの接続を作成するときには、 SNOWFLAKE_HOST、 SNOWFLAKE_ACCOUNT、および OAuth トークンを使用する必要があります。SNOWFLAKE_HOST を使用せずに OAuth トークンを使用することはできず、 OAuth トークンをSnowpark Container Services外部で使用することはできません。詳細については、 SQL を実行するための OAuth トークンの使用 をご参照ください。
さまざまなSnowflakeドライバーを使用するサンプルコードについては、 Snowflake接続例 をご参照ください。
例
チュートリアル2 (
main.py
を参照)では、コードは以下のように環境変数を読み取ります。SNOWFLAKE_ACCOUNT = os.getenv('SNOWFLAKE_ACCOUNT') SNOWFLAKE_HOST = os.getenv('SNOWFLAKE_HOST')
このコードは、これらの変数を選択したSnowflakeクライアントの接続作成コードに渡します。コンテナーはこれらの認証情報を使用して、サービスロールをプライマリロールとする新しいセッションを作成し、クエリを実行します。以下のコード例は、Pythonで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' )
デフォルトのホストを使用する場合(つまり、接続を作成するときに
host
引数を含めない場合)は、他の形式の認証(ユーザー名とパスワードなど)を使用したSnowflakeへの接続がサポートされます。たとえば、以下の接続では、認証するユーザー名とパスワードを指定します。conn = snowflake.connector.connect( account = os.getenv('SNOWFLAKE_ACCOUNT'), user = '<user-name>', password = <password> )
デフォルトホストを使用するには、お客様のサービスからアカウントのSnowflakeホスト名へのアクセスを許可するネットワークルールと外部アクセスの統合が必要です。たとえば、アカウント名が MyAccount の場合、ホスト名は myaccount.snowflakecomputing.com になります。詳細については、 ネットワークエグレス をご参照ください。
アカウントのSnowflake APIホスト名に一致するネットワークルールを作成します。
CREATE OR REPLACE NETWORK RULE snowflake_egress_access MODE = EGRESS TYPE = HOST_PORT VALUE_LIST = ('myaccount.snowflakecomputing.com');
先行するネットワークルールを使用して統合を作成します。
CREATE EXTERNAL ACCESS INTEGRATION snowflake_egress_access_integration ALLOWED_NETWORK_RULES = (snowflake_egress_access) ENABLED = true;
SQL を実行するためのデータベースとスキーマコンテキストを設定します。¶
このセクションでは、2つの概念について説明します。
サービス/ジョブを作成するデータベースとスキーマを決定するためにSnowflakeが使用するロジック。
Snowflakeがこの情報をコンテナーに伝え、コンテナーコードが同じデータベースとスキーマコンテキストで SQL を実行できるようにするためのメソッド。
Snowflakeは以下のロジックを使用して、サービス/ジョブを作成するデータベースとスキーマを決定します。
サービスの場合、Snowflakeは CREATE SERVICE コマンドで提供されたサービス名を使用して、サービスのデータベースとスキーマコンテキストを決定します。
例1: 次の CREATE SERVICE コマンドは、サービス名として
test_service
を指定します。CREATE SERVICE test_service IN COMPUTE POOL ...
Snowflakeは、このサービスを現在のデータベースとスキーマに配置します。
例2: 次の CREATE SERVICE コマンドは完全修飾サービス名を指定します。
CREATE SERVICE test_db.test_schema.test_service IN COMPUTE POOL ...
Snowflakeは、現在のスキーマに関係なく、指定されたデータベース(
test_db
)とスキーマ(test_schema
)にサービスを配置します。
ジョブの場合、ジョブを作成するときに EXECUTE SERVICE コマンドを使用してジョブ名を指定することはありません。
EXECUTE SERVICE IN COMPUTE POOL ..
この場合は、どこにもジョブを配置する機会がありません。したがって、Snowflakeはジョブを現在のデータベースとスキーマに配置します。異なるスキーマでジョブに SQL ステートメントを実行させる場合は、異なるスキーマコンテキストを使用することができます。例:
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 ...
Snowflakeがサービス/ジョブを開始するときには、以下の環境変数を使用して、実行中のコンテナーにデータベースとスキーマ情報が提供されます。
SNOWFLAKE_DATABASE
SNOWFLAKE_SCHEMA
コンテナーコードでは、この例に示すように、接続コードで環境変数を使用して、使用するデータベースとスキーマを決定することができます。
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')
)
例
チュートリアル2 では、Snowflakeに接続して SQL ステートメントを実行するSnowflakeジョブを作成します。以下のステップは、チュートリアルのコードがどのように環境変数を使用するかをまとめたものです。
共通セットアップ(共通セットアップ セクションを参照)では、データベースとスキーマを含む、リソースを作成します。また、セッションの現在のデータベースとスキーマも設定します。
USE DATABASE tutorial_db; ... USE SCHEMA data_schema;
ジョブを作成(EXECUTE SERVICE を実行)すると、Snowflakeはコンテナーを起動し、コンテナー内の以下の環境変数をセッションの現在のデータベースとスキーマに設定します。
SNOWFLAKE_DATABASE は「TUTORIAL_DB」に設定
SNOWFLAKE_SCHEMA は「DATA_SCHEMA」に設定
ジョブコード(チュートリアル2の
main.py
を参照)はこれらの環境変数を読み取ります。SNOWFLAKE_DATABASE = os.getenv('SNOWFLAKE_DATABASE') SNOWFLAKE_SCHEMA = os.getenv('SNOWFLAKE_SCHEMA')
ジョブコードは SQL ステートメント(
main.py
のrun_job()
関数)を実行するコンテキストとしてデータベースとスキーマを設定します。{ "account": SNOWFLAKE_ACCOUNT, "host": SNOWFLAKE_HOST, "authenticator": "oauth", "token": get_login_token(), "warehouse": SNOWFLAKE_WAREHOUSE, "database": SNOWFLAKE_DATABASE, "schema": SNOWFLAKE_SCHEMA } ...
SNOWFLAKE_ACCOUNT、SNOWFLAKE_HOST、 SNOWFLAKE_DATABASE、 SNOWFLAKE_SCHEMA はSnowflakeがアプリケーションコンテナー用に生成する環境変数ですが、 SNOWFLAKE_WAREHOUSE はそうではありません(Snowflakeはウェアハウス名をコンテナーに渡さないため、チュートリアル2のアプリケーションコードがこの変数を作成しました)。
コンテナー用ウェアハウスの指定¶
サービス(またはジョブ)がSnowflakeに接続してSnowflakeウェアハウスでクエリを実行する場合は、ウェアハウスを指定する以下のオプションがあります。
アプリケーションコードでウェアハウスを指定します。 コードでクエリを実行するためにSnowflakeセッションを開始する際に、接続構成の一部としてウェアハウスを指定します。例については、 チュートリアル2 をご参照ください。
サービスの作成時にデフォルトのウェアハウスを指定します。 デフォルトのウェアハウスを指定するには、 CREATE SERVICE コマンドでオプションの QUERY_WAREHOUSE パラメーターを指定します。アプリケーションコードが接続構成の一部としてウェアハウスを提供しない場合、Snowflakeはデフォルトのウェアハウスを使用します。 ALTER SERVICE コマンドを使用して、デフォルトウェアハウスを変更します。
両方の方法でウェアハウスを指定した場合は、アプリケーションコードで指定されたウェアハウスが使用されます。
SQL を実行するための OAuth トークンの使用¶
Snowflakeが提供するすべてのクライアントは、認証方法として OAuth をサポートしています。Snowflakeと合わせてサービス/ジョブコンテナーも OAuth メカニズムを使用して認証します。たとえば、コンテナーが SQL を実行する場合、コンテナーは他のSnowflakeクライアントと同様に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'
)
サービス/ジョブを作成すると、Snowflakeはコンテナーを実行し、コンテナー内の /snowflake/session/token
にコンテナーが使用するOauthトークンを提供します。
この OAuth トークンについては、次の点に注意してください。
/snowflake/session/token
ファイルのコンテンツは10分で期限切れとなり、Snowflakeはこのファイルを数分ごとに更新するため、コンテンツは使用する直前に読み取る必要があります。コンテナーがSnowflakeに正常に接続した後には、有効期限は接続に適用されません(ユーザーが直接作成するセッションと同様)。この OAuth トークンは、特定のSnowflakeサービス/ジョブ内でのみ有効です。OAuth トークンをコピーしてサービス/ジョブ外部で使用することはできません。
OAuth トークンを使用して、コンテナーは以下のようにユーザーとサービス/ジョブロールとしてSnowflakeに接続します。
ユーザーはサービス/ジョブを作成した人です。
ロールはサービス/ジョブのサービスロールであり、これがサポートされる唯一のロールです。ロールを変更することはできません。
OAuth トークンを使用して接続すると、新しいセッションが作成されます。OAuth トークンはいずれの既存の SQL セッションとも関連付けられていません。
注釈
ストアドプロシージャの実行とサービス/ジョブの実行の大きな違いは、ストアドプロシージャはそれを実行する SQL と同じセッションで実行されることです。しかし、コンテナーが新しい接続を確立するたびに、新しいセッションが作成されます。
ネットワーク機能の構成¶
以下のセクションでは、サービスとジョブのネットワーク機能(ネットワークのイングレスとエグレス)を構成する方法を説明します。
ネットワークイングレス¶
インターネットからサービスとのやり取りできるようにするには、サービスがリッスンしているネットワークポートを、サービス仕様ファイルのエンドポイントとして宣言します。これらのエンドポイントはイングレスを制御します。
デフォルトでは、サービスエンドポイントはプライベートです。 サービス関数 と サービス間通信 のみがプライベートエンドポイントにリクエストできます。エンドポイントをパブリックと宣言すると、インターネットからのエンドポイントへのリクエストを許可することができます。サービスを作成するロール(パブリックエンドポイントを使用)は、アカウントの BIND SERVICE ENDPOINT 権限を持っている必要があります。
endpoints:
- name: <endpoint name>
port: <port number>
protocol : < TCP / HTTP / HTTPS >
public: true
例については、 チュートリアル1 をご参照ください。
注釈
現在、ネットワークイングレスをサポートしているのは、ジョブではなくサービスのみです。
イングレスとウェブアプリのセキュリティ¶
パブリックエンドポイントサポート(ネットワークイングレス)を使用して、ウェブホスティング用のSnowpark Container Servicesサービスを作成できます。セキュリティを強化するために、Snowflakeはプロキシサービスを採用して、クライアントからサービスへの受信リクエストと、サービスからクライアントへの送信応答をモニターします。このセクションでは、プロキシが何を行い、Snowpark Container Servicesに展開されたサービスにどのような影響を与えるかを説明します。
注釈
ローカルでサービスをテストする場合はSnowflakeプロキシを使用しないため、Snowpark Container Servicesに展開した場合とローカルでサービスを実行した場合のエクスペリエンスに違いが生じます。このセクションを確認し、より良いテストのためにローカル設定を更新してください。
例:
禁止されている HTTP メソッドをリクエストが使用する場合、プロキシは受信 HTTP リクエストを転送しません。
プロキシは、応答のContent-Typeヘッダーが実行可能ファイルを含むことを示す場合は、403応答をクライアントに送信します。
さらに、プロキシはリクエストと応答に新しいヘッダーを注入したり、既存のヘッダーを変更したりすることもできます。
たとえば、リクエストを受信すると、サービスは応答で HTML、 JavaScript、 CSS などのウェブページのコンテンツをクライアントのブラウザーに送信する可能性があります。ブラウザー上のウェブページはサービスの一部であり、ユーザーインターフェイスとして機能します。セキュリティ上の理由から、サービスに制限がある場合(他サイトへのネットワーク接続の制限など)に、サービスのウェブページにも同じ制限を設けたい場合があります。
デフォルトでは、サービスはインターネットにアクセスする権限を持っていません。ブラウザーでも、クライアントアプリがインターネットにアクセスし、データを共有する可能性を制限する必要があります。外部アクセス統合(EAI)を設定してサービスが example.com
(ネットワークエグレス を参照)にアクセスできるようにすると、サービスのウェブページもブラウザーを通して example.com
にアクセスできるようになります。
Snowflakeプロキシは、応答に Content-Security-Policy
(CSP)ヘッダーを追加して、サービスとウェブページに同じネットワーク制限を適用します。デフォルトでは、プロキシは一般的なセキュリティの脅威から守るために、応答にベースライン CSP を追加します。さらに、サービスが EAI を使用するように設定されている場合、プロキシはウェブページに対して EAI から CSP まで同じネットワークルールを適用します。この CSP により、ブラウザーのウェブページは、サービスがアクセスできるのと同じサイトにアクセスできるようになります。
以下のセクションでは、Snowflakeプロキシがサービスに対する受信リクエストをどのように処理し、サービスからクライアントへの送信応答をどのように変更するかを説明します。
サービスへの受信リクエスト¶
リクエストを受信すると、プロキシはリクエストをサービスに転送する前に以下を実行します。
禁止された HTTP メソッドを持つ受信リクエスト: 受信 HTTP リクエストが以下の禁止された HTTP メソッドのいずれかを使用する場合、プロキシはそのリクエストをサービスに転送しません。
TRACE
OPTIONS
CONNECT
クライアントへの応答送信¶
Snowflakeプロキシは、クライアントに応答を転送する前に、サービスから送信された応答にこれらの修正を適用します。
ヘッダースクラビング: Snowflakeプロキシは、これらの応答ヘッダーを削除します(存在する場合)。
X-XSS-Protection
Server
X-Powered-By
Public-Key-Pins
Content-Type応答ヘッダー: サービス応答でContent-Typeヘッダーに次の MIME 型の値(実行可能ファイルを示す)が含まれる場合、Snowflakeプロキシはその応答をクライアントに転送しません。代わりに、プロキシは
403 Forbidden
応答を送信します。application/x-msdownload
: Microsoftの実行可能ファイル。application/exe
: 汎用実行可能ファイル。application/x-exe
: 別の汎用実行可能ファイル。application/dos-exe
: DOS の実行可能ファイル。application/x-winexe
: Windowsの実行可能ファイル。application/msdos-windows
: MS-DOS Windows実行可能ファイル。application/x-msdos-program
: MS-DOS 実行可能ファイル。application/x-sh
: Unixシェルスクリプト。application/x-bsh
: Bourneシェルスクリプト。application/x-csh
: Cシェルスクリプト。application/x-tcsh
: Tcshシェルスクリプト。application/batch
: Windowsバッチファイル。
X-Frame-Options応答ヘッダー: クリックジャッキング攻撃を防ぐために、Snowflakeプロキシはこの応答ヘッダーを
DENY
に設定し、他のウェブページがサービスのウェブページにiframeを使用できないようにします。Cross-Origin-Opener-Policy(COOP)応答ヘッダー: Snowflakeは COOP 応答ヘッダーを
same-origin
に設定し、参照元のクロスオリジンウィンドウがサービスタブにアクセスできないようにします。Cross-Origin-Resource-Policy(CORP)応答ヘッダー: Snowflakeは CORP ヘッダーを
same-origin
に設定し、外部サイトが(iframeなどで)イングレスエンドポイントによって公開されたリソースをロードできないようにします。X-Content-Type-Options応答ヘッダー: Snowflakeプロキシはこのヘッダーを
nosniff
に設定し、クライアントがサービスによって応答に記載された MIME 型を変更できないようにします。Cross-Origin-Embedder-Policy(COEP)応答ヘッダー: Snowflakeプロキシは COEP 応答ヘッダーを
credentialless
に設定します。これは、画像やスクリプトなどのクロスオリジンオブジェクトをロードするときに、リモートオブジェクトがCross-Origin Resource Sharing(CORS)プロトコルをサポートしていない場合、Snowflakeはそれをロードするときに認証情報を送信しないことを意味します。Content-Security-Policy-Report-Only応答ヘッダー: Snowflakeプロキシは、クライアントに CSP レポートをSnowflakeに送信するよう指示する新しい値で、この応答ヘッダーを置き換えます。
Content-Security-Policy(CSP)応答ヘッダー: デフォルトでは、Snowflakeプロキシは、一般的なウェブ攻撃から保護するために、以下のベースライン CSP を追加します。
default-src 'self' 'unsafe-inline' 'unsafe-eval' http: https: blob: data:; object-src 'none'; connect-src 'self' http: https: wss:; frame-ancestors 'self';
コンテンツセキュリティポリシーの考慮点は2つあります。
プロキシが追加するベースラインコンテンツセキュリティポリシーに加えて、サービス自身が応答に明示的に CSP を追加することができます。サービスは、より厳格な CSP を追加して、セキュリティを強化することを選択する場合があります。たとえば、サービスは CSP を追加して、
self
からのスクリプトのみを許可する場合があります。script-src 'self'
結果としてクライアントに送られる応答には、2つの CSP ヘッダーがあります。応答を受信すると、クライアントブラウザーは、各ポリシーによって指定された追加制限を含む、最も厳格なコンテンツセキュリティポリシーを適用します。
サービスが外部サイト(ネットワークエグレス)にアクセスできるように外部アクセス統合(EAI)を構成すると、Snowflakeプロキシは、ウェブページがそのサイトにアクセスできるようにする CSP を作成します。たとえば、 EAI に関連付けられているネットワークルールが、サービスに
example.com
へのエグレスアクセスを許可しているとします。次に、Snowflakeプロキシは以下の CSP 応答ヘッダーを追加します。default-src 'self' 'unsafe-inline' 'unsafe-eval' http://example.com https://example.com blob: data:; object-src 'none'; connect-src 'self' http://example.com https://example.com wss://example.com; frame-ancestors 'self';
ブラウザーは、応答で受け取ったコンテンツアクセスポリシーを尊重します。この例では、ブラウザーはアプリに
example.com
へのアクセスを許可しますが、他のサイトへのアクセスは許可しません。
ネットワークエグレス¶
アプリケーション(ジョブまたはサービス)コードは、インターネットへのアクセスを必要とする場合があります。デフォルトでは、アプリケーションコンテナーはインターネットにアクセスする権限を持っていません。 外部アクセス統合(EAIs) を使用してインターネットアクセスを有効にする必要があります。
通常、ジョブやサービスから許可される外部アクセスを管理するために、アカウント管理者は EAIs を作成します。アカウント管理者は、開発者がジョブやサービスを実行するために使用する特定のロールに EAI の使用権限を付与できます。
次の例は、ネットワークルールを使用して指定された特定の宛先へのエグレストラフィックを許可する EAI を作成するステップの概要を示しています。その後、特定のインターネット宛先へのリクエストを許可するジョブやサービスを作成するときに、 EAI を参照します。
例
アプリケーション(ジョブまたはサービス)のコードが、以下の宛先にリクエストを送信するとします。
HTTPS が、translation.googleapis.comにリクエストする
HTTP と HTTPS が、google.comにリクエストする
以下のステップに従って、ジョブやサービスがインターネット上のこれらのドメインにアクセスできるようにします。
外部アクセス統合(EAI)を作成するこれには適切な権限が必要です。たとえば、 ACCOUNTADMIN ロールを使用して EAI を作成することができます。これは2段階のプロセスです。
CREATE NETWORK RULE コマンドを使用して、アクセスを許可する外部宛先をリストした1つ以上のエグレスネットワークルールを作成します。この例は1つのネットワークルールで実現できますが、説明のために2つのネットワークルールを作成します。
translate_network_rule
という名前のネットワークルールを作成します。CREATE OR REPLACE NETWORK RULE translate_network_rule MODE = EGRESS TYPE = HOST_PORT VALUE_LIST = ('translation.googleapis.com');
このルールは、
translation.googleapis.com
の宛先への TCP 接続を許可します。VALUE_LIST プロパティのドメインは、オプションのポート番号を指定しないため、デフォルトのポート443(HTTPS)が想定されます。これにより、アプリケーションはhttps://translation.googleapis.com/
で始まる任意の URL に接続できます。google_network_rule
という名前のネットワークルールを作成します。CREATE OR REPLACE NETWORK RULE google_network_rule MODE = EGRESS TYPE = HOST_PORT VALUE_LIST = ('google.com:80', 'google.com:443');
これにより、アプリケーションは
http://google.com/
またはhttps://google.com/
で始まる任意の URL に接続できます。
注釈
VALUE_LIST
パラメーターには、完全なホスト名を指定する必要があります。ワイルドカード(例:*.googleapis.com
)はサポートされていません。Snowpark Container Servicesは、ポート22、80、443、1024+を許可するネットワークルールのみをサポートします。参照されているネットワークルールが他のポートへのアクセスを許可している場合、サービスの作成は失敗します。追加のポートが必要な場合は、担当者にお問い合わせください。
注釈
ジョブまたはサービスが HTTP または HTTPS リクエストをインターネット上の任意の宛先に送信できるようにするには、 VALUE_LIST プロパティでドメインとして「0.0.0.0」を指定します。以下のネットワークルールは、インターネット上の任意の宛先に「HTTP」と「HTTPS」の両方のリクエストを送信することを許可します。「0.0.0.0」をサポートしているのは、ポート80または443のみです。
CREATE NETWORK RULE allow_all_rule TYPE = 'HOST_PORT' MODE= 'EGRESS' VALUE_LIST = ('0.0.0.0:443','0.0.0.0:80');
外部アクセス統合(EAI) を作成し、先行する2つのエグレスネットワークルールが許可されることを指定します。
CREATE EXTERNAL ACCESS INTEGRATION google_apis_access_integration ALLOWED_NETWORK_RULES = (translate_network_rule, google_network_rule) ENABLED = true;
これで、アカウント管理者は、開発者に統合の使用権限を付与して、インターネット上の特定の宛先にアクセスできるジョブ/サービスを実行できるようにすることができます。
GRANT USAGE ON INTEGRATION google_apis_access_integration TO ROLE test_role;
以下の例に示すように、 EAI を指定してサービスまたはジョブを作成します。サービスまたはジョブを作成するロールは、 EAI の使用権限と参照されるシークレットの読み取り権限が必要です。ACCOUNTADMIN ロールを使用してサービスやジョブを作成することはできません。
サービスを作成します。
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);
この例の CREATE SERVICE リクエストは、インラインサービス仕様を使用し、 EAI を含むようにオプションの EXTERNAL_ACCESS_INTEGRATIONS プロパティを指定します。EAI は、サービスから特定の宛先へのエグレストラフィックを許可するネットワークルールを指定します。
ジョブを作成します。
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);
この例の EXECUTE SERVICE コマンドは、インライン仕様と、 EAI を含めるためのオプション EXTERNAL_ACCESS_INTEGRATIONS プロパティを指定します。これは、ジョブから EAI が許可するネットワークルールで指定された宛先への、エグレストラフィックを許可します。
コンテナー間のネットワーク通信¶
次の2つを考慮します。
サービスインスタンスのコンテナー間の通信: サービスインスタンスが複数のコンテナーを実行する場合、これらのコンテナーはlocalhostを介して相互に通信できます(サービス仕様でエンドポイントを定義する必要はありません)。
複数のサービス/ジョブまたは複数のサービスインスタンスにまたがるコンテナー間の通信: 異なるサービス(または同じサービスの異なるインスタンス)に属するコンテナーは、仕様ファイルで定義されたエンドポイントを使用して通信できます。詳細については、 サービス間通信 をご参照ください。
Snowflakeシークレット使用によるコンテナー認証情報の引き渡し¶
サービスまたはジョブが外部エンドポイント(Snowflakeの外部)と通信する場合は、アプリケーションコードが使用できるように、コンテナー内に認証情報を提供する必要があります。そうするには、まず Snowflakeシークレット オブジェクトに認証情報を格納します。次に、サービスまたはジョブの仕様ファイルに、これらのシークレットをコンテナーに渡すための containers.secrets
フィールドを含めます。
これらの認証情報をコンテナー内の環境変数に渡すか、コンテナー内のローカルファイルで利用できるようにします。選択した内容に応じて、仕様ファイルは以下のセクションで説明するようなコンストラクトを提供します。
シークレットを環境変数として引き渡し¶
コンテナーにSnowflakeシークレットを環境変数として渡すには、 containers.secrets
フィールドを含めます。
containers:
- name: main
image: <url>
secrets:
- snowflakeSecret: <snowflake-secret-name>
secretKeyRef: <secret-key-reference>
envVarName: <env-variable-name>
secretKeyRef
: この値はSnowflakeシークレットの型によって異なります。可能な値:
username
、またはSnowflakeシークレットがpassword
型の場合はpassword
。Snowflakeシークレットが
generic_string
型の場合はsecret_string
。Snowflakeシークレットが
oauth2
型の場合はaccess_token
。
注釈
環境変数として渡されたシークレットは、サービス(またはジョブ)が作成された後に更新することはできません。
例1: パスワード 型のシークレットを環境変数として引き渡し¶
この例では、 password
型の以下のSnowflakeシークレットオブジェクトを作成します。
CREATE SECRET testdb.testschema.my_secret_object
TYPE = password
USERNAME = 'snowman'
PASSWORD = '1234abc';
このSnowflakeシークレットオブジェクトをコンテナー内の環境変数(例: LOGIN_USER
や LOGIN_PASSWORD
)に提供するには、仕様ファイルに以下の containers.secrets
フィールドを追加します。
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
この例の containers.secrets
フィールドは、2つの snowflakeSecret
オブジェクトのリストです。
最初のオブジェクトは、Snowflakeシークレットオブジェクトの
username
をコンテナーの環境変数LOGIN_USER
にマップします。2番目のオブジェクトは、Snowflakeシークレットオブジェクトの
password
をコンテナーの環境変数LOGIN_PASSWORD
にマップします。
例2: generic_string 型のシークレットを環境変数として引き渡し¶
この例では、 generic_string
型の以下のSnowflakeシークレットオブジェクトを作成します。
CREATE SECRET testdb.testschema.my_secret
TYPE=generic_string
SECRET_STRING='
some_magic: config
';
このSnowflakeシークレットオブジェクトをコンテナー内の環境変数(例: GENERIC_SECRET)に提供するには、仕様ファイルに以下の containers.secrets
フィールドを追加します。
containers:
- name: main
image: <url>
secrets:
- snowflakeSecret: testdb.testschema.my_secret
secretKeyRef: secret_string
envVarName: GENERIC_SECRET
oauth2 型のシークレットを環境変数に渡すことについて¶
これは、役に立つシナリオではありません。OAuth トークンでは、期限切れになると新しいトークンをコンテナーに渡す必要があるからです。しかし、環境変数として渡されたシークレットは更新できないため、「oauth2」型のシークレットは環境変数として渡さないでください。
ローカルコンテナーファイルでのシークレットの引き渡し¶
Snowflakeシークレットをローカルコンテナーファイル内のアプリケーションコンテナーで利用できるようにするには、 containers.secrets
フィールドを含めます。
containers:
- name: <name>
image: <url>
...
secrets:
- snowflakeSecret: <snowflake-secret-name>
directoryPath: '<local directory path in the container>'
directoryPath
: 指定されたこのディレクトリにあるシークレットキーごとに1つのファイルがSnowflakeによって入力されるため、 secretKeyRef
を指定する必要はありません。
注釈
サービス(またはジョブ)が作成された後、Snowflakeのシークレットオブジェクトが更新されると、Snowflakeは実行中のコンテナー内の対応するシークレットファイルを更新します。
例1: ローカルコンテナーファイルにおける password 型のシークレットの引き渡し¶
この例では、 password
型の以下のSnowflakeシークレットオブジェクトを作成します。
CREATE SECRET testdb.testschema.my_secret_object
TYPE = password
USERNAME = 'snowman'
PASSWORD = '1234abc';
これらの認証情報をローカルコンテナーファイルで利用できるようにするには、仕様ファイルに以下の containers.secrets
フィールドを追加します。
containers:
- name: main
image: <url>
secrets:
- snowflakeSecret: testdb.testschema.my_secret_object
directoryPath: '/usr/local/creds'
サービスまたはジョブを開始すると、Snowflakeはコンテナー内に /usr/local/creds/username
と /usr/local/creds/password
の2つのファイルを作成します。そうすると、アプリケーションコードはこれらのファイルを読み取ることができます。
例2: ローカルコンテナーファイルにおける oauth2 型のシークレットの引き渡し¶
この例では、 oauth2
型の以下のSnowflakeシークレットオブジェクトを作成します。
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;
これらの認証情報をローカルコンテナーファイルで利用できるようにするには、仕様ファイルに以下の containers.secrets
フィールドを追加します。
containers:
- name: main
image: <url>
secrets:
- snowflakeSecret: testdb.testschema.oauth_secret
directoryPath: '/usr/local/creds'
Snowflakeは OAuth シークレットオブジェクトからアクセストークンをフェッチし、コンテナーに /usr/local/creds/access_token
を作成します。
ジョブまたはサービスがoauth2型のシークレットを使用する場合、サービスまたはジョブはインターネット宛先にアクセスするためにそのシークレットを使用することが求められます。oauthシークレットは 外部アクセス統合(EAI) によって許可される必要があります。それ以外の場合、 CREATE SERVICE または SERVICE EXECUTE は失敗します。この追加の EAI 要件は、oauth2型のシークレットにのみ適用され、他の型のシークレットには適用されません。
要約すると、このようなサービスを作る際の典型的なステップは以下のとおりです。
oauth2型のシークレットを作成します(前述のとおり)。
サービスまたはジョブによるシークレットの使用を許可する EAI を作成します。例:
CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION example_eai ALLOWED_NETWORK_RULES = (<name>) ALLOWED_AUTHENTICATION_SECRETS = (testdb.testschema.oauth_secret) ENABLED = true;
仕様に
containers.secrets
フィールドを含むサービスまたはジョブを作成します。また、oauth2シークレットの使用を許可するために、 EXTERNAL_ACCESS_INTEGRATIONS プロパティに EAI を含めるようにオプションで指定します。CREATE SERVICE (インライン仕様を使用)コマンドの例:
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);
エグレスの詳細については、 ネットワークエグレス をご参照ください。
ガイドラインと制約¶
イメージプラットフォームの要件: 現在、Snowpark Container Servicesにはlinux/amd64プラットフォームイメージが必要です。
サービス/ジョブコンテナーの権限なし: サービス/ジョブコンテナーは権限として実行されないため、ホスト上のハードウェアの構成を変更できず、限られた OS 構成のみを変更できます。サービス/ジョブコンテナーは、通常のユーザー(つまり、ルートを必要としないユーザー)ができるオペレーティングシステム設定のみを実行できます。
データベースおよびスキーマの名前変更:
すでにサービスを作成したデータベースやスキーマの名前は変更しないでください。名前変更は事実上、サービスを別のデータベースとスキーマに移動することになりますが、これはサポートされていません。例:
サービス DNS 名は従来のデータベース名とスキーマ名を反映し続けます。
Snowflakeが実行中のサービスコンテナーに提供したデータベースとスキーマの情報は、引き続き従来の名前を参照します。
サービスがイベントテーブルにインジェストする新しいログは、従来のデータベース名とスキーマ名を参照し続けます。
サービス関数は従来のデータベースとスキーマのサービスを参照し続け、サービス関数を呼び出すと失敗します。
サービス仕様は、Snowflakeステージやイメージリポジトリなどのオブジェクトを参照することができます。これらのオブジェクトが存在するデータベース名やスキーマ名を変更した場合は、サービス仕様の参照オブジェクトのデータベース名やスキーマ名を手動で更新する必要があります。
データベースおよびスキーマのドロップおよびドロップ解除:
親データベースまたはスキーマをドロップすると、サービスは非同期に削除されます。つまり、内部プロセスでサービスが削除されるまで、しばらくの間サービスが実行され続ける可能性があります。
以前に削除されたデータベースやスキーマのドロップ解除を試行しても、サービスが復元される保証はありません。
所有権譲渡: サービスとジョブの所有権譲渡はサポートされていません。
複製: Snowflakeで複製を扱う場合、以下の点に注意してください。
サービス、ジョブ、コンピューティングプール、リポジトリなどのSnowpark Container Servicesオブジェクトを複製することはできません。
データベース内にリポジトリを作成した場合は、データベース全体を複製することはできません。データベースにサービス、ジョブ、コンピューティングプールなどの他のリソースが含まれている場合、データベースの複製プロセスは成功しますが、データベース内の個々のオブジェクトは複製されません。
ジョブのタイムアウト: Snowpark Container Servicesのジョブは同期的に実行されます。ステートメントがタイムアウトすると、ジョブはキャンセルされます。デフォルトのステートメントタイムアウトは2日間。お客様は、ALTER SESSION を使用してパラメーター STATEMENT_TIMEOUT_IN_SECONDS を設定することにより、タイムアウトを変更できます。
ALTER SESSION SET statement_timeout_in_seconds=<time>
EXECUTE SERVICE コマンドを実行する前に設定します。