febc技術メモ

Japanese version of http://febc-yamamoto.hatenablog.com

続・さくらのクラウド上にMetabaseを構築する【HTTPS対応版】

前回はMetabase環境構築を行いました。

しかし、実運用の際はHTTPS対応は必須だと思いますので対応版を作りました。

Metabase環境構築 on さくらのクラウド(HTTPS版)

今回はLet's encryptにてHTTPS対応を行うバージョンとなっています。 Let's encrypt対応にはsteveltn/https-portalコンテナを利用します。

構築手順は前回とほぼ同じですが、あらかじめさくらのクラウド上にDNSゾーンの登録を行っておく必要があります。

テンプレート

前回との差分は以下の通りです。

  • コメントを追加
  • Let's encrypt用にDNS関連の記述を追加
  • RancherOSのcloud-configにLet's encrypt用のコンテナを記述
### 概要
#
# データベースアプライアンス(PostgreSQL)とRancherOSでMetabase実行環境を構築するテンプレート
#
# このテンプレートはRancherOS上のDockerでMetabaseを実行する構成となっています。
# Metabaseのバックエンドとしてデータベースアプライアンス(PostgreSQL)を利用します。
#
# MetabaseサーバのHTTPS対応としてLet's encryptでの証明書取得も行います。
#
# <事前準備>
#
# 1) さくらのクラウド上にSSH用の公開鍵を登録します。
# 2) さくらのクラウド上にDNSゾーンを登録しネームサーバの設定などを行っておきます。
#    (すでに登録済みのゾーンがあればそれを利用可能です。)
#
# <構築手順>
# 1) リソースマネージャーにて新しいテンプレートを作成し、このtffileの内容を貼り付けます。
# 2) tffile編集画面の"変数定義"タブにて以下の値を編集します。
#    - サーバ管理者のパスワード(server_password)
#    - データベース接続ユーザーのパスワード(database_password)
#    - さくらのクラウドに登録済みの公開鍵の名称(ssh_public_key_name)
#    - さくらのクラウドに登録済みのDNSゾーン名(dns_zone_name)
# 3) リソースマネージャー画面にて"計画/反映"を実行
#
# <動作確認>
#
# ブラウザから以下のURLにアクセスするとMetabaseの画面が開きます。
#    https://<MetabaseサーバのFQDN>/
#
# MetabaseサーバのFQDNは以下の形式です。
#    ${server_name}.${dns_zone_name}
#
# FQDNの例:
#    - server_name: "metabase"
#    - dns_zone_name: "example.com"
# この場合FQDNは以下のようになります。
#    FQDN: metabase.example.com
#
# <サーバへのSSH接続>
#
# サーバへのSSH接続は、指定した公開鍵による公開鍵認証のみ許可されるようになっています。
# SSH接続の際は秘密鍵を指定して接続してください。
#
# > usacloudでのSSH接続例
# $ usacloud server ssh -i <your-private-key-file> <your-server-name>
#
# SSH接続後はdocker logsコマンドなどでMetabaseコンテナのログを確認可能です。
#
### 変数定義
locals {
  #*********************************************
  # パスワード/公開鍵関連(要変更)
  #*********************************************
  # サーバ管理者のパスワード
  server_password = "<put-your-password-here>"
  
  # データベース接続ユーザーのパスワード
  database_password = "<put-your-password-here>"
 
  # さくらのクラウドに登録済みの公開鍵の名称
  ssh_public_key_name = "<put-your-public-key-name>"

  # さくらのクラウドに登録済みのDNSゾーン名
  dns_zone_name = "<put-your-zone-name>"

  #*********************************************
  # サーバ/ディスク
  #*********************************************
  # サーバ名
  server_name = "metabase"

  # サーバホスト名
  host_name = "${local.server_name}"

  # サーバ コア数
  server_core = 2

  # サーバ メモリサイズ(GB)
  server_memory = 4

  # ディスクサイズ
  disk_size = 20

  #*********************************************
  # ネットワーク(スイッチ/パケットフィルタ)
  #*********************************************
  # スイッチ名
  switch_name = "metabase-internal"

  # パケットフィルタ名
  packet_filter_name = "metabase-filter"

  #*********************************************
  # データベースアプライアンス
  #*********************************************
  # データベースアプライアンス名
  database_name = "metabase-db"

  # プラン
  database_plan = "30g" # 10g/30g/90g/240g

  # 接続ユーザー名
  database_user_name = "metabase"

  # バックアップ時刻
  database_backup_time = "01:00"
}

### サーバ/ディスク

