OpenStack neutronのVLAN aware VMsとGet me a networkを使ってみた

  • 7
    いいね
  • 0
    コメント

Fujitsu Advent CalenderおよびOpenStack Advent Calenderの記事として使われています。
この記事は個人の見解であり、所属する会社、組織を代表するものではありません。また、間違い等ありましたら指摘していただけると幸いです。

はじめに

本記事はOpenStack Neutronの以下の機能を実際に使ってみながら
ほんのり調べてまとめたものです。

  • VLAN aware VMs1
  • Get me a network2

結論からいうと、どちらの機能も問題なく動作しました。
その際のログや内部構造などに興味があればスクロールしてみてください。
どんな機能なのかパッと知りたい方は、以下のセクション名をクリックしてください。
(さっそく下に答えが見えていますが)

  • VLAN aware VMsとは
  • Get me a networkとは

VLAN aware VMsとは

これはVMインスタンスに対して、単一のvNICを使って複数のVLANタグを引き込めるようにする機能です。

  • 従来VLANタグはVMインスタンスに到達する前にOVS(br-int)で外されていたため、VM側に引き込むことができませんでした(br-int内で内部用のport-VLANが設定されていただけ)
  • 複数のnetworkをVMインスタンスに接続するためにはその都度vNICを追加(hot attach)する必要があり、スケーラビリティに課題がありました。

本機能が搭載されたことにより

  • VM内に複数のコンテナを搭載して、それぞれのコンテナを独立したnetworkにつなげたい。
  • VMをルータとして動かす

などが可能になります。

環境構築

時間がなかったので devstackを用意しました。3
今回使ったマシン(VM)のスペックは以下:

  • OS
$ lsb_release -a

No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 16.04.1 LTS
Release:        16.04
Codename:       xenial
  • CPU: 2cores
  • メモリ: 4GB4
  • HDD: 30GB
  • その他必要なこと

    1. gitとopenvswitchをインストールしておく

      sudo apt install git openvswitch-switch
      
    2. sudo権限を持ったstackユーザを作っておく

      sudo adduser stack
      sudo gpasswd -a stack sudo
      

devstack環境構築:

  1. stackユーザでログイン
  2. devstack を git clone

    git clone https://github.com/openstack-dev/devstack.git
    
  3. devstack/local.confを作成。以下のように編集する

    devstack.local.conf
    [[local|localrc]]
    SERVICE_TOKEN=stack
    ADMIN_PASSWORD=stack
    DATABASE_PASSWORD=stack
    RABBIT_PASSWORD=stack
    SERVICE_PASSWORD=$ADMIN_PASSWORD
    LOGFILE=$DEST/logs/stack.sh.log
    LOGDAYS=2
    # 不要なので disableに
    disable_service n-net
    disable_service tempest
    # これが今回の要となるサービス
    enable_service q-trunk
    # Neutron系のサービス
    enable_service q-svc
    enable_service q-meta
    enable_service q-l3
    enable_service q-dhcp
    enable_service q-agt
    # VLANを使う設定
    Q_PLUGIN=ml2
    Q_ML2_TENANT_NETWORK_TYPE=vlan
    ENABLE_TENANT_VLANS=True
    PHYSICAL_NETWORK=physnet
    ML2_VLAN_RANGES=physnet:1000:2000
    OVS_PHYSICAL_BRIDGE=br-eth1
    OVS_BRIDGE_MAPPINGS=public:br-ex,physnet:br-eth1
    
  4. local.confに定義した OVS_PHYSICAL_BRIDGEと同じOVSを事前に作成しておく

    sudo ovs-vsctl add-br br-eth1
    
  5. devstackを実行

    ./stack.sh
    
  6. 成功すると下記が出力される

    =========================
    DevStack Component Timing
    =========================
    Total runtime         937
    run_process            61
    test_with_retry         5
    apt-get-update          4
    pip_install           140
    restart_apache_server  13
    wait_for_service       18
    apt-get                 7
    =========================
    This is your host IP address: 192.168.122.178
    This is your host IPv6 address: ::1
    Horizon is now available at http://192.168.122.178/dashboard
    Keystone is serving at http://192.168.122.178/identity/
    The default users are: admin and demo
    The password: stack
    
  7. trunk(VLAN aware VMs)の機能が有効になっているか確認

    $ openstack extension list --network | grep trunk
    
    • trunkサービスが有効になっていないようです。(local.confの定義不足?)
  8. trunkサービスを(手動で)有効化するため、neutron.confを編集

    /etc/neutron/neutron.conf
    -service_plugins = neutron.services.l3_router.l3_router_plugin.L3RouterPlugin
    +service_plugins = trunk,neutron.services.l3_router.l3_router_plugin.L3RouterPlugin
    
  9. q-svc(neutron-server)を再起動

    • screen -rq-svcのセッションに入ってシグナルを入れて 再起動(コマンドを再実行)
  10. 再度コマンド実行。 trunkおよびtrunk-detailsが見つかれば成功

    $ openstack extension list --network | grep trunk
    | Trunk port details                            | trunk-details             | Expose trunk port details                                                                                                                                |
    | Trunk Extension                               | trunk                     | Provides support for trunk ports
    
  11. 自動作成されたリソース(network/subnet/port/router)を全て削除しておく

