Building a Homelab VM Server (2020 Edition)

Michael Lynch

自宅ラボ用VMサーバーを自作する(2020年版)

過去5年間、私はすべてのソフトウェア開発を仮想マシン(VM)で行ってきました。プロジェクトごとに専用のVMを用意することで、依存関係の衝突やTCPポートの競合といった面倒から解放されています。

3年前には、すべてのVMをホストするために自作のhomelabサーバーを構築して、一段上の環境へ進みました。多くの開発作業が高速になり、信頼性も向上した素晴らしい投資でした。

ここ数ヶ月、そのVMサーバーの限界を感じるようになりました。プロジェクトがより多くのリソースを必要とするようになり、最初の自作で犯したミスのツケも回ってきたのです。そこで2020年版として、まったく新しいhomelab VMサーバーを構築することにしました。

新しいVMサーバー自作用パーツの写真

新しいVMサーバー自作に使ったパーツ一式(ほぼすべて)

経緯はいいから構成を見せてほしい

このプロジェクトの背景に興味がなければ、直接構成の紹介へジャンプできます。

なぜわざわざVMサーバーを丸ごと作るのか

当初はWindowsデスクトップ上のVirtualBoxでVMを動かしていました。しばらくは問題ありませんでしたが、再起動が大きな手間になりました。

Windows Updateによる強制的な再起動、ソフトウェアのインストールを完了するための自発的な再起動、そしてときどき起こるOSのクラッシュなどにより、開発用VM一式を月に3〜5回は再起動しなければなりませんでした。

専用のVMサーバーなら、再起動のほとんどを回避できます。VMホストは最小限のソフトウェアしか動かしていないため、クラッシュや必須の再起動はめったに起こりません。

「homelab」とは?

homelabは、この数年で広まった単なる俗称です。homelabサーバーは他のサーバーと何ら変わりありません。違うのは、オフィスやデータセンターではなく自宅で構築するということだけです。多くの人が、本番のビジネス環境で同じツールを使う前の、リスクの低い練習環境として活用しています。

なぜクラウドを使わないのか

クラウドサーバーでも同じことはできますし、ハードウェアを自分で維持する手間(とはいえ楽しい手間ですが)も省けますが、コストが高すぎます。homelabサーバーと同等のVMリソースをAWS EC2で用意すると、年間6,000ドル以上かかります

AWS EC2インスタンスでは年間6,112.68ドルかかることを示すスクリーンショット

homelabサーバーの代わりにAWSを使うと、年間6,000ドル以上かかります

必要に応じてクラウドインスタンスを起動・停止すればコストは大幅に抑えられますが、それではワークフローに手間が増えてしまいます。ローカルのVMサーバーなら、コストを細かく管理する心配をせずに、10〜20台のVMを常に使える状態で維持できます。

過去の失敗から学ぶ

2017年に組んだサーバーはよく働いてくれましたが、3年間使う中で、改善すべき重要な点がいくつか見えてきました。

1. ストレージはローカルに置く

私のSynology NASには10.9TBのストレージ容量があります。これだけネットワークストレージがあれば、「ホストOSの起動に必要な最小限以上のディスクをサーバーに積む必要はないだろう」と考えました。

10.9TBと表示されたスクリーンショット

最初の自作では、10.9TBのネットワークストレージに頼っていました。

これは愚かな考えでした。

まず、ネットワークストレージ上でVMを動かすと、ディスクサーバーに完全に依存することになります。Synologyは2ヶ月に一度ほどOSのアップデートを公開し、そのたびに再起動が必要です。VMがSynologyのストレージ上で動いていると、Synology側のアップデートを適用するたびにVM群全体をシャットダウンしなければなりません。WindowsデスクトップでVMを動かしていたときと同じ再起動の問題が再発したのです。

Synologyのアップグレード画面のスクリーンショット

ストレージサーバーのOSは頻繁なアップグレードを必要とします。

次に、ネットワーク越しのランダムなディスクアクセスは遅いという問題です。最初の自作当時、開発の中心はバックエンドのPythonやGoアプリケーションで、大きなディスクI/Oは発生しませんでした。その後、フロントエンドのWeb開発にも手を広げました。最近のWebフレームワークはすべてNode.jsを使っており、プロジェクトごとに依存関係だけで1万〜20万ものランダムなJavaScriptファイルが存在します。Node.jsのビルドではランダムなディスクアクセスが大量に発生するため、ネットワークストレージにとっては最悪の条件でした。

