AWS入門ブログリレー2024 〜Amazon EKS編〜

2024.04.19

当エントリは弊社AWS事業本部による『AWS 入門ブログリレー 2024』の25日目のエントリです。

このブログリレーの企画は、普段 AWS サービスについて最新のネタ・深い/細かいテーマを主に書き連ねてきたメンバーの手によって、 今一度初心に返って、基本的な部分を見つめ直してみよう、解説してみようというコンセプトが含まれています。

AWS をこれから学ぼう!という方にとっては文字通りの入門記事として、またすでに AWS を活用されている方にとっても AWS サービスの再発見や 2024 年のサービスアップデートのキャッチアップの場となればと考えておりますので、ぜひ最後までお付合い頂ければ幸いです。

では、さっそくいってみましょう。今回のテーマは『Amazon EKS』です。

はじめに

Kubernetesとは

EKSは「マネージド型の Kubernetesクラスター」を提供するものであるため、Kubernetesクラスターの説明は避けて通れないかと思います。
Kubernetesの大まかな概要については、色々なところで説明されているかと思うので、ここでは簡単に説明すると、コンテナ化されたアプリケーションを自動で管理・運用するためのオープンソースのプラットフォームです。コンテナの管理・運用とは以下のようなことを指します。

  • 必要に応じてコンテナを自動で増減し、効率よくリソースを使用します
  • コンテナが止まっても自動で再起動するので、高可用性が保たれます
  • アプリケーションの更新の仕組みも提供されているので、ある程度自動で更新ができます

つまり、Kubernetesを使えば、コンテナ化されたアプリケーションをスケーラブルかつ高可用性に運用できるため、クラウドネイティブなアプリ開発・運用が容易になるということです。

Kubernetesではクラスターが中心的な概念となります。クラスターとは、Kubernetesがコンテナ化されたアプリケーションを実行するための基盤となる、マシンの集合体のことです。

Kubernetesクラスターのアーキテクチャは以下のようになっています。

それぞれのコンポーネントについて簡単に説明します。

  • ノード (Node)
    • コンテナが実際に実行される仮想マシンまたは物理マシンです。
    • コンテナランタイム (Docker、containerd など) がインストールされている必要があります。
    • 各ノードには以下の2つのエージェントが存在します。
    • kubelet: コントロールプレーンとノード間の通信を担当し、ポッドの起動や停止などを行います。
    • kube-proxy: ノード上のネットワークルールを管理し、クラスター内部のロードバランシングを実現します。
  • コントロールプレーン (Control Plane)
    • クラスター全体の状態を管理し、ノードへの指示を出す役割を担います。
    • 以下のコンポーネントから構成されています。
    • kube-apiserver: Kubernetes APIを提供し、kubeletやその他のコンポーネントとの通信の中心的な役割を果たします。
    • etcd: クラスターの設定データや状態を永続的に保存するための分散キーバリューストアです。
    • kube-scheduler: 新しいポッドをどのノードで実行するかをスケジューリングします。
    • kube-controller-manager: クラスターの現状と理想状態を比較し、理想状態に近づけるよう調整を行います。
    • cloud-controller-manager: クラウドプロバイダーのAPIと連携し、クラウドリソースの管理を行います。

これらのノードとコントロールプレーンの連携によって、Kubernetesクラスターが構築されます。コントロールプレーンがクラスター全体の状態を管理し、ノードがコンテナの実行環境を提供する形です。

Amazon EKSの概要と特徴

Kubernetesクラスターについて概要を説明したので、ここからはAmazon EKSが上記のKubernetesクラスターのどの部分をマネージドしてくれるのかを説明します。

Amazon EKSは、Kubernetesコントロールプレーンの運用を完全にマネージドしてくれるサービスです。上記の絵に照らし合わせると以下の部分をAWSが管理してくれます。

コントロールプレーンは冗長化されており、AWSリージョン内の3つのAZをまたいで、少なくとも2つのkube-apiserverインスタンスと3つのetcdインスタンスを配置されます。 またコントロールプレーンに問題が生じた場合は、AWS側が自動的にインスタンス置き換えなどの対応をしてくれます。こういった部分がマネージドである所以ということですね。