調査

3つのnetwork(VLAN)をVMインスタンスに引き込む構成を作ってみました。

                      +--------------------------------------------+
                      |                                            |
                      |            +--------------------+     +----|---+
                      |        +---| network1 VLAN:1031 |-----+        |
 +----------+         |        |   +--------------------+     |        |
 |          |         |        |                              |        |
 |          |   +-----+----+   |   +--------------------+     |        |
 |       vNIC---|  trunk   |---+---| network2 VLAN:1090 |-----+ Router |
 |   VM     |   +----------+   |   +--------------------+     |        |
 | instance |     VLAN:1052    |                              |        |
 +----------+                  |   +--------------------+     |        |
                               +---| network3 VLAN:1048 |-----+        |
                                   +--------------------+     +---------
  1. 4つのnetwork/subnetを作成(一部出力結果は省略)

    neutron net-create net1; neutron subnet-create net1 192.168.10.0/24 --name subnet1
    neutron net-create net2; neutron subnet-create net2 192.168.20.0/24 --name subnet2
    neutron net-create net3; neutron subnet-create net3 192.168.30.0/24 --name subnet3
    neutron net-create trunk; neutron subnet-create trunk 192.168.100.0/24 --name trunk-subnet
    neutron net-list -c name -c provider:network_type -c provider:segmentation_id
    +-------+-----------------------+--------------------------+
    | name  | provider:network_type | provider:segmentation_id |
    +-------+-----------------------+--------------------------+
    | net2  | vlan                  |                     1090 |
    | trunk | vlan                  |                     1052 |
    | net1  | vlan                  |                     1031 |
    | net3  | vlan                  |                     1048 |
    +-------+-----------------------+--------------------------+
    
  2. Routerを作成し、全てのsubnetと接続させておく

    neutron router-create router1
    neutron router-interface-add router1 subnet1
    neutron router-interface-add router1 subnet2
    neutron router-interface-add router1 subnet3
    neutron router-interface-add router1 trunk-subnet
    
  3. 束ねられる側のportを3つ作成(出力結果は省略)

    openstack port create --network net1 port-net1
    openstack port create --network net2 port-net2
    openstack port create --network net3 port-net3
    
  4. trunk用(束ねる側)のport作成(出力結果は省略)

    openstack port create --network trunk my-trunk
    
  5. trunkの定義を作成(my-trunkをtrunk用のportとする)

    openstack network trunk create --parent-port my-trunk trunk-net
    +-----------------+--------------------------------------+
    | Field           | Value                                |
    +-----------------+--------------------------------------+
    | admin_state_up  | UP                                   |
    | created_at      | 2016-12-11T01:18:21Z                 |
    | description     |                                      |
    | id              | 3b9bb4f7-ae10-477e-9178-e870f134e3f0 |
    | name            | trunk-net                            |
    | port_id         | 027824df-170d-4f5b-9619-daa3373255a2 |
    | project_id      | 598bd1c3dd904b4fbe48ac8b05a0cd01     |
    | revision_number | 1                                    |
    | status          | DOWN                                 |
    | sub_ports       |                                      |
    | tenant_id       | 598bd1c3dd904b4fbe48ac8b05a0cd01     |
    | updated_at      | 2016-12-11T01:18:21Z                 |
    +-----------------+--------------------------------------+
    
  6. trunkのsubportとして先ほどの3つのportを設定する

    openstack network trunk set trunk-net \
    --subport port=port-net1,segmentation-type=vlan,segmentation-id=1100 \
    --subport port=port-net2,segmentation-type=vlan,segmentation-id=1200 \
    --subport port=port-net3,segmentation-type=vlan,segmentation-id=1300
    
    • VMインスタンス側に引き込むVLANIDを指定できます。
  7. 現在の設定状況を確認する

    openstack network trunk show trunk-net
    +-----------------+--------------------------------------------------------------------------------------------------+
    | Field           | Value                                                                                            |
    +-----------------+--------------------------------------------------------------------------------------------------+
    | admin_state_up  | UP                                                                                               |
    | created_at      | 2016-12-11T01:18:21Z                                                                             |
    | description     |                                                                                                  |
    | id              | 3b9bb4f7-ae10-477e-9178-e870f134e3f0                                                             |
    | name            | trunk-net                                                                                        |
    | port_id         | 027824df-170d-4f5b-9619-daa3373255a2                                                             |
    | project_id      | 598bd1c3dd904b4fbe48ac8b05a0cd01                                                                 |
    | revision_number | 2                                                                                                |
    | status          | DOWN                                                                                             |
    | sub_ports       | port_id='867d7f27-8da0-4dfc-8d37-82e9f1db5f97', segmentation_id='1100', segmentation_type='vlan' |
    |                 | port_id='dd79c326-2a73-4d66-a6d5-a71aaefd3948', segmentation_id='1200', segmentation_type='vlan' |
    |                 | port_id='e7837b32-b51a-48c8-a4ee-18195b1d336d', segmentation_id='1300', segmentation_type='vlan' |
    | tenant_id       | 598bd1c3dd904b4fbe48ac8b05a0cd01                                                                 |
    | updated_at      | 2016-12-11T01:20:54Z                                                                             |
    +-----------------+--------------------------------------------------------------------------------------------------+
    trunk-netのsubportとして3つのportが登録されているようなので、想定通り
    
  8. VM用のイメージおよび鍵作成

    • デフォルトで入っているcirrosは vconfigが使えませんでした。(パスは通っている...)
    • diskimage-builderでサクッとubuntuのイメージを作ります
    # diskimage-builderのインストール
    sudo pip install diskimage-builder
    export DIB_DEV_USER_USERNAME='ubuntu'
    export DIB_DEV_USER_PASSWORD='ubuntu'
    disk-image-create ubuntu vm devuser -o my-ubuntu
    # Keypairの登録
    nova keypair-add ubuntu --pub-key id_rsa.pub
    # Glanceにイメージの登録
    openstack image create  ubuntu --disk-format qcow2 --container-format bare --public --file my-ubuntu.qcow2
    
  9. SecurityGroupの設定(外部からのSSHとicmpを通す)

    neutron security-group-rule-create 45267cfb-1385-47d6-bd62-941c4f6612d7 --direction ingress --port-range-min 22 --port-range-max 22 --protocol tcp --remote-ip-prefix 0.0.0.0/0
    neutron security-group-rule-create 45267cfb-1385-47d6-bd62-941c4f6612d7 --direction ingress --protocol icmp --remote-ip-prefix 0.0.0.0/0
    
  10. VMインスタンスの配備。--nicの引数にはtrunk用のport(my-trunk)を指定します(出力結果は省略)

    nova boot vlan-aware-vm --flavor d1 --image b360b1af-2bf3-4276-9852-e7ee5832c9cc --nic port-id=027824df-170d-4f5b-9619-daa3373255a2 --key-name ubuntu
    nova list
    +--------------------------------------+---------------+--------+------------+-------------+---------------------+
    | ID                                   | Name          | Status | Task State | Power State | Networks            |
    +--------------------------------------+---------------+--------+------------+-------------+---------------------+
    | 65909ef2-1b7b-40f4-9bce-1ca44dc1d059 | vlan-aware-vm | ACTIVE | -          | Running     | trunk=192.168.100.4 |
    +--------------------------------------+---------------+--------+------------+-------------+---------------------+
    

    ようやく調査環境の出来上がりです。ホスト上/VM内部から見ていきましょう。