2. より良いVM管理ソフトウェアを選ぶ

最初のサーバーでは、VM管理ソフトとしてKimchiVMware ESXiの2つを検討しました。VMwareの方がはるかに洗練され成熟していましたが、Kimchiの泥臭い気概とオープンソースである点に惹かれました。

Kimchiのスクリーンショット

KimchiのWeb UIに表示された初期のVM一覧

インストールしてすぐに、Kimchiの開発が止まってしまいました。

私が使い始めた直後にコミットが途絶えたことを示すKimchiリポジトリのコミットグラフ

Kimchiへのコードコミットは、私が使い始めた直後にほぼ止まってしまいました。

時間が経つにつれ、Kimchiの欠点はどんどん明らかになりました。VMの「クローン」や「シャットダウン」ボタンを何度かクリックしないと反応しないこともあり、クリックする直前にボタンが消えたり位置がずれたりするUIのバグにも悩まされました。

3. リモート管理を前提に考える

部屋の隅に置かれた古いVMサーバーの写真

VMサーバーは部屋の隅にひっそりと置かれています。普段は便利ですが、物理的にアクセスが必要なときには不便です。

「Kimchiは所詮ソフトウェアなのに、なぜ別のVM管理ソフトを入れるためだけにサーバーを丸ごと作り直す必要があったのか」と思われたかもしれません。それは、リモート管理の重要性を想定できていなかったからです。

私のVMサーバーは、オフィスの隅に置かれたモニターもキーボードもつながっていないただのPCです。SSHやWebインターフェースでアクセスできる99%の場面では問題ありません。しかし、サーバーが起動に失敗したときや新しいホストOSをインストールしたいといった残り1%の場面では大変な手間がかかります。サーバーを机まで引きずって持ってきて、デスクトップのキーボードとモニターを外してつなぎ直し、修正が終わったらまた元の配置に戻さなければなりません。

次の自作では、電源を入れた瞬間から物理的に触っているのと同じレベルでアクセスできる仮想コンソールが欲しいと考えました。DellのiDRACHPのiLOのようなものをイメージしていました。

Dell iDRACインターフェースのスクリーンショット

リモートサーバー管理の選択肢として検討したDell iDRAC

パーツ選び

CPU

最初のVMサーバーのCPUはRyzen 7 1700でした。8コア16スレッドで、当時は話題の最新CPUでした。しかし、/r/homelab(Redditのhomelabコミュニティ)で自作を披露したところ、コンシューマー向けパーツを使った素人だと馬鹿にされてしまいました。イケてる人たちはエンタープライズ機器を使うのだそうです。

Redditユーザー /u/pylori による『お前 homelabやってるの? 新しいコンシューマー製品より長持ちするように作られたエンタープライズ機器のハードウェア障害を心配するとかマジで言ってるの?』というコメント

/r/homelabでは私の最初の自作は不評でした

二度と/r/homelabに馬鹿にされないようにと、今度はエンタープライズ向けサーバーハードウェアの世界に挑戦することにしました。奮発して、物理CPUを2基搭載するシステムを組むことにしました。

コストパフォーマンスを最大化するため、4〜8年前に発売された中古CPUに絞って探しました。候補ごとにPassMarkでベンチマークスコアを調べ、eBayでそのモデルの中古の最近の販売価格を確認しました。

最もコスト効率が良いと感じたのはIntel Xeon E5 v3ファミリー、特に2600番台でした。最終的にE5-2680 v3に決めました。平均ベンチマークは15,618で、eBayでの中古価格は約130ドルでした。

Intel Xeon E5-2680 v3 CPUの写真Xeon E5-2680 v3の15618というスコアを示すcpubenchmark.netのスクリーンショット

Intel Xeon E5-2680 v3はcpubenchmark.netで15,618を記録しています

参考までに、以前の自作で使ったRyzen 7のベンチマークは14,611でした。つまりデュアルE5-2680にすれば、旧サーバーから2倍以上の処理能力になります。

マザーボード

SuperMicro MBD-X10DAL-I-Oマザーボードの写真

