Agile育成ブログ
未来を変える喜びを
未分類

📘 改訂版:SnowflakeとTerraformによるインフラストラクチャ・アズ・コード(IaC)実践ガイド

◉ 本書の目的

ユーザー、ロール、データベース、スキーマをはじめとするSnowflakeのリソースを Terraformで管理するための方法を紹介します。

IaC (Infrastructure as Code) ツールである Terraform を利用することで、リソース管理における「視認性」「再利用性」「監査可能性」が飛躍的に向上します。Snowflakeコンソールでの手動 SQL 実行と異なり、リソースの定義をコードとして一元管理し、Git(GitHubなど)で変更履歴をバージョン管理できる点に大きなメリットがあります。特に複数のプロジェクトで横断的に開発する現場では、既存コードの使い回しによる圧倒的な開発効率の向上が期待できます。

◉ 対象とする読者

本書は、Snowflakeをデータプラットフォームとして利用している「データエンジニア」や「ソフトウェアエンジニア」を読者の対象としています。

  • 「データウェアハウスとしての Snowflake の利点は理解しているが、構成の管理方法がわからない」
  • 「データウェアハウスの変更を管理するための CI/CD の設定方法で悩んでいる」

といった課題を持つ方が、現代のデータ開発におけるベストプラクティスを参考にできる内容を執筆しています。本書を読み進める上で、Snowflakeの基礎的な知識があるとより深い理解に繋がります。

◉ 取り扱う内容

本書で扱う主な内容は以下の通りです。

  • Terraform × Snowflake
  • GitHub Actions を用いた CI/CD
  • Schema Migration Tool (Flyway, Liquibaseなど)

本書のタイトルの通り、Snowflakeのリソース管理は Terraform で実行します。実際の現場のようなチーム開発を前提として、Terraform の実行には GitHub Actions を使用し、IaC のデプロイメントを一箇所で管理します。

また、Snowflakeのテーブル定義やスキーマ構造の変更(マイグレーション)には、もはや主流となった dbt (Data Build Tool) や、専門のスキーママイグレーションツール(Flyway, Liquibaseなど)の活用に焦点を当てます。

本書に掲載する情報をもとに、「Snowflake × Terraform」を使った、堅牢で効率的な開発にぜひ取り組んでみてください。

🚀 技術解説のアップデート

◉ Snowflakeとは(最新の視点)

Snowflakeとは、一言にすればクラウド型のデータウェアハウス(DWH)です。従来の DWH との最大の違いは、ストレージ(データリソース)コンピュート(処理リソース)が完全に分離し、独立してスケーリングできる点にあります。

  • 特徴的なアーキテクチャ: 「マルチクラスター、共有データ」をキーワードとし、データは一箇所(クラウドストレージ)に保存され、処理は複数の独立した仮想ウェアハウス(クラスター)によって超高速で並列実行されます。
  • コスト効率と柔軟性: コンピュートリソースを使わないアイドル時には課金が発生しないため、コスト効率に優れています。
  • データクラウドへの進化: 現在、Snowflakeは DWH という枠を超え、データ共有(Data Sharing)、外部データへのアクセス(External Tables)、そしてアプリケーション開発(Streamlit/Snowflake Native Apps)を可能にするデータクラウドへと進化しています。Zero Copy CloneTime Travel はその核となる機能です。

◉ Terraformとは

Terraform は、Infrastructure as Code (IaC) の代表的なツールであり、AWS, Azure などのクラウドサービス上のインフラリソースをコードとして定義・構築まで行うことができます。

  • メリット: コンソール画面での手動操作よりも、素早く、ミスがなく再現性高く構築が可能です。
  • 対応プロバイダー: AWS、Azure などの各種クラウドプロバイダーに加え、本書で対象とする Snowflake のリソース(データベース、ユーザー、ロールなど)も、Snowflake Provider を使ってコードとして管理できます。

🛠️ インストールと基本コマンド

◉ Installの方法(Homebrew)

MacOS の Homebrew を使った Terraform のインストール方法を紹介します。

$ brew tap hashicorp/tap
$ brew install hashicorp/tap/terraform

◉ Installの確認

インストールが完了したら、terraform -help コマンドで確認してください。

$ terraform -help
Usage: terraform [global options] <subcommand> [args]
# ... 省略 ...

◉ 基本コマンド(変更なし)

最低限覚えておくべき基本コマンドは以下の通りです。

コマンド役割
initワーキングディレクトリの初期準備、プロバイダーのインストール。
validate構成ファイルの構文および基本設定の妥当性チェック。
plan構成の実行計画(追加・更新・削除)の確認。実際のリソースには反映されない。
apply実行計画に基づき、実際のリソースの追加・更新・削除を実行。
destroy作成したインフラの削除。実行時には最大限の注意が必要。
fmtコードのフォーマットを整形し、一貫性を保つ。

📐 リソース定義の例(変更なし)

Terraform では、.tf 拡張子を持つファイルにリソース定義を記載します。オブジェクトリソースの定義と、それに対するアクセス権限を付与するための grant が基本となります。

