

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

# 信頼性のベストプラクティス
<a name="reliability"></a>

このセクションでは、EKS で実行されているワークロードを回復力と高可用性にするためのガイダンスを提供します。

## このガイドの使い方
<a name="how-to-use-this-guide"></a>

このガイドは、EKS で可用性と耐障害性に優れたサービスを開発して運用したい開発者やアーキテクトを対象としています。このガイドは、使いやすいようにさまざまなトピック領域にまとめられています。各トピックは簡単な概要から始まり、EKS クラスターの信頼性に関する推奨事項とベストプラクティスのリストが続きます。

## 序章
<a name="introduction"></a>

EKS の信頼性のベストプラクティスは、次のトピックにまとめられています。
+ アプリケーション
+ コントロールプレーン
+ データプレーン

システムの信頼性を高めるものは何ですか? 一定期間の環境の変化にもかかわらず、システムが一貫して機能し、需要を満たすことができる場合は、信頼性と呼ぶことができます。これを実現するには、システムは障害を検出し、自動的に修復し、需要に基づいてスケーリングできる必要があります。

お客様は、ミッションクリティカルなアプリケーションとサービスを確実に運用するための基盤として Kubernetes を使用できます。ただし、コンテナベースのアプリケーション設計原則を組み込むことに加えて、ワークロードを確実に実行するには、信頼性の高いインフラストラクチャも必要です。Kubernetes では、インフラストラクチャはコントロールプレーンとデータプレーンで構成されます。

EKS は、可用性と耐障害性に優れた本番稼働グレードの Kubernetes コントロールプレーンを提供します。

EKS では、AWS が Kubernetes コントロールプレーンの信頼性を担当します。EKS は、AWS リージョンの 3 つのアベイラビリティーゾーンで Kubernetes コントロールプレーンを実行します。Kubernetes API サーバーと etcd クラスターの可用性とスケーラビリティを自動的に管理します。

