

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

# ワークロード
<a name="scale-workloads"></a>

ワークロードは、クラスターのサイズに影響します。Kubernetes APIs を大量に使用するワークロードは、1 つのクラスターに保持できるワークロードの合計量を制限しますが、負荷を軽減するために変更できるデフォルトがいくつかあります。

Kubernetes クラスターのワークロードは、Kubernetes API と統合する機能 (Secrets や ServiceAccounts など) にアクセスできますが、これらの機能は必ずしも必要ではなく、使用されていない場合は無効にする必要があります。ワークロードへのアクセスと Kubernetes コントロールプレーンへの依存を制限すると、クラスターで実行できるワークロードの数が増え、ワークロードへの不要なアクセスがなくなり、最小特権のプラクティスが実装されるため、クラスターのセキュリティが向上します。詳細については、[セキュリティのベストプラクティス](https://docs.aws.amazon.com/eks/latest/best-practices/security.html)をお読みください。

## ポッドネットワークに IPv6 を使用する
<a name="_use_ipv6_for_pod_networking"></a>

VPC を IPv4 から IPv6 に移行することはできないため、クラスターをプロビジョニングする前に IPv6 を有効にすることが重要です。VPC で IPv6 を有効にしても、IPv6 を使用する必要はなく、ポッドやサービスで IPv6 を使用している場合でもIPv4 アドレスとの間でトラフィックをルーティングできます。詳細については、[EKS ネットワークのベストプラクティス](https://docs.aws.amazon.com/eks/latest/best-practices/networking.html)を参照してください。

[クラスターで IPv6 を使用すると、最も一般的なクラスターとワークロードのスケーリング制限の一部を回避できます](https://docs.aws.amazon.com/eks/latest/userguide/cni-ipv6.html)。IPv6 は、使用可能な IP アドレスがないため、ポッドとノードを作成できない IP アドレスの枯渇を回避します。また、ノードあたりの ENI アタッチメントの数を減らすことで、ポッドが IP アドレスをより速く受け取るため、ノードごとのパフォーマンスも向上します。[VPC CNI で IPv4 プレフィックスモード](https://docs.aws.amazon.com/eks/latest/best-practices/prefix-mode-linux.html)を使用することで、同様のノードパフォーマンスを実現できますが、VPC で十分な IP アドレスが利用可能であることを確認する必要があります。

## 名前空間あたりのサービス数の制限
<a name="_limit_number_of_services_per_namespace"></a>

[名前空間内のサービスの最大数は 5,000 で、クラスター内のサービスの最大数は 10,000 です](https://github.com/kubernetes/community/blob/master/sig-scalability/configs-and-limits/thresholds.md)。ワークロードとサービスを整理し、パフォーマンスを向上させ、名前空間スコープリソースへのカスケードの影響を回避するには、名前空間あたりのサービス数を 500 に制限することをお勧めします。

kube-proxy を使用してノードごとに作成される IP テーブルルールの数は、クラスター内のサービスの合計数に応じて増加します。数千の IP テーブルルールを生成し、それらのルールを介してパケットをルーティングすると、ノードのパフォーマンスに影響し、ネットワークレイテンシーが増加します。

名前空間あたりのサービス数が 500 未満である限り、単一のアプリケーション環境を含む Kubernetes 名前空間を作成します。これにより、サービス検出の制限を回避するためにサービス検出を小さく保ち、サービス名の衝突を回避することもできます。アプリケーション環境 (dev、test、prod など) では、名前空間の代わりに個別の EKS クラスターを使用する必要があります。

## Elastic Load Balancer のクォータを理解する
<a name="_understand_elastic_load_balancer_quotas"></a>

サービスを作成するときは、使用するロードバランシングのタイプ (Network Load Balancer (NLB) や Application Load Balancer (ALB) など) を検討してください。ロードバランサーのタイプごとに機能や[クォータが異なります](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-limits.html)。デフォルトのクォータの一部は調整できますが、クォータの最大数もあり、変更することはできません。アカウントのクォータと使用状況を表示するには、AWS コンソールで [Service Quotas ダッシュボード](https://console.aws.amazon.com/servicequotas)を表示します。

たとえば、デフォルトの ALB ターゲットは 1000 です。エンドポイントが 1000 を超えるサービスがある場合は、クォータを増やすか、サービスを複数の ALBs に分割するか、Kubernetes Ingress を使用する必要があります。デフォルトの NLB ターゲットは 3000 ですが、AZ あたり 500 ターゲットに制限されています。クラスターが NLB サービスに対して 500 個を超えるポッドを実行している場合は、複数の AZs を使用するか、クォータ制限の引き上げをリクエストする必要があります。

サービスに結合されたロードバランサーを使用する代わりに、[イングレスコントローラー](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/)を使用します。AWS Load Balancer コントローラーはイングレスリソースの ALBs を作成できますが、クラスターで専用コントローラーを実行することを検討することもできます。クラスター内イングレスコントローラーを使用すると、クラスター内でリバースプロキシを実行して、単一のロードバランサーから複数の Kubernetes サービスを公開できます。コントローラーには、[Gateway API](https://gateway-api.sigs.k8s.io/) のサポートなどのさまざまな機能があり、ワークロードの数と規模に応じてメリットが得られる場合があります。

## Route 53、Global Accelerator、または CloudFront を使用する
<a name="_use_route_53_global_accelerator_or_cloudfront"></a>

複数のロードバランサーを使用するサービスを単一のエンドポイントとして利用できるようにするには、[Amazon CloudFront](https://aws.amazon.com/cloudfront/)、[AWS Global Accelerator](https://aws.amazon.com/global-accelerator/)、または [Amazon Route 53](https://aws.amazon.com/route53/) を使用して、すべてのロードバランサーを単一の顧客向けエンドポイントとして公開する必要があります。各オプションにはさまざまな利点があり、ニーズに応じて個別に使用することも、一緒に使用することもできます。

Route 53 は、共通の名前で複数のロードバランサーを公開し、割り当てられた重みに基づいて各ロードバランサーにトラフィックを送信できます。[DNS の重みの詳細については、 ドキュメントを参照してください](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resource-record-sets-values-weighted.html#rrsets-values-weighted-weight)。また、[AWS Load Balancer Controller ドキュメント](https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.4/guide/integrations/external_dns/#usage)の [Kubernetes 外部 DNS コントローラー](https://github.com/kubernetes-sigs/external-dns)を使用してそれらを実装する方法も確認できます。

Global Accelerator は、リクエスト IP アドレスに基づいて、最も近いリージョンにワークロードをルーティングできます。これは、複数のリージョンにデプロイされるワークロードには便利ですが、1 つのリージョンの 1 つのクラスターへのルーティングは改善されません。Route 53 を Global Accelerator と組み合わせて使用すると、AZ が利用できない場合はヘルスチェックや自動フェイルオーバーなどの追加の利点があります。[このブログ記事](https://aws.amazon.com/blogs/containers/operating-a-multi-regional-stateless-application-using-amazon-eks/)では、Route 53 で Global Accelerator を使用する例を示しています。

CloudFront は、Route 53 および Global Accelerator で使用するか、単独で複数の宛先にトラフィックをルーティングできます。CloudFront は、オリジンソースから提供されるアセットをキャッシュするため、提供している内容に応じて帯域幅要件が軽減される可能性があります。

## エンドポイントの代わりに EndpointSlices を使用する
<a name="_use_endpointslices_instead_of_endpoints"></a>

サービスラベルに一致するポッドを検出するときは、エンドポイントの代わりに [EndpointSlices](https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/) を使用する必要があります。エンドポイントは小規模でサービスを公開する簡単な方法ですが、自動スケーリングや更新を行う大規模なサービスでは、Kubernetes コントロールプレーンで大量のトラフィックが発生します。EndpointSlices には、トポロジ対応ヒントなどを有効にする自動グループ化があります。

デフォルトでは、すべてのコントローラーが EndpointSlices を使用するわけではありません。コントローラーの設定を確認し、必要に応じて有効にする必要があります。[AWS Load Balancer Controller](https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.4/deploy/configurations/#controller-command-line-flags) では、`--enable-endpoint-slices`オプションの フラグを有効にして EndpointSlices を使用する必要があります。

## 可能であれば、イミュータブルシークレットと外部シークレットを使用する
<a name="_use_immutable_and_external_secrets_if_possible"></a>

kubelet は、そのノード上のポッドのボリュームで使用されるシークレットの現在のキーと値のキャッシュを保持します。kubelet は、変更を検出するためにシークレットに監視を設定します。クラスターがスケールすると、監視の数が増えると API サーバーのパフォーマンスに悪影響を及ぼす可能性があります。

Secrets のウォッチの数を減らすには、次の 2 つの戦略があります。
+ Kubernetes リソースへのアクセスを必要としないアプリケーションの場合、automountServiceAccountToken: false を設定することで、サービスアカウントシークレットの自動マウントを無効にすることができます。
+ アプリケーションのシークレットが静的で、今後変更されない場合は、シーク[レットをイミュータブルとして](https://kubernetes.io/docs/concepts/configuration/secret/#secret-immutable)マークします。kubelet は、イミュータブルシークレットの API 監視を維持しません。

サービスアカウントのポッドへの自動マウントを無効にするには、ワークロードで次の設定を使用します。特定のワークロードにサービスアカウントが必要な場合は、これらの設定を上書きできます。

```
apiVersion: v1
kind: ServiceAccount
metadata:
  name: app
automountServiceAccountToken: true
```

制限の 10,000 を超える前に、クラスター内のシークレットの数をモニタリングします。次のコマンドを使用して、クラスター内のシークレットの合計数を確認できます。この制限は、クラスターモニタリングツールでモニタリングする必要があります。

```
kubectl get secrets -A | wc -l
```

この制限に達する前に、クラスター管理者に警告するようにモニタリングを設定する必要があります。Secrets Store CSI ドライバーで [AWS Key Management Service (AWS KMS)](https://aws.amazon.com/kms/) や [Hashicorp Vault](https://www.vaultproject.io/) などの外部シークレット管理オプションを使用することを検討してください。 [https://secrets-store-csi-driver.sigs.k8s.io/](https://secrets-store-csi-driver.sigs.k8s.io/)

## デプロイ履歴の制限
<a name="_limit_deployment_history"></a>

古いオブジェクトはクラスター内で追跡されるため、ポッドの作成、更新、削除に時間がかかる場合があります。[デプロイ](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#clean-up-policy)`revisionHistoryLimit`の を減らして、古い ReplicaSets をクリーンアップできます。これにより、Kubernetes Controller Manager によって追跡されるオブジェクトの合計量が減ります。10 のデプロイのデフォルトの履歴制限。

クラスターが CronJobs またはその他のメカニズムを使用して多数のジョブオブジェクトを作成する場合は、 [`ttlSecondsAfterFinished`設定](https://kubernetes.io/docs/concepts/workloads/controllers/ttlafterfinished/)を使用してクラスター内の古いポッドを自動的にクリーンアップする必要があります。これにより、指定した時間が経過すると、正常に実行されたジョブがジョブ履歴から削除されます。

## enableServiceLinks をデフォルトで無効にする
<a name="_disable_enableservicelinks_by_default"></a>

ポッドがノードで実行されると、kubelet はアクティブなサービスごとに一連の環境変数を追加します。Linux プロセスには環境の最大サイズがあり、名前空間にサービスが多すぎると到達できます。名前空間あたりのサービス数は 5,000 を超えることはできません。その後、サービス環境変数の数はシェルの制限を超過し、起動時に Pod がクラッシュします。

ポッドがサービス検出にサービス環境変数を使用しない理由は他にもあります。環境変数名の競合、漏洩しているサービス名、および合計環境サイズがいくつかあります。サービスエンドポイントを検出するには、CoreDNS を使用する必要があります。

## リソースごとに動的アドミッションウェブフックを制限する
<a name="_limit_dynamic_admission_webhooks_per_resource"></a>

 [動的アドミッションウェブフックには、](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/)アドミッションウェブフックとミューテーションウェブフックが含まれます。これらは、リソースが Kubernetes API に送信されるときに順番に呼び出される Kubernetes コントロールプレーンの一部ではない API エンドポイントです。各ウェブフックのデフォルトのタイムアウトは 10 秒で、複数のウェブフックまたはいずれかのタイムアウトがある場合、API リクエストにかかる時間を増やすことができます。

特に AZ インシデント中に、ウェブフックの可用性が高く、 [failurePolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#failure-policy) が適切に設定され、リソースを拒否するか、障害を無視することを確認します。--dry-run kubectl コマンドがウェブフックをバイパスできるようにして、不要な場合はウェブフックを呼び出さないでください。

```
apiVersion: admission.k8s.io/v1
kind: AdmissionReview
request:
  dryRun: False
```

ウェブフックをミューテーションすると、リソースが頻繁に連続して変更される可能性があります。5 つの変更ウェブフックがあり、50 のリソースをデプロイする場合、etd は、変更したリソースの古いバージョンを削除するために圧縮が 5 分ごとに実行されるまで、各リソースのすべてのバージョンを保存します。etcd が置き換えられたリソースを削除するこのシナリオでは、etcd から 200 個のリソースバージョンが削除され、リソースのサイズによっては、デフラグが 15 分ごとに実行されるまで、etcd ホストでかなりのスペースを使用する場合があります。

このデフラグメンテーションにより etcd が一時停止し、Kubernetes API とコントローラーに他の影響を与える可能性があります。大規模なリソースを頻繁に変更したり、数百のリソースをすばやく連続して変更したりすることは避けてください。

## 複数のクラスター間でワークロードを比較する
<a name="_compare_workloads_across_multiple_clusters"></a>

同様のパフォーマンスを持つ必要があるが、持たないクラスターが 2 つある場合は、メトリクスを比較して理由を特定してみてください。

例えば、クラスターのレイテンシーを比較するのは一般的な問題です。これは通常、API リクエストの量の違いが原因です。次の CloudWatch LogInsight クエリを実行して、違いを理解できます。

```
filter @logStream like "kube-apiserver-audit"
| stats count(*) as cnt by objectRef.apiGroup, objectRef.apiVersion, objectRef.resource, userAgent, verb, responseStatus.code
| sort cnt desc
| limit 1000
```

フィルターを追加して絞り込むことができます。例えば、 からのすべてのリストリクエストに焦点を当てます`foo`。

```
filter @logStream like "kube-apiserver-audit"
| filter verb = "list"
| filter user.username like "foo"
| stats count(*) as cnt by objectRef.apiGroup, objectRef.apiVersion, objectRef.resource, responseStatus.code
| sort cnt desc
| limit 1000
```