【CentOS7】”安全な” OSテンプレート用イメージの作り方【Hyper-V / VMware / VirtualBox】

CentOSのロゴ

検証環境の作成やアプリケーションのテストを、Hyper-V、VMware、VirtualBox 等で行う場合、ベースとなるOSのテンプレートイメージが手元にあると、それをインポートするだけですぐに新しいOS環境を作ることができ便利です。

ただし、テンプレートの作成を新規インストールしたOSをエクスポートしただけで済ますと、色々と問題が起こる可能性があるので、その解決法をまとめてみました。

エクスポートだけの場合に起こる問題

仮想マシンをエクスポートするということは、その環境を丸ごとコピーするということなので、ゴミが残っていたり、サーバごとに一意の設定がそのまま引き継がれていたりと、何かと問題が起きる可能性があります。

具体的にどのような問題が起きるのか、例を挙げます。

前環境の不要データが残ったままになる

テンプレートを作成するために、OSを新規インストールして、少し設定をいじりエクスポートする間にも、結構な量のデータが蓄積されます。このままでは、テンプレートからデプロイした環境にも不要なデータが引き継がれてしまいます。

不要データの例を以下に挙げます。

  • 各種ログファイル
  • 受信したメール
  • 各種一時ファイル、キャッシュ等
  • 実行コマンド履歴

これらのファイルは意外にサイズが膨れがちなので、削除することはテンプレートの圧縮にとっても有効です。

サーバごとに一意のIDや設定が引き継がれる

サーバには、各サーバごとに一意でなければいけない(かぶってはいけない)IDや設定があります。

同じテンプレートからデプロイした仮想マシンは、これらの値が全く同じになってしまうので、問題が起きる可能性があります。(セキュリティ的にも良くありません)

一意な設定の例を以下に挙げます。

  • SSHのホスト鍵
  • IPアドレス等の一部ネットワーク設定
  • 各種UUID(yumのUUID、Machine-id、物理ディスクやLVMのUUID などなど)

安全なテンプレート作成法

OSからユーザー固有の情報を削除し、テンプレートとして使用できる状態にすることを、一般化(generalization)といいます。

ここまでで挙げた問題点を踏まえ、CentOS を一般化し、テンプレートイメージを作成する方法を解説していきます。ほとんどの操作でroot権限が必要になります。

テンプレートの要件によっては不要な作業もあるかと思うので、手順は適宜飛ばしてください。

 

なお、この一連の作業をシェルスクリプト化したものをGitHubに上げてありますので、ご参考にどうぞ。

https://github.com/haxyier/generalization.sh

ログファイルの削除

不要なログファイルを削除します。logrotate によってローテーションされたものは削除し、削除すると問題がありそうなログは中身を空にします。

#ロギングの停止
$ systemctl stop rsyslog
$ auditctl -e 0

#ローテーションされた古いログの削除
$ find /var/log -name "*-????????" -print0 | xargs -0 --no-run-if-empty rm -f
$ find /var/log -name "*.gz" -print0 | xargs -0 --no-run-if-empty rm -f
$ rm -f "/var/log/dmesg.old"

#OSインストール時のログを削除
$ rm -f "/var/log/anaconda/*"

#クラッシュダンプの削除
$ rm -rf "/var/crash/*"

#その他のログを空にする
$ find /var/log -type f -print0 | xargs -0 --no-run-if-empty truncate -s 0

不要ファイルの削除

テンプレートには不要なファイルを削除します。

#受信メールの削除(使用しているメーラーにより、適宜コマンドを変更してください)
$ systemctl stop postfix
$ find /var/spool/mail -type f -print0 | xargs -0 --no-run-if-empty truncate -s 0

#cron設定の削除
$ rm -f "/var/spool/cron/*"

#DHCPステータスファイルを削除
$ rm -f "/var/lib/dhclient/*"

#yumのキャッシュを削除
$ yum clean all

#SSHのホスト鍵を削除(次回起動時に自動で再生成されます)
$ rm -f "/etc/ssh/ssh_host_*_key*"

#SSH用ディレクトリの削除(authorized_keys や known_hosts の削除)
$ rm -rf "/root/.ssh"
$ find /home -maxdepth 2 -mindepth 2 -name .ssh -type d | xargs --no-run-if-empty rm -rf

#Kickstart用設定ファイルを削除
$ rm -f "/root/anaconda-ks.cfg"

#一時ファイルの削除
$ rm -rf "/tmp/*"
$ rm -rf "/var/tmp/*"

補足

