Kotaro7750's Gehirn
Home About
  • Home
  • Category
  • About

Synology DS1522+を買ったので宅鯖用に仮想化環境をIaCでセットアップする ~VM編~

2024-09-28

前回の記事では、Synology DS1522+をセットアップ・コンテナをAnsibleで起動できるようにしました。 これだけでも非常に便利ですが、ときにはコンテナだけではなくVMもあると便利です。

幸い、SynologyのNAS製品にはVirtual Machine Managerという仮想マシンを扱うためのアプリケーションを無料で導入することができます。 今回は、この機能を使ってSynology DS1522+に仮想マシンを立てていきます。 後述のように試した範囲では完全にIaCのようにはできませんでしたが、Packerを使ったコード管理されたイメージを利用しているためそれでお茶を濁しています。

TL; DR;

  • イメージのビルドをPackerで行うことによってUI上での手動ですがSynologyのNASでVMをデプロイすることができました。
  • デプロイもTerraformで行うこともできますが、その場合UI上で現れなくなります。

Virtual Machine Managerのインストール

前回の記事で既に基本的なセットアップは済んでいることは前提としています。

DSM(ブラウザ上で操作できる専用OS)の「パッケージセンター」アプリから、Virtual Machine Managerをインストールします。 インストール自体は簡単でウィザードに従っていくだけです。 VMMのインストール

Packerによるゴールデンイメージの作成

Virtual Machine Managerで作成したVMにOSをインストールし、その上で様々な設定投入を行うのも可能ですが、我が家の宅鯖ではイミュータブルインフラストラクチャを実践するようにしています。 具体的には、Packerを使ってAnsibleによって設定が投入されたイメージを作成し、そのイメージを旧イメージと入れ替えることで実現します。 詳しくは、以前記事に書いたため、そちらを読んでいただければと思います。

以降では、ビルド方式を問わず、cloud-initによる設定が可能なKVMイメージを利用することを前提とします。

半分IaCによるVMのデプロイ

半分IaCとは?

Synology Virtual Machine Managerでは、内部ではlibvirtを利用しています。 そのため、Terraformのlibvirt providerを利用してVMをデプロイすることが可能です。

$ systemctl status pkg-libvirtd.service
● pkg-libvirtd.service - libvirt daemon
   Loaded: loaded (/usr/local/lib/systemd/system/pkg-libvirtd.service; static; vendor preset: disabled)
   Active: active (running) since Sun 2024-07-28 14:37:47 KST; 2 months 9 days ago
 Main PID: 27114 (libvirtd)
   CGroup: /Virtualization.slice/pkg-libvirtd.service
           ├─20318 /usr/local/bin/qemu-system-x86_64 -name guest=d6ef89a3-a353-453a-957c-2a62ae24a1ef,debug-threads=on -S -object secret,id=masterKey0,format=raw,file=/var/lib/libvirt/qemu/domain-1-d6...
           └─27114 /var/packages/Virtualization/target/usr/local/bin/libvirtd -d --listen --config /etc/libvirt/libvirtd.conf --pid-file /var/run/libvirtd.pid

しかし、この方法によるVMのデプロイを試してみたのですが、Virtual Machine ManagerのUI上には現れませんでした。 おそらくですが、libvirtのさらに一つ上のレイヤにVirtual Machine Manager自体の状態を管理するレイヤがあり、UI上ではそこの情報を表示するようになっているようです。

いずれにしても、Terraformのlibvirt providerを使った方法だとUIの管理外となってしまうということです。 完全にTerraformで管理するのでUIはいらない、という割り切りもありだとは思いますが、私はUIでもみられるようにしたかったので、デプロイする部分は手動で行いつつも、可能な限りその範囲を狭めるようにしていきます。 なお、Terraformでデプロイしたいという方もいると思うので、Terraformでデプロイする方法をおまけセクションに書いています。

デプロイ方法

完全なIaCを行うことはやめましたが、それでもある程度はIaCを実践したいです。 そこで、デプロイの際に用いるcloud-initのISOイメージに関してはTerraformで作成していきます。 つまり、デプロイの流れとしては、

  1. Terraformでcloud-initのISOイメージを作成
  2. Virtual Machine ManagerのUIでPackerで作成したイメージとcloud-initのISOイメージを使ってVMを作成

