前書き

Kubernetesは、サーバーのクラスター全体でコンテナー化されたアプリケーションの展開と操作を管理できる強力なコンテナーオーケストレーションシステムです。 Kubernetesは、コンテナワークロードの調整に加えて、アプリケーションとサービス間の信頼性の高いネットワーク接続を維持するために必要なインフラストラクチャとツールを提供します。

Kubernetes cluster networking documentationは、Kubernetesネットワークの基本的な要件は次のとおりであると述べています。

_
* すべてのコンテナは、NATなしで他のすべてのコンテナと通信できます。
* すべてのノードは、NATなしですべてのコンテナと通信できます(逆も同様です)。
* コンテナがそれ自体を見るIPは、他の人がそれを見ると同じIP
_

この記事では、Kubernetesがクラスター内のこれらのネットワーク要件をどのように満たすかについて説明します。ポッド内、ポッド間、ノード間でのデータの移動方法です。

また、Kubernetes * Service *がアプリケーションに単一の静的IPアドレスとDNSエントリを提供し、複数の絶えずスケーリングおよびシフトするポッドに分散される可能性のあるサービスとの通信を容易にする方法も示します。

Kubernetesの_pods_および_nodes_の用語またはその他の基本に慣れていない場合は、記事https://www.digitalocean.com/community/tutorials/an-introduction-to-kubernetes[An Introduction to Kubernetes]で一般的なアーキテクチャと関連するコンポーネント。

まず、1つのポッド内のネットワークの状況を見てみましょう。

ポッドネットワーキング

Kubernetesでは、_pod_は組織の最も基本的な単位です。すべての密接に関連し、単一の機能またはサービスを実行する密結合コンテナのグループです。

ネットワークに関しては、Kubernetesは従来の仮想マシンまたは単一のベアメタルホストと同様にポッドを処理します。各ポッドは単一の一意のIPアドレスを受け取り、ポッド内のすべてのコンテナーはそのアドレスを共有し、* lo ループバックを介して相互に通信します localhost *ホスト名を使用したインターフェース。 これは、ポッドのすべてのコンテナーを同じネットワークスタックに割り当てることで実現されます。

この状況は、コンテナ化の数日前に単一のホストに複数のサービスを展開した人なら誰でも知っているはずです。 すべてのサービスは、リッスンするために一意のポートを使用する必要がありますが、それ以外の場合、通信は単純でオーバーヘッドが低くなります。

ポッドツーポッドネットワーキング

ほとんどのKubernetesクラスターでは、ノードごとに複数のポッドを展開する必要があります。 ポッドからポッドへの通信は、同じノード上の2つのポッド間、または2つの異なるノード間で発生する場合があります。

1つのノードでのポッド間通信

単一のノードで、互いに直接通信する必要がある複数のポッドを使用できます。 ポッド間のパケットのルートをトレースする前に、ノードのネットワーク設定を調べてみましょう。 次の図は概要を示しており、詳細に説明します。

image:https://assets.digitalocean.com/articles/k8s-networking/single.png [単一のKubernetesノードのネットワークの概要]

各ノードには、Kubernetesクラスターネットワークに接続されたネットワークインターフェイス(この例では* eth0 )があります。 このインターフェイスは、ノードの root *ネットワーク名前空間内にあります。 これは、Linux上のネットワークデバイスのデフォルトのネームスペースです。

プロセス名前空間によってコンテナが実行中のアプリケーションを相互に分離できるように、ネットワーク名前空間はインターフェイスやブリッジなどのネットワークデバイスを分離します。 ノード上の各ポッドには、独自の分離されたネットワーク名前空間が割り当てられます。

ポッドの名前空間は、_virtual ethernet pair_で* root 名前空間に接続されます。本質的には、両端にインターフェースを持つ2つの名前空間間のパイプです(ここでは root 名前空間で veth1 eth0 *を使用しています)ポッド内)。

最後に、ポッドは相互に接続され、ブリッジ* br0 を介してノードの eth0 インターフェースに接続されます(ノードは cbr0 または docker0 *などを使用する場合があります)。 ブリッジは基本的に物理的なイーサネットスイッチのように機能し、ARP(アドレス解決プロトコル)またはIPベースのルーティングを使用して、トラフィックを転送する他のローカルインターフェイスを検索します。

パケットを* pod1 から pod2 *にトレースしてみましょう。

  • * pod1 は、 pod2 *のIPを宛先とするパケットを作成します

  • パケットは、仮想イーサネットペアを介してルートネットワーク名前空間に移動します。

  • パケットはブリッジ* br0 *へと続きます

  • 宛先ポッドは同じノードにあるため、ブリッジは* pod2 *の仮想イーサネットペアにパケットを送信します

  • パケットは仮想イーサネットペアを通過して、* pod2 のネットワーク名前空間とポッドの eth0 *ネットワークインターフェイスに移動します。

ノード内のポッドからポッドへのパケットをトレースしたので、ノード間のポッドトラフィックの流れを見てみましょう。

2つのノード間のポッド間通信

クラスター内の各ポッドには固有のIPがあり、すべてのポッドは他のすべてのポッドと直接通信できるため、2つの異なるノード上のポッド間を移動するパケットは前のシナリオと非常に似ています。

