SELECTSELECT

SELECT

SnowflakeのCI/CDとDevOps(後編):実装ステップ完全ガイド

By Tomáš SobotíkJul 9, 20257 min read

このページはEnglishDeutschEspañolFrançaisItalianoPortuguêsでもご覧いただけます。

前回の記事では、SnowflakeのさまざまなDevOps機能を取り上げました。これらは、Snowflakeのインフラをコードとして管理し、自動化していくための個別の構成要素です。

本記事では、CREATE OR ALTER、Git連携、EXECUTE IMMEDIATE FROMといったSnowflake標準機能を組み合わせて、Snowflakeインフラの自動デプロイを実現するCI/CDパイプラインの構築方法を解説します。リポジトリにはGitHub、オーケストレーターにはGitHub Actionsを使用します。

まずは、GitHub Actionsのワークフローについて簡単に整理しておきましょう。

GitHub Actionsのワークフロー

GitHub Actionsは、GitHubに組み込まれた強力なCI/CDプラットフォームです。イベント駆動型のパイプラインによって、ソフトウェア開発のさまざまな作業を自動化できます。ワークフローはYAMLファイルで定義し、リポジトリの.github/workflows/ディレクトリに配置します。各ワークフローは、ランナーと呼ばれる仮想マシン上で動作する1つ以上のジョブで構成されます。ランナーはGitHubがホストしてくれるため、こちら側で管理する必要はありません。ワークフローがトリガーされると自動的に割り当てられますが、セルフホスト型のランナーを使うこともできます。

パイプラインを作るには、いくつかの要素を定義する必要があります。

トリガー

リポジトリ上のイベント(push、pull_requestなど)、cronによるスケジュール実行、あるいは手動トリガーを指定できます。

ランナー環境

コードを実行する場所、すなわちランナーのOSを指定します。代表的なものはubuntu-latestやwindows-latestです。

自動化の構成

続いて、自動化の中身を定義します。実体は、一連のステップの集まりです。ここで意識しておきたいのは、コードを実行するたびにランナーマシンはデフォルトのクリーンな状態で起動するという点です。そのため、必要な言語(Pythonなど)のインストール、リポジトリからのコード取得、環境変数の読み込みといった準備をジョブごとに行う必要があります。各ステップは、シェルコマンド、スクリプトの実行、ビルド済みアクションのいずれかで構成できます。さらに各ステップでは、${{ github.event_name }}${{ secrets.SF_ACCOUNT_ID }}などのコンテキスト情報も利用できます。

こうした特性により、GitHub Actionsは、DB認証情報を安全に管理しつつSQLスクリプトを実行し、複数環境へ変更を反映し、誰がいつ変更したかを追跡する必要があるCI/CDパイプラインに非常によく適しています。しかも、バージョン管理との連携が標準で組み込まれています。

アカウントインフラ向けのSnowflake CI/CDパイプライン

ここからはVS Codeを使ったローカル環境で、SQLスクリプトとGitHub Actions用のYAML定義を書いていきます。準備ができたら、リモートリポジトリにプッシュしてプルリクエストを作成し、devブランチへマージします。図のとおり、ここではいくつかのSnowflake機能を組み合わせて使います。また、CI/CDパイプラインは2つのバリエーションで作成します。

1 SnowflakeのGit拡張機能を使う方法 このアプローチでは、GitHub Actionsはあくまでオーケストレーターとして動作します。Git拡張機能を使うことで、すべてのコードをSnowflake内で直接実行できます。

2 SnowCLIを使ってGitHubランナー上で実行する方法 SnowflakeのGit拡張機能を使いたくない場合は、Snowflake Command Line Interface(SnowCLI)を利用して、ランナーマシン上で直接コードを実行することもできます。こちらの方法もあわせて紹介します。

Snowflakeインフラの作成

まずはインフラを定義し、複数のSQLファイルに分けて保存していきましょう。

ウェアハウス:

USE ROLE sysadmin;

--ELT warehouse definition
CREATE WAREHOUSE IF NOT EXISTS elt WITH
WAREHOUSE_SIZE = XSMALL
AUTO_SUSPEND = 60
AUTO_RESUME = True
INITIALLY_SUSPENDED = True;

--developers warehouse definition
CREATE WAREHOUSE IF NOT EXISTS developers WITH
WAREHOUSE_SIZE = SMALL
AUTO_SUSPEND = 120
AUTO_RESUME = True
INITIALLY_SUSPENDED = True;

続いてロールも用意します。

/*
 * Role name: LOADER
 * Description: Used by ELT pipelines to load data */
 */
USE ROLE securityadmin;
CREATE OR ALTER ROLE loader;

最後に、データベースとスキーマです。

/*
 * DB name: DEVOPS
 * Description: Used for showcasing Snowflake DevOps capabilities
 */
use role sysadmin;

create or alter database devops;

------------------------SCHEMAS------------------------

/*
 * Schema name: ADMIN
 * Description: To keep all admin stuff at one place
 */

コードを展開

Gitステージを活用したCI/CDパイプライン

初期SQLスクリプトの準備ができたので、次はGitHub Actionsのワークフローを組み立てていきます。このワークフローはSnowflakeのGit拡張機能を利用するため、SnowflakeアカウントとGitHubリポジトリの連携があらかじめ有効になっていることが前提です。連携の設定方法は、~ SnowflakeのGit連携 ~に関する別記事で詳しく解説しています。

