

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

# 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) 