SnowflakeのQuickstart「Build a Snowflake Native App with Snowpark Container Services」をやってみた

SnowflakeのQuickstart「Build a Snowflake Native App with Snowpark Container Services」をやってみた

Clock Icon2024.11.25

さがらです。

SnowflakeのQuickstart「Build a Snowflake Native App with Snowpark Container Services」をやってみたので、その内容をまとめてみます。

https://quickstarts.snowflake.com/guide/build-a-native-app-with-spcs/index.html?index=..%2F..index#0

検証環境

  • Ubuntu 24.04LTS(WSL2上で動作)
  • Rancher Desktop 1.14.2

1.Overview

このQuickstartの概要についてまとめられています。

このQuickstartを通すことで、Snowpark Container Servicesを用いたSnowflake Native App Frameworkに沿ったアプリケーションをSnowflakeアカウントにデプロイすることが出来ます。

アプリケーションの内容としては、TPC-Hのデータセットを照会して上位の販売員を返し、表示する販売データや販売員の数をGUI上で変更することができるアプリケーションとなっています。アーキテクチャとしては、VueベースのJavaScriptのフロントエンド、FlaskベースのPythonのバックエンド、ルーターとしてのnginx、となっています。

2.Snowflake Application Code

ここでは、Snowflake社が用意している下記のリポジトリをローカルにクローンします。

https://github.com/Snowflake-Labs/sfguide-build-a-native-app-with-spcs

git clone https://github.com/Snowflake-Labs/sfguide-build-a-native-app-with-spcs

3.Native App Provider Setup

次は、Snowflake側でNative Appの開発・デプロイに必要なオブジェクトの作成をしていきます。

まず、操作用のロールとしてnaspcs_roleというロールを作成します。create application packageなど、必要な権限を付与します。

use role accountadmin;
create role if not exists naspcs_role;
grant role naspcs_role to role accountadmin;
grant create integration on account to role naspcs_role;
grant create compute pool on account to role naspcs_role;
grant create warehouse on account to role naspcs_role;
grant create database on account to role naspcs_role;
grant create application package on account to role naspcs_role;
grant create application on account to role naspcs_role with grant option;
grant bind service endpoint on account to role naspcs_role;

次に、アプリケーション用のファイルやコンテナイメージを保存するためのデータベースなどを作成していきます。

use role naspcs_role;
create database if not exists spcs_app;
create schema if not exists spcs_app.napp;
create stage if not exists spcs_app.napp.app_stage;
create image repository if not exists spcs_app.napp.img_repo;
create warehouse if not exists wh_nap with warehouse_size='xsmall';

4.Consumer Privilege Setup

次に、デプロイされたアプリケーションを用いて分析をするためのロール、分析用のデータを格納するデータベース、などのオブジェクトを作成します。

まずは分析用のロールとしてnacというロールを作成します。

use role accountadmin;
create role if not exists nac;
grant role nac to role accountadmin;
create warehouse if not exists wh_nac with warehouse_size='xsmall';
grant usage on warehouse wh_nac to role nac with grant option;
grant imported privileges on database snowflake_sample_data to role nac;
grant create database on account to role nac;
grant bind service endpoint on account to role nac with grant option;
grant create compute pool on account to role nac;
grant create application on account to role nac;

分析用のデータを格納するデータベース・スキーマ・テーブルを作成します。

use role nac;
create database if not exists nac_test;
create schema if not exists nac_test.data;
use schema nac_test.data;
create view if not exists orders as select * from snowflake_sample_data.tpch_sf10.orders;

5. Build and Upload Container Images

これまでの工程で格納場所は出来たので、コンテナイメージをビルドしてSnowflake上のイメージリポジトリにプッシュしていきます。

5.1 Get Image Repository URL

まず、Snowflake上で下記のクエリを実行して、コンテナイメージのアップロード先を確認し、コピーしておきます。

use role naspcs_role;
show image repositories in schema spcs_app.napp;

2024-11-25_15h20_14

5.2 Build and Push Images

次に、コンテナイメージをビルドし、Snowflakeのイメージリポジトリにプッシュしていきます。

このチュートリアルでは2種類の方法が提示されているのですが、Step 5.2.2 - Individual Docker Commandsの方法に沿ってやっていきます。

※ここから、<SNOWFLAKE_REPO>は先程コピーしたイメージリポジトリのURLに書き換えて各コマンドを実行していきます。

