[ English | 日本語 | Deutsch | Indonesia ]

ハリウッド^H^H^H^H^Hクラウドナイトメア

ここにあるのは、OpenStack クラウドオペレータ達の苦闘の抜粋である。これを読み、彼らの叡智を学ぶが良い。

二重 VLAN

私は、新しい OpenStack クラウドのセットアップをするため、カナダのブリティッシュコロンビア州ケロウナの現地にいた。デプロイ作業は完全に自動化されていた。Cobbler が物理マシンに OS をデプロイし、それを起動し、その後は Puppet が引き継いだ。私は練習で幾度もデプロイシナリオを実行してきたし、もちろん全て正常であった。

ケロウナの最終日、私はホテルから電話会議に参加していた。その裏で、私は新しいクラウドをいじっていた。私はインスタンスを1つ起動し、ログインした。全ては正常に思えた。退屈しのぎに、私が ps aux を実行したところ、突然そのインスタンスがロックアップしてしまった。

これは単なる1回限りの問題と思ったので、私はインスタンスを削除して、新しいインスタンスを起動した。その後電話会議は終了し、私はデータセンターを離れた。

データセンターで、私はいくつかの仕事を済ませると、ロックアップのことを思い出した。私は新しいインスタンスにログインし、再度 ps aux を実行した。コマンドは機能した。ふぅ。私はもう一度試してみることにした。今度はロックアップした。

何度か問題が再現した後、私はこのクラウドが実は問題を抱えているという不幸な結論に至った。更に悪いことに、私がケロウナから出発する時間になっており、カルガリーに戻らなければならなかった。

どこかであなたはこのような障害調査を行ったことがあるだろうか?インスタンスはコマンドを打つ度に全くランダムにロックアップしてしまう。元になったイメージの問題か?No-全てのイメージで同じ問題が発生する。コンピュートノードの問題か?No-全てのノードで発生する。インスタンスはロックアップしたのか?No!新しいSSH接続は問題なく機能する!

我々は助けを求めた。ネットワークエンジニアは、これは MTU の問題ではないかというのだ。素晴らしい!MTU! 事態は動き始めた! MTU とは何で、何故それが問題になるのだろうか?

MTU とは最大転送単位(Maximum Transmission Unit)である。これは、各パケットに対してそのインターフェースが受け取る最大バイト数を指定する。もし2つのインターフェースが異なる MTU であった場合、バイトは尻切れトンボとなって変なことが起こり始める。例えばセッションのランダムなロックアップとか。

注釈

すべてのパケットサイズが 1500 に収まるわけではない。SSH 経由の ls コマンド実行は 1500 バイト未満のサイズのパケット1つで収まるかもしれない。しかし、 ps aux のように多大な出力を行うコマンドを実行する場合、1500 バイトのパケットが複数必要とある。

OK。では MTU の問題はどこから来るのか?なぜ我々は他のデプロイでこの問題に遭遇しなかったのか?この状況は何が新しいのか?えっと、新しいデータセンター、新しい上位リンク、新しいスイッチ、スイッチの新機種、新しいサーバー、サーバーの新機種…つまり、基本的に全てが新しいものだった。素晴らしい。我々は様々な領域で MTU の増加を試してみた。スイッチ、コンピュータのNIC、インスタンスの仮想NIC、データセンターの上位リンク用のインターフェースのMTUまでいじってみた。いくつかの変更ではうまくいったが、他はダメだった。やはり、この線の障害対策はうまくいってないようだった。我々はこれらの領域のMTUは変更すべきではないようだ。

結局、我々のネットワーク管理者(Alvao)と私自身は4つのターミナルウィンドウ、1本の鉛筆と紙切れを持って座った。1つのウインドウで我々は ping を実行した。2つ目のウインドウではクラウドコントローラー上の tcpdump 、3つ目ではコンピュートノード上の tcpdump 、4つ目ではインスタンス上の tcpdump を実行した。前提として、このクラウドはマルチノード、非マルチホスト構成である。

1つのクラウドコントローラーが全コンピュートノードのゲートウェイの役割を果たしていた。ネットワーク設定には VlanManager が使われていた。これは、クラウドコントローラーと全コンピュートノードで、各 OpenStack プロジェクトが異なる VLAN を持つことを意味する。パケットサイズ変更のため、 ping-s オプションを使用していた。パケットが全て戻ってくる時もあれば、パケットが出ていったきり全く戻って来ない時もあれば、パケットはランダムな場所で止まってしまう時もある、という状況だった。 tcpdump を変更し、パケットの16進ダンプを表示するようにした。外部、コントローラー、コンピュート、インスタンスのあらゆる組み合わせの間で ping を実行した。

