翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。
EKS データプレーン
可用性と回復力の高いアプリケーションを運用するには、可用性と回復力の高いデータプレーンが必要です。伸縮自在なデータプレーンにより、Kubernetes はアプリケーションを自動的にスケーリングして修復できます。回復力のあるデータプレーンは、2 つ以上のワーカーノードで構成され、ワークロードに合わせて増減し、障害から自動的に回復できます。
EKS を使用するワーカーノードには、EC2 インスタンスと Fargate の 2 つの選択肢があります。 https://docs.aws.amazon.com/eks/latest/userguide/fargate.htmlEC2 インスタンスを選択した場合は、ワーカーノードを自分で管理することも、EKS マネージド型ノードグループを使用することもできます。マネージドワーカーノード、セルフマネージドワーカーノード、および Fargate を混在させたクラスターを持つことができます。
Fargate の EKS は、回復力のあるデータプレーンへの最も簡単なパスを提供します。Fargate は、分離されたコンピューティング環境で各 Pod を実行します。Fargate で実行されている各 Pod は、独自のワーカーノードを取得します。Fargate は、Kubernetes がポッドをスケーリングすると、データプレーンを自動的にスケーリングします。水平ポッドオートスケーラーを使用して、データプレーンとワークロードの両方をスケールできます。
EC2 ワーカーノードをスケーリングする推奨方法は、Kubernetes Cluster Autoscaler
レコメンデーション
EC2 Auto Scaling グループを使用してワーカーノードを作成する
ベストプラクティスは、個々の EC2 インスタンスを作成してクラスターに結合するのではなく、EC2 Auto Scaling グループを使用してワーカーノードを作成することです。Auto Scaling Groups は、終了または失敗したノードを自動的に置き換え、クラスターに常にワークロードを実行する容量があるようにします。
Kubernetes Cluster Autoscaler を使用してノードをスケールする
Cluster Autoscaler は、クラスターに十分なリソースがなく、別のワーカーノードを追加すると実行できないポッドがある場合に、データプレーンのサイズを調整します。Cluster Autoscaler は事後対応プロセスですが、クラスターの容量不足によりポッドが保留中状態になるまで待機します。このようなイベントが発生すると、EC2 インスタンスがクラスターに追加されます。クラスターの容量が不足するたびに、ワーカーノードが追加されるまで、新しいレプリカまたは新しいポッドは使用できなくなります (保留中状態)。この遅延は、データプレーンがワークロードの需要を満たすのに十分な速度でスケールできない場合に、アプリケーションの信頼性に影響を与える可能性があります。ワーカーノードが一貫して十分に活用されておらず、そのすべてのポッドを他のワーカーノードでスケジュールできる場合、Cluster Autoscaler はそれを終了します。
Cluster Autoscaler によるオーバープロビジョニングの設定
クラスター内のポッドがすでに保留中の場合、Cluster Autoscaler はデータプレーンのスケールアップをトリガーします。したがって、アプリケーションがより多くのレプリカを必要とする時間と、実際にレプリカが増えるまでに遅延が生じる可能性があります。この遅延の可能性に対処するオプションは、必要以上のレプリカを追加し、アプリケーションのレプリカの数を増やすことです。
Cluster Autoscaler が推奨するもう 1 つのパターンでは、一時停止ポッドと Priority Preemption 機能
複数の Auto Scaling グループでの Cluster Autoscaler の使用
--node-group-auto-discovery
フラグを有効にして Cluster Autoscaler を実行します。これにより、Cluster Autoscaler は、特定の定義されたタグを含むすべての Auto Scaling グループを検索し、マニフェストで各 Auto Scaling グループを定義および維持する必要がなくなります。
ローカルストレージでの Cluster Autoscaler の使用
デフォルトでは、Cluster Autoscaler はローカルストレージがアタッチされたポッドがデプロイされているノードをスケールダウンしません。Cluster Autoscaler がこれらのノードをスケールダウンできるようにするには、 --skip-nodes-with-local-storage
フラグを false に設定します。
ワーカーノードとワークロードを複数の AZs
ワーカーノードとポッドを複数の AZ で実行することで、個々の AZs の障害からワークロードを保護できます。ノードを作成するサブネットを使用して、ワーカーノードが作成される AZ を制御できます。
Kubernetes 1.18 以降を使用している場合、ポッドを 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
は他のゾーンを認識していないため、それらのノードでスケジュールされます。このトポロジがスケジューラで期待どおりに機能するには、ノードがすべてのゾーンに既に存在している必要があります。この問題は、Kubernetes 1.24 で機能ゲートを追加して解決MinDomainsInPodToplogySpread
この機能ゲートでは、スケジューラに対象ドメインの数を通知する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 の容量を確保する
Amazon EBS を使用して永続ボリュームを提供する場合は、ポッドと関連する EBS ボリュームが同じ AZ にあることを確認する必要があります。書き込み時に、EBS ボリュームは 1 つの AZ 内でのみ使用できます。ポッドは、別の AZ にある EBS-backed 永続ボリュームにアクセスできません。Kubernetes スケジューラは、ワーカーノードが配置されている AZ を認識
クラスターに必要な EBS ボリュームと同じ AZ でポッドをスケジュールするキャパシティを常に確保できるように、十分なキャパシティーを持つ AZ ごとに Auto Scaling グループを作成します。さらに、Cluster Autoscaler で--balance-similar-node-groups
この機能を有効にする必要があります。
EBS ボリュームを使用するアプリケーションを実行しているが、高可用性の要件がない場合、アプリケーションのデプロイを単一の AZ に制限できます。EKS では、ワーカーノードに AZ の名前を含むfailure-domain.beta.kubernetes.io/zone
ラベルが自動的に追加されます。ノードにアタッチされているラベルは、 を実行して確認できますkubectl get nodes --show-labels
。組み込みノードラベルの詳細については、こちらを参照してください
以下の例では、ポッドは AZ us-west-2c
でのみスケジュールされます。
apiVersion: v1
kind: Pod
metadata:
name: single-az-pod
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: failure-domain.beta.kubernetes.io/zone
operator: In
values:
- us-west-2c
containers:
- name: single-az-container
image: kubernetes/pause
永続ボリューム (EBS によってバックアップ) にも AZ の名前が自動的にラベル付けされます。永続ボリュームが属する AZ は、 を実行して確認できますkubectl get pv -L topology.ebs.csi.aws.com/zone
。ポッドが作成され、ボリュームをクレームすると、Kubernetes はボリュームと同じ AZ のノードでポッドをスケジュールします。
このシナリオを考えてみましょう。1 つのノードグループを持つ EKS クラスターがあります。このノードグループには、3 つの AZs。EBS-backed 永続ボリュームを使用するアプリケーションがあります。このアプリケーションと対応するボリュームを作成すると、その Pod は 3 つの AZs の最初の AZ に作成されます。その後、この Pod を実行するワーカーノードは異常になり、その後使用できなくなります。Cluster Autoscaler は、異常なノードを新しいワーカーノードに置き換えます。ただし、Auto Scaling グループは 3 つの AZs にまたがるため、新しいワーカーノードは 2 番目または 3 番目の AZ で起動される可能性がありますが、状況に応じて最初の AZ では起動されません。AZ に制約された EBS ボリュームは最初の AZ にのみ存在するが、その AZ で使用できるワーカーノードがないため、ポッドをスケジュールすることはできません。したがって、AZ ごとに 1 つのノードグループを作成する必要があります。そのため、他の AZ でスケジュールできないポッドを実行するには、常に十分な容量が必要です AZs 。
または、EFS
ノードモニタリングエージェントのノード問題を検出する
ワーカーノードの障害は、アプリケーションの可用性に影響を与える可能性があります。ノードモニタリングエージェントを使用して、ヘルスの問題を検出して表示できます。ノードの自動修復を有効にして、問題が検出されたときノードを自動的に置き換えることもできます。
ノードモニタリングエージェントは、すべての Amazon EKS Auto Mode クラスターの機能として用意されています。他のクラスタータイプでは、モニタリングエージェントを Amazon EKS アドオンとして追加できます。詳細については、「Amazon EKS ユーザーガイド」の「ノードの自動修復の有効化」および「ノードのヘルスの問題の調査」を参照してください。
システムと Kubernetes デーモンのリソースを予約する
オペレーティングシステムと Kubernetes デーモンのコンピューティングキャパシティを予約limits
宣言されていないポッドは、システムリソースを飽和させ、オペレーティングシステムプロセスと Kubernetes デーモン (kubelet
、コンテナランタイムなど) がシステムリソースのポッドと競合する状況にノードを配置する可能性があります。kubelet
フラグ--system-reserved
と を使用して--kube-reserved
、システムプロセス (udev
、 sshd
など) と Kubernetes デーモンのリソースをそれぞれ予約できます。
EKS 最適化 Linux AMI を使用する場合、CPU、メモリ、ストレージはデフォルトでシステムおよび Kubernetes デーモン用に予約されます。この AMI 起動に基づくワーカーノードの場合、EC2 ユーザーデータはbootstrap.sh
スクリプトKubeletConfiguration
ファイルに書き込まれます/etc/kubernetes/kubelet/kubelet-config.json
。
ノードでカスタムデーモンを実行し、デフォルトで予約されている CPU とメモリの量が不十分である場合、システムリソースの予約を増やす必要がある場合があります。
eksctl
は、システムデーモンと Kubernetes デーモンのリソース予約
QoS の実装
重要なアプリケーションでは、ポッド内のコンテナに requests
=limits
を定義することを検討してください。これにより、別の Pod がリソースをリクエストした場合にコンテナが強制終了されることはありません。
すべてのコンテナに CPU とメモリの制限を実装するのがベストプラクティスです。コンテナがシステムリソースを誤って消費して、他のコロケーションプロセスの可用性に影響を与えるのを防ぐためです。
すべてのワークロードのリソースリクエスト/制限を設定およびサイズ設定する
ワークロードのリソースリクエストと制限のサイズ設定には、いくつかの一般的なガイダンスを適用できます。
-
CPU のリソース制限を指定しないでください。制限がない場合、リクエストはコンテナが取得する相対的な CPU 時間の重み
として機能します。これにより、ワークロードは人為的な制限や飢餓なしに CPU 全体を使用できます。 -
CPU 以外のリソースの場合、
requests
=limits
を設定すると最も予測可能な動作が得られます。requests
!= の場合limits
、コンテナの QOSも保証済みからバースト可能に減少するため、ノードの圧力 が発生した場合に削除される可能性が高くなります。 -
CPU 以外のリソースの場合、リクエストよりもはるかに大きい制限を指定しないでください。より大きい
limits
は に対して設定されrequests
、ノードがオーバーコミットされる可能性が高くなり、ワークロードが中断される可能性が高くなります。 -
Karpenter
や Cluster AutoScaler などのノードの自動スケーリングソリューションを使用する場合、リクエストのサイズが正しいことが特に重要です。これらのツールは、ワークロードリクエストを調べて、プロビジョニングするノードの数とサイズを決定します。リクエストが小さすぎて制限が大きい場合、ワークロードがノードに密集している場合、ワークロードが削除されたり、OOM が強制終了されたりすることがあります。
リソースリクエストの決定は難しい場合がありますが、Vertical Pod Autoscaler
名前空間のリソースクォータを設定する
名前空間は、複数のチームまたはプロジェクト間に分散された多くのユーザーがいる環境での使用を対象としています。これらは名前の範囲を提供し、複数のチーム、プロジェクト、ワークロード間でクラスターリソースを分割する方法です。名前空間でリソースの消費を集計して制限できます。ResourceQuota
CPU やメモリなどのコンピューティングリソースの名前空間でリソースクォータが有効になっている場合、ユーザーはその名前空間内のコンテナごとにリクエストまたは制限を指定する必要があります。
名前空間ごとにクォータを設定することを検討してください。を使用してLimitRanges
、名前空間内のコンテナに事前設定された制限を自動的に適用することを検討してください。
名前空間内のコンテナリソースの使用を制限する
Resource Quotas は、名前空間で使用できるリソースの量を制限するのに役立ちます。LimitRange
オブジェクトLimitRange
を使用すると、コンテナのデフォルトのリクエストと制限を設定できます。これは、コンピューティングリソースの制限を設定することが組織内の標準プラクティスではない場合に役立ちます。名前が示すように、 LimitRange
は名前空間内の Pod またはコンテナあたりのコンピューティングリソース使用量の最小値と最大値を適用できます。また、名前空間で PersistentVolumeClaim ごとに最小ストレージリクエストと最大ストレージリクエストを適用します。
を LimitRange
と組み合わせて使用ResourceQuota
して、コンテナレベルと名前空間レベルで制限を適用することを検討してください。これらの制限を設定すると、コンテナまたは名前空間がクラスター内の他のテナントが使用するリソースに影響を与えなくなります。
CoreDNS
CoreDNS は、Kubernetes で名前解決とサービス検出機能を実行します。デフォルトでは EKS クラスターにインストールされます。相互運用性のために、Kubernetes Service for CoreDNS は kube-dnskube-system
名前空間のデプロイの一部として実行され、EKS ではデフォルトで、宣言されたリクエストと制限を持つ 2 つのレプリカを実行します。DNS クエリは、 kube-system
名前空間で実行される kube-dns
サービスに送信されます。
レコメンデーション
CoreDNS メトリクスのモニタリング
CoreDNS には Prometheus core_dns_response_rcode_count_total
)coredns_dns_request_duration_seconds_sum
、エラー (coredns_dns_responses_total
、NXDOMAIN、SERVFAIL、FormErr)、および CoreDNS Pod のメモリ消費量のモニタリングを特に検討する必要があります。
トラブルシューティングの目的で、kubectl を使用して CoreDNS ログを表示できます。
for p in $(kubectl get pods -n kube-system -l k8s-app=kube-dns -o jsonpath='{.items[*].metadata.name}'); do kubectl logs $p -n kube-system; done
NodeLocal DNSCache を使用する
NodeLocal DNSCache を実行することで、クラスター DNS kube-dns
サービスを使用する代わりに、ノードで実行されている DNS キャッシュエージェントを使用して名前を解決します。
CoreDNS の cluster-proportional-scaler を設定する
クラスター DNS のパフォーマンスを向上させるもう 1 つの方法は、クラスター内のノードと CPU コアの数に基づいて CoreDNS デプロイを自動的に水平スケーリング
ノードとノード内の CPU コアの集計は、CoreDNS をスケールできる 2 つのメトリクスです。両方のメトリクスを同時に使用できます。より大きなノードを使用する場合、CoreDNS スケーリングは CPU コアの数に基づきます。一方、より小さなノードを使用する場合、CoreDNS レプリカの数はデータプレーンの CPU コアによって異なります。比例オートスケーラーの設定は次のようになります。
linear: '{"coresPerReplica":256,"min":1,"nodesPerReplica":16}'
ノードグループで AMI を選択する
EKS は、セルフマネージド型ノードグループとマネージド型ノードグループの両方を作成するためにお客様が使用する最適化された EC2 AMIs を提供します。これらの AMIsは、サポートされているすべての Kubernetes バージョンについて、すべてのリージョンで公開されます。EKS は、CVEsまたはバグが検出されたときに、これらの AMIs を非推奨としてマークします。したがって、ノードグループの AMIsしている間は、非推奨の AMI を使用しないことをお勧めします。
非推奨AMIs は、以下のコマンドを使用して Ec2 describe-images api を使用してフィルタリングできます。
aws ec2 describe-images --image-id ami-0d551c4f633e7679c --no-include-deprecated
また、describe-image 出力にフィールドとして DeprecationTime が含まれているかどうかを確認することで、非推奨の AMI を認識することもできます。例:
aws ec2 describe-images --image-id ami-xxx --no-include-deprecated
{
"Images": [
{
"Architecture": "x86_64",
"CreationDate": "2022-07-13T15:54:06.000Z",
"ImageId": "ami-xxx",
"ImageLocation": "123456789012/eks_xxx",
"ImageType": "machine",
"Public": false,
"OwnerId": "123456789012",
"PlatformDetails": "Linux/UNIX",
"UsageOperation": "RunInstances",
"State": "available",
"BlockDeviceMappings": [
{
"DeviceName": "/dev/xvda",
"Ebs": {
"DeleteOnTermination": true,
"SnapshotId": "snap-0993a2fc4bbf4f7f4",
"VolumeSize": 20,
"VolumeType": "gp2",
"Encrypted": false
}
}
],
"Description": "EKS Kubernetes Worker AMI with AmazonLinux2 image, (k8s: 1.19.15, docker: 20.10.13-2.amzn2, containerd: 1.4.13-3.amzn2)",
"EnaSupport": true,
"Hypervisor": "xen",
"Name": "aws_eks_optimized_xxx",
"RootDeviceName": "/dev/xvda",
"RootDeviceType": "ebs",
"SriovNetSupport": "simple",
"VirtualizationType": "hvm",
"DeprecationTime": "2023-02-09T19:41:00.000Z"
}
]
}