めもめも

このブログに記載の内容は個人の見解であり、必ずしも所属組織の立場、戦略、意見を代表するものではありません。

OpenStack Nova Tuning Guide的な何か

変更履歴
2014/03/19 ver1.0 作成

このドキュメントの目的

Compute Nodeが数百台の規模でNovaを利用する場合、実用的な性能を実現するには、OS/QPID/Novaなどのさまざまなパラメータを調整する必要が出てきます。このドキュメントでは、調整するべきパラメータの候補をざっくりとリストアップすることを目指します。RHEL6 + RDO(Grizzly/Havana)あたりを前提にしています。

まだまだ歴史の浅いOpenStackですので、いきなりすべての情報を網羅するのは難しい部分もありますが、みなさまからの情報を元に随時アップデートしていければいいなー、と思ってます。設定するべき具体的な値については、環境依存の要素も多く、実環境での経験を元に「Best Practice」を見出す必要があります。具体的な設定値についても、今後、できるだけ情報を追加していきたいと思います。

参考資料
Red Hat Enterprise Linux OpenStack Platform (Installation and Configuration Guide)
Red Hat Enterprise Linux 6 パフォーマンスチューニングガイド
Red Hat Enterprise MRG 2 Messaging Installation and Configuration Guide
OpenStack Documentation - OpenStack Configuration Reference
Openstack 導入事例(ヤフー株式会社)

OS (RHEL6)

cpuspeedサービスによるCPU周波数の自動調整は、パフォーマンス優先に設定します。

/etc/sysconfig/cpuspeed

GOVERNOR=performance

Compute Nodeは、tunedサービスのプロファイルを「virtual-host」に設定します。RDOの場合は、インストール時に自動設定されるはずですが、手動で設定する場合は、下記の通りです。

# tuned-adm profile virtual-host
# chkconfig tuned on
# service tuned start

QPID, Nova Conductorが稼働するサーバは、メッセージング(RPC)によるネットワーク負荷が高くなるので、ネットワーク周りのチューニングが必要です。

/etc/sysctl.conf(以下はデフォルト値。推奨値というわけではありません。)

# TCPソケットが受け付けた接続要求を格納するキューの最大長
 net.core.somaxconn=4096
# 受信用ウィンドウ・サイズの最大値。
 net.core.rmem_max = 16777216
# 送信用ウィンドウ・サイズの最大値。
 net.core.wmem_max = 16777216
# データ受信バッファサイズ
 net.ipv4.tcp_rmem = 4096 349520 16777216
# データ送信バッファサイズ
 net.ipv4.tcp_wmem = 4096 65536 16777216
# カーネルがキューイング可能なパケットの最大個数
 net.core.netdev_max_backlog=4096
# ソケット当たりのSYNを受け付けてACKを受け取っていない状態のコネクションの保持可能数
 net.ipv4.tcp_max_syn_backlog=4096

QPID

Compute Nodeの数に比例して接続数が増えるので、スレッド数や同時接続数まわりのチューニングが必要です。

qpidd.conf(以下はデフォルト値。推奨値というわけではありません。)

  worker-threads N (3)            Sets the broker thread pool size
  max-connections N (500)         Sets the maximum allowed connections
  connection-backlog N (10)       Sets the connection backlog limit for the server socket
  staging-threshold N (5000000)   Stages messages over N bytes to disk

worker-threadsは、サーバのCPUコア数程度が推奨です。

max-connectionsについては、大雑把な見積で、最低でも「(Compute Node数+20)*30」程度が必要です。Nova関連サービスは、それぞれ、QPIDに対するコネクションプール(デフォルトで30個)を持っていますが、Compute Nodeでは最低限nova-computeサービスが稼働しており、その他のコントローラー系で20個程度のサービスがあるためです。

接続数がmax-connectionsに達していないのに接続がタイムアウトする場合は、connection-backlogを増やしてみるのもよいかも知れません。

注意 既知の問題により、GrizzlyでQPIDを使う場合は、下記の指定が必須です。

nova.conf

amqp_rpc_single_reply_queue=True

RDOでは、openstack-nova-2013.1.2-3以降で、デフォルトで上記の設定が採用されるように修正されていますが、独自ビルドなどを使用する際は、明示的に指定する必要があるので注意してください。

(参考)Bug 960539 - nova-compute and other oslo based qpid services appears to be leaking qpid exchanges

Nova Conductor

sqlalchemyによるDB接続に関するパラメータです。典型的には、idel_timeout, (min|max)_pool_size, max_overflowあたりを増やす感じでしょうか。

nova.conf

[database]
db_inc_retry_interval = True 	#(BoolOpt) Whether to increase interval between db connection retries, up to db_max_retry_interval
db_max_retries = 20 	#(IntOpt) maximum db connection retries before error is raised. (setting -1 implies an infinite retry count)
db_max_retry_interval = 10 	#(IntOpt) max seconds between db connection retries, if db_inc_retry_interval is enabled
db_retry_interval = 1 	#(IntOpt) seconds between db connection retries
idle_timeout = 3600 	#(IntOpt) Timeout before idle sql connections are reaped
max_overflow = None 	#(IntOpt) If set, use this value for max_overflow with sqlalchemy
max_pool_size = None 	#(IntOpt) Maximum number of SQL connections to keep open in a pool
max_retries = 10 	#(IntOpt) Maximum db connection retries during startup. (setting -1 implies an infinite retry count)
min_pool_size = 1 	#(IntOpt) Minimum number of SQL connections to keep open in a pool
pool_timeout = None 	#(IntOpt) If set, use this value for pool_timeout with sqlalchemy
retry_interval = 10 	#(IntOpt) Interval between retries of opening a sql connection