遂に、Alvaro が何かを掴んだ。外部からのパケットがクラウドコントローラーを叩いた際、パケットは VLAN で設定されるべきではない。我々はこれが正しいことを検証した。パケットがクラウドコントローラーからコンピュートノードに行く際、パケットはインスタンス宛の場合にのみ VLAN を持つべきである。これもまた正しかった。ping のレスポンスがインスタンスから送られる際、パケットは VLAN 中にいるべきである。OK。クラウドコントローラーからインターネットにパケットが戻る際、パケットには VLAN を持つべきではない。NG。うぉっ。まるで パケットの VLAN 部分が削除されていないように見える。

これでは意味が無かった。

このアイデアが我々の頭を駆け巡る間、私はコンピュートノード上でコマンドをランダムに叩いていた。

$ ip a

10: vlan100@vlan20: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br100 state UP

「Alvaro、VLAN 上に VLAN って作れるのかい?」

「もしやったら、パケットに余計に4バイト追加になるよ・・」

やっと事の全容が判明した…

$ grep vlan_interface /etc/nova/nova.conf
vlan_interface=vlan20

nova.conf 中で、 vlan_interface は OpenStack が全ての VLAN をアタッチすべきインターフェースがどれかを指定する。正しい設定はこうだった。

vlan_interface=bond0

これはサーバーの冗長化された(bonded)NIC であるべきだからだ。

vlan20 はデータセンターが外向けのインターネットアクセス用に我々に付与した VLAN である。これは正しい VLAN で bond0 にアタッチされている。

ミスにより、私は全てのテナント VLAN を bond0 の代わりに vlan20 にアタッチするよう OpenStack を設定した。これにより1つの VLAN が別の VLAN の上に積み重なり、各パケットに余分に4バイトが追加され、送信されるパケットサイズが 1504 バイトになる原因となった。これがパケットサイズ 1500 のみ許容するインターフェースに到達した際、問題の原因となったのだった!

全力でこの問題を修正した結果、全てが正常に動作するようになった。

「あの問題」

2012年8月の終わり、カナダ アルバータ州のある大学はそのインフラを OpenStack クラウドに移行した。幸か不幸か、サービスインから1~2日間に、彼らのサーバーの1台がネットワークから消失した。ビッ。いなくなった。

インスタンスの再起動後、全ては元通りに動くようになった。我々はログを見直し、問題の箇所(ネットワーク通信が止まり、全ては待機状態になった)を見た。我々はランダムな事象の原因はこのインスタンスだと判断した。

数日後、それは再び起こった。

我々はログのセットを両方見直した。頻発したログの1つは DHCP だった。当時、OpenStack はデフォルトでは DHCP リース期間を 1分に設定していた (現在は 2分)。これは、各インスタンスが固定 IP アドレスを更新するためにクラウドコントローラー(DHCP サーバー)に接続することを意味する。幾つかの理由で、このインスタンスはその IP アドレスを更新できなかった。インスタンスのログとクラウドコントローラー上のログを突き合わせ、並べてやりとりにしてみた。

  1. インスタンスはIPアドレスを更新しようとする。

  2. クラウドコントローラーは更新リクエストを受信し、レスポンスを返す。

  3. インスタンスはそのレスポンスを「無視」して、更新リクエストを再送する。

  4. クラウドコントローラーは2度めのリクエストを受信し、新しいレスポンスを返す。

  5. インスタンスはクラウドコントローラーからのレスポンスを受信しなかったため、更新リクエストを 255.255.255.255 に送信し始める。

  6. クラウドコントローラーは 255.255.255.255 宛のリクエストを受信し、3番めのレスポンスを返す。

  7. 最終的に、インスタンスはIPアドレス取得を諦める。

この情報により、我々は問題が DHCP 実行に起因するものと確信した。何らかの理由でインスタンスが新しいIPアドレスを取得できず、その結果IPアドレスがなくなり、インスタンスは自分自身をネットワークから切り離した、と考えた。

ちょっと Google 検索した結果、VLAN モードでの DHCPリースエラー を見つけた。この情報はその後の我々の DHCP 方針の支えになった。

最初のアイデアは、単にリース時間を増やすことだった。もしインスタンスが毎週1回だけIPアドレスを更新するのであれば、毎分更新する場合よりこの問題が起こる可能性は極端に低くなるだろう。これはこの問題を解決しないが、問題を単に取り繕うことはできる。

