読者です 読者をやめる 読者になる 読者になる

ytooyamaのブログ

サーバ構築とか、仕事で発見したこととか、趣味のこととかを書いています。

CentOS7でNICのBondingを行うには

重要なこと

CentOS7はNetworkManagerが標準で実行されています。ここは元となっているRed Hat Enterprise Linux 7でも同様です。もしNetworkManagerを有効の状態でBondingを行なってもよければ、NetworkManager GUI、nmcliコマンド、nmtuiコマンドなどで設定を実行できて便利なので、NetworkManagerを生かしたまま、お好みの方法でBondingをした方がいいと思います。詳細はRHEL7のマニュアル「ネットワークガイド第4章 ネットワークボンディングの設定」をご覧ください。OVSでBondingをする場合はNetworkManager/networkサービスのいずれかが正常に動いていれば、どちらでも構いません。

さて、LinuxでBondingを行うには2つの方法があります。一つはKernelのbondingモジュールを使ってカーネルレベルでBondingするという方法です。もう一つはOpenvSwitchを使ってBondingするという方法です。

前者は追加でインストールするものはないのですぐに使えます。OpenvSwitchを使う方法はLinuxにOpenvSwitchをインストールするという手間が追加で発生します。LinuxでBondingをした場合はLinuxの様々なコマンドで状態を確認します。例えばパケットが送受信されているかはtcpdumpコマンドを使うなど。一方、OVSを使ったBondingの方がステータスの確認をするコマンドが充実しているので便利だったりします。

はじめに

実際の手順に入る前に、今回の構成を以下に書いてみます。 サーバーには3つのNICを用意して、うち2つはbonding用、1つは管理用に使います。作業するときは管理用のNIC経由でサーバーにアクセスします。今回の例はeth0とeth2は同じVLANで、eth1はeth0,2とは別のVLANに接続されているのを想定しています。

  • eth0–bonding用
  • eth2–bonding用
  • eth1–管理用(別VLAN)

家庭でBondingを試したい場合は、Linux KVMを使うといいと思います。eth0と2をLinux Bridgeとつなぎ、eth1をKVM標準のNATにつなげば良いと思います。

今回は上に載せるアプリケーションの都合でNetworkManagerを無効化して、従来のnetworkサービスを使う方法について説明します。NetworkManagerが使えるならもっと楽ができるし情報もたくさんあるのですが、そこはまあ仕方ないですね。

LinuxのBondingモジュールで構成する

1) まず、yum updateでシステムを最新の状態に更新します。新しいKernelが追加された場合は再起動します。

2) 次にeth0とeth2の設定を記述します。

HWADDRはNICMACアドレスを記述します。

# vi /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
BOOTPROTO=none
HWADDR=xx:xx:xx:xx:xx:xx
ONBOOT=yes
MASTER=bond0
SLAVE=yes
# vi /etc/sysconfig/network-scripts/ifcfg-eth2
DEVICE=eth2
BOOTPROTO=none
HWADDR=xx:xx:xx:xx:xx:xx
ONBOOT=yes
MASTER=bond0
SLAVE=yes

3) bond0というデバイスを作るため、次のように設定を記述します。

# vi /etc/sysconfig/network-scripts/ifcfg-bond0
DEVICE=bond0
BOOTPROTO=none
ONBOOT=yes
BONDING_OPTS="mode=1 miimon=100"

bondingのモードを切り替えるには上記ネットワーク設定にあるBONDING_OPTSにモードを指定します。設定を反映するにはmodprobe -r bonding &&modprobe bondingなどと実行するか、ホストを再起動しましょう。

4) ifcfg-bond0 にローカルIPを設定します。

...
IPADDR=172.17.14.224
NETMASK=255.255.255.0
GATEWAY=172.17.14.1
DNS1=172.17.14.3

5) デフォルトゲートウェイを設定します。

# vi /etc/sysconfig/network
GATEWAY=172.17.14.1