ホスト上の構成

OVSの構成を確認します。

sudo ovs-vsctl list-br

br-eth1
br-ex
br-int
br-tun
tbr-3b9bb4f7-a

tbr-3b9bb4f7-aが新たに作成されているようです。
以下のコマンドを使って接続関係を調査しました。

ovs-vsctl show
brctl show
virsh dumpxml <domain>
ovs-ofctl show
ip link show type veth

以下に結果をまとめます。

表. Network/SubnetとVLANIDとの対応関係

Network名 Subnet 実際のVLANID 内部用VLANID VM内に届くVLANID
net1 192.168.10.0/24 1031 1 1100
net2 192.168.20.0/24 1090 2 1200
net3 192.168.30.0/24 1048 3 1300
trunk 192.168.100.0/24 1052 4 なし
                 +--------------------------------+
                 |      VM(vlan-aware-vm)         |
                 |                                |
                 |                                |
                 +--------------|-----------------+
                       |  tap027824df-17 |
                       +--------+--------+
                                |
                 +--------------+-----------------+
                 |  qbr027824df-17 (linuxbridge)  |
                 +--------------+-----------------+
                                |
                       +--------|--------+
                       |  qvb027824df-17 |veth peer
                       +--------|--------+
                                |
                       +--------|--------+
                       |  qvo027824df-17 |veth peer
