FJCT Tech blog

富士通クラウドテクノロジーズ公式エンジニアブログです

富士通クラウドテクノロジーズ

FJCT/Tech blog

続・IaaS基盤をテストする環境を作る話

この記事は富士通クラウドテクノロジーズ Advent Calendar 2018 21日目です。

20日目は @egoa56さんの サーバログイン時にエモい画像を出してAORI駆動開発してみた話でした。個人的な思い出話で恐縮ですが、学生の頃、管理者権限を持っていた研究室の共用サーバーで、学友が利用中の疑似端末のデバイスファイルに「進捗どうですか」と書き込んでいたずらしていたこと(例: echo "進捗どうですか" > /dev/pts/XX)を思い出しました。この話を参考にすれば、より強いAORI力を得られていたと思います。(※いたずらは節度をわきまえましょう)

はじめに

本日は @ntoofu から、 「続・IaaS基盤をテストする環境を作る話」と題して、 仮想インフラ周りのテストにまつわる話をしたいと思います。 (「続」とあるように、今日の話は去年のAdvent Calendarに投稿した IaaS基盤をテストする環境を作る話 の続報も兼ねています。)

まずは、去年から取り組んでいるIaaS基盤運用にContinuous Integration (CI)の考え方を 導入しようという動きについて簡単に説明します。

現在の私の業務は、去年までに続いて今年もニフクラという IaaS型のクラウドサービスの仮想化基盤の面倒を見るのが中心です。 VMware製品を仮想化基盤に採用しているため、vCenter ServerやNSX等を扱うことが多く、 加えて基盤運用の中で必要なサーバーにはOSS製品なども利用しており (例えば、ログの保持にElasticsearchを用いるなど)、 そうした多種多様のサーバーを運用しています。

管理する台数も多いため、それらの運用は随所で自動化がなされています。 新たに手順を自動化したり、自動化のスクリプト自体を修正したりと言ったことも日常的に 行っており、比較的コーディングを行う機会は多い業務になっています。 (10日目の記事である Operation as a code 実現に向けた運用統合ライブラリの作成活動について にて紹介している取り組みなどは、スクリプトの改善の良い例です。) また、例えばスケーラビリティの問題などで、運用中にサーバーの設定を変更したり、 トラブルの再発防止のために監視項目を追加したいということもしばしば発生します。

こうした都合により、自動化スクリプトの変更や、IaaS基盤運用システムに対する変更は 日常的に必要になっています。その一方で、それらの変更にミスがあった場合、 サービス障害に結びつくことも珍しくないため、その品質についても担保しなければなりません。

しかしながら、闇雲に確認作業やレビューを増やすといった古典的なアプローチでは、 運用システムに対する変更を加えることへの負担が大きくなってしまい、

  • 変更が大きくなることで、トラブルを生むリスクが増す
  • 変更を加えられる間隔が長くなるため、改善を図ってから恩恵を受けるまでが遅くなる
  • 変更に対する工数の多さがモチベーションを下げ、細かな問題は放置されやすくなる

といったリスクがあると考えています。

そこで、 より迅速に、それでいてより安全に、システムの設定や運用自動化の改善を行いたい という思いから、CIの考え方を導入したいと画策し、去年より活動しています。 CIは、ビルド・テストを自動化することで、本流となるソースコード(一般的にmasterブランチのもの) に対する修正(変更のマージ)を、日常的に実施できるようにすることであり、 迅速かつ安全にプロダクトを改善・エンハンスするという、 まさに求めていたメリットを得られることが期待できます。

IaaS基盤のテスト環境

しかし、CIの考えを取り入れるためには、前提となる「自動ビルド・自動テスト」を実現せねばなりませんが、 実際にはテスト環境を整備する部分に大きな課題がありました。 その解決のために、Nested hypervisorを活用し、テスト環境をオンデマンドに作成できるようにしました。 (一部、去年の内容と変わっていますが、問題があってやり方を少し変えていたりするためです。)

テスト環境として元々用いられていた環境は、多くの開発者が利用している環境であり、どうしても クリーンな状態が保ちづらい状況にありました。また、hypervisor自体がテスト対象になることも あるため、環境の数に応じて物理サーバーが必要になるので環境の数自体も制約が大きい状態でした。 したがって、自動ビルドが安定して動くとも考えにくい上、自動テストを並列で実施したりすることが 出来るほどの環境の数もないような状況でした。

そこで、以下のようなアプローチでこの問題を解決しています。

Nested hypervisor

f:id:tofu_cider:20181221080035p:plain
Nested hypervisor

