さくらのクラウド上にTerraformでMisskeyサーバーを立てる
あらすじ
- AWS 上で Misskey サーバーを展開しているが、円安の影響が大きいため、国内クラウドに移りたい
- さくらのクラウドを選んだ理由
- 公式で Terraform provider が提供されている
- 懸念点
- マネージドなコンテナのオーケストレーション機能が無い(Amazon ECS みたいなものを使いたい)
- k8s を使用した場合、ノードのオートスケールを上手く組めるか
Terraform でリソースを作成してみる
Terraform からさくらのクラウドを操作するため、API キーを作成する。API キーのページからアカウントを選択し、「追加」をクリックする。
「アクセストークン」と「アクセストークンシークレット」が得られるので、次のようにファイルに書き込む。
{
"AccessToken": "my-access-token",
"AccessTokenSecret": "my-access-secret",
"Zone": "is1a"
}
まず最初のリソースを作成してみる。
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、パスワードは無しでログインできる。
これでサーバーからはインターネットに接続できて、インターネットからは22,80番ポートだけ開いているサーバーが出来上がる。(昨今のインターネット的には22番は変えるべきだし、ウェブサーバーとしては前段に Cloudflare など CDN を挟んで IP アドレスで制限するべきだが、今は playground ということで良しとする)
ネットワークについて考える
先の例では、ネットワークインターフェースを shared
に設定したが、これだとサーバーは常にパブリックなインターネットに繋がってしまいセキュリティ的に不安がある。これから DB サーバーなどインターネットに直接は繋がらないサーバーも作りたい。
AWS ではプライベートサブネットを用意することで実現したが、さくらのクラウドではどう作れば良いか考える。
さくらのクラウドでは、「スイッチ」と「ルータ+スイッチ」で構成する必要がある。
「ルータ+スイッチ」はインターネットと直接接続し、L3でスイッチングできる。プレフィクスにより金額が変わり、月額7,920円から。
ということで、ひとまず先ほどのマシンをスイッチに繋いでみる。
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 ルーターを追加する。
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 でリッスンする。
nc -l -p 3000
サーバー app-2 から app-1 に接続し、試しに hello と打って Enter を押す。
nc 192.168.1.1 3000
hello
するとサーバー app-1 の方で hello と出力される。また apt update
などを実行して、VPC ルーターを介してインターネットとも通信できることを確認する。
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