+-------------------------------+-----------------------------------+
|                              #1                                   |
|                                                                   |
|                     tbr-3b9bb4f7-a (openvswitch)                  |
|                                                                   |
|     #2         #3         #4         #5                           |
+------+----------+----------+----------+---------------------------+
    tpt-027    spt-867    spt-dd7    spt-e78
       |       tag:1100   tag:1200   tag:1300
       |          |          |          |       DHCP      DHCP      DHCP       DHCP
       |          |          |          |      (net1)    (net2)    (net3)     (trunk)
       |          |          |          |         |         |         |         |
       |          |          |          |         |         |         |         |
     tag:4      tag:1      tag:2      tag:3     tag:1     tag:2     tag:3     tag:4
    tpi-027    spi-867    spi-dd7    spi-e78   tap407b   tap6514   tapa92f   tap1cf
+------+----------+----------+----------+---------|---------|---------|---------|---+
|     #28        #16        #17        #18       #8        #9        #10       #11  |
|                                                                                   |
|                         br-int (openvswitch)                                      |
|                                                                                   |
| #1             #12        #13        #14      #27            #3              #2   |
+--|--------------+----------+----------+--------+--------------|---------------|---+
int-br-ex      qr-2c9     qr-3d7      qr-cee   qr-ecf       patch-tun     int-br-eth1
   |            tag:1      tag:2      tag:3    tag:4            |               |
   |              |          |          |        |              |               |
   |              |          |          |        |          patch-int           |
   |           qr-2c9     qr-3d7      qr-cee   qr-ecf  +--------|-----------+   |
   |           +--|----------|----------|--------|-+   | br-tun(openvswitch)|   |
   |           |              Router               |   +--------------------+   |
   |           |         (network namespace)       |                            |
   |           +-----------------------------------+                            |
phy-br-ex                                                                  phy-br-eth1
+--|-------------------+                                     +------------------|---+
| br-ex (openvswitch)  |                                     | br-eth1 (openvswitch)|
+----------------------+                                     +----------------------+

VMとbr-intとの間に新たなOVSが作成されていました。

ログ. 各OVS上のフローテーブル(コメント付き)

sudo ovs-ofctl dump-flows br-eth1
NXST_FLOW reply (xid=0x4):
 cookie=0x9340811c311457d0, duration=6454.065s, table=0, n_packets=2, n_bytes=180, idle_age=6453, priority=4,in_port=1,dl_vlan=1 actions=mod_vlan_vid:1031,NORMAL
 cookie=0x9340811c311457d0, duration=6442.165s, table=0, n_packets=3, n_bytes=222, idle_age=6203, priority=4,in_port=1,dl_vlan=2 actions=mod_vlan_vid:1090,NORMAL
 cookie=0x9340811c311457d0, duration=6434.023s, table=0, n_packets=2, n_bytes=132, idle_age=6199, priority=4,in_port=1,dl_vlan=3 actions=mod_vlan_vid:1048,NORMAL
 cookie=0x9340811c311457d0, duration=6394.064s, table=0, n_packets=92, n_bytes=4768, idle_age=5359, priority=4,in_port=1,dl_vlan=4 actions=mod_vlan_vid:1052,NORMAL
 cookie=0x9340811c311457d0, duration=6764.132s, table=0, n_packets=87, n_bytes=7430, idle_age=5478, priority=2,in_port=1 actions=drop
 cookie=0x9340811c311457d0, duration=6764.156s, table=0, n_packets=0, n_bytes=0, idle_age=39005, priority=0 actions=NORMAL

  ↑内部用のVLANID → 実際のVLANIDに変換して転送、それ以外は全て破棄する

sudo ovs-ofctl dump-flows br-int