通常hypervisorは物理サーバーにインストールし、その上で仮想マシン(VM)を実行できるようにしますが、 VMの上にhypervisorもインストールすることは可能で、Nested hypervisorと呼ばれています。 これを利用することで、テスト環境に必要になるESXi(VMware基盤におけるhypervisor)をVMとして 柔軟に扱うことが出来ます。

Linked clone

Nested hypervisorによりhypervisorをVMとして扱えるため、 vCenter serverのような管理サーバーや後述の踏み台サーバーなどのテスト環境に必要な他のコンポーネントVMとして用意しておけば、それらVM群をまるごとClone(コピー)することで 環境をいくつでも複製できることになります。 したがって、「種」になるようなVM群を一度用意しておけば、 以降同じような環境を簡単に作成可能になります。

しかし、単純にこれを行うと、環境を増やす度に全VMのデータをコピーする必要があり、 ストレージ容量を大量に消費する上、コピー自体に時間がかかってしまいます。

そこで、Linked cloneと呼ばれる方式を利用します。Linked cloneは端的に言えばCopy on Write方式の cloneであり、実際に書き込みが発生して差分が生まれるまではCloneしてもほとんど容量を消費しません。

ネットワークの隔離

また、Cloneする方法はストレージ以外にも問題があります。 各VMIPアドレスや、Nested hypervisor上のVMMACアドレスは変化しないため、 Clone前後のVMたちが同じL2ネットワークセグメントに属することが出来ません。

f:id:tofu_cider:20181221080214p:plain
ネットワーク隔離

そこで、VM群を全て同じ物理サーバー上に配置する代わりに、 uplinkを割り当てない仮想スイッチを環境ごとに作成してVM群をそこに接続することで、 他の環境に影響を与えないネットワークを利用できます。

踏み台サーバー

単純に専用仮想スイッチだけで完結しては環境へのアクセスの手段がないため、 1台だけ環境の外と中の間を橋渡しできる踏み台サーバーを用意し、それを利用することにします。

f:id:tofu_cider:20181221080306p:plain
踏み台サーバー

踏み台サーバー上では、環境内からインターネットのリソースにアクセスするためのHTTP proxyや、 環境内で使うためのDNSサーバーを稼働させています。

また、テストやビルドのためのプログラムは環境内で実行する必要があり、それを容易に行えるように するために、Docker APIの受け口をTCPソケットで公開したDocker hostを環境内に用意しておき、 踏み台にはDNATの設定をしておくことで環境外から環境内のDocker host上でコンテナを実行できるように しています。同時に、踏み台サーバーでNFSサーバーを稼働し、環境内Docker hostと環境外の作業サーバーで マウントすることで、コンテナと間接的にファイルシステムの一部を共有できるようにしています。

ストレージ

f:id:tofu_cider:20181221080357p:plain
FreeNAS VMを利用

Nested hypervisor上で可動させるVMの利用するストレージ(データストア)は、 VMとして環境ごとに構築したFreeNASを利用することで、環境の破棄に応じて 全てまとめて削除できるようにしています。

一時期vSANも試していたのですが、冗長化のため2つのNested hypervisorで 書き込みが発生しても、最終的に同じ物理ストレージへの書き込みとなるため、 無駄が多いことが予想され、実際にそのせいだったかは定かではありませんが、 私が検証した環境ではFreeNASの領域をiSCSIマウントするほうが高速でした。

自動ビルド

環境が整備できたところで、まずは自動ビルドをすることにしました。 ここでビルドした後の環境を、ビルド済み環境として流用することで、 各種のテストを行うための環境として活用が可能になることが 期待できたため、優先的に取り組みました。

特に説明なく「ビルド」と表現しましたが、インフラ自体に対するビルドとはいわゆる構築のこと であると考えており、IaaS基盤運用システムを対象にした自動ビルドとはすなわち、 先に説明したテスト環境にIaaS基盤運用のシステムを自動構築することに他なりません。

既に、基盤運用に用いる各種サーバーの構築は Ansible によって自動化されていたため、 テスト環境内にてこのAnsibleを実行することにより、自動ビルドは実現することができました。 実際には、テスト環境用のパラメータを用意したりテスト環境固有の細かな問題を潰す必要は 出てくることがあり、サーバーの種類が多かったこともあってそれなりに手間はかかりましたが、 特別な工夫はあまりありませんでした。

f:id:tofu_cider:20181221082059p:plain
ビルド後の環境の流用

また、ビルド後には、テスト環境の作成のために種になるVM群を軒並みLinked cloneするのと同様に、 テスト環境のVM群を軒並みFull clone(実際に全てコピーする)することにしています。 これは、Full clone後のVM群をテスト環境作成の種として扱うことで、ビルド後の状態のテスト環境を 直ちに用意できるようになるためです。