ユーザー、ロール、ロール階層の作成例は以下の通りです。

resource "snowflake_user" "user1" {
  name    = "user1"
  comment = "example user"
}

resource "snowflake_role" "parent" {
  name    = "parent_role"
  comment = "example role"
}

resource "snowflake_role" "child" {
  name    = "child_role"
  comment = "example role"
}

resource "snowflake_role_grants" "grants" {
  role_name = snowflake_role.child.name

  # childロールにparentロールを付与し、ロールの階層関係を構築
  roles = [
    snowflake_role.parent.name,
  ]
  
  # user1にchildロールを付与
  users = [
    snowflake_user.user1.name
  ]
}

◉Snowflake トライアルアカウントの作成

以下のリンクからSnowflakeのトライアルアカウントの作成を行いましょう。すでにSnowflakeを登録済みで利用可能な方はスキップしてください。

◉Snowflakeへのログインを完了する

アカウントが作成できて、以下の画像のようにSnowflakeの画面にログインできれば準備完了です。

◉Snowflakeの準備

SnowflakeでTerraform用に使用するユーザーとロールとウェアハウスの準備をします。

🛠️ 改訂版:Snowflake IaC環境構築とCI/CD実践ガイド

◉ Snowflakeの準備(最新のセキュリティと推奨事項)

Terraform で使用するユーザー、ロール、およびウェアハウスの準備に関する SQL を更新し、パスワード認証ではなく、よりセキュアなキーペア認証の導入を推奨します。

-- 1. 専用ロールの作成 (最小権限の原則に基づき、必要な権限のみを付与)
CREATE ROLE IF NOT EXISTS TERRAFORM_CI_ROLE COMMENT = 'Role for Terraform CI/CD automation.';

-- 2. サービスアカウントユーザーの作成 (キーペア認証を推奨)
-- パスワード認証を使用する場合の例(セキュリティリスクが高いため非推奨)
CREATE USER IF NOT EXISTS TERRAFORM_CI_USER
    PASSWORD = 'TemporaryPassword123!' -- セキュリティのため、必ず複雑なパスワードに変更
    DEFAULT_ROLE = TERRAFORM_CI_ROLE
    DEFAULT_WAREHOUSE = TERRAFORM_WH
    MUST_CHANGE_PASSWORD = TRUE;

-- 3. 必要な管理権限の付与 (最小権限の原則に基づき、SECURITYADMINとSYSADMINの直接付与は非推奨)
-- ユーザーやロール管理には USERADMIN または SECURITYADMIN のみが望ましい
GRANT ROLE USERADMIN TO ROLE TERRAFORM_CI_ROLE;
GRANT ROLE SYSADMIN TO ROLE TERRAFORM_CI_ROLE; -- リソース作成のために一時的にSYSADMINを付与

-- 4. ウェアハウスの作成と設定(最新の推奨設定)
CREATE OR REPLACE WAREHOUSE TERRAFORM_WH 
    WAREHOUSE_SIZE = XSMALL
    AUTO_RESUME = TRUE
    AUTO_SUSPEND = 300 -- 5分間(コスト削減のため短めに設定)
    INITIALLY_SUSPENDED = TRUE
    STATEMENT_TIMEOUT_IN_SECONDS = 3600 -- 60分
    COMMENT = 'For Terraform CI/CD operations.';

-- 5. 権限付与
-- 作成したCI/CD用ロールにウェアハウスの使用権限を付与
GRANT USAGE ON WAREHOUSE TERRAFORM_WH TO ROLE TERRAFORM_CI_ROLE;

-- 補足: 複数のロールに同じウェアハウス権限を付与する際は、個別にGRANTを実行します。
GRANT USAGE ON WAREHOUSE TERRAFORM_WH TO ROLE SECURITYADMIN;

◉ 環境変数の準備(セキュリティ強化)

Terraform の実行環境変数を、よりセキュアな方式に更新します。パスワード認証は非推奨とし、シークレット(秘密情報)は GitHub Actions の Secrets を通じてのみ渡すようにします。

環境変数,目的,旧設定の注意点,最新の推奨
SNOWFLAKE_ACCOUNT,アカウントロケーター,変更なし,変更なし
SNOWFLAKE_USER,ユーザー名,変更なし,変更なし
SNOWFLAKE_PASSWORD,パスワード,環境変数ではなくGitHub Secretsでのみ設定。非推奨。,使用しない (SNOWFLAKE_PRIVATE_KEYに置き換えを推奨)
SNOWFLAKE_ROLE,使用ロール,変更なし,変更なし
SNOWFLAKE_WAREHOUSE,使用ウェアハウス,変更なし,変更なし

キーペア認証を導入する場合: SNOWFLAKE_PASSWORD の代わりに、秘密鍵を GitHub Secrets に格納し、SNOWFLAKE_PRIVATE_KEY または SNOWFLAKE_PRIVATE_KEY_PATH を使用します。

◉ GitHub ActionsでTerraformを実行(ワークフロー構成の現代化)

1. AWSでTerraformのステートを管理する

