ミニPCにIncusOSをインストールして、Tailscale経由で接続可能なTalos Linuxによるk8sクラスタを構築

に公開

構成

不変(immutable)をテーマに、Kubernetesクラスタを構築します。

不変(immutable)

Immutable OSというLinuxディストリビューションが増えてきています。
何が不変かというと、ログなど書き込みが必要な一部のディレクトリ以外は、全て読み取り専用になっていることを指します。
OSやアプリケーションの動作に必要なファイルの上書きができないため、ファイルを書き換えたれたり、マルウェアをインストールされたりなどのサイバー攻撃への耐性があります。

今回紹介するIncusOSとTalos Linuxのように、特定のアプリケーションを動作させるためだけのImmutable OSも存在します。
その場合、sshやシェルすら入っていない、まるでdistrolessのコンテナのようなセキュアな環境です。

IncusOS

https://linuxcontainers.org/ja/incus-os/introduction/

Incusは、VMとコンテナを実行可能な仮想環境ツールです。
LXC / LXD / Linux Containersと言う名前の方がまだ有名かもしれません、それらのforkです。

IncusOSは、そのIncusを実行するためだけのOSです。
OSが起動すると、Incusのみが起動します。
前述の通りImmutable OSで、VMからの権限昇格などでホストマシンの権限を奪われるリスクが大幅に削減されています。

また、アップデートも自動でダウンロードされ、設定すれば反映(再起動)も自動化可能です。
https://linuxcontainers.org/incus-os/docs/main/reference/system/update/

Incusはクラスタリング機能もあるため、適切に設定すればサービスの無停止と自動更新を両立可能です。
筆者はまだクラスタリング機能は試していなく、自動再起動も有効にはしていません。

Secure Bootにも対応、というよりデフォルトではSecure Bootでないと起動しません。

Talos Linux

https://docs.siderolabs.com/talos/v1.12/overview/what-is-talos

Linuxディストリビューションであると同時に、Kubernetesのディストリビューションでもあります。
Kubernetesのnodeとして稼働するためだけのOSです。
起動後はシェルもsshもないですが、50000番のポートが開いているため、ネットワーク経由で別の端末から設定します。
専用のコマンドtalosctlは、PC上で開発用のk8sクラスタを構築して動作確認をすることも可能です。
詳しい使い方は、ドキュメントとチュートリアルをご覧ください。
https://docs.siderolabs.com/talos/v1.12/getting-started/quickstart

Talos LinuxをIncus上で動作させるメリットはいくつかありますが、今回はWi-Fi経由で接続させるためというのが最大の理由でした。
Talos LinuxはWi-Fiに対応していなく、Bare Metalにインストールしようとすると物理的にLANケーブルで接続する必要があります。
IncusなどVM上であれば、VMのネットワーク設定で管理できるため、Wi-FI経由でもTalos Linuxを動作させることができます。

Tailscale

WireGuardベースのVPNサービスです。
外向き通信だけでVPNを構築でき、自宅サーバへ外出先から接続するのに便利です。

IncusOSはTailscaleとの統合機能が組み込まれていて、Incus内のネットワークへTailscale経由で接続可能です。
IncusOS上に構築されているネットワークは、明示的に設定しなければLAN内からは直接接続できません。
Tailscale経由にすることで、Tailscaleでの権限がなければLAN内でもアクセスできないという、簡易ゼロトラスト構成にしています。

手順

細かい手順は、公式ドキュメントへのリンクを貼りますので、最新の手順はそちらを参照ください。

1. IncusOSのISOイメージをダウンロード

手順4までは、こちらのページに詳しく載っています。
https://linuxcontainers.org/incus-os/docs/main/getting-started/installation/physical/

IncusOSは、ISOイメージにいくつかの設定を行う必要があります。
IncusOS image downloaderを使用すると、それらをGUIで行うことができます。
https://incusos-customizer.linuxcontainers.org/ui/

注意が必要な設定は、必須となっているクライアント証明書です。
手元で作成しても良いですが、generatedと言うリンクをクリックすると、ブラウザでクライアント証明書を生成可能です。
このリンクをクリックすると生成できると言うのに気づかず時間を取られました・・・。
生成された証明書は、起動後のIncusOSと認証するのに必要なため、ダウンロード後は所定のパスへ移動してください。
CLIとWEB UIがありますが、どちらもクライアント証明書で認証します。

WEB UI用には、PCのOSもしくはブラウザへ証明書をインストールしてください。
Macの場合は、client.crtをダブルクリックして、キーチェーンから証明書を信頼すればOKです。

Incus CLI向けには、~/.config/incus/ディレクトリへファイルを移動してください。

mv client.crt ~/.config/incus/client.crt
mv client.key ~/.config/incus/client.key

2. IncusOSのISOイメージをUSBメモリへ書き込む

ISOイメージの書き込み方法は、筆者はBalena Etcherを使用しました。
普段使用している書き込み方法がない方は、使い方が簡単なのでおすすめです。

