2013年12月17日火曜日

コマンドラインからだけで OpenVNet の機能を推測してみる

Wakame Advent Calendar http://atnd.org/events/45749 を機会に wakame-vdc から分離された? OpenVNet を触ってみようと思います。機能を知るには API を見るのが一番なので、まずは動かす前に API を見てみます。 API は https://github.com/axsh/openvnet/wiki/WebAPI-Reference にあるということですが、最新版ではないかも?という噂を聞いたので、今回は CLI の vnctl のコマンドラインから機能を推測してみることにします(きちんと更新されているようでしたらごめんなさい)。実際に動かしてみるのは明日以降にします。

CLI のインストール


Advent Calendar 2日目のエンジニアじゃないけど仮想ネットワークOSSのOpenVNetをサクっとインストールしとく。 #wakameug を参考にインストールしてみます。

用意した環境はインストールガイドと微妙に違いますが、CentOS 6.5 に入れました。
# vi /etc/yum.repos.d/openvnet.repo
[openvnet]
name=OpenVNet
baseurl=http://dlc.openvnet.axsh.jp/packages/rhel/6/vnet/current/
enabled=1
gpgcheck=0
# vi /etc/yum.repos.d/openvnet-third-party.repo
[openvnet-third-party]
name=OpenVNet Third Party
baseurl=http://dlc.openvnet.axsh.jp/packages/rhel/6/third_party/current/
enabled=1
gpgcheck=0
# rpm -Uvh http://dlc.wakame.axsh.jp.s3-website-us-east-1.amazonaws.com/epel-release
# yum install -y wakame-vnet

今日は実際のデーモンは起動しないので、CLI が使える環境を設定だけ。

# export PATH=/opt/axsh/wakame-vnet/ruby/bin:/opt/axsh/wakame-vnet/vnctl/bin:$PATH
# which vnctl
/opt/axsh/wakame-vnet/vnctl/bin/vnctl
# which ruby
/opt/axsh/wakame-vnet/ruby/bin/ruby
# ruby --version
ruby 2.0.0p247 (2013-06-27 revision 41674) [x86_64-linux]
# vnctl
/opt/axsh/wakame-vnet/vnctl/bin/vnctl:8:in `<main>': undefined method `setup' for Bundler:Module (NoMethodError)

vnctl と ruby が入っている場所に PATH を通してみたのですが、vnctl がうまく動きません。 Ruby の bundler の設定が必要なようです。 Ruby の bundler 初心者の僕にはよく分かりません。検索してみると、 bundler は Gemfile.lock というファイルが場所で bundle exec でファイルを実行するといいみたいです。 /etc/init/vnctl.conf でもそうなっているので、チャレンジしてみます。

# cd /opt/axsh/wakame-vnet/vnctl/
# which bundle
/opt/axsh/wakame-vnet/ruby/bin/bundle
# bundle exec ./bin/vnctl
Could not find fuguta-1.0.2 in any of the sources
Run `bundle install` to install missing gems.

まだダメです。言われたとおりに bundle install を実行してみます。

# bundle install
Fetching gem metadata from http://rubygems.org/.......
Fetching gem metadata from http://rubygems.org/..
Installing fuguta (1.0.2)
Installing multi_json (1.8.0)
Installing multi_xml (0.5.5)
Installing httparty (0.11.0)
Installing thor (0.18.1)
Using bundler (1.3.5)
Your bundle is complete!
Use `bundle show [gemname]` to see where a bundled gem is installed.
Post-install message from httparty:
When you HTTParty, you must party hard!
# vnctl
Commands:
  vnctl datapath         # Operations for datapaths.
  vnctl help [COMMAND]   # Describe available commands or one specific command
  vnctl interface        # Operations for interfaces.
  vnctl ip_address       # Operations for ip addresses.
  vnctl ip_lease         # Operations for ip leases.
  vnctl mac_lease        # Operations for mac leases.
  vnctl network          # Operations for networks.
  vnctl network_service  # Operations for network services.
  vnctl route            # Operations for routes.
  vnctl route_link       # Operations for route links.
  vnctl security_group   # Operations for security groups.
# vnctl
/opt/axsh/wakame-vnet/vnctl/bin/vnctl:8:in `<main>': undefined method `setup' for Bundler:Module (NoMethodError)

今度はきちんと動きました。ただし、/opt/axsh/wakeme-vnet/vnctl 以下で vnctl を実行する必要があるようです。何はともあれ vnctl が動いたので、やっと今日の目的に進めます。

RPM だけでだめなのはそういうものなのでしょうか? 誰か教えてください。

CLI の使い方を探る

さて CLI のコマンドとオプションを探ってみます。 今日のポリシーとしてコードは読みません。