ご参考:https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/eks-architecture.html

一方で、ワーカーノード(Node)の部分はある程度ユーザーが管理する必要があります。

Amazon EKSを使い始めるために必要なもの

EKSクラスター作成のために必要なもの

こちらの図はEKSクラスターを作成する際に最低限必要なもの(※NatGatewayについては冗長化は必須ではなく、またNATインスタンスやVPCエンドポイントでも可)を表した図になっています。

上記の図に従い、EKSクラスター作成で必須となるリソースについて確認していきます。
なお、これらのリソースはeksctlであればコマンド一発で作成出来てしまうのですが、知っておくことでより理解を深められると思うので記載しておきます。

  • VPC
    • 要件を満たすVPCを用意する必要があります。代表的な要件は以下です。既存のVPCにEKSクラスターを建てたい場合は注意してください
    • 異なるAZに存在する2つ以上のサブネット
      • 必須要件ではないがパブリックサブネットとプライベートサブネットを作成するのが推奨
    • 各サブネットに6個以上のIPが必須、16個以上推奨
    • VPCが DNS ホスト名DNS 解決 をサポート
    • ノードのデプロイ先がプライベートサブネットの場合はNatまたはVPCエンドポイント
    • ロードバランサーをサブネットにデプロイする場合はサブネットに対して次のタグ
      • (プライベートサブネット)kubernetes.io/role/internal-elb:1
      • (パブリックサブネット)kubernetes.io/role/elb:1
  • クラスターサービスロール

EKSクラスターの作成

さて前提リソースが作成されたことでEKSクラスタを作成できる状態になりましたが、EKSクラスタの作成時には様々な設定項目があります。 ここでは主要な設定項目と設計するに辺り知っておいたほうがよいことをお伝えします

クラスター設定

  • Kubernetesバージョンについて
    • Kubernetesはアップデートサイクルが早く、平均して 4 か月に 1 回、新しい Kubernetes バージョンをリリースしています
    • マイナーバージョンは、リリース後の最初の 14 か月間、Amazon EKS での標準サポートされます
    • バージョンが標準サポート終了日を過ぎると、自動的に延長サポートが開始され、クラスター時間ごとの追加料金が発生するので注意
    • EKSを使う上ではこのアップデートサイクルについていき、なるべく最新のバージョンに追従することが一つのポイントになります。

クラスターアクセス

Kubernetesでコンテナを起動するためには、Kubernetes APIを実行する必要があるわけですが、このAPIを実行するには当然、認証及び認可が必要となります。EKSではこの認証認可方法(クラスター認証モード)として大きく2つのやり方を用意しています

  • EKS APIを使った方法
  • ConfigMap「aws-auth」を使った方法

ConfigMap「aws-auth」は、昔からある認証方法であり、現在はAWSとしてはEKS APIを使った方法を推奨しています。
ConfigMapとはKubernetesのリソースの一種であり、通常はアプリケーションの設定情報(例えばDatabaseのホスト名等)をコンテナに渡すのに使ったりします。
従来、EKSでは以下のような形でIAMユーザやロールによる認証を行い、

EKSクラスターへ「kubectl」コマンドでアクセスする際の認証・認可の仕組みと設定 | DevelopersIO より抜粋

認証したIAMに対して、ConfigMap「aws-auth」を使い、以下のような形でKubernetes APIに対する権限を設定していました。

ConfigMap「aws-auth」を使った認証認可の詳細については下記のブログが大変参考になります。

ポイントはConfigMap「aws-auth」は、Kubernetesがもつリソースであるため、EKSクラスターが作成されていないと操作するのが難しい(コントロールプレーンが出来ていないとKubernetesAPIにアクセス出来ないため)という点です。
EKSクラスターを作成したIAMプリンシパルに関しては初期登録されますが、その他のユーザやそれに紐づく権限についてはEKSクラスター作成時に合わせて設定するといったことが難しいということを意味します。