デュアルCPUシステムの欠点は、マザーボードの選択肢が限られることでした。デュアルのIntel 2011-v3 CPUに対応するマザーボードはほんの一握りしかなく、価格も300〜850ドルと、マザーボードに想定していたよりはるかに高額でした。

私が選んだのはSuperMicro MBD-X10DAL-I-Oで、320ドルと同等のマザーボードの中では安い方でしたが、それでも前回使ったもの5倍の価格でした。

メモリ

Crucial製メモリの写真

サーバー用メモリについては、あまり情報に基づいた選択ができないように感じました。コンシューマー向けハードウェアなら、さまざまなメモリのレビューやベンチマークを載せたサイトがたくさんありますが、サーバー用メモリではそういった情報は見当たりませんでした。

ブランドへの信頼からCrucial CT4K16G4RFD4213 64GB(4 x 16GB)を選びました。前回の自作では32GBでしたが、一部のワークフローでその上限に近づいていたため、数年先までカバーできるよう倍の64GBにしました。

ストレージ

Samsung 860 EVOの写真

M.2 SSDは小型で性能も素晴らしく、マザーボードにすっきり収まってケーブルも不要なので大好きですが、残念ながらMBD-X10DALはM.2インターフェースに対応していません。

そこで従来のSATAに落ち着き、1TBのSamsung 860 EVOを購入しました。VM1台あたり通常40GBを割り当てているので、1TBあれば十分な余裕があります。将来足りなくなれば、ディスクを追加すれば済みます。

電源

Corsair CX550M 550W 80 PLUS Bronzeの写真

電源ユニット(PSU)選びはそれほど面白いものではないので、今回も信頼できるブランドという理由でCorsair CX550M 550W 80 PLUS Bronzeを選びました。

各パーツの消費電力を合計すると400Wだったので、450Wでも十分でした。しかし550W版はわずか10ドル高いだけだったので、100Wの余裕を持たせる価値はあると判断しました。

もう一つ重視したのはセミモジュラーケーブルです。前回の自作では非モジュラーケーブルを使ったため、PSUのケーブルがすべて固定で外せませんでした。サーバー内部の部品はほとんどないのに、余分な電源ケーブルでごちゃごちゃしてしまったのです。セミモジュラーなら、使わないケーブルをPSUから外してすっきりさせられます。

ファン

Hyper 212 CPUクーラーの写真

デュアルCPU構成では冷却が意外な難題でした。MBD-X10DALは2つのCPUソケット間のスペースが狭いため、並べて設置できる薄型のファンを慎重に探しました。Cooler Master Hyper 212が2つ並べてぴったり収まりました。

ケース

Fractal Meshify Cケースの写真

サーバーはオフィスの隅に目立たず置いているので、透明パネルや派手な装飾のあるケースは避けたかったのです。

Fractal Design Meshify C Blackは評価が高く、シンプルで静かなケースとして良さそうでした。

グラフィックス

MSI GeForce GT 710 GPUの写真

ヘッドレスサーバーではグラフィックボードはそれほど重要ではありません。初期インストール時やたまのデバッグで画面を表示できれば十分なので、安価で手軽なMSI GeForce GT 710を選びました。

リモート管理

リモート管理のソリューションを調べましたが、その高さに驚きました。当初はDellのiDRACを使うつもりでしたが、リモートコンソールには300ドルのエンタープライズライセンスが必要で、構成もDell製パーツに縛られます。KVM over IPデバイスも調べましたが、さらに高く600〜1,000ドルの範囲でした。

Raritan Dominion KVM over IPの購入ページのスクリーンショット

市販のKVM over IPデバイスは500〜1,000ドルします。

そこでリモート管理を実現するために、少し変わった方法としてRaspberry Piで自作したKVM over IPデバイスを使うことにしました。TinyPilotと呼んでいます。

サーバーに接続されたTinyPilotの写真TinyPilot経由でのProxmoxインストールの画面収録

TinyPilotを使ってサーバーにOSをインストールしているところ

TinyPilotはHDMI出力をキャプチャし、ブラウザからのキーボード・マウス入力を転送します。物理的なキーボード、マウス、モニターを直接つないだときとまったく同じアクセスが得られます。ソフトウェアはオープンソースで、完成品も購入できます。

2020年版サーバーの構成

