「cloud-init」でWSL環境の初期セットアップを自動化してみよう

はじめに
第11回では、独自のカスタマイズを施したWSLディストリビューションの作成方法を紹介しました。開発に使うミドルウェアやアプリがプリインストールされた自社専用のWSLディストリを作ることで、開発環境の構築をより効率化できるでしょう。
しかし、カスタムディストリビューションに含めることができない、個別のカスタマイズというものも存在します。例えば以下のようなものです。
- 個人のメールアドレスやGit設定
- ログインに使うSSH公開鍵
- .bashrcなどの個人向け設定ファイル
- プロジェクト固有の環境変数
これらの個人設定は、共通のイメージに含めることはできません。開発者ごとに異なる設定が必要な上、項目によってはセキュリティリスクになることもあるためです。こうした環境ごとに異なる設定は、初回起動時に自律的に行うべきです。そしてこれを実現するのが「cloud-init」です。今回はWSLでcloud-initを使う方法を紹介します。
cloud-initとは
cloud-initは、クラウドインスタンスの初期化を自動化するためのツールの名称です。元々はAmazon EC2などのクラウド環境で、仮想マシンの初回起動時に自律的な初期化を行うために開発されました。現在ではAWSやAzureといったクラウドのみならず、VMwareやProxmoxなどの仮想化ソフトウェア、LXD/LXCなどのコンテナプラットフォーム、MAASなどのベアメタル環境、そして今回紹介するWSLなど、幅広い環境で利用されています。
user-dataとは
cloud-initでは、起動時にインスタンスに流し込まれたuser-dataと呼ばれるデータをもとに、初期化を行います。user-dataは複数のフォーマットをサポートしていますが、その中でもよく使われるのが「Cloud config」と呼ばれるYAML形式のデータです。具体的には、以下のようなYAMLを使用します。
#cloud-config ← (1) users: ← (2) - name: developer sudo: ALL=(ALL) NOPASSWD:ALL ssh_authorized_keys: - ssh-rsa AAAAB3Nza...(略) packages: ← (3) - nginx write_files: ← (4) - path: /etc/nginx/sites-available/myapp content: | server { listen 80; server_name myapp.example.com; (...略...) } runcmd: ← (5) - apt -U -y full-upgrade
このYAMLを読んだcloud-initが何をするかは、見ただけでなんとなく理解できるのではないでしょうか。
- Cloud configは「#cloud-config」という行で開始する必要があります(1)
- usersセクションでは作成するユーザーを設定します。ここでは「developer」というユーザーを作成してパスワードなしのsudoを許可し、SSHログイン用の公開鍵を設定します(2)
- packagesセクションではシステムに追加でインストールするパッケージを指定します。ここではnginxパッケージをインストールします(3)
- write_filesセクションではファイルを指定した内容で作成します。ここではnginxのホストの設定を追加します(4)
- runcmdセクションでは任意のコマンドを実行できます。ここではOS全体をアップデートするaptコマンドを実行します(5)
なお、その他のuser-dataのフォーマットについてはこちらを参照してください。
cloud-initでWSLを初期化する
それでは、実際にuser-dataを作成し、WSLのディストリビューションを初期化してみましょう。[Windows]キー+[R]キーを押して「ファイル名を指定して実行」のダイアログを表示します。ここに「%USERPROFILE%」と入力して[Enter]キーを押してください。エクスプローラーで自分のユーザーフォルダが開くので、ここに「.cloud-init」という名前で、新しいフォルダを作成してください。
.cloud-initフォルダの中に、以下の内容のファイルを「ubuntu-all.user-data」という名前で作成してください。
#cloud-config users: - name: developer groups: adm, dialout, cdrom, floppy, sudo, audio, dip, video, plugdev, netdev sudo: ALL=(ALL) NOPASSWD:ALL shell: /bin/bash timezone: Asia/Tokyo locale: ja_JP.UTF-8 packages: - vim - fzf - curl write_files: - path: /etc/wsl.conf append: true content: | [user] default=developer runcmd: - apt -U -y full-upgrade - sudo -u developer git config --global user.name (自分の名前) - sudo -u developer git config --global user.email (自分のメールアドレス)
user-dataが作成できたら、Ubuntu 24.04を新しくインストールして、正しく初期化が行われるか見てみましょう。PowerShellを起動して、以下のコマンドを実行してください。ここでは--nameオプションを使用してディストリビューションに名前を付けています。現在のWSLでは、このように固有の名前を付けることで、同一のディストリビューション(ここではUbuntu 24.04)をPC上に複数インストールできるのです。
$ wsl --install -d Ubuntu-24.04 --name cloud-init-test
以下のコマンドを実行してみてください。既にインストールされているUbuntu-24.04に加え、cloud-init-test(中身はUbuntu 24.04)がインストールされていることが分かるでしょう。
$ wsl --list
ディストリビューションは、以下のようにwslコマンドの-dオプションに名前を指定して起動できます。
$ wsl -d cloud-init-test
インストールしたディストリビューションを起動したら、cloud-initの内容が反映されていることを確認しましょう。developerユーザーとしてログインしており、タイムゾーンは日本になっています。またGitの個人的な設定が既に行われており、fzfパッケージも追加されています。
/etc/wsl.confにも、デフォルトユーザーの設定が追記されています。
バージョンごとに初期化プロセスを使い分ける
先ほどのYAMLファイルは「ubuntu-all.user-data」という名前で作成しました。ここから想像がつくかもしれませんが、WSLのcloud-initではディストリビューションやバージョンによって異なるuser-dataを自動的に適用できます。このuser-dataのファイル名は、以下のようなフォーマットとなっています。
* <ID>-<VERSION_ID>.user-data
IDとVERSION_IDは、対象となるディストリビューションのIDとバージョンに置き換えます。例えば、Ubuntu 24.04上で、以下のコマンドを実行してみてください。
$ grep -E '\b(VERSION_ID|ID)\b' /etc/os-release
Ubuntu 24.04はIDが「ubuntu」、VERSION_IDが「24.04」であることが分かります。そのため「ubuntu-24.04.user-data」という名前でYAMLを用意すると、その初期化処理はUbuntu 24.04にのみ適用されます。
ただし、先ほどはVERSION_ID部分を「all」としていました。この場合はすべてのバージョンのUbuntuが対象となります。これを利用することで、パッケージ名が変更されているといったUbuntuのバージョンごとの差異を吸収できます。
ファイル名を「default.user-data」とすると、すべてのディストリビューションに適用されるuser-dataを作ることができます。また、特定の名前(先ほどの例ではcloud-init-test)を付けたディストリビューションにのみ適用されるuser-dataも作れます。その場合はファイル名を「(ディストリビューション名).user-data」としてください。
ここまで聞くと「Ubuntu以外のディストリビューション向けのuser-dataも作れるのでは」と思うかもしれません。原理的にはそうなのですが、「初回起動時に%USERPROFILE%\.cloud-init以下からuser-dataを読み込む」という挙動が正しく行われるのは、Ubuntu側のカスタマイズによるものです。現在、公式に提供されているAlmaLinux 10などをそのままインストールしても、cloud-initによる初期化はできません。もしUbuntuと同様のことを他のディストリビューションでも行いたいのであれば、cloud-initを適切に設定したカスタムディストリビューションを作成する必要があるでしょう。
おわりに
今回はcloud-initを使用して、WSL環境の初期セットアップを自動化する方法を紹介しました。cloud-initをうまく活用すれば、これまで手動で行っていた個人レベルの設定や、プロジェクト固有の環境構築を完全に自動化できます。開発環境は何度も作り直すことがあるでしょう。何度も行う作業であればあるほど、自動化による恩恵は大きくなります。バージョンごとに異なるuser-dataを用意できる柔軟性により、環境の差異を適切に吸収できるのも大きなメリットです。
cloud-init自体はクラウド環境の初期化においても必須のツールです。user-dataの記述方法に慣れておくと、本番の構築にも役立つでしょう。まずは手元の環境から、cloud-initをぜひ活用してみてください。
連載バックナンバー
Think ITメルマガ会員登録受付中
全文検索エンジンによるおすすめ記事
- 「mmdebstrap」でUbuntuをカスタマイズして、オリジナルのWSLディストリビューションを作ろう
- ownCloud導入はじめの一歩(仮想マシンイメージとCentOS 7のインストール手順)
- Ubuntuサーバの管理
- Kubernetes環境を構築して、実際にコンテナを動かしてみよう
- Windowsでもコンテナを使いたい! WSLで「Docker」に入門しよう
- WSLとWindowsの設定ファイルを「chezmoi」を使って安全に管理しよう
- Project CalicoをKubernetesで使ってみる:構築編
- 「microk8s」を使って、WSL上にKubernetesクラスターを構築してみよう
- Windows 11でLinuxを使う:Windows Subsystem for Linux 2の設定
- 「Visual Studio Code」と「WSL」+「Docker」をもっと便利に使いこなそう