2014年12月16日火曜日

Linux で veth のペアのデバイスを調べる方法

この記事は、OpenStack Advent Calendar の 12/16 の記事です。 Advent Calendar らしく軽い小ネタを紹介したいと思います。

OpenStack Neutron を使っていると veth のペアがたくさん作成されます。 @enakai00 さんが書いた nova-compute内のネットワーク詳細 の図を見ると、veth pai がたくさん作成されるのが分かります。

ネットワークデバイスの種類を知る方法

VM が2個しか起動していない Compute Node でもたくさんのデバイスがあります。 ネットワークデバイスにはいろいろ種類があり、通常のネットワークデバイス以外にも、 linux bridge, tap device, veth (virtual ethernet device) などいろいろあります。 でも、ip link コマンドなどを使っても、その種類は通常表示されず、名前しか情報源がありません。

-d オプションを付けて ip link コマンドを実行すると、びっくりデバイスの種類が表示されます。 これを見ると qbr0f657850-c2bridgetap0f657850-c2 は tap (tun) デバイス、 qvb0f657850-c2veth デバイスだと分かります。

この -d オプション、ip(8) コマンドのマニュアルを見ても出て来ません。どうしてなのでしょうか? どなたかご存知でしたら教えて下さい。

ubuntu@stack02:~$ ip -d link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 promiscuity 0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
link/ether 52:54:00:06:f7:0e brd ff:ff:ff:ff:ff:ff promiscuity 0
3: ovs-system: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default
link/ether 7a:1a:cb:27:31:87 brd ff:ff:ff:ff:ff:ff promiscuity 1
4: br-int: <BROADCAST,UP,LOWER_UP> mtu 1400 qdisc noqueue state UNKNOWN mode DEFAULT group default
link/ether 9e:0d:03:df:e9:44 brd ff:ff:ff:ff:ff:ff promiscuity 1
6: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default
link/ether fa:af:f9:17:d9:91 brd ff:ff:ff:ff:ff:ff promiscuity 0
bridge
7: qbr0f657850-c2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1400 qdisc noqueue state UP mode DEFAULT group default
link/ether 62:d9:1f:5e:46:b5 brd ff:ff:ff:ff:ff:ff promiscuity 0
bridge
8: br-tun: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN mode DEFAULT group default
link/ether 06:67:1b:78:f4:48 brd ff:ff:ff:ff:ff:ff promiscuity 1
9: qvo0f657850-c2: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1400 qdisc pfifo_fast master ovs-system state UP mode DEFAULT group default qlen 1000
link/ether 0e:5a:08:46:0b:eb brd ff:ff:ff:ff:ff:ff promiscuity 2
veth
10: qvb0f657850-c2: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1400 qdisc pfifo_fast master qbr0f657850-c2 state UP mode DEFAULT group default qlen 1000
link/ether 62:d9:1f:5e:46:b5 brd ff:ff:ff:ff:ff:ff promiscuity 2
veth
11: tap0f657850-c2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1400 qdisc pfifo_fast master qbr0f657850-c2 state UNKNOWN mode DEFAULT group default qlen 500
link/ether fe:16:3e:09:9e:9e brd ff:ff:ff:ff:ff:ff promiscuity 1
tun
12: qbr2948dbdf-a4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1400 qdisc noqueue state UP mode DEFAULT group default
link/ether a6:ab:a4:80:f5:13 brd ff:ff:ff:ff:ff:ff promiscuity 0
bridge
13: qvo2948dbdf-a4: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1400 qdisc pfifo_fast master ovs-system state UP mode DEFAULT group default qlen 1000
link/ether e6:af:80:d8:df:9d brd ff:ff:ff:ff:ff:ff promiscuity 2
veth
14: qvb2948dbdf-a4: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1400 qdisc pfifo_fast master qbr2948dbdf-a4 state UP mode DEFAULT group default qlen 1000
link/ether a6:ab:a4:80:f5:13 brd ff:ff:ff:ff:ff:ff promiscuity 2
veth
15: tap2948dbdf-a4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1400 qdisc pfifo_fast master qbr2948dbdf-a4 state UNKNOWN mode DEFAULT group default qlen 500
link/ether fe:16:3e:fd:92:56 brd ff:ff:ff:ff:ff:ff promiscuity 1
tun

veth デバイスのペアを特定する方法