3. BIOSからSecure BootをSetup Modeにする

IncusOSはほぼSecure Boot前提です。
使わない方法もあるみたいですが、筆者はうまくいきませんでした。
筆者はSecure Bootに詳しくありませんので、簡単に説明します。
なお、この手順の説明は、対象の端末のOSを完全に消去する前提です。
今のOSを残す必要がある場合は、この手順は実施しないでください

  1. BIOSを起動する
    起動方法は端末により異なりますが、F2、F10、DELETEキーあたりが多いと思います。
  2. Secure Bootの項目で、Setup Modeにする
    これも端末により異なりますが、Securityという項目にあることが多いと思います。
    Setup Modeにすることで、これからインストールするOS = IncusOSが鍵を設定できるようになります。
  3. BIOSの設定を保存する
    保存を忘れることがよくあります。
    ファンクションキーのどれかを押すと保存(Save)できる旨が、画面内のどこかに書いてあると思いますので、それに従ってください。

4. IncusOSのISOイメージを書き込んだUSBメモリを端末に挿し、起動する

基本的にはインストールは自動で進み、完了すると再起動するよう促されます。
もしインストール画面に進まない場合は、Secure Bootの設定が間違っている可能性があります。

5. 再起動後、画面に表示されているIPアドレスを確認し、接続する

https://linuxcontainers.org/incus-os/docs/main/getting-started/access/
画面の下の方に、IPアドレスが表示されています。
WEB UIでもCLIでも構いませんので、そのIPアドレスへ接続します。
WEB UIの場合、httpではなくhttpsであり、自己証明書のため証明書エラーは無視する必要があります。

Incus CLIをまだインストールしていない場合は、こちらに手順が載っています。
https://incus-ja.readthedocs.io/ja/latest/installing/

上記ページの一番最後に、Fetching the encryption recovery keyと言う項目があります。
リカバリーキーの出力は、記事投稿時点ではCLIでしか行えないようです。
後述のTailscaleの設定もCLIでしか行えないため、この記事の手順に従う場合はCLIをこの段階でインストールすることをお勧めします。

手順1でクライアント証明書を~/.config/incus/ディレクトリに配置してあれば、以下のコマンドでremoteサーバとして設定できます。

incus remote add <任意のサーバ> <IncusOSのIPアドレ>

他にIncusサーバを使っていなければ、デフォルトの操作対象をこのサーバに設定しておきましょう。

incus remote switch <先ほど設定したサーバ>

Incusにはローカルとリモートの概念があり、IncusOSは別端末のため必ずremoteとなります。
今回は関係ありませんが、Incus CLIを実行している端末内にIncusを構築することも可能です。

この段階でTailscaleの設定を行うことが可能となります。
ただ、設定してもIncus内にVMがないと動作確認を行いづらいため、先にTalos LinuxのVMを作成します。

6. Talos LinuxのISOイメージをダウンロードする

Talos LinuxのISOイメージは、GitHub Releaseで公開されています。
https://github.com/siderolabs/talos/releases

いくつかありますが、metal-amd64.isoもしくはmetal-arm64.isoをダウンロードしてください。
アーキテクチャは、IncusOSをインストールした端末のものです。

もし拡張機能の追加などカスタマイズを行いたい場合は、Talos Linux Image Factoryのページから、カスタマイズしたイメージのダウンロードが可能です。
https://factory.talos.dev/

7. Incus上にTalos LinuxのVMを作成する

WEB UIでもCLIでも作成できますが、今回はWEB UIで説明します。

まず、左のメニューのStorage => Custom ISOsを開き、右上のUpload custom ISOと言う緑のボタンをクリックします。

モーダルが開くので、Choose Fileから手順6でダウンロードしたISOイメージをアップします。
Aliasは何でもいいですが、Incus内でユニークである必要があります。

アップロードが完了したら、イメージの欄の一番右にある再生ボタン(▶︎)で、VMを作成できます。
初期値だとメモリがTalos Linuxの推奨値に満たないため、IncusOSのホストマシンに余力があれば増やします。
https://docs.siderolabs.com/talos/v1.12/getting-started/system-requirements

インスタンス数は、最低二つ、できれば三つ用意します。
一つはControl Planeで、残りがWorkerです。
インスタンスの作成が完了したら、忘れずにインスタンスをStartします。

Startすると、Secure Bootで起動が失敗すると思います。
WEB UIのConsoleから、設定を行います。
GraphicとText consoleの二種類ありますが、表示されている画面により操作しやすいものが変わるので、画面表示崩れたら別の方に切り替えてください。

UEFI Firmware Setupを押すと、BIOSに入ります。

Secure Bootの設定を開きます。

Reset Secure Boot Keysを選択します。

F10を押して保存します。

ESCキーを何回か押して最初の画面に戻り、Continueを選択します。

Talos LinuxのISOイメージはCD-ROMとして扱われるので、一番上のCD-ROMを選択します。

Talos Linuxが起動します。一番上を選択するか、そのまま待つとTalos Linuxが起動します。

