

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# コスト最適化 - ネットワーキング
<a name="cost-opt-networking"></a>

高可用性 (HA) のシステム設計は、耐障害性と耐障害性を実現するためのベストプラクティスです。実際には、ワークロードと基盤となるインフラストラクチャを特定の AWS リージョンの複数のアベイラビリティーゾーン (AZs) に分散することを意味します。Amazon EKS 環境にこれらの特性があることを確認することで、システムの全体的な信頼性が向上します。これと組み合わせて、EKS 環境は、さまざまなコンストラクト (VPCs など）、コンポーネント (ELBs など）、統合 (ECR やその他のコンテナレジストリなど) で構成される可能性があります。

高可用性システムとその他のユースケース固有のコンポーネントの組み合わせは、データの転送と処理方法に大きな役割を果たします。これにより、データ転送と処理によって発生するコストにも影響します。

以下に詳述するプラクティスは、さまざまなドメインやユースケースで費用対効果を実現するために、EKS 環境を設計および最適化するのに役立ちます。

## ポッド間の通信
<a name="_pod_to_pod_communication"></a>

設定によっては、Pod 間のネットワーク通信とデータ転送が Amazon EKS ワークロードの実行にかかる全体的なコストに大きな影響を与える可能性があります。このセクションでは、高可用性 (HA) アーキテクチャ、アプリケーションのパフォーマンス、耐障害性を考慮しながら、ポッド間通信に関連するコストを削減するためのさまざまな概念とアプローチについて説明します。

### アベイラビリティーゾーンへのトラフィックの制限
<a name="_restricting_traffic_to_an_availability_zone"></a>

Kubernetes プロジェクトは、障害ドメイン間のワークロード分散やトポロジ対応ボリュームプロビジョナーなどの機能を有効にするために、ノードに割り当てられた kubernetes.io/hostname、topology.kubernetes.io/region、topology.kubernetes.io/zone などのラベルを含むトポロジ対応コンストラクトの開発を早期に開始しました。Kubernetes 1.17 を卒業したことで、ラベルは Pod 間通信のトポロジ対応ルーティング機能を有効にするためにも活用されました。

以下は、コストを削減し、レイテンシーを最小限に抑えるために、EKS クラスター内のポッド間のクロス AZ トラフィックの量を制御する方法に関するいくつかの戦略です。

 *クラスター内のポッド間のクロス AZ トラフィックの量 (バイト単位で転送されるデータ量など) を詳細に可視化する場合は、[この投稿を参照してください](https://aws.amazon.com/blogs/containers/getting-visibility-into-your-amazon-eks-cross-az-pod-to-pod-network-bytes/)。*

![トポロジ対応ルーティング](http://docs.aws.amazon.com/ja_jp/eks/latest/best-practices/images/topo_aware_routing.png)


上記の図に示すように、サービスは Pod 宛てのトラフィックを受信する安定したネットワーク抽象化レイヤーです。サービスが作成されると、複数の EndpointSlices が作成されます。各 EndpointSlice には、Pod アドレスのサブセットと、それらが実行されているノード、および追加のトポロジ情報を含むエンドポイントのリストがあります。すべてのノードで実行されるデーモンセットである Amazon VPC CNI を使用する場合、 はネットワークルールを維持し、Pod 通信とサービス検出を有効にします (代替 eBPF ベースの CNIs は kube-proxy を使用しない場合がありますが、同等の動作を提供します）。内部ルーティングのロールは満たされますが、作成された EndpointSlices から消費されるものに基づいて行われます。

EKS では、kube-proxy は、ノードまたは AZ 配置に関係なく、クラスター内のすべてのポッドへのトラフィック分散に iptables NAT ルール (または [IPVS](https://docs.aws.amazon.com/eks/latest/best-practices/ipvs.html)、[NFTables](https://kubernetes.io/blog/2025/02/28/nftables-kube-proxy/)) を主に使用します。このデフォルトのディストリビューションは、クロス AZ トラフィックルーティングにつながる可能性があり、大規模なデプロイでは、機密性の高いアプリケーションのレイテンシーが増加し、AZ 間のデータ転送料金が発生する可能性があります。

 **トポロジ対応ルーティングの使用 (以前はトポロジ対応ヒントと呼ばれていました)** 

[https://kubernetes.io/docs/concepts/services-networking/topology-aware-routing/](https://kubernetes.io/docs/concepts/services-networking/topology-aware-routing/)を有効にして Kubernetes サービスに実装すると、EndpointSlice コントローラーはクラスターが分散されているさまざまなゾーンにエンドポイントを比例して割り当てます。これらのエンドポイントごとに、EndpointSlice コントローラーはゾーンの*ヒント*も設定します。*ヒントは、エンドポイントがトラフィックを処理するゾーンを*記述します。 `kube-proxy`は、適用される*ヒントに基づいて、ゾーンからエンドポイントにトラフィックをルーティング*します。

次の図は、ヒントを含む EndpointSlices が、ゾーンのオリジンポイントに基づいてどの宛先に移動するか`kube-proxy`がわかるように編成されている方法を示しています。ヒントがない場合、このような割り当てや組織は存在せず、トラフィックは送信元に関係なく異なるゾーンの宛先にプロキシされます。

![エンドポイントスライス](http://docs.aws.amazon.com/ja_jp/eks/latest/best-practices/images/endpoint_slice.png)


場合によっては、EndpointSlice コントローラーは別のゾーンに*ヒント*を適用することがあります。つまり、エンドポイントは別のゾーンから発信されたトラフィックを処理する可能性があります。これは、異なるゾーンのエンドポイント間のトラフィックの均等な分散を維持しようとするためです。

以下は、サービスの*トポロジ対応ルーティング*を有効にする方法に関するコードスニペットです。

```
apiVersion: v1
kind: Service
metadata:
  name: orders-service
  namespace: ecommerce
  annotations:
    service.kubernetes.io/topology-mode: Auto
spec:
  selector:
    app: orders
  type: ClusterIP
  ports:

* protocol: TCP
port: 3003
targetPort: 3003
```

以下のスクリーンショットは、EndpointSlice コントローラーが AZ で実行されているポッドレプリカのエンドポイントにヒントを正常に適用した結果を示しています`eu-west-1a`。

![スライスシェル](http://docs.aws.amazon.com/ja_jp/eks/latest/best-practices/images/slice_shell.png)


**注記**  
トポロジ対応ルーティングはまだベータ版であることに注意してください。この機能は、クラスタートポロジ全体で均等に分散されたワークロードでより予測しやすく機能します。コントローラーは、ゾーン間でエンドポイントを比例的に割り当てますが、ゾーン内のノードリソースのバランスが不均衡になりすぎて過剰なオーバーロードを回避すると、ヒントの割り当てをスキップする可能性があります。したがって、[ポッドトポロジのスプレッド制約などのアプリケーションの可用性を高めるスケジューリング制約](https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/)と組み合わせて使用することを強くお勧めします。また、[Amazon EC2 スポットインスタンス](https://aws.amazon.com/ec2/spot/)を使用する場合など、ゾーン間で容量が変動する場合は、比例分布を計算するときに中断や置換がリアルタイムで検出されないため、ヒントが割り当てられない場合があることに注意してください。

 **トラフィック分散の使用** 

Kubernetes 1.30 で導入され、1.33 で一般公開された[トラフィックディストリビューション](https://kubernetes.io/docs/reference/networking/virtual-ips/#traffic-distribution)は、同じゾーンのトラフィック設定のためにトポロジ対応ルーティングよりも簡単な代替手段を提供します。トポロジ対応ルーティングは、エンドポイントの過負荷を回避するためにトラフィックルーティングにインテリジェントなアプローチを使用しようとしますが、予期しない動作が発生しました。トラフィック分散は、代わりに予測可能性を優先します。PreferClose オプションは、kube-proxy に、EndpointSlice Controller によって設定されたゾーン*ヒント*に基づいて、まず同じゾーンエンドポイントにトラフィックをルーティングするルールを作成するように指示します。同じゾーンエンドポイントが利用できない場合、サービスのクラスターエンドポイント間でトラフィックを分散することにフォールバックします。この機能は、トポロジ対応ルーティングが提供する負荷の均等分散を試みるのではなく、近接性の最適化というトレードオフを受け入れるワークロード向けに設計されています。

以下は、サービスの*トラフィック分散*を有効にする方法に関するコードスニペットです。

```
apiVersion: v1
kind: Service
metadata:
  name: orders-service
  namespace: ecommerce
spec:
  trafficDistribution: PreferClose
  selector:
    app: orders
  type: ClusterIP
  ports:

* protocol: TCP
port: 3003
targetPort: 3003
```

トラフィック分散を有効にすると、一般的な課題として、1 つの AZ 内のエンドポイントが過負荷になることがあります。ほとんどのトラフィックが同じゾーンから発信される場合です。このオーバーロードは重大な問題を引き起こす可能性があります。
+ マルチ AZ 配置を管理する 1 つの Horizontal Pod Autoscaler (HPA) は、異なる AZs。ただし、このアクションは、影響を受けるゾーンで増加した負荷に効果的に対処できません。
+ この状況は、リソースの非効率性につながる可能性があります。Karpenter などのクラスターオートスケーラーがさまざまな AZs 間でポッドのスケールアウトを検出すると、影響を受けていない AZs に追加のノードがプロビジョニングされ、不要なリソースの割り当てが発生する可能性があります。

この課題を克服するには:
+ ゾーンごとに個別のデプロイを作成し、独自の HPAs を使用して互いに独立してスケーリングします。
+ トポロジのスプレッド制約を活用して、クラスター全体のワークロード分散を確保します。これにより、トラフィックの多いゾーンでのエンドポイントの過負荷を防ぐことができます。

 **Autoscaler の使用: 特定の AZ にノードをプロビジョニングする** 

 複数の *AZ にまたがる高可用性環境でワークロードを実行することを強くお勧め*AZs。これにより、特に AZ に問題がある場合に、アプリケーションの信頼性が向上します。ネットワーク関連のコストを削減するために信頼性を犠牲にする場合は、ノードを 1 つの AZ に制限できます。

同じ AZ ですべての Pod を実行するには、同じ AZ でワーカーノードをプロビジョニングするか、同じ AZ で実行されているワーカーノードで Pod をスケジュールします。単一の AZ 内にノードをプロビジョニングするには、[Cluster Autoscaler (CA)](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler) で同じ AZ に属するサブネットを持つノードグループを定義します。[Karpenter では、](https://karpenter.sh/) を使用して、ワーカーノードを作成する AZ `topology.kubernetes.io/zone`を指定します。たとえば、次の Karpenter プロビジョナースニペットは、us-west-2a AZ のノードをプロビジョニングします。

 **Karpenter** 

```
apiVersion: karpenter.sh/v1
kind: Provisioner
metadata:
name: single-az
spec:
  requirements:

* key: "topology.kubernetes.io/zone"`
operator: In
values: ["us-west-2a"]
```

 **クラスターオートスケーラー (CA)** 

```
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
  name: my-ca-cluster
  region: us-east-1
  version: "1.21"
availabilityZones:

* us-east-1a
managedNodeGroups:
* name: managed-nodes
labels:
  role: managed-nodes
instanceType: t3.medium
minSize: 1
maxSize: 10
desiredCapacity: 1
...
```

 **ポッド割り当てとノードアフィニティの使用** 

または、複数の AZs で実行されているワーカーノードがある場合、各ノードには AZ の値 (us-west-2a や us-west-2b など) を含む *[topology.kubernetes.io/zone](http://topology.kubernetes.io/zone%E2%80%9D) * というラベルが付けられます。`nodeSelector` または を使用して`nodeAffinity`、単一の AZ 内のノードにポッドをスケジュールできます。たとえば、次のマニフェストファイルは、AZ us-west-2a で実行されているノード内で Pod をスケジュールします。

```
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: test
spec:
  nodeSelector:
    topology.kubernetes.io/zone: us-west-2a
  containers:

* name: nginx
image: nginx
imagePullPolicy: IfNotPresent
```

### ノードへのトラフィックの制限
<a name="_restricting_traffic_to_a_node"></a>

ゾーンレベルでのトラフィックの制限では不十分な場合があります。コストを削減するだけでなく、頻繁に相互通信を行う特定のアプリケーション間のネットワークレイテンシーを減らすという要件も追加される場合があります。最適なネットワークパフォーマンスを実現し、コストを削減するには、特定のノードへのトラフィックを制限する方法が必要です。例えば、マイクロサービス A は、高可用性 (HA) セットアップであっても、ノード 1 のマイクロサービス B と常に通信する必要があります。ノード 1 のマイクロサービス A がノード 2 のマイクロサービス B と通信すると、特にノード 2 が別の AZ にある場合、この種のアプリケーションに必要なパフォーマンスに悪影響を及ぼす可能性があります。

 **サービス内部トラフィックポリシーの使用** 

Pod ネットワークトラフィックをノードに制限するには、*[サービス内部トラフィックポリシー](https://kubernetes.io/docs/concepts/services-networking/service-traffic-policy/) *を使用できます。デフォルトでは、ワークロードの サービスに送信されるトラフィックは、生成されたさまざまなエンドポイントにランダムに分散されます。したがって、HA アーキテクチャでは、マイクロサービス A からのトラフィックは、異なる AZs 間で特定のノード上のマイクロサービス B のレプリカに移動する可能性があります。ただし、サービスの内部トラフィックポリシーを に設定すると`Local`、トラフィックはトラフィックの送信元のノード上のエンドポイントに制限されます。このポリシーは、ノードローカルエンドポイントの排他的な使用を指示します。つまり、そのワークロードのネットワークトラフィック関連のコストは、ディストリビューションがクラスター全体であった場合よりも低くなります。また、レイテンシーが低くなり、アプリケーションのパフォーマンスが向上します。

**注記**  
この機能は、Kubernetes のトポロジ対応ルーティングと組み合わせることはできません。

![ローカル内部トラフィック](http://docs.aws.amazon.com/ja_jp/eks/latest/best-practices/images/local_traffic.png)


以下は、サービス*の内部トラフィックポリシー*を設定する方法に関するコードスニペットです。

```
apiVersion: v1
kind: Service
metadata:
  name: orders-service
  namespace: ecommerce
spec:
  selector:
    app: orders
  type: ClusterIP
  ports:

* protocol: TCP
port: 3003
targetPort: 3003
  internalTrafficPolicy: Local
```

トラフィックの減少によるアプリケーションからの予期しない動作を回避するには、次のアプローチを検討する必要があります。
+ 通信ポッドごとに十分なレプリカを実行する
+ [トポロジ分散制約を使用してポッドを比較的均等に分散させる](https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/) 
+ 通信ポッド[のコロケーションにポッドアフィニティルール](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity)を使用する

この例では、マイクロサービス A のレプリカが 2 つ、マイクロサービス B のレプリカが 3 つあります。マイクロサービス A のレプリカがノード 1 と 2 の間に分散されていて、マイクロサービス B のレプリカがノード 3 にある場合、`Local`内部トラフィックポリシーのため通信できません。使用可能なノードローカルエンドポイントがない場合、トラフィックはドロップされます。

![node-local_no_peer](http://docs.aws.amazon.com/ja_jp/eks/latest/best-practices/images/no_node_local_1.png)


Microservice B にノード 1 と 2 の 3 つのレプリカのうち 2 つがある場合、ピアアプリケーション間の通信が行われます。ただし、マイクロサービス B の分離されたレプリカには、通信するピアレプリカがありません。

![node-local_with_peer](http://docs.aws.amazon.com/ja_jp/eks/latest/best-practices/images/no_node_local_2.png)


**注記**  
シナリオによっては、上記の図に示されているような分離されたレプリカが目的 (外部受信トラフィックからのリクエストの処理など) を満たしていても、懸念の原因にならない場合があります。

 **トポロジのスプレッド制約によるサービス内部トラフィックポリシーの使用** 

*内部トラフィックポリシー*を*トポロジの分散制約*と組み合わせて使用すると、異なるノードでマイクロサービスを通信するための適切な数のレプリカを確保できます。

```
apiVersion: apps/v1
kind: Deployment
metadata:
  name: express-test
spec:
  replicas: 6
  selector:
    matchLabels:
      app: express-test
  template:
    metadata:
      labels:
        app: express-test
        tier: backend
    spec:
      topologySpreadConstraints:
      - maxSkew: 1
        topologyKey: "topology.kubernetes.io/zone"
        whenUnsatisfiable: ScheduleAnyway
        labelSelector:
          matchLabels:
            app: express-test
```

 **ポッドアフィニティルールでの サービス内部トラフィックポリシーの使用** 

もう 1 つの方法は、サービス内部トラフィックポリシーを使用するときに Pod アフィニティルールを使用することです。Pod アフィニティを使用すると、頻繁に通信するため、スケジューラに影響を与えて特定の Pod をコロケーションできます。特定の Pod に厳密なスケジューリング制約 (`requiredDuringSchedulingIgnoredDuringExecution`) を適用することで、スケジューラがノードに Pod を配置するときの Pod コロケーションの結果が向上します。

```
apiVersion: apps/v1
kind: Deployment
metadata:
  name: graphql
  namespace: ecommerce
  labels:
    app.kubernetes.io/version: "0.1.6"
    ...
    spec:
      serviceAccountName: graphql-service-account
      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - orders
            topologyKey: "kubernetes.io/hostname"
```

## Load Balancerからポッドへの通信
<a name="_load_balancer_to_pod_communication"></a>

EKS ワークロードは通常、EKS クラスター内の関連する Pod にトラフィックを分散するロードバランサーによってフロントされます。アーキテクチャは、内部および/または外部向けロードバランサーで構成される場合があります。アーキテクチャとネットワークトラフィックの設定によっては、ロードバランサーと Pod 間の通信がデータ転送料金に大きな影響を与える可能性があります。

[AWS Load Balancer Controller](https://kubernetes-sigs.github.io/aws-load-balancer-controller) を使用して、ELB リソース (ALB および NLB) の作成を自動的に管理できます。このようなセットアップで発生するデータ転送料金は、ネットワークトラフィックによって取得されるパスによって異なります。AWS Load Balancer Controller は、*インスタンス*モードと *ip* モードの 2 つのネットワークトラフィックモードをサポートしています。

*インスタンスモード*を使用すると、EKS クラスターの各ノードで NodePort が開きます。その後、ロードバランサーはノード間でトラフィックを均等にプロキシします。ノードで送信先 Pod が実行されている場合、データ転送コストは発生しません。ただし、送信先 Pod が別のノードにあり、トラフィックを受信する NodePort とは異なる AZ にある場合、kube-proxy から送信先 Pod への追加のネットワークホップが発生します。このようなシナリオでは、AZ 間のデータ転送料金が発生します。ノード間でトラフィックが均等に分散されるため、kube-proxies から関連する送信先 Pod へのクロスゾーンネットワークトラフィックホップに関連する追加のデータ転送料金が発生する可能性が高くなります。

次の図は、ロードバランサーから NodePort に、その後 から別の AZ の別のノードの宛先 Pod `kube-proxy`に流れるトラフィックのネットワークパスを示しています。これはインスタンス*モード*設定の例です。

![LB から Pod](http://docs.aws.amazon.com/ja_jp/eks/latest/best-practices/images/lb_2_pod.png)


*ip モード*を使用する場合、ネットワークトラフィックはロードバランサーから送信先 Pod に直接プロキシされます。そのため、このアプローチには*データ転送料金はかかりません*。

**注記**  
データ転送料金を削減するために、ロードバランサーを *ip トラフィックモード*に設定することをお勧めします。この設定では、ロードバランサーが VPC 内のすべてのサブネットにデプロイされていることを確認することも重要です。

以下の図は、ロードバランサーからネットワーク *IP モードで* Pod に流れるトラフィックのネットワークパスを示しています。

![IP モード](http://docs.aws.amazon.com/ja_jp/eks/latest/best-practices/images/ip_mode.png)


## コンテナレジストリからのデータ転送
<a name="_data_transfer_from_container_registry"></a>

### Amazon ECR
<a name="_amazon_ecr"></a>

Amazon ECR プライベートレジストリへのデータ転送は無料です。*リージョン内データ転送には料金はかかりません*が、インターネットへのデータ転送とリージョン間のデータ転送には、転送の両側でインターネットデータ転送料金が請求されます。

ECRs の組み込み[イメージレプリケーション機能](https://docs.aws.amazon.com/AmazonECR/latest/userguide/replication.html)を使用して、関連するコンテナイメージをワークロードと同じリージョンにレプリケートする必要があります。これにより、レプリケーションは 1 回課金され、同じリージョン (リージョン内) のイメージプルはすべて無料になります。

*[インターフェイス VPC エンドポイント](https://docs.aws.amazon.com/whitepapers/latest/aws-privatelink/what-are-vpc-endpoints.html)を使用してリージョン内の ECR リポジトリに接続することで、*ECR からのイメージのプル (データ転送) に関連するデータ転送コストをさらに削減できます。ECR のパブリック AWS エンドポイントに接続する別の方法 (NAT ゲートウェイとインターネットゲートウェイ経由) では、データ処理と転送のコストが高くなります。次のセクションでは、ワークロードと AWS サービス間のデータ転送コストの削減について詳しく説明します。

特に大きなイメージでワークロードを実行している場合は、キャッシュされたコンテナイメージを使用して独自のカスタム Amazon マシンイメージ (AMIs) を構築できます。これにより、コンテナレジストリから EKS ワーカーノードへの初期イメージのプル時間と潜在的なデータ転送コストを削減できます。

## インターネットおよび AWS サービスへのデータ転送
<a name="_data_transfer_to_internet_aws_services"></a>

インターネット経由で Kubernetes ワークロードを他の AWS のサービスやサードパーティーのツールやプラットフォームと統合するのが一般的な方法です。関連する送信先との間でトラフィックをルーティングするために使用される基盤となるネットワークインフラストラクチャは、データ転送プロセスで発生するコストに影響を与える可能性があります。

### NAT ゲートウェイの使用
<a name="_using_nat_gateways"></a>

NAT ゲートウェイは、ネットワークアドレス変換 (NAT) を実行するネットワークコンポーネントです。以下の図は、他の AWS サービス (Amazon ECR、DynamoDB、S3) およびサードパーティープラットフォームと通信する EKS クラスター内の Pod を示しています。この例では、ポッドは個別の AZs。インターネットからのトラフィックを送受信するために、NAT ゲートウェイが 1 つの AZ のパブリックサブネットにデプロイされ、プライベート IP アドレスを持つリソースが 1 つのパブリック IP アドレスを共有してインターネットにアクセスできるようになります。この NAT Gateway は、インターネットゲートウェイコンポーネントと通信し、パケットを最終送信先に送信できるようにします。

![NAT Gateway](http://docs.aws.amazon.com/ja_jp/eks/latest/best-practices/images/nat_gw.png)


このようなユースケースで NAT ゲートウェイを使用する場合、*各 AZ に NAT ゲートウェイをデプロイすることで、データ転送コストを最小限に抑えることができます*。これにより、インターネットにルーティングされるトラフィックは同じ AZ の NAT ゲートウェイを通過し、AZ 間のデータ転送を回避します。ただし、AZ 間データ転送のコストを節約できますが、この設定はアーキテクチャに追加の NAT ゲートウェイのコストが発生することを意味します。

この推奨アプローチを次の図に示します。

![(推奨されるアプローチ)](http://docs.aws.amazon.com/ja_jp/eks/latest/best-practices/images/recommended_approach.png)


### VPC エンドポイントの使用
<a name="_using_vpc_endpoints"></a>

このようなアーキテクチャのコストをさらに削減するには、*[VPC エンドポイント](https://docs.aws.amazon.com/whitepapers/latest/aws-privatelink/what-are-vpc-endpoints.html)を使用してワークロードと AWS サービス間の接続を確立する必要があります*。VPC エンドポイントを使用すると、データ/ネットワークパケットがインターネットを通過することなく、VPC 内から AWS のサービスにアクセスできます。すべてのトラフィックは内部であり、AWS ネットワーク内にとどまります。VPC エンドポイントには、インターフェイス VPC エンドポイント ([多くの AWS サービスでサポート)](https://docs.aws.amazon.com/vpc/latest/privatelink/aws-services-privatelink-support.html) とゲートウェイ VPC エンドポイント (S3 と DynamoDB でのみサポート) の 2 種類があります。

 **ゲートウェイ VPC エンドポイント** 

 *Gateway VPC エンドポイントに関連する時間単位またはデータ転送コストはありません*。Gateway VPC エンドポイントを使用する場合は、VPC の境界を越えて拡張できないことに注意してください。VPC ピアリング、VPN ネットワーク、または Direct Connect 経由で使用することはできません。

 **インターフェイス VPC エンドポイント** 

VPC エンドポイントには[時間単位の料金](https://aws.amazon.com/privatelink/pricing/)がかかり、基盤となる ENI を介したデータ処理には追加料金がかかります。AZ 間のデータ転送は[課金されない](https://aws.amazon.com/about-aws/whats-new/2022/04/aws-data-transfer-price-reduction-privatelink-transit-gateway-client-vpn-services/)ことに注意してください。

次の図は、VPC エンドポイントを介して AWS サービスと通信するポッドを示しています。

![VPC エンドポイント](http://docs.aws.amazon.com/ja_jp/eks/latest/best-practices/images/vpc_endpoints.png)


## VPCs間のデータ転送
<a name="_data_transfer_between_vpcs"></a>

場合によっては、異なる VPCs (同じ AWS リージョン内) にワークロードがあり、相互に通信する必要がある場合があります。これは、トラフィックがそれぞれの VPCs にアタッチされたインターネットゲートウェイを介してパブリックインターネットを通過できるようにすることで実現できます。このような通信を有効にするには、EC2 インスタンス、NAT ゲートウェイ、NAT インスタンスなどのインフラストラクチャコンポーネントをパブリックサブネットにデプロイします。ただし、これらのコンポーネントを含むセットアップでは、VPCs との間でデータを処理/転送するための料金が発生します。個別の VPCs との間のトラフィックが AZs 間で移動する場合は、データ転送に追加料金が発生します。次の図は、NAT ゲートウェイとインターネットゲートウェイを使用して、異なる VPCs 内のワークロード間の通信を確立するセットアップを示しています。

![VPCs間](http://docs.aws.amazon.com/ja_jp/eks/latest/best-practices/images/between_vpcs.png)


### VPC ピアリング接続
<a name="_vpc_peering_connections"></a>

このようなユースケースのコストを削減するために、[VPC ピアリング](https://docs.aws.amazon.com/vpc/latest/peering/what-is-vpc-peering.html)を使用できます。VPC ピアリング接続では、同じ AZ 内に留まるネットワークトラフィックのデータ転送料金は発生しません。トラフィックが AZs を超えると、コストが発生します。ただし、同じ AWS リージョン内の別々の VPC 内のワークロード間のコスト効率の高い通信にはVPCs ピアリングアプローチが推奨されます。ただし、VPC ピアリングは推移的なネットワークを許可しないため、主に 1:1 VPC 接続に有効であることに注意してください。

次の図は、VPC ピアリング接続を介したワークロード通信の概要を示しています。

![ピア接続](http://docs.aws.amazon.com/ja_jp/eks/latest/best-practices/images/peering.png)


### 推移的なネットワーク接続
<a name="_transitive_networking_connections"></a>

前のセクションで説明したように、VPC ピアリング接続では推移的なネットワーク接続は許可されません。3 つ以上の VPCs を推移的なネットワーク要件で接続する場合は、[Transit Gateway](https://docs.aws.amazon.com/vpc/latest/tgw/what-is-transit-gateway.html) (TGW) を使用する必要があります。これにより、VPC ピアリングの制限や、複数の VPC 間の複数の VPC ピアリング接続に関連する運用オーバーヘッドVPCs克服できます。TGW に送信されたデータに対して[、時間単位で課金](https://aws.amazon.com/transit-gateway/pricing/)されます。*TGW を通過する AZ 間トラフィックに関連する送信先コストはありません。*

次の図は、異なる VPCs 内の同じ AWS リージョン内のワークロード間で TGW を通過する AZ 間トラフィックを示しています。

![推移的](http://docs.aws.amazon.com/ja_jp/eks/latest/best-practices/images/transititive.png)


## Service Mesh の使用
<a name="_using_a_service_mesh"></a>

サービスメッシュは、EKS クラスター環境のネットワーク関連コストを削減するために使用できる強力なネットワーク機能を提供します。ただし、サービスメッシュを採用すると、サービスメッシュが環境にもたらす運用タスクと複雑さを慎重に検討する必要があります。

### トラフィックをアベイラビリティーゾーンに制限する
<a name="_restricting_traffic_to_availability_zones"></a>

 **Istio の Locality 加重ディストリビューションの使用** 

Istio を使用すると、ルーティングの発生*後に*ネットワークポリシーをトラフィックに適用できます。これは、[ローカリティ加重分散](https://istio.io/latest/docs/tasks/traffic-management/locality-load-balancing/distribute/)などの[送信先ルール](https://istio.io/latest/docs/reference/config/networking/destination-rule/)を使用して行われます。この機能を使用すると、送信元に基づいて特定の送信先に移動できるトラフィックの重み (パーセンテージで表される) を制御できます。このトラフィックのソースは、外部 (またはパブリック向け) ロードバランサーまたはクラスター自体内の Pod のいずれかです。すべての Pod エンドポイントが使用可能になると、加重ラウンドロビン負荷分散アルゴリズムに基づいてローカリティが選択されます。特定のエンドポイントが異常または使用できない場合、利用可能なエンドポイントでこの変更を反映するように、[ローカリティの重みが自動的に調整されます](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/load_balancing/locality_weight.html)。

**注記**  
ローカル性加重分散を実装する前に、まずネットワークトラフィックパターンと、送信先ルールポリシーがアプリケーションの動作に与える影響を理解する必要があります。そのため、[AWS X-Ray](https://aws.amazon.com/xray/) や [Jaeger](https://www.jaegertracing.io/) などのツールを使用して分散トレースメカニズムを導入することが重要です。

上記の Istio 送信先ルールは、ロードバランサーから EKS クラスター内の Pod へのトラフィックを管理するためにも適用できます。ローカル加重分散ルールは、高可用性ロードバランサー (特に Ingress Gateway) からトラフィックを受信するサービスに適用できます。これらのルールにより、ゾーンオリジン - この場合のロードバランサーに基づいて、 へのトラフィック量を制御できます。正しく設定すると、異なる AZs のポッドレプリカにトラフィックを均等またはランダムに分散するロードバランサーと比較して、エグレスクロスゾーントラフィックが少なくなります。

以下は、Istio の送信先ルールリソースのコードブロックの例です。以下に示すように、このリソースは、`eu-west-1`リージョン内の 3 つの異なる AZs からの受信トラフィックの加重設定を指定します。これらの設定は、特定の AZ からの受信トラフィックの大部分 (この場合は 70%) を、送信元と同じ AZ の送信先にプロキシする必要があることを宣言します。

```
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: express-test-dr
spec:
  host: express-test.default.svc.cluster.local
  trafficPolicy:
    loadBalancer:                      +
      localityLbSetting:
        distribute:
        - from: eu-west-1/eu-west-1a/  +
          to:
            "eu-west-1/eu-west-1a/_": 70
            "eu-west-1/eu-west-1b/_": 20
            "eu-west-1/eu-west-1c/_": 10
        - from: eu-west-1/eu-west-1b/_  +
          to:
            "eu-west-1/eu-west-1a/_": 20
            "eu-west-1/eu-west-1b/_": 70
            "eu-west-1/eu-west-1c/_": 10
        - from: eu-west-1/eu-west-1c/_  +
          to:
            "eu-west-1/eu-west-1a/_": 20
            "eu-west-1/eu-west-1b/_": 10
            "eu-west-1/eu-west-1c/*": 70**
    connectionPool:
      http:
        http2MaxRequests: 10
        maxRequestsPerConnection: 10
    outlierDetection:
      consecutiveGatewayErrors: 1
      interval: 1m
      baseEjectionTime: 30s
```

**注記**  
分散先として指定できる最小重みは 1% です。これは、メイン送信先のエンドポイントが異常または使用できなくなった場合に備えて、フェイルオーバーリージョンとゾーンを維持するためです。

次の図は、*eu-west-1* リージョンに高可用性ロードバランサーがあり、ローカル性の加重分散が適用されるシナリオを示しています。この図の宛先ルールポリシーは、*eu-west-1a* からのトラフィックの 60% を同じ AZ の Pod に送信するように設定されていますが、*eu-west-1a* からのトラフィックの 40% は eu-west-1b の Pod に送信する必要があります。

![トラフィックコントロールの停止](http://docs.aws.amazon.com/ja_jp/eks/latest/best-practices/images/istio-traffic-control.png)


### アベイラビリティーゾーンとノードへのトラフィックの制限
<a name="_restricting_traffic_to_availability_zones_and_nodes"></a>

 **Istio での サービス内部トラフィックポリシーの使用** 

Pod 間の*外部*着信トラフィックと*内部*トラフィックに関連するネットワークコストを削減するために、Istio の送信先ルールと Kubernetes Service *の内部トラフィックポリシー*を組み合わせることができます。Istio 送信先ルールをサービス内部トラフィックポリシーと組み合わせる方法は、主に 3 つの要素によって異なります。
+ マイクロサービスの役割
+ マイクロサービス全体のネットワークトラフィックパターン
+ Kubernetes クラスタートポロジ全体にマイクロサービスをデプロイする方法

次の図は、ネストされたリクエストの場合のネットワークフローと、前述のポリシーがトラフィックをどのように制御するかを示しています。

![外部および内部トラフィックポリシー](http://docs.aws.amazon.com/ja_jp/eks/latest/best-practices/images/external-and-internal-traffic-policy.png)


1. エンドユーザーは **APP A にリクエストを行い、**A**PP C **にネストされたリクエストを行います。 このリクエストは、最初に高可用性ロードバランサーに送信されます。ロードバランサーには、上記の図に示すように AZ 1 および AZ 2 のインスタンスがあります。

1. その後、外部受信リクエストは Istio Virtual Service によって正しい宛先にルーティングされます。

1. リクエストがルーティングされると、Istio 送信先ルールは、送信元 (AZs 1 または AZ 2) に基づいて、各 AZ へのトラフィック量を制御します。

1. その後、トラフィックは **APP A **のサービスに送信され、それぞれの Pod エンドポイントにプロキシされます。図に示すように、着信トラフィックの 80% が AZ 1 の Pod エンドポイントに送信され、着信トラフィックの 20% が AZ 2 に送信されます。

1.  **その後、APP A** は **APP C **に内部リクエストを行います。 **APP C** のサービスでは、内部トラフィックポリシーが有効になっています (`internalTrafficPolicy``: Local`)。

1. **APP C のノードローカルエンドポイントが使用可能であるため、APP A** (**NODE 1**) から **APP C **への内部リクエストは成功しました。 ****

1. **APP ****C** に使用可能な*ノードローカルエンドポイント*がないため、APP A (**NODE 3) から APP C への**内部リクエストは失敗します。 **** 図に示すように、APP C には NODE 3 にレプリカがありません。 **\***\*

以下のスクリーンショットは、このアプローチのライブ例からキャプチャされています。最初のスクリーンショットのセットは、 への外部リクエストが成功`graphql`し、 からノード 上の同じ場所にある`orders`レプリカ`graphql`へのネストされたリクエストが成功したことを示しています`ip-10-0-0-151.af-south-1.compute.internal`。

![Before](http://docs.aws.amazon.com/ja_jp/eks/latest/best-practices/images/before.png)


![結果の前](http://docs.aws.amazon.com/ja_jp/eks/latest/best-practices/images/before-results.png)


Istio を使用すると、プロキシが認識している[アップストリームクラスター](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/intro/terminology)とエンドポイントの統計を検証してエクスポートできます。これにより、ネットワークフローの全体像と、ワークロードのサービス間の分散の割合を把握できます。同じ例を続けると、`graphql`プロキシが認識している`orders`エンドポイントは、次のコマンドを使用して取得できます。

```
kubectl exec -it deploy/graphql -n ecommerce -c istio-proxy -- curl localhost:15000/clusters | grep orders
```

```
...
orders-service.ecommerce.svc.cluster.local::10.0.1.33:3003::**rq_error::0**
orders-service.ecommerce.svc.cluster.local::10.0.1.33:3003::**rq_success::119**
orders-service.ecommerce.svc.cluster.local::10.0.1.33:3003::**rq_timeout::0**
orders-service.ecommerce.svc.cluster.local::10.0.1.33:3003::**rq_total::119**
orders-service.ecommerce.svc.cluster.local::10.0.1.33:3003::**health_flags::healthy**
orders-service.ecommerce.svc.cluster.local::10.0.1.33:3003::**region::af-south-1**
orders-service.ecommerce.svc.cluster.local::10.0.1.33:3003::**zone::af-south-1b**
...
```

この場合、`graphql`プロキシはノードを共有するレプリカの`orders`エンドポイントのみを認識します。サービス注文から `internalTrafficPolicy: Local`設定を削除し、上記のようなコマンドを再実行すると、結果は異なるノードにまたがるレプリカのすべてのエンドポイントを返します。さらに、それぞれのエンドポイント`rq_total`の を調べると、ネットワークディストリビューションに比較的均等な共有があることがわかります。したがって、エンドポイントが異なる AZs で実行されているアップストリームサービスに関連付けられている場合、ゾーン間のこのネットワーク分散によりコストが高くなります。

上記の前のセクションで説明したように、Pod-affinity を使用することで、頻繁に通信する Pod を共同配置できます。

```
...
spec:
...
  template:
    metadata:
      labels:
        app: graphql
        role: api
        workload: ecommerce
    spec:
      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - orders
            topologyKey: "kubernetes.io/hostname"
      nodeSelector:
        managedBy: karpenter
        billing-team: ecommerce
...
```

`graphql` と `orders` レプリカが同じノード (`ip-10-0-0-151.af-south-1.compute.internal`) に共存しない場合、 への最初のリクエスト`graphql`は、以下の Postman スクリーンショット`200 response code`の に示されているように成功しますが、 から `graphql`へのネストされた 2 番目のリクエストは で`orders`失敗します`503 response code`。

 ![After](http://docs.aws.amazon.com/ja_jp/eks/latest/best-practices/images/after.png) ![After results](http://docs.aws.amazon.com/ja_jp/eks/latest/best-practices/images/after-results.png) 

## その他のリソース
<a name="_additional_resources"></a>
+  [Istio を使用して EKS のレイテンシーとデータ転送コストに対処する](https://aws.amazon.com/blogs/containers/addressing-latency-and-data-transfer-costs-on-eks-using-istio/) 
+  [Amazon Elastic Kubernetes Service のネットワークトラフィックに対するトポロジ対応ヒントの影響を調べる](https://aws.amazon.com/blogs/containers/exploring-the-effect-of-topology-aware-hints-on-network-traffic-in-amazon-elastic-kubernetes-service/) 
+  [Amazon EKS Cross-AZ ポッドからポッドネットワークバイトへの可視性の取得](https://aws.amazon.com/blogs/containers/getting-visibility-into-your-amazon-eks-cross-az-pod-to-pod-network-bytes/) 
+  [Istio で AZ トラフィックを最適化する](https://youtu.be/EkpdKVm9kQY) 
+  [トポロジ対応ルーティングで AZ トラフィックを最適化する](https://youtu.be/KFgE_lNVfz4) 
+  [サービス内部トラフィックポリシーによる Kubernetes のコストとパフォーマンスの最適化](https://youtu.be/-uiF_zixEro) 
+  [Istio とサービスの内部トラフィックポリシーを使用して Kubernetes のコストとパフォーマンスを最適化する](https://youtu.be/edSgEe7Rihc) 
+  [一般的なアーキテクチャでのデータ転送コストの概要](https://aws.amazon.com/blogs/architecture/overview-of-data-transfer-costs-for-common-architectures/) 
+  [AWS コンテナサービスのデータ転送コストについて](https://aws.amazon.com/blogs/containers/understanding-data-transfer-costs-for-aws-container-services/) 