ここまでできたら再起動すると、次回起動時にbond0が作られてネットワーク通信できる状態になります。cat /proc/net/bonding/bond0コマンドでbondingの状態を確認できます。

OVSでBondingを構成する

1) まず、yum updateでシステムを最新の状態に更新します。新しいKernelが追加された場合は再起動します。

2) openvswitch パッケージをインストールします。CentOSの場合はOpenStack用のリポジトリーに比較的新し目のopenvswitchパッケージが用意されているのでyum list|grep centos-release-openstackを実行して可能な限り新しいOpenStackバージョンを確認して、メタパッケージをインストールします。これでOpenStackパッケージリポジトリ〜が有効になるので、そのあとyum install openvswitchを実行してOVSをインストールします。

3) 次にeth0とeth2の設定を記述します。

# vi /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
BOOTPROTO=none
HWADDR=xx:xx:xx:xx:xx:xx
ONBOOT=yes
IPADDR=0.0.0.0
# vi /etc/sysconfig/network-scripts/ifcfg-eth2
DEVICE=eth2
BOOTPROTO=none
HWADDR=xx:xx:xx:xx:xx:xx
ONBOOT=yes
IPADDR=0.0.0.0

「ONBOOT=yes」と「IPADDR=0.0.0.0」を書いて、NICのstateがUPになるようにします。ここら辺はNetworkManagerだとよしなにやってくれるのですが、networkサービスではちょっと工夫する必要があります。

4) OVSではブリッジポートに自身のポートとbondingのポートをくっつけることでNICのbondingを実現します。そのために、まずOVSのブリッジ設定を記述します。

# vi /etc/sysconfig/network-scripts/ifcfg-ovsbr0
DEVICE=ovsbr0
ONBOOT=yes
BOOTPROTO=none
IPADDR=172.17.14.224
NETMASK=255.255.255.0
GATEWAY=172.17.14.1
DNS1=172.17.14.3

5) デフォルトゲートウェイを設定します。

# vi /etc/sysconfig/network
GATEWAY=172.17.14.1

6) コマンドを実行して、ブリッジとポートの割り当てを行います。

# systemctl start openvswitch && systemctl enable openvswitch
# ovs-vsctl add-br ovsbr0
# ovs-vsctl add-bond ovsbr0 bond0 eth0 eth2
# ovs-vsctl set port bond0 bond_mode=active-backup

7) 次のコマンドを実行することで様々な情報を引き出すことができます。

# ovs-appctl bond/list
(bondingデバイスとモード、スレーブデバイスを一覧で表示)
# ovs-appctl bond/show
(上記をもう少し詳細に表示)
# ovs-ofctl dump-flows ovsbr0
(パケットの送受信の状態の表示)
# ovs-vsctl show
(ブリッジとポートの状態と構成を一覧表示)

今回OpenStackを動かすにあたり、OpenStackではNetworkManagerはまだ利用できないので、NetworkManagerをオフにした上でBondingする方法を調べたら割と苦労したので、今後のためを思ってブログに書いてみました。誰か一人にでも役立つことがあれば幸いです。

リンク集

今回の記事を書くにあたり、参考にしたサイト一覧です。

Linux Bonding

OVS Bonding

docker-composeやWSLのサポート、いくつかのバグ修正がされたVagrant 1.9.5がリリース

Vagrant 1.9.5が5/15にリリースされていたので更新。OS X版は特に問題なし。

VagrantはOSやアプリケーションのデプロイメントツールで、Vagrantプラグインにより、様々な機能を追加したり、ハイパーバイザー、コンテナーに対応できる。標準ではVirtualBoxをサポートするほか、プラグインの追加により、Linux KVM、Docker、Hyper-V、ESXiなどに対応できる。

ダウンロードは公式サイトから可能。

CentOS 7でVanilla Kernelを使う方法

追記 (2017/5/14)
* make prepareを追加
* 同じ方法で4.9.27をビルド完了 

