Open vSwitchのVRRP(L3HA)で高可用性を実現する!


目次

みなさん、こんにちは。コンテンツ・メディア第1事業部インフラ担当の藤本佳世です。

今回もOpenStackの続き、【Open vSwitchのVRRP(L3HA)で高可用性を実現する!】についてお話しします。

前回の記事はこちら

VRRPとは

VRRP(Virtual Router Redundancy Protocol)とは、ルータの冗長化をサポートするプロトコルです。

フリューでは、OpenStackで立ち上げた仮想インスタンスに接続する際に、このVRRP機能を採用しています。

仮想インスタンスへはFloatingIPでssh接続しています。

その通信が、Neutron(networknode)サーバでプライベートIPアドレスにNAT変換され、仮想インスタンスに接続されます。この処理を行うNeutron(networknode)サーバ2台をVRRP構成にすることで、master側のサーバに障害が発生した場合、すぐにstandby側のもう1台のサーバに自動的に処理を切り替えることができます。

<イメージ図>

openstack_vrrp

構築について

公式ドキュメントを参考に構築を進めました。

ネットワークの知識が必要なので、慣れないうちは苦労するかもしれません。

サーバ構成について

コンポーネント ノード
サーバ1 Keystone/Horizon/Nova/Cinder/Glance/Neutron ※1 MySQL/Memcached/RabbitMQ ※2 Heartbeat controllernode
サーバ2 Keystone/Horizon/Nova/Cinder/Glance/Neutron ※1 MySQL/Memcached/RabbitMQ ※2 Heartbeat controllernode
サーバ3 Nova/Cinder/Neutron computenode/storagenode
サーバ4 Nova/Cinder/Neutron computenode/storagenode
サーバ5 Nova/Cinder/Neutron computenode/storagenode
サーバ6 Nova/Cinder/Neutron computenode/storagenode
サーバ7 Neutron networknode
サーバ8 Neutron networknode

ネットワーク作成について

ネットワーク名 ext-net80 vxlan-net80
プロジェクト admin service
ネットワーク種別 flat vxlan
外部ネットワーク external1
割り当てサブネット ext-subnet80 10.0.80.0/24 vxlan-subnet80 192.168.80.0/24
Gateway 10.0.80.1 192.168.80.1

※1ネットワークセグメントのみの情報です。実際には同じような構成で3パターン作成しました。

設定内容

各ノードに対して設定を行います。ポイントとなる部分を書き出してみました。

用語の説明

NAT変換 IPアドレスを変換する技術のこと
VXLAN L3ネットワーク上に論理的なL2ネットワークを構築するトンネリングプロトコルのこと
ML2プラグイン OpenStack Networking で、複雑な実世界のデータセンターで使われている様々な L2 ネットワーク技術を同時に利用できるようにするフレームワークのこと
GRE ML2 がサポートするネットワークセグメントタイプの一種
Flat ML2 がサポートするネットワークセグメントタイプの一種
DHCP IPアドレスなどを自動的に割り当てる仕組みのこと

controllernode

共通のオプションを設定します。

[DEFAULT]
verbose = True
core_plugin = ml2
service_plugins = router
allow_overlapping_ips = True
router_distributed = False
l3_ha = True
l3_ha_net_cidr = 169.254.192.0/18
max_l3_agents_per_router = 3
min_l3_agents_per_router = 2
dhcp_agents_per_network = 2

ML2プラグインを設定します。

[ml2]
type_drivers = flat,vlan,gre,vxlan    
tenant_network_types = vlan,gre,vxlan 
mechanism_drivers = openvswitch      ←opnevswitchを指定
 
[ml2_type_flat]
flat_networks = external1,external2,external3
 
[ml2_type_vlan]
network_vlan_ranges = external1,external2,external3,vlan:1000:2999
 
[ml2_type_gre]
tunnel_id_ranges = 1:1000           ←お使いの環境に応じたGREの最小値:最大値に置き換えて下さい
 
