Dockerにおけるネットワークまず、広く使われているコンテナ化技術「Docker」を例として、コンテナネットワークの概要を説明する。コンテナは一般的にLinux OS上で起動する。このホストは「コンテナホスト」と呼ばれ、各コンテナはコンテナホスト内の論理的なネットワークに接続されている。
具体的には、コンテナホスト内に論理ブリッジ(Linuxブリッジ)が存在し、各コンテナは、LinuxのNetwork Namespace機能により隔離され、仮想ネットワークインターフェース(veth)でこのブリッジに接続される。これによって、コンテナ内のプロセスから見ると、自分専用のネットワークインターフェースがあるように見えている。
そして、コンテナホスト自身が持つネットワークインターフェースもこのブリッジに接続されているため、コンテナで起動するサービスを外部公開する場合には、コンテナホストに対するアクセスがLinuxカーネルのiptablesを使ってNATされる(図表1)。
図表1 Dockerのコンテナネットワーク
Kubernetesでコンテナ群を管理さて、開発環境のように小規模なものであれば、1台のコンテナホスト内で必要なコンテナをすべて起動することができるため、上記のような実装で問題ない。
しかし、コンテナ数が多い場合や、本番環境のように可用性が求められる場合には、クラスター化が必要になる。ここで、分散したコンテナ群を効率的に管理するツールとして「Kubernetes」が登場した。
Kubernetesによるクラスター構成は次のようなものだ。「Master」と「Node」と呼ばれるLinuxホストで構成され、コンテナはNode上で「Pod」と呼ばれる単位で扱われる。このPodは、1つ以上のコンテナ、Podごとのファイルシステム、ネットワークインターフェースを持つ(図表2)。
図表2 KubernetesのNodeとPod
【課題1】コンテナ間の通信このようなクラスター環境における課題は、コンテナ間の通信だ。Podには独立したIPアドレスが割り当てられるが、Node内でのみ有効なため、そのままではNodeを跨いだ通信は難しい。Dockerでは、LinuxのNAT機能を用いていたが、すべてのPod間通信をNATテーブルで制御するのは限界がある。そこで、多くのコンテナネットワークソリューションではVXLAN技術などによるオーバーレイネットワークが採用されている。
オーバーレイネットワークとは、パケットをカプセル化して送信し、受信側でカプセル化を解いて宛先に届けるものだ。具対的には、Podから送信されたパケットは、Node内のブリッジを経由してLinuxカーネルでカプセル化され、宛先Nodeに送信される。そして、受信したNodeはカプセル化を解いて宛先のPodにパケットを届ける(図表3)。
図表3 Podとオーバーレイネットワーク[画像をクリックで拡大]
オープンソースでは「Flannel」(https://github.com/coreos/flannel)や、RedHat OpenShift Container Platformで利用されている「OpenShift SDN」(https://github.com/openshift/sdn)等がこのアプローチでコンテナ間の通信を実現している。OpenStackにおける仮想マシン間通信と同じ実装だ。
また、別の実装方法として、Podが持つIPアドレスをNodeネットワークに公開する方法もある。オープンソースの「Calico」(https://github.com/projectcalico/calico)は、Podに割り当てられるIPアドレスをBGPでNode外に広報し、各Nodeが経路情報を学習するものである。この手法であれば、基本的にNATは利用されず、パフォーマンスインパクトも小さい。また、BGPを利用することで、Nodeに接続しているネットワーク機器側でもPod向けネットワークが確認可能になる。