最近のLinuxなら、なんらかのパッケージ管理システムがあって、yumとかdnfとかaptといったようなパッケージ管理用のコマンドがあり、パッケージをコマンドを使うなどで簡単に導入したり、アップデートができると思います。Linuxディストリビューションによっては自分でビルドすることを主眼においているものも存在します。

普段はLinuxディストリビューションが用意するパッケージを使っていればインストールが楽ですし、パッチの迅速な適用ができるので良いのですが、時に自らの手で欲しいバージョンのパッケージを作成して使いたいと思う時があります。

ちなみにVanilla KernelとはオリジナルのLinuxカーネルの事です。Linux KernelはThe Linux Kernel Organizationのコミュニティグループが開発、管理をしています。

さて、主題の「CentOS 7でVanilla Kernelを使う方法」ですが、下記のサイトの手順にあるように実行するだけです。 make rpmを実行したらすぐインストールできるrpmパッケージを生成することができます。簡単ですね。

…とだけ書いて終わりだと不親切すぎますし、実際その通りやろうとしてみると、いろいろと事前に準備するものもあったりするので、ブログにまとめようと思います。

必要なパッケージをインストールする

今回はソースインストールではなく、インストールや設定を容易にするためにrpmパッケージを作ってみます。その場合に必要なパッケージは次の通りです。

# yum groupinstall "Development Tools"
# yum install openssl-devel bc ncurses ncurses-devel rpmdevtools yum-utils rpm-build

カーネルソースをダウンロード

Linuxカーネルを次の手順に従ってダウンロードします。

# git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git
# cd linux-stable
# git checkout v4.9.26 <-目的のバージョンのソースに切り替え

もしくは次のサイトを開いて、目的のバージョンのtar.gzのファイルをダウンロードしたあと、展開してください。

カーネルのビルド

次のコマンドをそれぞれ実行してカーネルのビルドを行います。

# make oldconfig   #現在のカーネルと同じ設定を適用
# make menuconfig    #ビルドするカーネルのオプションを定義する
# make prepare

# make rpm                 #rpmパッケージを作る

カーネルのビルドには多くの時間がかかります。最後のmake rpmを実行したあとは、しばしなんらかの方法で時間を潰しましょう。 ビルドが完成すると~/rpmbuild/RPMSディレクトリーにrpmパッケージが、~/rpmbuild/SRPMSディレクトリーにソースRPMパッケージが展開されます。

ビルドしたrpmパッケージをインストー

f:id:ytooyama:20170513011414p:plain

~/rpmbuild/RPMSディレクトリーに移動して、yum localinstall "packagename"コマンドを使ってrpmパッケージをインストールします。

ビルドしたカーネルをデフォルトに設定する

インストールしたらCentOS 7を再起動します。GRUBの画面で新しいカーネルを選択するとそのカーネルでOSが起動します。起動したらログインしてdmesgコマンドを使って起動ログを閲覧し、変なログ、エラーが出ていないか確認します。

ちなみに新しいカーネルを標準のカーネルに設定したい場合は、次のようにしてデフォルトのカーネルを設定します。grep ^menuent /boot/grub2/grub.cfg | awk -F\' '{ print $2 }'コマンドでインストール済みのカーネル一覧を出力します。

# grep ^menuent /boot/grub2/grub.cfg | awk -F\' '{ print $2 }'
CentOS Linux (4.9.26) 7 (Core)
CentOS Linux (3.10.0-327.el7.x86_64) 7 (Core)
CentOS Linux (0-rescue-9541e782676048f19421d05ff8b295a1) 7 (Core)

上から0,1,2…番と数えます。/etc/default/grubGRUB_DEFAULTに起動するkernelの番号を設定します。今回はビルドしたカーネル4.9.26を標準としたいので、0を設定します。

# vi /etc/default/grub
...
GRUB_DEFAULT=0