# パブリックアーカイブ(OS)のID参照用のデータソース(RancherOS)
data sakuracloud_archive "rancheros" {
  os_type = "rancheros"
}

# 公開鍵のID参照用のデータソース
data "sakuracloud_ssh_key" "ssh_public_key" {
  name_selectors = ["${local.ssh_public_key_name}"]
}

# ディスク
resource "sakuracloud_disk" "disk" {
  name              = "${local.server_name}"
  source_archive_id = "${data.sakuracloud_archive.rancheros.id}"
  hostname          = "${local.host_name}"
  password          = "${local.server_password}"
  note_ids          = ["${sakuracloud_note.provisioning.id}"]
  ssh_key_ids       = ["${data.sakuracloud_ssh_key.ssh_public_key.id}"]
  disable_pw_auth   = true

  lifecycle {
    ignore_changes = ["source_archive_id"]
  }
}

# サーバ
resource "sakuracloud_server" "server" {
  name              = "${local.server_name}"
  disks             = ["${sakuracloud_disk.disk.id}"]
  core              = "${local.server_core}"
  memory            = "${local.server_memory}"
  packet_filter_ids = ["${sakuracloud_packet_filter.filter.id}"]
  additional_nics   = ["${sakuracloud_switch.sw.id}"]
}

# スタートアップスクリプト(IP設定、metabaseコンテナ起動)
locals {
  fqdn = "${local.server_name}.${local.dns_zone_name}"
}

resource "sakuracloud_note" "provisioning" {
  name  = "provisioning-metabase"
  class = "yaml_cloud_config"

  content = <<EOF
#cloud-config
rancher:
  console: default
  docker:
    engine: docker-17.09.1-ce
  network:
    interfaces:
      eth1:
        address: 192.168.100.10/28
        dhcp: false
  services:
    https-portal:
      image: sacloud/https-portal
      ports:
        - "80:80"
        - "443:443"
      volumes:
        - https-portal:/var/lib/https-portal
      environment:
        DOMAINS: "${local.fqdn} -> http://192.168.100.10:3000"
        STAGE: production
      restart: always
    metabase:
      image: metabase/metabase:latest
      ports:
        - "3000:3000"
      environment:
        MB_DB_TYPE: postgres
        MB_DB_DBNAME: ${local.database_user_name}
        MB_DB_PORT: 5432
        MB_DB_USER: ${local.database_user_name}
        MB_DB_PASS: ${local.database_password}
        MB_DB_HOST: 192.168.100.2
      restart: always
EOF
}

### データベースアプライアンス
resource "sakuracloud_database" "db" {
  name = "${local.database_name}"

  database_type = "postgresql"
  plan          = "${local.database_plan}"

  user_name     = "${local.database_user_name}"
  user_password = "${local.database_password}"

  allow_networks = ["192.168.100.0/28"]
  port           = 5432
  backup_time    = "${local.database_backup_time}"

  switch_id     = "${sakuracloud_switch.sw.id}"
  ipaddress1    = "192.168.100.2"
  nw_mask_len   = 28
  default_route = "192.168.100.1"
}

### パケットフィルタ
resource "sakuracloud_packet_filter" "filter" {
  name = "${local.packet_filter_name}"

  expressions = {
    protocol    = "tcp"
    dest_port   = "22"
    description = "Allow external:SSH"
  }

  expressions = {
    protocol    = "tcp"
    dest_port   = "80"
    description = "Allow external:HTTP(for Let's encrypt)"
  }

  expressions = {
    protocol    = "tcp"
    dest_port   = "443"
    description = "Allow external:HTTPS"
  }

  expressions = {
    protocol = "icmp"
  }

  expressions = {
    protocol = "fragment"
  }

  expressions = {
    protocol    = "udp"
    source_port = "123"
  }

  expressions = {
    protocol    = "tcp"
    dest_port   = "32768-61000"
    description = "Allow from server"
  }

  expressions = {
    protocol    = "udp"
    dest_port   = "32768-61000"
    description = "Allow from server"
  }

  expressions = {
    protocol    = "ip"
    allow       = false
    description = "Deny ALL"
  }
}

### スイッチ
resource sakuracloud_switch "sw" {
  name = "${local.switch_name}"
}

### DNS

data sakuracloud_dns "zone" {
  filter = {
    name   = "Name"
    values = ["${local.dns_zone_name}"]
  }
}

#DNSレコード
resource sakuracloud_dns_record "records" {
  dns_id = "${data.sakuracloud_dns.zone.id}"
  name   = "${local.server_name}"
  type   = "A"
  value  = "${sakuracloud_server.server.ipaddress}"
}

後はリソースマネージャーで展開するだけでOKです。

以上です。