こんにちは、Necoチームの鈴木です。
Necoチームでは仮想データセンター構築ツールPlacematを使って、データセンターを丸ごと仮想化し、その上でサーバーのプロビジョニングやKubernetesクラスタ構築、Kubernetes上で動作するアプリケーションのTest Suitesを実行しています。 Placematはプロジェクト初期に開発されたツールで、古いツールに依存していたり、実装方式や設計が洗練されていないなどの課題があっため、4ヶ月前からv2を開発開始し、先日リリースしました。 本記事ではその機能と使い方、今後のCI改善 Placemat on Kubernetesについて紹介します。
特徴
- シンプルな構成
- YAMLの設定ファイルで多彩なデータセンター環境を再現可能
- 多彩なVM設定
- 仮想BMC
シンプルな構成
Placematはシングルバイナリで構成されています。 使い方もシンプルで、インストールしたバイナリにYAMLの設定ファイルを渡して起動すると、設定に従ってネットワークを構成してVMを起動、終了時にはそれらをクリーンアップします。 CIで自動テストを実行するための環境作りがとても楽になります。aptで依存ライブラリをインストール、debパッケージでPlacematをインストールして起動すれば完了です。
YAMLの設定ファイルで多彩なデータセンター環境を再現可能
下記のリソースをYAMLファイルに定義して組み合わせることで、様々な構成の仮想データセンターを構築することができます。
1: Network
リソースを定義することで、Bridgeネットワークを作成します。VMやスイッチを相互に接続できます。
kind: Network name: my-net type: external use-nat: true address: 10.0.0.0/22
2: NetworkNamespace
リソースを定義することで、独立したネットワーク領域を作成します。Network Namespace内でbirdなどのアプリケーションを実行することでスイッチの機能をエミュレーションすることができます。
kind: NetworkNamespace name: my-netns init-scripts: - /path/to/script interfaces: - network: net0 addresses: - 10.0.0.1/24 apps: - name: bird command: - /usr/local/bird/sbin/bird - -f - -c - /etc/bird/bird_core.conf
3: Node
リソースを定義することでQEMUでVMを起動することができます。後述しますが多彩な設定が可能になっています。
kind: Node name: my-node interfaces: - net0 volumes: - kind: image name: root image: image-name copy-on-write: true - kind: localds name: seed user-data: user-data.yml network-config: network.yml - kind: raw name: data size: 10G - kind: hostPath name: host-data path: /var/lib/foo writable: false ignition: my-node.ign cpu: 2 memory: 4G smbios: manufacturer: cybozu product: mk2 serial: 1234abcd uefi: false tpm: true
4: Image
リソースでサーバーの起動ディスクイメージを定義できます。URLを指定してPlacematにダウンロードさせることもできますし、ローカルに保存済みのイメージファイルのパスを指定することもできます。
kind: Image name: ubuntu-cloud-image url: https://cloud-images.ubuntu.com/releases/16.04/release/ubuntu-16.04-server-cloudimg-amd64-disk1.img
Necoチームで使っている構成
Necoチームでは以下の構成の仮想データセンターを構築して自動テストに使っています。
- Network Namespace、Bridgeをそれぞれ作成し、Vethを作って指定されたBridgeに繋ぐことでネットワークを構成する。そして、それぞれのNamespace内でbird、chrony、squid、dnsmasqをコンテナで起動し、SwitchのBGPリフレクタ、DHCP Relay、NTPサーバー、プロキシサーバーの機能をエミュレーションする。
- Boot ServerやCompute SeverのVMを起動し、Tap Interfaceを使ってBridgeに繋いで、各RackのToR Switchに接続する。
多彩なVM設定
Node
リソースは以下のような多彩なVMの設定が可能で、様々なユースケースに対応可能です。
- プロビジョニング
- cloud-init、ignitionを使ってサーバーのプロビジョニングを自動化することができ、テスト環境の構築を容易にします。
- ファイル共有
hostPath
volumeを指定することで、virtio-9p-deviceを使ったホスト/ゲスト間のファイル共有が可能です。cloud-initやignitionでvolumeをmountすれば、テストに必要なファイルをホストから渡すこともできます。
- TPM
- Trusted Platform Module(TPM)をVMに設定することができます。TPMにディスク暗号化キーを保存するようなユースケースのテストを実行できます。
- UEFI
- 旧来のBIOSだけではなく、UEFIも利用することができます。
Quick Start
こちらのExampleを使ってPlacematを実際に動かす方法を紹介します。 動作環境はUbuntu 18.04/20.04になります。VMで動かす場合にはNested Virtualizationを有効にする必要があります。
ここでは以下のようなBootサーバー1台、Workerサーバー2台のClusterを構築していきます。
- BootサーバーはUbuntu20.04のイメージを使って起動し、cloud-initで初期設定してdnsmasq, nginxを起動して、network bootサーバーとして機能する
- WorkerサーバーはBootサーバーからiPXEをダウンロードし、Bootサーバーから提供されたFlatcar container linuxのイメージを使って起動する
使用する設定ファイルは以下になります。
kind: Network name: net0 type: external use-nat: true address: 172.16.0.1/24 --- kind: Network name: bmc type: bmc use-nat: false address: 172.16.1.1/24 --- kind: Image name: ubuntu-image url: https://cloud-images.ubuntu.com/releases/20.04/release/ubuntu-20.04-server-cloudimg-amd64.img --- kind: Node name: boot interfaces: - net0 volumes: - kind: image name: root image: ubuntu-image - kind: localds name: seed user-data: user-data.example.yml network-config: network-config.example.yml cpu: 1 memory: 2G --- kind: Node name: worker-1 interfaces: - net0 volumes: - kind: raw name: data size: 10G cpu: 1 memory: 2G smbios: serial: 1234abcd uefi: false --- kind: Node name: worker-2 interfaces: - net0 volumes: - kind: raw name: data size: 10G cpu: 1 memory: 2G smbios: serial: 5678efgh uefi: false
インストール
以下のコマンドを実行して依存packageとPlacematをインストールします。
# 依存packageをインストール $ sudo apt-get update $ sudo apt-get -y install --no-install-recommends qemu qemu-kvm socat picocom cloud-utils freeipmi-tools # Placematをインストール $ curl -O -sfL https://github.com/cybozu-go/placemat/releases/download/v2.0.4/placemat2_2.0.4_amd64.deb $ sudo dpkg -i ./placemat2_2.0.4_amd64.deb
Placematを起動
以下のコマンドを実行してplacematリポジトリをcloneし、exampleのclusterを構築します。
$ git clone https://github.com/cybozu-go/placemat.git $ cd placemat/examples $ sudo placemat2 --data-dir ./data --cache-dir ./cache ./cluster.example.yml
以下のログが表示されていれば起動成功です。
placemat2 info: "Start Placemat API server" address="127.0.0.1:10808"
サーバーにログイン
Placematを起動したコンソールとは別のコンソールを開き、以下のコマンドでnode(VM)の一覧を確認します。
$ pmctl2 node list boot worker-1 worker-2
続いてbootサーバーにログインします。
$ sudo pmctl2 node enter boot # ユーザー: ubuntu, パスワード: ubuntu でログインできます。 # ターミナルを終了する時は、Ctrl-qとCtrl-xを続けて押してください。
worker-1にもログインしてみます。bootサーバーからOSイメージをダウンロードしてセットアップを終えるとログインできるようになります。環境によっては時間がかかる場合があります。
# worker-1にログイン $ sudo pmctl2 node enter worker-1 # ターミナルを終了する時は、Ctrl-qとCtrl-xを続けて押してください。
BMCサーバーを起動
次にBMCサーバーを起動して、IPMI、Redfishを使ってVMを再起動してみます。ここではworker-1のBMCを起動して再起動してみたいと思います。
$ sudo pmctl2 node enter worker-1 $ echo 172.16.1.2 | sudo dd of=/dev/virtio-ports/placemat # ターミナルを終了する時は、Ctrl-qとCtrl-xを続けて押してください。
PlacematはVMの/dev/virtio-ports/placemat
にcharデバイスを設定して、BMCアドレスが通知されるのを待機しています。
アドレスが通知されると以下のようなログを出力してBMCサーバーを起動します。
placemat2 info: "creating BMC port" bmc_address="172.16.1.2" serial="1234abcd" placemat2 info: "BMC USer: Add user" user="cybozu"
ipmipower
コマンドを使ってworker-1の電源状態を取得してみます。
$ ipmipower --stat -u cybozu -p cybozu -h 172.16.1.2 -D LAN_2_0 172.16.1.2: on
続いてRedfishを使って電源状態を取得します。
$ curl -sku cybozu:cybozu https://172.16.1.2/redfish/v1/Systems/System.Embedded.1 | jq .PowerState "On"
worker-1を再起動
ipmipower
コマンドでworker-1を再起動します。
$ ipmipower --reset -u cybozu -p cybozu -h 172.16.1.2 -D LAN_2_0 172.16.1.2: ok
worker-1のコンソールに入ると再起動してネットワークブートしている様子が確認できます。
$ sudo pmctl2 node enter worker-1 # ターミナルを終了する時は、Ctrl-qとCtrl-xを続けて押してください。
Redfishを使う場合はこちらのコマンドで再起動できます。
$ curl -X POST -H "Content-Type: application/json" -d '{"ResetType":"ForceRestart"}' -sku cybozu:cybozu https://172.16.1.2/redfish/v1/Systems/System.Embedded.1/Actions/ComputerSystem.Reset
Placematを終了する
Placematを起動したコンソールでCtrl-cを押します。作成したBridgeやNetwork Namespaceなどをクリーンアップして終了します。
今後のCI改善計画 - Placemat on Kubernetes
最近ではRook/CephやMySQL Operator MOCOなど重量級のアプリケーションが稼働を始めたことなどもあって、CIの不安定さや遅さが問題になることが増えてきました。
- GCP上のNested VMが安定しない。VMが落ちてしまったり、起動してこないなどの不安定な挙動がある。
- GCPのQuotaに引っかかってしまい、インスタンスを起動できないことがある。
- GCPの利用料金がかさむ。
- Nested VMのCPUやIOのボトルネックにより、CIの実行時間が長い。
これらの課題を解決するために、PlacematをKubernetes上で動かしてCIを回すことを計画しています。
- 自社データセンターのBare Metalサーバー上に構築したKubernetesクラスタ(Staging環境)のPod内で、仮想データセンターを構築する。
- Github Actionsのself-hosted runnerを使って上記の環境でワークフローを実行する。
Self-hosted runnerをKubernetes Clusterで管理するためのOperatorを絶賛開発中です。 こちらのOperatorが完成したら、KubernetesのPod内に構築された仮想データセンターでワークフローを実行するように、CI環境の移行を進めていく予定です。 事前のPoCではCIの高速化が期待できる結果が出ているため、大幅なCI改善を見込んでいます。