ベアメタル環境でのサーバ構築/管理ツール 「sabakan」を試した

ベアメタル環境でのサーバ構築のためのツールや管理情報、APIなどを提供するsabakanを試してみましたのでメモを残しておきます。

sabakanとは

サイボウズさんのインフラ刷新プロジェクトNecoで用いられている機材管理ツールとのことです。

github.com

blog.cybozu.io

サーバの構成情報などを保持しておくインベントリ機能とそれらを用いてネットワークブート/プロビジョニングを行う機能を提供してくれます。
データストアとしてはetcdが用いられており、sabakan自体を複数起動して冗長構成にすることもできるようです。

f:id:febc_yamamoto:20190209115153p:plain
(画像引用元: https://github.com/cybozu-go/sabakan)

使い方としては、サーバのシリアル情報や持たせたい役割を構成情報として投入し、スイッチに繋いだ上でサーバの電源を入れるとアプリケーションがデプロイできる状態になる、という感じなようです。

次にもう少し詳しく機能をみてみます。

sabakanの持つ機能

sabakanのREADMEによると以下のような機能を持っているとのことです。

sabakanの機能(一部抜粋):

  • サーバの構成情報のインベントリ / IPアドレスの割り当て管理
  • DHCP(UEFI/iPXE HTTPでのネットワークブート用)サービス
  • HTTPサービス(OSイメージや任意のアセットの提供)
  • サーバのライフサイクル管理用APIの提供

(詳しくはREADMEのFeaturesを参照してください)

サーバのOSにはContainer Linuxを想定しており、Ignitionでプロビジョニングを行うためのjsonを組み立てたりHTTPで配信する機能も持っています。

また、サーバの状態(まだ初期化してないよ、とか動いてるよ、とか退役する/したとか)も保持してます。

参考: sabakan/lifecycle.md at master · cybozu-go/sabakan · GitHub

注意点として、サーバの状態は保持するだけでその変更はAPIなどを用いて外部から行う必要ということがあります。
ヘルスチェックなどを通じて状態を操作するコントローラー的なものは必要に応じて別途用意しないといけないということですね。

類似プロダクト

類似のプロダクトとしてはCoreOSのMatchboxがあります。

coreos.com

Kubernetes環境の構築/管理ツールであるTectonicで足回りの構築に使われているものです。

coreos.com

Matchboxはsabakanと同じくiPXEなどでのネットワークブート、Ignitionによるプロビジョニングに対応しています。

違いとしてはsabakanの方はより物理的なインフラを意識している(ラックの指定とかBMC周りとか)点とサーバの状態管理を行なっている点があります。
Matchboxの方はMetadata APIやTerraformプロバイダーの提供を行なうなど、クラウドを含めより汎用的なインフラ環境上で動かせることを目指しているように感じてます。

どちらも単体で動かすようなものではなく、ビルディングブロックとして他のシステムと協調して動かすものとなっていますので やりたいことに応じて使い分ければ良さそうですね。

sabakanでサーバ構築してみる

概要を押さえたところで早速sabakanを試してみます。

動かし方はGitHub上にGetting startedがありますのでこちらを参考にします。

github.com

また、個人的な好みにより今回はさくらのクラウドで動かします。
さくらのクラウドはOSなしでサーバ作成が出来ますしPXEブートも可能なのでsabakanが使えるはずです。

インフラの準備

まずsabakanを動かすためのサーバ/スイッチなどをさくらのクラウド上で作成します。
今回は以下のような構成にします。

構成:

f:id:febc_yamamoto:20190209121111p:plain

  • sabakan用サーバ
    • 作業用(ssh)にインターネット(共有セグメント)に接続
    • スイッチ(VPC)に接続、sabakanはVPC向けセグメントで動かす
  • VPCでは192.168.150.0/24を用いる

今回はsabakanをDocker上で動かすつもりですので、サーバのOSはContainer LinuxかRancherOSを入れとくのが楽だと思います。
サーバは作成後にスイッチへの接続、スイッチと接続したNIC(eth1)ヘのIPアドレス設定を行なっておきます(今回は192.168.150.1/24にします)。

sabakanの実行

インフラの準備ができたら早速sabakanを実行してみましょう。
以下はsabakan用サーバにssh接続して作業します。

sabakan用のconfigの作成

まずsabakan用のconfigファイルを用意します。
以下の内容をsabakan.ymlという名前で作成します。

etcd:
  endpoints:
    - http://localhost:2379
dhcp-bind: 192.168.150.1:67
advertise-url: http://192.168.150.1:10080

sabakanはconfigファイルだけでなくコマンドラインオプションで各種設定を指定可能ですが、configファイルとコマンドラインオプションを併用した場合はconfigファイルが優先され コマンドラインオプションでの指定が無視されますのでご注意ください(最初気付かずに数分悩みました)。

etcdとsabakanを起動

次にetcdとsabakanをDockerで起動します。
本来は各種オプションをしっかり指定しておくべきだとは思いますが今回はお試しということで色々手を抜いてます。

# etcd
$ docker run -d --rm --name etcd --network=host --uts=host quay.io/cybozu/etcd:3.3

# sabakan
$ docker run -d  --name sabakan --network=host -v $PWD:/work -w /work quay.io/cybozu/sabakan:1.1 -config-file sabakan.yml      

ネットブート用の設定類を投入

sabakanが起動したら次にネットブートを行うための各種設定を投入していきます。

sabakanのCLIクライアントsabactlの準備

sabakanの操作を行うためのCLIクライアントsabactlを準備しておきます。
今回はdocker execでsabakanコンテナ上でsabactlを実行するように以下のエイリアスを利用します。

$ alias sabactl='docker exec -it sabakan sabactl'

IPAM

まずIPアドレスの割り当て定義を投入します。 jsonファイルを作成してsabactlというsabakanのCLIクライアントを用いて投入します。

以下のファイルをipam.jsonという名前で作成してください。

{
   "max-nodes-in-rack": 8,
   "node-ipv4-pool": "192.168.150.0/24",
   "node-ipv4-range-size": 4,
   "node-ipv4-range-mask": 24,
   "node-index-offset": 1,
   "node-ip-per-node": 1,
   "bmc-ipv4-pool": "192.2.0.0/24",
   "bmc-ipv4-offset": "0.0.0.1",
   "bmc-ipv4-range-size": 1,
   "bmc-ipv4-range-mask": 24,
   "bmc-ipv4-gateway-offset": 1
}

作成したら以下のコマンドで投入します。

$ sabactl ipam set -f ipam.json

投入できたかは以下のコマンドで確認できます。

$ sabactl ipam get

ipam.jsonで定義している項目については以下のドキュメントを参照してください。

sabakan/ipam.md at master · cybozu-go/sabakan · GitHub

なお、こちらもとりあえず動けば良いため値は適当にしてます。

DHCPサーバの設定

次にDHCPサーバの設定を投入します。 IPAMと同じくファイルを作ってsabactlで投入します。

以下のファイルをdhcp.jsonとして作成します。

{
   "gateway-offset": 1,
}

投入は以下のコマンドです。

$ sabactl dhcp set -f dhcp.json

設定項目についてのドキュメントはこちらです。

sabakan/dhcp.md at master · cybozu-go/sabakan · GitHub

PXEブート用のイメージ

次にPXEブートを行うためのイメージをCoreOSのWebサイトから取得してsabakanに投入します。
イメージはcurlコマンドで以下のように取得します。

$ curl -o kernel -Lf http://stable.release.core-os.net/amd64-usr/current/coreos_production_pxe.vmlinuz
$ curl -o initrd.gz -Lf http://stable.release.core-os.net/amd64-usr/current/coreos_production_pxe_image.cpio.gz

取得したらsabactlで投入します。

$ sabactl images upload current kernel initrd.gz

なお、ここで指定しているcurrentは各イメージにつけるIDで任意の名前をつけれるようになっています。

sabakanは複数のイメージを登録しておくことが出来、PXEブート時に自動的に最新のイメージを利用するという仕組みになっています。

サーバの定義投入〜サーバ起動

ここまででsabakanの準備が整いました。後はサーバの定義を投入した上でサーバの電源を入れるだけです。
ということで早速定義の投入を行なってみます。

サーバのシリアル(ID)を取得

sabakanにサーバの定義情報を登録する際にサーバのシリアルが必要になります。
物理サーバであれば購入時の保証書などに記載されていると思いますのでそれを利用します。

今回はさくらのクラウドで動かしますので、単純にサーバのIDがあればOKです。

cloud-news.sakura.ad.jp

こちらの記事にあるように、さくらのクラウドではシリアル番号=IDとなります。
なのでさくらのクラウド上でサーバを作成してIDを控えましょう。

サーバの作成(さくらのクラウド)

さくらのクラウドでサーバ作成を行います。

ここでは以下の条件でサーバ作成してください。

  • サーバに接続するディスクはブランクディスクとする
  • サーバのNICはスイッチに接続する
  • 作成後すぐに起動のチェックは外しておく

こんな構成になるはずです。

f:id:febc_yamamoto:20190209150839p:plain

作成したらサーバのIDを控えましょう。

サーバの定義ファイルを作成

サーバのID(シリアル)が用意できましたので、sabakanに投入するサーバの定義ファイルを作成していきます。

まず以下のファイルをmachines.jsonとして作成します。

[
  {
    "serial": "先ほど控えたサーバのID",
    "rack": 0,               
    "role": "test",          
    "bmc": {                
      "type": "IPMI-2.0",
      "ipv4": ""         
    }                    
  }                      
]  

ここでは役割(role)をtestとしました。後ほどこのロール名を用いてIgnition設定を投入していきます。
また、今回はBMCは利用しませんので空にしています。

投入は以下のコマンドです。

$ sabactl machines create -f machines.json

サーバのプロビジョニング用にIgnition設定

次にこのサーバをプロビジョニングするためのIgnitionの設定を投入します。

プロビジョニングでは本来はディスクへのインストールなどを行うべきところですが、 今回はユーザー名core、パスワードがpasswordのユーザーを追加するだけとします。

まず以下のファイルをpasswd.ymlという名前で作成します。

users:      
  - name: core                                                                                                      
    passwordHash: "$1$2OsV8nCL$AaaGvkomzT5c/D6zApaMG0"                                                              
groups:                                               
  - name: sacloud      
    gid: 10000

次に以下のファイルをignision.ymlという名前で作成します。

passwd: passwd.yml

次にsabactlで投入します。

$ sabactl ignitions set -f ignision.yml test サーバのID

これで準備が整いました。

サーバの電源投入

いよいよプロビジョニングしてみます。サーバの電源をONにしコンソールを眺めましょう。

さくらのクラウド CLI usacloudをご利用の方は以下のコマンドでVNCコンソールを開くことが可能です。

$ usacloud server vnc サーバのID

f:id:febc_yamamoto:20190209161940p:plain

うまく設定出来ていればiPXEブートされている様子が見えるはずです。

起動したらユーザー名:core、パスワード:passwordでログインしてみましょう。

f:id:febc_yamamoto:20190209162507p:plain

ログインできれば成功です。

今回はプロビジョニングの設定が適当でしたが、きちんと設定すればすぐにアプリケーションをデプロイできる状態にまで持っていけますね!!

おまけ: sabactlでサーバの状態を変えてみる

前述の通りsabakan自体はサーバの状態を変えることはなく、外部から何らかの形で変えてあげる必要があります。
本来はサーバのプロビジョニングの完了を検知して適切にハンドリングするなどが必要ですが、ここではsabactlで手動で状態を変えてみます。

まず、初期状態ではサーバの状態はuninitializedになっています。

$ sabactl machines get-state サーバのID

uninitialized 

状態を変えるにはsabactl machines set-stateを使うようです。

# healthyにする
sabactl machines set-state サーバのID healthy

# retiringにする
sabactl machines set-state サーバのID retiring

# retiredにする!?
sabactl machines set-state サーバのID retired
Error: Bad Request: invalid request: invalid state: retired

retiredにするにはsabactl crypts deleteしなきゃいけないようです。

参考: sabakan/lifecycle.md at master · cybozu-go/sabakan · GitHub

$ sabactl crypts delete --force サーバのID

# ちゃんとretiredになってるはず
$ sabactl machines get-state サーバのID

retired

終わりに

ということで今回はsabakanを試してみました。 周りのコントローラーを工夫すれば色々出来そうですね。

以上です。