NXST_FLOW reply (xid=0x4):
 cookie=0x8386294fbb646d84, duration=200.142s, table=0, n_packets=0, n_bytes=0, idle_age=202, priority=10,icmp6,in_port=28,icmp_type=136 actions=resubmit(,24)
 cookie=0x8386294fbb646d84, duration=196.172s, table=0, n_packets=0, n_bytes=0, idle_age=196, priority=10,icmp6,in_port=30,icmp_type=136 actions=resubmit(,24)
 cookie=0x8386294fbb646d84, duration=195.993s, table=0, n_packets=0, n_bytes=0, idle_age=195, priority=10,icmp6,in_port=31,icmp_type=136 actions=resubmit(,24)
 cookie=0x8386294fbb646d84, duration=195.782s, table=0, n_packets=0, n_bytes=0, idle_age=195, priority=10,icmp6,in_port=29,icmp_type=136 actions=resubmit(,24)
 cookie=0x8386294fbb646d84, duration=200.133s, table=0, n_packets=0, n_bytes=0, idle_age=202, priority=10,arp,in_port=28 actions=resubmit(,24)
 cookie=0x8386294fbb646d84, duration=196.165s, table=0, n_packets=0, n_bytes=0, idle_age=196, priority=10,arp,in_port=30 actions=resubmit(,24)
 cookie=0x8386294fbb646d84, duration=195.974s, table=0, n_packets=0, n_bytes=0, idle_age=195, priority=10,arp,in_port=31 actions=resubmit(,24)
 cookie=0x8386294fbb646d84, duration=195.758s, table=0, n_packets=0, n_bytes=0, idle_age=195, priority=10,arp,in_port=29 actions=resubmit(,24)

  ↑actions=resubmit([port], [table])は、指定された所のルールを再評価するということ
   arpが届いたら table #24のルールを再評価する

 cookie=0x8386294fbb646d84, duration=49386.294s, table=0, n_packets=31, n_bytes=4334, idle_age=27054, priority=2,in_port=1 actions=drop
 cookie=0x8386294fbb646d84, duration=49386.023s, table=0, n_packets=0, n_bytes=0, idle_age=65534, priority=2,in_port=2 actions=drop

  ↑内部用VLANIDが付与されていないものは全てDROP

 cookie=0x8386294fbb646d84, duration=200.153s, table=0, n_packets=2, n_bytes=396, idle_age=199, priority=9,in_port=28 actions=resubmit(,25)
 cookie=0x8386294fbb646d84, duration=196.182s, table=0, n_packets=0, n_bytes=0, idle_age=196, priority=9,in_port=30 actions=resubmit(,25)
 cookie=0x8386294fbb646d84, duration=196.006s, table=0, n_packets=0, n_bytes=0, idle_age=196, priority=9,in_port=31 actions=resubmit(,25)
 cookie=0x8386294fbb646d84, duration=195.795s, table=0, n_packets=0, n_bytes=0, idle_age=195, priority=9,in_port=29 actions=resubmit(,25)

  ↑actions=resubmit([port], [table])は、指定された所のルールを再評価するということ
   #30, 31, 29からのパケットはtable #25のルールを再評価する

 cookie=0x8386294fbb646d84, duration=49075.947s, table=0, n_packets=0, n_bytes=0, idle_age=49075, priority=3,in_port=2,dl_vlan=1031 actions=mod_vlan_vid:1,NORMAL
 cookie=0x8386294fbb646d84, duration=49064.048s, table=0, n_packets=0, n_bytes=0, idle_age=49064, priority=3,in_port=2,dl_vlan=1090 actions=mod_vlan_vid:2,NORMAL
 cookie=0x8386294fbb646d84, duration=49055.894s, table=0, n_packets=0, n_bytes=0, idle_age=49055, priority=3,in_port=2,dl_vlan=1048 actions=mod_vlan_vid:3,NORMAL
 cookie=0x8386294fbb646d84, duration=49015.947s, table=0, n_packets=0, n_bytes=0, idle_age=49015, priority=3,in_port=2,dl_vlan=1052 actions=mod_vlan_vid:4,NORMAL

  ↑#2から届いたパケットに対して、実際の(外部に見える)VLAN → 内部用VLANの変換をして転送

 cookie=0x8386294fbb646d84, duration=49386.596s, table=0, n_packets=2233, n_bytes=181970, idle_age=1, priority=0 actions=NORMAL
 cookie=0x8386294fbb646d84, duration=49386.594s, table=23, n_packets=0, n_bytes=0, idle_age=65534, priority=0 actions=drop

  ↑いずれもマッチしない場合は全てDROP

 cookie=0x8386294fbb646d84, duration=200.147s, table=24, n_packets=0, n_bytes=0, idle_age=200, priority=2,icmp6,in_port=28,icmp_type=136,nd_target=fe80::f816:3eff:fe31:3980 actions=NORMAL
 cookie=0x8386294fbb646d84, duration=196.177s, table=24, n_packets=0, n_bytes=0, idle_age=196, priority=2,icmp6,in_port=30,icmp_type=136,nd_target=fe80::f816:3eff:febe:dc65 actions=NORMAL
 cookie=0x8386294fbb646d84, duration=195.999s, table=24, n_packets=0, n_bytes=0, idle_age=195, priority=2,icmp6,in_port=31,icmp_type=136,nd_target=fe80::f816:3eff:fefb:b50a actions=NORMAL
 cookie=0x8386294fbb646d84, duration=195.788s, table=24, n_packets=0, n_bytes=0, idle_age=195, priority=2,icmp6,in_port=29,icmp_type=136,nd_target=fe80::f816:3eff:fea6:851a actions=NORMAL
 cookie=0x8386294fbb646d84, duration=200.136s, table=24, n_packets=0, n_bytes=0, idle_age=200, priority=2,arp,in_port=28,arp_spa=192.168.100.4 actions=resubmit(,25)
 cookie=0x8386294fbb646d84, duration=196.168s, table=24, n_packets=0, n_bytes=0, idle_age=196, priority=2,arp,in_port=30,arp_spa=192.168.20.4 actions=resubmit(,25)
 cookie=0x8386294fbb646d84, duration=195.989s, table=24, n_packets=0, n_bytes=0, idle_age=195, priority=2,arp,in_port=31,arp_spa=192.168.30.4 actions=resubmit(,25)
 cookie=0x8386294fbb646d84, duration=195.775s, table=24, n_packets=0, n_bytes=0, idle_age=195, priority=2,arp,in_port=29,arp_spa=192.168.10.7 actions=resubmit(,25)
 cookie=0x8386294fbb646d84, duration=49386.593s, table=24, n_packets=18, n_bytes=756, idle_age=41435, priority=0 actions=drop

  ↑trunkおよびsubportに指定したIPアドレスと一致する場合は、更に table #25を評価
  一致しなければ全てDROP

 cookie=0x8386294fbb646d84, duration=200.161s, table=25, n_packets=0, n_bytes=0, idle_age=202, priority=2,in_port=28,dl_src=fa:16:3e:31:39:80 actions=NORMAL
 cookie=0x8386294fbb646d84, duration=196.192s, table=25, n_packets=0, n_bytes=0, idle_age=196, priority=2,in_port=30,dl_src=fa:16:3e:be:dc:65 actions=NORMAL
 cookie=0x8386294fbb646d84, duration=196.017s, table=25, n_packets=0, n_bytes=0, idle_age=196, priority=2,in_port=31,dl_src=fa:16:3e:fb:b5:0a actions=NORMAL
 cookie=0x8386294fbb646d84, duration=195.808s, table=25, n_packets=0, n_bytes=0, idle_age=195, priority=2,in_port=29,dl_src=fa:16:3e:a6:85:1a actions=NORMAL

  ↑trunkおよびsubportに指定したportのMACアドレスと一致する場合は転送
  一致しなければ全てDROP