我々は、このインスタンス上で tcpdump を実行して、操作で再びこの現象に遭遇するか見てみることにした。実際、我々はやってみた。

tcpdump の結果は非常に奇妙だった。一言で言えば、インスタンスが IP アドレスを更新しようとする前に、まるでネットワーク通信が停止しているように見えた。1分間のリース期間で大量の DHCP ネゴシエーションがあるため、確認作業は困難を極めた。しかし、パケット間のたった数ミリ秒の違いであれ、あるパケットが最初に到着する際、そのパケットが最初に到着し、そのパケットがネットワーク障害を報告した場合、DHCP より前にネットワーク障害が発生していることになる。

加えて、問題のインスタンスは毎晩非常に長いバックアップジョブを担っていた。「あの問題」(今では我々はこの障害をこう呼んでいる)はバックアップが行われている最中には起こらなかったが、(数時間たっていて)「あの問題」が起こるまであと少しのところだった。

それから何日か過ぎ、我々は「あの問題」に度々遭遇した。我々は「あの問題」の発生後、dhclient が実行されていないことを発見した。今、我々は、それが DHCP の問題であるという考えに立ち戻った。 /etc/init.d/networking restart を実行すると、全ては元通りに実行されるようになった。

探し続けてきた Google の検索結果が突然得られたという事態をお分かりだろうか?えっと、それがここで起こったことだ。私は dhclient の情報と、何故 dhclient がそのリースを更新できない場合に死ぬのかを探していて、我々が遭遇したのと同じ問題についての OpenStack と dnsmasq の議論の束を突然発見した。

高負荷ネットワーク IO と dnsmasq の問題

DHCPOFFERが送信されない事による、起動中のインスタンスのIPアドレスの消失

マジ?Google。

このバグ報告は、すべてに対して重要です。 KVMイメージがブリッジネットワークで接続を失う

レポートを読むのは楽しかった。同じ奇妙なネットワーク問題にあった人々であふれていたが、全く同じ説明はなかった。

つまり、これは qemu/kvm のバグである。

バグ報告を発見すると同時に、同僚が「あの問題」を再現することに成功した!どうやって?彼は iperf を使用して、インスタンス上で膨大なネットワーク負荷をかけた。30 分後、インスタンスはネットワークから姿を消した。

パッチを当てた qemu と再現方法を携えて、我々は「あの問題」を最終的に解決したかを確認する作業に着手した。インスタンスにネットワーク負荷をかけてから丸48時間後、我々は確信していた。その後のことは知っての通りだ。あなたは、joe へのバグ報告を検索し、私のコメントと実際のテストを見つけることができる。

イメージの消失

2012年の終わり、Cybera (カナダ アルバータ州にある、サイバーインフラのデプロイを監督する権限を持つ非営利団体)が、彼らの DAIR project 用に新しい OpenStack クラウドをデプロイした。サービスインから数日後、あるコンピュートノードがロックアップした。問題のノードの再起動にあたり、私は顧客の権限でインスタンスを起動するため、そのノード上で何のインスタンスがホスティングされていたかを確認した。幸運にも、インスタンスは1つだけだった。

nova reboot コマンドは機能しなかったので、 virsh を使用したが、すぐに仮想ディスクが見つからないとのエラーが返ってきた。この場合、仮想ディスクは Glance イメージで、イメージが最初に使用する際に /var/lib/nova/instances/_base にコピーされていた。何故イメージが見つからないのか?私はそのディレクトリをチェックし、イメージがないことを知った。

私は nova データベースを見直し、 nova.instances テーブル中の当該インスタンスのレコードを見た。インスタンスが使用しているイメージは virsh が報告したものと一致した。よって、ここでは矛盾は発見されなかった。

私は Glance をチェックし、問題のイメージがそのユーザの作成したスナップショットであることに注目した。最終的に、それはグッドニュースだった。このユーザが影響を受けた唯一のユーザだった。

最後に、私は StackTack をチェックし、ユーザのイベントを見直した。彼らはいくつかのスナップショットを作ったり消したりしていた-ありそうな操作ではあるが。タイムスタンプが一致しないとはいえ、彼らがインスタンスを起動して、その後スナップショットを削除し、それが何故か /var/lib/nova/instances/_base から削除されたというのが私の結論だった。大した意味は無かったが、それがその時私が得た全てだった。