[ml2_type_vxlan]
vni_ranges = 1000:2000           ←お使いの環境に応じたVXLAN IDの最小値:最大値に置き換えて下さい  
vxlan_group = 239.1.1.1
 
[securitygroup]
firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver
enable_security_group = True
enable_ipset = True

networknode

Open vSwitchエージェントを設定します。

[ovs]
local_ip = XX.XX.XX.XX     ←GRE/VXLAN プロジェクトネットワークを扱うインターフェースのIPアドレスに置き換えて下さい 
bridge_mappings = vlan:br-vlan,external1:br-ex1,external2:br-ex2,external3:br-ex3
 
[agent]
tunnel_types = gre,vxlan
l2_population = False
 
[securitygroup]
firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver
enable_security_group = True
enable_ipset = True

L3エージェントの設定します。

[DEFAULT]
verbose = True
interface_driver = neutron.agent.linux.interface.OVSInterfaceDriver
use_namespaces = True
external_network_bridge =
router_delete_namespaces = True
agent_mode = legacy
ha_confs_path = $state_path/ha_confs
ha_vrrp_auth_type = PASS
ha_vrrp_auth_password = openstack
ha_vrrp_advert_int = 2

DHCPエージェントを設定します。

[DEFAULT]
verbose = True
interface_driver = neutron.agent.linux.interface.OVSInterfaceDriver
dhcp_driver = neutron.agent.linux.dhcp.Dnsmasq
use_namespaces = True
dhcp_delete_namespaces = True

メタデータエージェントの設定します。

[DEFAULT]
verbose = True
nova_metadata_ip = XX.XX.XX.XX
metadata_proxy_shared_secret = METADATA_SECRET  ←METADATA_SECRETは適切なものに置き換えて下さい

computenode

Open vSwitchエージェントを設定します。

[ovs]
local_ip = XX.XX.XX.XX    ←GRE/VXLAN プロジェクトネットワークを扱うインターフェースのIPアドレスに置き換えて下さい
bridge_mappings = vlan:br-vlan
 
[agent]
tunnel_types = gre,vxlan
l2_population = False
 
[securitygroup]
firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver
enable_security_group = True
enable_ipset = True

ネットワークの作成

次は、ネットワークの作成の手順をご紹介します。 フリューでは、3つのネットワークセグメントが存在し、それぞれ仮想ルータを3台構築しました。

下記の通り、flat外部ネットワークとプロジェクトネットワーク(vxlan)を作成しました。

    <td style="height: 24px; width: 10px;">
      ext-net80
    </td>

    <td style="height: 24px; width: 125px;">
      vxlan-net80
    </td>
  </tr>

  <tr style="height: 24px;">
    <td style="height: 24px; width: 141.917px;">
      <strong>プロジェクト</strong>
    </td>

    <td style="height: 24px; width: 10px;">
      admin
    </td>

    <td style="height: 24px; width: 125px;">
      service
    </td>
  </tr>

  <tr style="height: 24px;">
    <td style="height: 24px; width: 141.917px;">
      <strong>ネットワーク種別</strong>
    </td>

    <td style="height: 24px; width: 10px;">
      flat
    </td>

    <td style="height: 24px; width: 125px;">
      vxlan
    </td>
  </tr>

  <tr style="height: 24px;">
    <td style="height: 24px; width: 141.917px;">
      <strong>外部ネットワーク</strong>
    </td>

    <td style="height: 24px; width: 10px;">
      external1
    </td>

    <td style="height: 24px; width: 125px;">
      ―
    </td>
  </tr>

  <tr style="height: 24px;">
    <td style="height: 24px; width: 141.917px;">
      <strong>割り当てサブネット</strong>
    </td>

    <td style="height: 24px; width: 10px;">
      ext-subnet80  

10.0.80.0/24

    <td style="height: 24px; width: 125px;">
      vxlan-subnet80  

