「AWS EKS」でKubernetesクラスターを構築してコンテナアプリケーションをデプロイしてみよう

- 1 はじめに
- 2 EKSとは
- 2.1 Kubernetesの基本概念
- 2.2 EKSの特徴
- 2.3 EKSの料金
- 3 EKSクラスターの構築
- 3.1 前提条件
- 3.2 ステップ1: IAMロールの作成
- 3.3 ステップ2: VPCの準備
- 3.4 ステップ3: EKSクラスターの作成
- 3.5 ステップ4: kubectlの設定
- 3.6 ステップ5: ノードグループの作成
- 4 ECRからのデプロイ
- 4.1 デプロイの準備
- 4.2 マニフェストの解説
- 4.3 デプロイの実行
- 4.4 アプリケーションへのアクセス
- 4.5 デプロイの動作確認
- 4.6 ログの確認
- 5 リソースのクリーンアップ
- 6 おわりに
はじめに
第13回では「GitHub Actions」から「AWS ECR」にコンテナイメージをプッシュする方法を学びました。これでコンテナイメージの保存場所は確保できましたが、実際にアプリケーションを本番環境で動かすには、コンテナを実行・管理する基盤が必要です。
単純なアプリケーションであれば、EC2インスタンスでDockerを直接実行することも可能です。しかし、以下のような要件が出てくると、手動での管理は困難になります。
- スケーラビリティ
例えば、ECサイトでセール時にアクセスが集中した際に、手動でサーバーを増やしていては間に合わないため、負荷の増加に応じて自動的にコンテナの数を増やす仕組みが必要 - 高可用性
コンテナやノードに障害が発生した場合、人間が手動で再起動するまでサービスが停止してしまうようでは本番運用には耐えられない。仮に深夜にアプリケーションがクラッシュしても自動的に別のノードで再起動し、サービスを復旧できるようにしておく必要がある - ゼロダウンタイムデプロイ
アプリケーションをバージョンアップする際はユーザーへの影響が出ないよう、サービスを停止せずに切り替えられるのが理想であるため、無停止で段階的に新バージョンをリリースできる仕組みが必要 - リソース効率
1台のサーバーに1つのアプリケーションだけを割り当てるのはリソースの利用効率が悪く、インフラコストも高くなる。限りあるサーバーリソースを無駄なく使い切るためには、複数のアプリケーションを効率的に配置するスケジューラーが必要 - 統一された運用
環境ごとに管理手順が異なっていると、ミスを起こすリスクも高まる。開発環境、ステージング環境、本番環境それぞれで同じデプロイ・管理方法を適用できるのが理想
これらの課題を解決するために「コンテナオーケストレーションツール」が必要になります。その中でも「Kubernetes」はGoogleが長年培ったコンテナ運用のノウハウをオープンソース化したもので、業界標準として広く採用されています。
しかし、Kubernetesクラスターを自前で構築・運用するのは容易ではありません。コントロールプレーンの冗長化、etcdのバックアップ、バージョンアップデート、セキュリティパッチの適用など、多くの運用タスクが発生します。
「AWS EKS(Elastic Kubernetes Service)」)は、こうしたKubernetesの運用負荷を大幅に軽減するマネージドサービスです。AWSがコントロールプレーンの管理を担当し、開発者はアプリケーションのデプロイと運用に集中できます。
本記事では、第13回でECRにプッシュしたコンテナイメージを実際にEKS上で動かす手順を解説します。
EKSとは
AWS EKSは、AWSが提供するマネージド型Kubernetesサービスです。Kubernetesのコントロールプレーンを自動的に管理し、高可用性、セキュリティ、スケーラビリティを提供します。
Kubernetesの基本概念
EKSを理解するには、まずKubernetesの基本的なコンポーネントを押さえておく必要があります。
コントロールプレーンとデータプレーンKubernetesクラスターは、大きく2つの部分で構成されます。
- コントロールプレーン
クラスター全体を管理する「司令塔」でAPI Server、Scheduler、Controller Managerなどが含まれる - データプレーン(ワーカーノード)
実際にコンテナが動作するサーバー。1つ以上のサーバーをワーカーノードとしてKubernetesに追加できる
- Pod
PodはKubernetesにおける最小の実行単位。Kubernetesはコンテナを直接実行するのではなく、Podと呼ばれる箱のようなものにコンテナを詰めてデプロイする。Podには1つ以上のコンテナを詰めることができる - Deployment
DeploymentはPodをデプロイするための設定。Podをいくつデプロイしたいのか、Podがクラッシュした時に再実行するのかなど、Podをコントロールするための設定が書かれている - Service
Kubernetesにおいて、Podはいつでも作り直される可能性がある。Podは再作成されるとIPアドレスが変わってしまうため、PodのIPアドレスを使って直接アクセスしようとするのは悪手となる。Serviceは対象となるPodの集まりに固定したアクセス先を提供するもので、PodのIPアドレスを意識せずにアクセスが可能となる。また、同じアプリのPodが複数ある場合はServiceが自動的にリクエストを振り分ける - Namespace
NamespaceはKubernetesを整理するための部屋のようなもの。例えば、1つのKubernetesに開発とステージングの2環境をデプロイするとしたとき、開発とステージングをNamespace(部屋)で分けることでリソースを整理して管理できる。また、別のNamespaceであれば同じ名前のPodやServiceも作成できるため、環境ごとに同じ名前を使い回せる - ConfigMap
ConfigMapはアプリの設定情報を保存する場所で、データベースの接続先や環境ごとに変わる設定値などをコンテナイメージとは別に管理できる。これにより、同じコンテナイメージを使いながら環境ごとに異なる設定を適用できる - Secret
Secretはパスワードやトークンなどの機密情報を保存する場所です。ConfigMapと似ていますが、機密情報を扱うため暗号化して保存されます。データベースのパスワードやAPI キーなど、コードに直接書きたくない情報を安全に管理できます。
ここまでに説明したオブジェクト以外にも、Kubernetesでは様々なオブジェクトが実装されています。詳細は「Kubernetesのコンセプト」をご確認ください。
EKSの特徴
EKSはKubernetesのコントロールプレーンや一部のワーカーノードをAWSが管理します。従来のKubernetesを真面目に運用しようと思うと、コントロールプレーンやワーカーノードの冗長化、障害が発生したサーバーの切り離しや復旧、定期的なアップグレードなど、多くの運用タスクが発生します。
しかし、EKSを使用することでこれらのタスクをAWSが自動で行ってくれます。複数のアベイラビリティーゾーン(AZ)に自動的にサーバーを配置したり、障害発生時の自動復旧、セキュリティパッチの適用、バージョンアップグレードなどをAWSに任せられるということです。また、AWSのサービスと親和性が高く、EKSとその他のサービスを簡単に連携できます。
EKSでは3つのノードタイプからワーカーノードを選択できます。1つ目はAWSがワーカーノードを管理するマネージドノードグループ、2つ目は自分でEC2を管理するセルフマネージドノード、3つ目がサーバーレスでPodを実行するFargateです。
詳細は、AWSの公式ドキュメント「コンピューティングを管理する」をご確認ください。
本記事では、最も一般的なマネージドノードグループを使用します。
EKSの料金
EKSの料金は以下で構成されます。
- コントロールプレーン: 1クラスターあたり0.10ドル/時間(約73ドル/月)
- ワーカーノード: 使用するEC2インスタンスの料金
- データ転送: 通常のAWSデータ転送料金
詳細は、こちらもAWSの公式ドキュメント「Amazon EKSの料金」をご確認ください。
EKSクラスターの構築
EKSクラスターを構築するには、以下の手順が必要です。
- IAMロールの作成
- VPCの準備
- EKSクラスターの作成
- ノードグループの作成
前提条件
EKSを利用するには、前提として以下のものが必要となります。
- AWSアカウント(第13回で作成済み)
- kubectl(Kubernetesのコマンドラインツール)
- AWS CLI(バージョン2推奨)
kubectlのインストール
ローカルマシンにkubectlをインストールします。インストール方法とセットアップ手順は、使用しているOSに応じて公式ドキュメントを参照してください。
【kubectlのインストールおよびセットアップ】
インストール後、以下のコマンドでバージョンを確認できます。
kubectl version --client
AWS CLIのインストール
AWS CLIをインストールします。インストール方法、認証情報の設定、基本的な使い方については公式ドキュメントを参照してください。
【AWS CLIのインストールまたは更新】
【AWS CLI の設定】
認証情報は、以下のコマンドで設定します。
aws configure
アクセスキーID、シークレットアクセスキー、デフォルトリージョン、出力形式を入力します。詳細は上記のドキュメントを参照してください。
ステップ1: IAMロールの作成
EKSクラスターとノードグループが使用するIAMロールを作成します。
- EKSクラスター用IAMロール
EKSクラスターがAWSリソースを管理するために必要なロールです。
【Amazon EKS クラスター IAM ロール】- IAMコンソールを開く
- 「ロール」→「ロールを作成」
- 信頼されたエンティティタイプ: 「AWSのサービス」
- ユースケース: 「EKS」→「EKS - Cluster」を選択
- ポリシー: 「AmazonEKSClusterPolicy」が自動選択される
- ロール名:
EKSClusterRole
- ノードグループ用IAMロール
ワーカーノードがECRからイメージをpullしたり、CloudWatchにログを送信するために必要なロールです。
【Amazon EKS ノード IAM ロール】- IAMコンソールで「ロールを作成」
- 信頼されたエンティティタイプ: 「AWSのサービス」
- ユースケース: 「EC2」を選択
- ポリシー: 以下の3つを選択
AmazonEKSWorkerNodePolicy
AmazonEC2ContainerRegistryReadOnly
AmazonEKS_CNI_Policy
- ロール名:
EKSNodeRole
ステップ2: VPCの準備
EKSクラスターを配置するVPCが必要です。既存のVPCを使用することもできますが、ここではAWSが提供するCloudFormationテンプレートで新規VPCを作成します。
【Amazon EKS VPC の作成】
- CloudFormationコンソールを開く
- 「スタックの作成」
- テンプレートURL: AWSが提供するVPCテンプレートを指定
https://s3.us-west-2.amazonaws.com/amazon-eks/cloudformation/2020-10-29/amazon-eks-vpc-private-subnets.yaml
- スタック名:
eks-vpc
- 作成を実行
スタックの作成が完了すると、スタックのステータスが「CREATE_IN_PROGRESS」から「CREATE_COMPLETE」に変わります。
作成されたVPCには、パブリックサブネットとプライベートサブネットが2つのAZに配置されます。
ステップ3: EKSクラスターの作成
それでは、EKSクラスターを作成します。
【Amazon EKS クラスターの作成】
- EKSコンソールを開く
- 「クラスターを作成」
- 以下を設定
- クラスターを設定:
- 設定オプション:
カスタム設定
- EKSオートモード:
オフ
- クラスター名:
my-cluster
- Kubernetesバージョン: 最新(例: 1.33)
- クラスターサービスロール:
EKSClusterRole
- 設定オプション:
- ネットワーキング:
- VPC: 作成した
eks-vpc
- サブネット: すべて選択
- セキュリティグループ: デフォルト
- クラスターエンドポイントアクセス: 「パブリックおよびプライベート」
- VPC: 作成した
- コントロールプレーンのログ記録: 必要に応じて有効化
- クラスターを設定:
- 「作成」をクリック
クラスターの作成には10〜15分程度かかります。ステータスが「アクティブ」になるまで待ちます。
ステップ4: kubectlの設定
作成したEKSクラスターへkubectlでアクセスできるように設定します。
aws eks update-kubeconfig --region ap-northeast-1 --name my-cluster接続確認:
kubectl get svc
※service
のショートネームです。kubectl get service
と同じ意味です。他のリソースのショートネームはkubectl api-resources
で確認できます。
以下のような出力が表示されれば成功です。
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.100.0.1 <none> 443/TCP 10m
以下のようなエラーが出る場合は、EKSを作成したユーザーとaws eks update-kubeconfig
を実行したユーザーが違うことに起因します。
E1002 22:11:15.449068 95521 memcache.go:265] "Unhandled Error" err="couldn't get current server API group list: the server has asked for the client to provide credentials"
コマンドを実行したユーザーもEKSにアクセスできるように設定します。
- EKSコンソールで作成したクラスター(
my-cluster
)を開く - 「アクセス」タブ→IAM アクセスエントリから「作成」をクリック
- 以下を設定
- IAM アクセスエントリを設定
- IAM プリンシパル:
アクセスを許可するIAMユーザー
- IAM プリンシパル:
- アクセスポリシーを追加
- ポリシー名:
AmazonEKSClusterAdminPolicy
- 「ポリシーを追加」をクリック
- ポリシー名:
- 「作成」をクリック
- IAM アクセスエントリを設定
操作が完了したら、再度kubectl get svc
を実行してみてください。
ステップ5: ノードグループの作成
コンテナを実行するワーカーノードを追加します。
【マネージドノードグループの作成】
- EKSコンソールで作成したクラスター(
my-cluster
)を開く - 「コンピューティング」タブ→「ノードグループを追加」
- 以下を設定
- ノードグループ名:
my-nodegroup
- ノードIAMロール:
EKSNodeRole
- AMIタイプ: Amazon Linux 2023(デフォルト)
- インスタンスタイプ: t3.medium(検証用)
- ディスクサイズ: 20GB
- スケーリング設定:
- 必要なサイズ: 2
- 最小サイズ: 1
- 最大サイズ: 3
- サブネット: プライベートサブネットを選択
- ノードグループ名:
- 「作成」をクリック
ノードグループの作成には数分かかります。ステータスが「アクティブ」になったら、ノードを確認します。
kubectl get nodes
以下のような出力が表示されれば成功です。
NAME STATUS ROLES AGE VERSION ip-192-168-xx-xx.ap-northeast-1.compute.internal Ready <none> 2m v1.33.x ip-192-168-xx-xx.ap-northeast-1.compute.internal Ready <none> 2m v1.33.x
ECRからのデプロイ
第13回でECRにプッシュしたコンテナイメージを、EKSクラスターにデプロイします。
デプロイの準備
- ECRイメージURIの確認
ECRコンソールから、デプロイするイメージのURIを確認します。ACCOUNT_ID.dkr.ecr.ap-northeast-1.amazonaws.com/my-app:main
- Kubernetesマニフェストの作成
アプリケーションをデプロイするためのマニフェストファイルを作成します。 deployment.yamlapiVersion: apps/v1 kind: Deployment metadata: name: my-app labels: app: my-app spec: replicas: 3 selector: matchLabels: app: my-app template: metadata: labels: app: my-app spec: containers: - name: my-app image: ACCOUNT_ID.dkr.ecr.ap-northeast-1.amazonaws.com/my-app:main ports: - containerPort: 8000 resources: requests: memory: "128Mi" cpu: "100m" limits: memory: "256Mi" cpu: "200m"
※ACCOUNT_ID
は自分のAWSアカウントIDに置き換えてください。
service.yamlapiVersion: v1 kind: Service metadata: name: my-app-service spec: type: LoadBalancer selector: app: my-app ports: - protocol: TCP port: 80 targetPort: 8000
マニフェストの解説
Deploymentreplicas: 3
: Podを3つ起動し、冗長性を確保image
: ECRのイメージURIを指定resources
: CPUとメモリの要求量と上限を設定
type: LoadBalancer
: AWS ELB(Elastic Load Balancer)を自動作成port: 80
: 外部からポート80でアクセスtargetPort: 8000
: コンテナ内のポート8000に転送
デプロイの実行
作成したマニフェストをクラスターに適用します。
kubectl apply -f deployment.yaml kubectl apply -f service.yaml
デプロイの状態を確認します。
kubectl get deployments kubectl get pods kubectl get services
ServiceのEXTERNAL-IP
にロードバランサーのURLが表示されます(表示されるまで数分かかる場合があります)。
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE my-app-service LoadBalancer 10.100.xx.xx xxxxx-xxxx.ap-northeast-1.elb.amazonaws.com 80:xxxxx/TCP 2m
アプリケーションへのアクセス
WebブラウザでEXTERNAL-IP
のURLにアクセスすると、デプロイしたアプリケーションが表示されます。
curl http://xxxxx-xxxx.ap-northeast-1.elb.amazonaws.com
第13回で作成したアプリケーションが動作していることを確認できます。
デプロイの動作確認
- スケーリングの確認
Podの数を変更してみます。kubectl scale deployment my-app --replicas=5 kubectl get pods
5つのPodが起動します。 - 自動復旧の確認
Podを削除してみます。kubectl delete pod <pod-name> --force --grace-period=0 kubectl get pods
※--force
と--grace-period=0
は強制削除のオプションです。通常の運用では不要ですが、ここでは自動復旧の動作を即座に確認するために使用しています。本番環境では通常のkubectl delete pod <pod-name>
を使用してください。
Deploymentが自動的に新しいPodを起動し、指定されたreplica数を維持します。 - ローリングアップデート
新しいイメージをデプロイする際、段階的に更新されます。kubectl set image deployment/my-app my-app=ACCOUNT_ID.dkr.ecr.ap-northeast-1.amazonaws.com/my-app:new-tag kubectl rollout status deployment/my-app
ログの確認
アプリケーションのログを確認します。
kubectl logs -f deployment/my-app
CloudWatch Logsと統合する場合は、AWS Load Balancer ControllerやFluent Bitをセットアップします。
【Amazon EKS での CloudWatch Container Insights の使用>】
リソースのクリーンアップ
検証が終わったら、課金を避けるためリソースを削除します。
- Serviceの削除
kubectl delete -f service.yaml
※これによりELBが削除されます。 - Deploymentの削除
kubectl delete -f deployment.yaml
- ノードグループの削除
EKSコンソールから、ノードグループを削除します。- EKSコンソールで作成したクラスター(
my-cluster
)を開く - 「コンピューティング」タブ→「my-nodegroup」を選択
- 「削除」をクリック
- EKSコンソールで作成したクラスター(
- クラスターの削除
EKSコンソールから、クラスターを削除します。
※ノードグループが完全に削除されてからこの手順を実行してください。- EKSコンソールで作成したクラスター(
my-cluster
)を開く - 「クラスターを削除」をクリック
- EKSコンソールで作成したクラスター(
- VPCスタックの削除
CloudFormationコンソールから、eks-vpc
スタックを削除します。
※EKSが完全に削除されてからこの手順を実行してください。- CloudFormationコンソールで作成したスタック(
eks-vpc
)を選択 - 「削除」をクリック
- CloudFormationコンソールで作成したスタック(
- IAMロールの削除
IAMコンソールから、作成した2つのロールを削除します。- IAMコンソール→ロールから
EKSClusterRole
、EKSNodeRole
にチェックを付ける - 「削除」をクリック
- IAMコンソール→ロールから
おわりに
本記事では、AWS EKSを使ってKubernetesクラスターを構築し、第13回でECRにプッシュしたコンテナイメージをデプロイする方法を学びました。
EKSを使うことで、コンテナオーケストレーションの複雑な管理をAWSに任せ、アプリケーションの開発と運用に集中できます。また、Kubernetesの標準的な機能をそのまま使えるため、他のクラウドやオンプレミス環境への移行も容易です。
次回はIaCツールである「Terraform」を使って、ここまでに構築したクラウド環境をコードからプロビジョニングします。IaCはDevOpsにとって重要な技術の1つです。ぜひこの機会にマスターしましょう。
連載バックナンバー
Think ITメルマガ会員登録受付中
全文検索エンジンによるおすすめ記事
- 「GitHub Actions」と「AWS ECR」を連携してセキュアなCI/CDパイプラインを構築してみよう
- Kubeflowを構築する
- 「microk8s」を使って、WSL上にKubernetesクラスターを構築してみよう
- コンテナを効率的に運用・管理する標準ツール「Kubernetes」とは
- 【CNDW2024】金融システムにおけるクラウドネイティブ化を実現するEKSの最前線
- コンテナは場所を選ばない!「オンプレ or クラウド × コンテナ」(前編)
- Pulumi Kubernetes Operatorを活用してPulumiのCI/CDを実現しよう
- KubernetesのDiscovery&LBリソース(その1)
- コンテナは場所を選ばない!「オンプレ or クラウド×コンテナ」(後編)
- Kubernetes上のコンテナをIngressでインターネットに公開するまで