コンピュートノードがロックアップした原因はハードウェアの問題だったことが判明した。我々はそのハードウェアを DAIR クラウドから取り外し、修理するよう Dell に依頼した。Dell が到着して作業を開始した。何とかかんとか(あるいはタイプミス)で、異なるコンピュートノードを落としてしまい、再起動した。素晴らしい。

そのノードが完全に起動した際、インスタンスが起動した時に何が起こるのかを見るため、私は同じシナリオを実行して、インスタンスを復旧した。インスタンスは全部で4つあった。3つは起動し、1つはエラーになった。このエラーは以前のエラーと同じだった。「unable to find the backing disk.」マジ、何で?

再度、イメージがスナップショットであることが判明した。無事に起動した他の3インスタンスは標準のクラウドイメージであった。これはスナップショットの問題か?それは意味が無かった。

DAIR のアーキテクチャーは /var/lib/nova/instances が共有 NFS マウントであることに注意したい。これは、全てのコンピュートノードがそのディレクトリにアクセスし、その中に _base ディレクトリが含まれることを意味していた。その他の集約化エリアはクラウドコントローラーの /var/log/rsyslog だ。このディレクトリは全コンピュートノードの全ての OpenStack ログが収集されていた。私は、 virsh が報告したファイルに関するエントリがあるのだろうかと思った。

dair-ua-c03/nova.log:Dec 19 12:10:59 dair-ua-c03
2012-12-19 12:10:59 INFO nova.virt.libvirt.imagecache
[-] Removing base file:
/var/lib/nova/instances/_base/7b4783508212f5d242cbf9ff56fb8d33b4ce6166_10

あっはっは!じゃぁ、OpenStack が削除したのか。でも何故?

Essex で、 _base 下の任意のファイルが使用されていないかどうか定期的にチェックして確認する機能が導入された。もしあれば、OpenStack Compute はそのファイルを削除する。このアイデアは問題がないように見え、品質的にも良いようだった。しかし、この機能を有効にすると最終的にどうなるのか?Essex ではこの機能がデフォルトで無効化されていた。そうあるべきであったからだ。これは、 Folsom で有効になることが決定された 。私はそうあるべきとは思わない。何故なら

何かを削除する操作はデフォルトで有効化されるべきではない。

今日、ディスクスペースは安価である。データの復元はそうではない。

次に、DAIR の共有された /var/lib/nova/instances が問題を助長した。全コンピュートノードがこのディレクトリにアクセスするため、全てのコンピュートノードは定期的に _base ディレクトリを見直していた。あるイメージを使用しているインスタンスが1つだけあり、そのインスタンスが存在するノードが数分間ダウンした場合、そのイメージが使用中であるという印を付けられなくなる。それゆえ、イメージは使用中に見えず、削除されてしまったのだ。そのコンピュートノードが復帰した際、そのノード上でホスティングされていたインスタンスは起動できない。

バレンタインデーのコンピュートノード大虐殺

この物語のタイトルは実際の事件よりかなりドラマティックだが、私はタイトル中に「バレンタインデーの大虐殺」を使用する機会が再びあるとは思わない(し望まない)。

この前のバレンタインデーに、クラウド中にあるコンピュートノードが最早動いていないとの警告を受け取った。つまり、

$ openstack compute service list

出力で、この特定のノードの状態が XXX になっていた。

実に奇妙なことだが、私はクラウドコントローラーにログインし、問題のコンピュートノードに ping と SSH の両方を実行できた。通常、この種の警告を受け取ると、コンピュートノードは完全にロックしていてアクセス不可になる。

数分間のトラブル調査の後、以下の詳細が判明した。

  • 最近、あるユーザがそのノード上で CentOS のインスタンスを起動しようとした。

  • このユーザはそのノード(新しいノード)上の唯一のユーザだった。

  • 私が警告を受け取る直前、負荷率は8に急増した。

  • 冗長化された 10Gb ネットワークデバイス(bond0)は DOWN 状態だった。

  • 1Gb NICはまだ生きていて、有効だった。

私は bonding ペアの両方の NIC の状態を確認し、両方ともスイッチポートへの通信ができないことを知った。bond 中の各 NIC が異なるスイッチに接続されていることを知り、私は、各スイッチのスイッチポートが同時に死ぬ可能性はまずないと思った。私は 10Gb デュアルポート NIC が死んで、交換が必要だと結論づけた。私は、そのノードがホスティングされているデータセンターのハードウェアサポート部門に宛てたチケットを作成した。私は、それが新しいノードで、他のインスタンスがまだそのノード上でホスティングされていないことを幸運に思った。