これに対して新しい方式であるEKS APIを使った認証認可では、ConfigMapを使わないため、KubernetesAPIによる操作が不要になりました。EKSクラスターの有無を気にせずにIAMユーザやロールに対してKubernetesの権限が設定できるようになったので、シンプルになったと言えます。
そのため、新規作成する際はEKS APIを使った認証を選択するのが良いと思います。

EKS APIを使った認証認可ではアクセスエントリとアクセスポリシーという概念を使います。

  • アクセスエントリ:IAMユーザやロール等のIAM プリンシパル ARNとKubernetes上のユーザやグループを紐づける設定です
  • アクセスポリシー:アクセスエントリに対して、どのような権限をどの範囲(クラスター全体か名前空間か)で付与するかを指定します。
    • デフォルトで用意されている権限は以下の通りです。
    • AmazonEKSClusterAdminPolicy – クラスター管理者
    • AmazonEKSAdminPolicy – (特定の名前空間の)管理者
    • AmazonEKSEditPolicy – (特定の名前空間の)ほとんどの Kubernetes リソースを編集できるようにする権限
    • AmazonEKSViewPolicy – (特定の名前空間の)ほとんどの Kubernetes リソースを表示できる権限

EKS APIを使った認証認可の詳細については、以下の記事がとても参考になります。

ネットワーキング

事前に作成したVPCやサブネットなどを指定します。ここで指定したサブネットにコントロールプレーンとワーカーノードが通信するためのkube-api-server通信用ENIが作成されます。

またここで設定するセキュリティグループ(及びデフォルトで作成される eks-cluster-sg-<EKSクラスター名>-<uniqueID> )はkube-api-server通信用ENIとワーカーノードに付与されるセキュリティグループです。

eks-cluster-sg-<EKSクラスター名>-<uniqueID> という名前のセキュリティグループについてはデフォルトでEKSクラスター作成時に必ず作成されます。ネットワーキング設定で指定するセキュリティグループはオプション扱いであり、デフォルトで作成されるセキュリティグループの他に追加でセキュリティグループをつけたい時に使います。

クラスターエンドポイントアクセス

VPC内のワーカーノード等からkube-api-serverに対して通信が発生する際にどの経路を通るか、また、kube-api-serverにパブリックでアクセス可能とするかどうかを選びます。パブリック・アクセスについてはCIDRでアクセス元を制限することもできます。

以下から選択できます。

  • パブリック:kube-api-serverに対してパブリック・アクセス可能。またVPCからkube-api-serverへの通信の際にもVPCの外に出て通信します(ただしAmazon のネットワークからは出ないとのこと)
  • パブリック及びプライベート:kube-api-serverに対してパブリック・アクセス可能。またVPCからkube-api-serverへの通信にはVPC内のENIを経由してプライベートで通信します。
  • プライベート:kube-api-serverに対してパブリック・アクセス不可とする設定です。VPCからkube-api-serverへの通信もVPC内のENIを経由してプライベートで通信します。

パブリック・アクセス可能にしないとVPCと接続された社内ネットワークからしかKubernetesを操作できなくなるなど、特殊な運用をすることになるので、基本的にはパブリック及びプライベートを選択するのが良いです。(EKS ベスト プラクティス ガイドでもパブリック及びプライベートを推奨)

ご参考:VPC とサブネットに関する考慮事項 - EKS ベスト プラクティス ガイド

コントロールプレーンのログ記録

EKSコントロールプレーンのログを記録するかどうかを指定します。記録する場合、CloudWatch Logsに出力されます。

  • ログ種別
    • APIサーバー:Kubernetes API サーバーコンポーネントログ。Kubernetes API を公開するAPIサーバへのAPIリクエストに関するログ
    • 監査ログ:クラスター内の一連のアクションに関するログでそのアクションを発生したのはいつ、誰が、どういったことをといったような情報が記録される
    • Authenticator:EKSクラスターへIAM認証でアクセスした際の認証ログ。IAMのARN等が記録
    • コントローラーマネージャー:クラスターコントローラーの状態に関するログ
    • スケジューラー:スケジュール決定に関するログ