ゲスト上の構成

VMインスタンスにログインします。一旦ルータ(namespace)に入った後でSSHログインします。

ip netns
qrouter-d282be23-d5fa-4080-95d9-e087854c9b6a
qdhcp-00ceeee0-f72e-441b-9c3e-f398b3ded30f
qdhcp-a5620b9c-70f6-4b8f-953a-b54730c014a2
qdhcp-a8e2324b-38a7-4780-9a61-b5b99500a32e
qdhcp-4f3bf5ff-4a68-42b6-93a1-58ce3ea7fba8

sudo ip netns exec qrouter-d282be23-d5fa-4080-95d9-e087854c9b6a bash
ssh -i ubuntu_sshkey/id_rsa ubuntu@192.168.100.4
bash
  • なぜかデフォルトがshだったためbashを呼び出しています

NICの構成を確認してみます。

ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether fa:16:3e:31:39:80 brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.4/24 brd 192.168.100.255 scope global ens3
       valid_lft forever preferred_lft forever
    inet6 fe80::f816:3eff:fe31:3980/64 scope link
       valid_lft forever preferred_lft forever

通常の配備と比べて変化はないようです。
とはいえ、VM内に VLAN1100, 1200, 1300 のタグ付きパケットが届くはずなので
確認のためVLAN I/Fを定義します。(結果は省略)

sudo vconfig add ens3 1100; sudo vconfig add ens3 1200; sudo vconfig add ens3 1300
sudo ifconfig ens3.1100 192.168.10.7/24
sudo ifconfig ens3.1200 192.168.20.4/24
sudo ifconfig ens3.1300 192.168.30.4/24
ip a | grep -2 192.168

2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether fa:16:3e:31:39:80 brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.4/24 brd 192.168.100.255 scope global ens3
       valid_lft forever preferred_lft forever
    inet6 fe80::f816:3eff:fe31:3980/64 scope link
--
3: ens3.1100@ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether fa:16:3e:31:39:80 brd ff:ff:ff:ff:ff:ff
    inet 192.168.10.7/24 brd 192.168.10.255 scope global ens3.1100
       valid_lft forever preferred_lft forever
    inet6 fe80::f816:3eff:fe31:3980/64 scope link
--
4: ens3.1200@ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether fa:16:3e:31:39:80 brd ff:ff:ff:ff:ff:ff
    inet 192.168.20.4/24 brd 192.168.20.255 scope global ens3.1200
       valid_lft forever preferred_lft forever
    inet6 fe80::f816:3eff:fe31:3980/64 scope link
--
5: ens3.1300@ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether fa:16:3e:31:39:80 brd ff:ff:ff:ff:ff:ff
    inet 192.168.30.4/24 brd 192.168.30.255 scope global ens3.1300
       valid_lft forever preferred_lft forever
    inet6 fe80::f816:3eff:fe31:3980/64 scope link

ルータ内から適当にpingを飛ばして、そのパケットをVM内でキャプチャしてみます。
VLANタグが付与されているか確認します。