1時間後、私は同じ警告を受信したが、別のコンピュートノードだった。拍手。OK、問題は間違いなく現在進行中だ。元のノードと全く同様に、私は SSH でログインすることが出来た。bond0 NIC は DOWN だったが、1Gb NIC は有効だった。

そして、最も重要なこと。同じユーザが CentOS インスタンスを作成しようとしたばかりだった。何だと?

私はこの時点で完全に混乱した。よって、私はネットワーク管理者に対して、私を助けられるか聞いてみるためメールした。彼は両方のスイッチにログインし、すぐに問題を発見した。そのスイッチは2つのコンピュートノードから来たスパニングツリーパケットを検出し、スパニングツリーループを回避するため、即時にそれらのポートをダウンさせたのだ。

Feb 15 01:40:18 SW-1 Stp: %SPANTREE-4-BLOCK_BPDUGUARD: Received BPDU packet on Port-Channel35 with BPDU guard enabled. Disabling interface. (source mac fa:16:3e:24:e7:22)
Feb 15 01:40:18 SW-1 Ebra: %ETH-4-ERRDISABLE: bpduguard error detected on Port-Channel35.
Feb 15 01:40:18 SW-1 Mlag: %MLAG-4-INTF_INACTIVE_LOCAL: Local interface Port-Channel35 is link down. MLAG 35 is inactive.
Feb 15 01:40:18 SW-1 Ebra: %LINEPROTO-5-UPDOWN: Line protocol on Interface Port-Channel35 (Server35), changed state to down
Feb 15 01:40:19 SW-1 Stp: %SPANTREE-6-INTERFACE_DEL: Interface Port-Channel35 has been removed from instance MST0
Feb 15 01:40:19 SW-1 Ebra: %LINEPROTO-5-UPDOWN: Line protocol on Interface Ethernet35 (Server35), changed state to down

彼はスイッチポートを再度有効にしたところ、2つのコンピュートノードは即時に復活した。

不幸にも、この話にはエンディングがない…我々は、なぜ CentOS イメージがスパニングツリーパケットを送信し始める原因をいまだ探している。更に、我々は障害時にスパニングツリーを軽減する正しい方法を調査している。これは誰かが思うより大きな問題だ。スパニングツリーループを防ぐことはスイッチにとって非常に重要であるが、スパニングツリーが起こった際に、コンピュートノード全体がネットワークから切り離されることも大きな問題である。コンピュートノードが 100 インスタンスをホスティングしていて、そのうち1つがスパニングツリーパケットを送信した場合、そのインスタンスは事実上他の 99 インスタンスを DDoS(サービス不能攻撃)したことになる。

これはネットワーク業界で進行中で話題のトピックである。特に仮想マシンと仮想スイッチで発生する。

ウサギの穴に落ちて

稼働中のインスタンスからコンソールログを取得可能なユーザはサポートの恩恵となる。インスタンスの中で何が起こっているのか何度も確認できるし、あなたが悩まずに問題を修正することができる。不幸なことに、過剰な失敗の記録は時々、自らの問題となり得る。

報告が入った。VM の起動が遅いか、全く起動しない。標準のチェック項目は?nagios 上は問題なかったが、RabbitMQ クラスタの現用系に向かうネットワークのみ高負荷を示していた。捜査を開始したが、すぐに RabbitMQ クラスタの別の部分がざるのようにメモリリークを起こしていることを発見した。また警報か?RabbitMQ サーバーの現用系はダウンしようとしていた。接続は待機系にフェイルオーバーした。

この時、我々のコントロールサービスは別のチームによりホスティングされており、我々には現用系サーバー上で何が起こっているのかを調査するための大したデバッグ情報がなく、再起動もできなかった。このチームは警報なしで障害が起こったと連絡してきたが、そのサーバーの再起動を管理していた。1時間後、クラスタは通常状態に復帰し、我々はその日は帰宅した。

翌朝の継続調査は別の同様の障害でいきなり始まった。我々は急いで RabbitMQ サーバーを再起動し、何故 RabbitMQ がそのような過剰なネットワーク負荷に直面しているのかを調べようとした。nova-api のデバッグログを出力することにより、理由はすぐに判明した。tail -f /var/log/nova/nova-api.log は我々が見たこともない速さでスクロールしていた。CTRL+C でコマンドを止め、障害を吐き出していたシステムログの内容をはっきり目にすることが出来た。-我々のユーザの1人のインスタンスからのシステムログだった。

