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)で最小権限を実現する
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
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
# タグキー タグ値 kubernetes.io/cluster/prod-cluster shared kubernetes.io/role/internal-elb 1
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
kubectl get nodes --label-columns topology.kubernetes.io/zone
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
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"
よくあるエラーとトラブルシュート
「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日で実務レベルのスキルが身につく【初心者向けハンズオンセミナー】も開催しています。
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:AWS CloudFormationでインフラをコード管理する方法|テンプレートの基本構造とマルチAZ構成パターン入門
- この記事の属するカテゴリ:AWS(Amazon Linux)へ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます