AWS EKSでKubernetesクラスターをマルチAZ構成で設計する方法|マネージドノードグループとVPC設計の実践

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)AWS(Amazon Linux) > AWS EKSでKubernetesクラスターをマルチAZ構成で設計する方法|マネージドノードグループとVPC設計の実践
「EKSのノードグループをマルチAZにするには、どう設定すればいいのか?」
AWSでEKS(Elastic Kubernetes Service)を本番運用しようとすると、避けて通れないのがこの問いです。

EKSのコントロールプレーン(APIサーバー・ etcd など)はAWSが3つのAZに自動で冗長化してくれます。しかしワーカーノード(データプレーン)は、ClusterConfig YAMLの設定を適切に書かないと1つのAZに偏ります。AWSの障害はAZ単位で発生するため、ノードが1つのAZに集中していると、そのAZが落ちた瞬間にPodが全滅し、サービスが停止します。

この記事では、eksctlを使ってEKSクラスターをマルチAZ構成で設計する実践手順を解説します。VPCサブネットの設計要件、ClusterConfig YAMLの書き方、ノードグループのAZ分散設定、そしてIRSA(IAM Roles for Service Accounts)にPodへの最小権限付与まで、実際の設定ファイルと出力例を交えながら紹介します。

この記事のポイント

・EKSのマルチAZ設計はノードグループのAZを3つに分散させることが基本
・eksctlのClusterConfig YAMLでVPC・ノードグループの設定を一括定義できる
・プライベートサブネットにはEKS用タグ(kubernetes.io/role/internal-elb: 1)の設定が必須
・PodへのAWS権限はIRSA(IAM Roles for Service Accounts)で最小権限を実現する


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

EKSのアーキテクチャ全体像(コントロールプレーンとデータプレーン)

EKSは「コントロールプレーン」と「データプレーン(ワーカーノード)」の2層構造です。

コントロールプレーンはKubernetesのAPIサーバー・ etcd ・スケジューラーをまとめたもので、AWSが複数のAZにまたがって完全マネージドで提供します。ユーザーはコントロールプレーンの管理を一切しなくてよいのが大きな特徴です。

データプレーン(ワーカーノード)はEC2インスタンス群で構成されます。ここはユーザーが設計・管理する責任範囲です。マルチAZ設計で設定すべきはこのデータプレーンです。

EKSのマルチAZ設計における基本的な構成要素は次の通りです。

マネージドノードグループ: AWSがEC2のライフサイクル(起動・停止・交換)を管理するノードグループ。3AZ分散が推奨
・VPC・サブネット: ノードを配置するプライベートサブネットを3AZに分けて作成する
・ALB Ingress Controller: ServiceのロードバランシングにALBを使う場合、複数AZのパブリックサブネットに展開される
・NATゲートウェイ: プライベートサブネットからのアウトバウンド通信を中継する。各AZに1台ずつ配置(HighlyAvailable設定)

VPCとサブネットの設計(EKS専用の要件)

EKSクラスターを作成する前に、VPCとサブネットの設計を固める必要があります。後から変更できない部分があるため、最初の設計が肌心です。

1. サブネット数とAZ

EKSのマルチAZ設計では、最低2つのAZに各 1つのサブネットが必要です。実務では3AZ(ap-northeast-1a / 1c / 1d)を推奨します。 1AZが落ちても残り2/3のノードで継続稼働できます。

ap-northeast-1bはAWS東京リージョンでEKSが利用できないアカウントが多いため、ap-northeast-1a / 1c / 1dを使うのが定番です。

サブネット構成は次の通りです。

パブリックサブネット(3つ): ALB・NATゲートウェイを配置する。インターネットゲートウェイ経由でルーティング
プライベートサブネット(3つ): ワーカーノードを配置する。インターネットに直接公開しない

2. サブネットタグの設定(必須)

EKSが適切なサブネットを自動選択できるよう、サブネットにタグを設定する必要があります。これを忘れると、Ingress ControllerがALBを作成できずにエラーになります。

パブリックサブネット(インターネット向けALB用)に設定するタグ:

# タグキー タグ値 kubernetes.io/cluster/prod-cluster shared kubernetes.io/role/elb 1

プライベートサブネット(ワーカーノード・Internal ALB用)に設定するタグ:

# タグキー タグ値 kubernetes.io/cluster/prod-cluster shared kubernetes.io/role/internal-elb 1

eksctlを使ってVPCを自動生成する場合、これらのタグが自動で付与されます。既存のVPCを利用する場合は手動で設定してください。

eksctlでクラスターを作成する手順

1. eksctlのインストール

eksctlはAWS公式のEKSクラスター管理CLIです。Amazon Linux 2023やRHEL 9系での導入手順を示します。

# GitHub公式リリースからバイナリを取得する ARCH=amd64 PLATFORM=$(uname -s)_$ARCH curl -sLO "https://github.com/eksctl-io/eksctl/releases/latest/download/eksctl_${PLATFORM}.tar.gz" tar -xzf eksctl_${PLATFORM}.tar.gz -C /tmp sudo mv /tmp/eksctl /usr/local/bin # バージョン確認 eksctl version