GRUB2はデフォルト設定を定義するファイルの設定を書き換えた後、起動時に読み込まれる新しいgrub.cfgファイルを生成する必要があります。CentOS 7ではupdate-grubといったコマンドはないので、次のように実行してください。最後に再起動して新しいカーネルを読み込んでみましょう。以降はGRUBカーネルを選択しなくてもカーネル4.9.28を使ってCentOS 7.3が起動するはずです。

# grub2-mkconfig -o /boot/grub2/grub.cfg
# reboot

無事に起動したようです。

f:id:ytooyama:20170513011355p:plain

以上、CentOS 7でVanilla Kernelを使う方法でした。

さてここまでやってみるとこう思うと思います。なんてパッケージのビルドって時間や手間暇がかかるんだと。昔はソースビルドするのが当たり前でしたが、ビルド済みパッケージがあるおかげで普段、色々ラクをさせてもらっているのです。その裏にいるのは人なのか機械なのかはわかりませんが、パッケージのメンテナーに感謝しましょう。

情報源へのリンク

今回の情報源のリンクを最後にまとめます。

RHEL7でサブスクライブに失敗?

CentOSに疲れたので、気分転換にRHEL7を使ってみることにしました。 そうしたらRHELでも問題が起きました。その問題とはサブスクライブがうまく通らないという現象です。

実行したこと

  • RHEL7.3をインストー
  • サブスクライブ

ユーザー、パスワードは自分のアカウントのものを設定しました。

# subscription-manager register --username admin-example --password secret

特にエラーが出なかったので、システムを最新化するため、yum updateを実施しました

結果

次のようなエラーになりました。

# yum update
...
This system is registered to Red Hat Subscription Management, but is not receiving updates. You can use subscription-manager to assign subscriptions.There are no enabled repos

エラーで検索したら次のようなナレッジベースを発見しました。 時刻が狂っているとそういった問題が起きることがあるみたいです。でもdateコマンドで確認した時刻は特に狂っているような様子はありませんでした。

解決方法

いろいろな方法があるようですが、subscription-manager refreshコマンドを実行した後、yum updateを実行したら、先ほどのようなエラーは起きなくなり、うまくいきました。いろいろ調べた上で解決しないようでしたらsubscription-manager refreshコマンドをお試しください。

【未解決】複数のNICを持つCentOS 7.3/Scientific Linux 7.3などでSSH接続するとなかなか接続できない原因を探ったけどダメだった

最近困っているネタ。ちなみに未解決です。

起きた問題

  • VirtualBoxにインストールしたCentOS 7.3/Scientific Linux 7.3
  • 各OSは7.3の最新版、カーネルは「3.10.0-514.16.1.el7」を利用
  • 最初のNICにポートフォワーディングを設定してSSHアクセス
  • 「Connection closed」 or 「Connection reset」エラーとなり、しばらく接続できない

考えたこと

パッチのバグ

yum update後起きることが多かったので、Device Mapper、Network Manager、Systemd、Firewalldの何れかのパッチのバグかなと思って少しずつパッチを適用しては確認をしてみましたが、該当のパッチを当てなくても起動、再起動を繰り返すと症状が再現するのでこの線はないと判断しました。

NetworkManagerを無効にしたらどうか?

「NetworkManagerを無効にしたらどうかな」と思い、無効化してみました。するとip addr addコマンドでIPアドレスを割り当ててもさっぱり張り付きません。ifconfig ethX up/downコマンドも想定通り動かず、pingも通りませんでした。tcpdumpで調べるとそもそもパケットが来てないという状況。というわけで、Network Managerは元に戻しました。

NICの自動命名を無効に設定する

GRUB_CMDLINE_LINUX行にnet.ifnames=0を追加する」ことで実現できる方法です。NICの名前が接続方法によってユニークな名前(ensXXXとかenpXXXとか)にならなくなり、従来のethXみたいな形式に戻ります。 ただしこれをやると一見まともに動くように見えますが、再起動を繰り返すとIPアドレスを取得しなくなり、SSHアクセスできないし、その上ifconfig ethX up/downをいくらやろうがIPアドレスが設定されなくなり、泥沼にはまります。

もうやだこのOS

