

 **このページの改善にご協力ください** 

このユーザーガイドに貢献するには、すべてのページの右側のペインにある「**GitHub でこのページを編集する**」リンクを選択してください。

# ハイブリッドノードの概念
<a name="hybrid-nodes-concepts"></a>

*Amazon EKS Hybrid Nodes* を使用すると、オンプレミス環境またはエッジ環境で実行されている物理マシンまたは仮想マシンを、AWS クラウドで実行されている Amazon EKS クラスターに接続できます。このアプローチには多くの利点がありますが、単一のネットワーク環境で Kubernetes クラスターを運用することに慣れているユーザーにとっては、新しいネットワークの概念やアーキテクチャが導入されることにもなります。

以下のセクションでは、EKS Hybrid Nodes での Kubernetes とネットワーキングの概念、およびハイブリッドアーキテクチャにおけるトラフィックフローについて詳しく説明します。これらのセクションを理解するには、ポッド、ノード、サービス、Kubernetes コントロールプレーン、kubelet、kube-proxy の概念など、Kubernetes ネットワークに関する基本的な知識に精通している必要があります。

これらのページは、「[ハイブリッドノードにおけるネットワーキングの概念](hybrid-nodes-concepts-networking.md)」、「[ハイブリッドノードにおける Kubernetes の概念](hybrid-nodes-concepts-kubernetes.md)」、「[ハイブリッドノード向けネットワークトラフィックフロー](hybrid-nodes-concepts-traffic-flows.md)」の順に読むことをお勧めします。

**Topics**
+ [ハイブリッドノードにおけるネットワーキングの概念](hybrid-nodes-concepts-networking.md)
+ [ハイブリッドノードにおける Kubernetes の概念](hybrid-nodes-concepts-kubernetes.md)
+ [ハイブリッドノード向けネットワークトラフィックフロー](hybrid-nodes-concepts-traffic-flows.md)

# ハイブリッドノードにおけるネットワーキングの概念
<a name="hybrid-nodes-concepts-networking"></a>

このセクションでは、EKS Hybrid Nodes のネットワークトポロジー設計の際に考慮すべき、コアネットワーキングの概念と制約について詳しく説明します。

## EKS Hybrid Nodes におけるネットワーキングの概念
<a name="_networking_concepts_for_eks_hybrid_nodes"></a>