出力例:

0.192.0

2. ClusterConfig YAMLを作成する

eksctlにはCLIオプションの直接指定とYAML定義て2通りがあります。本番環境ではYAMLをGitリポジトリで管理することを強く推奨します。設定変更の履歴が残り、レビューを通せるためです。

以下のYAMLを cluster-config.yaml として保存します。

# cluster-config.yaml apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: prod-cluster region: ap-northeast-1 version: "1.29" vpc: cidr: "10.0.0.0/16" nat: gateway: HighlyAvailable # 各AZにNATゲートウェイを1台ずつ配置する managedNodeGroups: - name: ng-prod instanceType: t3.medium minSize: 3 maxSize: 9 desiredCapacity: 3 availabilityZones: # 3AZを明示的に指定する(省略すると偏るリスクがある) - ap-northeast-1a - ap-northeast-1c - ap-northeast-1d volumeSize: 30 volumeType: gp3 privateNetworking: true # ノードをプライベートサブネットに配置する iam: withAddonPolicies: autoScaler: true cloudWatch: true addons: - name: vpc-cni - name: coredns - name: kube-proxy

主要項目の説明:

vpc.nat.gateway: HighlyAvailable: 3AZそれぞれにNATゲートウェイを1台ずつ配置する。 1AZのNATが落ちても他AZへの影響がない
managedNodeGroups[].availabilityZones: 3AZを明示的に指定する。省略するとeksctlが任意に選ぶため、設計意図通りにならない場合がある
privateNetworking: true: ワーカーノードをプライベートサブネットに配置する。インターネットからの直接アクセスを遠断

3. クラスターを作成する(eksctl create cluster)

YAMLファイルを使ってクラスターを作成します。

eksctl create cluster -f cluster-config.yaml

クラスター作成には15分程度かかります。完了後、ノードの状態とAZ分散を確認します。

kubectl get nodes --label-columns topology.kubernetes.io/zone

出力例(3AZに1ノードずつ分散):

NAME STATUS ROLES AGE VERSION ZONE ip-10-0-97-xxx.ap-northeast-1.compute.internal Ready 5m v1.29.x ap-northeast-1a ip-10-0-130-xxx.ap-northeast-1.compute.internal Ready 5m v1.29.x ap-northeast-1c ip-10-0-162-xxx.ap-northeast-1.compute.internal Ready 5m v1.29.x ap-northeast-1d

Pod配置のAZ分散制御(topologySpreadConstraints)

ノードが3AZに分散されていても、PodがどのノードにスケジュールされるかはKubernetesのスケジューラーが判断します。重要なサービスは「Podを複数のAZに必ず分散させる」制約をかける必要があります。

topologySpreadConstraintsでPodのAZ分散を強制する

Kubernetes 1.19以降で安定版になったtopologySpreadConstraintsを使います。Deployment YAMLのspec.template.specに追加します。

# Deployment YAMLの抄粤(spec.template.spec に追加) topologySpreadConstraints: - maxSkew: 1 topologyKey: topology.kubernetes.io/zone whenUnsatisfiable: DoNotSchedule labelSelector: matchLabels: app: my-app

設定の意味:

maxSkew: 1: AZ間でのPod数の差を1以内に制限する
topologyKey: topology.kubernetes.io/zone: AZ単位でPodを分散させる
whenUnsatisfiable: DoNotSchedule: 制約を満たせない場合はPodをPendingにする(スケジュールしない)

AZ障害時の挙動を確認する

実際の障害を想定して、ノードをcordonし(スケジュール対象から外し)、Podが他のノードへフェイルオーバーされることをテスト環境で確認します。

# 1. ap-northeast-1a のノードをスケジュール対象から外す kubectl cordon ip-10-0-97-xxx.ap-northeast-1.compute.internal # 2. ノードの状態を確認する kubectl get nodes # NAME STATUS ROLES # ip-10-0-97-xxx.ap-northeast-1.compute.internal Ready,SchedulingDisabled # ip-10-0-130-xxx.ap-northeast-1.compute.internal Ready # ip-10-0-162-xxx.ap-northeast-1.compute.internal Ready # 3. テスト完了後、cordonを解除する kubectl uncordon ip-10-0-97-xxx.ap-northeast-1.compute.internal

cordonしただけではPodが自動で移動しないことに注意してください。Podの再スケジュールを強制させるには kubectl drain を実行するか、Deploymentのレプリカ数を一時的に増減させるPodを再作成する方法があります。

IRSAでPodにAWS権限を最小権限で付与する

KubernetesのPodからS3やSQSなどのAWSサービスにアクセスする場合、古い方法ではEC2インスタンスプロファイルにIAMポリシーを付与していました。しかしこの方法はノード上の全Podが同じ権限を持つため、最小権限の原則に反します。