自動テスト

基盤運用に必要なサーバーが構築済みのテスト環境が容易に作成できるようになったため、 これに基づいて、実際にシステムの正常性を確認するテストをする土壌が整いました。 そこで、このようなテスト環境を作成し、各種のインテグレーションテストを自動で行う取り組みも 進めています。

実際に実施している自動テストの例として、DHCPサーバー及びその関連サーバーのテストがあげられます。 ニフクラでは、ユーザーにより作成されたサーバーに対し、DHCPにより特定のアドレスを払い出すような 仕組みが存在しており、そのシステムのテストとして、DB上での割り当てどおりにサーバーにアドレスが 振られるかどうかや、ゲートウェイの情報が設定されるかを、実際にサーバーを作成した上で確認するように しました。

インフラのテスト方法

インフラの振る舞いまで含めてテストをする方法として、 私の知る限りでは一般的に定着しているものはありません。 振る舞いをテストするフレームワークというコンセプトでは Infratasterがありますが、 先に挙げたDHCPの話などになると、やはり自力で作り込まないといけない部分が 非常に大きいのではないかと思います。

そこで、今のところは以下のライブラリなどを中心に使いつつ、Pythonでテストを書いています。

  • pytest
  • pyvmomi
    • vSphereのPython SDKとして
    • vSphere上での操作が必要な場合に利用(VMの作成など)
  • fabric
    • 適当なVMなどにSSH接続してシェル上でコマンド実行するために利用
    • 実際にpingコマンドで疎通の確認をする場合などに利用
    • コマンド実行結果を使う場合、出力形式次第ではパースなどが必要となるのが大変

特にfabricを必要とするようなケースは、かなり泥臭いアプローチになりがちですが、 現状ではやむを得ないと考えています。

インフラのテストのしやすさ

また、テストコードを書きやすいソースコードとそうでないものがあるように、 インフラのテストを進める上で、設計がテストのしやすさに影響すると感じました。

具体的にあった例として、運用者への通知は通常Zabbixを経由してメールを送るようにしている一方で、 サーバー上で動くスクリプトが異常を検知すると直接メールを送るものもあり、 急遽テスト環境内にSMTPでメールを受けてREST APIで内容を確認できるソフトウェア MailHogを導入するということがありました。 全てがZabbixを経由していれば、適切にアラートが上げられるかどうかを確かめるテストのために、 SMTPサーバーに相当するコンポーネントは不要で、Zabbixだけを確認できれば良かったでしょう。

この記事で取り上げているテスト環境の構成は、VMwareアプライアンス等も含めた テスト環境が必要であるというのが背景としてありますが、 同時に、システムを構成するサーバーとサーバーの互いの連携を分割しきれないため、 それら全てをまるごとテスト環境に詰め込んでいるという側面もあります。 しかし、先の例から言えることとして、サーバー間が無節操に連携をするのではなく、 インターフェイスを統一することで、テスト環境に必要なコンポーネントを少なくすることも可能なはずです。

この考えに基づけば、テストしやすいインフラというものを設計段階から考慮すべきなのかもしれません。

今後

ここまで、出来ていることを中心に話しましたが、 以下のように出来ていないことや解決したいこともたくさんあります。

  • テストケースの充実
    • まだ自動テストの対象が限定的なため、拡充していきたい
  • ビルド及びテスト時間の短縮
    • 実際にデプロイなどを行うため、どうしても時間がかさみ、数時間のオーダーで待つこともある
  • ストレージ使用量の削減
    • Nested hypervisor上の複数のVMのdiskが詰まったFreeNAS VMをまるごとクローンするため肥大化しがち
    • Nested hypervisor自体のメモリ量が大きめであるため、起動時にswapファイルで容量を大きく奪われる

また、CIの実現の後にはContinuous Deploymentなどにも取り組み、 トイルを撲滅し運用それ自体をエンジニアリングすることを目指しているため、 まだまだやるべきことは山積していますので、来年も継続してこの活動は 推進していく予定です。また、機会があればお話したいと思います。

まとめ

  • 迅速・安全に、システムの設定や運用自動化の改善を行いたいので、CIの考え方をIaaS基盤運用に取り入れたい
  • Nested hypervisorを利用しクリーンなテスト環境を作成できるようにした
  • クリーンなテスト環境でIaaS基盤運用システムをビルドし、テストできるようにした

明日、22日目は @herietさんの「KnativeのコンポーネントとCRD」です。 今日の記事とは打って変わってServerlessの話題になりそうですね。面白そうです。