まず、Snowflake上のイメージリポジトリにログインします。

docker login <SNOWFLAKE_REPO>

2024-11-25_15h42_10

次に、バックエンドに関するコンテナイメージをビルドし、Snowflakeのイメージリポジトリにプッシュします。

cd backend
docker build --platform linux/amd64 -t eap_backend .
cd ..
docker tag eap_backend <SNOWFLAKE_REPO>/eap_backend
docker push <SNOWFLAKE_REPO>/eap_backend

2024-11-25_15h46_32

次に、フロントエンドに関するコンテナイメージをビルドし、Snowflakeのイメージリポジトリにプッシュします。

cd frontend  
docker build --platform linux/amd64 -t eap_frontend . 
cd ..
docker tag eap_frontend <SNOWFLAKE_REPO>/eap_frontend
docker push <SNOWFLAKE_REPO>/eap_frontend

2024-11-25_15h52_12

最後に、ルーターに関するコンテナイメージをビルドし、Snowflakeのイメージリポジトリにプッシュします。

cd router 
docker build --platform linux/amd64 -t eap_router . 
cd ..
docker tag eap_router <SNOWFLAKE_REPO>/eap_router
docker push <SNOWFLAKE_REPO>/eap_router

2024-11-25_15h56_15

あとはQuickstartにも載っていないおまけですが、以下のクエリを実行するとプッシュしたイメージの一覧が確認できます。

show images in image repository spcs_app.napp.img_repo;

2024-11-25_17h33_43

5.3 Upload Native App Code

次に、App packageの構築に使用するコードをSPCS_APP.NAPP.APP_STAGEステージにアップロードします。

クローンしたリポジトリの/app/srcフォルダ内にあるsetup.sqlfullstack.yamlmanifest.ymlreadme.mdを全てSPCS_APP.NAPP.APP_STAGEステージにアップロードします。

アップロード後、SPCS_APP.NAPP.APP_STAGEステージは下図のようになります。

2024-11-25_16h04_34

参考までに、各ファイルの内容は下記のようになっています。

  • setup.sql:アプリケーションに関連するロールやスキーマの作成と、アプリケーションの起動や停止に使用するストアドプロシージャを定義するSQLが記述されたファイル。setup scriptに関して詳細は公式Docもご覧ください。
    • 下記の内容はサンプルコードをそのまま貼り付けていますが、個人的にはロールのベストプラクティスに沿って、各ロールをSYSADMINにGRANTして各オブジェクトをSYSADMIN・ACCOUNTADMINも見れるようにした方が良いと思います。
CREATE APPLICATION ROLE app_admin;
CREATE APPLICATION ROLE app_user;
CREATE SCHEMA IF NOT EXISTS app_public;
GRANT USAGE ON SCHEMA app_public TO APPLICATION ROLE app_admin;
GRANT USAGE ON SCHEMA app_public TO APPLICATION ROLE app_user;
CREATE OR ALTER VERSIONED SCHEMA v1;
GRANT USAGE ON SCHEMA v1 TO APPLICATION ROLE app_admin;

CREATE PROCEDURE v1.register_single_callback(ref_name STRING, operation STRING, ref_or_alias STRING)
 RETURNS STRING
 LANGUAGE SQL
 AS $$
      BEGIN
      CASE (operation)
         WHEN 'ADD' THEN
            SELECT system$set_reference(:ref_name, :ref_or_alias);
         WHEN 'REMOVE' THEN
            SELECT system$remove_reference(:ref_name);
         WHEN 'CLEAR' THEN
            SELECT system$remove_reference(:ref_name);
         ELSE
            RETURN 'Unknown operation: ' || operation;
      END CASE;
      RETURN 'Operation ' || operation || ' succeeds.';
      END;
   $$;
GRANT USAGE ON PROCEDURE v1.register_single_callback( STRING,  STRING,  STRING) TO APPLICATION ROLE app_admin;

CREATE OR REPLACE PROCEDURE app_public.start_app(poolname VARCHAR, whname VARCHAR)
    RETURNS string
    LANGUAGE sql
    AS $$
BEGIN
        EXECUTE IMMEDIATE 'CREATE SERVICE IF NOT EXISTS app_public.st_spcs
            IN COMPUTE POOL Identifier(''' || poolname || ''')
            FROM SPECIFICATION_FILE=''' || '/fullstack.yaml' || '''
            QUERY_WAREHOUSE=''' || whname || '''';