データプレーンの信頼性に対する責任は、ユーザー、顧客、AWS の間で共有されます。EKS には、Kubernetes データプレーンをデプロイするための 4 つのワーカーノードオプションが用意されています。

 最もマネージド型のオプションである [EKS Auto Mode](https://docs.aws.amazon.com/eks/latest/userguide/automode.html) は、データプレーンのプロビジョニング、スケーリング、更新を処理し、マネージド型のコンピューティング、ネットワーキング、ストレージ機能を提供します。Auto Mode AMIs は頻繁にリリースされ、クラスターは CVE 修正とセキュリティパッチをデプロイするために最新の AMI に自動的に更新されます。Auto Mode NodePools で[中断](https://docs.aws.amazon.com/eks/latest/userguide/create-node-pool.html#_disruption)コントロールを設定することで、これが発生するタイミングを制御できます。

Fargate は、ノードごとに 1 つの Pod を実行して、データプレーンのプロビジョニングとスケーリングを処理します。3 番目のオプションであるマネージドノードグループは、データプレーンのプロビジョニングと更新を処理します。最後に、セルフマネージド型ノードはデータプレーンの最小マネージド型オプションです。使用する AWS マネージドデータプレーンが多いほど、責任は軽減されます。

 [マネージド型ノードグループは](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html)、EC2 ノードのプロビジョニングとライフサイクル管理を自動化します。EKS API (EKS コンソール、AWS API、AWS CLI、CloudFormation、Terraform、または を使用`eksctl`) を使用して、マネージドノードを作成、スケーリング、アップグレードできます。マネージドノードは、アカウントで EKS 最適化 Amazon Linux 2 EC2 インスタンスを実行し、SSH アクセスを有効にすることでカスタムソフトウェアパッケージをインストールできます。マネージドノードをプロビジョニングすると、複数のアベイラビリティーゾーンにまたがることができる EKS マネージド Auto Scaling グループの一部として実行されます。これは、マネージドノードの作成時に指定したサブネットを介して制御します。また、EKS はマネージドノードに自動的にタグを付け、Cluster Autoscaler で使用できるようにします。

Amazon EKS は、マネージド型ノードグループで CVE およびセキュリティパッチの責任共有モデルに従います。マネージドノードは Amazon EKS に最適化された AMIs を実行するため、Amazon EKS はバグ修正時にこれらの AMIs のパッチ適用されたバージョンを構築する責任があります。ただし、これらのパッチが適用された AMI バージョンのマネージド型ノードグループへのデプロイはユーザーが担当します。

EKS [はノードの更新も管理します](https://docs.aws.amazon.com/eks/latest/userguide/update-managed-node-group.html)が、更新プロセスを開始する必要があります。[マネージドノードを更新する](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-update-behavior.html)プロセスは、EKS ドキュメントで説明されています。

セルフマネージド型ノードを実行する場合は、[Amazon EKS 最適化 Linux AMI ](https://docs.aws.amazon.com/eks/latest/userguide/eks-optimized-ami.html)を使用してワーカーノードを作成できます。AMI とノードのパッチ適用とアップグレードはお客様の責任となります。`eksctl`、CloudFormation、または infrastructure をコードツールとして使用してセルフマネージドノードをプロビジョニングするのがベストプラクティスです。これにより、[セルフマネージドノードを簡単にアップグレード](https://docs.aws.amazon.com/eks/latest/userguide/update-workers.html)できるためです。ワーカーノードを更新するときは[、新しいノードへの移行](https://docs.aws.amazon.com/eks/latest/userguide/migrate-stack.html)を検討してください。移行プロセスによって古いノードグループが として**テイント**`NoSchedule`され、新しいスタックが既存のポッドワークロードを受け入れる準備ができたらノードが**ドレイン**されるためです。ただし、[セルフマネージドノードのインプレースアップグレード](https://docs.aws.amazon.com/eks/latest/userguide/update-stack.html)を実行することもできます。

 **責任共有モデル - Fargate** 

![\[責任共有モデル - Fargate\]](http://docs.aws.amazon.com/ja_jp/eks/latest/best-practices/images/reliability/SRM-Fargate.jpeg)


 **責任共有モデル - MNG** 

![\[責任共有モデル - MNG\]](http://docs.aws.amazon.com/ja_jp/eks/latest/best-practices/images/reliability/SRM-MNG.jpeg)


このガイドには、EKS データプレーン、Kubernetes コアコンポーネント、アプリケーションの信頼性を向上させるために使用できる一連の推奨事項が含まれています。

## フィードバック
<a name="feedback"></a>

このガイドは、より広範な EKS/Kubernetes コミュニティから直接フィードバックや提案を収集するために GitHub でリリースされています。ガイドに含める必要があると思われるベストプラクティスがある場合は、問題をファイルするか、GitHub リポジトリに PR を送信してください。サービスに新機能が追加されたとき、または新しいベストプラクティスが進化したときに、ガイドを定期的に更新する予定です。

# 高可用性アプリケーションの実行
<a name="application"></a>

お客様は、変更を行う場合や特にトラフィックの急増時など、アプリケーションを常に利用できることを期待しています。スケーラブルで回復力のあるアーキテクチャにより、中断することなくアプリケーションやサービスを実行し、ユーザーを満足させます。スケーラブルなインフラストラクチャは、ビジネスのニーズに応じて増減します。単一障害点を排除することは、アプリケーションの可用性を向上させ、回復力を高めるための重要なステップです。

Kubernetes を使用すると、アプリケーションを運用し、可用性と回復力に優れた方法で実行できます。宣言型管理により、アプリケーションを設定すると、Kubernetes は引き続き[現在の状態を目的の状態と照合しようとします](https://kubernetes.io/docs/concepts/architecture/controller/#desired-vs-current)。

## 推奨事項
<a name="_recommendations"></a>

### Pod Disruption Budgets を設定する
<a name="_configure_pod_disruption_budgets"></a>

 [Pod Disruption Budgets](https://kubernetes.io/docs/tasks/run-application/configure-pdb/) は、アプリケーションが同時に発生する中断の量を制限するために使用されます。ワークロードの一部を常に利用できるようにすることが重要な場合は、ワークロード用に設定する必要があります。EKS Auto Mode、Karpenter、Cluster Autoscaler は、スケールダウン時に設定された Pod Disruption Budgets を認識し、準拠します。EKS Auto Mode、Karpenter、マネージド型ノードグループは、ノードの更新時に Pod Disruption Budgets にも準拠します。

### シングルトンポッドの実行を避ける
<a name="_avoid_running_singleton_pods"></a>

アプリケーション全体が 1 つの Pod で実行されている場合、その Pod が終了するとアプリケーションは使用できなくなります。個々のポッドを使用してアプリケーションをデプロイする代わりに、[デプロイ](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)を作成します。デプロイによって作成されたポッドが失敗または終了した場合、デプロイ[コントローラー](https://kubernetes.io/docs/concepts/architecture/controller/)は新しいポッドを起動して、指定された数のレプリカポッドが常に実行されていることを確認します。

### 複数のレプリカを実行する
<a name="_run_multiple_replicas"></a>

デプロイを使用してアプリケーションの複数のレプリカポッドを実行すると、可用性の高い方法で実行できます。1 つのレプリカが失敗しても、残りのレプリカは機能します。ただし、Kubernetes が損失を補うために別の Pod を作成するまで、容量が減ります。さらに、[Horizontal Pod Autoscaler ](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/)を使用して、ワークロードの需要に基づいてレプリカを自動的にスケーリングできます。

### ノード間でレプリカをスケジュールする
<a name="_schedule_replicas_across_nodes"></a>

複数のレプリカを実行することは、すべてのレプリカが同じノードで実行されていて、ノードが使用できなくなった場合にはあまり役に立ちません。ポッドアンチアフィニティまたはポッドトポロジの分散制約を使用して、デプロイのレプリカを複数のワーカーノードに分散することを検討してください。

複数の AZs で実行することで、一般的なアプリケーションの信頼性をさらに向上させることができます。

#### Pod アンチアフィニティルールの使用
<a name="_using_pod_anti_affinity_rules"></a>

以下のマニフェストは、ポッドを別々のノードと AZ に配置することを **Kubernetes スケジューラに指示します。 AZs 個別のノードや AZ は必要ありません。そうすると、各 AZ でポッドが実行されると、Kubernetes はポッドをスケジュールできなくなります。アプリケーションに必要なレプリカが 3 つしかない場合は、 `requiredDuringSchedulingIgnoredDuringExecution`に を使用できます。Kubernetes `topologyKey: topology.kubernetes.io/zone`スケジューラは同じ AZ で 2 つのポッドをスケジュールしません。

```
apiVersion: apps/v1
kind: Deployment
metadata:
  name: spread-host-az
  labels:
    app: web-server
spec:
  replicas: 4
  selector:
    matchLabels:
      app: web-server
  template:
    metadata:
      labels:
        app: web-server
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - web-server
              topologyKey: topology.kubernetes.io/zone
            weight: 100
          - podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - web-server
              topologyKey: kubernetes.io/hostname
            weight: 99
      containers:
      - name: web-app
        image: nginx:1.16-alpine
```

#### ポッドトポロジの分散制約の使用
<a name="_using_pod_topology_spread_constraints"></a>

ポッドのアンチアフィニティルールと同様に、ポッドトポロジの分散制約により、ホストや AZs などのさまざまな障害 (またはトポロジ) ドメインでアプリケーションを使用できるようになります。このアプローチは、異なるトポロジドメインのそれぞれに複数のレプリカを配置することで、耐障害性と可用性を確保しようとする場合に非常に効果的です。一方、ポッドのアンチアフィニティルールは、互いにアンチアフィニティを持つポッドが反発効果を持つため、トポロジドメインに 1 つのレプリカがある場合に簡単に結果を生成できます。このような場合、専用ノード上の 1 つのレプリカは耐障害性には適していません。また、 リソースの適切な使用にも適していません。トポロジの分散制約を使用すると、スケジューラがトポロジドメイン全体に適用しようとするスプレッドまたはディストリビューションをより細かく制御できます。このアプローチで使用する重要なプロパティを以下に示します。

1. `maxSkew` は、トポロジドメイン間でモノが不均等になる最大ポイントを制御または決定するために使用します。たとえば、アプリケーションに 10 個のレプリカがあり、3 つの AZs にデプロイされている場合、均等に分散することはできませんが、分散の不均等さに影響を与えることができます。この場合、 は 1～10 の範囲で指定`maxSkew`できます。値 1 は、 のようなスプレッド`4,3,3`、`3,4,3`または 3 つの AZs `3,3,4`にまたがるスプレッドになる可能性があることを意味します。対照的に、値が 10 の場合、 のようなスプレッド`10,0,0`、`0,10,0`または 3 つの AZs `0,0,10`にまたがるスプレッドになる可能性があります。

1. `topologyKey` はノードラベルの 1 つのキーであり、ポッドディストリビューションに使用するトポロジドメインのタイプを定義します。たとえば、ゾーンスプレッドには次のキーと値のペアがあります。

   ```
   topologyKey: "topology.kubernetes.io/zone"
   ```

1. `whenUnsatisfiable` プロパティは、必要な制約が満たされない場合にスケジューラがどのように応答するかを決定するために使用されます。

1. `labelSelector` は、指定した制約に従ってポッドを配置する場所を決定するときにスケジューラがポッドを認識できるように、一致するポッドを見つけるために使用されます。

上記の他に、[Kubernetes ドキュメント](https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/)でさらに詳しく読むことができるフィールドがあります。

**ポッドトポロジーが 3 つの AZs**  
 ![\[Pod topology spread constraints across 3 AZs\]](http://docs.aws.amazon.com/ja_jp/eks/latest/best-practices/images/reliability/pod-topology-spread-constraints.jpg) 

```
apiVersion: apps/v1
kind: Deployment
metadata:
  name: spread-host-az
  labels:
    app: web-server
spec:
  replicas: 10
  selector:
    matchLabels:
      app: web-server
  template:
    metadata:
      labels:
        app: web-server
    spec:
      topologySpreadConstraints:
      - maxSkew: 1
        topologyKey: "topology.kubernetes.io/zone"
        whenUnsatisfiable: ScheduleAnyway
        labelSelector:
          matchLabels:
            app: express-test
      containers:
      - name: web-app
        image: nginx:1.16-alpine
```

### Kubernetes メトリクスサーバーを実行する
<a name="_run_kubernetes_metrics_server"></a>

Kubernetes [メトリクスサーバー](https://github.com/kubernetes-sigs/metrics-server)をインストールして、アプリケーションのスケーリングに役立てます。[HPA](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/) や [VPA](https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler) などの Kubernetes Autoscaler アドオンは、アプリケーションのメトリクスを追跡してスケーリングする必要があります。metrics-server は、スケーリングの決定に使用できるリソースメトリクスを収集します。メトリクスは kubelets から収集され、[Metrics API 形式で](https://github.com/kubernetes/metrics)提供されます。

メトリクスサーバーはデータを保持せず、モニタリングソリューションではありません。その目的は、CPU とメモリの使用状況メトリクスを他のシステムに公開することです。アプリケーションの状態を経時的に追跡する場合は、Prometheus や Amazon CloudWatch などのモニタリングツールが必要です。

[EKS ドキュメント](https://docs.aws.amazon.com/eks/latest/userguide/metrics-server.html)に従って、EKS クラスターに metrics-server をインストールします。

## 水平ポッドオートスケーラー (HPA)
<a name="_horizontal_pod_autoscaler_hpa"></a>

HPA は、需要に応じてアプリケーションを自動的にスケーリングし、ピークトラフィック中に顧客に影響を与えないようにできます。これは、リソースメトリクスを提供する APIsする Kubernetes のコントロールループとして実装されます。

HPA は、次の APIs からメトリクスを取得できます。1. Resource Metrics API `metrics.k8s.io` とも呼ばれる — ポッド 2 の CPU とメモリの使用量を提供します。 `custom.metrics.k8s.io`— Prometheus などの他のメトリクスコレクターからのメトリクスを提供します。これらのメトリクスは Kubernetes クラスター**の内部**にあります。3。 `external.metrics.k8s.io`— Kubernetes クラスターの**外部**にあるメトリクス (SQS キューの深さ、ELB レイテンシーなど) を提供します。

これらの 3 つの APIs のいずれかを使用して、アプリケーションをスケールするための メトリクスを指定する必要があります。

### カスタムメトリクスまたは外部メトリクスに基づくアプリケーションのスケーリング
<a name="_scaling_applications_based_on_custom_or_external_metrics"></a>

カスタムメトリクスまたは外部メトリクスを使用して、CPU またはメモリ使用率以外のメトリクスでアプリケーションをスケーリングできます。[カスタムメトリクス](https://github.com/kubernetes-sigs/custom-metrics-apiserver) API サーバーは、HPA がアプリケーションの自動スケーリングに使用できる `custom-metrics.k8s.io` API を提供します。

[Prometheus Adapter for Kubernetes Metrics APIs](https://github.com/directxman12/k8s-prometheus-adapter) を使用して Prometheus からメトリクスを収集し、HPA で を使用できます。この場合、Prometheus アダプターは Prometheus メトリクスを [Metrics API 形式で](https://github.com/kubernetes/metrics/blob/master/pkg/apis/metrics/types.go)公開します。

Prometheus Adapter をデプロイしたら、kubectl を使用してカスタムメトリクスをクエリできます。 `kubectl get —raw /apis/custom.metrics.k8s.io/v1beta1/`

外部メトリクスは、名前が示すように、Horizontal Pod Autoscaler に Kubernetes クラスターの外部にあるメトリクスを使用してデプロイをスケールする機能を提供します。たとえば、バッチ処理ワークロードでは、SQS キューで処理中のジョブの数に基づいてレプリカの数をスケールするのが一般的です。

Kubernetes ワークロードをオートスケーリングするには、KEDA (Kubernetes Event-driven Autoscaling) を使用できます。これは、多数のカスタムイベントに基づいてコンテナスケーリングを駆動できるオープンソースプロジェクトです。この [AWS ブログ](https://aws.amazon.com/blogs/mt/autoscaling-kubernetes-workloads-with-keda-using-amazon-managed-service-for-prometheus-metrics/)では、Amazon Managed Service for Prometheus for Kubernetes ワークロードの自動スケーリングを使用する方法について説明します。

## 垂直ポッドオートスケーラー (VPA)
<a name="_vertical_pod_autoscaler_vpa"></a>

VPA は、アプリケーションの「適切なサイズ」に役立つように、Pod の CPU とメモリの予約を自動的に調整します。リソース割り当てを増やすことで実行される垂直スケーリングが必要なアプリケーションの場合、[VPA](https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler) を使用してポッドレプリカを自動的にスケーリングしたり、スケーリングに関する推奨事項を提供したりできます。

VPA の現在の実装では Pod にインプレース調整が実行されないため、VPA でスケーリングする必要がある場合、アプリケーションは一時的に使用できなくなる可能性があります。代わりに、スケーリングが必要な Pod を再作成します。

 [EKS ドキュメント](https://docs.aws.amazon.com/eks/latest/userguide/vertical-pod-autoscaler.html)には、VPA を設定するためのチュートリアルが含まれています。

 [Fairwinds Goldilocks ](https://github.com/FairwindsOps/goldilocks/)プロジェクトは、CPU およびメモリのリクエストと制限に関する VPA レコメンデーションを視覚化するためのダッシュボードを提供します。VPA 更新モードでは、VPA の推奨事項に基づいて Pod を自動スケーリングできます。

## アプリケーションの更新
<a name="_updating_applications"></a>

最新のアプリケーションには、高い安定性と可用性を備えた迅速なイノベーションが必要です。Kubernetes は、顧客を中断することなくアプリケーションを継続的に更新するためのツールを提供します。

可用性を犠牲にすることなく変更を迅速にデプロイできるようにするベストプラクティスをいくつか見てみましょう。

### ロールバックを実行するメカニズムがある
<a name="_have_a_mechanism_to_perform_rollbacks"></a>

元に戻すボタンがあると、災害を回避できます。本番環境クラスターを更新する前に、別の下位環境 (テスト環境または開発環境) でデプロイをテストするのがベストプラクティスです。CI/CD パイプラインを使用すると、デプロイの自動化とテストに役立ちます。継続的デプロイパイプラインを使用すると、アップグレードに欠陥が発生した場合に、古いバージョンにすばやく戻ることができます。

デプロイを使用して、実行中のアプリケーションを更新できます。これは通常、コンテナイメージを更新することによって行われます。`kubectl` を使用して、次のようなデプロイを更新できます。

```
kubectl --record deployment.apps/nginx-deployment set image nginx-deployment nginx=nginx:1.16.1
```

`--record` 引数はデプロイの変更を記録し、ロールバックを実行する必要がある場合に役立ちます。 は、クラスター内のデプロイに記録された変更`kubectl rollout history deployment`を表示します。を使用して変更をロールバックできます`kubectl rollout undo deployment <DEPLOYMENT_NAME>`。

デフォルトでは、ポッドの再作成を必要とするデプロイを更新すると、デプロイは[ローリング更新](https://kubernetes.io/docs/tutorials/kubernetes-basics/update/update-intro/)を実行します。つまり、Kubernetes はデプロイで実行中のポッドの一部のみを更新し、すべてのポッドを一度に更新するわけではありません。Kubernetes が `RollingUpdateStrategy`プロパティを使用してローリング更新を実行する方法を制御できます。

デプロイの*ローリング更新*を実行するときは、 [https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#max-unavailable](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#max-unavailable)プロパティを使用して、更新中に使用できないポッドの最大数を指定できます。Deployment の `Max Surge`プロパティを使用すると、必要な数のポッドに対して作成できるポッドの最大数を設定できます。

ロールアウトが顧客`max unavailable`を混乱させないように調整することを検討してください。例えば、Kubernetes `max unavailable`はデフォルトで 25% を設定します。つまり、100 個のポッドがある場合、ロールアウト中にアクティブに動作しているポッドは 75 個のみです。アプリケーションで最低 80 個の Pod が必要な場合は、このロールアウトが中断される可能性があります。代わりに、 を 20% `max unavailable`に設定して、ロールアウト全体で少なくとも 80 個の機能ポッドがあることを確認できます。

### ブルー/グリーンデプロイを使用する
<a name="_use_bluegreen_deployments"></a>

変更には本質的にリスクが伴いますが、元に戻すことができない変更は致命的になる可能性があります。*ロールバック*を通じて時間を効果的に戻すことができる手順を変更すると、機能強化と実験の安全性が向上します。ブルー/グリーンデプロイでは、問題が発生した場合に変更をすばやく取り消す方法があります。このデプロイ戦略では、新しいバージョンの環境を作成します。この環境は、更新されるアプリケーションの最新バージョンと同じです。新しい環境がプロビジョニングされると、トラフィックは新しい環境にルーティングされます。新しいバージョンがエラーを発生させずに必要な結果を生成する場合、古い環境は終了します。それ以外の場合、トラフィックは古いバージョンに復元されます。

Kubernetes でブルー/グリーンデプロイを実行するには、既存のバージョンのデプロイと同じ新しいデプロイを作成します。新しいデプロイのポッドがエラーなしで実行されていることを確認したら、アプリケーションのポッドにトラフィックをルーティングする サービスの`selector`仕様を変更することで、新しいデプロイへのトラフィックの送信を開始できます。

[Flux](https://fluxcd.io)、[Jenkins](https://www.jenkins.io)、["](https://spinnaker.io) などの多くの継続的統合ツールを使用すると、ブルー/グリーンデプロイを自動化できます。AWS Containers ブログには、AWS Load Balancer Controller を使用したチュートリアルが含まれています。[AWS Load Balancer Controller を使用したブルー/グリーンデプロイ、Canary デプロイ、A/B テスト](https://aws.amazon.com/blogs/containers/using-aws-load-balancer-controller-for-blue-green-deployment-canary-deployment-and-a-b-testing/) 

### Canary デプロイを使用する
<a name="_use_canary_deployments"></a>

Canary デプロイは、変更からリスクを大幅に排除できる Blue/Green デプロイのバリアントです。このデプロイ戦略では、古いデプロイと並行してポッド数が少ない新しいデプロイを作成し、トラフィックのごく一部を新しいデプロイに振り向けます。メトリクスが、新しいバージョンのパフォーマンスが既存のバージョンと同じかそれ以上であることを示している場合は、新しいデプロイへのトラフィックを徐々に増やし、すべてのトラフィックが新しいデプロイに転送されるまでスケールアップします。問題が発生した場合は、すべてのトラフィックを古いデプロイにルーティングし、新しいデプロイへのトラフィックの送信を停止できます。

Kubernetes には Canary デプロイを実行するネイティブな方法はありませんが、[Istio](https://docs.flagger.app/tutorials/istio-progressive-delivery) で [Flagger](https://github.com/weaveworks/flagger) などのツールを使用できます。

## ヘルスチェックと自己修復
<a name="_health_checks_and_self_healing"></a>

バグのないソフトウェアはありませんが、Kubernetes はソフトウェア障害の影響を最小限に抑えるのに役立ちます。以前は、アプリケーションがクラッシュした場合、アプリケーションを手動で再起動して状況を修復する必要がありました。Kubernetes を使用すると、ポッド内のソフトウェア障害を検出し、新しいレプリカに自動的に置き換えることができます。Kubernetes を使用すると、アプリケーションの状態をモニタリングし、異常なインスタンスを自動的に置き換えることができます。

Kubernetes は 3 [種類のヘルスチェック](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/)をサポートしています。

1. Liveness プローブ

1. スタートアッププローブ (Kubernetes バージョン 1.16 以降でサポート)

1. 準備状況プローブ

 Kubernetes エージェントである [Kubelet](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/) は、上記のすべてのチェックを実行する責任があります。Kubelet は Pod の状態を 3 つの方法で確認できます。kubelet は、Pod のコンテナ内でシェルコマンドを実行するか、コンテナに HTTP GET リクエストを送信するか、指定されたポートで TCP ソケットを開くことができます。

コンテナ内でシェルスクリプトを実行する `exec`ベースのプローブを選択した場合は、`timeoutSeconds`値の有効期限が切れ*る前に*シェルコマンドが終了していることを確認します。そうしないと、ノードに`<defunct>`プロセスが発生し、ノードに障害が発生します。

## 推奨事項
<a name="_recommendations_2"></a>

### Liveness Probe を使用して異常なポッドを削除する
<a name="_use_liveness_probe_to_remove_unhealthy_pods"></a>

Liveness プローブは、プロセスが実行され続けるがアプリケーションが応答しなくなる*デッドロック*状態を検出できます。たとえば、ポート 80 でリッスンするウェブサービスを実行している場合、Pod のポート 80 で HTTP GET リクエストを送信するように Liveness プローブを設定できます。Kubelet は定期的に GET リクエストを Pod に送信し、レスポンスを期待します。Pod が 200～399 の間に応答した場合、kubelet は Pod が正常であると見なします。そうしないと、Pod は異常としてマークされます。Pod がヘルスチェックに継続的に失敗した場合、kubelet はそれを終了します。

を使用して`initialDelaySeconds`、最初のプローブを遅延させることができます。

Liveness Probe を使用する場合は、Kubernetes がすべての Pod を置き換えようとし、アプリケーションがオフラインになるため、すべての Pod が同時に Liveness Probe に失敗する状況でアプリケーションが実行されないようにしてください。さらに、Kubernetes は引き続き Liveness Probes にも失敗する新しい Pod を作成し、コントロールプレーンに不要な負荷をかけます。外部データベースなど、Pod の外部にある要素に依存するように Liveness Probe を設定しないでください。つまり、応答しない external-to-your-Pod データベースは、Pod が Liveness Probes に失敗しないようにする必要があります。

Sandor Szücs の投稿[「LIVENESS PROBES ARE DANGEROUS](https://srcco.de/posts/kubernetes-liveness-probes-are-dangerous.html)」では、プローブの設定ミスによって発生する可能性のある問題について説明しています。

### 起動に時間がかかるアプリケーションに Startup Probe を使用する
<a name="_use_startup_probe_for_applications_that_take_longer_to_start"></a>

アプリの起動にさらに時間が必要な場合は、Startup Probe を使用して Liveness and Readiness Probe を遅延させることができます。たとえば、データベースからキャッシュをハイドレートする必要がある Java アプリケーションは、完全に機能するまでに最大 2 分かかる場合があります。Liveness または Readiness Probe が完全に機能するまでは失敗する可能性があります。Startup Probe を設定すると、Liveness または Readiness Probe が実行される前に Java アプリが*正常*になります。

Startup Probe が成功するまで、他のすべてのプローブは無効になります。Kubernetes がアプリケーションの起動を待機する最大時間を定義できます。最大設定時間が経過しても Pod が起動プローブに失敗した場合、Pod は終了し、新しい Pod が作成されます。

Startup Probe は Liveness Probe に似ています。失敗すると、Pod が再作成されます。Ricardo A. が記事[「Fantastic Probes and How To Configure Them](https://medium.com/swlh/fantastic-probes-and-how-to-configure-them-fef7e030bd2f)」で説明しているように、アプリケーションの起動時間が予測できない場合には、スタートアッププローブを使用する必要があります。アプリケーションの起動に 10 秒かかることがわかっている場合は、`initialDelaySeconds`代わりに で Liveness/Readiness Probe を使用する必要があります。

### Readiness Probe を使用して部分的な利用不能を検出する
<a name="_use_readiness_probe_to_detect_partial_unavailability"></a>

Liveness プローブは、Pod を終了 (したがってアプリを再起動) して解決されたアプリの障害を検出しますが、Readiness Probe はアプリが*一時的に*使用できない可能性のある状態を検出します。このような状況では、アプリが一時的に応答しなくなることがありますが、このオペレーションが完了すると再び正常であることが予想されます。

たとえば、強力なディスク I/O オペレーション中に、アプリケーションが一時的にリクエストを処理できない場合があります。ここでは、アプリケーションの Pod を終了することは解決策ではありません。同時に、Pod に送信される追加のリクエストが失敗する可能性があります。

Readiness Probe を使用すると、アプリの一時的な使用不能を検出し、再び機能するまで Pod へのリクエストの送信を停止できます。*障害によって Pod が再作成される Liveness Probe とは異なり、Readiness Probe が失敗すると、Pod は Kubernetes Service からトラフィックを受信しません*。準備プローブが成功すると、Pod はサービスからのトラフィックの受信を再開します。

Liveness Probe と同様に、Pod の外部にあるリソース (データベースなど) に依存する Readiness Probe を設定しないでください。設定の不十分な準備状況によってアプリケーションが機能しなくなるシナリオを次に示します。アプリケーションのデータベースに到達できない場合に Pod の準備状況プローブが失敗すると、同じヘルスチェック基準を共有するため、他の Pod レプリカも同時に失敗します。この方法でプローブを設定すると、データベースが使用できないたびに Pod の準備プローブが失敗し、Kubernetes は*すべての* Pod へのトラフィックの送信を停止します。

Readiness Probes を使用する副作用は、デプロイの更新にかかる時間を短縮できることです。準備プローブが成功しない限り、新しいレプリカはトラフィックを受信しません。それまでは、古いレプリカは引き続きトラフィックを受信します。



## 中断への対応
<a name="_dealing_with_disruptions"></a>

Pod の有効期間は限られています。長時間稼働している Pod がある場合でも、Pod が正常に終了することを確認するのが賢明です。アップグレード戦略によっては、Kubernetes クラスターのアップグレードで新しいワーカーノードの作成が必要になる場合があります。そのため、すべての Pod を新しいノードで再作成する必要があります。適切な終了処理と Pod Disruption Budgets を使用すると、Pod が古いノードから削除され、新しいノードで再作成されるため、サービスの中断を回避できます。

ワーカーノードをアップグレードする推奨方法は、新しいワーカーノードを作成し、古いノードを終了することです。ワーカーノードを終了する前に、`drain`終了する必要があります。ワーカーノードがドレインされると、そのすべてのポッドは*安全に*エビクションされます。ここでのキーワードは安全です。ワーカーのポッドが削除されると、単に`SIGKILL`シグナルが送信されるわけではありません。代わりに、削除されるポッド内の各コンテナのメインプロセス (PID 1) に`SIGTERM`シグナルが送信されます。`SIGTERM` シグナルが送信されると、Kubernetes は`SIGKILL`シグナルが送信される前にプロセスに時間 (猶予期間) を与えます。この猶予期間はデフォルトで 30 秒です。デフォルトを上書きするには、kubectl の `grace-period`フラグを使用するか、Podspec `terminationGracePeriodSeconds`で宣言します。

 `kubectl delete pod <pod name> —grace-period=<seconds>` 

通常、メインプロセスに PID 1 がないコンテナがあります。Python ベースのサンプルコンテナを考えてみましょう。

```
$ kubectl exec python-app -it ps
 PID USER TIME COMMAND
 1   root 0:00 {script.sh} /bin/sh ./script.sh
 5   root 0:00 python app.py
```

この例では、シェルスクリプトは `SIGTERM`を受け取ります。この例では Python アプリケーションであるメインプロセスは`SIGTERM`シグナルを取得しません。Pod が終了すると、Python アプリケーションは突然強制終了されます。これは、コンテナ[https://docs.docker.com/engine/reference/builder/#entrypoint](https://docs.docker.com/engine/reference/builder/#entrypoint)の を変更して Python アプリケーションを起動することで修正できます。または、[dumb-init](https://github.com/Yelp/dumb-init) などのツールを使用して、アプリケーションがシグナルを処理できるようにすることもできます。

[コンテナフック](https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks)を使用して、コンテナの開始または停止時にスクリプトまたは HTTP リクエストを実行することもできます。`PreStop` フックアクションは、コンテナが`SIGTERM`シグナルを受信する前に実行され、このシグナルが送信される前に完了する必要があります。`terminationGracePeriodSeconds` 値は、`SIGTERM`シグナルが送信されたときではなく、`PreStop`フックアクションの実行が開始されたときから適用されます。

## 推奨事項
<a name="_recommendations_3"></a>

### Pod Disruption Budgets で重要なワークロードを保護する
<a name="_protect_critical_workload_with_pod_disruption_budgets"></a>

アプリケーションのレプリカ数が宣言されたしきい値を下回った場合、Pod Disruption Budget または PDB は一時的に削除プロセスを停止できます。使用可能なレプリカの数がしきい値を超えると、削除プロセスは続行されます。PDB を使用して、 `minAvailable`とレプリカ`maxUnavailable`の数を宣言できます。たとえば、アプリのコピーを少なくとも 3 つ使用できるようにする場合は、PDB を作成できます。

```
apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
  name: my-svc-pdb
spec:
  minAvailable: 3
  selector:
    matchLabels:
      app: my-svc
```

上記の PDB ポリシーは、3 つ以上のレプリカが使用可能になるまでエビクションプロセスを停止するように Kubernetes に指示します。ノードドレイニングは を尊重します`PodDisruptionBudgets`。EKS マネージド型ノードグループのアップグレード中、[ノードは 15 分のタイムアウトでドレインされます](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-update-behavior.html)。15 分後、更新が強制されない場合 (オプションは EKS コンソールでローリング更新と呼ばれます）、更新は失敗します。更新を強制すると、ポッドは削除されます。

セルフマネージド型ノードの場合、[AWS Node Termination Handler](https://github.com/aws/aws-node-termination-handler) などのツールを使用して、EC2 [メンテナンスイベントや EC2 スポットの中断などEC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-instances-status-check_sched.html)2 インスタンスが使用できなくなる可能性のあるイベントに Kubernetes コントロールプレーンが適切に応答するようにすることもできます。 [EC2 ](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-interruptions.html) Kubernetes API を使用してノードをコーディングし、新しい Pod がスケジュールされていないことを確認してからドレインし、実行中の Pod を終了します。

Pod anti-affinity を使用して、異なるノードでデプロイの Pod をスケジュールし、ノードのアップグレード中の PDB 関連の遅延を回避できます。

### カオスエンジニアリングを実践する
<a name="_practice_chaos_engineering"></a>

カオスエンジニアリングは、本番環境の乱れに耐えられるシステムの能力の信頼性を構築するために、分散システムで実験する分野です。

ブログで Dominik Tornow は、[Kubernetes が「ユーザーがシステムの望ましい状態の表現をシステムに提供する](https://medium.com/@dominik.tornow/the-mechanics-of-kubernetes-ac8112eaa302)*」宣言システムであることを説明しています。次に、システムは現在の状態と望ましい状態を考慮して、現在の状態から望ましい状態に移行するコマンドのシーケンスを決定します。* 「�� つまり、Kubernetes は常に*目的の状態*を保存し、システムが逸脱すると、Kubernetes は状態を復元するアクションを実行します。たとえば、ワーカーノードが使用できなくなった場合、Kubernetes はポッドを別のワーカーノードに再スケジュールします。同様に、`replica`クラッシュした場合、[Deployment Contoller](https://kubernetes.io/docs/concepts/architecture/controller/#design) は新しい を作成します`replica`。このようにして、Kubernetes コントローラーは障害を自動的に修正します。

[Gremlin](https://www.gremlin.com) などのカオスエンジニアリングツールは、Kubernetes クラスターの耐障害性をテストし、単一障害点を特定するのに役立ちます。クラスター (およびそれ以降) に人為的カオスを導入するツールは、システムの弱点を発見し、ボトルネックや設定ミスを特定し、制御された環境で問題を修正する機会を与える可能性があります。カオスエンジニアリングの哲学は、予期しないダウンタイムを最小限に抑えるために、意図的にモノを破壊し、インフラストラクチャをストレステストすることを提唱しています。

### Service Mesh を使用する
<a name="_use_a_service_mesh"></a>

サービスメッシュを使用して、アプリケーションの耐障害性を向上させることができます。サービスメッシュにより、service-to-service通信が可能になり、マイクロサービスネットワークのオブザーバビリティが向上します。ほとんどのサービスメッシュ製品は、アプリケーションのネットワークトラフィックを傍受して検査する各サービスと一緒に小さなネットワークプロキシを実行することで機能します。アプリケーションを変更せずに、アプリケーションをメッシュに配置することができます。サービスプロキシの組み込み機能を使用すると、ネットワーク統計の生成、アクセスログの作成、分散トレースのアウトバウンドリクエストへの HTTP ヘッダーの追加を行うことができます。

サービスメッシュは、自動リクエストの再試行、タイムアウト、サーキットブレーク、レート制限などの機能により、マイクロサービスの耐障害性を高めるのに役立ちます。

複数のクラスターを操作する場合は、サービスメッシュを使用して、クラスター間のservice-to-service通信を有効にできます。

### サービスメッシュ
<a name="_service_meshes"></a>
+  [Istio](https://istio.io) 
+  [LinkerD](http://linkerd.io) 
+  [コンサル](https://www.consul.io) 



## オブザーバビリティ
<a name="_observability"></a>

オブザーバビリティは、モニタリング、ログ記録、トレースを含む包括的な用語です。マイクロサービスベースのアプリケーションは、本質的に分散されます。単一のシステムのモニタリングで十分なモノリシックアプリケーションとは異なり、分散アプリケーションアーキテクチャでは、各コンポーネントのパフォーマンスをモニタリングする必要があります。クラスターレベルのモニタリング、ログ記録、分散トレースシステムを使用して、顧客を混乱させる前にクラスター内の問題を特定できます。

トラブルシューティングとモニタリング用の Kubernetes 組み込みツールは限られています。metrics-server はリソースメトリクスを収集してメモリに保存しますが、保持しません。kubectl を使用して Pod のログを表示できますが、Kubernetes は自動的にログを保持しません。また、分散トレースの実装は、アプリケーションコードレベルまたはサービスメッシュを使用して行われます。

Kubernetes の拡張性はここにあります。Kubernetes を使用すると、任意の一元的なモニタリング、ログ記録、トレースソリューションを導入できます。

## 推奨事項
<a name="_recommendations_4"></a>

### アプリケーションをモニタリングする
<a name="_monitor_your_applications"></a>

最新のアプリケーションでモニタリングする必要があるメトリクスの数は継続的に増加しています。これは、お客様の課題の解決に集中できるように、アプリケーションを自動的に追跡する方法がある場合に役立ちます。[Prometheus](https://prometheus.io) や [CloudWatch Container Insights](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/ContainerInsights.html) などのクラスター全体のモニタリングツールは、クラスターとワークロードをモニタリングし、問題が発生した場合、または問題が発生する前にシグナルを提供できます。

モニタリングツールを使用すると、運用チームがサブスクライブできるアラートを作成できます。イベントのアラームをアクティブ化するルールを検討してください。イベントが悪化すると、停止したり、アプリケーションのパフォーマンスに影響を与えたりする可能性があります。

モニタリングすべきメトリクスが不明な場合は、次の方法からヒントを得ることができます。
+  [RED メソッド](https://www.weave.works/blog/a-practical-guide-from-instrumenting-code-to-specifying-alerts-with-the-red-method)。リクエスト、エラー、期間を表します。
+  [USE メソッド](http://www.brendangregg.com/usemethod.html)。使用率、飽和度、エラーを表します。

Sysdig の記事 [Kubernetes でのアラートのベストプラクティス](https://sysdig.com/blog/alerting-kubernetes/)には、アプリケーションの可用性に影響を与える可能性のあるコンポーネントの包括的なリストが含まれています。

### Prometheus クライアントライブラリを使用してアプリケーションメトリクスを公開する
<a name="_use_prometheus_client_library_to_expose_application_metrics"></a>

アプリケーションの状態をモニタリングし、標準メトリクスを集約することに加えて、[Prometheus クライアントライブラリ](https://prometheus.io/docs/instrumenting/clientlibs/)を使用してアプリケーション固有のカスタムメトリクスを公開し、アプリケーションのオブザーバビリティを向上させることもできます。

### 一元的なログ記録ツールを使用してログを収集し、保持する
<a name="_use_centralized_logging_tools_to_collect_and_persist_logs"></a>

EKS でのログ記録は、コントロールプレーンログとアプリケーションログの 2 つのカテゴリに分類されます。EKS コントロールプレーンのログ記録は、コントロールプレーンからアカウントの CloudWatch Logs に直接監査ログと診断ログを提供します。アプリケーションログは、クラスター内で実行されている Pod によって生成されるログです。アプリケーションログには、ビジネスロジックアプリケーションと CoreDNS、Cluster Autoscaler、Prometheus などの Kubernetes システムコンポーネントを実行する Pod によって生成されたログが含まれます。

 [EKS は 5 種類のコントロールプレーンログ](https://docs.aws.amazon.com/eks/latest/userguide/control-plane-logs.html)を提供します。

1. Kubernetes API サーバーコンポーネントログ

1. 監査 

1. オーセンティケーター

1. コントローラーマネージャー

1. スケジューラー

コントローラーマネージャーとスケジューラのログは、ボトルネックやエラーなどのコントロールプレーンの問題の診断に役立ちます。デフォルトでは、EKS コントロールプレーンログは CloudWatch Logs に送信されません。コントロールプレーンのログ記録を有効にし、アカウント内のクラスターごとにキャプチャする EKS コントロールプレーンログのタイプを選択できます。

アプリケーションログを収集するには、[Fluent Bit](http://fluentbit.io)、[Fluentd](https://www.fluentd.org)、[CloudWatch Container Insights](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/deploy-container-insights-EKS.html) などのログアグリゲータツールをクラスターにインストールする必要があります。

Kubernetes ログアグリゲータツールは DaemonSets として実行され、ノードからコンテナログをスクレイプします。その後、アプリケーションログは一元管理された保存先に送信されます。例えば、CloudWatch Container Insights は Fluent Bit または Fluentd のいずれかを使用してログを収集し、CloudWatch Logs に送信して保存できます。Fluent Bit と Fluentd は、Elasticsearch や InfluxDB などの多くの一般的なログ分析システムをサポートしているため、Fluent ビットまたは Fluentd のログ設定を変更することで、ログのストレージバックエンドを変更できます。

### 分散トレースシステムを使用してボトルネックを特定する
<a name="_use_a_distributed_tracing_system_to_identify_bottlenecks"></a>

一般的な最新のアプリケーションには、ネットワーク上に分散されたコンポーネントがあり、その信頼性は、アプリケーションを構成する各コンポーネントが適切に機能するかどうかによって異なります。分散トレースソリューションを使用して、リクエストのフローとシステムの通信方法を理解できます。トレースは、アプリケーションネットワークにボトルネックが存在する場所を示し、カスケード障害を引き起こす可能性のある問題を防ぐことができます。

アプリケーションにトレースを実装するには、2 つのオプションがあります。共有ライブラリを使用してコードレベルで分散トレースを実装するか、サービスメッシュを使用できます。

コードレベルでトレースを実装すると、不利になる可能性があります。この方法では、コードを変更する必要があります。Polyglot アプリケーションがある場合、これはさらに複雑になります。また、サービス全体でさらに別のライブラリを維持する責任もあります。

[LinkerD](http://linkerd.io) や [Istio](http://istio.io) などの Service Mesh を使用して、アプリケーションコードへの最小限の変更でアプリケーションに分散トレースを実装できます。サービスメッシュを使用して、メトリクスの生成、ログ記録、トレースを標準化できます。

[AWS X-Ray](https://aws.amazon.com/xray/) などのトレースツールである [Jaeger](https://www.jaegertracing.io) は、共有ライブラリとサービスメッシュの両方の実装をサポートしています。

(共有ライブラリとサービスメッシュ) の両方の実装をサポートする [AWS X-Ray](https://aws.amazon.com/xray/) や [Jaeger](https://www.jaegertracing.io) などのトレースツールを使用することを検討してください。これにより、後でサービスメッシュを採用する場合にツールを切り替える必要がなくなります。

# EKS コントロールプレーン
<a name="control-plane"></a>

**ヒント**  
 Amazon EKS [https://aws-experience.com/emea/smb/events/series/get-hands-on-with-amazon-eks?trk=4a9b4147-2490-4c63-bc9f-f8a84b122c8c&sc_channel=el](https://aws-experience.com/emea/smb/events/series/get-hands-on-with-amazon-eks?trk=4a9b4147-2490-4c63-bc9f-f8a84b122c8c&sc_channel=el)ワークショップを通じてベストプラクティスをご覧ください。

Amazon Elastic Kubernetes Service (EKS) は、独自の Kubernetes コントロールプレーンまたはワーカーノードをインストール、運用、保守することなく、AWS で Kubernetes を簡単に実行できるようにするマネージド Kubernetes サービスです。アップストリーム Kubernetes を実行し、Kubernetes 準拠の認定を受けています。この準拠により、EC2 またはオンプレミスにインストールできるオープンソースのコミュニティバージョンと同様に、EKS は Kubernetes APIs を確実にサポートします。アップストリーム Kubernetes で実行されている既存のアプリケーションは、Amazon EKS と互換性があります。

EKS は、Kubernetes コントロールプレーンノードの可用性とスケーラビリティを自動的に管理し、異常なコントロールプレーンノードを自動的に置き換えます。

## EKS アーキテクチャ
<a name="reliability_cpeks_architecture"></a>

EKS アーキテクチャは、Kubernetes コントロールプレーンの可用性と耐久性を損なう可能性のある単一障害点を排除するように設計されています。

EKS によって管理される Kubernetes コントロールプレーンは、EKS マネージド VPC 内で実行されます。EKS コントロールプレーンは、Kubernetes API サーバーノード etcd クラスターで構成されます。API サーバー、スケジューラなどのコンポーネントを実行し、Auto Scaling グループで`kube-controller-manager`実行する Kubernetes API サーバーノード。EKS は、AWS リージョン内の個別のアベイラビリティーゾーン (AZs) で最低 2 つの API サーバーノードを実行します。同様に、耐久性のために、 etcd サーバーノードは 3 つの AZs にまたがる Auto Scaling グループでも実行されます。EKS は各 AZ で NAT ゲートウェイを実行し、API サーバーと etcd サーバーはプライベートサブネットで実行されます。このアーキテクチャにより、単一の AZ のイベントが EKS クラスターの可用性に影響を与えなくなります。

新しいクラスターを作成すると、Amazon EKS はクラスターとの通信に使用するマネージド Kubernetes API サーバーの高可用性エンドポイントを作成します ( などのツールを使用`kubectl`)。マネージドエンドポイントは NLB を使用して Kubernetes API サーバーの負荷分散を行います。EKS は、ワーカーノードとの通信を容易にするために、異なる AZs に 2 つの [ENI](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-eni.html) もプロビジョニングします。

EKS データプレーンネットワーク接続

![\[接続\]](http://docs.aws.amazon.com/ja_jp/eks/latest/best-practices/images/reliability/eks-data-plane-connectivity.jpeg)


[Kubernetes クラスターの API サーバーがパブリックインターネット (パブリックエンドポイントを使用) から到達可能か](https://docs.aws.amazon.com/eks/latest/userguide/cluster-endpoint.html)、VPC (EKS マネージド ENIs) または両方から到達可能かを設定できます。

ユーザーとワーカーノードがパブリックエンドポイントまたは EKS マネージド ENI を使用して API サーバーに接続するかどうかにかかわらず、接続には冗長パスがあります。

## 推奨事項
<a name="cp-recs"></a>

以下の推奨事項を確認してください。

## コントロールプレーンメトリクスのモニタリング
<a name="reliability_cpmonitor_control_plane_metrics"></a>

Kubernetes API メトリクスをモニタリングすると、コントロールプレーンのパフォーマンスに関するインサイトが得られ、問題を特定できます。コントロールプレーンに異常があると、クラスター内で実行されているワークロードの可用性が損なわれる可能性があります。例えば、コントローラーの書き込みが不十分な場合、API サーバーが過負荷になり、アプリケーションの可用性に影響する可能性があります。

Kubernetes は`/metrics`、エンドポイントでコントロールプレーンメトリクスを公開します。

を使用して公開されているメトリクスを表示できます`kubectl`。

```
kubectl get --raw /metrics
```

これらのメトリクスは [Prometheus テキスト形式で](https://github.com/prometheus/docs/blob/master/content/docs/instrumenting/exposition_formats.md)表されます。

Prometheus を使用して、これらのメトリクスを収集して保存できます。2020 年 5 月、CloudWatch は CloudWatch Container Insights で Prometheus メトリクスをモニタリングするためのサポートを追加しました。そのため、Amazon CloudWatch を使用して EKS コントロールプレーンをモニタリングすることもできます。[新しい Prometheus スクレイプターゲットの追加のチュートリアル: Prometheus KPI サーバーメトリクス](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/ContainerInsights-Prometheus-Setup-configure.html#ContainerInsights-Prometheus-Setup-new-exporters)を使用してメトリクスを収集し、CloudWatch ダッシュボードを作成してクラスターのコントロールプレーンをモニタリングできます。

Kubernetes API サーバーのメトリクスは、[こちら](https://github.com/kubernetes/apiserver/blob/master/pkg/endpoints/metrics/metrics.go)で確認できます。たとえば、 `apiserver_request_duration_seconds` は API リクエストの実行にかかる時間を指定できます。

これらのコントロールプレーンメトリクスのモニタリングを検討してください。

### API サーバー
<a name="reliability_cpapi_server"></a>


| メトリクス | 説明 | 
| --- | --- | 
|   `apiserver_request_total`   |  verb、dry run 値、グループ、バージョン、リソース、スコープ、コンポーネント、HTTP レスポンスコードごとに分割された apiserver リクエストのカウンター。  | 
|   `apiserver_request_duration_seconds*`   |  動詞、ドライラン値、グループ、バージョン、リソース、サブリソース、スコープ、コンポーネントごとのレスポンスレイテンシーヒストグラムを秒単位で表示します。  | 
|   `apiserver_admission_controller_admission_duration_seconds*`   |  名前で識別され、オペレーションと API リソースとタイプ (検証または承認) ごとに分割された、秒単位のアドミッションコントローラーレイテンシーヒストグラム。  | 
|   `apiserver_admission_webhook_rejection_count`   |  アドミッションウェブフック拒否の数。名前、オペレーション、拒否コード、タイプ (検証または承認）、エラータイプ (calling\$1webhook\$1error、apiserver\$1internal\$1error、no\$1error) で識別されます  | 
|   `rest_client_request_duration_seconds*`   |  レイテンシーヒストグラムを秒単位でリクエストします。動詞と URL で分類されます。  | 
|   `rest_client_requests_total`   |  ステータスコード、メソッド、ホストでパーティション分割された、HTTP リクエスト数。  | 
+ ヒストグラムメトリクスには、\$1bucket、\$1sum、および \$1count サフィックスが含まれます。

### etcd
<a name="reliability_cpetcd"></a>


| メトリクス | 説明 | 
| --- | --- | 
|   `etcd_request_duration_seconds*`   |  オペレーションとオブジェクトタイプごとに秒単位の Etcd リクエストレイテンシーヒストグラム。  | 
|   `apiserver_storage_db_total_size_in_bytes` または `apiserver_storage_size_bytes` (EKS v1.28 以降)  |  Etcd データベースのサイズ。  | 
+ ヒストグラムメトリクスには、\$1bucket、\$1sum、および \$1count サフィックスが含まれます。

[Kubernetes モニタリング概要ダッシュボード](https://grafana.com/grafana/dashboards/14623)を使用して、Kubernetes API サーバーのリクエストとレイテンシーおよび etcd レイテンシーメトリクスを視覚化およびモニタリングすることを検討してください。

**重要**  
データベースのサイズ制限を超えると、 etcd はスペースなしアラームを発行し、それ以降の書き込みリクエストの実行を停止します。つまり、クラスターは読み取り専用になり、新しいポッドの作成、デプロイのスケーリングなどのオブジェクトを変更するすべてのリクエストは、クラスターの API サーバーによって拒否されます。

## クラスター認証
<a name="reliability_cpcluster_authentication"></a>

EKS は現在、[ベアラー/サービスアカウントトークン](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#service-account-tokens)と[ウェブフックトークン認証を使用する IAM 認証の 2 種類の認証](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#webhook-token-authentication)をサポートしています。ユーザーが Kubernetes API を呼び出すと、ウェブフックはリクエストに含まれる認証トークンを IAM に渡します。トークンは、ベース 64 署名付き URL であり、AWS コマンドラインインターフェイス ([AWS CLI) ](https://aws.amazon.com/cli/)によって生成されます。

EKS クラスターを作成する IAM ユーザーまたはロールは、クラスターへのフルアクセスを自動的に取得します。EKS クラスターへのアクセスを管理するには、[aws-auth 設定マップ](https://docs.aws.amazon.com/eks/latest/userguide/add-user-role.html)を編集します。

`aws-auth` 設定マップを誤って設定し、クラスターにアクセスできなくなった場合でも、クラスター作成者のユーザーまたはロールを使用して EKS クラスターにアクセスできます。

万一、AWS リージョンで IAM サービスを使用できない場合は、Kubernetes サービスアカウントのベアラートークンを使用してクラスターを管理することもできます。

クラスター内のすべてのアクションを実行できる`super-admin`アカウントを作成します。

```
kubectl -n kube-system create serviceaccount super-admin
```

スーパー管理者クラスター管理者ロールを付与するロールバインディングを作成します。

```
kubectl create clusterrolebinding super-admin-rb --clusterrole=cluster-admin --serviceaccount=kube-system:super-admin
```

サービスアカウントのシークレットを取得します。

```
SECRET_NAME=`kubectl -n kube-system get serviceaccount/super-admin -o jsonpath='{.secrets[0].name}'`
```

シークレットに関連付けられたトークンを取得します。

```
TOKEN=`kubectl -n kube-system get secret $SECRET_NAME -o jsonpath='{.data.token}'| base64 --decode`
```

サービスアカウントとトークンを に追加します`kubeconfig`。

```
kubectl config set-credentials super-admin --token=$TOKEN
```

スーパー管理者アカウントを使用するには`kubeconfig`、 で現在のコンテキストを設定します。

```
kubectl config set-context --current --user=super-admin
```

最終`kubeconfig`版は次のようになります。

```
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data:<REDACTED>
    server: https://<CLUSTER>.gr7.us-west-2.eks.amazonaws.com
  name: arn:aws:eks:us-west-2:<account number>:cluster/<cluster name>
contexts:
- context:
    cluster: arn:aws:eks:us-west-2:<account number>:cluster/<cluster name>
    user: super-admin
  name: arn:aws:eks:us-west-2:<account number>:cluster/<cluster name>
current-context: arn:aws:eks:us-west-2:<account number>:cluster/<cluster name>
kind: Config
preferences: {}
users:
#- name: arn:aws:eks:us-west-2:<account number>:cluster/<cluster name>
#  user:
#    exec:
#      apiVersion: client.authentication.k8s.io/v1beta1
#      args:
#      - --region
#      - us-west-2
#      - eks
#      - get-token
#      - --cluster-name
#      - <<cluster name>>
#      command: aws
#      env: null
- name: super-admin
  user:
    token: <<super-admin sa's secret>>
```

## アドミッションウェブフック
<a name="reliability_cpadmission_webhooks"></a>

Kubernetes には、アドミッションウェブフック[の検証とアドミッションウェブフックの変更の 2 種類のアドミッションウェブフックがあります](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers)。これにより、ユーザーは kubernetes API を拡張し、API によって受け入れられる前にオブジェクトを検証または変更できます。これらのウェブフックの設定が悪いと、クラスターの重要なオペレーションがブロックされ、EKS コントロールプレーンが不安定になる可能性があります。

クラスターの重要なオペレーションに影響を与えないようにするには、次のように「キャッチオール」ウェブフックを設定しないでください。

```
- name: "pod-policy.example.com"
  rules:
  - apiGroups:   ["*"]
    apiVersions: ["*"]
    operations:  ["*"]
    resources:   ["*"]
    scope: "*"
```

または、タイムアウトが 30 秒未満のフェイルオープンポリシーがウェブフックにあることを確認し、ウェブフックが使用できない場合にクラスターの重要なワークロードが損なわれないようにします。

### 安全でないポッドをブロックする `sysctls`
<a name="reliability_cpblock_pods_with_unsafe_sysctls"></a>

 `Sysctl` は、ランタイム中にユーザーがカーネルパラメータを変更できるようにする Linux ユーティリティです。これらのカーネルパラメータは、ネットワーク、ファイルシステム、仮想メモリ、プロセス管理など、オペレーティングシステムの動作のさまざまな側面を制御します。

Kubernetes では、ポッドに`sysctl`プロファイルを割り当てることができます。Kubernetes は、安全と安全でない`systcls`に分類されます。Safe `sysctls`はコンテナまたは Pod に名前空間化され、設定してもノードまたはノード自体の他の Pod には影響しません。これとは対照的に、安全でない sysctl は、他の Pod を中断したり、ノードを不安定にしたりする可能性があるため、デフォルトでは無効になっています。

安全でない `sysctls`はデフォルトで無効になっているため、kubelet は安全でない`sysctl`プロファイルを持つ Pod を作成しません。このような Pod を作成すると、スケジューラはそのような Pod をノードに繰り返し割り当てますが、ノードは起動に失敗します。この無限ループは最終的にクラスターコントロールプレーンに負荷をかけ、クラスターを不安定にします。

[OPA Gatekeeper](https://github.com/open-policy-agent/gatekeeper-library/blob/377cb915dba2db10702c25ef1ee374b4aa8d347a/src/pod-security-policy/forbidden-sysctls/constraint.tmpl) または [Kyverno](https://kyverno.io/policies/pod-security/baseline/restrict-sysctls/restrict-sysctls/) を使用して、安全でない のポッドを拒否することを検討してください`sysctls`。

## クラスターのアップグレードの処理
<a name="reliability_cphandling_cluster_upgrades"></a>

2021 年 4 月以降、Kubernetes リリースサイクルは年間 4 つのリリース (四半期に 1 回) から年間 3 つのリリースに変更されました。新しいマイナーバージョン (1.**21** や 1.**22** など) が約 [15 週間ごとに](https://kubernetes.io/blog/2021/07/20/new-kubernetes-release-cadence/#what-s-changing-and-when)リリースされます。Kubernetes 1.19 以降、各マイナーバージョンは、最初のリリースから約 12 か月間サポートされています。Kubernetes v1.28 の登場により、コントロールプレーンとワーカーノード間の互換性スキューが n-2 から n-3 のマイナーバージョンに拡張されました。詳細については、[「クラスターアップグレードのベストプラクティス](cluster-upgrades.md)」を参照してください。

## クラスターエンドポイントの接続
<a name="reliability_cpcluster_endpoint_connectivity"></a>

Amazon EKS (Elastic Kubernetes Service) を使用する場合、Kubernetes コントロールプレーンのスケーリングやパッチ適用などのイベント中に接続のタイムアウトやエラーが発生することがあります。これらのイベントにより、kube-apiserver インスタンスが置き換えられ、FQDN を解決するときに異なる IP アドレスが返される可能性があります。このドキュメントでは、Kubernetes API コンシューマーが信頼性の高い接続を維持するためのベストプラクティスの概要を説明します。

**注記**  
これらのベストプラクティスを実装するには、新しい DNS 再解決および再試行戦略を効果的に処理するために、クライアント設定またはスクリプトの更新が必要になる場合があります。

主な問題は、DNS クライアント側のキャッシュと、パブリックエンドポイントの場合は*パブリック NLB、プライベートエンドポイントの場合は X-ENI* という EKS エンドポイントの古い IP アドレスの可能性です。kube-apiserver インスタンスが置き換えられると、完全修飾ドメイン名 (FQDN) が新しい IP アドレスに解決される場合があります。ただし、AWS マネージド Route 53 ゾーンで 60 秒に設定された DNS 有効期限 (TTL) 設定により、クライアントは短期間、古い IP アドレスを引き続き使用できます。

これらの問題を軽減するには、Kubernetes API コンシューマー (kubectl、CI/CD パイプライン、カスタムアプリケーションなど) に次のベストプラクティスを実装する必要があります。
+ DNS 再解決の実装
+ バックオフとジッターを使用して再試行を実装します。例えば、[この記事の「障害発生](https://aws.amazon.com/builders-library/timeouts-retries-and-backoff-with-jitter/)」を参照してください。
+ クライアントタイムアウトを実装します。長時間実行されるリクエストがアプリケーションをブロックしないように、適切なタイムアウトを設定します。一部の Kubernetes クライアントライブラリ、特に OpenAPI ジェネレーターによって生成されたライブラリでは、カスタムタイムアウトを簡単に設定できない場合があります。
  + kubectl を使用した例 1:

  ```
    kubectl get pods --request-timeout 10s # default: no timeout
  ```
  + Python を使用した例 2: [Kubernetes クライアントが \$1request\$1timeout パラメータを提供する](https://github.com/kubernetes-client/python/blob/release-30.0/kubernetes/client/api_client.py#L120) 

これらのベストプラクティスを実装することで、Kubernetes API を操作する際のアプリケーションの信頼性と耐障害性を大幅に向上させることができます。これらの実装は、特にシミュレートされた障害条件下で徹底的にテストし、実際のスケーリングまたはパッチ適用イベント中に期待どおりに動作することを確認してください。

## 大規模なクラスターの実行
<a name="reliability_cprunning_large_clusters"></a>

EKS は、コントロールプレーンインスタンスの負荷をアクティブにモニタリングし、自動的にスケーリングして、高いパフォーマンスを確保します。ただし、大規模なクラスターを実行する場合は、Kubernetes 内の潜在的なパフォーマンスの問題と制限、および AWS サービスのクォータを考慮する必要があります。
+ [ProjectCalico チームによって実行されたテスト](https://www.projectcalico.org/comparing-kube-proxy-modes-iptables-or-ipvs/)に従って、 `kube-proxy`を `iptables` モードで使用した場合、1000 を超えるサービスを持つクラスターでネットワークレイテンシーが発生する可能性があります。解決策は、 [`ipvs``kube-proxy`モードでの実行](ipvs.md)に切り替えることです。
+ また、CNI が Pod の IP アドレスをリクエストする必要がある場合や、新しい [EC2 インスタンスを頻繁に作成する必要がある場合に、EC2 API リクエストのスロットリング](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/throttling.html)が発生することがあります。 EC2 IP アドレスをキャッシュするように CNI を設定することで、EC2 API の呼び出しを減らすことができます。より大きな EC2 インスタンスタイプを使用して EC2 スケーリングイベントを減らすことができます。

## その他のリソース:
<a name="reliability_cpadditional_resources"></a>
+  [Amazon EKS ワーカーノードのクラスターネットワークの説明を解除する](https://aws.amazon.com/blogs/containers/de-mystifying-cluster-networking-for-amazon-eks-worker-nodes/) 
+  [Amazon EKS クラスターエンドポイントのアクセスコントロール](https://docs.aws.amazon.com/eks/latest/userguide/cluster-endpoint.html) 
+  [AWS re:Invent 2019: Amazon EKS under the hood (CON421-R1)](https://www.youtube.com/watch?v=7vxDWDD2YnM) 

# EKS データプレーン
<a name="data-plane"></a>

高可用性で回復力のあるアプリケーションを運用するには、高可用性で回復力のあるデータプレーンが必要です。伸縮自在なデータプレーンにより、Kubernetes はアプリケーションを自動的にスケーリングして修復できます。回復力のあるデータプレーンは、2 つ以上のワーカーノードで構成され、ワークロードに合わせて増減し、障害から自動的に回復できます。

EKS を使用するワーカーノードには、[EKS Auto Mode マネージドノード](https://docs.aws.amazon.com/eks/latest/userguide/automode.html)、[EC2 インスタンス、Fargate ](https://docs.aws.amazon.com/eks/latest/userguide/worker.html)の複数の選択肢があります。 [https://docs.aws.amazon.com/eks/latest/userguide/fargate.html](https://docs.aws.amazon.com/eks/latest/userguide/fargate.html)

EKS Auto Mode は、回復力のあるデータプレーンへの最も簡単なパスを提供します。Auto Mode は、Kubernetes クラスターの AWS 管理をクラスター自体を超えて拡張し、AWS がワークロードのスムーズな運用を可能にするインフラストラクチャをセットアップおよび管理できるようにします。Auto Mode は、Kubernetes が Pod をスケーリングするにつれてデータプレーンを自動的にスケールアップまたはスケールダウンし、クラスター内のノードが現在実行中のワークロードに対して適切かつ費用対効果の高いサイズになるように継続的に機能します。

EC2 インスタンスを選択した場合は、ワーカーノードを自分で管理することも、[EKS マネージド型ノードグループ](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html)を使用することもできます。Auto Mode、マネージドワーカーノード、セルフマネージドワーカーノード、Fargate を組み合わせたクラスターを持つことができます。

Fargate は、分離されたコンピューティング環境で各 Pod を実行します。Fargate で実行されている各 Pod は、独自のワーカーノードを取得します。Fargate は、Kubernetes がポッドをスケーリングするときにデータプレーンを自動的にスケーリングします。[水平ポッドオートスケーラー](https://docs.aws.amazon.com/eks/latest/userguide/horizontal-pod-autoscaler.html)を使用して、データプレーンとワークロードの両方をスケーリングできます。

EC2 ワーカーノードをスケールする (AWS によって自動的に実行される EKS Auto Mode を使用しない場合) 推奨方法は、[Karpenter](https://karpenter.sh/)、[Kubernetes Cluster Autoscaler](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md)、または [EC2 Auto Scaling グループ](https://docs.aws.amazon.com/autoscaling/ec2/userguide/AutoScalingGroup.html)を使用することです。

## 推奨事項
<a name="_recommendations"></a>

### ワーカーノードとワークロードを複数の AZs
<a name="_spread_worker_nodes_and_workloads_across_multiple_azs"></a>

ワーカーノードと Pod を複数の AZ で実行することで、個々の AZs の障害からワークロードを保護できます。ノードを作成するサブネットを使用して、ワーカーノードが作成される AZ を制御できます。

AZs 間でポッドを分散するための推奨方法は、[ポッドにトポロジースプレッド制約を使用することです](https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/#spread-constraints-for-pods)。EKS Auto Mode や Karpenter などの自動スケーリング機能はトポロジの分散制約を認識し、制約を満たすために正しい AZs でノードを自動的に起動します。

以下のデプロイでは、可能な場合はポッドを AZs に分散し、そうでない場合はとにかくポッドを実行できるようにします。

```
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-server
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web-server
  template:
    metadata:
      labels:
        app: web-server
    spec:
      topologySpreadConstraints:
        - maxSkew: 1
          whenUnsatisfiable: ScheduleAnyway
          topologyKey: topology.kubernetes.io/zone
          labelSelector:
            matchLabels:
              app: web-server
      containers:
      - name: web-app
        image: nginx
        resources:
          requests:
            cpu: 1
```

**注記**  
 `kube-scheduler` は、それらのラベルを持つノードを介してのみトポロジドメインを認識します。上記のデプロイが 1 つのゾーンにのみノードを持つクラスターにデプロイされている場合、すべてのポッド`kube-scheduler`は他のゾーンを認識していないため、それらのノードでスケジュールされます。このトポロジがスケジューラで期待どおりに機能するには、ノードがすべてのゾーンに既に存在している必要があります。トポロジスプレッド制約の `minDomains`プロパティは、この問題を回避するために実行されているノードがある場合でも、対象となるドメインの数をスケジューラに通知するために使用されます。

**警告**  
`whenUnsatisfiable` を に設定すると`DoNotSchedule`、トポロジの分散制約が満たされない場合、ポッドはスケジュールできなくなります。これは、トポロジの分散制約に違反するのではなく、ポッドを実行しない方が望ましい場合にのみ設定する必要があります。

古いバージョンの Kubernetes では、ポッドアンチアフィニティルールを使用して、複数の AZs 間でポッドをスケジュールできます。以下のマニフェストは、個別の AZ でポッドをスケジュールすることを **Kubernetes スケジューラに指示します。 AZs

```
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-server
  labels:
    app: web-server
spec:
  replicas: 4
  selector:
    matchLabels:
      app: web-server
  template:
    metadata:
      labels:
        app: web-server
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - web-server
              topologyKey: failure-domain.beta.kubernetes.io/zone
            weight: 100
      containers:
      - name: web-app
        image: nginx
```

**警告**  
異なる AZs 間でポッドをスケジュールする必要はありません。そうしないと、デプロイ内のポッドの数が AZs の数を超えることはありません。

### EBS ボリュームを使用するときに、各 AZ でノードを起動する機能を確保する
<a name="_ensure_ability_to_launch_nodes_in_each_az_when_using_ebs_volumes"></a>

Amazon EBS を使用して永続ボリュームを提供する場合は、ポッドと関連する EBS ボリュームが同じ AZ にあることを確認する必要があります。ポッドは、別の AZ にある EBS-backed 永続ボリュームにアクセスできません。Kubernetes ス[ケジューラは、ノード上のラベルからワーカーノードが配置されている AZ を認識し](https://kubernetes.io/docs/reference/kubernetes-api/labels-annotations-taints/#topologykubernetesiozone)、ボリュームと同じ AZ に EBS ボリュームを必要とするポッドを常にスケジュールします。ただし、ボリュームが配置されている AZ にワーカーノードがない場合は、Pod をスケジュールできません。

EKS Auto Mode または Karpenter を使用する場合は、NodeClass が各 AZ のサブネットを選択することを確認する必要があります。マネージド型ノードグループを使用する場合は、各 AZ にノードグループがあることを確認する必要があります。

EBS ストレージ機能は EKS Auto Mode に組み込まれていますが、Karpenter または Managed Node Groups を使用している場合は[、EBS CSI ](https://docs.aws.amazon.com/eks/latest/userguide/ebs-csi.html)もインストールする必要があります。

### EKS Auto Mode を使用してワーカーノードを管理する
<a name="_use_eks_auto_mode_to_manage_worker_nodes"></a>

EKS Auto Mode は、運用上のオーバーヘッドを最小限に抑えながら、本番環境対応のクラスターを提供することで、EKS 管理を合理化します。Auto Mode は、クラスターで実行されている Pod に応じて、ノードの数をスケールアップまたはスケールダウンします。ノードはソフトウェアパッチと修正によって自動的に最新の状態に保たれ、更新は設定された [NodePool](https://docs.aws.amazon.com/eks/latest/userguide/create-node-pool.html#_disruption) 中断設定と Pod Disruption Budgets に従って実行されます。

### ノードモニタリングエージェントを実行する
<a name="_run_the_node_monitoring_agent"></a>

[Node Monitoring Agent](https://docs.aws.amazon.com/eks/latest/userguide/node-health.html) は、Kubernetes イベントを発行し、Node のステータス条件を更新することで、Node のヘルス問題を監視して対応します。Node Monitoring Agent は EKS Auto Mode ノードに含まれており、Auto Mode で管理されていないノードの EKS アドオンとしてインストールできます。

EKS Auto Mode、Managed Node Groups、Karpenter はすべて、Node Monitoring Agent によって報告された致命的なノード状態を検出し、それらの状態が発生したときにそれらのノードを自動的に修復できます。

### QoS の実装
<a name="_implement_qos"></a>

重要なアプリケーションの場合は、Pod のコンテナに `requests`=`limits` を定義することを検討してください。これにより、別の Pod がリソースをリクエストした場合にコンテナが強制終了されることはありません。

ベストプラクティスとして、すべてのコンテナに CPU とメモリの制限を実装することをお勧めします。これにより、コンテナがシステムリソースを誤って消費し、他のコロケーションプロセスの可用性に影響を与えることが防止されます。

### すべてのワークロードのリソースリクエスト/制限を設定およびサイズ設定する
<a name="_configure_and_size_resource_requestslimits_for_all_workloads"></a>

ワークロードのリソースリクエストと制限のサイズ設定には、いくつかの一般的なガイダンスを適用できます。
+ CPU のリソース制限を指定しないでください。制限がない場合、リクエストは[相対的な CPU 時間コンテナが取得する量の](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#how-pods-with-resource-limits-are-run)重みとして機能します。これにより、ワークロードは人為的な制限や飢餓なしに CPU 全体を使用できます。
+ CPU 以外のリソースの場合、 `requests`= `limits`を設定すると最も予測可能な動作が得られます。`requests`\$1= の場合`limits`、コンテナの [QOS](https://kubernetes.io/docs/tasks/configure-pod-container/quality-service-pod/#qos-classes) も保証済みからバースト可能に減るため、[ノードの圧力](https://kubernetes.io/docs/concepts/scheduling-eviction/node-pressure-eviction/)が発生した場合に削除される可能性が高くなります。
+ CPU 以外のリソースの場合、リクエストよりもはるかに大きい制限を指定しないでください。より大きいほど、 に対して設定`limits`され`requests`、ノードがオーバーコミットされる可能性が高くなり、ワークロードが中断される可能性が高くなります。
+ [Karpenter](https://aws.github.io/aws-eks-best-practices/karpenter/) や [Cluster AutoScaler](https://aws.github.io/aws-eks-best-practices/cluster-autoscaling/) などのノードの自動スケーリングソリューションを使用する場合、リクエストのサイズが正しいことが特に重要です。これらのツールは、ワークロードリクエストを調べて、プロビジョニングするノードの数とサイズを決定します。リクエストが小さすぎて制限が大きい場合、ノードに密集している場合、ワークロードが削除されたり、OOM が強制終了されたりすることがあります。

リソースリクエストの決定は難しい場合がありますが、[Vertical Pod Autoscaler](https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler) などのツールは、実行時にコンテナリソースの使用状況を観察することで、リクエストを「適切なサイズ」にするのに役立ちます。リクエストサイズの決定に役立つその他のツールは次のとおりです。
+  [ゴールドロック](https://github.com/FairwindsOps/goldilocks) 
+  [パーカ](https://www.parca.dev/) 
+  [Prodfiler](https://prodfiler.com/) 
+  [rsg](https://mhausenblas.info/right-size-guide/) 

### 名前空間のリソースクォータを設定する
<a name="_configure_resource_quotas_for_namespaces"></a>

名前空間は、複数のチームまたはプロジェクト間に分散された多くのユーザーがいる環境での使用を対象としています。これらは名前の範囲を提供し、複数のチーム、プロジェクト、ワークロード間でクラスターリソースを分割する方法です。名前空間のリソース消費の集計を制限できます。[https://kubernetes.io/docs/concepts/policy/resource-quotas/](https://kubernetes.io/docs/concepts/policy/resource-quotas/) オブジェクトは、名前空間で作成できるオブジェクトの数量をタイプ別に制限できます。また、そのプロジェクトのリソースによって消費される可能性のあるコンピューティングリソースの合計量も制限できます。特定の名前空間でリクエストできるストレージやコンピューティング (CPU およびメモリ) リソースの合計を制限できます。

CPU やメモリなどのコンピューティングリソースの名前空間でリソースクォータが有効になっている場合、ユーザーはその名前空間内のコンテナごとにリクエストまたは制限を指定する必要があります。

名前空間ごとにクォータを設定することを検討してください。を使用して`LimitRanges`、名前空間内のコンテナに事前設定された制限を自動的に適用することを検討してください。

### 名前空間内のコンテナリソースの使用を制限する
<a name="_limit_container_resource_usage_within_a_namespace"></a>

Resource Quotas は、名前空間で使用できるリソースの量を制限するのに役立ちます。[`LimitRange` オブジェクト](https://kubernetes.io/docs/concepts/policy/limit-range/)は、コンテナがリクエストできる最小リソースと最大リソースの実装に役立ちます。`LimitRange` を使用すると、コンテナのデフォルトのリクエストと制限を設定できます。これは、コンピューティングリソースの制限を設定することが組織内の標準プラクティスではない場合に役立ちます。名前が示すように、 `LimitRange`は名前空間内の Pod またはコンテナあたりのコンピューティングリソース使用量の最小値と最大値を適用できます。また、名前空間で PersistentVolumeClaim ごとに最小ストレージリクエストと最大ストレージリクエストを適用します。

を `LimitRange`と組み合わせて使用`ResourceQuota`して、コンテナおよび名前空間レベルで制限を適用することを検討してください。これらの制限を設定すると、コンテナまたは名前空間がクラスター内の他のテナントが使用するリソースに影響を与えなくなります。

### NodeLocal DNSCache を使用する
<a name="_use_nodelocal_dnscache"></a>

[NodeLocal DNSCache を実行することで、クラスター DNS ](https://kubernetes.io/docs/tasks/administer-cluster/nodelocaldns/)のパフォーマンスを向上させることができます。この機能は、クラスターノードで DNS キャッシュエージェントを DaemonSet として実行します。すべてのポッドは、`kube-dns`サービスを使用する代わりに、ノードで実行されている DNS キャッシュエージェントを使用して名前を解決します。この機能は EKS Auto Mode に自動的に含まれます。

### 自動スケーリング CoreDNS を設定する
<a name="_configure_auto_scaling_coredns"></a>

クラスター DNS のパフォーマンスを向上させるもう 1 つの方法は、[CoreDNS ポッドの組み込み自動スケーリング](https://docs.aws.amazon.com/eks/latest/userguide/coredns-autoscaling.html)を有効にすることです。

この機能は、ノード数や CPU コア数など、クラスターの状態を継続的にモニタリングします。この情報に基づいて、コントローラーは EKS クラスター内の CoreDNS デプロイのレプリカ数を動的に調整します。