2011年8月7日日曜日

CentOS 6.0 で NIC と ethX の対応を固定化する

CentOS 6.0 で NIC 交換 (オンボードの場合はマザーボード交換も含む) した場合でも、ethX が変化しないように、固定化する方法です。RHEL6 でも同様にして可能。
2015-01-18追記、CentOS7/RHEL7についてはこちらを参照。

CentOS 6.0 のデフォルトでは、MAC アドレスと ethX を対応付けており、交換により MAC が変化すると、自動的に新たな対応関係が作られるようになっているため、ethX がずれてしまいます。対応関係は、/etc/udev/rules.d/70-persistent-net.rules に設定されます。
このあたりについては、前に書いた記事を参照してください。

CentOS 6.0 で NIC 交換した場合の挙動
CentOS 6.0 で NIC と ethX の対応を変更する

以上が基礎知識ですが、まずは、この 70-persistent-net.rules を無効化します。
少々、荒っぽいやり方ですが、ルールが自動生成されないように、/dev/null へシンボリックリンクを張ってしまいます。
[root@centos6 ~]# ln -s -f /dev/null /etc/udev/rules.d/70-persistent-net.rules
[root@centos6 ~]# ls -l /etc/udev/rules.d/70-persistent-net.rules
lrwxrwxrwx 1 root root 9 Aug  7 12:07 /etc/udev/rules.d/70-persistent-net.rules -> /dev/null
このとき messages に、次のメッセージが出ますが、一時的なものなので、気にする必要はありません。
Aug  7 12:07:22 centos6 udevd[406]: can not read '/etc/udev/rules.d/70-persistent-net.rules'

次に、/etc/udev/rules.d/65-eth.rules ファイルを新規作成して、次のように記載します。
ACTION=="add", KERNEL=="eth*", ID=="0000:02:01.0", DRIVERS=="?*", ATTR{type}=="1", NAME="eth2", OPTIONS="last_rule"
ACTION=="add", KERNEL=="eth*", ID=="0000:02:04.0", DRIVERS=="?*", ATTR{type}=="1", NAME="eth3", OPTIONS="last_rule"
ここで、0000:02:01.0 や 0000:02:04.0 は PCI アドレスです。lspci で表示される値に、0000: (domain と呼ばれる管理番号ですが、普通のマシンは 0000 です) をつけた値です。この PCI アドレスは、ethtool コマンドで確認することもできます。
[root@centos6 ~]# ethtool -i eth2
driver: e1000
version: 7.3.21-k6-NAPI
firmware-version: N/A
bus-info: 0000:02:01.0
[root@centos6 ~]# ethtool -i eth3
driver: e1000
version: 7.3.21-k6-NAPI
firmware-version: N/A
bus-info: 0000:02:04.0
書き忘れそうでしたが、この方法を用いる場合は、/etc/sysconfig/network-scripts/ifcfg-ethX の HWADDR= は設定しないほうが良いです。設定した場合は、MAC のチェックが行われ、一致しなければ ifup が失敗します。

最後に、再起動します。設定内容によっては、立ち上げ時に、ethX の入れ替えを行ったことを示すメッセージが出力されます。
Aug  7 12:45:05 centos6 kernel: udev: renamed network interface eth0 to eth2
Aug  7 12:45:05 centos6 kernel: udev: renamed network interface eth1 to eth3
この環境では、NIC は 2本 (eth0, eth1) なのですが、ここで紹介した PCI アドレスによる固定化方法により、eth2 および eth3 に変更しています。

udev に関して、次の記事を一読されると理解が深まるものと思います。

参考URL:
http://gihyo.jp/dev/serial/01/sc-literacy/0015?page=1
http://donko.jp/LFS/LFS6.4jp/chapter07/network.html

2011-08-12追記
Fedora 15 では、biosdevname が使えるとか。参考メモ。
http://ja.community.dell.com/techcenter/b/weblog/archive/2011/08/03/fedora-15.aspx
2011-12-10追記、RHEL6.1 以降でもbiosdevnameが利用できるようです。DellマシンではデフォルトON、その他ベンダではデフォルトOFF。ブートパラメータとしてbiosdevname={0|1} を渡すことで切り替えも可能。HW が対応している必要があるので、事前に biosdevname コマンド(-i ethXX オプション)で名前解決可能かどうか確かめたほうがいいです。ただ、実際に試してみると、em1 や p1p1 みたいなインタフェース名って気色悪く感じました。あと、おそらく ethXX を決め打ちにしているアプリケーションがありそうなので、まだまだ業務サーバで利用はできないと思います。きっと普及までには5年ぐらいの歳月がかかるのではないかと思う。
なお、ブートパラメータとして指定する biosdevname=1 は、カーネルが解釈するわけではありません。Fedora 15 以降 または RHEL6.1 以降の環境で、/lib/udev/rules.d/71-biosdevname.rules を参照してください。この中から /proc/cmdline を読み取るという仕掛けのようです。/proc/cmdline を伝言板のように使うこの実装は醜いと思うんですがね。