カテゴリ構成支払額
CPUIntel Xeon E5-2680 v3(x2、中古)$264.82
マザーボードSuperMicro MBD-X10DAL-I-O$319.99
ディスクSamsung 860 EVO(1TB)$149.99
メモリCrucial CT4K16G4RFD4213 64GB(4 x 16GB)$285.99
電源Corsair CX550M 550W 80 PLUS Bronze$79.99
グラフィックスMSI GeForce GT 710$44.99
ケースFractal Design Meshify C Black$84.99
CPUファンCooler Master Hyper 212(x2)$72.98
リモート管理TinyPilot(KVM over IP)$65.00
合計$1,368.74
空のケースの外側の写真空のケース内部の写真

Meshify Cは、これまで使った中でケーブルマネジメントが最も優れたケースでした。内蔵のベルクロストラップでケーブルを整理でき、ゴム製の仕切りでケースの反対側にケーブルを隠せます。

CPUを取り付けたマザーボードの写真すべてのパーツを取り付けたマザーボードの写真

マザーボード、CPU、メモリ、ファンの取り付け

完成した自作homelab VMサーバーの写真

新しい場所に収まった完成した自作サーバー

VM管理:Proxmox

VMの管理にはProxmox VEを使っています。

Proxmoxダッシュボードのスクリーンショット

すべてのVMを表示するProxmoxのダッシュボード

前回の自作でKimchiに痛い目を見たので、別の無料ソリューションを試すことには慎重でした。Proxmoxは12年の歴史があるので、十分安心できると感じました。見た目はKimchiから大きく進化していますが、ESXiほどの洗練さはありません。

Proxmoxで最も気に入っているのはスクリプトで操作できる点です。私がよく行う作業の一つに、テンプレートから新しいVMを作成し、Ansibleで追加のソフトウェアをインストールするというものがあります。ESXiでは、毎回Web UIで手作業でボタンをクリックしなければこれを行う方法が見つかりませんでした。ProxmoxではCLIが非常に強力なので、./create-vm whatgotdone-devと実行するだけで、スクリプトがWhat Got Done開発用の新しいVMを自動で作成してくれます。

最大の不満は、Proxmoxが直感的でないことです。Craft Computingのインストールチュートリアルを見つけるまで、インストール方法すら分かりませんでした。しかし、一度使い方を覚えてしまえば簡単に使えます。

ベンチマーク

古いVMサーバーを退役させる前に、性能向上を測るために普段のワークフローで簡単なベンチマークを取りました。

古いVMのほとんどは、ローカルのSSDには数台分しか空きがなかったためネットワークストレージ上で動いていました。以下のベンチマークでは、3つのシナリオで性能を比較しています。

  • 2017年版サーバー(NAS):ネットワークストレージ上に置いていた典型的なVM
  • 2017年版サーバー(SSD):ローカルストレージに置いていた少数のVM
  • 2020年版サーバー:すべてのVMをローカルSSDで実行するため、NASとSSDの区別なし

注意:これは厳密なテストではありません。各ワークフローで1回ずつサンプルを取得しただけで、条件を揃えるための正規化などは行っていません。

新しいVMのプロビジョニング

最初に計測したのは新しいVMのプロビジョニングです。私はほぼすべてのVMで使うUbuntu 18.04の標準VMテンプレートを用意しています。新しいVMが必要になるたびに、以下の手順を行うシェルスクリプトを実行しています。

  1. ベーステンプレートからVMをクローンする。
  2. VMを起動する。
  3. ホスト名をubuntuからVMの名前に変更する。
  4. 新しいホスト名を反映させるためにVMを再起動する。
  5. apt update && apt upgradeで最新のソフトウェアを取得する。
2020年版サーバーが2017年版サーバーのNASとSSDの両方を上回ることを示すグラフ

新しいサーバーでは、このワークフローが大幅に高速化しました。VMのクローンは、旧サーバーでは15分かかっていたのが、新サーバーでは4分未満になりました。

パッケージのアップグレードを省いた場合、高速化の度合いはやや小さくなります。新サーバーはNASストレージとの比較では依然として圧倒的で、8分から2分半弱まで短縮されました。SSD同士の比較では、むしろ旧サーバーに負けています。VMのクローンはディスク性能に依存する可能性が高く、旧サーバーのM.2 SSDの方が新しいSATA SSDより高速だったためです。

VMの起動

VMの電源を入れてからログイン画面が表示されるまでの時間はどれくらいでしょうか。