というものになります。

Terraformによるcloud-init ISOイメージの作成

まずは、cloud-initのISOイメージをTerraformを用いて作成する部分ですが、以下のようにnull_resourceとlocal-execを用いて、Terraform CLIを実行したホスト上でコマンドを実行しています。 作成に用いているコマンドは、cloud-localdsというもので、userdataやnetworkconfigを指定することでそれらを含むISOイメージを作成してくれます。

resource "null_resource" "cloudinit-iso" {
  provisioner "local-exec" {
    command     = "cloud-localds cloudinit-iso-repository/cloudinit.iso <(echo \"$USERDATA\") -N <(echo \"$NETWORK_CONFIG\")"
    interpreter = ["/bin/bash", "-c"]
    environment = {
      USERDATA = templatefile("userdata.cfg.tftpl",
        {
          hostname        = "vm1",
          username        = "localadmin",
          password        = null,
          authorized_keys = [],
      })
      NETWORK_CONFIG = templatefile("network-config.tftpl",
        {
          ipaddress = "172.16.1.2/24",
      })
    }
  }

  provisioner "local-exec" {
    when    = destroy
    command = "rm cloudinit-iso-repository/cloudinit.iso"
  }
}

userdataやnetwork-configは適当に作成します。 ちなみにこのuserdataでは、パスワードを指定しないとパスワードなしのsudoが可能・指定するとそのパスワードでのsudoが可能というものになっています。 以前Hashicorp Vault SSH OTPを使ったワンタイムパスワードログインを実装した際のVMを作っているということです。

# userdata.cfg.tftpl

#cloud-config
hostname: ${hostname}
users:
  - name: ${username}
    %{ if password != null }passwd: ${password}
    lock_passwd: false%{ endif }
    sudo: %{ if password != null }"ALL=(ALL) ALL"%{ else }"ALL=(ALL) NOPASSWD:ALL"%{ endif }
    shell: /bin/bash
    %{ if authorized_keys != null }
    ssh_authorized_keys:
      %{ for authorized_key in authorized_keys ~}
      - "${authorized_key}"
      %{ endfor }
    %{ endif }

# network-config.tftpl

network:
  version: 2
  renderer: networkd
  ethernets:
    mainif:
      match:
        driver: "virt*"
      dhcp4: false
      dhcp6: true
      addresses:
      - ${ipaddress}
      routes:
      - to: default
        via: 172.16.1.254
      nameservers:
        addresses: [172.16.1.201, 172.16.1.200]

ISOイメージが作成される先をNASのNFS共有マウントとしておくことで、この後のVM作成をスムーズに行えます。

VMの作成

既存のイメージからVMを作成するにはインポートを行います。 VMのインポート1 VMのインポート2 VMのインポート3 VMのインポート4

ストレージの部分ではPackerで作成したイメージを指定します。 この方法で作成したVMでは、Packerイメージビルド時のディスクサイズから変えることができないため注意が必要です。 qemu-img resizeコマンドで変更することはできますが、可能なら作成時に変えられるようにしてほしいところです。 イメージの指定

そのまま作成ウィザードを進めていきます。 ネットワーク設定

追加のISOファイルとして、Terraformで作成したcloud-initのISOファイルを指定します。 cloud-init ISOの指定

このようにするとVMが作成されます。 電源を入れて接続してみると、Packerイメージが使われていることがわかります。(Packerイメージはkubernetesノードとして利用することを想定しているためkubeletが入っている) cloud-init ISOの指定

まとめ

自動化はcloud-initのISOのみではありますが、SynologyのNASにおいてもIaCによるVMのデプロイを実現することができました。 今のところ完全にIaCを綺麗に行う方法を見つけていませんが、Terraform Providerもドキュメント不足ですがあるみたいなので引き続き模索してみようと思います。

おまけ 〜完全IaC〜の模索

Virtual Machine Managerの内部ではlibvirtが動いているため、UI上で管理できなくなることを許容するならばTerraformのKVM providerを利用することで人力を介さない完全なIaCを実現することができます。