2011-08-17追記
Fedora 15 で、上に書いた 65-eth.rules を使うと、ID= は将来の udev で廃止になるから使うなというようなメッセージが出るようです。
Aug 18 00:20:35 fedora15 udevd[358]: ID= will be removed in a future udev version, please use KERNEL= to match the event device, or KERNELS= to match a parent device, in /etc/udev/rules.d/65-eth.rules:2
そこで、別解です。次のルールであれば、Fedora 15 でも CentOS 6.0 でも使えるようです。
ACTION=="add", SUBSYSTEMS=="pci", KERNELS=="0000:02:01.0", DRIVERS=="?*", NAME="eth2", OPTIONS="last_rule"
ACTION=="add", SUBSYSTEMS=="pci", KERNELS=="0000:02:04.0", DRIVERS=="?*", NAME="eth3", OPTIONS="last_rule"
udev ルールに使える attribute は、次のようにして確認できます。
[root@centos6 ~]# udevadm info -a -p /sys/class/net/eth2

Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.

  looking at device '/devices/pci0000:00/0000:00:11.0/0000:02:01.0/net/eth2':
    KERNEL=="eth2"
    SUBSYSTEM=="net"
    DRIVER==""
    ATTR{addr_assign_type}=="0"
    ATTR{addr_len}=="6"
    ATTR{dev_id}=="0x0"
    ATTR{ifalias}==""
    ATTR{iflink}=="2"
    ATTR{ifindex}=="2"
    ATTR{features}=="0x10ba9"
    ATTR{type}=="1"
    ATTR{link_mode}=="0"
    ATTR{address}=="00:0c:29:xx:xx:xx"
    ATTR{broadcast}=="ff:ff:ff:ff:ff:ff"
    ATTR{carrier}=="1"
    ATTR{speed}=="1000"
    ATTR{duplex}=="full"
    ATTR{dormant}=="0"
    ATTR{operstate}=="up"
    ATTR{mtu}=="1500"
    ATTR{flags}=="0x1003"
    ATTR{tx_queue_len}=="1000"

  looking at parent device '/devices/pci0000:00/0000:00:11.0/0000:02:01.0':
    KERNELS=="0000:02:01.0"
    SUBSYSTEMS=="pci"
    DRIVERS=="e1000"
    ATTRS{vendor}=="0x8086"
    ATTRS{device}=="0x100f"
    ATTRS{subsystem_vendor}=="0x15ad"
    ATTRS{subsystem_device}=="0x0750"
    ATTRS{class}=="0x020000"
    ATTRS{irq}=="19"
    ATTRS{local_cpus}=="3"
    ATTRS{local_cpulist}=="0-1"
    ATTRS{modalias}=="pci:v00008086d0000100Fsv000015ADsd00000750bc02sc00i00"
    ATTRS{numa_node}=="-1"
    ATTRS{enable}=="1"
    ATTRS{broken_parity_status}=="0"
    ATTRS{msi_bus}==""

  looking at parent device '/devices/pci0000:00/0000:00:11.0':
    KERNELS=="0000:00:11.0"
    SUBSYSTEMS=="pci"
    DRIVERS==""
    ATTRS{vendor}=="0x15ad"
    ATTRS{device}=="0x0790"
    ATTRS{subsystem_vendor}=="0x0000"
    ATTRS{subsystem_device}=="0x0000"
    ATTRS{class}=="0x060401"
    ATTRS{irq}=="0"
    ATTRS{local_cpus}=="3"
    ATTRS{local_cpulist}=="0-1"
    ATTRS{modalias}=="pci:v000015ADd00000790sv00000000sd00000000bc06sc04i01"
    ATTRS{numa_node}=="-1"
    ATTRS{enable}=="1"
    ATTRS{broken_parity_status}=="0"
    ATTRS{msi_bus}=="1"

  looking at parent device '/devices/pci0000:00':
    KERNELS=="pci0000:00"
    SUBSYSTEMS==""
    DRIVERS==""

2015-01-16追記
RHEL7/CentOS7 の場合について、別の記事を書きました。

2011年8月6日土曜日

CentOS の bonding の arp_validate オプション

