Open4

さくらのクラウド上にTerraformでMisskeyサーバーを立てる

defaultcfdefaultcf

あらすじ

  • AWS 上で Misskey サーバーを展開しているが、円安の影響が大きいため、国内クラウドに移りたい
  • さくらのクラウドを選んだ理由
    • 公式で Terraform provider が提供されている
  • 懸念点
    • マネージドなコンテナのオーケストレーション機能が無い(Amazon ECS みたいなものを使いたい)
    • k8s を使用した場合、ノードのオートスケールを上手く組めるか
defaultcfdefaultcf

Terraform でリソースを作成してみる

Terraform からさくらのクラウドを操作するため、API キーを作成する。API キーのページからアカウントを選択し、「追加」をクリックする。
https://secure.sakura.ad.jp/cloud/?#!/apikey/top/
アクセスレベルは「作成・削除」とする。
API 作成画面

「アクセストークン」と「アクセストークンシークレット」が得られるので、次のようにファイルに書き込む。

$HOME/.usacloud/default/config.json
{
    "AccessToken": "my-access-token",
    "AccessTokenSecret": "my-access-secret",
    "Zone": "is1a"
}

まず最初のリソースを作成してみる。

server.tf
resource "sakuracloud_server" "app" {
  name        = "app"
  description = "app"
  tags        = ["misskey", "app"]

  disks = [sakuracloud_disk.app.id]

  network_interface {
    upstream         = "shared"
    packet_filter_id = sakuracloud_packet_filter.app.id
  }

  disk_edit_parameter {
    disable_pw_auth = true
  }
}

resource "sakuracloud_packet_filter" "app" {
  name        = "app"
  description = "app"

  expression {
    protocol         = "tcp"
    destination_port = "22"
  }

  expression {
    protocol         = "tcp"
    destination_port = "80"
  }

  # どのルールにもマッチしない場合 allow になってしまうため
  expression {
    protocol    = "ip"
    allow       = false
    description = "Deny ALL"
  }
}

data "sakuracloud_archive" "ubuntu" {
  os_type = "ubuntu2204"
}

resource "sakuracloud_disk" "app" {
  name              = "app-${count.index + 1}"
  source_archive_id = data.sakuracloud_archive.ubuntu.id
}

コンソールからログインできるか確認する。ユーザー名は ubuntu、パスワードは無しでログインできる。
https://manual.sakura.ad.jp/cloud/server/os-packages/archive-iso/ubuntu22044-releasenote.html#id2

これでサーバーからはインターネットに接続できて、インターネットからは22,80番ポートだけ開いているサーバーが出来上がる。(昨今のインターネット的には22番は変えるべきだし、ウェブサーバーとしては前段に Cloudflare など CDN を挟んで IP アドレスで制限するべきだが、今は playground ということで良しとする)

defaultcfdefaultcf

ネットワークについて考える

先の例では、ネットワークインターフェースを shared に設定したが、これだとサーバーは常にパブリックなインターネットに繋がってしまいセキュリティ的に不安がある。これから DB サーバーなどインターネットに直接は繋がらないサーバーも作りたい。
AWS ではプライベートサブネットを用意することで実現したが、さくらのクラウドではどう作れば良いか考える。

さくらのクラウドでは、「スイッチ」と「ルータ+スイッチ」で構成する必要がある。
https://manual.sakura.ad.jp/cloud/network/switch/about.html
スイッチはインターネットから直接接続できない位置にあり、ローカルの機器同士をL2で接続するために使用する。月額2,200円。
「ルータ+スイッチ」はインターネットと直接接続し、L3でスイッチングできる。プレフィクスにより金額が変わり、月額7,920円から。

ということで、ひとまず先ほどのマシンをスイッチに繋いでみる。

server.tf
variable "app_count" {
  default = 2
}

resource "sakuracloud_switch" "main" {
  name        = "main"
  tags        = ["misskey"]
}

resource "sakuracloud_server" "app" {
  count       = var.app_count
  name        = "app-${count.index + 1}"
  tags        = ["misskey", "app"]

  disks = [sakuracloud_disk.app[count.index].id]

  network_interface {
    upstream        = sakuracloud_switch.main.id
    user_ip_address = "192.168.1.${count.index + 1}"
  }

  disk_edit_parameter {
    hostname        = "app-${count.index + 1}"
    disable_pw_auth = true
    ip_address      = "192.168.1.${count.index + 1}"
    netmask         = 24
    gateway         = "192.168.1.254"
  }
}

data "sakuracloud_archive" "ubuntu" {
  os_type = "ubuntu2204"
}

resource "sakuracloud_disk" "app" {
  count             = var.app_count
  name              = "app-${count.index + 1}"
  source_archive_id = data.sakuracloud_archive.ubuntu.id
}

ただし、サーバーはスイッチだけに繋ぐとサーバーからインターネットへの通信ができない。

ローカルIPアドレスのみを持つサーバーがインターネット通信を行うためには、別途VPCルータが必要になります。
https://manual.sakura.ad.jp/cloud/network/switch/about.html

ということで VPC ルーターを追加する。

vpc_router.tf
resource "sakuracloud_vpc_router" "main" {
  name                = "main"
  tags                = ["misskey"]
  internet_connection = true
  plan                = "standard"

  private_network_interface {
    index        = 1
    ip_addresses = ["192.168.1.254"]
    netmask      = "24"
    switch_id    = sakuracloud_switch.main.id
  }
}

これで先ほど作ったサーバー同士が通信できることを確認する。
サーバー app-1 でリッスンする。

app-1
nc -l -p 3000

サーバー app-2 から app-1 に接続し、試しに hello と打って Enter を押す。

app-2
nc 192.168.1.1 3000
hello

するとサーバー app-1 の方で hello と出力される。また apt update などを実行して、VPC ルーターを介してインターネットとも通信できることを確認する。

defaultcfdefaultcf

k8s クラスタ作成

# net.ipv4.ip_forward = 0 になっていることを確認
sysctl net.ipv4.ip_forward

cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.ipv4.ip_forward = 1
EOF
sudo sysctl --system

# sysctl net.ipv4.ip_forward = 1 に変更されたことを確認
sysctl net.ipv4.ip_forward