Amazon EKS 入門 + Kubernetes 基本操作ハンズオン

EKS クラスターをマネコンで構築し、Pod / Deployment / Service など k8s の基本操作を一通り学ぶ

Amazon EKS Kubernetes kubectl マネコン操作 中級 所要時間 90〜120 分 v1.0

📋 概要

このハンズオンでは、Amazon EKS(Elastic Kubernetes Service)クラスターをマネジメントコンソールで構築し、kubectl から Kubernetes の基本リソース(Pod / Deployment / Service)を操作します。コンテナオーケストレーションの中核である k8s の概念と操作を、実際に手を動かしながら習得します。

項目内容
所要時間90〜120 分(クラスター作成の待ち時間含む)
難易度中級
主要サービスAmazon EKS、EC2(マネージドノード)、IAM、kubectl
構築方法マネジメントコンソール操作(eksctl は使用しない)
前提リソースデフォルト VPC(または 2 AZ 以上のサブネットを持つ VPC)
⚠️ 料金に注意(必ずクリーンアップ)

EKS クラスターは稼働中 1 クラスターあたり $0.10/時間(約 $73/月)の固定料金がかかります。さらにマネージドノードの EC2 料金(t3.medium × 2 台など)と、Service(LoadBalancer) で作成される ELB の料金が加算されます。ハンズオン完了後は必ずすべて削除してください。放置すると 1 日で数百円規模の課金になります。

Kubernetes の主要リソース(このハンズオンで扱う)

リソース役割
Podコンテナを動かす最小単位。1 つ以上のコンテナをまとめたもの
DeploymentPod の数(レプリカ)を維持・更新する。自己修復・ローリング更新を担う
ServicePod 群への安定したアクセス先(IP/DNS)を提供。負荷分散も行う
NodePod が実際に動作するワーカー(EKS ではマネージドノードの EC2)
Namespaceリソースを論理的に分離する単位(default / kube-system など)

🏗️ 構成図

👤 管理者(AWS CloudShell + kubectl)
↓ aws eks update-kubeconfig / kubectl
🧠 EKS コントロールプレーン(AWS マネージド)
API サーバー / etcd / スケジューラ。handson-eks-cluster
↓ Pod をスケジュール
⚙️ マネージドノードグループ(EC2 t3.medium × 2)
Pod(Nginx コンテナ)が稼働
↓ Service (LoadBalancer)
🌐 ELB → インターネットからアクセス
ℹ️ コントロールプレーンとデータプレーン

EKS では コントロールプレーン(k8s の頭脳)を AWS が完全管理します。利用者は データプレーン(Pod が動くノード)を用意します。このハンズオンではデータプレーンに「マネージドノードグループ」(EC2)を使います。

✅ 前提条件

⚠️ クラスター作成者の権限について

EKS クラスターを作成した IAM プリンシパル(ユーザー/ロール)には、自動的にクラスター管理者権限(access entry)が付与されます。後で kubectl を実行する CloudShell も、クラスター作成時と同じ IAM ユーザーで操作してください。異なるプリンシパルだと kubectl で認証エラーになります。

kubectl のインストール(CloudShell)

CloudShell に kubectl が無い場合は以下でインストールします(公式の安定版を取得)。

curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" chmod +x kubectl mkdir -p ~/bin && mv kubectl ~/bin/ export PATH=~/bin:$PATH kubectl version --client
ℹ️ kubectl のバージョン互換性

kubectl はクラスターの Kubernetes バージョンと ±1 マイナーバージョン以内であれば動作します。最新の安定版を入れておけば、本ハンズオンで作成するクラスター(最新マイナス 1〜2 程度)と問題なく通信できます。

🔧 ステップ 1: IAM ロールの作成(2 種類)

EKS には「クラスター用ロール」と「ノード用ロール」の 2 つの IAM ロールが必要です。

1-1. クラスターサービスロールの作成

手順
  1. IAM コンソール → 「ロール」→「ロールを作成」
  2. 信頼されたエンティティタイプ: 「AWS のサービス」
  3. ユースケース: 検索で「EKS」→「EKS - Cluster」を選択 → 「次へ」
  4. ポリシー AmazonEKSClusterPolicy が自動で付与される → 「次へ」
  5. ロール名: handson-eks-cluster-role → 「ロールを作成」

1-2. ノード(ワーカー)用ロールの作成

手順
  1. IAM → 「ロール」→「ロールを作成」
  2. 信頼されたエンティティタイプ: 「AWS のサービス」
  3. ユースケース: 「EC2」 を選択 → 「次へ」
  4. 以下の 3 つのポリシーを検索して付与する