veth デバイスは 2個のネットワークデバイスがセットになっていて、 一方の veth デバイスに入力したパケットはそのままペアになっている veth デバイスに出力されます。

そうすると、どのネットワークデバイスがペアになっているかを知る方法がほしいです。 OpenStack では、ポートIDを元に veth デバイスが作成されるので、名前からペアを推測することはできますが、 やはりシステム上で確認したいものです。

ethtool を使うと veth の相手の veth デバイスを知ることができます。

ubuntu@stack02:~$ sudo ethtool -S qvb2948dbdf-a4
NIC statistics:
     peer_ifindex: 13

peer_ifindex が 13 になっています。 この番号は上の ip link コマンドの出力の左端に表示されているネットワークデバイスの通し番号です。 13 は qvo2948dbdf-a4 が相手だと分かります。

qvo2948dbdf-a4qvb2948dbdf-a4 がペアの veth デバイスということになります。

まとめ

Neutron でたくさん作成されるネットワークデバイスの種類を Linux で確認する方法と、 veth のペアのデバイスを作成する方法を紹介しました。 こういう小ネタもたまっていくと便利ですね。

余談

Neutron で ML2 plugin + OVS mechanism driver を使っていると、 VM のポート毎に veth ペア qvo2948dbdf-a4qvb2948dbdf-a4 とブリッジ qbr2948dbdf-a4 が作成されます。

このデバイス名の由来を見ておきましょう。

  • q: Quantum の q です。これが実装された当時は Neutron ではなく Quantum だった名残です。すでに運用されているシステムがあるので、名前の変更は簡単ではなく q が残っています。
  • 2-3文字目 : 役割を表しています。
    • vo: vveth の頭文字です。o は OVS に接続される方の veth の片割れという意味です。
    • vb: vveth の頭文字です。b は (Linux) bridge に接続される方の veth の片割れという意味です。
    • br: bridge の頭文字です。
  • 4文字目以降 : Neutron Port UUID の前の方の値

2014年12月10日水曜日

openstack.jp のデザインを直してくれる人募集

OpenStack Advent Calendar (2枚目) の 12/10 分です。 最初は 2枚目のカレンダーには書く気は全くなかったのですが、 openstack.jp ウェブサイトのデザインのイケていないところを知ってもらい、 デザインしてくれる人を募集するいい機会だと思いますので、書いてみることにします。

openstack.jp のウェブサイトを見てみましょう。

左上に OpenStack のロゴはありますが、何かいまいちです。 いまいちなところをあげてみましょう。

  • なんか色合いが OpenStack っぽくない。
  • デフォルトのテーマを持ってきて使っている印象を受ける。
  • 最近のサイトだと、サイバーは左よりも右の方が多いかな。サイトの上にメニューがあって、右に追加の情報があることが多いですね。
  • トップページにユーザー会についての情報が二箇所もある。メインコンテンツとサイドバーの下の方。

せめて、色調を OpenStack っぽくして、メニューバーを上に横に並べるだけで、だいぶ改善するように思います。

同じ OpenStack ユーザー会が主催している OpenStack Days Tokyo のウェブサイトはイベント会社が作っているだけあってきちんとしていますね。

OpenStack と一緒に取り上げられることも多い同じ IaaS 基盤である CloudStackEucalyptus の日本ユーザー会のサイトを見てみましょう。色合いも本家と比較的あっていますし、デフォルトの設定のままという感じも薄いので、合格点というところだと思います。 これらに比べてるとだいぶ見劣りがしますね。

実は、半月くらい前はもっといまいちな状態でした。archive.org によると、2014年6月19日時点の様子はこんな感じでした。左上のロゴがテーマのデフォルトのままになっている、同じメニューが上と左にある、といった状況で、あまりにひどいので、直しました。

といろいろデザイン面でいまいちな点を挙げて来ましたが、 2〜3人のボランティアで運用されている状況の中、 コンテンツを更新いただいている方には感謝しています。

デザイン面がよくなれば、openstack.jp もそれなりのサイトになると思いますので、デザインを直してやろうという方がいれば大歓迎です。

2014年2月14日金曜日

OpenStack Third Party Testing: How to use Zuul for your Jenkins

When setting up OpenStack third party testing, it is useful to trigger rechcecking from Gerrit comment such as recheck no bug or recheck-<vendor> and there is an onging discussion whether recheck support should be a requirement.