$ systemctl status pkg-libvirtd.service
● pkg-libvirtd.service - libvirt daemon
   Loaded: loaded (/usr/local/lib/systemd/system/pkg-libvirtd.service; static; vendor preset: disabled)
   Active: active (running) since Sat 2024-07-13 09:33:25 KST; 2 days ago
 Main PID: 8850 (libvirtd)
   CGroup: /Virtualization.slice/pkg-libvirtd.service
           └─8850 /var/packages/Virtualization/target/usr/local/bin/libvirtd -d --listen --config /etc/libvirt/libvirtd.conf --pid-file /var/run/libvirtd.pid

ただし、libvirtへの接続方式としてSSHを利用する方式だと、NASのOS内に必要なコマンドがないため接続することができません。

SSHでの接続拒否

そこでlibvirtの設定を変更することでSSH経由ではなくlibvirtに対して直接TCPで接続するようにします。 設定自体はlibvirt - ArchWikiを参考にしました。

libvirtの設定ファイルである/etc/libvirt/libvirtd.confを直接変更する形だと、なぜか再起動を跨ぐと設定が揮発してしまったため、適当な場所に設定ファイルを作成して、libvirtのユニットファイルにおいてその設定ファイルを読み込ませるような設定をします。

$ cat /usr/local/lib/systemd/system/pkg-libvirtd.service
[Unit]
Description=libvirt daemon
Requires=pkg-virtlogd.service
After=pkg-virtlogd.service
IgnoreOnIsolate=yes
DefaultDependencies=no

[Service]
KillMode=process
Restart=always
RestartSec=1
StartLimitBurst=5
StartLimitInterval=10
Type=forking
ExecStartPre=/bin/bash /var/packages/Virtualization/conf/systemd/insert_libvirtd_ko.sh
# この行の--configを/etc/libvirt/libvirtd.confから自分で用意したものに変える
ExecStart=/var/packages/Virtualization/target/usr/local/bin/libvirtd -d --listen --config /var/services/homes/localadmin/libvirtd.conf --pid-file /var/run/libvirtd.pid
ExecStopPost=/bin/bash /var/packages/Virtualization/conf/systemd/umount_qemu_mem.sh
PIDFile=/var/run/libvirtd.pid
Slice=Virtualization.slice
Delegate=yes

[X-Synology]

設定自体は簡単で、listenするアドレスを変更・認証の無効化をしているだけです。

$ sudo diff /var/services/home/localadmin/libvirtd.conf /etc/libvirt/libvirtd.conf
522,523c522
< #listen_addr = "127.0.0.1"
< listen_addr = "172.16.1.1"
---
> listen_addr = "127.0.0.1"
525,526c524
< #auth_tcp = "sasl"
< auth_tcp = "none"
---
> auth_tcp = "sasl"

Related Posts

スケーラブルなOpenTelemetry CollectorパイプラインをKubernetes上に構築する

スケーラブルなOpenTelemetry CollectorパイプラインをKubernetes上に構築する

2025-04-14

KorbでKubernetesの既存PVのStorage Classを変更する

KorbでKubernetesの既存PVのStorage Classを変更する

2024-12-15

Packerで実現するKVMでのイミュータブルインフラストラクチャ

Packerで実現するKVMでのイミュータブルインフラストラクチャ

2024-09-27

New Posts

スケーラブルなOpenTelemetry CollectorパイプラインをKubernetes上に構築する

スケーラブルなOpenTelemetry CollectorパイプラインをKubernetes上に構築する

2025-04-14

OpenTelemetry Certified Associate ( OTCA ) を取得した

OpenTelemetry Certified Associate ( OTCA ) を取得した

2025-04-13

Golangのnet/httpの実装からHTTP1.1クライアントでのTCPコネクションの挙動を確かめる

Golangのnet/httpの実装からHTTP1.1クライアントでのTCPコネクションの挙動を確かめる

2025-03-21

ToC

  • TL; DR;
  • Virtual Machine Managerのインストール
  • Packerによるゴールデンイメージの作成
  • 半分IaCによるVMのデプロイ
  • 半分IaCとは?
  • デプロイ方法
  • Terraformによるcloud-init ISOイメージの作成
  • VMの作成
  • まとめ
  • おまけ 〜完全IaC〜の模索

Ads

Ads

Privacy Policy