ポリシー役割
AmazonEKSWorkerNodePolicyノードがクラスターに参加するための権限
AmazonEKS_CNI_PolicyPod ネットワーク(VPC CNI)の権限
AmazonEC2ContainerRegistryReadOnlyECR からコンテナイメージを取得する権限
  1. ロール名: handson-eks-node-role → 「ロールを作成」
ℹ️ 2 つのロールの違い

クラスターロールは EKS コントロールプレーンが AWS リソースを管理するために使います(信頼先は eks.amazonaws.com)。ノードロールは EC2 ワーカーノードがクラスターに参加し ECR からイメージを取得するために使います(信頼先は ec2.amazonaws.com)。

🔧 ステップ 2: EKS クラスターの作成

手順
  1. AWS コンソールで「EKS」を検索して開く
  2. 「クラスター」→「クラスターを作成

2-1. 設定(Configure cluster)

設定値
設定オプション
カスタム設定 / Quick configuration いずれでも可(本手順はカスタム)
名前
handson-eks-cluster
Kubernetes バージョン
最新の安定版(例: 1.31)
クラスターサービスロール
handson-eks-cluster-role
クラスターアクセス(認証モード)
EKS API および ConfigMap(デフォルト推奨)
クラスター管理者アクセス
有効(作成者に管理者権限を自動付与)

2-2. ネットワーク(Specify networking)

設定値
VPC
デフォルト VPC を選択
サブネット
2 つ以上の AZ のサブネットを選択(例: ap-northeast-1a / 1c)
セキュリティグループ
デフォルトのまま(指定しなくても可)
クラスターエンドポイントアクセス
パブリック
⚠️ サブネットは 2 AZ 以上が必須

EKS はコントロールプレーンの冗長化のため、異なる 2 つ以上の AZのサブネットを要求します。1 AZ しか選べない場合は作成に失敗します。デフォルト VPC なら各 AZ にサブネットがあるので 2 つ以上選択してください。

2-3. アドオン・ログ設定

手順
  1. アドオン(Add-ons): デフォルトの kube-proxy / CoreDNS / Amazon VPC CNI をそのまま有効化 → 「次へ」
  2. ログ記録: 任意(このハンズオンでは無効のまま可)→ 「次へ」
  3. 確認画面で内容を確認 → 「作成
⏳ クラスター作成には 10〜15 分かかります

ステータスが「作成中」→「アクティブ」に変わるまで待ちます。この間に次のステップの準備(CloudShell で kubectl インストール)を進められますが、ノードグループ作成(ステップ 3)はクラスターがアクティブになってからです。

🔧 ステップ 3: マネージドノードグループの作成

クラスターが「アクティブ」になったら、Pod を動かすワーカーノード(EC2)を追加します。

手順
  1. EKS → handson-eks-cluster → 「コンピューティング」タブ
  2. 「ノードグループを追加」をクリック

3-1. 設定

設定値
名前
handson-nodegroup
ノード IAM ロール
handson-eks-node-role

3-2. コンピューティングとスケーリング

設定値
AMI タイプ
Amazon Linux 2023 (AL2023_x86_64_STANDARD)
容量タイプ
オンデマンド
インスタンスタイプ
t3.medium
ディスクサイズ
20 GiB
希望するサイズ
2
最小サイズ
2
最大サイズ
3
ℹ️ なぜ t3.medium 以上か

EKS では各ノードで動かせる Pod 数が ENI(ネットワークインターフェイス)数に依存します。t3.micro/small は IP 数が少なく、システム Pod(CoreDNS など)でほぼ埋まってしまうため、t3.medium 以上を推奨します。

3-3. ネットワーク

手順
  1. サブネット: クラスターと同じサブネットを選択
  2. 「次へ」→ 確認 → 「作成
  3. ステータスが「アクティブ」になるまで待つ(2〜5 分)
✅ 確認

「コンピューティング」タブにノードグループが「アクティブ」で表示され、ノード(EC2)2 台が作成されれば成功です。

🔧 ステップ 4: kubectl でクラスターに接続

CloudShell から kubectl がクラスターと通信できるよう設定します。

4-1. kubeconfig の更新

aws eks update-kubeconfig \ --region ap-northeast-1 \ --name handson-eks-cluster

これで ~/.kube/config にクラスターの接続情報が書き込まれます。

4-2. ノードの確認