別のノードにある* pod1 から pod3 *にパケットをトレースしてみましょう。

image:https://assets.digitalocean.com/articles/k8s-networking/double.png [2つのKubernetesノード間のネットワーク図]

  • * pod1 は、 pod3 *のIPを宛先とするパケットを作成します

  • パケットは、仮想イーサネットペアを介してルートネットワーク名前空間に移動します。

  • パケットはブリッジ* br0 *へと続きます

  • ブリッジはルーティング先のローカルインターフェイスを見つけられないため、パケットはデフォルトルートから* eth0 *に向けて送信されます

  • _オプション:_ノードにパケットを適切にルーティングするためにクラスターがネットワークオーバーレイを必要とする場合、パケットはネットワークに向かう前にVXLANパケット(またはその他のネットワーク仮想化技術)にカプセル化されます。 または、ネットワーク自体に適切な静的ルートを設定することもできます。その場合、パケットはeth0に移動し、ネットワークから変更されません。

  • パケットはクラスターネットワークに入り、正しいノードにルーティングされます。

  • パケットは* eth0 *の宛先ノードに入ります

  • _オプション:_パケットがカプセル化されている場合、この時点でカプセル化が解除されます

  • パケットはブリッジ* br0 *へと続きます

  • ブリッジはパケットを宛先ポッドの仮想イーサネットペアにルーティングします

  • パケットは仮想イーサネットペアを介してポッドの* eth0 *インターフェースに渡されます

パケットがポッドIPアドレスを介してルーティングされる方法に精通したので、Kubernetes _services_と、このインフラストラクチャ上でのパケットの構築方法を見てみましょう。

サービスネットワーキングへのポッド

Kubernetesクラスターの動的な性質により、ポッドを移動、再起動、アップグレード、またはスケールイン/スケールアウトできるため、ポッドIPのみを使用して特定のアプリケーションにトラフィックを送信することは困難です。 さらに、一部のサービスには多数のレプリカがあるため、それらの間で負荷を分散する方法が必要です。

Kubernetesは、_Services_でこの問題を解決します。 サービスは、単一の仮想IP(VIP)をポッドIPのセットにマッピングするAPIオブジェクトです。 さらに、Kubernetesは各サービスの名前と仮想IPのDNSエントリを提供するため、サービスは名前で簡単にアドレス指定できます。

仮想IPからクラスター内のポッドIPへのマッピングは、各ノードの「+ kube-proxy +」プロセスによって調整されます。 このプロセスでは、https://www.digitalocean.com/community/tutorials/a-deep-dive-into-iptables-and-netfilter-architecture [iptables]またはIPVSを設定して、パケットを送信する前にVIPをポッドIPに自動的に変換します。クラスターネットワークへ。 個々の接続が追跡されるため、パケットが戻ったときに適切に変換解除できます。 IPVSとiptablesはどちらも、単一のサービス仮想IPを複数のポッドIPにロードバランシングできますが、IPVSには使用できるロードバランシングアルゴリズムの柔軟性がはるかにあります。

パケットがポッド* pod1 からサービス service1 *に到達するまでのルートを見てみましょう。

image:https://assets.digitalocean.com/articles/k8s-networking/double-service.png [2つのKubernetesノード間のネットワーク図、仮想IPのDNAT変換を示しています]

  • * pod1 は、 service1 *のIPを宛先としてパケットを作成します

  • パケットは、仮想イーサネットペアを介してルートネットワーク名前空間に移動します。

  • パケットはブリッジ* br0 *へと続きます

  • ブリッジは、パケットをルーティングするローカルインターフェイスを検出しないため、パケットは* eth0 *に向かうデフォルトルートに送信されます

  • 「+ kube-proxy +」で設定されたiptablesまたはIPVSは、利用可能なまたは指定されたロードバランシングアルゴリズムを使用して、パケットの宛先IPを一致させ、仮想IPからサービスのポッドIPの1つに変換します

  • _オプション:_前のセクションで説明したように、この時点でパケットがカプセル化される場合があります

  • パケットはクラスターネットワークに入り、正しいノードにルーティングされます。

  • パケットは* eth0 *の宛先ノードに入ります

  • _オプション:_パケットがカプセル化されている場合、この時点でカプセル化が解除されます

  • パケットはブリッジ* br0 *へと続きます

  • パケットは、* veth1 *を介して仮想イーサネットペアに送信されます。

  • パケットは仮想イーサネットペアを通過し、* eth0 *ネットワークインターフェイスを介してポッドネットワーク名前空間に入ります

パケットが* node1 *に戻ると、VIPからポッドへのIP変換が逆になり、パケットはブリッジおよび仮想インターフェイスを介して正しいポッドに戻ります。

結論

この記事では、Kubernetesクラスターの内部ネットワークインフラストラクチャを確認しました。 ネットワークを構成する構成要素について説明し、さまざまなシナリオでのホップごとのパケットの旅を詳しく説明しました。

Kubernetesの詳細については、https://www.digitalocean.com/community/tags/kubernetes?type = tutorials [Kubernetesチュートリアルタグ]およびhttps://kubernetes.io/docs/home/[the Kubernetesの公式ドキュメント]。