1.ポッドネットワーク: 同じポッド内の異なるコンテナ間の通信
ポッドは、Kubernetes でデプロイ可能な最小単位です。これは、1 つ以上の密接に関連したコンテナの組み合わせです。これらのコンテナは、同じネットワーク名前空間とストレージ ボリュームを共有するため、同じポッド内のコンテナ間で通信が行われます。
所有容器都共享相同的网络命名空间和IP地址——PodIP
はい通过localhost直接通信
。
k8s が Pod を作成するときは、常に最初に作成されInfra 容器
、呼び出すこともできますpause容器
。このコンテナは他のコンテナにネットワーク機能やストレージ機能などの共有基盤を提供し、他の業務コンテナは一時停止コンテナのネットワークスタックやボリュームマウントボリュームを共有します。
一時停止コンテナーが作成されると、ネットワーク ネームスペース ネットワーク スタックが初期化され、その後、他のコンテナーが一時停止コンテナーに参加して、インフラ コンテナーのネットワークを共有できるようになります。同じポッド内のすべてのユーザー コンテナについて、そのインバウンドおよびアウトバウンドのトラフィックは一時停止コンテナを介して完了すると見なされます。
一時停止コンテナが作成および管理されます虚拟以太网(veth)接口
。コンテナが起動する前に、一時停止コンテナは各コンテナの仮想イーサネット インターフェイスを作成し、次の図に示すように一个保留在宿主机上(称为 vethxxx),另一个保留在容器网络命名空间内
その名前を変更します。eth0
2 つの仮想インターフェイスの両端は互いに接続されており、一方の端から入力されたデータはもう一方の端から出力されます。
ポーズコンテナは、業務コンテナごとに主に以下の機能を提供します。
- IPC 名前空間: ポッド内の複数のコンテナーは、SystemV IPC または POSIX メッセージ キューを使用して通信できます。
- ネットワーク名前空間: ポッド内の複数のコンテナが同じ IP およびポート範囲にアクセスできます。
- PID 名前空間: ポッド内のさまざまなアプリケーションは、他のアプリケーションのプロセス ID を確認できます。
- UTS 名前空間: ポッド内の複数のコンテナはホスト名を共有します。
- ボリューム (共有ストレージ ボリューム): ポッド内の各コンテナは、ポッド レベルで定義されたボリュームにアクセスできます。
2. ポッドネットワーク: 同じノード上の異なるポッド間の通信
同じノード上の異なる POD 間の通信は、と容器网络接口(CNI)
で接続することによって主机网络命名空间中的虚拟以太网(veth)接口
実現されます。新しい Pod が生成されるたびに、プラグインに基づいて vethxxxx や calixxxx などの新しい仮想ネットワーク カードが Node 上に生成され、このネットワーク カードは Pod 内の eth0 に対応します。
図に示すように、veth インターフェイスはホストのネットワーク名前空間に保持され、CNI プラグイン (Flannel や Calico など) によって作成されたインターフェイス (cni0 や flannel0 など) に接続されます虚拟网桥
。 )。これらの veth インターフェイスが適切に接続されると、通信できるようになります。POD がパケットを送信すると、パケットは veth インターフェイスを介してホスト ネットワーク名前空間の veth インターフェイスに送信され、その後仮想ブリッジにパケットが送信されます。仮想ブリッジは、データ パケットをターゲット POD の veth インターフェイスにルーティングし、最後にデータ パケットをターゲット POD に送信します。
図に示すように、ブリッジの IP アドレスとネットワーク セグメントは同じノードの異なる POD でありIP地址通常属于同一网段
、CNI プラグインを介して同じ仮想ブリッジ (cni0 など) に接続されています。仮想ブリッジは、異なる POD の IP アドレスが競合しないように、その IP アドレス空間と割り当てを管理します。
特定の IP アドレスとネットワーク セグメントは、使用される CNI プラグインとネットワーク スキームによって異なります。たとえば、Flannel プラグインはデフォルトでネットワーク セグメント 10.244.x.0/24 を使用します。ここで、x は各 POD にランダムに割り当てられます。これは、異なる POD の IP アドレスがネットワーク セグメント 10.244.x.0/24 に存在することを意味します (x は異なる値です)。
2.1 CNI の概要
Calico や flannel などの CNI は、ネットワーク サービス自体を提供するのではなく、コンテナ ネットワークを運用および構成するための仕様を定義するだけです。CNI は、コンテナーの作成時にネットワーク リソースを割り当て、コンテナーを破棄するときにネットワーク リソースを削除することだけに重点を置いています。一般的な CNI プラグインには、Calico、flannel などが含まれます。
具体的なプロセスを次の図に示します。
クラスター内にポッドが作成されると、最初にポッドの構成が apiserver を通じて書き込まれます。apiserver の一部の管理および制御コンポーネント (スケジューラーなど) は、特定のノードにスケジュールされます。ノード ノード上の Kubelet がこのポッドの作成を監視した後、最初に先ほど述べた構成ディレクトリ内の構成ファイルを読み取り、どのプラグインが使用されるかを宣言し、次に特定の CNI プラグインを実行します。 . バイナリ ファイルを作成すると、CNI プラグインがポッドのネットワーク空間に入り、ポッドのネットワークを設定します。このプロセス中に、CNI プラグインはポッドのネットワーク名前空間を作成し、veth インターフェイスの 1 つをその名前空間に接続します。もう 1 つの veth インターフェイスはホストのネットワーク名前空間に残り、CNI プラグインによって作成された仮想マシンに接続されます。橋の上で。
3.ポッドネットワーク: 異なるノードポッドが相互に通信します。
異なるノード ポッドが相互に通信したい場合は、cni0 ブリッジの外側に CNI プラグインによって構成されたネットワーク トンネルがあり、上の図に示すように、新しい仮想ネットワーク カード flannel0 が cni0 ブリッジのデータを受信して維持します。受信データを処理するためのルーティング テーブル パケット化と転送 (vxlan トンネル)。
cni0 : ブリッジデバイスポッドが作成されるたびに、veth ペアが作成されます。一方のセクションはポッドの eth0 で、もう一方のセクションは cni0 ブリッジのポートです。
VTEP 機器: VXLAN トンネル エンド ポイント (仮想トンネル エンド ポイント) Flannel の VNI のデフォルト値は 1 であるため、ホストの VTEP 機器は flannel.1 と呼ばれます。VTEP デバイスは、レイヤー 2 データ フレームを介して相互に通信します。元の IP パケットを受信した後、送信元 VTEP デバイスは宛先 MAC アドレスをそれに追加し、内部データ フレームにカプセル化して、宛先 VTEP デバイスに送信します。
flannel.1 : vxlan ゲートウェイ デバイス、ユーザー vxlan メッセージの解凍とパッケージ化。さまざまなポッド データ トラフィックがオーバーレイ デバイスから反対側のエンドにトンネルの形式で送信されます。flannel.1 は、ターゲット IP の MAC アドレスを取得するための arp リクエストを送信しません。代わりに、Linux カーネルは、ユーザー空間の flanneld プログラムに「L3 Miss」イベント リクエストを送信します。flanneld プログラムがリクエスト イベントを受信した後、このアドレスと一致するサブネット内の flannel.1 デバイスの MAC アドレス、つまり、ターゲット ポッドが配置されているホスト内の flannel.1 デバイスの MAC アドレス。
flanneld : 各ホスト上で flanneld をエージェントとして実行すると、クラスターのネットワーク アドレス空間からホストの小さなネットワーク セグメント サブネットが取得され、そこからホスト内のすべてのコンテナーの IP アドレスが割り当てられます。同時に、Flanneld は K8s クラスター データベースを監視し、データをカプセル化するときに必要な mac、ip、およびその他のネットワーク データ情報を flannel.1 デバイスに提供します。
VXLAN : Virtual eXtensible Local Area Network、仮想拡張 LAN。L2 over L4 (MAC-in-UDP) パケット カプセル化モードを採用して、レイヤ 2 パケットをレイヤ 3 プロトコルでカプセル化します。これにより、データの大規模なレイヤ 2 仮想移行の要件を満たしながら、レイヤ 2 ネットワークをレイヤ 3 範囲内で拡張できるようになります。センターおよびマルチテナンシーの要件。flannel は vxlan の一部の機能のみを使用し、VNI は 1 に固定されます。
内部データ フレームは、ホストのレイヤ 2 ネットワーク経由で送信することはできません。Linux カーネルは、内部データ フレームをホストの eth0 経由で送信する内部データ フレームを伝送する、ホストの通常のデータ フレームにさらにカプセル化する必要もあります。
コンテナーのクロスネットワーク通信ソリューション: クラスターのホストが同じサブネット内にある場合、flannel.1 トンネルはスキップされ、ルーティング eth0 を通じて直接転送されます。同じサブネット内にない場合、flannel.1 トンネルはトンネルを通って転送されます。
異なるノード上のポッド通信プロセス:
- ポッド内のデータは、ポッドのルーティング情報に従ってブリッジ cni0 に送信されます。
- cni0 は、ノード ルーティング テーブルに従ってトンネル デバイス flannel.1 にデータを送信します。
- flannel.1 は、データ パケットの宛先 IP を確認し、ピア トンネル デバイスに関する必要な情報を flanneld から取得し、データ パケット flannel.1 をカプセル化して、データ パケットをピア デバイスに送信します。
- データ パッケージには が含まれており
Outer IP 与 Inner IP等相关信息, 将PodIP和所在的NodeIP关联起来
、この関連付けを通じて、異なる Pod が相互にアクセスできます。 - 反対側のノードのネットワーク カードはデータ パケットを受信し、データ パケットがオーバーレイ パケットであることを確認し、外側のカプセル化を復号化し、内側のカプセル化を flannel.1 に送信します。
- Device Flannel.1 デバイスはデータ パケットをチェックし、ルーティング テーブルに従って照合し、データを cni0 デバイスに送信します。
- cni0 はルーティング テーブルと一致し、データをブリッジに送信します。
3.1 Flannel コンテナ ネットワークの概要
Flannel が kubernet が依存する基盤ネットワークを構築できる理由は、次の 2 点を実現できるためです。
- 相互に競合しないように、各ノード上の Docker コンテナに IP アドレスを割り当てます。
- これらの IP アドレス間にオーバーレイ ネットワークを確立でき、データ パケットをオーバーレイ ネットワークを通じてターゲット コンテナにそのまま配信できます。
フランネルネットワーク伝送プロセス:
- データはソース コンテナから送信された後、ホスト マシンの dockerO 仮想ネットワーク カードを介して flannel0 仮想ネットワーク カードに転送されます。これは P2P 仮想ネットワーク カードです。flanneld サービスはネットワーク カードのもう一方の端を監視します ( Flannel は、Etcd サービスを通じてノード間のルーティング テーブルを維持します。);
- ソース ホストの flanneld サービスは、元のデータ コンテンツを UDP カプセル化して、独自のルーティング テーブルに従って宛先ノードの flanneld サービスに配信します。データが到着すると、解凍されて、ホストの flannel0 仮想ネットワーク カードに直接入力されます。 dockerO 仮想ネットワーク カード。
- ·最後に、ローカル コンテナが通信するのと同じように、docker ルートがターゲット コンテナに到達し、データ パケット全体の配信が完了します。
4. サービスネットワーク: ClusterIp
Kubernetes では、Pod是非持久性的资源
必要に応じて を作成および破棄できます。Deployment を使用してアプリケーションを実行する場合、水平方向の拡張と縮小を実現するために、必要に応じてポッドを動的に作成または破棄できます。
Deploymentを導入し、Podに複数のコピーを設定すると、あるサービスに複数のPodと複数のpodIpが存在することになり、それらのPodのIPがわかってもアクセスするのが不便になります。また、Pod的IP地址是动态分配
も変化する可能性があるため、実際の通信においてはPodのIPアドレスを直接使用して通信すると問題が発生します。この問題を解決するために、Kubernetes はサービスの概念を導入しました。
したがって、他の Pod がサービス (Nginx) に対応するすべての Pod をリクエストできるようにするための統一された入り口が必要です。このとき、リソース オブジェクト Service があり、その主な機能は統一された入り口を提供することであり、これはすべての Pod にアクセスするために 1 つの IP だけが必要であることを意味し、この入り口 IP は Service の IP である ClusterIP です。
Pod IP アドレスは実際には特定のネットワーク カード (仮想デバイスの可能性があります) 上に存在しますが、
Cluster IP是一个完全虚拟的IP
それに対応するネットワーク デバイスがありません。
- クラスター IP は Kubernetes Service オブジェクトに対してのみ機能し、Kubernetes によって管理および割り当てられます。
- クラスター IP を ping できません。応答する「エンティティ ネットワーク オブジェクト」がありません。
- クラスター IP はサービス ポートと組み合わせて特定の通信ポートを形成することのみが可能であり、クラスター IP だけでは通信の基盤を持たず、Kubernetes クラスターのような閉じられた空間に属します。
- 仮想 IP は固定されているため、サービスはポッドの動的 IP を解決できます。
Service是一种持久性资源
、これは 1 つ以上のエンドポイントを提供し、ラベル セレクターを通じてクラスター内のポッドのグループを指すことができます。サービスは ClusterIP を使用して内部クラスターへのネットワーク接続を提供します。ClusterIP は固定仮想 IP であるため、通过Service来访问Pod
ポッドの動的 IP アドレスを直接使用する必要はありません。デプロイメントが作成され、アプリケーションが実行されると、通常、ポッドにアクセスするためのインターフェースを提供する 1 つ以上のサービスが作成されます。このようにして、ポッドの IP アドレスが変更された場合でも、サービスのエンドポイントを介してポッドにアクセスできるため、クラスター内で信頼性の高い通信が確保され、ポッドの動的な変更によって引き起こされる問題が回避されます。
サービス抽象化レイヤーを導入することにより、K8s は次の問題も解決できます。
-
サービス検出: サービスは、サービス検出の問題を解決するために統合された ClusterIP を提供します。クライアントは、ClusterIP 経由でのみアプリの Pod クラスターにアクセスできます。クラスター内の Pod と PodIP の特定の数を気にする必要はありません。PodIP が変更された場合でも、 、ClusterIP によってブロックされます。ここでの ClusterIP は実際には仮想 IP (仮想 IP (VIP) とも呼ばれます) であることに注意してください。
-
負荷分散: サービス抽象化レイヤーには負荷分散機能があり、アプリケーション クラスター内のさまざまな Pod インスタンスにアクセスして負荷共有と HA の高可用性を実現するためのさまざまな戦略をサポートします。K8s のデフォルトの負荷分散戦略は RoundRobin ですが、他の複雑な戦略もカスタマイズできます。
上記の K8s クラスタでは Service が独立したコンポーネントとして描かれていますが、実際には独立した Service というコンポーネントは存在せず、抽象的な概念にすぎません。
4.1 サービスの検出
K8s は、ServiceName+ClusterIP を通じてサービス検出と負荷分散を均一に保護し、基盤となるテクノロジーは DNS+Service Registry に基づいて開発されています。K8s サービス ディスカバリとロード バランシングは、Kube-Proxy + iptables 転送を通じてクライアントに実装されており、アプリケーションに対して非侵入的であり、プロキシを通過せず、さらなるパフォーマンスの損失はありません。K8s サービス検出メカニズムは、最新のマイクロサービス検出メカニズムと従来の Linux カーネル メカニズムをうまく組み合わせたものと考えることができます。
5. クラスタネットワークへの外部アクセス
5.1 ノードポート
K8sのサービスネットワークClusterIpはクラスタの内部ネットワークのみであり、クラスタ外から直接アクセスすることはできません。NodePort を介して K8s 内のサービスを公開したい場合は、サービスの NodePort タイプを使用して、サービスの ClusterIP に対応するポートを各ノードの IP にマッピングします。マッピングされたポートの範囲は 30000 ~ 32767 です。
Service NodePort サービスがリリースされると、K8s は各ワーカー ノードで nodePort ポートを開きます。このポートの背後にあるのは、Kube-Proxy
K8s 外部のクライアントが K8s クラスター内のサービスにアクセスしたい場合、サービスの NodePort ポートを介して呼び出しを開始し、この呼び出しは Kube-Proxy を介して内部 Servcie 抽象化レイヤーに転送され、その後転送されます。ポッド上のターゲットへ。
5.1.1containerPort、port、nodePort、targetPortの違いと接続
- コンテナポート:
Container容器暴露的端口
。ContainerPort は、ポッド内のコンテナーが公開する必要があるポッド コントローラーで定義されたポートです。 - ポート:
service暴露在集群中的端口,仅限集群内部访问
。Port はクラスター (クラスター ネットワーク) 上で公開されるポートであり、クラスター内のクライアントがサービスにアクセスするための入り口 (clusterIP:port) を提供します。mysql コンテナはポート 3306 を公開します (DockerFile を参照)。クラスタ内の他のコンテナはポート 33306 を通じて mysql サービスにアクセスしますが、mysql サービスが NodePort で構成されていないため、外部トラフィックは mysql サービスにアクセスできません。 - ノードポート:
集群节点Node暴露在外网中的端口
。nodePort は、クラスター外のクライアントがサービス (つまり、nodeIP) にアクセスする方法を提供します。nodePort は、k8s クラスター内のサービスへの外部ネットワーク アクセスの入り口を提供します。 - ターゲットポート:
Pod暴露的端口
。targetPort はポッド上のポートです。port/nodePort からのデータは、kube-proxy を介してバックエンド ポッドの targetPort に流れ、最終的にコンテナーに入ります。したがって、targetPort とコンテナーのcontainerPort は一致している必要があります。
5.2 LoadBalancer クラウドロードバランサー
NodePortをベースに、クラウドサービスプロバイダーが提供するロードバランサLoad-Balancerを追加し、このバランサを利用すると、アクセス時にnodePort30055を持っていく必要がなくなり、トラフィックを自動的にクラスタ内の各ノードに分散することができます。
5.3 Nginx サービスのリバース プロキシとドメイン名
Nodeport はレイヤー 4 パケット転送のみをサポートするため、ドメイン名ベースの転送と URI ベースのマッチングはサポートしません。したがって、リバース プロキシ用に Nodeport に Nginx サービスのレイヤーを追加することを検討しました。
Nginx をリバース プロキシ サーバーとして使用するのが一般的で、複数のサービスに負荷分散とルーティング機能を提供します。この場合、Nginx は通常、別のポッドにデプロイされ、そのポッドはサービスによって外部ネットワークに公開されます。外部リクエストが Nginx サービスに到達すると、Nginx ポッドにルーティングされます。次に、Nginx Pod は、設定に従ってリクエストを対応する APP サービスに転送します。
上の図は、クライアント アクセスを模擬したパケット キャプチャの状況を示しています。パケット キャプチャを通じて、リバース プロキシに Nginx を使用する場合、ポッド内のサービスにアクセスするには大量のパケットの送信が必要であることがわかります。ページでは 59 個のパケットをリクエストする必要があり、これにより大量のリソース損失が発生し、Ingress が発生しました。
5.4 イングレスプロキシサービス
Ingress は Service の上にあるプロキシの層で、通常、Ingress は HTTP ルーティング設定を提供するために Service の前で使用されます。これにより、外部 URL、ドメインベースの仮想ホスティング、SSL、負荷分散を設定できるようになります。
Ingress は 7 層のロード バランサーに相当し、k8s のリバース プロキシを抽象化したものです。一般的な動作原理は確かに Nginx に似ています。Ingress でマッピング ルールを 1 つずつ確立すると理解できます。Ingress コントローラーは、Ingress API オブジェクト内の構成ルールをリッスンし、それらを Nginx 構成 (kubernetes 宣言 API と制御ループ) に変換します。 ).その後、外部の世界にサービスを提供します。Ingress には、Ingress コントローラーと Ingress リソースが含まれます。
- イングレス コントローラー: コアはデプロイメントであり、nginx、Contour、Haproxy、trafik、Istio などの多くの実装メソッドがあります。記述する必要がある yaml は、Deployment、Service、ConfigMap、ServiceAccount (Auth) です。サービス タイプは NodePort または LoadBalancer です。
- ingress リソース: これは Ingress タイプの k8s API オブジェクトであり、この部分は開発者向けです。
上図に示すように、Ingress 利用後のパケット キャプチャ プロセスでは、この時点では eth0 と docker ブリッジが Kube-Proxy を介して通信せず、Ingress Controller を介して直接通信していることがわかります。静的な Web ページにアクセスするには、再度パケットを送信します。35 バッグ。