CentOS 5 および CentOS 6 の bonding で ARP 監視を行う場合、arp_validate というオプションを利用できます。
以下、その処理内容についてのメモです。

 Bladeサーバ            Blade収納ユニット
┌──────────┐──────────────┐
│              active│          ┌───┐Blade   │   Blade外部switch
│    ┌──┐  ┌──┤          │      │内部switch  ┌───┐
│    │    ├─┤eth0├─────┤ SW1  ├─────┤      │        
│    │    │  └──┤→…………………………………………┐    │  ┌───┐
│    bond0 │        │ARP要求   └───┘        │  │SW3 │  arp_ip_target
│    │192.168.50.111│broadcast ┌───┐        │  │    ├─┤192.168.50.222
│    │    │  ┌──┤←…………………………………………┴………→│      │
│    │    ├─┤eth1├─────┤ SW2  ├──────┤      │  └───┘
│    └──┘  └──┤          │      │        │  └───┘
│              backup│          └───┘        │
└──────────┘──────────────┘

Bladeサーバの場合、上図のように、収納ユニット内部にスイッチ (SW1 および SW2) が実装される構造になっていることがあります。この場合、部分の障害を検出できるように ARP 監視を用いることができます。
注記:内部スイッチが、部分のリンク障害時に、eth0---SW1 間のリンクを無効化するという機能(UFD: Uplink Failure Detection)を備えている場合があります。機能があるなら、併用するのがいいのではと思います。スイッチの障害対応機能が完璧に動くかどうか?という側面もあるため、スイッチ機能+MII 監視ではなく、スイッチ機能+ARP 監視が良いものと思います。
ただし、ARP 監視のデフォルト動作 (arp_validate=0) では、受信カウンタのチェックのみ行われるため、隣のBladeサーバが同様に ARP 監視 (ARP要求のbroadcast送信) を行ってしまうと、正しく障害検知出来なくなります。