kubectl get nodes
✅ 期待結果
NAME                                              STATUS   ROLES    AGE   VERSION
ip-172-31-xx-xx.ap-northeast-1.compute.internal   Ready    <none>   3m    v1.31.x
ip-172-31-yy-yy.ap-northeast-1.compute.internal   Ready    <none>   3m    v1.31.x

2 台のノードが Ready で表示されれば接続成功です。

4-3. クラスター全体の確認

# システム Pod(CoreDNS, kube-proxy, aws-node)の確認 kubectl get pods -n kube-system # 全 namespace の確認 kubectl get namespaces
⚠️ error: You must be logged in to the server (Unauthorized) が出たら

kubectl を実行している IAM プリンシパルがクラスター作成者と異なる場合に発生します。CloudShell が想定の IAM ユーザーで動いているか aws sts get-caller-identity で確認してください。別ユーザーで作成した場合は EKS の「アクセス」タブからアクセスエントリを追加します。

🔧 ステップ 5: Pod の基本操作【k8s 基本①】

まずは単一の Pod を起動して、k8s の最も基本的な操作を体験します。

5-1. Pod の起動

kubectl run nginx-pod --image=nginx:latest

5-2. Pod の確認

# 一覧表示 kubectl get pods # 詳細表示(イベント・割り当てノードなど) kubectl describe pod nginx-pod # より詳しい情報(IP・ノード名を列に追加) kubectl get pods -o wide
✅ 期待結果
NAME        READY   STATUS    RESTARTS   AGE
nginx-pod   1/1     Running   0          30s

STATUS が Running、READY が 1/1 になれば Pod 起動成功です。ContainerCreating の場合は数十秒待ちます。

5-3. ログとコンテナ内シェル

# Pod(コンテナ)のログを表示 kubectl logs nginx-pod # Pod 内でコマンドを実行 kubectl exec nginx-pod -- nginx -v # Pod 内のシェルに入る(対話) kubectl exec -it nginx-pod -- /bin/bash # → コンテナ内に入る。`exit` で抜ける

5-4. ポートフォワードで動作確認

# ローカル(CloudShell)の 8080 を Pod の 80 に転送 kubectl port-forward nginx-pod 8080:80 & curl http://localhost:8080 # → Nginx の "Welcome to nginx!" HTML が返る # 確認後: kill %1 でフォワードを停止

5-5. Pod の削除

kubectl delete pod nginx-pod
ℹ️ 単体 Pod の弱点

kubectl run で作った単体 Pod は、削除されると自動で復活しません。ノード障害で消えても再作成されません。本番では次のステップの Deployment で Pod を管理し、自己修復・冗長化を実現します。

🔧 ステップ 6: Deployment の作成【k8s 基本②】

Deployment は指定した数の Pod(レプリカ)を維持し、自己修復とローリング更新を担うリソースです。マニフェスト(YAML)で宣言的に管理します。

6-1. マニフェストファイルの作成

CloudShell で以下のファイルを作成します(cat > ... << 'EOF' で貼り付け)。

cat > nginx-deployment.yaml << 'EOF' apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.27 ports: - containerPort: 80 EOF

6-2. マニフェストの適用

kubectl apply -f nginx-deployment.yaml

6-3. 状態の確認

# Deployment の確認 kubectl get deployments # Pod が 3 つ作られたことを確認 kubectl get pods -l app=nginx # ReplicaSet(Deployment が内部で作る Pod 管理単位) kubectl get replicasets
✅ 期待結果
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3/3     3            3           40s

3/3 で 3 つの Pod が動いていれば成功です。

6-4. 自己修復を体験する

Pod を 1 つ手動削除しても、Deployment が即座に新しい Pod を作り直します。

# Pod 名を 1 つコピーして削除 kubectl get pods -l app=nginx kubectl delete pod <Pod 名の 1 つ> # すぐに確認 → 新しい Pod が作られ常に 3 つに保たれる kubectl get pods -l app=nginx
✅ 確認ポイント

削除した Pod の代わりに新しい Pod(AGE が数秒)が自動生成され、合計 3 つが維持されます。これが Deployment の自己修復(self-healing)です。

🔧 ステップ 7: Service で外部公開【k8s 基本③】

Pod は再作成のたびに IP が変わります。Service は Pod 群への安定したアクセス先を提供し、負荷分散します。LoadBalancer タイプにすると AWS の ELB が自動作成され、インターネットから到達できます。

Service の 3 タイプ

タイプ用途
ClusterIP(デフォルト)クラスター内部のみからアクセス可能
NodePort各ノードの特定ポートで公開(<NodeIP>:<Port>)
LoadBalancerクラウドの LB(AWS では ELB)を自動作成して外部公開