問題の起きる条件

NIC1はNATでポートフォワード設定を行っています。NIC2とNIC3はBondingをして使う予定なのでL2に接続しただけの状態です。CentOS 7はNetworkManagerがデフォルトで設定されているため、Upした状態になっています。

起きる問題

なかなか接続できない時はNAT接続のNICが後ろに来ているとき eth0がNAT接続のNIC、eth1とeth2がHost-Onlyを使っている場合です。

問題ないパターン

このように並んでいる時は問題ありません。

lo:
eth0:
eth1:
eth2:

なかなか接続できないパターン

IPアドレスが設定されているeth0が後ろに来るとなかなか接続できなくなります。このパターンだとPingはなかなか通らないです。

lo:
eth1:
eth2:
eth0:

NICの認識順が再起動を繰り返すとあべこべになることがあります。 ダメなパターンに陥ると、次のようになかなか接続できなくなることがあります。

問題は「Connection reset by peer」と言われたり、「Connection closed by remote host」と言われたりすることでしょうか。エラーが一定しないのはちょっと面倒くさかったです。

% ssh root@localhost -p 58022
ssh_exchange_identification: read: Connection reset by peer
% ssh root@localhost -p 58022
ssh_exchange_identification: Connection closed by remote host
% ssh root@localhost -p 58022
ssh_exchange_identification: Connection closed by remote host
% ssh root@localhost -p 58022
ssh_exchange_identification: Connection closed by remote host
% ssh root@localhost -p 58022
ssh_exchange_identification: read: Connection reset by peer
% ssh root@localhost -p 58022
ssh_exchange_identification: Connection closed by remote host

というかバージョン6まではこんな問題ではまらなかったんだけどなあ…相変わらずEL7系は慣れません。

CentOS 7/Scientific Linux 7でOpenvSwitchを使う

CentOS 7/Scientific Linux 7でOpenvSwitchを使う方法を調べるとインストールまでしか書いていない記事を割と多く見つけるので、メモのために書いておこうと思います。

2つのサーバーを用意して、一方にはOpenvSwitch環境、一方は普通のLinux環境を同じL2ネットワークにつないで検証しました。前提として各サーバーに2つのNICを用意して、それぞれ別のL2ネットワークにつないだ構成を想定しています。なお、OVSでSELinuxはちょっと面倒くさいので、珍しくdisabledにしています。

インストールから利用までの流れは次の通りです。

サーバー側の設定

OVSのインストー

CentOS 7/Scientific Linux 7やベースとなっているRHEL 7はOpenvSwitchは標準リポジトリーに含まれないため、インストールするためにOpenStackリポジトリーを有効にしてOpenvSwitchをインストールします。

OpenStack Newtonまでは2.5系のOVSが、Ocataでは2.6.1系のOVSをインストールできます。今回はOcataのリポジトリーにある2.6.1系をインストールするため、次のように実施しました。

# yum install -y https://repos.fedorapeople.org/repos/openstack/openstack-ocata/rdo-release-ocata-2.noarch.rpm
# yum install -y centos-release-openstack-ocata

あとは次の通りです。

  • OpenvSwitchをインストールする
# yum install openvswitch

# systemctl enable openvswitch 
# systemctl start openvswitch 

そもそも使う気が無ければさっさとぬっころします。クライアント側はこの設定は不要です。

# setenforce 0
# sed -i "s/\(^SELINUX=\).*/\1disabled/" /etc/selinux/config

ちなみにsetenforce 0はある書籍で「SELinuxを一時的に無効化するための設定」とか「SELinuxをコマンドで無効化」するためのコマンドだとか書かれているのを目にしたことがありますが、SELinuxによる強制アクセス制御を実施しないようにするための設定です。このコマンドを実行してもSELinuxは無効化されません。適用された場合はログに記録されます。

OVSの設定

  • ブリッジの作成

2つのブリッジを作って、別々のNICを割り当てるのを想定しているため、ブリッジを作ります。