S3をバックエンドとし、DynamoDBでステートロックを行う方針はベストプラクティスとして引き続き有効です。

  • Terraform バージョンの更新: ~> 1.3.0 から 最新安定版 (~> 1.6.0 以上) に更新を推奨します。

provider.tf の更新例:

terraform {
  required_version = "~> 1.6.0" # 最新安定版に更新

  backend "s3" {
    bucket         = "terraform-state-mnagaa"
    region         = "ap-northeast-1"
    key            = "common-github.tfstate"
    dynamodb_table = "mnagaa-terraform-state-lock"
    # OIDCを使用する場合、profileやaccess keyの記載は不要になる
  }
  
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0" # 最新のメジャーバージョンに更新
    }
    # Snowflake Providerのソースを明記
    snowflake = {
      source  = "Snowflake-Labs/snowflake"
      version = "~> 0.89.0" # 最新安定版に更新
    }
  }
}

provider "aws" {
  region = "ap-northeast-1"
  # OIDCを使うため、クレデンシャル設定はGitHub Actions側で行う
  default_tags {
    tags = {
      env     = var.environment
      project = var.project
      owner   = "terraform"
      tfstate = "common-github"
    }
  }
}

2. OIDCを使ったAWSとGitHub Actionsの連携(最新のベストプラクティス)

OIDC(OpenID Connect)を使った AWS との連携は、最もセキュアで推奨される方法です。GitHub Actions での OIDC 設定は、Terraform で管理することがベストプラクティスです。

aws_iam_openid_connect_provider

3. Terraform Planを実行するワークフロー (tf-plan.yml の現代化)

GitHub Actions の構文とセキュリティを強化し、最新の setup-terraform アクションを使用します。

  • uses: actions/checkout@v3@v4 以上へ更新
  • aws-actions/configure-aws-credentials@master@v4 以上へ更新
  • 環境変数ではなく with ブロックでの Terraform バージョン指定を優先。
  • defaults: run:working-directory はステップごとに行う方が柔軟。

tf-plan.yml の主要な変更点:

# ... (on: pull_request: 部分は変更なし)
env:
  # ... (AWS/Terraform/Snowflakeの環境変数は Secretsから読み込む)
  # TF_VERSION: "1.3.0" # setup-terraformのwithで指定することを推奨

jobs:
  plan-common:
    runs-on: ubuntu-latest # 最新のUbuntuランナーを使用
    # ... (permissionsは変更なし)
    strategy:
      matrix:
        path:
          - common-snowflake
    
    defaults:
      run:
        working-directory: ./terraform/project/${{ matrix.path }} # working-directoryをmatrixに合わせる

    steps:
      - uses: actions/checkout@v4 # アクションを最新版に更新

      - uses: aws-actions/configure-aws-credentials@v4 # アクションを最新版に更新
        with:
          role-to-assume: arn:aws:iam::${{ env.AWS_ACCOUNT_ID }}:role/mnagaa-github-actions-ro-role
          aws-region: ${{ env.AWS_REGION }}

      - uses: hashicorp/setup-terraform@v3 # アクションを最新版に更新
        with:
          terraform_version: 1.6.0 # TF_VERSIONではなくwithで直接指定 (推奨)

      - name: Check format
        run: terraform fmt -check -recursive

      # -chdir=${{ matrix.path }} は defaults:run: で設定済みのため不要
      - name: Init
        run: terraform init -upgrade -no-color

      - name: Check validate
        run: terraform validate

      - name: Plan
        run: terraform plan -no-color -input=false

4. Terraform Applyを実行するワークフロー (tf-apply-common.yml の現代化)

tf-apply-common.yml は、workflow_dispatch で手動実行するための優れた方法です。

  • refresh_only の代替: Terraform の新しいバージョンでは、plan コマンドが自動でリフレッシュを行うため、専用の refresh_only オプションは不要になりました。ここでは、旧バージョンとの互換性のために残されていた refresh_only ステップを最新のベストプラクティスに近づけるために削除するか、plan のみを行うオプションとして残すことを推奨します。

tf-apply-common.yml の主要な変更点:

# ... (on: workflow_dispatch: inputs: 部分は変更なし)

jobs:
  apply-common:
    # ... (runs-on, permissions, defaults:run: は plan と同様に更新)
    steps:
      - uses: actions/checkout@v4

      - uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::${{ env.AWS_ACCOUNT_ID }}:role/mnagaa-github-actions-rw-role # Write権限のロールを使用
          aws-region: ${{ env.AWS_REGION }}

      - uses: hashicorp/setup-terraform@v3
        with:
          terraform_version: 1.6.0 # 最新版を指定

      - name: Init
        run: terraform init -upgrade -no-color

      - name: Apply
        # refresh_only のカスタムインプットを利用して、apply を実行するかを制御
        if: ${{ github.event.inputs.refresh_only == 'false' }} 
        run: terraform apply -no-color -auto-approve
        
      - name: Plan (Refresh Onlyとして実行する場合)
        # refresh_only が true の場合は、plan の実行に留める
        if: ${{ github.event.inputs.refresh_only == 'true' }} 
        run: terraform plan -no-color -input=false