OpenStack nova-scheduler はどのように動作するのか

OpenStack nova-scheduler 是如何運作的

最近、仕事の都合で OpenStack nova のコードを詳しく読む機会があったので、nova がどのように動作しているのかを記録するためにいくつか記事を書くことにしました。まず第1回目は、nova-scheduler の部分から始めます。コードレベルで、conductor がどのように scheduler を呼び出し、scheduler がどのように決定を下すのか、そのプロセスを解説していきます。

本記事は、執筆時点での最新安定版(stable)である Victoria をベースにしています。

nova-scheduler の概要

nova-scheduler はプラグインベースのスケジューラとして設計されており、ユーザーは自身のニーズに合わせて独自のスケジューラドライバを記述することができます。nova でデフォルトで有効になっているのは、nova のコードベース自体に含まれている filter scheduler(フィルタースケジューラ)

Filter scheduler の動作原理は非常にシンプルです。基本的には、すべてのホストを一連の「フィルター」にかけ、条件に合わないホストを除外し、条件を満たしたホストだけが最終的な選択プールに残ります。これらのフィルターを通過したホストに対して重み付け(weighing)を行ってソートし、上位のホストの中からランダムに1つを選択して、最終的に VM を作成するホストを決定します。簡単なフローについては、公式ドキュメントの図を参考にしてください。

OpenStack filter scheduler

OpenStack 自体にもいくつかのよく使われるフィルターが用意されていますが、必要に応じて独自のカスタムフィルターを作成し、設定で有効にすることも可能です。Weigher(ウェイアー) も同様に、よく使われるものがいくつか提供されており、ニーズに合わせて自作することもできます。

nova-scheduler ドライバのメソッド一覧

以下の nova-scheduler ドライバのベースクラス から4つのメソッドを確認できます。

  • __init__
  • run_periodic_tasks
  • hosts_up
  • select_destinations

__init__

init はその名の通り、このクラスを初期化するためのもので、host manager と service group API の2つのオブジェクトを取得します。

run_periodic_tasks

このメソッドも同様に、その用途を容易に理解できます。定期的に実行する必要のあるロジックはこのメソッド内に配置されますが、ベースクラスでは何も実装されず、直接 pass されています。

hosts_up

hosts_up は、サービスまたはトピックを実行しているホストを含むリストを返します。

select_destinations

select_destinations はスケジューラ全体の核心部分であり、ホスト選択のロジックはこのメソッド内に実装されます。nova-conductor はインスタンスをスケジューリングする際に、このメソッドを呼び出します。

nova-scheduler の全体的な動作の仕組み

現在、Nova の内部処理の大部分は conductor によって処理されています。conductor manager のコードから、以下の役割を持つ インスタンスをスケジューリングする関数を見つけることができます。

def _schedule_instances(self, context, request_spec,
                        instance_uuids=None, return_alternates=False):
    scheduler_utils.setup_instance_group(context, request_spec)
    with timeutils.StopWatch() as timer:
        host_lists = self.query_client.select_destinations(
            context, request_spec, instance_uuids, return_objects=True,
            return_alternates=return_alternates)
    LOG.debug('Took %0.2f seconds to select destinations for %s '
              'instance(s).', timer.elapsed(), len(instance_uuids))
    return host_lists

コードからは、conductor manager が スケジューラのクエリクライアント を通じて呼び出している select_destinations このメソッドは、最終的に RPC を介して nova-scheduler ドライバの select_destinations に送られ、処理されます。

前述のフィルタとウェイアーを経た後、select_destinations は各インスタンスの宛先を含む セレクションオブジェクト(selection object)を返します。

まとめ

nova-scheduler 全体のフローは非常にシンプルで分かりやすく、ドライバベースの設計により、ユーザーは自身のニーズに応じてスケジューラを柔軟に入れ替えることができます。標準の filter scheduler を使用する場合でも、独自のフィルタを簡単に作成できます。個人的には非常に優れた設計だと思いますが、ホスト数や同時にスケジューリングするインスタンス数が多い場合にはパフォーマンスの問題が発生する可能性があり、その解決策として nova cell の分割が必要になるかもしれません。

リファレンス

https://docs.openstack.org/nova/latest/user/filter-scheduler.html
https://github.com/openstack/nova/tree/stable/victoria


著作権表示:このブログのすべての記事は、特記のない限りCC BY-NC-SA 4.0ライセンスの下で提供されています。

コメントを残す