本記事は、さくらインターネット Advent Calendar2024 25日目の記事です。
さくらのクラウドでcloud-initを使ってみたので、学んだことを利用例と合わせて記載します。
cloud-initって何?
cloud-initは、クラウド環境においてインスタンスの初期設定を自動化するツールです。
cloud-initを使うと、以下のようなことができます。
- ユーザーの作成
- SSH鍵の設定
- パッケージのインストール
- ホスト名の設定
- ネットワークの設定
- スクリプトやコマンドの実行
他にもいろいろなことができます。
詳しいことは公式ドキュメントを参照ください。
さくらのクラウドでも、cloud-initを使ってサーバーの起動時に初期設定を行うことができます。
cloud-initを使ってみる
cloud-init | さくらのクラウド マニュアルを参考に使ってみます。
さくらのクラウドでcloud-initを使うには、名前の末尾に「(cloudimg)」が付くパブリックアーカイブを選ぶ必要があります。
この記事では、「Ubuntu Server 20.04.6 LTS 64bit (cloudimg)」を選びます。
追加ユーザデータには、以下を入力します。
password: $6$rounds=4096$aUONx5Ru8eTS$a9QMv8zx6C7DQXMvtYeJqxzeCyQ9KF6Aap.mGXECmADcNo/Qe9jWFABKfOWFQojr/grq3rdzNKGvJIzo1ekuU.
これは、デフォルトユーザーのパスワードをpassword
にするための設定です。
サーバーが起動したら、以下でログインできるようになっているかと思います。
- ユーザー名:
ubuntu
- パスワード:
password
Terraformからcloud-initを使ってみる
Terraform for さくらのクラウド(v2)では、sakuracloud_server
のuser_data
にユーザデータを与えることでcloud-initを使うことができます。
詳しくはサーバ - Terraform for さくらのクラウド(v2)を参照ください。
例えば、以下のようなコードで、cloud-initで初期設定を行うサーバーを構築することができます。
data "sakuracloud_archive" "ubuntu_cloudimg" {
filter {
tags = [
"cloud-init",
"distro-ubuntu",
]
}
}
resource "sakuracloud_disk" "root" {
name = "test"
description = "Root volume"
plan = "ssd"
size = 20
source_archive_id = data.sakuracloud_archive.ubuntu_cloudimg.id
lifecycle {
create_before_destroy = true
ignore_changes = [
source_archive_id,
]
}
}
resource "sakuracloud_server" "test" {
name = "test"
core = 1
description = "Test server"
disks = [sakuracloud_disk.root.id]
memory = 1
user_data = templatefile("templates/cloud-config.yml.tftpl", {
ssh_public_key = file("files/ssh_key.pub")
})
network_interface {
upstream = "shared"
}
lifecycle {
ignore_changes = [
user_data,
]
}
}
Terraformのtemplatefile関数を使ってuser_data
にtemplates/cloud-config.yml.tftpl
というファイルの内容を入力しています。
user_data
をignore_changesに設定しているのは、user_data
を変更するたびにサーバーの再起動が発生するのを防ぐためです。
cloud-initを使うのがサーバー作成時のみの場合、意図しない再起動を防ぐために設定しておくのがおすすめです。
templates/cloud-config.yml.tftpl
の内容は以下の通りです。
#cloud-config
locale: ja_JP.utf8
ssh_authorized_keys:
- ${ssh_public_key}
ssh_pwauth: false
chpasswd:
expire: false
password: $6$rounds=4096$aUONx5Ru8eTS$a9QMv8zx6C7DQXMvtYeJqxzeCyQ9KF6Aap.mGXECmADcNo/Qe9jWFABKfOWFQojr/grq3rdzNKGvJIzo1ekuU.
timezone: Asia/Tokyo
${ssh_public_key}
にはtemplatefile関数で入力しているファイルfiles/ssh_key.pub
の内容が記述されます。
サーバーを複数台まとめて構築する際など、サーバーごとに設定する公開鍵を変えたいときにTerraformのtemplateと組み合わせて使うと便利です。
メタデータを参照する
cloud-initでは、インスタンスのメタデータを参照することができます。
さくらのクラウドで利用できるメタデータは、cloud-init | さくらのクラウド マニュアルに記載されています。
メタデータはJinjaテンプレートの形式で参照することができます。
## template: jinja
#cloud-config
hostname: {{ ds.meta_data.Server.Name }}
locale: ja_JP.utf8
ssh_authorized_keys:
- ${ssh_public_key}
ssh_pwauth: false
chpasswd:
expire: false
password: $6$rounds=4096$aUONx5Ru8eTS$a9QMv8zx6C7DQXMvtYeJqxzeCyQ9KF6Aap.mGXECmADcNo/Qe9jWFABKfOWFQojr/grq3rdzNKGvJIzo1ekuU.
timezone: Asia/Tokyo
ds.meta_data.Server.Name
からは、さくらのクラウド上でのサーバーの名前を取得できます。
そのため、上に記載したTerraformのコードとこのユーザデータを使ってサーバーを構築した場合、そのサーバーのホスト名はtest
に設定されます。
cloud-initでNICを設定する
サーバーに接続しているネットワークインターフェースの情報もメタデータとして取得することができます。
そこで、cloud-initを使ってサーバーのネットワークインターフェースの設定を行ってみます。
## template: jinja
#cloud-config
bootcmd:
- |
if [ ! -e "/etc/netplan/60-netcfg.yaml" ]; then
cat <<EOF > /etc/netplan/60-netcfg.yaml
network:
ethernets:
lo:
addresses:
- 127.0.0.1/8
- ::1/128
ens3:
addresses:
- {{ ds.meta_data.Server.Interfaces[0].IPAddress }}/{{ ds.meta_data.Server.Interfaces[0].Switch.Subnet.NetworkMaskLen }}
dhcp4: false
nameservers:
addresses:
- 210.188.224.10
- 210.188.224.11
routes:
- to: default
via: {{ ds.meta_data.Server.Interfaces[0].Switch.Subnet.DefaultRoute }}
renderer: networkd
version: 2
EOF
netplan apply
fi
hostname: {{ ds.meta_data.Server.Name }}
locale: ja_JP.utf8
ssh_authorized_keys:
- ${ssh_public_key}
ssh_pwauth: false
chpasswd:
expire: false
password: $6$rounds=4096$aUONx5Ru8eTS$a9QMv8zx6C7DQXMvtYeJqxzeCyQ9KF6Aap.mGXECmADcNo/Qe9jWFABKfOWFQojr/grq3rdzNKGvJIzo1ekuU.
timezone: Asia/Tokyo
ネットワークの設定はbootcmd
で行っています。
ネットワークの設定ファイルが存在しない場合はネットワークの設定ファイルを書き出し、netplan apply
を実行します。
ds.meta_data.Server.Interfaces[0].IPAddress
で参照しているのは、サーバーに設定しているひとつめのNICに割り当てられたIPアドレスです。
上に記載したTerraformのコードを使ってサーバーを構築した場合、共有セグメントに接続されたNICのIPアドレスが取得できます。
共有セグメントに接続されたNICは、DHCPによって自動でIPアドレスが割り当てられますが、この機能を使っている場合はSLAの対象外になります。
そのため、共有セグメントに接続するNICをcloud-initで設定するなら、DHCPを無効化する設定も一緒に入れてしまうのがおすすめです。
DHCPにてIPアドレスを取得し通信を行っている際は、SLAの対象外となります。
DHCP | さくらのクラウド マニュアル
まとめ
さくらのクラウドでcloud-initを使ってサーバーの初期設定を行う方法を紹介しました。
ご参考になれば幸いです。