7-1. Service マニフェストの作成

cat > nginx-service.yaml << 'EOF' apiVersion: v1 kind: Service metadata: name: nginx-service spec: type: LoadBalancer selector: app: nginx ports: - protocol: TCP port: 80 targetPort: 80 EOF

selector: app: nginx によって、Deployment が作った 3 つの Pod へトラフィックが振り分けられます。

7-2. Service の作成

kubectl apply -f nginx-service.yaml

7-3. ELB の DNS 名を取得

kubectl get service nginx-service
✅ 期待結果
NAME            TYPE           CLUSTER-IP      EXTERNAL-IP                          PORT(S)
nginx-service   LoadBalancer   10.100.xx.xx    xxxx.ap-northeast-1.elb.amazonaws.com 80:31234/TCP

EXTERNAL-IP 列に ELB の DNS 名が表示されます(プロビジョニングに 2〜3 分かかり、最初は <pending> です)。

7-4. ブラウザ/curl でアクセス

# EXTERNAL-IP の DNS 名にアクセス curl http://<EXTERNAL-IP の DNS 名>/
✅ 確認

Nginx の "Welcome to nginx!" HTML が返れば、インターネット → ELB → Service → Pod の経路が完成です。ブラウザでも同じ URL にアクセスして確認できます。

⚠️ ELB が <pending> のまま / アクセスできない

ELB の作成には数分かかります。また、サブネットに ELB 作成用のタグ(kubernetes.io/role/elb)が必要な場合があります。デフォルト VPC のパブリックサブネットなら通常は自動で作成されます。数分待っても pending の場合は kubectl describe service nginx-service のイベントを確認してください。

🔧 ステップ 8: スケールとローリング更新

8-1. レプリカ数のスケール

# 3 → 5 にスケールアウト kubectl scale deployment nginx-deployment --replicas=5 kubectl get pods -l app=nginx # 5 → 2 にスケールイン kubectl scale deployment nginx-deployment --replicas=2

Service の selector が自動で増減後の Pod を追従するため、設定変更なしで負荷分散先が更新されます。

8-2. ローリング更新(イメージのバージョンアップ)

# nginx 1.27 → 1.28 へ更新 kubectl set image deployment/nginx-deployment nginx=nginx:1.28 # 更新の進捗を確認(古い Pod を停止しつつ新 Pod を起動) kubectl rollout status deployment/nginx-deployment
ℹ️ ローリング更新とは

Deployment は新バージョンの Pod を少しずつ起動し、古い Pod を段階的に停止します。これによりダウンタイムなしでアプリを更新できます。

8-3. 更新履歴とロールバック

# 更新履歴の確認 kubectl rollout history deployment/nginx-deployment # 1 つ前のバージョンにロールバック kubectl rollout undo deployment/nginx-deployment # イメージが戻ったことを確認 kubectl describe deployment nginx-deployment | grep Image
✅ 確認

スケール・ローリング更新・ロールバックが kubectl コマンドだけで完結することを体験できました。これが Kubernetes の宣言的な運用の強みです。

🧹 クリーンアップ

⚠️ 課金停止のため必ず全削除してください

EKS クラスター($0.10/時)+ EC2 ノード + ELB が課金され続けます。削除は順序が重要です(Service → ノードグループ → クラスター)。

削除手順(この順序で実施)

  1. Service(ELB)の削除
    先に Service を消して ELB を解放します。これを忘れるとクラスター削除後も ELB が残り課金されます。 kubectl delete service nginx-service kubectl delete deployment nginx-deployment
  2. ノードグループの削除
    EKS → handson-eks-cluster →「コンピューティング」タブ → handson-nodegroup を選択 →「削除」
    (完了まで 3〜5 分。EC2 ノードが終了します)
  3. クラスターの削除
    EKS → handson-eks-cluster →「削除」→ クラスター名を入力して確定
    (ノードグループ削除完了後に実行。完了まで 5〜10 分)
  4. IAM ロールの削除(任意)
    IAM → ロール → handson-eks-cluster-role / handson-eks-node-role を削除
⚠️ ELB の残骸を確認

Service を削除せずにクラスターを消すと、ELB が「みなしご」リソースとして残ることがあります。クリーンアップ後、EC2 コンソール →「ロードバランサー」に Service 由来の ELB が残っていないか確認し、あれば手動削除してください。

✅ 削除確認

EKS のクラスター一覧が空になり、EC2 のインスタンスとロードバランサーに handson 関連リソースが残っていなければ完了です。課金が停止します。