第1章 ライブインスタンスの移行方法

本項には、共有ストレージまたはブロックベースの移行を使用してライブ (実行中) インスタンスを移行する方法について記載します。ライブマイグレーションは、ダウンタイムがほぼないため、実稼動環境に有用です。

本項の手順では、コントローラーノード 1 つと、コンピュートノード 2 つを使用し、この 2 つのコンピュートノード間でインスタンスを移行します。

1.1. 前提条件

Red Hat OpenStack Platform は、2 種類のライブマイグレーションをサポートします。それぞれに独自の要件があります。

共有ストレージ
共有ストレージの場合には、インスタンスは両コンピュートノードからアクセス可能なストレージを使用して移行されます。移行元/移行先のハイパーバイザーのいずれにおいても、ストレージには、分散ファイルシステムを使用する必要があります (例: NFS または Red Hat Storage)。OpenStack Block Storage ボリューム (ボリュームベースのインスタンス) も共有ストレージを使用することができます。以下の手順では、NFS 共有ストレージを設定するステップを説明します。
ブロックベース
ブロックベースの移行は、移行元のホストから移行先に仮想マシンのイメージ全体を移動するため、所要時間が長くなりますが、この種類の移行ではバックエンドの分散ファイルシステムは必要ありません。各コンピュートノードの設定の際には、各ノードがホストするインスタンスを格納するのに十分なディスクを使用する必要があります。
警告

現在、CPU ピニングを使用するように設定されているインスタンスは移行できません。この問題に関する詳しい情報は、「Instance migration fails when using cpu-pinning from a numa-cell and flavor-property "hw:cpu_policy=dedicated"」のソリューションを参照してください。

1.1.1. 一般要件

両タイプの移行における一般的な要件は以下のとおりです。

  • 管理者として、クラウド環境にコマンドラインからアクセスできること (以下の手順はすべてコマンドラインで実行します)。各種コマンドを実行するには、まずユーザーの認証変数を読み込みます。

    # source ~/keystonerc_admin
  • 移行元/移行先の両ノードは、同じサブネットに配置され、同じプロセッサータイプを使用する必要があります。
  • コンピュートサーバー (コントローラーおよびノード) はすべて、相互で名前を解決できる必要があります。
  • Compute サービスおよび libvirt ユーザーの UID および GID はコンピュートノード間で同一でなければなりません。
  • コンピュートノードでは、libvirt と KVM を使用する必要があります。

1.1.2. マルチパス機能の要件

マルチパス機能が設定されたインスタンスを移行する場合は、移行元と移行先のノードでマルチパスデバイスの名前が同じである必要があります。移行先のノードで、インスタンスがマルチパスデバイスの名前を解決できない場合には、移行が失敗します。

移行元ノードと移行先ノードの両方でデバイス WWID の使用を強制することで、一貫性のあるマルチパスデバイス名を指定することができます。これには、移行先/移行元の両ノードで以下のコマンドを実行して ユーザーフレンドリーな名前 を無効にし、multipathd を再起動する必要があります。

# mpathconf --enable --user_friendly_names n
# systemctl restart multipathd

詳しい情報は、『DM Multipath ガイド』の「クラスター内では整合性のあるマルチパスデバイス名を維持する」を参照してください。

1.2. 移行の設定

以下の設定を行ってから、ライブインスタンスを移行するようにしてください。

  • ノード間で libvirt がセキュアに送信できることを確認します。
  • 共有ストレージを使用している場合は、全ノードへのアクセスと共有ストレージを設定します。
  • ブロックベースの移行を使用する場合は、全ノードへのアクセスとローカルディレクトリーを設定します。

1.2.1. セキュアな Libvirt の設定

TCP 呼び出しを使用して、移行を行います。libvirt を正しく設定することで、ノード間の TCP 経由のリモート呼び出しをセキュアに行うことができます。ただし、これには複数の方法があり、細心の注意を払って行う必要があります。