GRANT USAGE ON SERVICE app_public.st_spcs TO APPLICATION ROLE app_user;
GRANT SERVICE ROLE app_public.st_spcs!ALL_ENDPOINTS_USAGE TO APPLICATION ROLE app_user;

RETURN 'Service started. Check status, and when ready, get URL';
END;
$$;
GRANT USAGE ON PROCEDURE app_public.start_app(VARCHAR, VARCHAR) TO APPLICATION ROLE app_admin;

CREATE OR REPLACE PROCEDURE app_public.stop_app()
    RETURNS string
    LANGUAGE sql
    AS
$$
BEGIN
    DROP SERVICE IF EXISTS app_public.st_spcs;
END
$$;
GRANT USAGE ON PROCEDURE app_public.stop_app() TO APPLICATION ROLE app_admin;

CREATE OR REPLACE PROCEDURE app_public.app_url()
    RETURNS string
    LANGUAGE sql
    AS
$$
DECLARE
    ingress_url VARCHAR;
BEGIN
    SHOW ENDPOINTS IN SERVICE app_public.st_spcs;
    SELECT "ingress_url" INTO :ingress_url FROM TABLE (RESULT_SCAN (LAST_QUERY_ID())) LIMIT 1;
    RETURN ingress_url;
END
$$;
GRANT USAGE ON PROCEDURE app_public.app_url() TO APPLICATION ROLE app_admin;
GRANT USAGE ON PROCEDURE app_public.app_url() TO APPLICATION ROLE app_user;
  • fullstack.yaml:上述のsetup.sql内で定義しているストアドプロシージャapp_public.start_app内で使用する、作成するServiceの仕様をまとめたファイル。
spec:
  containers:
    - name: eap-frontend
      image: /spcs_app/napp/img_repo/eap_frontend
      env:
        VUE_APP_API_URL: /api/snowpark
    - name: eap-backend
      image: /spcs_app/napp/img_repo/eap_backend
    - name: eap-router
      image: /spcs_app/napp/img_repo/eap_router
      env:
        FE_SERVER: 127.0.0.1:8080
        BE_SERVER: 127.0.0.1:8081
  endpoints:
    - name: app
      port: 8000
      public: true
  • manifest.yml:Application Packageがアプリケーションを作成・管理するために必要な情報を定義している。セットアップスクリプト(今回でいうとsetup.sql)の場所、readmeファイルの場所、バージョン定義、アプリの構成情報が含まれます。manifest fileに関しては公式Docも併せてご覧ください。
#version identifier
manifest_version: 1

version:
  name: V1
  label: "Version One"
  comment: "The first version of our Native Application that includes SPCS"

#artifacts that are distributed from this version of the package
artifacts:
  readme: readme.md
  setup_script: setup.sql
  container_services:
    images:
      - /spcs_app/napp/img_repo/eap_frontend
      - /spcs_app/napp/img_repo/eap_backend
      - /spcs_app/napp/img_repo/eap_router

privileges:
 - CREATE COMPUTE POOL:
      description: "Enable application to create its own compute pool(s)"
 - BIND SERVICE ENDPOINT:
      description: "Enables application to expose service endpoints"
 - CREATE WAREHOUSE:
      description: "Enables application to create its own warehouse(s)"

references:
  - ORDERS_TABLE:
      label: "Orders View"
      description: "View created on Orders table from TPC-H samples"
      privileges:
        - SELECT
      object_type: VIEW
      multi_valued: false
      register_callback: v1.register_single_callback
  • readme.md:Snowsightからアプリケーションの詳細を確認した際に表示されるテキスト(Markdownで記述)
# build-a-native-app-with-spcs
 How to Build a Native App that includes Snowpark Container Services

6.Create Application Package

次に、Application Packageを作成し、アプリ利用者でインストール出来るようにnacロールに必要な権限の付与も行います。alter applicationコマンドは30秒ほど要するためご注意ください。

use role naspcs_role;
create application package spcs_app_pkg;
alter application package spcs_app_pkg add version v1 using @spcs_app.napp.app_stage;
grant install, develop on application package spcs_app_pkg to role nac;

このコマンドが完了すると、SPCS_APP_PKGというApplication Packageが作られて、Databasesから確認できます。

