コンテナ上でのipvsおよびiptablesの利用
従来の仮想マシンと比較して軽量な仮想環境としてコンテナが注目されている。コンテナによる仮想環境での特徴としてコンテナで同じカーネルを共有している点があげられる。
また、コンテナで実際のサービスを提供する場合、アプリケーションがほかにカーネルの提供する機能も必要となる。そこで今回はコンテナ環境下でのカーネルの機能の利用について実際に試してみた。
コンテナではホストのカーネルを共有しそれぞれのコンテナごとに独立した名前空間を作成して、その上でユーザプロセスを実行することによって仮想環境を実現している。
しかし、実際のサービスなどにおいてはhttpサーバやデータベースなどのユーザプロセスだけではなくカーネルの機能も合わせて利用される。例えば、ロードバランスやパケットのフィルタリングを行う場合などはipvsやiptablesといったカーネルの機能が必要になる。
コンテナ上でカーネルの機能を利用する場合、そのカーネルについてはすべてのコンテナで共有されている点において通常とは事情が異なる。
今回はipvsおよびiptablesについて実際にコンテナ上での利用を試してみた。
検証としてWebサーバへのアクセスをLVSを利用してロードバランスするシステムをコンテナを利用して構成することを考える(上図)
ホストマシン2台からなる構成で、それぞれのホストにipvsを利用してWebコンテナへのロードバランスを実行するLVSコンテナ、 iptablesとapacheを使ってLVSからロードバランスされてきたアクセスを受けるWebコンテナを作成する。
以下の説明ではそれぞれのホスト及びコンテナの構成方法についての詳細は割愛して、それぞれのコンテナ上でのipvsおよびiptablesの動作および設定についてのみ述べる
またコンテナ上でipvsadmで設定を行うためにはコンテナがroot権限で実行されている必要がある。いわゆる一般ユーザ権限による非特権コンテナではipvsの設定はできないようである。
実際にipvs設定を行うと次のようになる。今回はロードバランスするアドレスは10.10.0.100としてeth0のエイリアスとして設定してある。またLVSのパケットの転送方式はダイレクトルーティング(-gオプション)を選択している。
このようにipvsの設定方法は普通のLinux Boxの場合とほとんど変わらない。
Webコンテナはアドレスが異なる(192.168.0.50と192.168.0.51)2つのものを作成して、それそれにLVSコンテナからロードバランスされたパケットが転送されてくるようにする。
またここではWebコンテナは検証のためいわゆる非特権コンテナで実行されている。つまりWebコンテナ上のrootはホスト上からみた場合一般ユーザになっている。
LVSでダイレクトルーティング方式での転送を選択しているので、ロードバランスされてWebコンテナに振り分けられてくるパケットの宛先はサービスアドレス(10.10.0.100)のまになっている。この宛先のパケットをWebコンテナで受け取るためにiptablesのREDIRECTターゲットを利用する。
ipvsの場合と異なり、iptablesの設定はいわゆる非特権コンテナ上でも可能なようである。テスト時にWebコンテナの区別がつくようにindex.htmlにコンテナ名を記述しておく。
同様にもう一つのWebコンテナ(web2)をipアドレスを変えて(192.168.0.51)作成する。本来であれば同じホストにコンテナ複数作成してロードバランスしたとしても負荷分散や冗長化という観点からはあまり意味がないが検証用にそのように構成した。
2つのWebコンテナを構成後、LVSコンテナのeth0側からサービスアドレスにアクセスするとロードバランスされていることが確認された。
これは一般的なカーネル空間のログの問題のようで、今のところカーネル空間のログをそれぞれのコンテナに関連するログごとに分けて記録するような仕組みがない。つまりコンテナからカーネル空間のログを記録する動作をした場合、すべてのコンテナおよびホストで共通になっている場所に記録される(あまり自信がありませんが)。その関係上、コンテナ上ではiptablesを利用してLOGターゲットでカーネル空間にログを出力することは、今のところ意図的にできないようになっているようである。
コンテナ上でiptablesのログを記録するには、ユーザ空間にログを出力するULOGやNFLOGターゲットを利用する必要がある。
参考文献
また、コンテナで実際のサービスを提供する場合、アプリケーションがほかにカーネルの提供する機能も必要となる。そこで今回はコンテナ環境下でのカーネルの機能の利用について実際に試してみた。
コンテナ上でのカーネルの機能の利用
|
しかし、実際のサービスなどにおいてはhttpサーバやデータベースなどのユーザプロセスだけではなくカーネルの機能も合わせて利用される。例えば、ロードバランスやパケットのフィルタリングを行う場合などはipvsやiptablesといったカーネルの機能が必要になる。
コンテナ上でカーネルの機能を利用する場合、そのカーネルについてはすべてのコンテナで共有されている点において通常とは事情が異なる。
今回はipvsおよびiptablesについて実際にコンテナ上での利用を試してみた。
システム構成
コンテナ構成図 |
ホストマシン2台からなる構成で、それぞれのホストにipvsを利用してWebコンテナへのロードバランスを実行するLVSコンテナ、 iptablesとapacheを使ってLVSからロードバランスされてきたアクセスを受けるWebコンテナを作成する。
以下の説明ではそれぞれのホスト及びコンテナの構成方法についての詳細は割愛して、それぞれのコンテナ上でのipvsおよびiptablesの動作および設定についてのみ述べる
LVSコンテナ
LVSコンテナは2つのネットワークインターフェースeth0、eth1を持ちそれぞれが仮想ブリッジを介して仮想イーサネット(veth)によってホストマシン(物理マシン)のインターフェースに接続されている。eth0側が外部ネットワーク、eth1側がWebコンテナ側のネットワークになっている。ipvsの設定
ipvsの設定はコンテナ上にipvsadmによって可能である。ただし、ipvsadmを利用してコンテナ上でipvsの設定を実行する前にホスト側でip_vsモジュールをmodprobeにより読み込んでおく必要がある。
lvshost# modprobe ip_vs
またコンテナ上でipvsadmで設定を行うためにはコンテナがroot権限で実行されている必要がある。いわゆる一般ユーザ権限による非特権コンテナではipvsの設定はできないようである。
実際にipvs設定を行うと次のようになる。今回はロードバランスするアドレスは10.10.0.100としてeth0のエイリアスとして設定してある。またLVSのパケットの転送方式はダイレクトルーティング(-gオプション)を選択している。
lvs1 # ipvsadm -A -t 10.10.0.100:80 -s lc
lvs1 # ipvsadm -a -t 10.10.0.100:80 -r 192.168.0.50 -g
lvs1 # ipvsadm -a -t 10.10.0.100:80 -r 192.168.0.51 -g
lvs1 # ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 10.10.0.100:80 lc
-> 192.168.10.50:80 Route 1 0 0
-> 192.168.10.51:80 Route 1 0 0
lvs1 # ip addr add 10.10.0.100 label eth0:100 dev eth0
lvs1 # echo 1 > /proc/sys/net/ipv4/ip_forward
lvs1 # ipvsadm -a -t 10.10.0.100:80 -r 192.168.0.50 -g
lvs1 # ipvsadm -a -t 10.10.0.100:80 -r 192.168.0.51 -g
lvs1 # ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 10.10.0.100:80 lc
-> 192.168.10.50:80 Route 1 0 0
-> 192.168.10.51:80 Route 1 0 0
lvs1 # ip addr add 10.10.0.100 label eth0:100 dev eth0
lvs1 # echo 1 > /proc/sys/net/ipv4/ip_forward
このようにipvsの設定方法は普通のLinux Boxの場合とほとんど変わらない。
Webコンテナ
Webコンテナのネットワークインターフェースは仮想ブリッジを介して仮想イーサネット(veth)によりホストマシ ンのインターフェースに接続されている。ホストマシンのネットワークインターフェースは先ほどのLVSホストのeth1側のネットワークに接続するように 構成されている。Webコンテナはアドレスが異なる(192.168.0.50と192.168.0.51)2つのものを作成して、それそれにLVSコンテナからロードバランスされたパケットが転送されてくるようにする。
またここではWebコンテナは検証のためいわゆる非特権コンテナで実行されている。つまりWebコンテナ上のrootはホスト上からみた場合一般ユーザになっている。
Webコンテナの設定
コンテナ上でiptablesコマンドによりiptablesの設定は可能である。ただし、ipvsの場合と同様に設定を実行する前にホスト側でip_tablesモジュールをmodprobeにより読み込んでおく必要がある。
webhost# modprobe ip_tables
LVSでダイレクトルーティング方式での転送を選択しているので、ロードバランスされてWebコンテナに振り分けられてくるパケットの宛先はサービスアドレス(10.10.0.100)のまになっている。この宛先のパケットをWebコンテナで受け取るためにiptablesのREDIRECTターゲットを利用する。
root@web1# iptables -t nat -A PREROUTING -p tcp --dport 80 -d 10.10.0.100 -j REDIRECT
ipvsの場合と異なり、iptablesの設定はいわゆる非特権コンテナ上でも可能なようである。テスト時にWebコンテナの区別がつくようにindex.htmlにコンテナ名を記述しておく。
root@web1# echo "HELLO,This is web1" > /var/www/html/index.htm
同様にもう一つのWebコンテナ(web2)をipアドレスを変えて(192.168.0.51)作成する。本来であれば同じホストにコンテナ複数作成してロードバランスしたとしても負荷分散や冗長化という観点からはあまり意味がないが検証用にそのように構成した。
2つのWebコンテナを構成後、LVSコンテナのeth0側からサービスアドレスにアクセスするとロードバランスされていることが確認された。
$ curl http://10.10.0.100
HELLO,This is web1
$ curl http://10.10.0.100
HELLO,This is web2
HELLO,This is web1
$ curl http://10.10.0.100
HELLO,This is web2
コンテナ上のiptables/ipvsの設定について
作成した2つのWebコンテナでiptablesの設定を表示すると確認できるが、それぞれのコンテナで設定が独立していることがわかる。ipvsの設定も同様にコンテナごとに独立したものになる。コンテナ上のiptablesのLOGターゲットについて
コンテナ上の場合、iptablesのLOGターゲットでのログの取得はできないようである。これは一般的なカーネル空間のログの問題のようで、今のところカーネル空間のログをそれぞれのコンテナに関連するログごとに分けて記録するような仕組みがない。つまりコンテナからカーネル空間のログを記録する動作をした場合、すべてのコンテナおよびホストで共通になっている場所に記録される(あまり自信がありませんが)。その関係上、コンテナ上ではiptablesを利用してLOGターゲットでカーネル空間にログを出力することは、今のところ意図的にできないようになっているようである。
コンテナ上でiptablesのログを記録するには、ユーザ空間にログを出力するULOGやNFLOGターゲットを利用する必要がある。
その他
検証はしていないが、コンテナ上にインストールして実行するipvsadmやiptablesのコマンドはホストのカーネルバージョンとの互換性がある必要があるとおもわれる。まとめ
- iptableやipvsはコンテナでも同様に利用できる。
- ただしホスト側での事前のモジュールの読み込みが必要である。
- またipvsはroot権限でコンテナを実行していないと設定できない。
- iptablesでログを取得したい場合はULOGかNFLOGを使うこと。
参考文献
- コンテナ上でiptablesのログターゲットが利用できない背景(カーネル空間のログの問題)はここを参考にさせていただきました。
- 非特権コンテナについてはこちらを参考にさせていただきました(日本語約ページ)
コメント
コメントを投稿