VlAN1100(192.168.10.7)宛
tcpdump -i ens3.1100 -e -n
  ...(snip)...
  18:36:12.855988 fa:16:3e:19:53:38 > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 46: vlan 1100, p 0, ethertype ARP, Request who-has 192.168.10.7 tell 192.168.10.1, length 28
  18:36:12.856145 fa:16:3e:31:39:80 > fa:16:3e:19:53:38, ethertype 802.1Q (0x8100), length 46: vlan 1100,kjj p 0, ethertype ARP, Reply 192.168.10.7 is-at fa:16:3e:31:39:80, length 28

VlAN1200(192.168.20.4)宛
tcpdump -i ens3.1200 -e -n
  ...(snip)...
  18:49:10.673920 fa:16:3e:69:2a:0c > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 46: vlan 1200, p 0, ethertype ARP, Request who-has 192.168.20.4 tell 192.168.20.1, length 28
  18:49:10.674406 fa:16:3e:31:39:80 > fa:16:3e:69:2a:0c, ethertype 802.1Q (0x8100), length 46: vlan 1200, p 0, ethertype ARP, Reply 192.168.20.4 is-at fa:16:3e:31:39:80, length 28

VlAN1300(192.168.30.4)宛
tcpdump -i ens3.1300 -e -n
  ...(snip)...
  18:50:27.918014 fa:16:3e:fe:ff:3f > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 46: vlan 1300, p 0, ethertype ARP, Request who-has 192.168.30.4 tell 192.168.30.1, length 28
  18:50:27.918441 fa:16:3e:31:39:80 > fa:16:3e:fe:ff:3f, ethertype 802.1Q (0x8100), length 46: vlan 1300, p 0, ethertype ARP, Reply 192.168.30.4 is-at fa:16:3e:31:39:80, length 28

VMまでVLANタグが届いていることを確認できました。5
次にSecurity-group(SG)ですが、trunkとして指定したportのSGのみが作用していました。
trunkにまとめたVLANタグ通信ごとにSGを適用することはできないため
VMゲスト内で設定する必要がありそうです。

Get me a networkとは

VMインスタンス配備の簡易化機能です。
動作的には、Neutronのリソースを自動的に作ってVMインスタンスと接続してくれるため
利用者はNeutronのリソースを用意せずにVMインスタンスを配備できるようになりました。

従来、プロジェクト利用者が外部通信可能なVMインスタンスを配備するためには
少なくとも以下の手順が必要であり、ただVMだけ立ち上げたいユーザにとっては面倒だという
意見があったようです。

  1. private network作成
  2. private subnet作成
  3. router作成
  4. routerにprivate subnetを接続
  5. routerにexternal networkを接続

Neutron以前のNova-networkでは、上記のような作業は不要でした。

こうした背景から、利用者の負担を減らす仕組みが必要だよねという話になったようです。

環境構築

  1. 前のセクションと同じ方法で構築後、全てのリソースを削除しておく
  2. Get me a network(Auto Allocated Topology)が有効になっているかを確認

    openstack extension list --network | grep auto
    | Auto Allocated Topology Services              | auto-allocated-topology   | Auto Allocated Topology Services
    

ゼロから始めるGet me a network

タイトル回収のためNeutronのリソースが一つもない状態から始めます。

  • VMインスタンスの配備(出力結果は省略)

    • --nic auto というパラメータがトリガーです
    nova boot --flavor 1 --image 198384a2-9ece-4d24-a509-4ce02f183b63 vm1 --nic auto
    

ここでエラーが発生しました。

stdout
ERROR (BadRequest): Unable to automatically allocate a network for project 74df629a6bb04002be77a3ff998fb0a0 (HTTP 400) (Request-ID: req-ecbf665b-9563-46a4-b95a-122fb22646fa)

上記だけだと理由が分からないので、nova-apiのログを確認します(一部抜粋)

/opt/stack/logs/n-api.log
Error message: {"NeutronError": {"message": "Deployment error: No default router:external network.", "type": "AutoAllocationFailure", "detail": ""}}
Unable to auto-allocate networks. Deployment error: No default router:external network.

Defaultのrouter:externalなnetworkがないよ、言われています。
もう少し詳しく探るため、エラーが起きたNeutron側の処理まで順を追って確認します。

  (command)    +------+   +---------------------------+   +---------+
$ nova boot -->| Nova |-->| Python-neutronclient(CLI) |-->| Neutron |
               +------+   +---------------------------+   +---------+

(nova boot ---> 色々と省略 --->)

_ports_needed_per_instance

  • 指定されたプロジェクト内でVMインスタンスに付与するためのnetworkを探す。
  • 見つかった場合「使えるnetworkを見つけたからそれを指定しろ」というエラーが発生する

_can_auto_allocate_network

  • Auto Allocated Topology Servicesが有効な場合、 Python-neutronclientの validate_auto_allocated_topology_requirementsを呼び出す

validate_auto_allocated_topology_requirements

  • Neutronの get_auto_allocated_topologyを呼び出す

get_auto_allocated_topology