Kickstart とは、CentOS や RHEL のインストールを自動化するツールです。

これらのOSをインストールすると、/root/anaconda-ks.cfg に自動インストール用の設定ファイルが出力されるので、これを削除します。

システム固有IDの再生成

サーバごとに一意なIDを再生成します。

#yumのUUIDの削除(次回のyum使用時に自動で再生成されます)
$ rm -f "/var/lib/yum/uuid"

#ファイルシステムのUUID変更(xfsの場合)
#マウント中のファイルシステムは変更不可
#xfs_admin -U `uuidgen` <device-name>

#LVMのPVとVGのUUID変更
#マウント中のファイルシステムは変更不可
#pvchange -au
#vgchange -u <vg-name>

補足

起動中のシステムにマウントされているファイルシステムとLVMのUUIDは、変更することができません。一応参考までに変更コマンドを載せています。

システムの中に同一のUUIDを持つファイルシステムやLVM(PVやVG)を複数マウントすることは不可能なので、このままではそのようなシチュエーションにおいて問題が発生します。

ネットワーク設定のリセット

ファイアウォールのフィルター設定や、ホスト名、固定IPアドレス等のホスト固有のネットワーク設定をリセットします。

#ファイアウォールの設定を削除
$ truncate -s 0 "/etc/sysconfig/iptables"
$ rm -f "/etc/sysconfig/iptables.save"
$ rm -f "/etc/firewalld/services/*"
$ rm -f "/etc/firewalld/zones/*"

#ホスト名をデフォルトに戻す
$ hostnamectl set-hostname localhost.localdomain

#NIC設定の削除
$ sed -i '/^BOOTPROTO/c\BOOTPROTO="dhcp"' /etc/sysconfig/network-scripts/ifcfg-*
$ find /etc/sysconfig/network-scripts -name "ifcfg-*" -not -name "ifcfg-lo" -print0 | \
xargs -0 --no-run-if-empty sed -i '/^\(HWADDR\|UUID\|HOSTNAME\|DHCP_HOSTNAME\|IPADDR\|PREFIX\|NETMASK\|GATEWAY\|DNS\)/d'
$ rm -f "/etc/sysconfig/network-scripts/ifcfg-*.bak"

#CentOS 7.1 以降
#マシンIDの削除
$ rm -f "/etc/machine-id"
$ systemd-machine-id-setup

補足

firewalld の設定ファイル(/etc/firewalld 配下)を削除すると、次回起動時、自動的にOSインストール時と同一のデフォルト設定が作成され、適用されます。

 

ここでは、NIC設定(/etc/sysconfig/network-scripts/ifcfg-* )中のホスト固有の情報を削除しています。

IPアドレス等の情報を削除しているので、ひとまずDHCPを利用するように設定を変更しています。

 

machine-id(マシンID)とは、CentOS 7.1 で新たに追加されたIDで、ネットワーク上で機器を識別する際に使われる可能性があるそうです。

コマンド実行履歴の削除

最後に、history コマンドで閲覧することができるコマンド実行履歴を削除します。

$ rm -f "/root/.bash_history"
$ find /home -maxdepth 2 -mindepth 2 -name .bash_history | xargs --no-run-if-empty rm -f
export HISTSIZE=0

補足

コマンド実行履歴を完全に削除するには、各ユーザーのホームディレクトリ配下の .bash_history を削除するだけでは不十分です。

bashの仕様上、ログアウト時にまとめてコマンド履歴が書き出されるため、環境変数の HISTSIZE を利用して履歴ファイルのサイズを一時的にゼロに設定することで、このコマンド履歴の追記を回避しています。

システムをシャットダウンする

システムをシャットダウンします。

$ shutdown now

この状態で各仮想化ツール(Hyper-V や VMware 等)からシステムをエクスポートすれば、比較的安全なOSテンプレートの完成です。

参考

今回のテンプレート作成法を考えるにあたり、libguestfs-tools というパッケージの virt-sysprep というコマンドのソースコードを参考にしました。

virt-sysprep は、仮想マシンのイメージファイルを直接編集して一般化することができるツールです。

https://github.com/libguestfs/libguestfs/tree/master/sysprep

 

(virt-sysprep は、Hyper-V で使われている VHD形式のディスクイメージファイルとも互換性があるとどこかで読んだ気がするのですが、私の環境では使えませんでした…)

あわせて読みたい

コメントを残す

質問・感想などお気軽にどうぞ。
*が付いている項目は入力必須です。メールアドレス以外の項目が公開されます。
スパム防止のため、コメント反映まで少々時間がかかります。