# ovs-vsctl add-br ovsbr0
# ovs-vsctl add-br ovsbr1

これはコマンドを見ればわかりやすいですね。

# ovs-vsctl add-port ovsbr0 eth0
# ovs-vsctl add-port ovsbr1 eth1

それぞれのブリッジにIPアドレスを割り当てます。 このままだと再起動後に消えてしまうので、永続化するようにしてください。今回は省略します。

# ip addr add 192.168.0.101/24 dev ovsbr0
# ip addr add 192.168.1.101/24 dev ovsbr1
  • ポート割り当ての確認

想定したポートをブリッジに割り当てたか確認します。

# ovs-vsctl list-ifaces ovsbr0
# ovs-vsctl list-ifaces ovsbr1
  • ポートのUp

なぜかポートがDOWNのままなのでUpします。 ちょっと腑に落ちませんが、ifconfigコマンドを使うため、事前にnet-toolsをインストールします。

# ifconfig ovsbr0 up
# ifconfig ovsbr1 up

こんなシェルスクリプトを作っておくと便利かもしれません。

#!/bin/bash

ip addr add 192.168.0.101/24 dev ovsbr0
ip addr add 192.168.1.101/24 dev ovsbr1
ifconfig ovsbr0 up
ifconfig ovsbr1 up

クライアント側の設定

クライアント側は特に設定することはありませんが、同じネットワークからアクセスできるように最低限の構成(同じL2ネットワークに接続、IPアドレスの設定)はしておきます。

# ip addr add 192.168.0.102/24 dev eth0
# ip addr add 192.168.1.102/24 dev eth1

あとはOVSブリッジポートに対してpingを飛ばすだけです。きちんとネットワークがツナがているかはサーバー側にtcpdumpコマンドを入れて確認しましょう。

# ping -c4 192.168.0.101
# ping -c4 192.168.1.101

CentOS 7で壮大にはまったその後の話

先日、このようなエントリーを書きました。

ytooyama.hatenadiary.jp

CentOS 7で環境を構築する上ではまったことをつらつらと書いてみました。 今日調査した上で幾つか解決策があったので今日のエントリーとして書いてみようと思います。

(1) (条件によって)Gatewayを設定しているのにデフォルトゲートウェイが設定されない

これはOVSブリッジにゲートウェイを設定するときの話です。普通はNICの設定ファイルにGATEWAYを記述すると思います。

cat /etc/sysconfig/network-scripts/ifcfg-br-data0
..
IPADDR=172.17.28.114
NETMASK=255.255.255.0
GATEWAY=172.17.28.1

ただ、これだとNICが複数あるときにうまくゲートウェイが設定されないようです。 じゃあどうするかというと、route-brという設定ファイルを作成するようです。

cat /etc/sysconfig/network-scripts/route-br-data0
default 172.17.28.1 dev br-data0

これでデフォルトルートが設定されます。 この辺りの情報については次のドキュメントを確認してください。

ちなみにNICの設定に記述したGATEWAYはホストから外へ通信をするときに必要な設定なので消してはいけないようです。

(3) OpenvSwitchのExtraオプションが再起動でいろいろ消える

(4) IPアドレスの設定ファイルにExtraオプションを指定しても一部反映されない

これは設定の書き方の問題でした。次のように1行で記述して、アイテムを–(前後にスペースを入れる)でつなげることで全ての設定を再起動後の引き継ぐことができていました。最後のMACアドレスはOVSブリッジの物理ポートのMACアドレスを記述します。

OVS_EXTRA="set bridge br-data0 datapath_type=netdev -- br-set-external-id br-data0 bridge-id br-data0 -- set bridge br-data0 fail-mode=standalone other_config:hwaddr=XX:XX:XX:XX:XX:XX"

OVS_EXTRAについては以下の情報を参考にしました。

ちなみに何度もしつこく言って申し訳ありませんが、これらのような問題はOpenvSwitchとNetwork Managerの組み合わせで使っている場合は起きることはほぼありません。