Nova(プロセスの並列化)

Novaのコントローラー系のサービス(プロセス)は、メッセージングサーバで疎結合するようになっているので、同じサービス(プロセス)を同時に複数起動して負荷分散することが可能です。複数サーバに分散するだけではなく、サーバのCPUコア数が多い場合は、1つのサーバ上で複数起動することで性能が向上する場合もあります。この時、単純に複数起動するだけでよいものと、外部からの接続処理をロードバランサで振り分ける必要のあるものがあります。

ロードバランサで振りわける必要があるもの

プロセス 説明
nova-api REST APIを提供(Native API/EC2 API/Metadata Service APIをまとめて提供)
nova-api-os-compute REST APIを提供(Native APIのみ提供)
nova-api-ec2 REST APIを提供(EC2 APIのみ提供)
nova-api-metadata REST APIを提供(Metadata Service APIのみ提供)
nova-novncproxy novncによるコンソールアクセスを中継
nova-xvpvncproxy Javaクライアントからのコンソールアクセスを中継

単純に複数起動すればよいもの

プロセス 説明
nova-scheduler インスタンスの配置先を決定
nova-conductor DBアクセスのProxyサービス
nova-cert EC2 APIで必要となる証明書管理
nova-consoleauth コンソールアクセス時の認証管理

※nova-consoleauthを複数起動する際は、トークンをmemchacedで共有する設定が必要です。

Nova(メッセージング関連)

Nova Computeは、定期的なステータスレポートの送信、および、定期的な各種タスク(periodic task)の実行を行っており、これらに伴うQPIDのメッセージング処理(RPC)が発生します。Compute Nodeが増えるとメッセージング処理がボトルネックになるため、これらの実行間隔を伸ばす必要があります。

まず、ステータスレポートの送信間隔とステータスがアップデートされない場合にノードダウンと判定するタイムアウト時間の設定がこちらです。report_interval(ステータスレポートの送信間隔)を伸ばした場合は、service_down_time(タイムアウト時間)も合わせて伸ばしてください。

nova.conf

# seconds between nodes reporting state to datastore (integer
# value)
#report_interval=10
# maximum time since last check-in for up service (integer
# value)
#service_down_time=60

極端に伸ばした場合の弊害としては、Compute Nodeが障害停止した際に、それが認識されるまでの時間が長くなり、その間、Nova Schedulerが停止中のノードでインスタンスを起動しようとして失敗する可能性が高くなります。失敗した場合は、自動的にその他のノードを再選択するので、実害はありませんが、再選択が頻発するとNova Schedulerの処理が重くなる恐れがあります。

続いて、各periodic taskの設定です。
----

# interval to pull bandwidth usage info (integer value)
#bandwidth_poll_interval=600

これは、xenapiドライバのみで意味を持つ処理ですので、KVMを使用する際は無効化するべきです。最近のパッチで自動的に無効化されるようになりましたが、それ以前のバージョンでは、無効化する方法がありません。そのため、極端に大きな値に設定することをお勧めします。理論的には、次で表示される値が設定可能な最大値です。

$ python -c 'import sys ; print sys.maxint'

----

# interval to sync power states between the database and the
# hypervisor (integer value)
#sync_power_state_interval=600

これは、インスタンスがコントローラーの管理外の理由で停止した場合(障害停止、ユーザがゲストOSでpoweroffを実行した場合など)に、インスタンスの状態をDBに反映する処理を行います。

----

# Number of seconds between instance info_cache self healing
# updates (integer value)
#heal_instance_info_cache_interval=60

Neutronが行ったインスタンスに関する変更情報をNovaが取得して同期するタスクです。全てのインスタンスの情報を取得するためにメッセージングの通信量が多くなります。メッセージングの処理がボトルネックと思われる場合、まずは、この値を600程度まで伸ばすところからチューニングを開始するのがよいでしょう。(ただし、Icehouseでは、この処理に伴う通信量を減らすように改善が行われています。)

----

# Number of seconds to wait between runs of the image cache
# manager (integer value)
#image_cache_manager_interval=2400

Glanceからダウンロードしたイメージのキャッシュで長時間利用されていないものを削除するタスクです。

----

# Interval in seconds for reclaiming deleted instances
# (integer value)
#reclaim_instance_interval=0

デフォルトで無効化されています。(0を設定すると無効化されます。)

----

# Interval in seconds for gathering volume usages (integer
# value)
#volume_usage_poll_interval=0

デフォルトで無効化されています。(0を設定すると無効化されます。)

----

# Interval in seconds for polling shelved instances to offload
# (integer value)
#shelved_poll_interval=3600

Shelving機能を使わない場合は無効化して構いません。

----

# Interval in seconds for retrying failed instance file
# deletes (integer value)
#instance_delete_interval=300

インスタンスの削除処理に失敗して残ったディスクイメージなどのゴミ掃除を行います。

----

# Number of seconds to wait between runs of the cleanup task.
# (integer value)
#running_deleted_instance_poll_interval=1800

インスタンスの削除処理に失敗して、起動したままになっているインスタンスを強制削除します。