vnctl help [COMMAND] というヘルプを実行したのですが、情報量 0 です。
面倒なので、help をつけないで実行してみると、サブコマンドが出てきました (^^
この先もかなり探検が必要なようです。

# vnctl help datapath
Usage:
  vnctl datapath

Operations for datapaths.
# vnctl datapath
Commands:
  vnctl datapath add [OPTIONS] --display-name=DISPLAY_NAME --dpid=DPID --node-id=NODE_ID  # Creates a new datapath.
  vnctl datapath del UUID(S)                                                              # Deletes one or more datapath(s) separated by a space.
  vnctl datapath help [COMMAND]                                                           # Describe subcommands or one specific subcommand
  vnctl datapath modify UUID [OPTIONS]                                                    # Modify a datapath.
  vnctl datapath networks OPTIONS                                                         # subcommand to manage networks in this datapath.
  vnctl datapath route_links OPTIONS                                                      # subcommand to manage route_links in this datapath.
  vnctl datapath show [UUID(S)]                                                           # Shows all or a specific set of datapath(s).

この次は、サブコマンドのオプションも知りたいところです。いろいろなところに help や –help を入れてみたところ、サブコマンド名の直前に help をつけると、詳しいオプションが出ることが分かりました。上に表示されているヘルプをちゃんと見ると書いてありました。ゴメンナサイ、あまり直観的ではないですね。

# vnctl datapath add
No value provided for required options '--display-name', '--node-id', '--dpid'
# vnctl datapath add help
No value provided for required options '--display-name', '--node-id', '--dpid'
# vnctl datapath help add
Usage:
  vnctl add [OPTIONS] --display-name=DISPLAY_NAME --dpid=DPID --node-id=NODE_ID

Options:
  [--uuid=UUID]                    # Unique UUID for the datapath.
  --display-name=DISPLAY_NAME      # Human readable display name.
  [--is-connected]                 # Flag that detemines if the datapath is connected or not.
  [--dc-segment-id=DC_SEGMENT_ID]  # The datapath's dc segment id.
  --node-id=NODE_ID                # The node id for the datapath.
  [--ipv4-address=IPV4_ADDRESS]    # Ipv4 address for the datapath.
  --dpid=DPID                      # Hexadecimal id for the datapath.

Creates a new datapath.

API 体系を分析してみる

vnctl datapath help add のようなリソース作成コマンドのヘルプを順に実行して、リソース間を探ってみました。
矢印は、リソース作成時に指定するパラメータの関係を指しています。矢印の行先が指定されている方のパラメータです。



これを元に機能を推測してみます。

datapath
最初に作成するリソースのようです。 datapath ID と Node ID を指定することから、VM が起動するホストの OVS を表しているみたいです。
network
論理ネットワークを指すリソースのようです。論理 L2 とそのうえで動作する IPv4 サブネットがひとまとめで管理されています。
network を datapath に関連付けする際に broadcast MAC address を指定するところが特徴的に見えます。
network-mode というパラメータがあり、physical/virtual という指定ができるので、物理ネットワークの定義と仮想ネットワークの定義の両方に使用するのでしょうか。
IP address
network で使用する IP アドレスを登録するように見えます。
interface
interface は VM などが接続される endpoint に対応していると推測しました。
どうやって OVS の各ポートを識別するのかが気になります。
MAC アドレスが必須パラメータで、属性として network ID や datapath ID を指定できることから、OVS のポートに対応していて、MAC アドレスベースでネットワークを判定しているのかなと感じました。
IP lease
interface に IP Address を割り当てたり、現在の割り当て状況を管理するのに使っているようです。
なぜ network ID が IP Lease のパラメータにあるのかわかりませんでした。 interface はネットワークとは独立に存在できて、 IP Lease を変更すると、別のネットワークにもつなぎ直せるのかな?
network service
interface に接続された VM などがどんな L4 ポート番号を使用しているかを指定することで、その interface に接続されたネットワークサービスを表現しているようです。
route_link と route
経路情報があることからルーター機能に関するものであることは分かりますが、具体的にどのように使うかまでは分かりませんでした。

まとめ

おおざっぱに機能を推測してみました。ソースも読んでいませんし、実際にも動かしていないので、完全にはずしているかもしれません。

OpenStack Neutron や Amazon VPC のモデルとはだいぶ違いますね。 もう少し詳しく見てどういう思想で設計されているのかを知りたいと思います。

リソースモデルや CLI だけだとなかなか具体的なイメージが湧きませんね。 仮想ネットワーク作成例とコマンドラインシーケンスがあると分かりやすいなあと思いました。

明日も記事を書く予定ですが、実際に動かしてみようと思います。 VM を起動するのは面倒なので、network namespace を使って論理ネットワークの動作を見てみたいと思います。

Neutron VPNaaS を使ってみる ~ 意味もないけど、とりあえず back-to-back で IPsec VPN

OpenStack Neutron に Havana リリースで VPNaaS が追加されました。今回のリリースでは IPsec による L3 VPN のみが実装されています。Icehouse では SSL-VPN や BGP/MPLS による VPN なども計画されています。devstack を使って VPNaaS を動かして、どんなことが行われているのか見てみたいと思います。

VPNaaS だけでなく LBaaS/FWaaS を含めた Network Service の考え方は OpenStack Neutron の紹介資料 (Havana 版) の後ろの方で説明しているので、こちらもご参照ください。

構成

2か所のサイトを IPsec VPN で接続する例を考えます。


ここでは、一つの OpenStack で 2つのネットワークをそれぞれ別のサイトとみなして、VPNaaS を使って back-to-back で VPN を作成して接続します。上の図の site1, site2 はそれぞれ net1, net2 が対応します。router1, router2 にそれぞれ相手のネットワークに向けた経路情報を明示的に設定しない限り、net1 と net2 間は通信できないので、VPN 接続の確認として使うことができます。


devstack の実行

devstack の stable/havana branch を取得して、localrc を作成して、stack.sh を実行します。 Ubuntu 12.04.3 LTS を使っています。
git clone https://github.com/openstack-dev/devstack.git
cd devstack
git checkout stable/havana
wget -O localrc https://gist.github.com/amotoki/6520741/raw/6856653c57b67441c99aba057f310801da4d03ae/localrc-havana-allinone
./stack.sh
今回使った localrc は https://gist.github.com/amotoki/6520741 にありますので、参考にしてください。
Ceilometer, Heat, Swift も有効にしていますが、無効にしても構いません。
余談ですが、Ubuntu 12.04 では mongodb のバージョンが古いので、Ceilometer を動かすには 2.4.6 などの新しいバージョンの mongodb をインストールする必要があります。 Havana の Ubuntu Cloud Archives から mongodb をインストールするのが一番簡単だと思います。

VPNaaS 用の Neutron の設定

devstack では、設定ファイルの作成は devstack の実行中に行われますが、何が行われているのかを見ておきます。

まず /etc/neutron/neutron.conf です。 VPNaaS を有効にするには service_pliugins に VPN プラグイン neutron.services.vpn.plugin.VPNDriverPlugin を指定します。この例では、他に L3, LBaaS, FWaaS の reference implementation が有効になっています。大きな流れとしては OpenStack Neutron の紹介資料 (Havana 版) の資料 (p.19) で紹介しているように、Neutron では機能単位のプラグイン (Service Plugin) を用意する方向です。VPNaaS もこの方向で実装されています。
service_plugins = neutron.services.l3_router.l3_router_plugin.L3RouterPlugin,neutron.services.loadbalancer.plugin.LoadBalancerPlugin,neutron.services.vpn.plugin.VPNDriverPlugin,neutron.services.firewall.fwaas_plugin.FirewallPlugin
extension list を確認すると、vpnaas が有効になっていることが分かります。
$ neutron ext-list
+-----------------------+-----------------------------------------------+
| alias                 | name                                          |
+-----------------------+-----------------------------------------------+
| service-type          | Neutron Service Type Management               |
| fwaas                 | Firewall service                              |
| security-group        | security-group                                |
| l3_agent_scheduler    | L3 Agent Scheduler                            |
| lbaas_agent_scheduler | Loadbalancer Agent Scheduler                  |
| ext-gw-mode           | Neutron L3 Configurable external gateway mode |
| binding               | Port Binding                                  |
| quotas                | Quota management support                      |
| agent                 | agent                                         |
| router                | Neutron L3 Router                             |
| dhcp_agent_scheduler  | DHCP Agent Scheduler                          |
| external-net          | Neutron external network                      |
| multi-provider        | Multi Provider Network                        |
| allowed-address-pairs | Allowed Address Pairs                         |
| vpnaas                | VPN service                                   |
| extra_dhcp_opt        | Neutron Extra DHCP opts                       |
| provider              | Provider Network                              |
| lbaas                 | LoadBalancing service                         |
| extraroute            | Neutron Extra Route                           |
+-----------------------+-----------------------------------------------+
IPsec の実装は Openswan https://www.openswan.org/ を使用しています。
devstack 実行後には openswan パッケージがインストールされています。現状は openswan ベースの IPsec VPN だけが Neutron に入っている唯一の VPNaaS の実装です。
)$ COLS=80 dpkg -l openswan
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name                Version             Description
+++-===================-===================-======================================================
ii  openswan            1:2.6.37-1          Internet Key Exchange daemon
VPN に対応した L3 agent である neutron-vpn-agent が openswan を呼び出して VPN 接続を行います。 VPNaaS を使う場合には l3-agent の代わりに vpn-agent を使用します。 vpn-agent は l3-agent に VPN 用の機能が追加されたもので、通常の l3-agent としてもふるまいます。
実行されているサービスプロセスを確認すると vpn-agent が起動していることが分かります。 FWaaS も同時に有効にしているので、fwaas.ini も引数に指定されています。現状は VPNaaS に関連する設定項目はありません。
$ ps auxw | grep vpn-agent
1000      7786  0.0  0.0   9388   932 pts/90   S+   21:28   0:00 grep --color=auto vpn-agent
1000     17627  0.2  0.9 112980 39164 pts/14   S+   20:58   0:05 /usr/bin/python /usr/local/bin/neutron-vpn-agent --config-file /etc/neutron/neutron.conf --config-file=/etc/neutron/l3_agent.ini --config-file /etc/neutron/fwaas_driver.ini