通常ライブマイグレーションに使用される TCP 経由でのリモートアクセスには、3 つのセキュアなオプションがあります。以下の設定の libvirtd TCP ソケットを使用します。

  • 暗号化には TLS、認証には X.509 クライアント証明書
  • 認証および暗号化には GSSAPI/Kerberos
  • 暗号化には TLS、認証には Kerberos
注記

SSH トンネリングも可能ですが、通常、静的 (コールド) マイグレーションにのみ使用されます。

環境内の全コンピュートノードで以下の手順を行います。

  1. 適切なストラテジーを決定して、その設定を行う際には、ネットワーク管理者に問い合わせてください (『Red Hat Enterprise Linux 7 仮想化の導入および管理ガイド』の libvirt のドキュメントも参照してください)。
  2. ストラテジーに応じて、/etc/libvirt/libvirtd.conf ファイルの以下のパラメーターを更新してください。

    1. 暗号化には TLS、認証には X.509 クライアント証明書

      listen_tls = 1
      listen_tcp = 0
      auth_tls = "none"
      tls_no_verify_certificate = 0
      tls_allowed_dn_list = ["distinguished name pattern"]

      distinguished name pattern は、サーバー向けに発行した証明書と一致する 1 つまたは複数のパターンに置き換えます (例: C=GB,ST=London,L=London,O=Red Hat,CN=*)。複数の識別名パターンを指定する場合には、コンマで区切ります。詳しい情報は、「TLS と SSL 経由のリモート管理」を参照してください。

    2. 認証および暗号化には GSSAPI/Kerberos

      listen_tls = 0
      listen_tcp = 1
      auth_tcp = "sasl"
      sasl_allowed_username_list = ["Kerberos principal name pattern"]

      Kerberos principal name pattern は、サーバー向けに発行した Kerberos チケットと一致するパターンに置き換えます (例: libvirt/*.example.com@EXAMPLE.COM)。詳しい情報は「Using Kerberos」を参照してください。

    3. 暗号化には TLS、認証には Kerberos

      listen_tls = 1
      listen_tcp = 0
      auth_tls = "sasl"
      sasl_allowed_username_list = ["Kerberos principal name pattern"]

      同様に、Kerberos principal name pattern は、サーバー向けに発行した Kerberos チケットと一致するパターンに置き換えます。

  3. /etc/sysconfig/libvirtd ファイルを編集して、以下の行を追記します。

    LIBVIRTD_ARGS="--listen"
  4. 決定したストラテジーに合わせて、/etc/nova/nova.conf のアクセス URI の文字列を更新します。

    live_migration_uri=qemu+ACCESSTYPE://USER@%s/system

    ここで、

    • ACCESSTYPEtcp (暗号化なし) または tls (暗号化あり) に指定することができます。
    • USER はコンピュートのユーザーを指定します (ファイルパーミッションが適切に設定されるようにします)。問題が発生した場合は、'%s' (root ユーザーにデフォルト設定) のみを使用してみてください。

      例: TLS の使用
      live_migration_uri=qemu+tls://nova@%s/system
  5. 設定が完了したら libvirt を再起動します。

    # systemctl restart libvirtd.service

1.2.2. NFS 共有ストレージの設定

以下の共有ストレージの手順 (ブロックベースの移行では必要なし) では、Compute サービスのインスタンスディレクトリーを 2 つのノードにエクスポートし、ノードがアクセスできることを確認します。ディレクトリーのパスは、/etc/nova/nova.conf ファイルの state_path および instances_path パラメーターで設定されます。

以下の手順では、デフォルトのディレクトリーパス /var/lib/nova/instances を使用します。

  1. コントローラーホスト上で以下を実行します。

    1. NFS サーバーをすでに実行中でない限り、以下のパッケージをインストールする必要があります。

      # yum install nfs-utils
    2. /etc/sysconfig/nfs を更新して、NFS サーバーサービスの固定ポートを設定します。

      LOCKD_TCPPORT=32803
      LOCKD_UDPPORT=32769
    3. ファイアウォールトラフィックを更新して、NFS 通信を許可します。

      # iptables -v -I NFS -p tcp --dport 32803 -j ACCEPT
      # iptables -v -I NFS -p udp --dport 32769 -j ACCEPT
      # iptables -v -I NFS -p tcp --dport 111 -j ACCEPT
      # iptables -v -I NFS -p tcp --dport 2049 -j ACCEPT
      # iptables -v -I INPUT 1 -s 0.0.0.0/0 -p tcp -m state --state NEW,RELATED,ESTABLISHED -m tcp --dport 2049 -j ACCEPT
      # iptables -v -I OUTPUT 1 -d 0.0.0.0/0 -p tcp -m state --state RELATED,ESTABLISHED -m tcp --sport 2049 -j ACCEPT
    4. 以下を /etc/group ファイルに追加します。

      nova:x:162:nova
    5. 以下を /etc/passwd ファイルに追加します。

      nova:x:162:162:OpenStack Nova Daemons:/var/lib/nova:/sbin/nologin
    6. ディレクトリーを作成して、Compute サービスのユーザーの読み取り/書き込み権限が設定されていることを確認します (このユーザーはコントローラーおよび各ノードで同じである必要があることを念頭に置いてください)。以下のコマンドでは、Compute サービスのユーザーが nova であることが前提です。

      # mkdir -p /var/lib/nova/instances
      # chown nova:nova /var/lib/nova/instances
      # chmod 775 /var/lib/nova/instances
    7. 以下の行を /etc/exports ファイルに追加します。computeNode1_IP および computeNode2_IP は、2 つのコンピュートノードの IP アドレスに置き換えます。

      /var/lib/nova/instances computeNode1_IP(rw,sync,fsid=0,no_root_squash)
      /var/lib/nova/instances computeNode2_IP(rw,sync,fsid=0,no_root_squash)
    8. NFS サービスを起動/有効化して、iptables を再起動します。

      # systemctl start nfs-server.service
      # systemctl enable nfs-server.service
      # systemctl restart iptables.service
    9. /var/lib/nova/instances ディレクトリーをコンピュートノードにエクスポートします。

      # exportfs -avr
  2. 各コンピュートノードで以下を実行します。

    1. 必要なリモートパッケージをインストールします (インストール済みでない場合)。

      # yum install iptables openstack-utils openstack-nova-novncproxy -y
    2. NFS クライアントとして機能するように、rpcbind サービスを起動します。

      # systemctl start rpcbind.service
    3. 以下を /etc/group ファイルに追加します。

      nova:x:162:nova
    4. 以下を /etc/passwd ファイルに追加します。

      nova:x:162:162:OpenStack Nova Daemons:/var/lib/nova:/sbin/nologin
    5. ディレクトリーを作成して、パーミッションを変更します。

      # mkdir -p /var/lib/nova/instances
      # chown nova:nova /var/lib/nova/instances
      # chmod 775 /var/lib/nova/instances
    6. コントローラーのインスタンスディレクトリーをマウントします。controllerNode_IP は、コントローラーの IP アドレスに置き換えます。

      # mount -t nfs controllerNode_IP:/var/lib/nova/instances /var/lib/nova/instances
    7. ファイアウォールおよびネットワークトラフィックを設定します。libvirt がノード間で通信できるように、ファイアウォールを設定する必要があります (TCP は 16509、TLS は 16514)。可能であれば、お使いのコンピュートノードだけに、ポートへのリモートアクセスを制限します。トンネリングを使用しない限り、エフェメラルポート (49152 から 49215) も開放する必要があります。

      例: TCP の使用
      # iptables -v -I INPUT 1 -p tcp --dport 16509 -j ACCEPT
      # iptables -v -I INPUT 1 -p tcp --dport 16514 -j ACCEPT
      # iptables -v -I INPUT -p tcp --dport 49152:49261 -j ACCEPT
      # iptables -v -N NFS; iptables -v -I INPUT -j NFS
    8. iptables を保存して、SELinux により NFS アクセスが妨害されないようにします。

      # service iptables save
      # setsebool -P virt_use_nfs 1
    9. ノードでインスタンスディレクトリーを表示できることを確認します。

      # ls -ld /var/lib/nova/instances
      drwxr-xr-x. 9 nova nova 4096 Nov  5 20:37 /var/lib/nova/instances
      注記

      以下のコマンドを実行して、全マウント済みデバイスを確認することもできます。

      # df -k
    10. /etc/libvirt/qemu.conf ファイルで、qemu 設定を更新します。

      user="root"
      group="root"
      vnc_listen="0.0.0.0"
    11. Compute サービスの設定を更新します。

      # openstack-config --set /etc/nova/nova.conf DEFAULT instances_path /var/lib/nova/instances
      # openstack-config --set /etc/nova/nova.conf DEFAULT novncproxy_base_url http://controllerNode_IP:6080/vnc_auto.html
      # openstack-config --set /etc/nova/nova.conf DEFAULT vncserver_listen 0.0.0.0
      # openstack-config --set /etc/nova/nova.conf DEFAULT live_migration_flag VIR_MIGRATE_UNDEFINE_SOURCE,VIR_MIGRATE_PEER2PEER,VIR_MIGRATE_LIVE

      サービスを再起動します。

      # openstack-service restart
  3. コントローラーホスト上で以下を実行します。

    1. OpenStack パッケージをインストールします。

      # yum install openstack-utils openstack-nova-novncproxy -y
    2. Compute 設定を更新して、サービスを再起動します。

      # openstack-config --set /etc/nova/nova.conf DEFAULT vncserver_listen 0.0.0.0
      # openstack-service restart

1.2.3. ブロック移行の設定

ブロック移行を行う場合は、共有ストレージを使用できませんが、各種サービスがリモート通信用に設定されており、ローカルの /instances のディレクトリーに正しいパーミッションが設定されている必要があります。

以下の手順では、デフォルトのディレクトリーパス /var/lib/nova/instances を使用します。

  1. 各コンピュートノードで以下を実行します。

    1. 必要なリモートパッケージをインストールします (インストール済みでない場合)。

      # yum install iptables openstack-utils openstack-nova-novncproxy -y
    2. インスタンスに使用するディレクトリーを作成します (作成済みでない場合)。

      # mkdir -p /var/lib/nova/instances
    3. 以下を /etc/group ファイルに追加します。

      nova:x:162:nova
    4. 以下を /etc/passwd ファイルに追加します。

      nova:x:162:162:OpenStack Nova Daemons:/var/lib/nova:/sbin/nologin
    5. ディレクトリーのパーミッションを変更します。

      # chown nova:nova /var/lib/nova/instances;chmod 775 /var/lib/nova/instances
    6. ファイアウォールおよびネットワークトラフィックを設定します。libvirt がノード間で通信できるように、ファイアウォールを設定する必要があります (TCP は 16509、TLS は 16514)。可能であれば、お使いのコンピュートノードだけに、ポートへのリモートアクセスを制限します。トンネリングを使用しない限り、エフェメラルポート (49152 から 49215) も開放する必要があります。

      例: TCP の使用
      # iptables -v -I INPUT 1 -p tcp --dport 16509 -j ACCEPT
      # iptables -v -I INPUT 1 -p tcp --dport 16514 -j ACCEPT
      # iptables -v -I INPUT -p tcp --dport 49152:49261 -j ACCEPT
    7. ノードでインスタンスディレクトリーを表示できることを確認します。

      # ls -ld /var/lib/nova/instances
      drwxrwxr-x. 9 nova nova 4096 Nov  5 20:37 /var/lib/nova/instances
    8. /etc/libvirt/qemu.conf ファイルで、qemu 設定を更新します。

      user="root"
      group="root"
      vnc_listen="0.0.0.0"
    9. libvirtd サービスを再起動して、qemu 設定の変更が反映されるようにします。

      # systemctl restart libvirtd
    10. Compute サービスの設定を更新します。

      # openstack-config --set /etc/nova/nova.conf DEFAULT instances_path /var/lib/nova/instances
      # openstack-config --set /etc/nova/nova.conf DEFAULT novncproxy_base_url http://10.64.15.100:6080/vnc_auto.html
      # openstack-config --set /etc/nova/nova.conf DEFAULT vncserver_listen 0.0.0.0
      # openstack-config --set /etc/nova/nova.conf DEFAULT block_migration_flag VIR_MIGRATE_UNDEFINE_SOURCE,VIR_MIGRATE_PEER2PEER,VIR_MIGRATE_LIVE,VIR_MIGRATE_NON_SHARED_INC
    11. サービスを再起動します。

      # systemctl restart iptables.service;
      # openstack-service restart
  2. コントローラーホスト上で以下を実行します。

    1. OpenStack パッケージをインストールします。

      # yum install openstack-utils openstack-nova-novncproxy -y
    2. Compute 設定を更新して、サービスを再起動します。

      # openstack-config --set /etc/nova/nova.conf DEFAULT vncserver_listen 0.0.0.0
      # openstack-service restart

1.3. ライブインスタンスの移行

  1. インスタンスの一覧を表示して、対象のインスタンスが表示されていることを確認します。

    # nova list
  2. どのノードでインスタンスが実行されているかを確認します。

    # nova show DemoInstance
    +--------------------------------------+-----------------------------------+
    | Property                             | Value                             |
    +--------------------------------------+-----------------------------------+
    | ...                                  |                                   |
    | OS-EXT-SRV-ATTR:host                 | OpenStack2                        |
    | OS-EXT-SRV-ATTR:hypervisor_hostname  | OpenStack2                        |
    | ...                                  |                                   |
  3. 利用可能な移行先ノードの一覧を表示します。

    # nova service-list
    +------------------+------------+----------+---------+-------+-
    | Binary           | Host       | Zone     | Status  | State |
    +------------------+------------+----------+---------+-------+-
    | nova-compute     | OpenStack2 | nova     | enabled | up    |
    | nova-compute     | OpenStack3 | nova     | enabled | up    |
    | ...              |            |          |         |       |
  4. 移行先を選択して、十分なリソースがあることを確認します。

    # nova host-describe OpenStack3
    +------------+------------------------------+-----+-----------+---------+
    | HOST       | PROJECT                      | cpu | memory_mb | disk_gb |
    +------------+------------------------------+-----+-----------+---------+
    | OpenStack3 | (total)                      | 4   | 7707      | 49      |
    | OpenStack3 | (used_now)                   | 0   | 512       | 0       |
    | OpenStack3 | (used_max)                   | 0   | 0         | 0       |
    +------------+------------------------------+-----+-----------+---------+
  5. インスタンスを移行します。

    共有ストレージでの移行
    # nova live-migration DemoInstance OpenStack3
    ブロックとしての移行
    # nova live-migration --block-migrate DemoInstance OpenStack3
    警告

    インスタンスの移行は、使用率が低い時に行うようにしてください。ゲストオペレーティングシステムがディスク上のブロックに書き込む速度が、ブロックの移行速度よりも早い場合には、移行は完了されません。

  6. インスタンスのホストをチェックして、移行が完了したかどうかを確認します。

    # nova show DemoInstance
    +--------------------------------------+------------------------------------------------+
    | Property                             | Value                                          |
    +--------------------------------------+------------------------------------------------+
    | OS-DCF:diskConfig                    | AUTO                                           |
    | OS-EXT-AZ:availability_zone          | nova                                           |
    | OS-EXT-SRV-ATTR:host                 | OpenStack3                                     |
    | OS-EXT-SRV-ATTR:hypervisor_hostname  | OpenStack3                                     |
    ....
    注記

    トラブルシューティングを行うには、(移行元/移行先両方で) /var/log/nova/ にある以下のログファイルを参照してください。

    • nova-api.log
    • nova-compute.log
    • nova-conductor.log
    • nova-scheduler.log

1.4. ライブマイグレーションの制限事項

ライブマイグレーションの準備および実行時に考慮すべき制限事項が複数あります。

ライブマイグレーションを実行中の仮想マシンでの操作はできません。

ただし、ソースのコンピュートノードでは virsh を使用して、以下のような仮想マシンとの対話は可能です。

  • ライブマイグレーションの現在の状況を表示します。

    # virsh domjobinfo domain
    Time elapsed 110110 ms
    Data processed 100.500 GiB
    Data remaining 25.500 GiB
    ...[output truncated]...

    domain は、名前、移行元の仮想マシンに割り当てられた数字 ID または UUID に置き換えます。

  • 移行をキャンセルします。

    # virsh domjobabort domain
  • 仮想マシンを一時停止します。

    # virsh suspend domain
メモリーの負荷が大きい仮想マシンをライブマイグレーションするのは困難です。
  • 最大ダウンタイム (ミリ秒単位) を設定します。ライブマイグレーションに対してダウンタイムを設定するには、libvirt を使用します。
# virsh migrate-setmaxdowntime domain time_in_milliseconds
  • QEMU によりライブマイグレーションが進行中でないと判断された場合に、自動的にメモリーの書き込み速度を 25% まで落とします。この設定には、live_migration_flag オプションの引数の中に VIR_MIGRATE_AUTO_CONVERGE を含めてください。以下のコマンドを実行してこのオプションがアンコメントして、この引数を更新します。

    # sed -i 's/^#live_migration_flag/live_migration_flag/' /etc/nova/nova.conf
    # openstack-config --list --set /etc/nova/nova.conf libvirt live_migration_flag VIR_MIGRATE_AUTO_CONVERGE
ライブマイグレーションにより、過剰なネットワークトラフィックが発生します。

ライブマイグレーションがフルスピードで実行されると、メッセージキューなど、同じネットワーク上のサービスに悪影響を及ぼす可能性があります。最大速度を下げて設定するには、以下のコマンドを使用します。

# virsh migrate-setspeed domain speed_in_MBps

または、事前に任意の速度 (MBps 単位) で設定してください。以下に例を示します。

# openstack-config --set /etc/nova/nova.conf libvirt live_migration_bandwidth 50

他にネットワークトラフィック軽減するには、送信ページと更新ページの差分のみを取り、移行先に圧縮を適用する XBZRLE 圧縮を使用する方法があります。この機能を有効にするには、live_migration_flag の引数に VIR_MIGRATE_COMPRESSED を含めるようにしてください。今回も、このオプションは必ずコメント解除してください。以下のコマンドを実行して、設定を行います。

# sed -i 's/^#live_migration_flag/live_migration_flag/' /etc/nova/nova.conf
# openstack-config --list --set /etc/nova/nova.conf libvirt live_migration_flag VIR_MIGRATE_COMPRESSED

最後に、ライブマイグレーション専用のネットワークを使用するのも 1 つのオプションです。このソリューションを採用する場合には、まず以下のコマンドを実行して、live_migration_uri オプション内のホスト名のテンプレートに -lm サフィックスを追加します。

# openstack-config --set /etc/nova/nova.conf libvirt live_migration_uri qemu+tcp://nova@%s-lm/system

次に、DNS サーバーにより、このサフィックスが追加されたホスト名が、専用ネットワークの IP アドレスに対して解決されていることを確認します。

デフォルトでは、ターゲットノードがサポートする CPU 命令がソースノードより少ない場合には、ライブマイグレーションは実行できません。

このようなターゲットに対してライブマイグレーションを実行する必要がある場合には、/etc/nova/nova.conf ファイルの以下のオプションを使用します。

cpu_mode = custom
cpu_model = model

model は、/usr/share/libvirt/cpu_map.xml ファイルで定義された、対応の CPU モデルの 1 つに置き換えます。

ライブマイグレーションでは、メモリーのオーバーサブスクリプションは使用しません。
スケジューラーは、コンピューターノードから報告されたメモリー量を ram_allocation_ratio で乗算します。たとえば、メモリー量が 2 GB で、ram_allocation_ratio2 に設定されている場合は、スケジューラーは、メモリーが 4 GB と報告してしまいます。この問題を軽減するには、コンピュートノード自体に使用可能なメモリー量を定義する、reserved_host_memory_mb を負の値に設定します。これにより、この値は使用可能なメモリーから減算されるため、コンピュートノードは実際の空きメモリーよりも多い量を報告し、スケジューラーとコンダクターはどれだけのメモリーオーバーサブスクリプションを使用するのかが分かります。