This blog post describes the manual procedure of Zuul and how to migrate the trigger of Jenkins jobs from gerrit trigger jenkins plugin to Zuul.

After migrating to Zuul, I feel it is nice and makes it easy to control Jenkins jobs trigger flexibly.

If you are interested in setting up Zuul by puppet, please check the puppet manifests from Jay Pipes. https://github.com/jaypipes/os-ext-testing

Prerequisite

  • Ubuntu 12.04.3 LTS

Zuul setup

Installation

Install required dependency packages:

aptitude install python-pip
aptitude install python-webob python-lockfile python-paste
aptitude install python-yaml python-paramiko python-daemon

Create a user and a group for zuul service:

groupadd zuul
useradd -m -d /home/zuul -s /bin/bash -g zuul zuul

Retrieve and install zuul:

git clone https://git.openstack.org/openstack-infra/zuul /opt/zuul
pip install /opt/zuul
Configuration files
Preparation (optional)

puppet module in openstack-infra/config has useful config examples. Checkout them first to somewhere. I refer to the directory where you checkedout openstack-infra/config git repository by <INFRA_CONFIG>.

git clone https://git.openstack.org/openstack-infra/config
/etc/zuul/zuul.conf

Customize the following parameters. The detail description is available at http://ci.openstack.org/zuul/zuul.html#zuul-conf.

The following parameters are important:

  • [gerrit]
    • server : review.openstack.org
    • user : gerrit service account name
    • sshkey : gerrit service account ssh private key
    • baseurl : https://review.openstack.org/ if server field is different from review.openstack.org. It is useful if your zuul server is behind proxy ()or you are using SSH port forwarding to access OpenStack gerrit).
  • [zuul]
    • url_pattern : URL of each Jenkins job. Usually used to point a build job.
    • zuul_url : It is used as git repo URL. Jenkins job fetches a commit from this URL.
    • status_url : There is no need to customize it unless you post a start message.
[gearman]
server=127.0.0.1

[gearman_server]
start=true
log_config=/etc/zuul/gearman-logging.conf

[gerrit]
server=review.openstack.org
user=jenkins
sshkey=/var/lib/zuul/ssh/id_rsa

[zuul]
layout_config=/etc/zuul/layout.yaml
log_config=/etc/zuul/logging.conf
state_dir=/var/lib/zuul
git_dir=/var/lib/zuul/git
push_change_refs=false
url_pattern=http://<your log server>/logs/{job.name}/{build.number}
status_url=http://status.openstack.org/zuul/
job_name_in_report=true
zuul_url=http://ostack10.svp.cl.nec.co.jp/p
/etc/zuul

Prepare logging configurations.

cp config/modules/openstack_project/files/zuul/gearman-logging.conf /etc/zuul
cp config/modules/openstack_project/files/zuul/logging.conf /etc/zuul

openstack_functions.py is optional but it is useful to define LOG_PATH or single_use_node (disable a used slave node after the job completes).

cp config/modules/openstack_project/files/zuul/openstack_functions.py /etc/zuul
/etc/init.d/zuul

Create a startup script of zuul.

cp config/modules/zuul/files/zuul.init /etc/init.d/zuul
chmod +x /etc/init.d/zuul
/etc/zuul/layout.yaml

layout.yaml is a heart of zuul. The following is an example I used. The detail description is available at http://ci.openstack.org/zuul/zuul.html#layout-yaml.

  • check pipeline watches three gerrit events from master branch. branch parameter is optional. If you want to watch all branches, remove it.
    • Note that a target branch(es) can also be limited by branch parameter of jobs configuration. branch in jobs configuration selects jobs to be executed, but zuul post a result even when no job is selected. For such case, it looks better to limit a target branch in pipelines configuration.
  • If you remove success and/or failure entries from gerrit trigger definition, a result of a build job will not be posted to gerrit. It is useful while you are preparing zuul and jenkins.

  • If parameter-function: use_single_node is specified, a slave node where the build run will be offline. Enable it depending on your test infra.

includes:
  - python-file: openstack_functions.py

