要求
Dockerを用いて、常用するインフラをいざという時にすぐ再展開できるようにしたい。
しかも、既存のインフラとの運用を考えると、L2で地続きになっていてほしい。
導入前提条件
DockerとOpenvSwitchが動くこと。特にovs-dockerコマンドが動けば良い。
何故Docker+OpenvSwitchを使うのか
SoftEtherVPNやDHCP等に代表される、L2の疎通ができたほうが望ましいサービス群を一発展開するのに最適だった。
Ipvlanや、Macvlanも悪くはないが、特にSoftEtherVPNを利用する場合は、
コンテナ内へL2のプロミスキャスポートを設定する必要があり、要件を満たさない。
また、今後開発環境として個人的に利用するとしても、L2疎通が取れたほうが、
ネットワーク系のスクリプトを書いたときに、遥かに検証が容易となる。
- SoftEtherVPN
- ローカルブリッジに必要
- 利用しない場合、やけに接続性が高いだけとなりあまり旨味がない
- DHCP
- DHCP Relay Agentによる中継も可能
- Docker内にそのような仕組みを置くのは可能な限り回避したい
何故シェルスクリプトで展開するのか
OpenvSwitchのDockerプラグインのIssueが一年前から放置されている等、メンテナンスが行き届いておらず、動作が怪しかったりしたため、docker-composeの利用を断念した。そもそも、このプラグインを利用したしても、docker-composeの文法的にL2の挙動を記述する内容が見当たらないので、シェルスクリプトで展開する決意をした。
また、今度はOpenStackNeutronをDockerで利用する方法もあるが、オーケストレーションは不要なので機能過剰と判断、利用しないことにした。
成果物と最低限の説明だけ欲しい人は、Github:fono09/infra_portaleをご利用ください。
構成
コンテナは、既存のインフラから見ても、L2で完全に独立したホストに見えるように展開する。
OpenvSwtichと物理スイッチへの接続はL2でブリッジされている。
基本的な作り方
ネットワーク周り
- 既存の物理ネットワークへの出口にプロミスキャスポートを用意する
- Open vSwtichで仮想ブリッジを作る
- 仮想ブリッジとプロミスキャスポートを繋げて既存のネットワークとL2疎通を取る
以上をまとめて
ip link set $IFACE promisc on
ovs-vsctl add-br $VSWITCH_NAME
ovs-vsctl add-port $VSWITCH_NAME $IFACE
各々のサービスに関して
- Dockerコンテナを立てる
- Dockerの標準ネットワーク不使用
- 勿論、設定ファイルやオプションで一発動作するように
- Open vSwtichの仮想ブリッジと接続
以上をまとめて
docker run -d --name $CT_NAME --net=none -v foo:bar alice/great-service
ovs-docker add-port $VSWTICH_NAME $CT_IF0 $CT_NAME --ipaddress=$CT_ADDR --gateway=$CT_GATEWAY
撤収時はただ逆の操作をします
- DockerのコンテナをOpen vSwtichの仮想ブリッジから外す
- コンテナを消す
- 仮想ブリッジの撤収
以上をまとめて
ovs-docker del-port $VSWTICH_NAME $CT_IF0 $CT_NAME
docker rm -f $CT_NAME
ovs-vsctl del-br $VSWTICH_NAME
詰まりやすいところ
ホスト再起動への耐性
- OpenvSwitch
- 独自にデータベースを持っており再起動に耐える
- ovs-docker
- 動作中のdockerを名前で引いた後PIDで追跡する為、再起動でPIDが変更され仮想I/Fが孤立するとCTIDで再追跡する仕組みがない
- docker
- CTIDは固定されている
以上のように、ovs-dockerに再起動耐性がないので、systemdのUnitファイルを作成し、登録。
システム終了時にきれいに撤収するようしている。
SoftEtherVPN
L2疎通をコンテナへ取れるようにすること。出来ていない場合、接続したクライアントは、
SoftEtherVPNのSecureNATにぶら下がってしまい、ルーティングが厄介に。
そもそも、既存のインフラとL2の疎通を取るという要求を満たせない。今回は、2つの仮想I/Fを利用した。
vim
Samba
id (username)
コマンドで利用ユーザーのUIDを把握して、設定に流し込むこと。
これを設定しないと、ユーザーは自分のファイルにアクセスできない。
DHCP
コンテナを立ち上げた後、仮想I/Fを後付するので、ネットワークの立ち上がりを全く待たないイメージを引いて動作不良に悩まされた。
ネットワークが上がってくるのが間に合わない場合もある。
今回使用したイメージに含まれているシェルスクリプト、chakphanu/docker-kea:master/src/starter.shにあるように、
ネットワークの立ち上がりを待つ動作はなんだかんだで重要なので、イメージ作成時に考慮すべきだとは思った。