さきほどは_check_requirementsのところで
is_default=Trueかつrouter:external=Trueのnetworkがなかったためエラーになったようです。

以下にGet me a networkが使える条件についてまとめました。


  1. is_defaultかつ router:externalのnetworkが存在している かつ
  2. is_defaultのsubnetpoolが自身のプロジェクトから参照可能(IPv4/v6は問わず) かつ
  3. 自身のプロジェクト内に 1. を含むnetworkが一つも存在しない

この条件下で、nova bootのオプションとして --nic auto を指定すると
Get me a network(auto-allocate-topology)が動作します。

ということで、管理者(admin)権限で以下のnetwork/subnet/subnetpoolを作成します。

# 管理者(admin)に変更
source ~/devstack/openrc admin admin

neutron net-create external --router:external --is_default
neutron subnetpool-create --is_default --shared --pool-prefix 10.0.0.0/20 --default-prefixlen 24 default_subnetpool
neutron subnet-create external --use-default-subnetpool
  • subnetpoolは shared 属性をつけないと他プロジェクトから参照できません6

気を取り直してもう一度

Re:ゼロから始めるGet me a network

これが言いたかっただけです

  • VMインスタンスの配備(出力結果は省略)
# プロジェクト利用者(demo)に変更
source ~/devstack/openrc demo demo

nova boot --flavor 1 --image 198384a2-9ece-4d24-a509-4ce02f183b63 vm1 --nic auto
nova list
+--------------------------------------+------+--------+------------+-------------+---------------------------------+
| ID                                   | Name | Status | Task State | Power State | Networks                        |
+--------------------------------------+------+--------+------------+-------------+---------------------------------+
| 03e7439e-7cdf-4fd3-b0fb-9b5cb234f2b8 | vm1  | ACTIVE | -          | Running     | auto_allocated_network=10.0.1.3 |
+--------------------------------------+------+--------+------------+-------------+---------------------------------+

配備に成功しました。以下のように自動作成されていることを確認できました:v_tone1:

topology.png

  • auto_allocated_network
  • auto_allocated_subnet_v4
  • auto_allocated_router

ついでですが--nic none と指定することで 下記のようにnetworkを持たない
VMインスタンスを配備することも可能です。

nova boot --flavor 1 --image 2180aed3-ea7c-4bec-a4fa-e61b22cfd64d --nic none vm2
nova list

+--------------------------------------+------+--------+------------+-------------+----------------------------------+
| ID                                   | Name | Status | Task State | Power State | Networks                         |
+--------------------------------------+------+--------+------------+-------------+----------------------------------+
| e36b8446-5c4c-42bb-a80f-834f7a387c31 | vm1  | ACTIVE | -          | Running     | auto_allocated_network=10.0.1.11 |
| 97934c9c-30eb-4d86-8b98-6eebe32db86b | vm2  | ACTIVE | -          | Running     |                                  |
+--------------------------------------+------+--------+------------+-------------+----------------------------------+

まとめ

VLAN aware VMs

  • 一つのvNICに複数のVLANタグを引き込ませる機能のこと
  • VMインスタンスとbr-intとの間に新たなOVSを噛ませてVLANタギング設定
  • openstack network trunk コマンドで設定可能
  • 現状はVMインスタンスに対する設定のみなので、将来ベアメタルにも 適用されることを期待。7

Get me a network

  • VMインスタンス配備時の設定簡易化機能のこと
  • 以下の条件の下、VMインスタンス配備時に --nic auto を指定することで動作する。
    1. is_default かつ router:externalnetwork が存在している
    2. is_defaultsubnetpoolが自身のプロジェクトから参照可能(IPv4/v6は問わず)
    3. 自身のプロジェクト内に 1. を含むnetworkが一つも存在しない
  • --nic noneを指定するとネットワークなしの状態で配備可能
  • 実際に使ってみて楽だと感じた。
  • Get me a network!と言いたくなる(個人差があります)

おわりに

調査しきれない部分5もありましたが
OpenStackは機能が充実して、かなり自由度が上がってきていると感じています。
初投稿なので緊張しました:beginner:

参考文献


  1. SPEC(仕様書)は こちら 

  2. SPEC(仕様書)は こちら 

  3. 開発向けのOpenStack環境の構築用スクリプト。マシン1台からOpenStackの環境を構築できます(All-in-one)。詳細はこちら 

  4. メモリをケチって2GBで動かしたところ、devstackインストール後にmysql上で[ERROR] InnoDB: Cannot allocate memory for the buffer poolが発生しました。^^; 

  5. 疎通確認用のVM/コンテナを作って色々確認する予定でしたがHDDとメモリ不足で断念。 

  6. networkは router:external属性をTrue(外部ネットワーク)にすると他プロジェクトから参照できます。 

  7. 詳しくはこちら 

この投稿は Fujitsu Advent Calendar 201615日目の記事です。