pipelines:
  - name: check
    description: Newly uploaded patchsets enter this pipeline to receive an initial +/-1 Verified vote from Jenkins.
    manager: IndependentPipelineManager
    precedence: low
    trigger:
      gerrit:
        - event: patchset-created
          branch: ^master$
        - event: change-restored
          branch: ^master$
        - event: comment-added
          branch: ^master$
          comment_filter: (?i)^\s*recheck(( (?:bug|lp)[\s#:]*(\d+))|( no bug))\s*$
    success:
      gerrit:
        verified: 1
    failure:
      gerrit:
        verified: -1

jobs:
  - name: ^.*$
    parameter-function: set_log_url
  - name: ^Neutron_Gate$
    parameter-function: single_use_node
  #- name: ^Neutron_Gate$
  #  branch: ^master$

projects:
  - name: openstack/neutron
    check:
      - Neutron_Gate
  - name: openstack-dev/sandbox
    testcheck:
      - TestJob
Create working directories

Create working directories for zuul.

# mkdir /var/log/zuul
# chown zuul /var/log/zuul
# mkdir /var/run/zuul
# chown zuul:zuul /var/run/zuul
# mkdir /var/lib/zuul
# chown zuul:zuul /var/lib/zuul
# mkdir /var/lib/zuul/git
# chown zuul /var/lib/zuul/git
# mkdir /var/lib/zuul/ssh
# chown zuul:zuul /var/lib/zuul/ssh
# chmod 700 /var/lib/zuul/ssh
# mkdir /var/lib/zuul/www
Apache
git repository

Zuul provides a git repository (if push_change_refs=false). The easiest way is to export git repositories via apache.

SetEnv GIT_PROJECT_ROOT /var/lib/zuul/git/
SetEnv GIT_HTTP_EXPORT_ALL

AliasMatch ^/p/(.*/objects/[0-9a-f]{2}/[0-9a-f]{38})$ /var/lib/zuul/git/$1
AliasMatch ^/p/(.*/objects/pack/pack-[0-9a-f]{40}.(pack|idx))$ /var/lib/zuul/git/$1
ScriptAlias /p/ /usr/lib/git-core/git-http-backend/

Enable required apache modues.

a2enmod proxy
a2enmod proxy_http
a2enmod rewrite
status page

(It is not tested yet.)

aptitude install libjs-jquery
cd /opt
git clone https://github.com/mathiasbynens/jquery-visibility.git
cd /var/lib/zuul/www
ln -s /opt/zuul/etc/status/public_html/index.html
ln -s /opt/zuul/etc/status/public_html/app.js
ln -s /usr/share/javascript/jquery/jquery.min.js
ln -s /opt/jquery-visibility/jquery-visibility.js
wget http://getbootstrap.com/2.3.2/assets/bootstrap.zip
unzip bootstrap.zip
rm bootstrap.zip

/etc/apache2/site-enabled/000-default

RewriteEngine on
RewriteRule ^/status.json$ http://127.0.0.1:8001/status.json [P]
Reload apache

Finally make sure apache loads a new configuration.

service apache2 reload
Start Zuul
service zuul start

The detail of command line under the hood is described at http://ci.openstack.org/zuul/zuul.html#starting-zuul.

Jenkins configuration for zuul

Zuul uses Gearman to dispatch build requests to Jenkins and receive build results. Jenkins Gearman plugin needs to be installed.

  1. Install Gearman plugin
  2. In Gearman Plugin config menu, set Gearman server host and port and test connection.
  3. In Gearman Plugin config menu, ensure to check "Enable Gearman".

Migrate Jenkins job trigger to zuul

Jenkins Gearman plugin dispatch Jenkins builds when it received build requests from Zuul (via Gearman), so no build trigger is needed in Jenkins job configruation.

Make sure that remove "Gerrit Event" from "Build Triggers" in Jenkis job configuration.

Otherwise, one gerrit event triggers two Jenkins builds per job through Gerrit Trigger plugin and Zuul.

That's all.

Tips

Defining vendor specific recheck
It is useful to kick only your CI system without affecting other CI systems. The following layout.yaml configuration allows you to trigger your build by a comment recheck-XXXX in addition to the existing recheck no bug or recheck bug NNNNN comments.
    trigger:
      gerrit:
        - event: patchset-created
        - event: change-restored
        - event: comment-added
          comment_filter:
            - (?i)^\s*recheck(( (?:bug|lp)[\s#:]*(\d+))|( no bug))\s*$
            - (?i)^\s*recheck-XXXX\s*$