ネットワークの準備

site1 側のネットワーク、ルーターは devstack の実行時にデフォルトで作成されているので、2つ目のサイトに相当するネットワーク、ルーターを作成します。ここではコマンドラインで作成していますが、ダッシュボードから作成した方が楽だと思います。(user_name: demo, tenant_name: demo で操作します)。さらに、それぞれのネットワークに接続した VM も起動しておきます。
$ neutron net-create net2
$ neutron subnet-create --name subnet2 net2 10.3.3.0/24
$ neutron router-create router2
$ neutron router-interface-add router2 subnet2
$ neutron router-gateway-set router2 ext_net
$ nova boot --key-name mykey --image tty-quantum --flavor m1.tiny --nic net-id= vm1
$ nova boot --key-name mykey --image tty-quantum --flavor m1.tiny --nic net-id= vm2
この状態ではこのようになります。


自分の例では以下のようなアドレスになりました。
  • Site1
    • VM1 : 10.0.0.3
    • router1 (net1側) : 10.0.0.1
  • Site1
    • VM2 : 10.3.3.2
    • router2 (net2側) : 10.3.3.1

この段階で異なるネットワーク間で ping が通らないことを確認しておきます。
  • VM1 -> router1(net1側) : OK
  • VM1 -> router2(net2側) : NG
  • VM1 -> VM2 : NG
  • VM2 -> router2(net2側) : OK
  • VM2 -> router1(net1側) : NG
  • VM2 -> VM1 : NG
セキュリティグループで ICMP と SSH を開けた上で確認します。
neutron security-group-rule-create --protocol tcp --port-range-min 22 --port-range-max 22 --remote-ip-prefix 0.0.0.0/0 default
neutron security-group-rule-create --protocol icmp --remote-ip-prefix 0.0.0.0/0 default

VPN の作成


VPN の作成は、それぞれのサイトで行います。

最初に、VPN service はルーターとサブネットを指定して作成します。VPN service は、VPN 接続を受け付けるサイト側で、VPN 接続をどのルーターで終端し、どのサブネットに関連付けるかを指定するものです。また、IPsec 接続の各種ポリシーはあらかじめ用意した IPsec Policy, IKE Policy で作成しておきます。この段階では VPN service の status は Pending Create で問題ありません。