EKSではIRSA(IAM Roles for Service Accounts)を使い、Pod単位でIAMロールを紐付ける設計を推奨します。

AWSをこれから学ぶ方は、AWS入門ページでAWS全体の基礎知識を身につけてからEKSの設計に取り組むと、各設定の意味が理解しやすくなります。

1. OIDCプロバイダーを確認する

eksctlでクラスターを作成すると、OIDCプロバイダーが自動で設定されます。IRSAはOIDCを使ってKubernetesのServiceAccountとAWS IAMを連携します。

# OIDCプロバイダーのエンドポイントを確認する aws eks describe-cluster --name prod-cluster --query "cluster.identity.oidc.issuer" --output text

出力例:

https://oidc.eks.ap-northeast-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE

2. ServiceAccountとIAMロールを紐付ける

eksctl create iamserviceaccountコマンドを使うと、Kubernetes ServiceAccountの作成とIAMロールの紐付けを一度に実行できます。S3読み取り専用の例を示します。

eksctl create iamserviceaccount --cluster prod-cluster --namespace production --name s3-reader-sa --attach-policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess --approve

実行結果:

[i] 1 iamserviceaccount (production/s3-reader-sa) was included [i] creating serviceaccount "production/s3-reader-sa" [v] created serviceaccount "production/s3-reader-sa"

作成したServiceAccountをDeploymentのspec.template.spec.serviceAccountNameに指定するだけで、そのPodのプロセスのみS3読み取り権限を持つIAMロールを取得します。ノード全体や他のPodには権限が漏れません。

よくあるエラーとトラブルシュート

「no subnets found for given AZs」エラー

eksctlがAvailabilityZonesに指定したAZでサブネットを見つけられない場合に出るエラーです。

原因として多いのかap-northeast-1bの指定です。東京リージョンのap-northeast-1bはEKSが利用できないアカウントが多いため、ap-northeast-1a / 1c / 1dを指定してください。

ノードが「NotReady」または「0 nodes ready」のままになる

ノードがReady状態にならない場合は、まずノードのイベントを確認します。

kubectl describe node <ノード名> | grep -A 20 "Events:"

よくある原因:

プライベートサブネットにNATゲートウェイのルートがない: ECRからコンテナイメージが引けずノードが起動しない。ルートテーブルにゾ NATゲートウェイへのルートを追加する
セキュリティグループのポート不足: コントロールプレーンとワーカーノード間で443/tcpおよび1025-65535/tcpが必要。ssコマンドやlsofでのポート確認も参考にしてください
ノードのIAMロールにポリシーが不足: AmazonEKSWorkerNodePolicy・AmazonEKS_CNI_Policy・AmazonEC2ContainerRegistryReadOnlyの3つが最低限必要

CoreDNSのPodがPendingになる

EKSのCoreDNSはクラスター内のDNS名前解決を担うコアコンポーネントです。ノードグループが作成される前にCoreDNSのPodが起動しようとしてPendingになることがあります。eksctl create clusterの完了を待てば自動で解消します。

ノードグループ作成後もPendingが続く場合は、次のコマンドで状況を確認します。

kubectl describe pod -n kube-system -l k8s-app=kube-dns | grep -A 10 "Events:"

本記事のまとめ

AWS EKSのマルチAZ設計の要点を表にまとめます。

設計項目 推奨設定
ワーカーノードのAZ分散 managedNodeGroups[].availabilityZonesで3AZを明示指定
NATゲートウェイの冗長化 vpc.nat.gateway: HighlyAvailable(各AZに1台)
プライベートサブネット配置 privateNetworking: trueでノードをインターネット非公開に
PodのAZ分散強制 topologySpreadConstraints(maxSkew: 1, DoNotSchedule)
Internal ALBのサブネット自動選択 プライベートサブネットにkubernetes.io/role/internal-elb: 1タグを設定
PodへのAWS権限付与 IRSAでeksctl create iamserviceaccountを使用(最小権限)

EKSのマルチAZ設計はVPCサブネットの設計段階から始まります。後から変更できない部分(VPCのCIDR、NATゲートウェイの配置方针)は最初に確定させてください。ノードグループのAZ分散とtopologySpreadConstraintsを組み合わせることで、AZ単位の障害に考えかられた本番環境が整います。

マルチAZ冗長設計の全体パターンは、AWS冗長設計の上級ページで体系的に解説しています。
AWSを基礎から学ぶ方は、AWS入門ページ(Amazon Linux基礎)からスタートすることをお勧めします。

AWS EKSのマルチAZ設計を「実務の型」として身につけませんか?

eksctlの使い方は調べれば分かります。でも「なぜ3AZにノードを分散させるのか」「topologySpreadConstraintsとPodAntiAffinityはどう使い分けるのか」を自信を持って説明できますか?
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼントしています。

「独学の時間がもったいない」「プロから直接、現場の技術を最短で学びたい」という本気の方には、2日で実務レベルのスキルが身につく【初心者向けハンズオンセミナー】も開催しています。

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。