2017年版サーバーはNASで48.5秒、SSDで32.4秒、2020年版サーバーは18.5秒で完了したことを示すグラフ

古いVMの起動には48秒かかりました。旧システムでもSSD上の少数のVMはやや速く、32秒でログイン画面が表示されました。新しいサーバーはその両方を大きく上回り、わずか18秒でVMが起動します。

What Got Doneのエンドツーエンドテストを実行

週刊ジャーナルアプリのWhat Got Doneには、機能をエンドツーエンドで検証する自動テストがあります。これは私のワークフローでも特に多様なもので、Go製バックエンドのコンパイル、Vueフロントエンドのコンパイル、一連のDockerコンテナのビルド、そしてChromeを自動操作してアプリを検証する処理が含まれます。旧VMではリソースを使い果たしていたワークフローだったので、大きな改善を期待していました。

2017年版SSDサーバーは5.4分、2020年版サーバーは5.6分で完了したことを示すグラフ

驚いたことに、2つのサーバー間で大きな性能差はありませんでした。コールドスタート(すべてのDockerベースイメージをダウンロードする場合)では、新サーバーの方が2%遅くなりました。ベースのDockerイメージがローカルにある場合は新サーバーの方が速くなりますが、差はわずか6%でした。ボトルネックは主にディスクとブラウザの処理にあるようで、新サーバーにしても大きな違いはありませんでした。

Is It Ketoのビルド

よく行うワークフローの一つに、ケトジェニックダイエット向けリソースのIs It Ketoのビルドがあります。Vue用の静的サイトジェネレーターであるGridsomeを使ってサイトを生成しています。

2017年版SSDサーバーは3.7分、2020年版サーバーは4分で完了したことを示すグラフ

大幅な高速化を期待していましたが、逆にビルドが遅くなって驚きました。旧サーバーでは主にCPUがボトルネックになっているように見えましたが、新サーバーでCPUリソースを倍にしても効果はありませんでした。次にディスクが原因かと考え、ファイルをRAMディスクに移してみましたが、ビルド速度は変わりませんでした。

私の仮説では、このワークフローはCPUに依存しているものの、並列化の効率が悪いということです。旧サーバーの方がコア数は少ないものの1コアあたりの性能は高いため、ビルドが5〜6スレッド程度にしか分散できないのであれば、新サーバーの48コアを活かせないのです。

新しいZestfulモデルのトレーニング

Zestfulは、レシピの材料を解析する機械学習ベースのAPIです。数ヶ月に一度、新しいデータで学習させ直しています。これは私のワークフローで最もCPUを intensive に使うものなので、新システムでどうなるか興味がありました。

2017年版SSDサーバーは18.3分、2020年版サーバーは8分で完了したことを示すグラフ

ついに48コアのCPUが輝く場面です。新サーバーは旧サーバーを圧倒し、モデルのトレーニングを半分以下の時間で完了しました。残念ながら、このワークフローは年に数回しか実行しませんが。

振り返り

コンシューマー向けハードウェアを恥じる必要はない

/r/homelabから尊敬されることは今後もないかもしれませんが、次の自作ではコンシューマー向けハードウェアに戻すつもりです。

サーバー用コンポーネントの最大の利点は、サーバー用ソフトウェアとの互換性が高いことだと感じています。2017年当時は、CPUのマルチスレッディングを無効にしないとESXiをインストールできず、性能が大幅に低下しました。しかしそれはLinuxカーネルの制限によるもので、後のアップデートで修正されました

サーバー用ハードウェアが高価なのは、信頼性が高いからです。ユーザー向けサービスにとってはこの特性は重要ですが、開発用サーバーではそれほど重要ではありません。開発サーバーでたまにクラッシュしたりビット反転が起きても、一日が台無しになることはないでしょう。

デュアルCPUのトータルコストを考える

デュアルCPUのコンピューターを自作したのは今回が初めてでした。興味深い経験でしたが、手間に見合う価値はなかったと思います。

ベンチマークを見る限り、CPUがワークフローのボトルネックになることはめったにありませんでした。最も決定的な証拠は、ProxmoxのCPU使用率の推移グラフです。ここ数ヶ月、CPU負荷が11%を超えたことは一度もなく、明らかにオーバースペックでした。

CPU使用率がサーバー全体の11%を超えたことがないことを示すグラフ