Site1 側
neutron vpn-ipsecpolicy-create ipsec-policy1
neutron vpn-ikepolicy-create ike-policy1
neutron vpn-service-create --name vpn1 router1 private-subnet
Site2 側
neutron vpn-ipsecpolicy-create ipsec-policy2
neutron vpn-ikepolicy-create ike-policy2
neutron vpn-service-create --name vpn2 router2 subnet2

次に、IPsec 接続を VPN service を指定して作成します。

IPsec 接続を作成するには、接続相手側の VPN ルータの外側の IP アドレスが必要です。以下のコマンドを実行することで、それぞれのルーターの外側の IP アドレスが以下のように分かります。
  • router1: 172.24.4.226
  • router2: 172.24.4.227
現在の Neutron API ではルーターの外側の IP アドレスは管理者権限でしか入手することができません。そのため、通常のユーザーが OpenStack どうしを VPNaaS で接続することはできません。これでは不便なので、ルーターの外部の IP アドレス情報を入手できるようにすることが検討されています。
$ OS_USERNAME=admin OS_TENANT_NAME=admin neutron router-port-list router1 --device_owner network:router_gateway -c fixed_ips
+-------------------------------------------------------------------------------------+
| fixed_ips                                                                           |
+-------------------------------------------------------------------------------------+
| {"subnet_id": "711a97f6-b6c0-425c-b17b-618904324f95", "ip_address": "172.24.4.226"} |
+-------------------------------------------------------------------------------------+
$ OS_USERNAME=admin OS_TENANT_NAME=admin neutron router-port-list router2 --device_owner network:router_gateway -c fixed_ips
+-------------------------------------------------------------------------------------+
| fixed_ips                                                                           |
+-------------------------------------------------------------------------------------+
| {"subnet_id": "711a97f6-b6c0-425c-b17b-618904324f95", "ip_address": "172.24.4.227"} |
+-------------------------------------------------------------------------------------+

この情報をもとに IPsec 接続を作成します。

まず Site1 側を作成します。 peer-address には接続相手の VPN ルーターの外側の IP アドレス (ここでは router2 の外側のアドレス) 172.24.4.227 を、peer-cidr は接続相手のサブネットアドレス 10.3.3.0/24 を指定します。 peer-id の指定内容は VPN ルーターの構成により変わりますが、vpn-agent ベースのルーターの場合は peer-address と同じアドレスを指定します。
$ neutron ipsec-site-connection-create --vpnservice-id vpn1 \
    --ikepolicy-id ike-policy1 --ipsecpolicy-id ipsec-policy1 \
    --peer-address 172.24.4.227 --peer-id 172.24.4.227 \
    --peer-cidr 10.3.3.0/24 --psk secret1 --name conn1
$ neutron ipsec-site-connection-list -c name -c peer_address -c peer_cidrs -c status
+-------+--------------+---------------+--------+
| name  | peer_address | peer_cidrs    | status |
+-------+--------------+---------------+--------+
| conn1 | 172.24.4.227 | "10.3.3.0/24" | DOWN   |
+-------+--------------+---------------+--------+
この段階では Site1 側の IPsec 接続 conn1 のステータスは、まだ相手と接続されていないので、DOWN となります。

次に、Site2 側の IPsec 接続を作成します。
$ neutron ipsec-site-connection-create --vpnservice-id vpn2 \
    --ikepolicy-id ike-policy2 --ipsecpolicy-id ipsec-policy2 \
    --peer-address 172.24.4.226 --peer-id 172.24.4.226 \
    --peer-cidr 10.0.0.0/24 --psk secret1 --name conn2
$ neutron ipsec-site-connection-list -c name -c peer_address -c peer_cidrs -c status
+-------+--------------+---------------+--------+
| name  | peer_address | peer_cidrs    | status |
+-------+--------------+---------------+--------+
| conn1 | 172.24.4.227 | "10.3.3.0/24" | ACTIVE |
| conn2 | 172.24.4.226 | "10.0.0.0/24" | ACTIVE |
+-------+--------------+---------------+--------+
相手と正常に接続されていれば、両方のサイトの IPsec 接続でステータスが ACTIVE になります。

導通も確認してみましょう。VM1 にログインして、VM2 に対して ping を実行します。
# ifconfig eth0
eth0      Link encap:Ethernet  HWaddr FA:16:3E:8A:39:FE
          inet addr:10.0.0.3  Bcast:10.0.0.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1185 errors:0 dropped:0 overruns:0 frame:0
          TX packets:821 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:126234 (123.2 KiB)  TX bytes:144124 (140.7 KiB)

# ping -c 5 10.3.3.2
PING 10.3.3.2 (10.3.3.2): 56 data bytes
64 bytes from 10.3.3.2: seq=0 ttl=62 time=6.093 ms
64 bytes from 10.3.3.2: seq=1 ttl=62 time=1.803 ms
64 bytes from 10.3.3.2: seq=2 ttl=62 time=1.886 ms
64 bytes from 10.3.3.2: seq=3 ttl=62 time=1.771 ms
64 bytes from 10.3.3.2: seq=4 ttl=62 time=1.399 ms

--- 10.3.3.2 ping statistics ---
5 packets transmitted, 5 packets received, 0% packet loss
round-trip min/avg/max = 1.399/2.590/6.093 ms

デバッグ情報