インスタンスIDの発見後、console.log を探すため /var/lib/nova/instances にアクセスした。

adm@cc12:/var/lib/nova/instances/instance-00000e05# wc -l console.log
92890453 console.log
adm@cc12:/var/lib/nova/instances/instance-00000e05# ls -sh console.log
5.5G console.log

思った通り、ユーザはダッシュボード上のコンソールログページを定期的に更新しており、ダッシュボードに向けて5GB のファイルが RabbitMQ クラスタを通過していた。

我々はユーザを呼び、しばらくダッシュボードの更新を止めるよう申し入れた。すると、恐ろしい VM の破壊は止み、彼らは大いに喜んだ。その後、我々はコンソールログのサイズを監視するようになった。

今日に至るまで、この問題 には完全な解決策がないが、我々は次回のサミットの議論に期待している。

Havana 死者の幽霊

台湾の Academia Sinica Grid Computing Centre の Felix Lee さんがこの話を提供してくれました。

RDO リポジトリーを使用して Grizzly から Havana 2013.2-2 に OpenStack を単にアップグレードしました。そして、すべてのものが EC2 API で非常に良く動作していました。

この API は、RunInstances などの特定の EC2 リクエストに対して、高負荷になり、応答が遅くなることに気がつきました。

Havana における /var/log/nova/nova-api.log の出力:

2014-01-10 09:11:45.072 129745 INFO nova.ec2.wsgi.server
[req-84d16d16-3808-426b-b7af-3b90a11b83b0
0c6e7dba03c24c6a9bce299747499e8a 7052bd6714e7460caeb16242e68124f9]
117.103.103.29 "GET
/services/Cloud?AWSAccessKeyId=[something]&Action=RunInstances&ClientToken=[something]&ImageId=ami-00000001&InstanceInitiatedShutdownBehavior=terminate...
HTTP/1.1" status: 200 len: 1109 time: 138.5970151

このリクエストは、処理に 2 分以上かかりました。しかし、同じハードウェアとシステム設定を使用している、他の一緒に動いている Grizzly 環境は迅速に実行されました。

Grizzly における /var/log/nova/nova-api.log の出力:

2014-01-08 11:15:15.704 INFO nova.ec2.wsgi.server
[req-ccac9790-3357-4aa8-84bd-cdaab1aa394e
ebbd729575cb404081a45c9ada0849b7 8175953c209044358ab5e0ec19d52c37]
117.103.103.29 "GET
/services/Cloud?AWSAccessKeyId=[something]&Action=RunInstances&ClientToken=[something]&ImageId=ami-00000007&InstanceInitiatedShutdownBehavior=terminate...
HTTP/1.1" status: 200 len: 931 time: 3.9426181

システムリソースを監視しているうちに、EC2 API がこのリクエストを処理している間、メモリー消費量が非常に増えていることに気が付きました。これは、メモリが開放されず、正常に処理されていないと気づきました。API がこれらのいくつかのリクエストを受け取ると、システムがメモリー不足になり、スワップを使い始めるまで、メモリー消費がすぐに大きくなります。各ノードは 48GB メモリーを持ち、"nova-api" プロセスが数分以内にそれらをすべて消費します。これが発生すると、nova-api サービスを再起動するまで、システム全体が使えなくなるほど遅くなります。

そのため、この問題を引き起こしているかもしれない、Havana で EC2 API に行われた変更を自分で探しはじめました。これはバグなのか、回避策が必要となる通常の動作なのか?

nova (OpenStack Compute) のコードを深堀りすると、私のシステムに影響を与える可能性がある 2 つの領域を api/ec2/cloud.py で見つけました。

instances = self.compute_api.get_all(context,
                                     search_opts=search_opts,
                                     sort_dir='asc')

sys_metas = self.compute_api.get_all_system_metadata(
    context, search_filts=[{'key': ['EC2_client_token']},
                           {'value': [client_token]}])

データベースに 100 万以上のメタデータおよび 300,000 インスタンスのレコードが「削除済み」または「エラー」状態で含まれていました。MySQL クライアントを使用して、まずバックアップを取得し、データベースをクリーンアップし、いくつか削除を実行することにしました。例えば、以下の SQL コマンドを実行して、1 年以上の間に削除されたインスタンスの行を削除しました。

mysql> delete from nova.instances where deleted=1 and terminated_at < (NOW() - INTERVAL 1 YEAR);

古いレコードの削除後、パフォーマンスが大幅に向上しました。新しい環境は順調に動作しつづけています。