ここ数ヶ月のCPU使用率の最大値は、サーバー全体の11%を超えたことがありません。

デュアルCPUが必須だったことで、マザーボードのコストが大幅に上がり、選択肢も限られてしまいました。デュアルのIntel 2011-v3 CPUに対応するマザーボードはごくわずかしかないため、他のマザーボード機能の面でも選べる幅が狭まりました。

リモート管理がもたらす柔軟性

TinyPilotでサーバーを管理するようになるまで、自分がどれだけ変化を避けていたかに気づきませんでした。BIOSやネットワーク設定を変更するたびに、次の数時間をマシンや周辺機器を物理的に移動させたり、つなぎ直してデバッグしたりすることになるリスクがありました。そう思うと、そうした設定には触れたくないと思っていました。

仮想コンソールがあれば、失敗を恐れずに済み、より柔軟に異なるOSを試せるようになります。新しいOSのインストールや習得にはもちろんそれなりの労力がかかりますが、マシンをあちこち移動させる必要がないと分かれば、ずっと気軽に挑戦できます。TinyPilotを作っていなければ、「まあ十分だ」といってESXiを使い続け、Proxmoxに挑戦することはなかったかもしれません。

1年後の追記

2021-12-05 追記

読者から、この構成で後から変えたい点はあるかと尋ねられたので、1年あまり使ってみての追記を共有します。

CPU - 過剰でした

デュアルのE5-2680 v3は明らかにやりすぎでした。

CPU使用率が50%を超えたことがめったにないことを示すグラフ

1年間の使用で、CPU使用率が50%を超えたことはめったになく、CPUが1基でも十分でした。

1年間の使用で、CPU使用率が100%に達したことは一度もなく、50%を超えたのもほんの数回だけだったので、CPUは1基でも十分でした。

SSD - 不足でした

1TBのSamsung SSDはほぼ満杯になったため、2TBのSamsung 870 Evoを追加で購入し、合計で3TBのSSDになりました。ケースにはさらにSSDを追加する十分なスペースがあります。

ディスクの空き容量が15%しかないことを示すスクリーンショット

サーバーのディスクの空き容量は15%しか残っていません。

デフォルトではVM1台あたり40GBのディスクを割り当てていますが、これでは足りないこともあります。Dockerを使う作業では、コンテナイメージですぐにディスクを使い切ってしまいます。数週間ごとにVMのディスクが満杯になり、docker system prune --allを実行しなければならなかったので、追加のディスクでそうした中断が減るはずです。

メモリ - やや不足でした

64GBのメモリはほぼ十分でしたが、メモリを確保するためにVMを停止しなければならない場面が何度かありました。リソース管理でワークフローを中断したくないので、同じメモリを64GB分追加で注文しました。

メモリ使用量が頻繁に64GBの上限に達していることを示すグラフ

64GBのメモリが上限に達しつつあります。

Proxmox - 今でも最高です

VMマネージャーとしてのProxmoxは今でも気に入っています。ライセンスも購入しましたが、新機能で自分が使っているものがあるかは分かりません。ただ、プロジェクトを支援できて嬉しく思っています。

厄介なことに、ライセンスはCPUごとに課金されるため、CPUを買いすぎたツケでProxmoxの料金も倍払わなければなりません。

パーツリスト(2021-12-05時点)

カテゴリ構成支払額
CPUIntel Xeon E5-2680 v3(x2、中古)$264.82
マザーボードSuperMicro MBD-X10DAL-I-O$319.99
ディスクSamsung 860 EVO(1TB)$149.99
ディスクSamsung 870 EVO(2TB)$239.99*
メモリCrucial CT4K16G4RFD4213 64GB(4 x 16GB)$285.99
メモリCrucial CT4K16G4RFD4213 64GB(4 x 16GB)$164.11*
電源Corsair CX550M 550W 80 PLUS Bronze$79.99
グラフィックスMSI GeForce GT 710$44.99
ケースFractal Design Meshify C Black$84.99
CPUファンCooler Master Hyper 212(x2)$72.98
リモート管理TinyPilot(KVM over IP)$65.00
合計$1,772.84

* 当初の自作から1年後に購入したものです。

原文は Michael Lynch により に公開されました。

この記事は「muse-spark-1.2-contributor」を使用して翻訳されました。