arp_validate=3 を設定すると、受信した ARP パケットの正当性を確認する処理が動くようになります。active (上図eth0) では、arp_ip_target からの ARP 応答を受信したかどうかの確認が行われるようになります。一方、わかりにくいところですが、backup (上図eth1) では、active (上図eth0) から送信された ARP 要求 (broadcast) を受信したかどうかの確認が行われるようになります。ドライバソース上、この ARP 確認処理の核心部分は、drivers/net/bonding/bond_main.c の次の箇所です。
   2741 static int bond_arp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
   2742 {
...
   2789         /*
   2790          * Backup slaves won't see the ARP reply, but do come through
   2791          * here for each ARP probe (so we swap the sip/tip to validate
   2792          * the probe).  In a "redundant switch, common router" type of
   2793          * configuration, the ARP probe will (hopefully) travel from
   2794          * the active, through one switch, the router, then the other
   2795          * switch before reaching the backup.
   2796          */
   2797         if (slave->state == BOND_STATE_ACTIVE)
   2798                 bond_validate_arp(bond, slave, sip, tip);
   2799         else
   2800                 bond_validate_arp(bond, slave, tip, sip);
   2801
...
"drivers/net/bonding/bond_main.c"
2798行目が、active 側の確認 (arp_ip_target からの ARP 応答であるか?) です。
2800行目が、backup 側の確認 (arp_ip_target に対する ARP 要求であるか?) です。
掲載したソースは、2.6.18-164.el5 (CentOS 5.5 のカーネル) のものですが、2.6.32-71.el6 (CentOS 6.0 のカーネル) でも、全く同じです。

最後に、この記事の図に対応する設定例サンプル (/etc/sysconfig/network-scripts/ifcfg-bond0, ifcfg-eth0, ifcfg-eth1) を載せます。
#
# network-scripts/ifcfg-bond0
#
DEVICE=bond0
ONBOOT=yes
BOOTPROTO=static
IPADDR=192.168.50.111
NETMASK=255.255.255.0
GATEWAY=192.168.50.254
BONDING_OPTS="mode=1 arp_interval=1200 arp_ip_target=192.168.50.222 arp_validate=3"
USERCTL=no
NM_CONTROLLED=no
arp_interval=1200 ミリ秒を勧めます。sysctl の net.ipv4.neigh.default.locktime (単位10ミリ秒) よりも長い値。
#
# network-scripts/ifcfg-eth0
#
DEVICE=eth0
MASTER=bond0
SLAVE=yes
BOOTPROTO=none
HWADDR=00:0C:29:xx:xx:xx
USERCTL=no
NM_CONTROLLED=no
#
# network-scripts/ifcfg-eth1
#
DEVICE=eth1
MASTER=bond0
SLAVE=yes
BOOTPROTO=none
HWADDR=00:0C:29:yy:yy:yy
USERCTL=no
NM_CONTROLLED=no

2011-08-08追記
どうやら Internet Explorer だと、テキストで書いた図が歪むようですので、PNG を貼ります。Chrome と Firefox ではきれいに見えます。IE の方は試してみては。

2011年8月5日金曜日

Fedora 15 で Linux 3.0

Fedora 15 の最新カーネル 2.6.40-4.fc15 は、実質は Linux 3.0 です。
rpm の changelog に次のようにあります。
# rpm -q --changelog kernel-2.6.40-4.fc15 | head -14
* Fri Jul 29 2011 Dave Jones  2.6.40-4
- Re-add utrace, which got accidentally dropped during the rebase.

* Thu Jul 28 2011 Dave Jones  2.6.40-3
- Fix module-init-tools conflict:

* Thu Jul 28 2011 Dave Jones  2.6.40-2
- fix crash in scsi_dispatch_cmd()

* Thu Jul 28 2011 Dave Jones  2.6.40-1
- Turn off debugging options. (make release)

* Tue Jul 26 2011 Dave Jones  2.6.40-0
- Rebase to final 3.0 (munge to 2.6.40-0)
おそらく、カーネルのバージョンにより処理内容を変えるアプリケーションへの配慮のためか、2.6.40 ということにしてあります。
以下、この 2.6.40-4.fc15 に含まれる config を使って、Linux 3.0 をビルドする手順です。バージョン表示だけのことではありますが、新鮮な気分を味わえます。

(1) Fedora 15 の動作環境を用意して、カーネル 2.6.40-4.fc15 までアップデートする。ただし、ビルドのためには、空き領域が 8GB 程度必要です。

(2) 開発用ツールをインストールする。
# yum groupinstall "Development Tools"

(3) http://www.kernel.org/ から linux-3.0.tar.bz2 を入手して展開する。
# cd /usr/src  ※これは例です。ほかの場所でも良い
# tar xf /tmp/linux-3.0.tar.bz2

(4) Makefile の EXTRAVERSION を設定する。
VERSION = 3
PATCHLEVEL = 0
SUBLEVEL = 0
EXTRAVERSION = -0.my15.x86_64  ※これは例です。自分の好みの文字列を指定すれば良い
...

(5) 2.6.40-4.fc15 の config をコピーする。
# cd /usr/src/linux-3.0
# cp /boot/config-2.6.40-4.fc15.x86_64 .config

(6) ビルドを実行する。もしも、2.6.38.8-35.fc15 等の少し古い config を用いた場合、新しく増えたオプションをどう設定するか問い合わせて来ます。2.6.40-4.fc15 であれば、オプション集合が一致しているので、何も聞かれることはなく、そのままコンパイルが進行します。
# make HOSTCXX="ccache g++" CC="ccache gcc"

(7) 出来上がったモジュールとカーネルをインストールする。
# make modules_install
# make install

(8) grub.conf の default を修正して再起動する。または、再起動時に GRUB メニューから作成した Linux 3.0 のエントリーを選択して起動する。

(9) uname -a で、カーネルバージョンを確認する!
# uname -a
Linux fedora15 3.0.0-0.my15.x86_64 #1 SMP Thu Aug 4 05:21:08 JST 2011 x86_64 x86_64 x86_64 GNU/Linux

2011-08-06追記
2.6.40-4.fc15 のアナウンス内容です。
http://lists.fedoraproject.org/pipermail/package-announce/2011-August/063271.html
Rebase to 3.0. Version reports as 2.6.40 for compatibility with older userspace.

だそうです。

2011-08-07追記
Linux のバージョン番号と歴史について、次の記事にまとめられています。
http://gihyo.jp/lifestyle/serial/01/ganshiki-soushi/0023

2011-08-09追記
手順 (6) で、make の並列化オプション --jobs=N (N は core 数 x 2 程度の自然数) を指定すると、ビルド時間を短縮できるようです。手元の 2core の環境で、--jobs=4 を指定したところ、確かにコンパイル時間が半分程度で済みました。

2011-08-14追記
ccache についての解説が下記にあります。
http://www.ibm.com/developerworks/jp/linux/library/l-ccache/

2011-09-09追記
Fedora 16 Alpha が出ており、そちらのカーネルは既に 3.0 になっているので、ビルドまではしたくない方は、そちらを試してみては。
人気ブログランキングへ にほんブログ村 IT技術ブログへ