![\[ハイブリッドノードのネットワーク概要図\]](http://docs.aws.amazon.com/ja_jp/eks/latest/userguide/images/hybrid-nodes-highlevel-network.png)


 **ネットワークハブとしての VPC** 

クラウドの境界を越えるすべてのトラフィックは VPC を経由しますが、これには、AWS で稼働する EKS コントロールプレーンまたはポッドや、ハイブリッドノードまたはそうしたノードで稼働しているポッド間のトラフィックも含まれます。クラスターの VPC はハイブリッドノードと残りのクラスター部分のネットワークハブとして機能している、と考えるとよいでしょう。このアーキテクチャによってトラフィックとそのルーティングを完全に制御できますが、これを導入するには、VPC のルート、セキュリティグループ、ファイアウォールを適切に設定する責任を負うことにもなります。

 **EKS コントロールプレーンから VPC に向かうトラフィック** 

EKS コントロールプレーンにより、**Elastic Network Interface (ENI)** が VPC にアタッチされ、これらの ENI によって、EKS API サーバーとの間でトラフィックが処理されます。EKS コントロールプレーンの ENI の配置は、クラスターを設定する際に制御します。なぜなら、クラスターの作成中に渡すサブネットに ENI がアタッチされるからです。

EKS では、セキュリティグループを、サブネットにアタッチする ENI に関連付けます。こうしたセキュリティグループにより、EKS コントロールプレーンとの間のトラフィックを、ENI を介して許可します。この点が EKS Hybrid Nodes では重要となります。ハイブリッドノードとそこで稼働しているポッドから EKS コントロールプレーン ENI へのトラフィックを許可する必要があるからです。

 **リモートノードネットワーク** 

リモートノードネットワーク、具体的にはリモートノード CIDR は、ハイブリッドノードとして使用するマシンに割り当てる IP アドレスの範囲を意味します。ハイブリッドノードをプロビジョニングすると、それらはオンプレミスのデータセンターやエッジロケーションに配置されます。これらのネットワークドメインは、EKS コントロールプレーンおよび VPC のドメインとは異なります。また、各ハイブリッドノードには、IP アドレスが 1 つまたは複数あり、VPC 内のサブネットとは異なるリモートノード CIDR に基づいて設定されています。

こうしたリモートノード CIDR を使用して EKS クラスターを構成すると、EKS でそれが認識され、ハイブリッドノードの IP アドレスを宛先としたすべてのトラフィック (kubelet API へのリクエストなど) をクラスターの VPC 経由でルーティングできるようになります。`kubelet` API への接続は、`kubectl attach`、`kubectl cp`、`kubectl exec`、`kubectl logs`、`kubectl port-forward` の各コマンドで使用されます。

 **リモートポッドネットワーク** 

ここでのリモートポッドネットワークとは、ハイブリッドノードで稼働するポッドに割り当てる IP アドレスの範囲を意味します。一般的には、これらの範囲で CNI を設定すると、CNI の IP Address Manager (IPAM) 機能によって、その範囲の一部が各ハイブリッドノードに割り当てられます。また、新規作成したポッドには、ポッドをスケジュールしたノードに割り当てた IP アドレスからアドレスが割り当てられます。

こうしたリモートポッド CIDR を使用して EKS クラスターを設定すると、EKS コントロールプレーンでそれが認識され、ハイブリッドノードで稼働しているポッドを宛先とするすべてのトラフィック (ウェブフックとの通信など) をクラスターの VPC 経由でルーティングできます。

![\[リモートポッドネットワーク\]](http://docs.aws.amazon.com/ja_jp/eks/latest/userguide/images/hybrid-nodes-remote-pod-cidrs.png)


 **オンプレミスから VPC に向かうトラフィック** 

ハイブリッドノードに使用するオンプレミスネットワークのトラフィックは、EKS クラスターに使用する VPC にルーティングする必要があります。オンプレミスネットワークを VPC に接続する場合、複数用意されている [Network-to-Amazon VPC 接続オプション](https://docs.aws.amazon.com/whitepapers/latest/aws-vpc-connectivity-options/network-to-amazon-vpc-connectivity-options.html)を利用することも、独自の VPN ソリューションを使用することもできます。

ここで重要なのは、AWS クラウド側の VPC とオンプレミスネットワーク間のルーティングを正しく設定することで、両方のネットワークの接続点を介して、適切なトラフィックが相互にルーティングされるようにすることです。

VPC では、リモートノードおよびリモートポッドネットワークに向かうすべてのトラフィックを、オンプレミスネットワークとの接続点 (ゲートウェイ) 経由でルーティングする必要があります。サブネットの一部に異なるルートテーブルがある場合は、ハイブリッドノードとそこで稼働しているポッドのルートを各ルートテーブルに設定する必要があります。これは、EKS コントロールプレーンの ENI がアタッチされるサブネットや、ハイブリッドノードと通信する必要のある EC2 のノードまたはポッドが含まれるサブネットにも当てはまります。

オンプレミスネットワークでは、ネットワークの設定によって、EKS クラスターの VPC や、ハイブリッドノードに必要なその他の AWS サービスとの間で生じるトラフィックを許可する必要があります。EKS クラスターのトラフィックは、ゲートウェイを双方向に通過することになります。

## ネットワーキング上の制約
<a name="_networking_constraints"></a>

 **完全にルーティングされたネットワーク** 

ここでの主な制約は、EKS コントロールプレーンとすべてのノード (クラウドまたはハイブリッドのノード) で生じるトラフィックが**完全にルーティング**されるネットワークを形成する必要があることです。つまり、すべてのノードが IP アドレスを使用してレイヤー 3 で互いに到達可能でなければなりません。

EKS コントロールプレーンとクラウドノードはフラットなネットワーク (VPC) 内にあるため、相互に到達可能な状態にありますが、ハイブリッドノードは異なるネットワークドメインに存在しています。そのため、VPC とオンプレミスネットワークでルーティング設定を追加して、ハイブリッドノードと他のクラスター部分との間で生じるトラフィックをルーティングする必要があります。ハイブリッドノードが互いに到達可能で、VPC からも到達可能な場合、ハイブリッドノードは、単一のフラットネットワークに配置することも、セグメント化した複数のネットワークに配置することもできます。

 **ルーティング可能なリモートポッド CIDR** 

EKS コントロールプレーンがハイブリッドノードで稼働中のポッド (ウェブフックやメトリクスサーバーなど) と通信したり、クラウドノードで稼働中のポッドがハイブリッドノードで稼働中のポッドと通信 (ワークロードの East-West 通信) したりするには、リモートポッドの CIDR へのトラフィックが VPC からルーティング可能でなければなりません。つまり、VPC では、ポッドの CIDR に向かうトラフィックをゲートウェイ経由でオンプレミスネットワークにルーティングでき、オンプレミスネットワークでは、ポッドのトラフィックを適切なノードにルーティングできる必要があります。

ここで重要なのは、VPC とオンプレミスでポッドのルーティング要件に違いがあることです。VPC には、リモートポッドへのトラフィックがゲートウェイを通過する必要があることを認識させるだけで済み、リモートポッドの CIDR が 1 つしかない場合は、必要なルートも 1 つのみです。

この要件は、オンプレミスネットワーク内の、ハイブリッドノードと同じサブネットでローカルルーターに至るまでに生じるすべてのホップに当てはまります。このルーターは、各ノードに割り当てられたポッド CIDR スライスを認識する必要がある唯一のルーターです。これにより、特定のポッドに向かうトラフィックを、そのポッドがスケジュールされているノードに配信できます。

オンプレミスのポッド CIDR へのこうしたルートを、ローカルのオンプレミスルーターから VPC ルートテーブルに伝達することもできますが、これは必須ではありません。オンプレミスのポッド CIDR を頻繁に変更しているため、VPC ルートテーブルを更新してそれらの変更を反映する必要がある場合は、オンプレミスのポッド CIDR を VPC ルートテーブルに伝達することが推奨されます。しかし、こうしたケースはまれです。

オンプレミスのポッド CIDR へのルーティングは、必ずしも設定する必要はありません。ハイブリッドノードでウェブフックを実行する必要がない場合、またはクラウドノード上のポッドがハイブリッドノード上のポッドと通信する必要がない場合は、オンプレミスネットワークのポッド CIDR へのルーティングを設定しなくても済みます。

 *では、ハイブリッドノードを使用するときに、オンプレミスのポッド CIDR 宛てトラフィックをルーティング可能にする理由について説明します。*

VPC CNI を備えた EKS をクラウドノードに使用している場合、VPC CNI によって VPC からポッドに直接 IP が割り当てられます。つまり、クラウドポッドも EKS コントロールプレーンもポッド IP に直接到達できるため、特別なルーティングは必要ありません。

オンプレミスでポッドが稼働している場合 (クラウドで他の CNI を使用)、ポッドは、通常、分離されたオーバーレイネットワークで実行され、CNI によってポッド間のトラフィック配信が処理されます。これは通常、カプセル化によって行われます。つまり、ポッド間のトラフィックをノード間のトラフィックに変換し、両端でカプセル化とカプセル化解除を行います。そのため、ノードとルーターに設定をさらに追加する必要はありません。

ハイブリッドノードを使用したネットワークは、両方のトポロジーが組み合わさっているという点で独特なものです。つまり、EKS コントロールプレーンとクラウドノード (VPC CNI を使用) は、ノードとポッドが含まれるフラットなネットワークを想定して動作し、一方、ハイブリッドノードで稼働するポッドは、オーバーレイネットワーク内に存在し、カプセル化には VXLAN (Cilium のデフォルト) が使用されます。ハイブリッドノードで稼働するポッドは、オンプレミスネットワークと VPC 間のルーティングが可能であることを前提に、EKS コントロールプレーンとクラウドノードで稼働中のポッドに到達できます。ただし、オンプレミスネットワークのポッド CIDR 宛てトラフィックをルーティングしておらず、オーバーレイネットワークに到達したトラフィックを適切なノードに転送できない場合、オンプレミスのポッド IP に戻るトラフィックは、最終的にドロップされます。

# ハイブリッドノードにおける Kubernetes の概念
<a name="hybrid-nodes-concepts-kubernetes"></a>

このページでは、EKS Hybrid Nodes システムアーキテクチャを支える Kubernetes の主要な概念について詳しく説明します。

## VPC の EKS コントロールプレーン
<a name="hybrid-nodes-concepts-k8s-api"></a>

EKS コントロールプレーン ENI の IP は、`default` デフォルトの名前空間にある `kubernetes` `Endpoints` オブジェクトに保存されます。EKS では、ENI の新規作成や削除が行わると、このオブジェクトが更新され、IP リストが常に最新状態に保たれます。

これらのエンドポイントは、`kubernetes` サービスを通じて使用できます。このサービスも `default` の名前空間に存在します。この `ClusterIP` タイプのサービスには、クラスターのサービス CIDR に含まれる最初の IP が割り当てられます。例えば、サービス CIDR が `172.16.0.0/16` の場合、サービス IP は `172.16.0.1` になります。

通常、ポッドは (稼働がクラウドノード上かハイブリッドノード上かに関係なく) そのように EKS Kubernetes API サーバーにアクセスします。サービス IP を宛先 IP として使用し、これをいずれかの EKS コントロールプレーン ENI に設定されている実際の IP に変換します。こうした動作の主な例外として `kube-proxy` があります。これによって変換を設定するからです。

## EKS API サーバーエンドポイント
<a name="hybrid-nodes-concepts-k8s-eks-api"></a>

EKS API サーバーには `kubernetes` サービス IP 以外の方法でもアクセスできます。EKS では、クラスター作成時に Route53 DNS 名も作成されます。これが、EKS の `endpoint` API アクションを呼び出す際に、EKS クラスターの `DescribeCluster` フィールド値になります。

```
{
    "cluster": {
        "endpoint": "https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.gr7.us-west-2.eks.amazonaws.com",
        "name": "my-cluster",
        "status": "ACTIVE"
    }
}
```

パブリックエンドポイントアクセスクラスター、もしくはパブリックおよびプライベートエンドポイントアクセスクラスターでは、ハイブリッドノードで、この DNS 名がインターネット経由でルーティング可能なパブリック IP に解決されます (デフォルトの場合)。プライベートエンドポイントアクセスクラスターの場合、DNS 名は、EKS コントロールプレーン ENI のプライベート IP に解決されます。

`kubelet` と `kube-proxy` は、そのように Kubernetes API サーバーにアクセスします。すべての Kubernetes クラスタートラフィックを VPC 経由にする場合、クラスターをプライベートアクセスモードで設定するか、オンプレミスの DNS サーバーを変更して EKS クラスターエンドポイントを EKS コントロールプレーン ENI のプライベート IP に解決する必要があります。

## `kubelet` エンドポイント
<a name="hybrid-nodes-concepts-k8s-kubelet-api"></a>

`kubelet` では複数の REST エンドポイントが公開されており、これによってシステムの他の要素は、kubelet と通信し、各ノードの情報を収集しています。ほとんどのクラスターにおいて、`kubelet` サーバーに向かうトラフィックの大部分は、コントロールプレーンで生じたものですが、特定のモニタリングエージェントも kubelet と通信する場合があります。

このインターフェイスを通じて、`kubelet` では、ログの取得 (`kubectl logs`)、コンテナ内でのコマンド実行 (`kubectl exec`)、トラフィックのポート転送 (`kubectl port-forward`) といった各種リクエストが処理されます。こうしたリクエストでは、基盤のコンテナランタイム環境との通信が `kubelet` を介して行われるため、クラスター管理者や開発者にとってシームレスなユーザー体験が実現します。

この API で最も一般的なコンシューマーとなるのは Kubernetes API サーバーです。上記の `kubectl` コマンドのいずれかを使用すると、`kubectl` が API サーバーに API リクエストを送信し、その後 API サーバーが、ポッドが稼働しているノードの `kubelet` API を呼び出します。そのため、多くの場合、ノード IP が EKS コントロールプレーンから到達可能である必要があります。また、ノードルートを誤って設定すると、ポッドが稼働中であっても、ログや `exec` コマンドを利用できません。

 **ノード IP** 

EKS コントロールプレーンは、ノードと通信する際に、`Node` オブジェクトのステータス (`status.addresses`) で報告されるアドレスの 1 つを使用します。

EKS クラウドノードでは、一般的に、ノード登録時に kubelet が EC2 インスタンスのプライベート IP を `InternalIP` として報告します。その後、Cloud Controller Manager (CCM) がこの IP を検証し、それが EC2 インスタンスに属していることを確認します。さらに、CCM は通常、インスタンスのパブリック IP (`ExternalIP`) と DNS 名 (`InternalDNS` と `ExternalDNS`) をノードステータスに追加します。

ただし、ハイブリッドノードには CCM はありません。EKS Hybrid Nodes CLI (`nodeadm`) を使用してハイブリッドノードを登録すると、CCM を介さずにノードのステータスでマシンの IP が直接報告されるように kubelet が設定されます。

```
apiVersion: v1
kind: Node
metadata:
  name: my-node-1
spec:
  providerID: eks-hybrid:///us-west-2/my-cluster/my-node-1
status:
  addresses:
  - address: 10.1.1.236
    type: InternalIP
  - address: my-node-1
    type: Hostname
```

マシンに複数の IP がある場合、kubelet は独自のロジックに従ってそれらの 1 つを選択します。選択される IP アドレスは `--node-ip` フラグで制御でき、このフラグは、`nodeadm` config の `spec.kubelet.flags` に渡すことが可能です。`Node` オブジェクトで報告された IP アドレスにのみ VPC からのルートが必要であり、マシンには、クラウドからアクセスできない他の IP アドレスを割り当てることができます。

## `kube-proxy`
<a name="hybrid-nodes-concepts-k8s-kube-proxy"></a>

 `kube-proxy` は、各ノードのネットワークレイヤーでサービス抽象化を実装する役割を果たし、Kubernetes サービスに向かうトラフィックのネットワークプロキシおよびロードバランサーとして機能します。また、`kube-proxy` は、Kubernetes API サーバーを監視し、サービスとエンドポイントに関連した変更を継続的に確認することで、基盤となるホストのネットワークルールを動的に更新し、適切なトラフィック転送を維持します。

`iptables` モードの `kube-proxy` は、複数の `netfilter` チェーンをプログラミングして、サービストラフィックを処理します。こうしたルールによって、以下の階層が形成されます。

1.  **KUBE-SERVICES チェーン**: すべてのサービストラフィックのエントリポイント。各サービスの `ClusterIP` とポートに一致するルールが定義されています。

1.  **KUBE-SVC-XXX チェーン**: サービス固有のチェーンに、各サービスの負荷分散ルールが定義されています。

1.  **KUBE-SEP-XXX チェーン**: エンドポイント固有のチェーンに、実際の `DNAT` ルールが定義されています。

次に示す `default` 名前空間内のサービス `test-server` の状況を確認してみましょう。\$1 サービス ClusterIP: `172.16.31.14` \$1 サービスポート: `80` \$1 バッキングポッド: `10.2.0.110`, `10.2.1.39`, `10.2.2.254` 

`iptables` ルールを検査するとき (`iptables-save 0 grep -A10 KUBE-SERVICES` を使用):

1. **KUBE-SERVICES** チェーンには、以下のように、サービスに一致するルールがあります。

   ```
   -A KUBE-SERVICES -d 172.16.31.14/32 -p tcp -m comment --comment "default/test-server cluster IP" -m tcp --dport 80 -j KUBE-SVC-XYZABC123456
   ```
   + このルールは、172.16.31.14:80 宛てのパケットに一致させる
   + コメントは、このルールの目的を示している: `default/test-server cluster IP` 
   + 一致するパケットは `KUBE-SVC-XYZABC123456` チェーンにジャンプさせる

1. **KUBE-SVC-XYZABC123456** チェーンには、確率ベースの負荷分散ルールが定義されています。

   ```
   -A KUBE-SVC-XYZABC123456 -m statistic --mode random --probability 0.33333333349 -j KUBE-SEP-POD1XYZABC
   -A KUBE-SVC-XYZABC123456 -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-POD2XYZABC
   -A KUBE-SVC-XYZABC123456 -j KUBE-SEP-POD3XYZABC
   ```
   + 最初のルール: 33.3% の確率で `KUBE-SEP-POD1XYZABC` にジャンプさせる 
   + 2 番目のルール: 50% の確率で残りのトラフィック (全体の 33.3%) を `KUBE-SEP-POD2XYZABC` にジャンプさせる 
   + 最後のルール: 残りのすべてのトラフィック (合計の 33.3%) を `KUBE-SEP-POD3XYZABC` にジャンプさせる 

1. 個々の **KUBE-SEP-XXX** チェーンで、DNAT (宛先 NAT) を実行します。

   ```
   -A KUBE-SEP-POD1XYZABC -p tcp -m tcp -j DNAT --to-destination 10.2.0.110:80
   -A KUBE-SEP-POD2XYZABC -p tcp -m tcp -j DNAT --to-destination 10.2.1.39:80
   -A KUBE-SEP-POD3XYZABC -p tcp -m tcp -j DNAT --to-destination 10.2.2.254:80
   ```
   + これらの DNAT ルールでは、宛先 IP とポートを書き換えて、トラフィックを特定のポッドに転送します。
   + 各ルールによって、トラフィックの約 33.3% を処理し、`10.2.0.110`、`10.2.1.39`、`10.2.2.254` の間で均等な負荷分散を行います。

このマルチレベルチェーン構造により、`kube-proxy` では、データパスにプロキシプロセスを必要とせずに、カーネルレベルのパケット操作によってサービスの負荷分散およびリダイレクトを効率的に実装できます。

### Kubernetes 運用への影響
<a name="hybrid-nodes-concepts-k8s-operations"></a>

ノードで `kube-proxy` の機能が失われると、ノードはサービストラフィックを適切にルーティングできなくなり、クラスターサービスに依存するポッドのタイムアウトや接続の失敗が発生します。この問題が特に深刻になりうるのは、ノードが最初に登録されたときです。CNI では、ポッドネットワークを設定する前に、Kubernetes API サーバーと通信して、ノードのポッド CIDR などの情報を取得する必要があります。それを行うには、`kubernetes` サービス IP を使用します。ただし、`kube-proxy` が起動できなかったり、適切な `iptables` ルールを設定できなかったりした場合、`kubernetes` サービス IP へのリクエストは EKS コントロールプレーン ENI の実際の IP に変換されません。その結果、CNI がクラッシュループに陥り、どのポッドも正しく稼働しなくなります。

前述したように、ポッドは Kubernetes API サーバーとの通信に `kubernetes` のサービス IP を使用しますが、そのように動作させるには、最初に `kube-proxy` に `iptables` ルールを設定する必要があります。

`kube-proxy` は、どのように API サーバーと通信するのでしょうか?

`kube-proxy` は、Kubernetes API サーバーの実際の IP アドレス、またはそれらに解決される DNS 名を使用するように設定する必要があります。EKS の場合、デフォルトの `kube-proxy` が、クラスター作成時に EKS によって作成される Route53 DNS 名を指すように設定されます。この値は、`kube-system` 名前空間の `kube-proxy` ConfigMap で確認できます。この ConfigMap の内容は、`kube-proxy` ポッドに注入される `kubeconfig` であるため、`clusters0.cluster.server` フィールドを確認してください。この値は、EKS `DescribeCluster` API を呼び出した結果にある、EKS クラスターの `endpoint` フィールドと一致しています。

```
apiVersion: v1
data:
  kubeconfig: |-
    kind: Config
    apiVersion: v1
    clusters:
    - cluster:
        certificate-authority: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
        server: https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.gr7.us-west-2.eks.amazonaws.com
      name: default
    contexts:
    - context:
        cluster: default
        namespace: default
        user: default
      name: default
    current-context: default
    users:
    - name: default
      user:
        tokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
kind: ConfigMap
metadata:
  name: kube-proxy
  namespace: kube-system
```

## ルーティング可能なリモートポッド CIDR
<a name="hybrid-nodes-concepts-k8s-pod-cidrs"></a>

この [ハイブリッドノードにおけるネットワーキングの概念](hybrid-nodes-concepts-networking.md) のページでは、ハイブリッドノードでウェブフックを実行したり、クラウドノードで稼働しているポッドがハイブリッドノードで稼働しているポッドと通信したりするための要件について詳しく説明します。ここでは重要な要件があります。特定のポッド IP を担当するノードを、オンプレミスルーターに認識させる必要があることです。これを実現する方法として、ボーダーゲートウェイプロトコル (BGP)、静的ルート、アドレス解決プロトコル (ARP) プロキシなどが挙げられます。以下のセクションでは、これらの方法について説明します。

 **ボーダーゲートウェイプロトコル (BGP)** 

CNI でサポートされている場合 (Cilium や Calico など)、CNI の BGP モードを使用して、ノードごとのポッド CIDR へのルートをノードからローカルルーターに伝達できます。CNI の BGP モードを使用する場合、CNI は仮想ルーターとして機能するため、ローカルルーターは、ポッド CIDR が別のサブネットに属し、ノードはそのサブネットへのゲートウェイであると認識します。

![\[ハイブリッドノード BGP ルーティング\]](http://docs.aws.amazon.com/ja_jp/eks/latest/userguide/images/hybrid-nodes-bgp.png)


 **静的ルート** 

または、ローカルルーターで静的ルートを設定することもできます。この方法を取ると、オンプレミスポッド CIDR を VPC に非常に簡単にルーティングできますが、最もエラーが発生しやすく、保守も困難になります。ルートが既存のノードと割り当てられたポッド CIDR で、常に最新の状態であることを確認しなければなりません。ノードの数が少なく、インフラストラクチャが静的である場合、これは実行可能なオプションであり、ルーターでの BGP 対応も不要になります。この方法を取る場合は、アドレスを IPAM によって決定せず、各ノードに割り当てるポッド CIDR スライスを使用して CNI を設定することをお勧めします。

![\[ハイブリッドノードの静的ルーティング\]](http://docs.aws.amazon.com/ja_jp/eks/latest/userguide/images/hybrid-nodes-static-routes.png)


 **アドレス解決プロトコル (ARP) プロキシ** 

ARP プロキシは、オンプレミスのポッド IP をルーティング可能にするもう 1 つのアプローチであり、特に、ハイブリッドノードがローカルルーターと同じレイヤー 2 ネットワークにある場合に便利です。ARP プロキシを有効にすると、ノードは、その IP が別のサブネットに属している場合でも、ホストするポッド IP の ARP リクエストに応答します。

ローカルネットワーク上のデバイスがポッド IP に到達を試みる場合、最初に「この IP を持っているなら応答せよ」という ARP リクエストを送信します。該当するポッドをホストしているハイブリッドノードは、自分の MAC アドレスで応答し、「その IP のトラフィックを処理できます」と伝えます。これによって、ルーター設定を必要とせずに、ローカルネットワーク上のデバイスとポッドの間に直接のパスが作成されます。

これを機能させるには、CNI がプロキシ ARP 機能に対応している必要があります。Cilium は、設定によってプロキシ ARP を有効化できるように設計されています。ここで特に考慮すべき点は、ポッド CIDR が環境内の他のネットワークと重複しないようにすることです。重複すると、ルーティングの競合が生じる可能性があるからです。

このアプローチには、次のような利点があります。\$1 BGP でルーターを設定する必要はなく、静的ルートを維持する必要もない。\$1 ルーター設定を制御できない環境でも効果的に機能する。

![\[ハイブリッドノード ARP プロキシ\]](http://docs.aws.amazon.com/ja_jp/eks/latest/userguide/images/hybrid-nodes-arp-proxy.png)


## ポッド間でのカプセル化
<a name="hybrid-nodes-concepts-k8s-pod-encapsulation"></a>

オンプレミス環境の CNI では、通常、カプセル化プロトコルによって、物理ネットワーク上で動作するオーバーレイネットワークが作成されます。この場合、再設定が不要になります。このセクションでは、このカプセル化の仕組みについて説明します。使用している CNI によっては、一部の詳細情報が異なる場合があります。

カプセル化では、元のポッドネットワークパケットを、基盤の物理ネットワークを介してルーティング可能な別のネットワークパケット内にラップします。これによって、ポッドの CIDR のルーティング方法が物理ネットワークで認識されていなくても、同じ CNI を実行しているノード間でポッドが通信できます。

Kubernetes で使用される最も一般的なカプセル化プロトコルは Virtual Extensible LAN (VXLAN) ですが、CNI に応じて、他のプロトコル (`Geneve` など) も利用できます。

### VXLAN カプセル化
<a name="_vxlan_encapsulation"></a>

VXLAN では、UDP パケット内にレイヤー 2 イーサネットフレームをカプセル化します。ポッドが別のノードにある別のポッドにトラフィックを送信すると、CNI では、以下が実行されます。

1. ポッド A からのパケットをインターセプトする

1. 元のパケットを VXLAN ヘッダーにラップする

1. ラップしたパケットを、ノードの通常のネットワークスタックを介して宛先ノードに送信する

1. 宛先ノードの CNI が、パケットをラップ解除し、ポッド B に配信する

VXLAN カプセル化中のパケット構造の変化を次に示します。

元のポッド間パケット

```
+-----------------+---------------+-------------+-----------------+
| Ethernet Header | IP Header     | TCP/UDP     | Payload         |
| Src: Pod A MAC  | Src: Pod A IP | Src Port    |                 |
| Dst: Pod B MAC  | Dst: Pod B IP | Dst Port    |                 |
+-----------------+---------------+-------------+-----------------+
```

VXLAN カプセル化後

```
+-----------------+-------------+--------------+------------+---------------------------+
| Outer Ethernet  | Outer IP    | Outer UDP    | VXLAN      | Original Pod-to-Pod       |
| Src: Node A MAC | Src: Node A | Src: Random  | VNI: xx    | Packet (unchanged         |
| Dst: Node B MAC | Dst: Node B | Dst: 4789    |            | from above)               |
+-----------------+-------------+--------------+------------+---------------------------+
```

この VXLAN ネットワーク識別子 (VNI) によって、異なるオーバーレイネットワークが区別されます。

### ポッド通信のシナリオ
<a name="_pod_communication_scenarios"></a>

 **同じハイブリッドノード上のポッド** 

同じハイブリッドノード上のポッドが通信する場合、通常はカプセル化は必要ありません。CNI では、ローカルルートが設定されます。これにより、ノードの内部仮想インターフェイスを介してポッド間のトラフィックを転送します。

```
Pod A -> veth0 -> node's bridge/routing table -> veth1 -> Pod B
```

パケットはノードから出ることはなく、カプセル化を必要としません。

 **異なるハイブリッドノード上のポッド** 

異なるハイブリッドノード上のポッド間で通信するには、カプセル化が必要です。

```
Pod A -> CNI -> [VXLAN encapsulation] -> Node A network -> router or gateway -> Node B network -> [VXLAN decapsulation] -> CNI -> Pod B
```

これにより、物理ネットワークでポッド IP のルーティングが認識されていなくても、ポッドトラフィックは、物理ネットワークインフラストラクチャを通過できます。

# ハイブリッドノード向けネットワークトラフィックフロー
<a name="hybrid-nodes-concepts-traffic-flows"></a>

このページでは、EKS ハイブリッドノード向けネットワークトラフィックフローについて、いくつかのトラフィックタイプ別にエンドツーエンドでネットワークパスの図を示しながら詳しく説明します。

以下のトラフィックフローを取り上げます。
+  [ハイブリッドノード `kubelet` から EKS コントロールプレーンまでのフロー](#hybrid-nodes-concepts-traffic-flows-kubelet-to-cp) 
+  [EKS コントロールプレーンからハイブリッドノード (`kubelet` サーバー) までのフロー](#hybrid-nodes-concepts-traffic-flows-cp-to-kubelet) 
+  [ハイブリッドノードで実行されているポッドから EKS コントロールプレーンまでのフロー](#hybrid-nodes-concepts-traffic-flows-pods-to-cp) 
+  [EKS コントロールプレーンからハイブリッドノードで実行されているポッドまでのフロー (ウェブフック)](#hybrid-nodes-concepts-traffic-flows-cp-to-pod) 
+  [ハイブリッドノードで実行されているポッド間](#hybrid-nodes-concepts-traffic-flows-pod-to-pod) 
+  [クラウドノード上のポッドからハイブリッドノード上のポッドまでのフロー (東西トラフィック)](#hybrid-nodes-concepts-traffic-flows-east-west) 

## ハイブリッドノード `kubelet` から EKS コントロールプレーンまでのフロー
<a name="hybrid-nodes-concepts-traffic-flows-kubelet-to-cp"></a>

![\[ハイブリッドノード kubelet から EKS コントロールプレーンまでのフロー\]](http://docs.aws.amazon.com/ja_jp/eks/latest/userguide/images/hybrid-nodes-kubelet-to-cp-public.png)


### リクエスト
<a name="_request"></a>

 **1`kubelet`. がリクエストを開始する** 

ハイブリッドノード上の `kubelet` が EKS コントロールプレーンと通信する必要がある場合 (例えば、ノードステータスを報告するため、あるいはポッドの仕様を取得するため) には、ノード登録時に提供された `kubeconfig` ファイルが使用されます。この `kubeconfig` には、ダイレクト IP アドレスではなく、API サーバーエンドポイント URL (Route53 DNS 名) が記載されています。

`kubelet` がエンドポイントに対して DNS ルックアップを実行します (例: `https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.gr7.us-west-2.eks.amazonaws.com`)。パブリックアクセスクラスターでは、これは AWS で実行中の EKS サービスに属するパブリック IP アドレス (例: `54.239.118.52`) に解決されます。次に `kubelet` は、このエンドポイントへの安全な HTTPS リクエストを作成します。初期パケットは以下のようになります。

```
+--------------------+---------------------+-----------------+
| IP Header          | TCP Header          | Payload         |
| Src: 10.80.0.2     | Src: 52390 (random) |                 |
| Dst: 54.239.118.52 | Dst: 443            |                 |
+--------------------+---------------------+-----------------+
```

 **2. ローカルルーターのルーティング** 

宛先 IP はパブリック IP アドレスであり、ローカルネットワークの一部ではないため、`kubelet` はこのパケットをそのデフォルトゲートウェイ (ローカルオンプレミスルーター) に送信します。ルーターは、宛先 IP を確認して、パブリック IP アドレスであると判断します。

パブリックトラフィックの場合、ルーターは通常、パケットをインターネットゲートウェイ、つまりインターネットへのアウトバウンドトラフィックを処理するボーダールーターに転送します。図では、これを省略しています。実際の転送は、オンプレミスネットワークがどのように設定されているかによって異なります。パケットは、オンプレミスのネットワークインフラストラクチャを通っていき、最終的にインターネットサービスプロバイダーのネットワークに到達します。

 **3. EKS コントロールプレーンまでの配信** 

パケットは、パブリックインターネットとトランジットネットワークを横断していき、AWS のネットワークに到達します。AWS のネットワークは、パケットを適切なリージョンの EKS サービスエンドポイントにルーティングします。EKS サービスに到達したパケットは、クラスターの実際の EKS コントロールプレーンに転送されます。

これはパブリックインターネットを通るルーティングであり、他のトラフィックフローで見られるようなプライベート VPC をルーティングされていくパスとは異なります。その主な違いは、パブリックアクセスモードを使用した場合、ポッドからではなくオンプレミスの `kubelet` から EKS コントロールプレーンへのトラフィックが VPC を経由せず、代わりにグローバルインターネットインフラストラクチャを使用することです。

### 応答
<a name="_response"></a>

EKS コントロールプレーンは、`kubelet` リクエストを処理してレスポンスを返します。

 **3. EKS コントロールプレーンがレスポンスを送信する** 

EKS コントロールプレーンはレスポンスパケットを作成します。このパケットには、ソースとしてパブリック IP、送信先としてハイブリッドノードの IP が含まれています。

```
+--------------------+---------------------+-----------------+
| IP Header          | TCP Header          | Payload         |
| Src: 54.239.118.52 | Src: 443            |                 |
| Dst: 10.80.0.2     | Dst: 52390          |                 |
+--------------------+---------------------+-----------------+
```

 **2. インターネットでのルーティング** 

レスポンスパケットは、インターネットサービスプロバイダーが決定したルーティングパスをたどってインターネット経由で戻り、オンプレミスネットワークのエッジルーターに到達します。

 **1. ローカルでの配信** 

オンプレミスのルーターは、パケットを受信し、宛先 IP (`10.80.0.2`) がローカルネットワークに属していると認識します。次に、受信したパケットをローカルネットワークインフラストラクチャ経由で転送します。パケットがターゲットのハイブリッドノードに到達すると、`kubelet` がレスポンスを受信して処理します。

## ハイブリッドノード `kube-proxy` から EKS コントロールプレーンまでのフロー
<a name="_hybrid_node_kube_proxy_to_eks_control_plane"></a>

クラスターのパブリックエンドポイントアクセスを有効にすると、戻りのトラフィックはパブリックインターネットを使用します。このトラフィックは、ハイブリッドノードの `kube-proxy` から EKS コントロールプレーンへと進み、`kubelet` から EKS コントロールプレーンへのトラフィックと同じパスを通ります。

## EKS コントロールプレーンからハイブリッドノード (`kubelet` サーバー) までのフロー
<a name="hybrid-nodes-concepts-traffic-flows-cp-to-kubelet"></a>

![\[EKS コントロールプレーンからハイブリッドノードまでのフロー\]](http://docs.aws.amazon.com/ja_jp/eks/latest/userguide/images/hybrid-nodes-cp-to-kubelet.png)


### リクエスト
<a name="_request_2"></a>

 **1. EKS Kubernetes API サーバーがリクエストを開始する** 

EKS Kubernetes API サーバーは、ノードオブジェクトのステータスからノードの IP アドレス (`10.80.0.2`) を取得します。次に、送信先 IP が設定済みのリモートノード CIDR (`10.80.0.0/16`) に属しているため、このリクエストを VPC 内の ENI 経由でルーティングします。初期パケットは以下のようになります。

```
+-----------------+---------------------+-----------------+
| IP Header       | TCP Header          | Payload         |
| Src: 10.0.0.132 | Src: 67493 (random) |                 |
| Dst: 10.80.0.2  | Dst: 10250          |                 |
+-----------------+---------------------+-----------------+
```

 **2. VPC ネットワークでの処理** 

パケットは、ENI を出て VPC ネットワーキングレイヤーに入り、さらにルーティングするためにサブネットのゲートウェイ宛てに送信されます。

 **3. VPC ルートテーブルのルックアップ** 

EKS コントロールプレーン ENI が含まれているサブネット用の VPC ルートテーブルには、リモートノード CIDR に固有のルート (図の 2 番目のルート) が登録されています。このルーティングルールに基づいて、パケットが VPC-to-onprem ゲートウェイに向けて送信されます。

 **4. 境界を越えて移動する** 

ゲートウェイは、確立済みの接続 (Direct Connect や VPN など) 経由でクラウド境界を越えてオンプレミスネットワークにパケットを転送します。

 **5. オンプレミスネットワークでの受信** 

パケットは、ハイブリッドノードが配置されているサブネット宛てのトラフィックを処理するローカルオンプレミスルーターに到達します。

 **6. 最後の配信** 

ローカルルーターは、宛先 IP (`10.80.0.2`) アドレスが自身に直接接続されているネットワークに属しているかどうかを識別して、ターゲットのハイブリッドノードに直接パケットを転送し、そこで `kubelet` がリクエストを受信して処理します。

### 応答
<a name="_response_2"></a>

ハイブリッドノードの `kubelet` は、リクエストを処理してレスポンスを返します。レスポンスは、同じパスを逆方向にたどります。

```
+-----------------+---------------------+-----------------+
| IP Header       | TCP Header          | Payload         |
| Src: 10.80.0.2  | Src: 10250          |                 |
| Dst: 10.0.0.132 | Dst: 67493          |                 |
+-----------------+---------------------+-----------------+
```

 **6. `kubelet` レスポンスを送信する** 

ハイブリッドノード (`10.80.0.2`) 上の `kubelet` は、送信元の IP を宛先としてレスポンスパケットを作成します。その宛先はローカルネットワークに属していないため、パケットはホストのデフォルトゲートウェイ、つまりローカルルーターに送信されます。

 **5. ローカルルーターのルーティング** 

ルーターは、宛先 IP (`10.0.0.132`) が `10.0.0.0/16` に属していると判断します。ここには、AWS に接続しているゲートウェイを指すルートがあります。

 **4. 境界を越えて戻る** 

パケットは、同じオンプレミスを通って VPC 接続 (Direct Connect や VPN など) まで戻り、クラウド境界を逆方向に横断します。

 **3. VPC でのルーティング** 

パケットが VPC に到達すると、ルートテーブルは宛先 IP が VPC CIDR に属しているかどうかを識別します。パケットは VPC 内にルーティングされます。

 **2. VPC ネットワークでの配信** 

VPC ネットワーキングレイヤーは、EKS コントロールプレーン ENI (`10.0.0.132`) を備えたサブネットにパケットを転送します。

 **1. ENI での受信** 

パケットは、Kubernetes API サーバーにアタッチされている EKS コントロールプレーン ENI に到達します。これでラウンドトリップは完了です。

## ハイブリッドノードで実行されているポッドから EKS コントロールプレーンまでのフロー
<a name="hybrid-nodes-concepts-traffic-flows-pods-to-cp"></a>

![\[ハイブリッドノードで実行されているポッドから EKS コントロールプレーンまでのフロー\]](http://docs.aws.amazon.com/ja_jp/eks/latest/userguide/images/hybrid-nodes-pod-to-cp.png)


### CNI NAT なし
<a name="_without_cni_nat"></a>

### リクエスト
<a name="_request_3"></a>

ポッドは一般に、`kubernetes` サービスを介して Kubernetes API サーバーと対話します。サービス IP がクラスターのサービス CIDR の最初の IP となります。この規約により、CoreDNS が使用可能になる前に稼働する必要があるポッドが API サーバー (例えば、CNI) に到達できるようになります。リクエストは、サービス IP を宛先としてポッドを出ていきます。例えば、サービス CIDR が `172.16.0.0/16` である場合、サービス IP は `172.16.0.1` になります。

 **1. ポッドがリクエストを開始する** 

ポッドは、ランダムな送信元ポートから API サーバーポート (443) 上の `kubernetes` サービス IP (`172.16.0.1`) にリクエストを送信します。パケットは以下のようになります。

```
+-----------------+---------------------+-----------------+
| IP Header       | TCP Header          | Payload         |
| Src: 10.85.1.56 | Src: 67493 (random) |                 |
| Dst: 172.16.0.1 | Dst: 443            |                 |
+-----------------+---------------------+-----------------+
```

 **2. CNI での処理** 

CNI は、宛先 IP が自身の管理するポッド CIDR に属していないことを検出します。**送信 NAT が無効になっている**ため、CNI はパケットを変更せずにホストネットワークスタックに渡します。

 **3. ノードネットワークでの処理** 

パケットはノードのネットワークスタックに入り、そこで `netfilter` フックが kube-proxy によって設定された `iptables` ルールをトリガーします。以下の順序でルールがいくつか適用されます。

1. パケットはまず `KUBE-SERVICES` チェーンをヒットします。ここには、各サービスの ClusterIP とポートに対応するルールが含まれています。

1. その対応するルールは、`kubernetes` サービスの `KUBE-SVC-XXX` チェーンにジャンプします (`172.16.0.1:443` 宛てのパケット)。ここには、ロードバランシングルールが含まれています。

1. ロードバランシングルールは、コントロールプレーン ENI IP (`10.0.0.132` または `10.0.1.23`) 用に `KUBE-SEP-XXX` チェーンのいずれかをランダムに選択します。

1. 選択した `KUBE-SEP-XXX` チェーンには実際のルールがあり、それにより宛先 IP はサービス IP から選択されている IP に変更されます。これは、Destination Network Address Translation (宛先ネットワークアドレス変換、DNAT) と呼ばれます。

選択されている EKS コントロールプレーン ENI の IP を `10.0.0.132` とした場合、これらのルールが適用されると、パケットは以下のようになります。

```
+-----------------+---------------------+-----------------+
| IP Header       | TCP Header          | Payload         |
| Src: 10.85.1.56 | Src: 67493 (random) |                 |
| Dst: 10.0.0.132 | Dst: 443            |                 |
+-----------------+---------------------+-----------------+
```

宛先 IP がローカルネットワーク内にないため、ノードはパケットをデフォルトゲートウェイに転送します。

 **4. ローカルルーターのルーティング** 

ローカルルーターは、宛先 IP (`10.0.0.132`) が VPC CIDR (`10.0.0.0/16`) に属していると判断して、AWS に接続しているゲートウェイに転送します。

 **5. 境界を越えて移動する** 

パケットは、確立済みの接続 (Direct Connect や VPN など) 経由でクラウド境界を越えて VPC に移動します。

 **6. VPC ネットワークでの配信** 

VPC ネットワーキングレイヤーは、EKS コントロールプレーン ENI (`10.0.0.132`) が存在する適切なサブネットにパケットをルーティングします。

 **7. ENI での受信** 

パケットは、Kubernetes API サーバーにアタッチされている EKS コントロールプレーン ENI に到達します。

### 応答
<a name="_response_3"></a>

EKS コントロールプレーンは、リクエストを処理してポッドにレスポンスを返します。

 **7. API サーバーがレスポンスを送信する** 

EKS Kubernetes API サーバーは、送信元の IP を宛先としてレスポンスパケットを作成します。パケットは以下のようになります。

```
+-----------------+---------------------+-----------------+
| IP Header       | TCP Header          | Payload         |
| Src: 10.0.0.132 | Src: 443            |                 |
| Dst: 10.85.1.56 | Dst: 67493          |                 |
+-----------------+---------------------+-----------------+
```

宛先 IP が設定済みのリモートポッド CIDR (`10.85.0.0/16`) に属しているため、パケットはサブネットのルーターを次のホップとして VPC 内の ENI 経由で送信されます。

 **6. VPC でのルーティング** 

VPC ルートテーブルにはリモートポッド CIDR (`10.85.0.0/16`) のエントリがあるため、このトラフィックは VPC-to-onprem ゲートウェイ宛てに送信されます。

 **5. 境界を越えて移動する** 

ゲートウェイは、確立済みの接続 (Direct Connect や VPN など) 経由でクラウド境界を越えてオンプレミスネットワークにパケットを転送します。

 **4. オンプレミスネットワークでの受信** 

パケットは、ローカルオンプレミスルーターに到達します。

 **3. ノードへの配信** 

ルーターのテーブルには `10.80.0.2` を次のホップとした `10.85.1.0/24` のエントリがあるため、パケットはノードに配信されます。

 **2. ノードネットワークでの処理** 

パケットがノードのネットワークスタックによって処理されると、`conntrack` (`netfilter` の一部) はポッドが最初に確立した接続とパケットを照合します。DNAT が最初に適用されたため、`conntrack` はソース IP を EKS コントロールプレーン ENI の IP から `kubernetes` サービス IP に書き換えることで DNAT を元に戻します。

```
+-----------------+---------------------+-----------------+
| IP Header       | TCP Header          | Payload         |
| Src: 172.16.0.1 | Src: 443            |                 |
| Dst: 10.85.1.56 | Dst: 67493          |                 |
+-----------------+---------------------+-----------------+
```

 **1. CNI での処理** 

CNI は、宛先 IP が自身のネットワーク内のポッドに属しているかどうかを識別して、適切なポッドネットワーク名前空間にパケットを配信します。

このフローは、なぜリモートポッド CIDR を VPC から各ポッドをホストする特定のノードに至るまで正しくルーティングできなければならないかを示しています。戻りパス全体は、クラウドとオンプレミスの両方のネットワーク全体にわたってポッド IP が適切にルーティングされるかどうかによって異なります。

### CNI NAT あり
<a name="_with_cni_nat"></a>

このフローは、*CNI NAT がない*ものと非常によく似ていますが、重要な違いが 1 つあります。CNI は、パケットに送信元 NAT (SNAT) を適用してから、ノードのネットワークスタックにパケットを送信します。これにより、パケットの送信元 IP がノードの IP に変更されるため、追加でルーティングを設定することなく、ノードにパケットをルーティングできます。

### リクエスト
<a name="_request_4"></a>

 **1. ポッドがリクエストを開始する** 

ポッドは、ランダムな送信元ポートから EKS Kubernetes API サーバーポート (443) 上の `kubernetes` サービス IP (`172.16.0.1`) にリクエストを送信します。パケットは以下のようになります。

```
+-----------------+---------------------+-----------------+
| IP Header       | TCP Header          | Payload         |
| Src: 10.85.1.56 | Src: 67493 (random) |                 |
| Dst: 172.16.0.1 | Dst: 443            |                 |
+-----------------+---------------------+-----------------+
```

 **2. CNI での処理** 

CNI は、宛先 IP が自身の管理するポッド CIDR に属していないことを検出します。**送信 NAT が有効になっている**ため、CNI は SNAT をパケットに適用して送信元 IP をノードの IP に変更してから、パケットをノードのネットワークスタックに渡します。

```
+-----------------+---------------------+-----------------+
| IP Header       | TCP Header          | Payload         |
| Src: 10.80.0.2  | Src: 67493 (random) |                 |
| Dst: 172.16.0.1 | Dst: 443            |                 |
+-----------------+---------------------+-----------------+
```

注: この例ではわかりやすくするために CNI と `iptables` をそれぞれ別のブロックに分けていますが、実際には `iptables` を使用して NAT を適用する CNI もあります。

 **3. ノードネットワークでの処理** 

ここでは、`kube-proxy` によって設定された `iptables` ルールが前の例と同じように動作して、パケットを EKS コントロールプレーン ENI のいずれかに負荷分散します。これでパケットは以下のようになります。

```
+-----------------+---------------------+-----------------+
| IP Header       | TCP Header          | Payload         |
| Src: 10.80.0.2  | Src: 67493 (random) |                 |
| Dst: 10.0.0.132 | Dst: 443            |                 |
+-----------------+---------------------+-----------------+
```

宛先 IP がローカルネットワーク内にないため、ノードはパケットをデフォルトゲートウェイに転送します。

 **4. ローカルルーターのルーティング** 

ローカルルーターは、宛先 IP (`10.0.0.132`) が VPC CIDR (`10.0.0.0/16`) に属していると判断して、AWS に接続しているゲートウェイに転送します。

 **5. 境界を越えて移動する** 

パケットは、確立済みの接続 (Direct Connect や VPN など) 経由でクラウド境界を越えて VPC に移動します。

 **6. VPC ネットワークでの配信** 

VPC ネットワーキングレイヤーは、EKS コントロールプレーン ENI (`10.0.0.132`) が存在する適切なサブネットにパケットをルーティングします。

 **7. ENI での受信** 

パケットは、Kubernetes API サーバーにアタッチされている EKS コントロールプレーン ENI に到達します。

### 応答
<a name="_response_4"></a>

EKS コントロールプレーンは、リクエストを処理してポッドにレスポンスを返します。

 **7. API サーバーがレスポンスを送信する** 

EKS Kubernetes API サーバーは、送信元の IP を宛先としてレスポンスパケットを作成します。パケットは以下のようになります。

```
+-----------------+---------------------+-----------------+
| IP Header       | TCP Header          | Payload         |
| Src: 10.0.0.132 | Src: 443            |                 |
| Dst: 10.80.0.2  | Dst: 67493          |                 |
+-----------------+---------------------+-----------------+
```

宛先 IP が設定済みのリモートノード CIDR (`10.80.0.0/16`) に属しているため、パケットはサブネットのルーターを次のホップとして VPC 内の ENI 経由で送信されます。

 **6. VPC でのルーティング** 

VPC ルートテーブルにはリモートノード CIDR (`10.80.0.0/16`) のエントリがあるため、このトラフィックは VPC-to-onprem ゲートウェイ宛てに送信されます。

 **5. 境界を越えて移動する** 

ゲートウェイは、確立済みの接続 (Direct Connect や VPN など) 経由でクラウド境界を越えてオンプレミスネットワークにパケットを転送します。

 **4. オンプレミスネットワークでの受信** 

パケットは、ローカルオンプレミスルーターに到達します。

 **3. ノードへの配信** 

ローカルルーターは、宛先 IP (`10.80.0.2`) アドレスが自身に直接接続されているネットワークに属しているかどうかを識別して、ターゲットのハイブリッドノードに直接パケットを転送します。

 **2. ノードネットワークでの処理** 

パケットがノードのネットワークスタックによって処理されると、`conntrack` (`netfilter` の一部) はパケットをポッドが最初に確立した接続と照合します。元々 DNAT が適用されていたため、送信元 IP を EKS コントロールプレーン ENI の IP から `kubernetes` サービス IP に書き換えることで元に戻します。

```
+-----------------+---------------------+-----------------+
| IP Header       | TCP Header          | Payload         |
| Src: 172.16.0.1 | Src: 443            |                 |
| Dst: 10.80.0.2  | Dst: 67493          |                 |
+-----------------+---------------------+-----------------+
```

 **1. CNI での処理** 

CNI は、このパケットが以前に SNAT が適用された接続に属しているかどうかを識別します。これにより、SNAT が逆方向に適用されるため、宛先 IP がポッドの IP に戻ります。

```
+-----------------+---------------------+-----------------+
| IP Header       | TCP Header          | Payload         |
| Src: 172.16.0.1 | Src: 443            |                 |
| Dst: 10.85.1.56 | Dst: 67493          |                 |
+-----------------+---------------------+-----------------+
```

CNI は、宛先 IP が自身のネットワーク内のポッドに属していることを検出して、適切なポッドネットワーク名前空間にパケットを配信します。

このフローは、CNI NAT の適用により、追加でポッド CIDR のルーティングを行うことなくパケットをノードにルーティングできるようにすることで、設定をどのように簡素化できるかを示しています。

## EKS コントロールプレーンからハイブリッドノードで実行されているポッドまでのフロー (ウェブフック)
<a name="hybrid-nodes-concepts-traffic-flows-cp-to-pod"></a>

![\[EKS コントロールプレーンからハイブリッドノードで実行されているポッドまでのフロー\]](http://docs.aws.amazon.com/ja_jp/eks/latest/userguide/images/hybrid-nodes-cp-to-pod.png)


このトラフィックパターンはウェブフックで最もよく見られるものであり、ウェブフックではハイブリッドノード上のポッドで実行されているウェブフックサーバーへの接続を EKS コントロールプレーンが直接開始する必要があります。例えば、アドミッションウェブフックを検証して変更するといった場合、このウェブフックはリソースの検証と変更のプロセス中に API サーバーによって呼び出されます。

### リクエスト
<a name="_request_5"></a>

 **1. EKS Kubernetes API サーバーがリクエストを開始する** 

クラスターに設定されたウェブフックが関連する API オペレーションによってトリガーされた場合、EKS Kubernetes API サーバーはそのウェブフックサーバーポッドに直接接続する必要があります。API サーバーはまず、そのウェブフックに関連付けられているサービスリソースまたはエンドポイントリソースでポッドの IP アドレスを検索します。

IP が `10.85.1.23` のハイブリッドノード上でウェブフックポッドが実行されている場合、EKS Kubernetes API サーバーはウェブフックエンドポイントへの HTTPS リクエストを作成します。`10.85.1.23` という宛先 IP は設定済みのリモートポッド CIDR (`10.85.0.0/16`) に属しているため、初期パケットは VPC の EKS コントロールプレーン ENI を介して送信されます。パケットは以下のようになります。

```
+-----------------+---------------------+-----------------+
| IP Header       | TCP Header          | Payload         |
| Src: 10.0.0.132 | Src: 41892 (random) |                 |
| Dst: 10.85.1.23 | Dst: 8443           |                 |
+-----------------+---------------------+-----------------+
```

 **2. VPC ネットワークでの処理** 

パケットは、EKS コントロールプレーン ENI を出て、サブネットのルーターを次のホップとする VPC ネットワーキングレイヤーに入ります。

 **3. VPC ルートテーブルのルックアップ** 

EKS コントロールプレーン ENI が含まれているサブネット用の VPC ルートテーブルには、リモートポッド CIDR (`10.85.0.0/16`) に固有のルートが登録されています。このルーティングルールにより、パケットは VPC-to-onprem ゲートウェイ (例えば、Direct Connect や VPN 接続の場合は仮想プライベートゲートウェイ) 宛てに送信されます。

```
Destination     Target
10.0.0.0/16     local
10.85.0.0/16    vgw-id (VPC-to-onprem gateway)
```

 **4. 境界を越えて移動する** 

ゲートウェイは、確立済みの接続 (Direct Connect や VPN など) 経由でクラウド境界を越えてオンプレミスネットワークにパケットを転送します。パケットがこの接続を通過するとき、パケットの送信元 IP アドレスと宛先 IP アドレスは元のまま維持されます。

 **5. オンプレミスネットワークでの受信** 

パケットは、ローカルオンプレミスルーターに到達します。ルーターは、自身のルーティングテーブルに問い合わせて、10.85.1.23 アドレスに到達する方法を決定します。そのためにオンプレミスネットワークには、適切なハイブリッドノード宛てにトラフィックを送信するポッド CIDR へのルートが必要です。

この例の場合、ルーターのルートテーブルには IP が `10.80.0.2` のハイブリッドノード経由で `10.85.1.0/24` サブネットに到達できることを示すエントリが登録されています。

```
Destination     Next Hop
10.85.1.0/24    10.80.0.2
```

 **6. ノードへの配信** 

ルーターは、ルーティングテーブルのエントリに基づいて、パケットをハイブリッドノード (`10.80.0.2`) に転送します。ノードに到達したとき、パケットは EKS Kubernetes API サーバーから送信されたときと同じままで、宛先 IP は依然としてポッドの IP です。

 **7. CNI での処理** 

ノードのネットワークスタックは、パケットを受信し、宛先 IP がノード自体の IP でないことを確認して、さらに処理するために CNI に渡します。CNI は、宛先 IP がこのノードでローカルに実行されているポッドに属しているかどうかを識別し、適切な仮想インターフェイス経由で適切なポッドにパケットを転送します。

```
Original packet -> node routing -> CNI -> Pod's network namespace
```

ポッド内のウェブフックサーバーは、リクエストを受信して処理します。

### 応答
<a name="_response_5"></a>

ウェブフックポッドは、リクエストを処理してレスポンスを返します。レスポンスは、同じパスを逆方向にたどります。

 **7. ポッドがレスポンスを送信する** 

ウェブフックポッドは、自身の IP を送信元とし、元のリクエスタ (EKS コントロールプレーン ENI) を宛先として、レスポンスパケットを作成します。

```
+-----------------+---------------------+-----------------+
| IP Header       | TCP Header          | Payload         |
| Src: 10.85.1.23 | Src: 8443           |                 |
| Dst: 10.0.0.132 | Dst: 41892          |                 |
+-----------------+---------------------+-----------------+
```

CNI は、このパケットが外部ネットワーク (ローカルポッドではない) に送信され、パケットが、元のソース IP を保持したままノードのネットワークスタックに渡されたことを確認します。

 **6. ノードネットワークでの処理** 

ノードは、宛先 IP (`10.0.0.132`) がローカルネットワーク内にないと判断して、自身のデフォルトゲートウェイ (ローカルルーター) にパケットを転送します。

 **5. ローカルルーターのルーティング** 

ローカルルーターは、自身のルーティングテーブルに問い合わせて、宛先 IP (`10.0.0.132`) が VPC CIDR (`10.0.0.0/16`) に属していると判断します。次に、AWS に接続しているゲートウェイにパケットを転送します。

 **4. 境界を越えて移動する** 

パケットは、同じオンプレミスを通って VPC 接続まで戻り、クラウド境界を逆方向に横断します。

 **3. VPC でのルーティング** 

パケットが VPC に到達すると、ルートテーブルは宛先 IP が VPC 内のサブネットに属しているかどうかを識別します。それに応じて、パケットは VPC 内にルーティングされます。

 **2. と 1. EKS コントロールプレーン ENI での受信** 

パケットは、Kubernetes API サーバーにアタッチされている ENI に到達します。これでラウンドトリップは完了です。API サーバーは、ウェブフックレスポンスを受信し、このレスポンスに基づいて元の API リクエストの処理を続行します。

このトラフィックフローは、なぜリモートポッド CIDR を正しく設定してルーティングする必要があるかを示しています。
+ VPC には、オンプレミスゲートウェイを指すリモートポッド CIDR のルートが登録されている必要があります。
+ オンプレミスネットワークには、そうしたポッドをホストしている特定のノード宛てにトラフィックを送信するポッド CIDR のルートが登録されている必要があります。
+ このルーティング設定がないと、ハイブリッドノード上のポッドで実行されているウェブフックやその他の同じようなサービスに EKS コントロールプレーンから到達できなくなります。

## ハイブリッドノードで実行されているポッド間
<a name="hybrid-nodes-concepts-traffic-flows-pod-to-pod"></a>

![\[ハイブリッドノードで実行されているポッド間\]](http://docs.aws.amazon.com/ja_jp/eks/latest/userguide/images/hybrid-nodes-pod-to-pod.png)


このセクションでは、異なるハイブリッドノード上で実行されているポッド同士がどのように通信しているかについて説明します。この例では、CNI がカプセル化に VXLAN を使用しているものとします。これは、Cilium や Calico などの CNI でよく見られることです。プロセス全体は、Geneve や IP-in-IP など、他のカプセル化プロトコルに似ています。

### リクエスト
<a name="_request_6"></a>

 **1. ポッド A が通信を開始する** 

ノード 1 上のポッド A (`10.85.1.56`) が、ノード 2 上のポッド B (`10.85.2.67`) にトラフィックを送信しようとしています。初期パケットは以下のようになります。

```
+------------------+-----------------+-------------+-----------------+
| Ethernet Header  | IP Header       | TCP/UDP     | Payload         |
| Src: Pod A MAC   | Src: 10.85.1.56 | Src: 43721  |                 |
| Dst: Gateway MAC | Dst: 10.85.2.67 | Dst: 8080   |                 |
+------------------+-----------------+-------------+-----------------+
```

 **2. CNI がパケットをインターセプトして処理する** 

ポッド A のパケットが自身のネットワーク名前空間を出ると、CNI がそのパケットをインターセプトします。CNI は自身のルーティングテーブルに問い合わせて、宛先 IP (`10.85.2.67`) はポッド CIDR に属している、この IP はローカルノードではなくノード 2 (`10.80.0.3`) に属している、パケットは VXLAN でカプセル化する必要がある、と判断します。

カプセル化するという判断は重要です。基盤となる物理ネットワークが、ノード IP 間のトラフィックをルーティングする方法は認識しているものの、ポッド CIDR を直接ルーティングする方法は認識していないためです。

CNI は、元のパケット全体を VXLAN フレーム内にカプセル化します。これにより、「パケット内のパケット」が次のような新しいヘッダー付きで効果的に作成されます。

```
+-----------------+----------------+--------------+------------+---------------------------+
| Outer Ethernet  | Outer IP       | Outer UDP    | VXLAN      | Original Pod-to-Pod       |
| Src: Node1 MAC  | Src: 10.80.0.2 | Src: Random  | VNI: 42    | Packet (unchanged         |
| Dst: Router MAC | Dst: 10.80.0.3 | Dst: 8472    |            | from above)               |
+-----------------+----------------+--------------+------------+---------------------------+
```

このカプセル化の重要なポイントは、外側のパケットにはノード 1 (`10.80.0.2`) からノード 2 (`10.80.0.3`) までのアドレスが指定されること、UDP ポート `8472` は Cilium がデフォルトで使用する VXLAN ポートであること、VXLAN Network Identifier (VNI) はこのパケットが属するオーバーレイネットワークを識別すること、元のパケット (ポッド A の IP を送信元とし、ポッド B の IP を宛先とする) 全体が内側でもそのまま保持されることです。

これで、カプセル化されたパケットは、ノード 1 の通常のネットワークスタックに入って、他のパケットと同じ方法で処理されます。

1.  **ノードネットワークでの処理**: ノード 1 のネットワークスタックは、宛先 (`10.80.0.3`) に基づいてパケットをルーティングします。

1.  **ローカルネットワークでの配信**:
   + 両方のノードが同じレイヤー 2 ネットワークにある場合、パケットはノード 2 に直接送信されます。
   + それぞれ別のサブネットにある場合、パケットはまずローカルルーターに転送されます。

1.  **ルーターでの処理**: ルーターは、自身のルーティングテーブルに基づいてパケットを転送して、ノード 2 に配信します。

 **3. 受信側のノードでの処理** 

カプセル化されたパケットがノード 2 (`10.80.0.3`) に到達すると、次のようになります。

1. ノードのネットワークスタックは、パケットを受信し、VXLAN パケット (UDP ポート `4789`) であると識別します。

1. パケットは、さらに処理するために CNI の VXLAN インターフェイスに渡されます。

 **4. VXLAN カプセル化解除** 

ノード 2 上の CNI は、次のように VXLAN パケットを処理します。

1. 外側のヘッダー (イーサネット、IP、UDP、VXLAN) を取り除きます。

1. 内側の元のパケットを抽出します。

1. これで、パケットは元の形式に戻ります。

```
+------------------+-----------------+-------------+-----------------+
| Ethernet Header  | IP Header       | TCP/UDP     | Payload         |
| Src: Pod A MAC   | Src: 10.85.1.56 | Src: 43721  |                 |
| Dst: Gateway MAC | Dst: 10.85.2.67 | Dst: 8080   |                 |
+------------------+-----------------+-------------+-----------------+
```

ノード 2 上の CNI は、宛先 IP (`10.85.2.67`) を確認して、次の処理を行います。

1. この IP がローカルポッドに属しているかどうかを識別します。

1. 適切な仮想インターフェイス経由でパケットをルーティングします。

1. ポッド B のネットワーク名前空間にパケットを配信します。

### 応答
<a name="_response_6"></a>

ポッド B がポッド A に応答するときは、プロセス全体が逆方向になります。

1. ポッド B がポッド A (`10.85.1.56`) にパケットを送信します。

1. ノード 2 の CNI は、そのパケットを VXLAN でカプセル化し、宛先をノード 1 (`10.80.0.2`) に設定します。

1. カプセル化されたパケットがノード 1 に配信されます。

1. ノード 1 の CNI は、パケットをカプセル化解除し、元のレスポンスをポッド A に配信します。

## クラウドノード上のポッドからハイブリッドノード上のポッドまでのフロー (東西トラフィック)
<a name="hybrid-nodes-concepts-traffic-flows-east-west"></a>

![\[クラウドノード上のポッドからハイブリッドノード上のポッドまでのフロー\]](http://docs.aws.amazon.com/ja_jp/eks/latest/userguide/images/hybrid-nodes-east-west.png)


### リクエスト
<a name="_request_7"></a>

 **1. ポッド A が通信を開始する** 

EC2 ノード上のポッド A (`10.0.0.56`) がハイブリッドノード上のポッド B (`10.85.1.56`) にトラフィックを送信しようとしています。初期パケットは以下のようになります。

```
+-----------------+---------------------+-----------------+
| IP Header       | TCP Header          | Payload         |
| Src: 10.0.0.56  | Src: 52390 (random) |                 |
| Dst: 10.85.1.56 | Dst: 8080           |                 |
+-----------------+---------------------+-----------------+
```

VPC CNI では、ポッド A に VPC CIDR からの IP があるため、ポッド A は EC2 インスタンス上の ENI に直接アタッチされます。ポッドのネットワーク名前空間は VPC ネットワークに接続されているため、パケットは VPC ルーティングインフラストラクチャに直接入ります。

 **2. VPC でのルーティング** 

VPC ルートテーブルにはリモートポッド CIDR (`10.85.0.0/16`) に固有のルートが登録されているため、このトラフィックは VPC-to-onprem ゲートウェイ宛てに送信されます。

```
Destination     Target
10.0.0.0/16     local
10.85.0.0/16    vgw-id (VPC-to-onprem gateway)
```

このルーティングルールに基づいて、パケットはオンプレミスネットワークに接続しているゲートウェイに向けて送信されます。

 **3. 境界を越えて移動する** 

ゲートウェイは、確立済みの接続 (Direct Connect や VPN など) 経由でクラウド境界を越えてオンプレミスネットワークにパケットを転送します。このトランジットを全体を通して、パケットの送信元 IP アドレスと宛先 IP アドレスは元のまま維持されます。

 **4. オンプレミスネットワークでの受信** 

パケットは、ローカルオンプレミスルーターに到達します。ルーターは、自身のルーティングテーブルに問い合わせて、10.85.1.56 アドレスに到達するための次のホップを決定します。オンプレミスルーターには、適切なハイブリッドノード宛てにトラフィックを送信するポッド CIDR へのルートが必要です。

ルーターのルートテーブルには IP `10.80.0.2` のハイブリッドノード経由で `10.85.1.0/24` サブネットに到達できることを示すエントリが登録されています。

```
Destination     Next Hop
10.85.1.0/24    10.80.0.2
```

 **5. ノードネットワークでの処理** 

ルーターは、パケットをハイブリッドノード (`10.80.0.2`) に転送します。パケットがノードに到達したとき、パケットのポッド A の IP は送信元のまま、ポッド B の IP は宛先のままです。

 **6. CNI での処理** 

ノードのネットワークスタックは、パケットを受信し、宛先 IP が自身のものでないことを確認して、さらに処理するために CNI に渡します。CNI は、宛先 IP がこのノードでローカルに実行されているポッドに属しているかどうかを識別し、適切な仮想インターフェイス経由で適切なポッドにパケットを転送します。

```
Original packet -> node routing -> CNI -> Pod B's network namespace
```

ポッド B は、パケットを受信し、必要に応じて処理します。

### 応答
<a name="_response_7"></a>

 **6. ポッド B がレスポンスを送信する** 

ポッド B は、自身の IP を送信元、ポッド A の IP を宛先として、レスポンスパケットを作成します。

```
+-----------------+---------------------+-----------------+
| IP Header       | TCP Header          | Payload         |
| Src: 10.85.1.56 | Src: 8080           |                 |
| Dst: 10.0.0.56  | Dst: 52390          |                 |
+-----------------+---------------------+-----------------+
```

CNI は、このパケットが外部ネットワーク宛てかどうかを識別して、ノードのネットワークスタックに渡します。

 **5. ノードネットワークでの処理** 

ノードは、宛先 IP (`10.0.0.56`) がローカルネットワークに属していないと判断し、自身のデフォルトゲートウェイ (ローカルルーター) にパケットを転送します。

 **4. ローカルルーターのルーティング** 

ローカルルーターは、自身のルーティングテーブルに問い合わせて、宛先 IP (`10.0.0.56`) が VPC CIDR (`10.0.0.0/16`) に属していると判断します。次に、AWS に接続しているゲートウェイにパケットを転送します。

 **3. 境界を越えて移動する** 

パケットは、同じオンプレミスを通って VPC 接続まで戻り、クラウド境界を逆方向に横断します。

 **2. VPC でのルーティング** 

パケットが VPC に到達すると、ルーティングシステムは宛先 IP が VPC 内のサブネットに属しているかどうかを識別します。パケットは、ポッド A をホストしている EC2 インスタンスに向けて、VPC ネットワーク経由でルーティングされます。

 **1. ポッド A がレスポンスを受信する** 

パケットは、EC2 インスタンスに到達し、そこにアタッチされている ENI 経由でポッド A に直接配信されます。VPC CNI は VPC 内のポッドにオーバーレイネットワーキングを使用しないため、別途カプセル化解除は必要なく、パケットは元のヘッダーのまま届きます。

この東西トラフィックフローは、なぜリモートポッド CIDR を正しく設定して、両方向からルーティング可能にする必要があるかを示しています。
+ VPC には、オンプレミスゲートウェイを指すリモートポッド CIDR のルートが登録されている必要があります。
+ オンプレミスネットワークには、そうしたポッドをホストしている特定のノード宛てにトラフィックを送信するルートがポッド CIDR で登録されている必要があります。