2024-11-25_17h37_26

また、ステージに置いたmanifest.ymlを参照して実行しているので、show versions in applicationを実行すると下図のようにmanifest.ymlを参照した内容で新しいバージョンV1が作成されます。

show versions in application package spcs_app_pkg;

2024-11-25_17h46_59

Snowsightからも、ProjectsApp Packagesから作成したApplication Packageが確認できます。

2024-11-25_17h58_56

2024-11-25_18h00_14

7.Install & Run Application

Snowflake上にApplication Packageは構築できたので、あとはこのApplication Packageを用いてアプリケーションをインストールしてSnowpark Container Services上で起動していきます。

7.1 Install App as the Consumer

今回アプリを利用するロールであるnacロールを使って、Application Packageからアプリケーションをインストールします。

use role nac;
create application spcs_app_instance from application package spcs_app_pkg using version v1;

2024-11-25_16h22_49

7.2 Create Compute Pool and Grant Privileges

インストールしたアプリケーション用のSnowpark Container ServicesのCompute Poolを作成し、必要な権限を付与します。

use database nac_test;
use role nac;
create compute pool pool_nac for application spcs_app_instance
    min_nodes = 1 max_nodes = 1
    instance_family = cpu_x64_s
    auto_resume = true;

grant usage on compute pool pool_nac to application spcs_app_instance;
grant usage on warehouse wh_nac to application spcs_app_instance;
grant bind service endpoint on account to application spcs_app_instance;
CALL spcs_app_instance.v1.register_single_callback(
  'ORDERS_TABLE' , 'ADD', SYSTEM$REFERENCE('VIEW', 'NAC_TEST.DATA.ORDERS', 'PERSISTENT', 'SELECT'));

7.3 Start App Service

これでアプリケーションを動かす準備は整ったので、実際にアプリケーションを起動してみます。

まず、下記のストアドプロシージャを実行して、作成したCompute Poolとウェアハウスを利用してアプリケーションを起動します。

call spcs_app_instance.app_public.start_app('POOL_NAC', 'WH_NAC');

2024-11-25_16h29_05

その後、下記の別のストアドプロシージャを実行して、アプリケーションのURLを確認します。

call spcs_app_instance.app_public.app_url();

起動には数分かかるため、準備が整っていないと下図のように結果が返ってきます。

2024-11-25_16h30_29

無事に準備が整った上でこのストアドプロシージャを実行すると、下図のようにURLが返ってきます。

2024-11-25_16h31_37

このURLをブラウザで貼り付けてEnterを押してみると、下図のように認証の画面が表示されます。

2024-11-25_16h33_09

認証を終えてサインインすると、下図のようにアプリケーションが表示されました。

2024-11-25_16h34_23

また、SnowsightのApps欄からも同じようにインストールしたアプリケーションを確認できます。

2024-11-25_16h36_29

右側の「…」からView detailsを押すことで、アプリケーションに関する情報を得ることが出来ます。例えば、About the appタブでは、ステージにアップロードしたreadme.mdの内容が表示されています。(右上のLaunch appを押してもワークシートに移動するだけでアプリケーションの画面には遷移しないためご注意ください。)

2024-11-25_16h41_04

8.Cleanup

このままアプリケーションを起動したまま放置するとコストがかなりかかってしまいますので、下記のクエリを実行してクリーンアップします。

※Quickstartに記載のあったdrop application spcs_app_instanceはそのまま実行するとエラーとなったので、cascadeオプションを追加しています。

--clean up consumer objects
use role nac;
drop application spcs_app_instance cascade;
drop compute pool pool_nac;
drop database nac_test;

--clean up provider objects
use role naspcs_role;
drop application package spcs_app_pkg;
drop database spcs_app;
drop warehouse wh_nap;

--clean up prep objects
use role accountadmin;
drop warehouse wh_nac;
drop role naspcs_role;
drop role nac;

最後に

SnowflakeのQuickstart「Build a Snowflake Native App with Snowpark Container Services」をやってみました。

最後のクリーンアップ時のcascadeオプションの追加以外は詰まることなく、Quickstartに記載されたコマンドを実行していくだけでSnowpark Container Servicesを用いたアプリケーションのデプロイが出来ました!Snowpark Container Servicesの取っ掛かりとしてはちょうどよいチュートリアルだと思います。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.