上では手順と動作確認を見てきましたが、デバッグ情報がどこにあるかを紹介しておきます。

  • neutron-vpn-agent のログ : /opt/stack/logs/screen-q-vpn.log (devstack の場合)
  • neutron-vpn-agent が作成する openswan の情報 : /opt/stack/data/neutron/ipsec/<router-id>
    • <router-id> は VPN service が関連付けられたルーターの ID
    • 通常のインストールであれば /var/lib/neutron などになります。
  • network namespace 内の ipsec 設定の情報
    • ip netns qrouter-ROUTER_ID ip -s xfrm state
    • ip netns qrouter-ROUTER_ID ip -s xfrm policy
    $ sudo netns exec qrouter-b78b3faf-e8d1-45dd-b185-02f65415b389 ip -s xfrm state
    src 172.24.4.227 dst 172.24.4.226
            proto esp spi 0x910992d8(2433323736) reqid 16385(0x00004001) mode tunnel
            replay-window 32 seq 0x00000000 flag af-unspec (0x00100000)
            auth-trunc hmac(sha1) 0x34f52f8ecdc75a4c3a4940e578b3f8a6a50e8147 (160 bits) 96
            enc cbc(aes) 0xc6091efe44c2a152ac5c77d6e6672f05 (128 bits)
            lifetime config:
              limit: soft (INF)(bytes), hard (INF)(bytes)
              limit: soft (INF)(packets), hard (INF)(packets)
              expire add: soft 0(sec), hard 0(sec)
              expire use: soft 0(sec), hard 0(sec)
            lifetime current:
              1512(bytes), 18(packets)
              add 2013-12-16 01:40:17 use 2013-12-16 01:46:21
            stats:
              replay-window 0 replay 0 failed 0
    src 172.24.4.226 dst 172.24.4.227
            proto esp spi 0xadd229c7(2916231623) reqid 16385(0x00004001) mode tunnel
            replay-window 32 seq 0x00000000 flag af-unspec (0x00100000)
            auth-trunc hmac(sha1) 0x8a0f54cd12bd528be9b7f7feeb6a901276d7264a (160 bits) 96
            enc cbc(aes) 0x4f7ffa695054c7408dae2f99ceb0c241 (128 bits)
            lifetime config:
              limit: soft (INF)(bytes), hard (INF)(bytes)
              limit: soft (INF)(packets), hard (INF)(packets)
              expire add: soft 0(sec), hard 0(sec)
              expire use: soft 0(sec), hard 0(sec)
            lifetime current:
              1512(bytes), 18(packets)
              add 2013-12-16 01:40:17 use 2013-12-16 01:46:21
            stats:
              replay-window 0 replay 0 failed 0
    

後始末