192.168.80.0/24

  <tr style="height: 24px;">
    <td style="height: 24px; width: 141.917px;">
      <strong>Gateway</strong>
    </td>

    <td style="height: 24px; width: 10px;">
      10.0.80.1
    </td>

    <td style="height: 24px; width: 125px;">
      192.168.80.1
    </td>
  </tr>
</table>

<p>
  ※1ネットワークセグメントのみの情報です。実際には同じような構成で3パターン作成しました。
</p>

<h3>
  flat外部ネットワーク作成
</h3>

<ol>
  <li>
    外部ネットワークを作成 ※下記の例では「ext-net80」というネットワーク名で作成しました。 <pre class="lang:default decode:true">neutron net-create ext-net80 --router:external1 True --provider:physical_network external1 --provider:network_type flat</pre>
  </li>

  <li>
    外部ネットワークのサブネットを作成 <pre class="lang:default decode:true">neutron subnet-create ext-net80 10.0.80.0/24 --name ext-subnet80 --allocation-pool start=10.0.80.101,end=10.0.80.200 --disable-dhcp --gateway 10.0.80.1</pre>
  </li>
</ol>

<h3>
  プロジェクトネットワーク(vxlan)作成
</h3>

<ol>
  <li>
    serviceプロジェクトのidを取得  

※ここではすでにserviceプロジェクトが存在することを前提としています。

openstack project show service

+————-+———————————-+ | Field | Value | +————-+———————————-+ | description | Demo Tenant | | enabled | True | | id | 443cd1596b2e46d4996xxxxxxxxxxxxx | | name | service | +————-+———————————-+

  <li>
    ネットワーク作成  

※先ほどとは異なり、network_typeにvxlanを指定します。

neutron net-create vxlan-net80 –tenant-id 443cd1596b2e46d4996xxxxxxxxxxxxx –provider:network_type vxlan

  <li>
    サブネットを作成 <pre class="lang:default decode:true">neutron subnet-create vxlan-net80 192.168.80.0/24 --name vxlan-subnet80 --gateway 192.168.80.1</pre>
  </li>

  <li>
    仮想ルータの作成 <pre class="lang:default decode:true">neutron router-create router80</pre>
  </li>

  <li>
    サブネットを仮想ルータにインターフェースとして接続 <pre class="lang:default decode:true">neutron router-interface-add router80 vxlan-subnet80</pre>
  </li>

  <li>
    ルータに外部ネットワークへのゲートウェイを追加 <pre class="lang:default decode:true">neutron router-gateway-set router80 ext-net80</pre>
  </li>
</ol>

<h2>
  HA確認
</h2>

<ol>
  <li>
    下記のコマンドでVRRP(active,standby)構成になっていることが確認できます。 <pre class="lang:default decode:true" title="router80の場合">$ neutron l3-agent-list-hosting-router router80

+————————————–+———+—————-+——-+———-+ | id | host | admin_state_up | alive | ha_state | +————————————–+———+—————-+——-+———-+ | 71a98e8f-1438-4e9aXXXXXXXXXXXXXXXXXX | サーバ7 | True | :-) | active | | 09a9a76d-d67d-44ebXXXXXXXXXXXXXXXXXX | サーバ8 | True | :-) | standby | +————————————–+———+—————-+——-+———-+

  <li>
    networknodeで、qrouterとqdhcp名前空間の作成を検証します。  

※両方のqrouter名前空間で同じUUIDが使われているはずです。

ip netns
qrouter-7a46dba8-8846-498c-9e10-588664558473

    <pre class="lang:default decode:true " title="networknode2(サーバ8)">ip netns

qrouter-7a46dba8-8846-498c-9e10-588664558473

  <li>
    networknodeでHAの動作確認をします。  

※qrouter 名前空間には ha, qr, qg インターフェースがあります。バックアップノードはqrとqgインターフェースはIPアドレスを持ちません。