name: Deploying Snowflake objects with CLI v1
env:
  SNOWFLAKE_ACCOUNT: ${{ secrets.SF_ACCOUNT }}
  SNOWFLAKE_USER: ${{ secrets.SF_USER }}
  SNOWFLAKE_PASSWORD: ${{ secrets.SF_PASSWORD }}
  SNOWFLAKE_DATABASE: ${{ secrets.SF_DATABASE }}
  SNOWFLAKE_SCHEMA: ${{ secrets.SF_SCHEMA }}
  SNOWFLAKE_ROLE: ${{ secrets.SF_ROLE }}
  SNOWFLAKE_WAREHOUSE: ${{ secrets.SF_WAREHOUSE }}

on:
  workflow_dispatch:

jobs:
  deploy-Snowflake-changes:

コードを展開

このコードが何をしているのか、順を追って見ていきましょう。

最初に、Snowflakeへ接続するための環境変数を設定しています。値はGitHub Secretsから取得します。次にトリガーを定義します。ここではworkflow_dispatchを指定しているので、リポジトリから手動でワークフローを起動する形になります。

あとはシンプルです。GitHubランナーにSnowCLIをインストールし、以下を実行できる状態にします。

  • Snowflakeへの接続
  • 必要なコマンドの実行

Snowflake公式から、セットアップと接続管理を簡単にしてくれるネイティブな~ GitHub Action ~が提供されています。

まずはALTER GIT REPOSITORYコマンドで、SnowflakeのGitリポジトリステージをリモートリポジトリと同期します。これにより、最新の変更がSnowflake内のGitステージへ直接取り込まれます。

次に、EXECUTE IMMEDIATEでSQLファイルのコードを直接実行します。ウェアハウス、ロール、データベースとスキーマをデプロイすれば完了です。これだけで、Snowflakeインフラへの変更をコードとして自動デプロイする、シンプルかつ実用的なワークフローのできあがりです。

GitHubランナー上でコードを実行するCI/CDパイプライン

同様のパイプラインをもう一つ作りますが、今度はSnowflakeのGitステージを使わず、すべてGitHubランナーマシン上で実行します。Gitステージは便利な機能ですが、読み取り専用であることや、プライベートネットワーク内のリポジトリにはアクセスできないなど、いくつかの制約があります。ケースによっては、SnowflakeのGit連携を採用しない理由になるかもしれません。YAMLワークフロー定義は次のとおりです。

name: Deploying Snowflake objects with cli v2

env:
  SNOWFLAKE_ACCOUNT: ${{ secrets.SF_ACCOUNT }}
  SNOWFLAKE_USER: ${{ secrets.SF_USER }}
  SNOWFLAKE_PASSWORD: ${{ secrets.SF_PASSWORD }}
  SNOWFLAKE_DATABASE: ${{ secrets.SF_DATABASE }}
  SNOWFLAKE_SCHEMA: ${{ secrets.SF_SCHEMA }}
  SNOWFLAKE_ROLE: ${{ secrets.SF_ROLE }}
  SNOWFLAKE_WAREHOUSE: ${{ secrets.SF_WAREHOUSE }}

on:
  workflow_dispatch:

jobs:
  deploy-Snowflake-changes:
    name: Snowflake infrastructure deployment

コードを展開

前のバージョンとの違いに注目してみましょう。今回はリモートリポジトリからランナーマシンへコードを持ってくる必要があります。そのために、リモートのコードを取得するcheckoutという別のアクションを使います。

その後はあらためてSnowCLIを使いますが、今回はリポジトリステージ上のファイルではなく、ランナーマシンに置かれたファイルからコードを実行します。

さらなる改善ポイント

ここまではSnowflakeインフラをデプロイする基本的なCI/CDパイプラインのシンプルな例でした。「本番運用に耐える」レベルに引き上げる余地はまだまだあります。実際の運用環境では、たとえば次のような構成が考えられます。

  • 環境ごと(dev、prod)にパイプラインを分ける
  • pushやpull requestのトリガーを特定のブランチに限定する
  • pushイベントとpull requestイベントで異なるステップを実行する

個人的には、Terraformのように、変更前に「どのリソースが作成・更新・削除されるか」を可視化する「plan」ステップがあると便利だと感じます。Snowflakeのネイティブ機能にも、いずれ同等の仕組みが登場することに期待しましょう。

まとめ

本記事では、継続的インテグレーションとデプロイにSnowflake標準のDevOps機能を活用する方法を解説しました。GitHub Actionsワークフローを使ったCI/CDパイプラインを実装し、ローカルマシンからリポジトリへ変更をプッシュするだけで、Snowflakeのインフラオブジェクトをコードとしてリモートリポジトリから直接デプロイできる仕組みを構築しました。

これでSnowflake上のDevOps運用をテーマにした連載は最終回となります。本シリーズは3本の記事で構成しました。

  1. SnowflakeのGit連携を徹底解説
  2. SnowflakeのCI/CDとDevOps(前編):機能とツールの全体像
  3. SnowflakeのCI/CDとDevOps(後編):実装ステップ完全ガイド

Tomáš Sobotík・Senior Data Engineer & Snowflake SME at Norlys

Tomasは長きにわたるSnowflake Data SuperHeroであり、Snowflakeに関する幅広い領域に精通したエキスパートです。10年以上にわたるデータ業界でのキャリアの中で、Snowflakeのデータエンジニア、アーキテクト、管理者として、さまざまな業界・技術領域のプロジェクトに携わってきました。コミュニティのコアメンバーとしても活発に知見を発信し、多くの人にインスピレーションを与えています。さらにO'Reillyのインストラクターとして、ライブのオンライントレーニングも実施しています。