現時点では unstack.sh を行っても openswan のプロセスが削除されません。このプロセスを停止しないと、対応する network namespace を削除できません。 openswan が作成するプロセス pluto の PID が /opt/stack/data/neutron/ipsec/*/var/run/pluto.pid にあるので、この情報をもとに関連プロセスを削除します。
$ sudo kill `cat /opt/stack/data/neutron/ipsec/*/var/run/pluto.pid$`
$ for ns in `ip netns | grep -E '(qrouter|qdhcp)-'`; do sudo ip netns delete $ns; done

2013年12月14日土曜日

OpenStack Neutron の紹介資料 (Havana 版)

OpenStack Neutron の概要紹介の資料をアップデートしました。 1年前の OSC で話した「Quantum の紹介」の資料をベースに Havana の Neutron の状況にあわせて更新しました。 ML2 Plugin の説明、LBaaS/FWaaS/VPNaaS などの Advanced Network Service の考え方に関する情報を追加しています。みなさんの理解の参考になればと思います。

こちらの記事でも公開しているのですが、分かりやすいように別記事にしておきます。

OpenStack 開発体制とコントリビューションのお誘い @ Okinawa Open Days (と Neutron Havana 紹介資料)

12/12-13 に開催された Okinawa Open Days に参加して来ました。前日の OpenStack BOF と OpenStack セッションで話をして来ました。12日は OpenStack セッションで、13日は SDN セッションでした。久しぶりに SDN 関係者ともたくさん話をできて楽しかったです。

OpenStack セッションで「OpenStack開発体制とコントリビューションのお誘い」と題して話しました。OpenStack の開発体制や品質維持が行われているか、機能追加・バグ修正の流れ、OpenStack へのコントリビューションの進め方について説明しました。 OpenStack の開発体制を理解する上でも参考になると思いますので、Advent Calendar でも紹介したいと思います。

OpenStack BOF の中で学生さんから OpenStack を触っておいた方がいいですか?という質問をもらいました。技術がどんどん出て来る現在、OpenStack などのクラウドOSはある意味でいろいろな技術の集合体であり、OpenStack に触れることで、コンピュータ、ネットワークのいろいろな技術について体系的、統合的に学べるではないかと話しました。それをきっかけに興味を持った部分を深く突っ込んでいってもらいたいと思いました。


OpenStack BOF では、Neutron のコンセプトがどのような考え方で作られているのかを、ざっくばらんに話しました。
それに向けて Neutron の概要資料を作りました。 1年前の OSC で話した「Quantum の紹介」の資料を Havana で状況にあわせて更新したものです。
ML2 Plugin の説明、LBaaS/FWaaS/VPNaaS などの Advanced Network Service の考え方に関する情報を追加しています。

2013年12月11日水曜日

OpenStack と Trema Sliceable Switch とつないでみる

日本 OpenStack ユーザー会 Advent Calendar の 11日目ということで、Neutron と Trema Sliceable Switch を組み合わせて動かしてみようと思います。Okinawa OpenDays の BOF でプレゼンしながらデバッグしています。

devstack を使って動かしていますが、Ubuntu 12.04 でパッケージを使った Havana with Neutron のインストールガイドも https://github.com/amotoki/openstack-havana-install-guideで作っています。今は NEC OpenFlow Plugin のみですが、ML2 Plugin も準備中です。

Trema は OpenFlow Controller Framework で C と Ruby で OpenFlow Controller を書くことができます。みなさん知っていますね。 Sliceable Switch のアプリケーションで、 OpenFlow Controller として動作します。

Neutron のプラグインは NEC OpenFlow Plugin を使います。Sliceable Switch には REST API があり、この API を Plugin から呼び出して、OpenFlow ネットワーク上に複数の論理ネットワークを作成します。

今回は以下のような 3ノードの構成を使用しました。使用したマシンは Ubuntu 12.04 の KVM の VM です。メモリは 2GB です。 NIC は 1つです。 OVS 間のデータプレーンは GRE トンネルで接続しました。
  • Controller Node (nova, neutron のすべてのサービスを動かします)
  • Compute Node
  • OpenFlow Controller


最初に Sliceable Switch をセットアップします。 RVM 環境を利用して Ruby 2.0.0 の環境で動かします。 Trema は Ubuntu 12.04 の ruby 1.8.7 でも動作しますが、 ruby 1.8.7 はすでにサポートが終わっていること、依存モジュールが今後動かないなどのトラブルが出てくる可能性もあります。

Trema のインストール

依存パッケージのインストール以外は root 権限は不要です。
sudo aptitude install gcc make ruby rubygems ruby-dev libpcap-dev libsqlite3-dev libglib2.0-dev sqlite3 libdbi-perl libdbd-sqlite3-perl apache2 libjson-perl
# rvm インストール
\curl -sSL https://get.rvm.io | bash -s stable
# rvm 環境の反映 (ログインし直すか、source .bash_profile と PATH の追加)
PATH=$PATH:$HOME/.rvm/bin
source .bash_profile
# ruby 2.0.0 インストール
rvm install 2.0.0
# trema インストール
gem install trema
bundle install

Sliceable Switch のインストール

インストールは方法は trema apps の sliceable switch の README.md に使い方が書かれています。https://github.com/amotoki/openstack-havana-install-guide/wiki/TremaSliceableSwitch にも詳しく書いておきました。

sliceable switch の実行

最後の起動方法だけが rvm 環境なので少し違います。もっといい方法を調べたいと思います。
sudo bash --login
LOGGING_LEVEL=info TREMA_TMP=$HOME/trema/work/trema trema run -d -c ~/trema/work/sliceable_switch/etc/sliceable.conf
sliceable switch の設定ファイルを引数に指定して trema を実行します。
デバッグレベルを変更する場合は TREMA_LOG_LEVEL で debug などを指定します。
TREMA_TMP 以下に一時ファイル、ログなどが生成されます。

きちんと起動していることを確認しておきます。
$ ps auxw | grep trema
root   24938 0.0 0.0 15024 1844 ?    Ss  17:50  0:00 /home/ubuntu/.rvm/gems/ruby-2.0.0-p353/gems/trema-0.4.6/objects/switch_manager/switch_manager --daemonize --port=6653 -- port_status::topology packet_in::filter state_notify::topology vendor::sliceable_switch
root   24940 0.0 0.0 15216 2044 ?    Ss  17:50  0:00 /home/ubuntu/.rvm/gems/ruby-2.0.0-p353/gems/trema-0.4.6/objects/packetin_filter/packetin_filter --daemonize --name=filter lldp::topology_discovery packet_in::sliceable_switch
root   24942 0.0 0.0 15284 2364 ?    Ss  17:50  0:00 /home/ubuntu/trema/apps/./topology/topology --name topology -d
root   24944 0.0 0.0 15608 2664 ?    Ss  17:50  0:00 /home/ubuntu/trema/apps/./topology/topology_discovery --name topology_discovery -d
root   24946 0.0 0.0 16752 3576 ?    Ss  17:50  0:00 /home/ubuntu/trema/apps/./flow_manager/flow_manager --name flow_manager -d
root   24948 0.0 0.2 21588 8652 ?    Ss  17:50  0:00 /home/ubuntu/trema/apps/./sliceable_switch/sliceable_switch --name sliceable_switch -d -s /home/ubuntu/trema/work/sliceable_switch/db/slice.db -a /home/ubuntu/trema/work/sliceable_switch/db/filter.db
ubuntu  25048 0.0 0.0  8108  896 pts/0  R+  17:53  0:00 grep --color=auto trema
6653/tcp と 8888/tcp が LISTEN されています。 6653 は OpenFlow の controller channel (secure channel) です。 8888 は Sliceable Switch の仮想ネットワークを操作するための REST API です。
$ netstat -ntl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address      Foreign Address     State
tcp    0   0 0.0.0.0:80       0.0.0.0:*        LISTEN
tcp    0   0 0.0.0.0:22       0.0.0.0:*        LISTEN
tcp    0   0 0.0.0.0:8888      0.0.0.0:*        LISTEN
tcp    0   0 0.0.0.0:6653      0.0.0.0:*        LISTEN
tcp6    0   0 :::22          :::*          LISTEN
OpenFlow Controller の準備は終わりです。

OpenStack Controller ノード


devstack を使ってインストールします。
パッケージを使った手順はhttps://github.com/amotoki/openstack-havana-install-guide/wiki/ControllerNodeに書いていますので、参考にして下さい。

localrc はこんな感じです。

KEYSTONE_TOKEN_FORMAT=UUID
PRIVATE_NETWORK_NAME=net1
PUBLIC_NETWORK_NAME=ext_net

disable_service n-net
enable_service neutron q-svc q-agt
enable_service q-dhcp
enable_service q-l3
enable_service q-meta

Q_USE_DEBUG_COMMAND=True
Q_PLUGIN=nec
GRE_LOCAL_IP=10.56.45.216:10.56.45.226
OFC_DRIVER=trema
OFC_API_HOST=10.56.45.218
OFC_API_PORT=8888
OFC_OFP_HOST=10.56.45.218
OFC_OFP_PORT=6653

LOGDIR=$DEST/logs
SCREEN_LOGDIR=$LOGDIR
LOGFILE=$LOGDIR/devstack.log
ADMIN_PASSWORD=pass
MYSQL_PASSWORD=stackdb
RABBIT_PASSWORD=stackqueue
SERVICE_PASSWORD=$ADMIN_PASSWORD
SERVICE_TOKEN=xyzpdqlazydog

Neutron を有効にして、プラグインは NEC OpenFlow Plugin を指定しています。OpenFlow Controller の情報を指定して実行します。ノード間は GRE トンネルで接続するので、GRE で接続するノードリストを指定しています。

./stack.sh を実行して待ちましょう。

OpenStack Compute Node ノード


こちらも同様に devstack を使ってインストールします。
パッケージを使った手順は XXXXXX に書いていますので、参考にして下さい。

localrc はこんな感じです。こちらはいたってシンプルです。
USE_NEUTRON=True

CC_HOST=10.56.45.216
MYSQL_HOST=${CC_HOST}
SERVICE_HOST=${CC_HOST}
RABBIT_HOST=${CC_HOST}
Q_HOST=${CC_HOST}

HOST_IP=$(get_host_ip)

ENABLED_SERVICES=n-cpu,rabbit

enable_service n-novnc
VNCSERVER_PROXYCLIENT_ADDRESS=$HOST_IP
VNCSERVER_LISTEN=$HOST_IP

enable_service q-agt

Q_PLUGIN=nec
GRE_REMOTE_IPS=10.56.45.216:10.56.45.226
OFC_OFP_HOST=${CC_HOST}

LOGDIR=$DEST/logs
SCREEN_LOGDIR=$LOGDIR
LOGFILE=$LOGDIR/devstack.log
LOG_COLOR=False

ADMIN_PASSWORD=pass
MYSQL_PASSWORD=stackdb
RABBIT_PASSWORD=stackqueue
SERVICE_PASSWORD=$ADMIN_PASSWORD
SERVICE_TOKEN=xyzpdqlazydog
こちらもしばらく待ちます。

初期状態の確認


一通り動かし終わったので、状態を見てみましょう。

まずは Neutron 側の情報から。
$ cd devstack
$ . openrc
$ neutron net-list
+--------------------------------------+---------+--------------------------------------------------+
| id                                   | name    | subnets                                          |
+--------------------------------------+---------+--------------------------------------------------+
| f567b464-2968-4d78-a884-875259bc9fc0 | net1    | 042d74c4-434a-4f52-884d-61c10539d2de 10.0.0.0/24 |
| ff946453-aa0e-492c-af8a-f0c53be78448 | ext_net | 73c5c8ca-8c94-4921-88a4-af77ef000fb8             |
+--------------------------------------+---------+--------------------------------------------------+
$ neutron net-show net1
+-----------------+--------------------------------------+
| Field           | Value                                |
+-----------------+--------------------------------------+
| admin_state_up  | True                                 |
| id              | f567b464-2968-4d78-a884-875259bc9fc0 |
| name            | net1                                 |
| router:external | False                                |
| shared          | False                                |
| status          | ACTIVE                               |
| subnets         | 042d74c4-434a-4f52-884d-61c10539d2de |
| tenant_id       | c980a2144ebc4a2dbeb0562218b96fb9     |
+-----------------+--------------------------------------+
$ neutron port-list -c id -c device_owner -c fixed_ips
+--------------------------------------+--------------------------+---------------------------------------------------------------------------------+
| id                                   | device_owner             | fixed_ips                                                                       |
+--------------------------------------+--------------------------+---------------------------------------------------------------------------------+
| 26755062-0bb2-41ff-a85c-95c927d2f5d1 | network:dhcp             | {"subnet_id": "042d74c4-434a-4f52-884d-61c10539d2de", "ip_address": "10.0.0.3"} |
| c8993f73-f737-4cd5-9736-4194cb6624db | compute:probe            | {"subnet_id": "042d74c4-434a-4f52-884d-61c10539d2de", "ip_address": "10.0.0.2"} |
| f48d65b7-85e0-4389-b271-144bde7b8b58 | network:router_interface | {"subnet_id": "042d74c4-434a-4f52-884d-61c10539d2de", "ip_address": "10.0.0.1"} |
+--------------------------------------+--------------------------+---------------------------------------------------------------------------------+
次に OpenFlow Controller 側の情報です。
$ netstat -nt
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address      Foreign Address     State
tcp    0   0 10.56.45.218:6653    10.56.45.226:55373   ESTABLISHED
tcp    0   0 10.56.45.218:6653    10.56.45.216:46843   ESTABLISHED
tcp    0   0 10.56.45.218:22      10.56.45.227:52031   ESTABLISHED
6653/tcp は OpenFlow の control channel です。 6653/tcp の接続が二つあります。
Controller ノードと Compute ノードの OVS br-int が OpenFlow Switch として動作していて、接続に来ていることがわかります。

br-int の設定方法は Install Guide の "Setup datapath bridge" https://github.com/amotoki/openstack-havana-install-guide/wiki/ComputeNodeNeutronNecPlugin を見てください。
set-controller というコマンドを実行すると、OpenFlow Switch として動作します。
ovs-vsctl --no-wait set-controller br-int tcp:10.56.45.210:6653
trema のログを見てみましょう。
trema では switch_manager が接続をうけて、個別の switch daemon を起動します。
switch.0xXXXXXXXXXXXXX.log があることから OVS から接続に来ていることが分かります。
% ls -1l trema/log/
total 12
-rw-r--r-- 1 root root  0 Dec 11 19:18 filter.log
-rw-r--r-- 1 root root  0 Dec 11 19:18 flow_manager.log
-rw-r--r-- 1 root root 6121 Dec 11 19:24 sliceable_switch.log
-rw-rw-rw- 1 root root  0 Dec 11 19:21 switch.0x10056045216.log
-rw-rw-rw- 1 root root  0 Dec 11 19:24 switch.0x10056045226.log
-rw-r--r-- 1 root root  0 Dec 11 19:18 switch_manager.log
-rw-r--r-- 1 root root  0 Dec 11 19:18 topology_discovery.log
-rw-r--r-- 1 root root  82 Dec 11 19:24 topology.log
sliceable_switch.log を見てみます。
以下は dpid = 0x10056045216 の OVS から接続があったことが分かります。
Wed Dec 11 19:21:12 2013 [info] Adding a port: dpid = 0x10056045216, port = 65534 ( "br-int" )
Wed Dec 11 19:22:04 2013 [info] Adding a port: dpid = 0x10056045216, port = 1 ( "tapc8993f73-f7" )
Wed Dec 11 19:22:09 2013 [info] Adding a port: dpid = 0x10056045216, port = 2 ( "tap26755062-0b" )
Wed Dec 11 19:22:17 2013 [info] Adding a port: dpid = 0x10056045216, port = 3 ( "tapf48d65b7-85" )
devstack の中で Neutron Plugin が仮想ネットワークの REST API が呼ばれて、スライス定義が登録されています。
Wed Dec 11 19:18:22 2013 [info] Loading slice definitions.
Wed Dec 11 19:18:22 2013 [info] Adding a port-slice binding ( type = 0x1, datapath_id = 0x10056045216, port = 0x1, vid = 0xffff, slice_number = 0x1, id = 3a084cc4-c090-456f-ac79-7acc9aa20c08, dynamic = 0, updated_at = 1386757102 ).
Wed Dec 11 19:18:22 2013 [info] Adding a port-slice binding ( type = 0x1, datapath_id = 0x10056045216, port = 0x2, vid = 0xffff, slice_number = 0x1, id = def41b36-0d8b-4651-b0dc-b6ede86877a3, dynamic = 0, updated_at = 1386757102 ).
Wed Dec 11 19:18:22 2013 [info] Adding a port-slice binding ( type = 0x1, datapath_id = 0x10056045216, port = 0x3, vid = 0xffff, slice_number = 0x1, id = 59392aa3-8779-403e-92b3-bdc8805630b9, dynamic = 0, updated_at = 1386757102 ).
Wed Dec 11 19:18:22 2013 [info] Adding a port-slice binding ( type = 0x1, datapath_id = 0x10056045216, port = 0x1, vid = 0xffff, slice_number = 0x3, id = 6dfd6bf6-ce17-409a-85f3-6b12f0059570, dynamic = 0, updated_at = 1386757102 ).
Sliceable Switch 側での仮想ネットワーク情報の確認もしてみます。期待通り。
% SLICE_DB_FILE=/home/ubuntu/trema/work/sliceable_switch/db/slice.db ./slice list
               ID               Description
f567b464-2968-4d78-a884-875259bc9fc0  ID=f567b464-2968-4d78-a884-875259bc9fc0 Name=net1 at Neutron.
ff946453-aa0e-492c-af8a-f0c53be78448  ID=ff946453-aa0e-492c-af8a-f0c53be78448 Name=ext_net at Neutron.

% SLICE_DB_FILE=/home/ubuntu/trema/work/sliceable_switch/db/slice.db ./slice show f567b464-2968-4d78-a884-875259bc9fc0
[Description]
ID=f567b464-2968-4d78-a884-875259bc9fc0 Name=net1 at Neutron.

[Port-based bindings]
           ID         Datapath ID    Port       VID
f48d65b7-85e0-4389-b271-144bde7b8b58      0x10056045216      3      65535
26755062-0bb2-41ff-a85c-95c927d2f5d1      0x10056045216      2      65535
c8993f73-f737-4cd5-9736-4194cb6624db      0x10056045216      1      65535

[MAC-based bindings]
No bindings found.

[MAC-based bindings on ports]
No bindings found.

Open vSwitch を見てみます。
$ sudo ovs-vsctl show
ce91e39a-ec92-4a6f-9fbe-d0c8f742c7a3
  Bridge br-ex
    Port "tap9632e3f8-53"
      Interface "tap9632e3f8-53"
    Port br-ex
      Interface br-ex
        type: internal
    Port "tap75223dc9-8f"
      Interface "tap75223dc9-8f"
  Bridge br-int
    Controller "tcp:10.56.45.218:6653"
      is_connected: true
    fail_mode: secure
    Port "tapf48d65b7-85"
      Interface "tapf48d65b7-85"
    Port br-int
      Interface br-int
        type: internal
    Port "tap26755062-0b"
      Interface "tap26755062-0b"
    Port "tapc8993f73-f7"
      Interface "tapc8993f73-f7"
  ovs_version: "1.10.2"
connected: true になっていて、接続されています。
br-int には Neutron のポートに対応するインタフェースがあることが分かります。

Compute Node の方も同じように試してみてください。
devstack を Controller Node で先に実行しているので、こちらには何もありません。

VM を起動してみる


ここで VM を起動してみましょう。
$ nova boot --image tty-quantum --flavor m1.tiny vm1
$ OS_USERNAME=admin OS_TENANT_NAME=admin nova hypervisor-servers ostack
+--------------------------------------+-------------------+---------------+---------------------+
| ID                                   | Name              | Hypervisor ID | Hypervisor Hostname |
+--------------------------------------+-------------------+---------------+---------------------+
| 9170da74-be92-4df4-8f6a-3963de13eede | instance-00000003 | 1             | ostack05            |
| a0d1f35a-0200-4145-9c17-470710f31dd0 | instance-00000004 | 2             | ostack06            |
+--------------------------------------+-------------------+---------------+---------------------+
$ OS_USERNAME=admin OS_TENANT_NAME=admin nova hypervisor-list
+----+---------------------+
| ID | Hypervisor hostname |
+----+---------------------+
| 1  | ostack05            |
| 2  | ostack06            |
+----+---------------------+
今回は Compute ノード側で起動しました。

console.log を見て、アドレスが割り当てられているか確認しましょう。

Horizon のコンソールからログインして ping が通れば成功です。

時間もせまってきたようなので、そろそろ終わりにしようと思います。
一応うまく行ったみたいです。
飲みながらやっていると、全然進みませんね。