8. Tailscale設定

Tailscaleのアカウント作成は済んでいる前提で進めます。
また、設定にはIncus CLIが必須です。

8-1. Auth key作成

まず、IncusOSに設定するAuth keyを、Tailscaleのコンソールから作成します。
https://login.tailscale.com/admin/settings/keys

設定は特に変えなくてOKですが、Descriptionくらい書いておいても良いかもしれません。

8-2. Incusのネットワーク設定確認

Incus内のネットワークのCIDRを確認します。
このCIDRを、Tailscaleへ登録します。

$ incus network list
+----------+--------+---------+----------------+---------------------------+----------------------------+---------+---------+
|   NAME   |  TYPE  | MANAGED |      IPV4      |           IPV6            |        DESCRIPTION         | USED BY |  STATE  |
+----------+--------+---------+----------------+---------------------------+----------------------------+---------+---------+
| incusbr0 | bridge | YES     | 192.0.2.1/24   | 2001:db8:1:1::1/64        | Local network bridge (NAT) | 4       | CREATED |
+----------+--------+---------+----------------+---------------------------+----------------------------+---------+---------+

incusbr0というインターフェースのCIDRが表示されると思いますので、メモします。
もし表示されない場合は何かここまでの手順が間違っていますので、確認してください。
IPv4もv6も、末尾が1になっていると思います、どちらも0に変更してこの後使用します。

192.0.2.1/24 => 192.0.2.0/24
2001:db8:1:1::1/64 => 2001:db8:1:1::/64

8-3. IncusOSの設定変更

Incus CLIで以下のコマンドを実行し、エディタを開きます。

incus admin os service edit tailscale

エディタでyamlファイルが表示されると思うので、以下の項目を更新します。

config:
  accept_routes: true
  advertised_routes:
  - <8-2で確認したCIDR。末尾を0にするのを忘れずに>
  - <8-2でIPv6があれば、追加OK。末尾の1を消すのを忘れずに>
  auth_key: <8-1で作成したAuth key>
  enabled: true

8-4. Taiscaleコンソールで、ルートをApprove

Subnetsとラベルのついた端末が追加されていると思います。
https://login.tailscale.com/admin/machines

端末をクリックすると、Subnets欄にAwaiting Approvalとあると思うので、CIDRが間違っていないことを確認したらチェックボックスにチェックを入れて承認します。

9. Incus内のTalos Linuxへ接続できることを確認

talosctlコマンドのインストール、及びPCへのTailscaleのインストールは済んでいる前提です。
https://docs.siderolabs.com/talos/v1.12/getting-started/talosctl

$ talosctl get disks --insecure --nodes <VMのIPアドレ>
NODE   NAMESPACE   TYPE   ID      VERSION   SIZE     READ ONLY   TRANSPORT   ROTATIONAL   WWID   MODEL           SERIAL
       runtime     Disk   loop0   2         75 MB    true                                                        
       runtime     Disk   sda     2         11 GB    false       virtio      true                QEMU HARDDISK   
       runtime     Disk   sr0     2         314 MB   false       virtio      true                QEMU CD-ROM  

9.5. Incus内の端末へドメイン名で接続する

これでVM内の端末へTailscale経由で接続できるようになりましたが、どうせならIPアドレスではなくドメイン名で接続したいところです。

まず、Incusのネットワーク設定を修正し、ドメイン解決ができるようにします。

incus network set incusbr0 dns.domain incus
incus network set incusbr0 dns.mode managed

一つ目のコマンドの最後のincusは、使用されるTLDです。
incusでなくてもOKですが、存在するものと衝突しないように注意してください。
RFCで予約されているものを使用するのが本来は正しいですが、慣例でincusにしています。
https://datatracker.ietf.org/doc/html/rfc2606

次に、Tailscale側でMagicDNSを設定します。
https://login.tailscale.com/admin/dns

有効になっていればそのままでOKです。

Nameservers欄で、先ほどのincusTLDを登録します。
Add nameserver => Custom

NameserverのIPアドレスは、8-2で確認した末尾が1のもの = incus network listコマンドの出力結果からサブネットマスクを除いたものを入力します。
Restrict to domainを有効にし、TLDであるincusを指定します。

PCから、名前解決できるか確認します。

dig talos-worker-1.incus

10. Talos Linuxのセットアップを行う

ここまで来れば、talosctlでTalos Linuxのセットアップを行えると思います。
ここから先は、Talos Linuxのドキュメントが詳しいので、そちらに任せます。

開発環境用の簡易手順。
https://docs.siderolabs.com/talos/v1.12/getting-started/getting-started

本番環境用の詳細手順。
https://docs.siderolabs.com/talos/v1.12/getting-started/prodnotes

まとめ

IncusOS + Talos Linuxという、Immutable OSの組み合わせによるKubernetes構成の紹介でした。
セルフホストでありながら、OSのアップデートをほとんど気にしなくて良い、メンテナンスの楽な構成です。

ispec inc.

Discussion