概要

CloudStack で cloud-init を使用する際の構築手順とメモ。

IDCFクラウド標準?(おすすめテンプレート)の CentOS 7.2 では cloud-init インストールしただけでは、正常動作しなかった※ので構築手順を記録しておく。

※cloud-init から META DATA サーバにアクセスできないエラーが発生

原因

CloudStack では VR が dpcp, META DATA サーバの役割も持っており、cloud-init が user_data を取得する際に、 /var/lib/dhclient/dhclient-eth0.leases ファイルから META DATA サーバのアドレスを取得している。

IDCFクラウド標準の CentOS 7.2 テンプレートでは、NetworkManager が有効になっており、NetworkManager でセットアップされた場合上記ファイルが作成されないため、cloud-init が META DATA サーバの情報取得出来ずにエラーが発生していた。

環境

  • CloudStack 4.3.0.3 (IDCFクラウド)
  • CentOS 7.2 64-bit

インストール手順

cloud-init インストール

$ sudo yum install cloud-init

cloud-init datasource 設定

以下のファイルを新規作成

/etc/cloud/cloud.cfg.d/99_cloudstack.cfg

datasource:
  CloudStack: {}
  None: {}
datasource_list:
  - CloudStack

cloud-init 有効化

$ sudo systemctl enable cloud-config
$ sudo systemctl enable cloud-init
$ sudo systemctl enable cloud-final

Interface 設定

IF 名の変更

GRUB_CMDLINE_LINUX のオプションに net.ifnames=0 を追記

/etc/default/grub

GRUB_CMDLINE_LINUX="rd.lvm.lv=centos/swap vconsole.font=latarcyrhebsun16 vconsole.keymap=jp106 rd.lvm.lv=centos/root crashkernel=auto net.ifnames=0 rhgb quiet"

grub へ反映

$ sudo grub2-mkconfig -o /boot/grub2/grub.cfg 

IF 設定

以下ファイルを新規作成

/etc/sysconfig/network-scripts/ifcfg-eth0

DEVICE="eth0"
BOOTPROTO="dhcp"
IPV6INIT="yes"
MTU="1500"
NM_CONTROLLED="no"
ONBOOT="yes"
TYPE="Ethernet"

NetworkManager 削除

$ sudo yum -y remove NetworkManager

network service 有効化

$ sudo chkconfig network on

再起動

$ sudo reboot

以上

IDCF コミュニティテンプレート

毎回やるのは面倒なのでテンプレート化 + 公開してみた

  • テンプレート名: CentOS 7.2 64bit with cloud-init

使用上の注意点

以下の制約があり、user_data へ引き渡すデータサイズは固定になるため、特定の環境下でしか使えない。
(ホスト名とか文字数が変わる環境下では、毎回改行の追加・削除等でバイト数を調整する必要がある。)

Base64エンコード前のデータのバイト数が3の倍数ではない場合、正常に認識できない

IDCFクラウド公式ブログ記事 より。

ちなみに terraform でインスタンス作成しようとしたときは以下のエラーとなる。

Error applying plan:

1 error(s) occurred:

* cloudstack_instance.default: Error creating the new instance test-01: CloudStack API error 400 (CSExceptionErrorCode: 9999): deployVirtualMachine accepts only userdata which size is multiples of 3 bytes before base64 encoding.

user_data を Base64エンコードした際のパディング( ケツに = が含まれるとダメ)が影響していると思われるが、正直使い物にならないのでなんとかして欲しい。

OKパターン

$ base64 default.yml | tr -d "\n" ;echo ""
I2Nsb3VkLWNvbmZpZwoKd3JpdGVfZmlsZXM6CiAgLSBwYXRoOiAvZXRjL3N5c2NvbmZpZy9tYWNrZXJlbC1hZ2VudAogICAgY29udGVudDogfAogICAgICBPVEhFUl9PUFRTPSItcm9sZT1zaG93cm9vbToke3NoYXJkfSIKICAgICAgQVVUT19SRVRJUkVNRU5UPTEKCgpydW5jbWQ6CiAgLSBzZXJ2aWNlIG1hY2tlcmVsLWFnZW50IHJlc3RhcnQK

NGパターン

$ base64 cloud-config.yml | tr -d "\n" ;echo ""
I2Nsb3VkLWNvbmZpZwoKd3JpdGVfZmlsZXM6CiAgLSBwYXRoOiAvZXRjL3N5c2NvbmZpZy9tYWNrZXJlbC1hZ2VudAogICAgY29udGVudDogfAogICAgICBPVEhFUl9PUFRTPSItcm9sZT1zaG93cm9vbToke3NoYXJkfSIKICAgICAgQVVUT19SRVRJUkVNRU5UPTEKCnJ1bmNtZDoKICAtIHNlcnZpY2UgbWFja2VyZWwtYWdlbnQgcmVzdGFydAo=