どのログを取得するかはシステム要件に応じて決める必要がありますが、EKSベストプラクティスガイド では「セキュリティのベストプラクティス」として「監査ログ」を取得することを推奨しています。

ご参考:Detective Controls - EKS Best Practices Guides

EKSクラスターでコンテナアプリケーションをデプロイするために必要なもの

EKSクラスターを作成したことでAWSアカウントは以下のような状態になりました。

EKSクラスター上でコンテナアプリケーションを動かすためには更にワーカーノードとkubectlを実行できる端末が必要になります。

  • ワーカーノード
    • ノードIAMロール
    • ワーカーノードに存在するkubeletデーモンは例えばECRからコンテナイメージをpullする等の用途でAWS APIを使用するのでそのためのIAMロールを作成します。なお、クラスターサービスロールとは別のものを付与する必要があります
    • ワーカーノードのIAMロールに最低限必要な権限(詳細はこちら
    • ワーカーノード
    • Amazon EKSでは、ワーカーノードの管理方法として以下の3つのオプションがあります。いずれかの方法でノードを作成します
      1. マネージド型ノードグループ: AWSがノードの管理作業を行ってくれますが、カスタマイズ性も確保されています。運用面の負荷が軽減されます。
      2. セルフマネージド型ノード: ユーザーが完全にノードを管理します。ノードの細かな制御が可能ですが、運用負荷が高くなります。
      3. Fargate: インフラストラクチャ全体をAWSが管理するサーバーレスオプションです。インフラ管理は一切不要ですが、カスタマイズ性に制限があります。
  • Kubectl
    • Pod(コンテナを起動するためのKubernetes上での最小単位)等のKubernetesリソースを作成するために、任意のPC端末等にkubectlコマンドをインストールする必要があります
    • kubectlコマンドを使ってコントロールプレーンのkube-apiserverに対してKubernetesリソースを操作する指示を出します
    • kubectlコマンドを実行する前に、 どこのKubernetesクラスター に対して どのユーザ で認証してコマンドを実行するのかを設定しておく必要があります。
    • EKSの場合、以下のコマンドを使うことで簡単に設定できます。
      • aws eks update-kubeconfig --region ap-northeast-1 --name <EKSクラスター名>
      • EKSクラスターが作成中の場合は Cluster status is CREATING と出力されます。EKSクラスターが作成完了するのを待って再度実行しましょう

最終的にはこのような状態になります。ここまでくればEKSクラスターでコンテナアプリケーションを立ち上げる準備は完了です。

実際に試してみる

さて、これでEKSクラスター上でコンテナアプリケーションを起動する準備が出来ました。

コンテナをデプロイしてみる

コンテナアプリケーションをデプロイしてみます。 コンテナアプリケーションのデプロイだけならそんなに難しくありません。

以下のようなyamlファイルを用意します。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx-container
        image: nginx:1.15

これは、Deploymentと呼ばれるKubernetesリソースで、デプロイすることで replicas の数のPod(コンテナを起動するためのKubernetes上での最小単位)を起動し、またその数を維持するように動きます。

以下のコマンドでkubectlが入った端末からデプロイしてみましょう。

kubectl apply -f ./deploy.yaml

デプロイできたら以下のコマンドでPodが立ち上がっていることを確認してみます。

> kubectl get pod
NAME                    READY   STATUS    RESTARTS   AGE
nginx-57bc7c484-7x27s   1/1     Running   0          4s
nginx-57bc7c484-fzv47   1/1     Running   0          4s
nginx-57bc7c484-mkmj5   1/1     Running   0          4s

無事、アプリケーションコンテナが立ち上がっていることを確認できました!

終わりに

以上、『AWS 入門ブログリレー 2024』の25日目のエントリ『Amazon EKS』編でした。 次回、4/19は弊社平木佳介による「AWS CloudFormation編」の予定です!

以上、とーちでした。

参考資料