ネットワーク名

        <td style="width: 506.183px;">
          169.254.192.0/18 の範囲の一意な IP アドレスを持つ
        </td>
      </tr>

      <tr>
        <td style="width: 161px;">
          qr インターフェース
        </td>

        <td style="width: 506.183px;">
          プロジェクトネットワークのゲートウェイ IP アドレスを持つ
        </td>
      </tr>

      <tr>
        <td style="width: 161px;">
          qg インターフェース
        </td>

        <td style="width: 506.183px;">
          外部ネットワーク上のプロジェクトルーターの IP アドレスを持つ
        </td>
      </tr>
    </table>

    <pre class="lang:default decode:true" title="networknode1(サーバ7)">ip netns exec qrouter-7a46dba8-8846-498c-9e10-588664558473 ip addr show

11: ha-255d2e4b-33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN group default link/ether fa:16:3e:25:05:d7 brd ff:ff:ff:ff:ff:ff inet 169.254.192.118 brd 169.254.255.255 scope global ha-255d2e4b-33 valid_lft forever preferred_lft forever inet6 fe80::f816:3eff:fe25:5d7/64 scope link valid_lft forever preferred_lft forever 12: qr-8de3e172-53: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN group default link/ether fa:16:3e:10:9f:f6 brd ff:ff:ff:ff:ff:ff inet 192.168.1.124 scope global qr-8de3e172-53 valid_lft forever preferred_lft forever inet6 fe80::f816:3eff:fe10:9ff6/64 scope link valid_lft forever preferred_lft forever 13: qg-374587d7-2a: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default link/ether fa:16:3e:82:a0:59 brd ff:ff:ff:ff:ff:ff inet 10.5.80.10124 scope global qg-374587d7-2a valid_lft forever preferred_lft forever inet6 fe80::f816:3eff:fe82:a059/64 scope link valid_lft forever preferred_lft forever

    <pre class="lang:default decode:true " title="networknode2(サーバ8)">ip netns exec qrouter-7a46dba8-8846-498c-9e10-588664558473 ip addr show

11: ha-90d1a59f-b1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN group default link/ether fa:16:3e:ae:3b:22 brd ff:ff:ff:ff:ff:ff inet 169.254.192.218 brd 169.254.255.255 scope global ha-90d1a59f-b1 valid_lft forever preferred_lft forever inet6 fe80::f816:3eff:feae:3b22/64 scope link valid_lft forever preferred_lft forever 12: qr-8de3e172-53: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN group default link/ether fa:16:3e:10:9f:f6 brd ff:ff:ff:ff:ff:ff inet6 fe80::f816:3eff:fe10:9ff6/64 scope link valid_lft forever preferred_lft forever 13: qg-374587d7-2a: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default link/ether fa:16:3e:82:a0:59 brd ff:ff:ff:ff:ff:ff inet6 fe80::f816:3eff:fe82:a059/64 scope link valid_lft forever preferred_lft forever

  <li>
    Networknodeで、マスターノードの HA インターフェースの IP アドレスから VRRP 通信が行われていることを確認します。 <pre class="lang:default decode:true">tcpdump -lnpi eth1

16:50:16.857294 IP 169.254.192.1 > 224.0.0.18: VRRPv2, Advertisement, vrid 1, prio 50, authtype simple, intvl 2s, length 20 16:50:18.858436 IP 169.254.192.1 > 224.0.0.18: VRRPv2, Advertisement, vrid 1, prio 50, authtype simple, intvl 2s, length 20 16:50:20.859677 IP 169.254.192.1 > 224.0.0.18: VRRPv2, Advertisement, vrid 1, prio 50, authtype simple, intvl 2s, length 20

冗長化することは、どんなシステムでも重要視される部分ですね。

最後に

今回初めてVRRPという単語を聞いた私にとっては、かなり苦戦する部分ではありましたが、何とか構築することができました。ネットワーク知識が必要となりますが、少しでも構築の参考になれば嬉しいです。


ha インターフェース