😊

Amazon EKSのノードをAmazon Linux 2023にする方法について

2023/11/07に公開

はじめに

2023年11月の時点でAmazon EKS on EC2を構成する際にOSとしてAmazon Linuxを選ぶと、AWSが提供しているOSはAmazon Linux 2のみとなっています。Amazon Linux 2のEOLが2025年6月30日に迫る中、Amazon Linux 2の使用を停止し、EKSノードのOSをAmazon Linux 2023に切り替えることを検討する機会がありました。そのため、その手順について述べます。

Amazon EKS 最適化 Amazon Linux AMIについて

こちらの記事を参照すると、2023年11月時点でAWSより提供されているAMIは、下記のOSです。

Amazon EKS 最適化 Amazon Linux AMI
Amazon EKS 最適化 Bottlerocket AMI
Amazon EKS 最適化 Ubuntu Linux AMI
Amazon EKS 最適化 Windows AMI

Amazon Linux AMIの部分を見ると、Amazon Linuxは、Amazon Linux 2をベースに作成されているようです。

Amazon EKS 最適化 Linux AMI は Amazon Linux 2 上に構築され、Amazon EKS ノードのベースイメージとして機能するように構成されています。

この記事でわかること

AWSドキュメントではEKSのノードとしてデプロイするためのEKS専用AMIを作成する方法が公開されています。その記事では、Amazon Linux向けのAMI作成プロセスが紹介されているため、今回はそれを基に以下の手順をまとめたいと思います。カスタムAMIをEKSのノードとしてデプロイする方法となりますので、Amazon Linux 2023以外のOSでも応用可能だと思います。

  • Amazon EKS 最適化 Amazon Linux 2023のAMIの作成方法
  • 作成したカスタムAMIをEKSのノードとしてデプロイする方法

Amazon EKS最適化 Amazon Linux 2023のAMIの作成

はじめに

公開されているGitHubリポジトリを利用すると、Amazon EKS チームが公式のAMI作成に使用するのと同一のものを作成できるそうです。そこで今回は、このリポジトリを用いて、AMIを作成するプロセスを紹介します。

Packer実行用EC2の作成

このリポジトリでは、Packerを用いてAMIの作成を行うことを前提としています。ローカルの環境にPackerをインストールするのも面倒なので、今回は、PackerをAWS上で実行できるようにします。PackerをインストールするEC2のOSはAmazon Linux 2023とします。

IAMロールの作成

Packerを用いてAMIを作成する際、自動的に以下が行われます。

  1. ソースAMIをもとにEC2が起動
  2. Packerを実行したEC2がそのEC2にログインし、各種ソフトウェアをインストールするためのコマンドを実行
  3. 設定が完了したEC2よりAMIを作成
  4. 起動したEC2を削除

したがって、Packerを実行するEC2インスタンスが他のインスタンスを操作するために必要な権限を持つIAMロールをアタッチすることが必須となります。

必要なIAMポリシーはこちらで公開されており、これをEC2インスタンスに適用します。しかし、このIAMポリシーだけでは十分ではありません。Amazon EKS最適化AMIを作成するためのビルドスクリプトを実行する際に、amazon-eks という名前のS3バケットからバイナリデータを取得する必要があるためです。このため、Packerが必要とする権限のポリシーに加えて、amazon-eks というS3バケットにアクセスするためのポリシーも追加する必要があります。

最終的に、EC2インスタンスからAmazon EKS最適化AMIをPackerで作成するために必要な全ての権限を含んだIAMポリシーは以下の通りです。

Packer用IAMポリシー
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "ec2:AttachVolume",
                "ec2:AuthorizeSecurityGroupIngress",
                "ec2:DeregisterImage",
                "ec2:DeleteSnapshot",
                "ec2:DescribeInstances",
                "ec2:CreateKeyPair",
                "ec2:DescribeRegions",
                "ec2:CreateImage",
                "ec2:CopyImage",
                "ec2:ModifyImageAttribute",
                "ec2:DescribeSnapshots",
                "ec2:DeleteVolume",
                "ec2:ModifySnapshotAttribute",
                "ec2:CreateSecurityGroup",
                "ec2:DescribeVolumes",
                "ec2:CreateSnapshot",
                "ec2:ModifyInstanceAttribute",
                "ec2:DescribeInstanceStatus",
                "ec2:DetachVolume",
                "ec2:TerminateInstances",
                "ec2:DescribeTags",
                "ec2:CreateTags",
                "ec2:RegisterImage",
                "ec2:RunInstances",
                "ec2:StopInstances",
                "ec2:DescribeSecurityGroups",
                "ec2:CreateVolume",
                "ec2:DescribeImages",
                "ec2:GetPasswordData",
                "ec2:DescribeImageAttribute",
                "ec2:DeleteSecurityGroup",
                "ec2:DescribeSubnets",
                "ec2:DeleteKeyPair"
            ],
            "Resource": "*"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::amazon-eks/*",
                "arn:aws:s3:::amazon-eks"
            ]
        }
    ]
}

今回EC2へのPackerセットアップはSystems Manager経由で行うため、上記のIAMポリシーに加え、AWS管理ポリシーであるAmazonSSMManagedInstanceCoreもEC2にアタッチするIAMロールに紐付けします。

Packerのインストール

公開されているビルドスクリプトを使用するにあたり、Packerを使ってAMIを作成することが前提条件となっています。そのため、まずはEC2インスタンスにPackerをインストールすることから始めます。

今回はAWSで起動したEC2インスタンス(OSはAmazon Linux 2023)上にPackerをインストールし、Amazon EKS 最適化 Amazon Linux 2023のAMIを作成します。

実行コマンド ※Systems Manager経由の作業を想定しています。

sudo yum install -y yum-utils

sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/AmazonLinux/hashicorp.repo

sudo yum -y install packer

インストール確認

バージョンが表示されれば成功

packer -v
参考

リポジトリのクローン作成

sudo yum install git

sudo git clone https://github.com/awslabs/amazon-eks-ami

cd amazon-eks-ami

Amazon Linux 2023 AMIテンプレート作成

makeインストール

Packerではmakeが必要になるが、Amazon Linux 2023 ではmakeがインストールされていないため、インストールします。

sudo yum install make

Packerプラグインのインストール

Amazon用のPluginが必要になるとのことなので、インストールします。

sudo packer plugins install github.com/hashicorp/amazon

AMIテンプレート作成

リポジトリの更新により古くなった情報があるため隠しています。以下の更新版をご覧ください。

GitHubリポジトリの中身はAmazon Linux 2023に対応していますが、リポジトリのREADME.mdは更新がされておらず、AMIの作成方法として2種類しか紹介されていません。具体的には、「最新のKubernetesバージョンに対応したAMIを作成する際は、makeコマンドを実施する」ことと、「特定のKubernetesバージョンを指定する際は、make 1.25のようなコマンドを実施すること」(この場合はバージョン1.25を指定)という2種類しか記載がありません。

実際に、makeを実行してもデフォルトで指定されているAmazon Linux 2をベースにAMIが作成されます。Amazon Linux 2 と Amazon Linux 2023 は、仕様に違いがあるため、インストールコマンドにも差があり、カスタムAMIのベースとなるAMIを無理矢理Amazon Linux 2023に変更しても、AMIの作成に失敗しました。

しかし、Makefileの中身を見ると、
Amazon Linux 2023を元にカスタムAMIが作成できるように記述が追加されていました。
内容を確認したい場合は、Makefile内のPHONY: transform-al2-to-al2023 あたりを確認してください。

結論として、Amazon Linux 2023用のAMIテンプレートを作成するには、以下のコマンドを実施することが必要になります。

sudo make transform-al2-to-al2023

上記のコマンドを実行すると、2つのjsonファイルが生成されます。

  • eks-worker-al2023.json
  • eks-worker-al2023-variables.json

eks-worker-al2023-variables.jsonの編集

先ほど生成されたファイルを元にすると、デフォルト状態でus-west-2のリージョンにEKS用のAMIが作成されます。今回はEKSクラスターをus-east-1に構築しているため、AMIもus-east-1に作成されるようにします。

  • eks-worker-al2023-variables.jsonの編集
cd /templates/al2023/
sudo vi eks-worker-al2-23-variables.json

# ファイル内の"aws_region": "us-west-2",の部分を "aws_region": "us-east-1"に変更する

AMIの作成

以下のコマンドを実行すると自動的にEC2が立ち上がり、各種ソフトウェアがインストールされ、インストールが完了した後にAMIが作成されます。(全ての処理が完了するまで10分ほどかかります。)

sudo PACKER_TEMPLATE_FILE=./eks-worker-al2023.json PACKER_DEFAULT_VARIABLE_FILE=./eks-worker-al2023-variables.json make 1.27

更新版(2024年3月12日追記)

リポジトリのREADME.mdが更新され、amazon Linux 2023に対応していることが明記されました。

README.md
# build an AMI with the latest Kubernetes version and the default OS distro
make

# build an AMI with a specific Kubernetes version and the default OS distro
make k8s=1.29

# build an AMI with a specific Kubernetes version and a specific OS distro
make k8s=1.29 os_distro=al2023

# check default value and options in help doc
make help

今回はAmazon Linux 2023にしたいため、make k8s=1.29 os_distro=al2023形式のコマンドが必要になります。

variables-default.jsonの編集

デフォルト状態ではus-west-2のリージョンにEKS用のAMIが作成されます。今回はEKSクラスターをus-east-1に構築しているため、AMIもus-east-1に作成されるようにします。

そのために、リポジトリにあるtemplates/al2023/variables-default.jsonを編集します。

  • variables-default.jsonの編集
sudo vi variables-default.json

# ファイルパスの指定は適宜変更してください。
# ファイル内の"aws_region": "us-west-2",の部分を "aws_region": "us-east-1"に変更する

AMIの作成

以下のコマンドを実行すると自動的にEC2が立ち上がり、各種ソフトウェアがインストールされ、インストールが完了した後にAMIが作成されます。(全ての処理が完了するまで10分ほどかかります。)

cd ../
cd ../
sudo make k8s=1.27 os_distro=al2023

# コマンドを実行する際は、/amazon-eks-ami 配下にしてください。

完了すれば Builds finished. The artifacts of successful builds are: といった表示がされます。

実際にkubernetes 1.27バージョンのAmazon Linux 2023 AMIが作成されていることを確認できました。

起動テンプレートについて

作成したAMIをEKSのノードとして稼働させるためには、このAMIをベースに起動テンプレートを作成する必要があります。EKSでノードを作成する際に、この起動テンプレートを指定することで、EKSのノードに今回作成したAmazon Linux 2023のAMIが使用されることになります。

前提条件

起動テンプレートを作成するにあたり、起動テンプレートのユーザーデータに指定の値を入れる必要があります。指定の値とは、ノードを参加させたいEKSクラスターの情報となります。そのため、起動テンプレートの作成前にEKSクラスターを作成しておく必要があります。なお、本記事ではEKSクラスターの作成方法は割愛します。

こちらを参考に、EKSクラスターの情報を取得します。

EKSクラスターの情報取得方法

EKSクラスターの情報取得方法は、マネジメントコンソールからの取得と、aws eksコマンドでの取得の2種類がありますが、マネジメントコンソールからだとAWS側のアップデートで画面が変更する可能性があるため、本記事では、aws eksコマンドでの取得を紹介します。

今回はAWS CloudShellから実行します。
※AWS CloudShellのIAMがAmazon EKSクラスターのRBAC設定によって承認されていることを前提とします。マネジメントコンソールからEKSクラスターを作成した場合は、追加設定なくCloudShellからコマンドを実行可能だと思います。

  • クラスターの certificate-authority を取得するために、次のコマンドを実行します。
aws eks describe-cluster --query "cluster.certificateAuthority.data" --output text --name Cluster01 --region us-east-1
  • クラスターの api-server-endpoint を取得するために、次のコマンドを実行します。
aws eks describe-cluster --query "cluster.endpoint" --output text --name Cluster01 --region us-east-1
  • クラスターの service-cidrを取得するために、次のコマンドを実行します。
aws eks describe-cluster --query "cluster.kubernetesNetworkConfig.serviceIpv4Cidr" --output text --name Cluster01 --region us-east-1

起動テンプレートの作成

Amazon EKS 最適化 Amazon Linux 2023 AMI と EKSクラスターの情報の準備が完了したので、起動テンプレートの作成に移ります。

起動テンプレートにおいて設定すべきポイントを記載します。

  1. OSイメージの指定
    起動テンプレートの作成にあたっては、指定するOSイメージを事前に作成したAMIにします。

  2. IAMインスタンスプロフィール
    ノード作成時に設定するため、「起動テンプレートの設定に含めない」とします。

  3. ユーザーデータ(2024年5月1日変更)
    下記のように設定します。certificate-authorityapi-server-endpointservice-cidrは事前に取得したものに変更してください。my-clusterに関しても作成したEKSクラスターの名前に変更してください。

※なお、私の環境で試した所、不要な半角スペースが入っているだけでエラーとなったため、試す際にはご注意ください。

MIME-Version: 1.0 
Content-Type: multipart/mixed; boundary="BOUNDARY"

--BOUNDARY 
Content-Type: application/node.eks.aws

---
apiVersion: node.eks.aws/v1alpha1
kind: NodeConfig
spec:
  cluster:
    name: my-cluster
    apiServerEndpoint: api-server-endpoint
    certificateAuthority: certificateAuthority
    cidr: service-cidr

--BOUNDARY--

MIME-Version: 1.0 
Content-Type: multipart/mixed; boundary="BOUNDARY"

--BOUNDARY 
Content-Type: application/node.eks.aws

---
apiVersion: node.eks.aws/v1alpha1
kind: NodeConfig
spec:
  cluster:
    name: Cluster01
    apiServerEndpoint: https://xxxxxxx.eks.amazonaws.com
    certificateAuthority: Y2VydGlmaWNhdGVBdXRob3JpdHk=
    cidr: 10.100.0.0/16

--BOUNDARY--
EKSの更新で仕様に変更があったため以前のものを隠しています。2024年4月以降に生成したAMIでこの中にあるユーザーデータを用いるとエラーとなります。2024年4月以降にAMIを作成した際のユーザーデータは上記のものを参考にしてください。

仕様変更部分は、下記が参考になります。
https://aws.amazon.com/blogs/containers/amazon-eks-optimized-amazon-linux-2023-amis-now-available/

  1. ユーザーデータ
    下記のように設定します。certificate-authorityapi-server-endpointservice-cidrmy-max-pods-valueは事前に取得したものに変更してください。
    (例:--apiserver-endpoint api-server-endpoint の部分は、--apiserver-endpoint https://xxxxxxx.eks.amazonaws.com となるイメージです。)
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="==MYBOUNDARY=="

--==MYBOUNDARY==
Content-Type: text/x-shellscript; charset="us-ascii"

#!/bin/bash
set -ex
/etc/eks/bootstrap.sh Cluster01 \
  --b64-cluster-ca certificate-authority \
  --apiserver-endpoint api-server-endpoint \
  --dns-cluster-ip service-cidr.10 \
  --container-runtime containerd \
  --kubelet-extra-args '--max-pods=my-max-pods-value' \
  --use-max-pods false

--==MYBOUNDARY==--

ノードの参加

作成した起動テンプレートを元に、EKSのノードとしてAmazon Linux 2023のEC2を参加させます。

ノードグループの追加

  • マネジメントコンソールより「ノードグループ」を追加します。

  • 「起動テンプレートを使用する」を有効化して、先ほど作成した起動テンプレートを指定します。

  • その他必要な設定を実施して、ノードグループを作成します。

ノードの確認

設定に成功している場合、ノードグループ作成後、しばらく経過するとノードが参加します。

ノードの情報を見ると、OSイメージがAmazon Linux 2023となっていることが確認できます。

ノードをプライベートサブネットで起動する場合の注意点

EKSのノードが起動する際、/etc/eks/bootstrap.shが実行されます。このスクリプトの実行時に外部のECRなどへのアクセスがあるため、完全に外部サービスと通信できないプライベートサブネットでは、ノードがクラスターに参加できません。

したがって、適宜必要なVPCエンドポイントを設定しておく必要があります。
特にECR用のエンドポイントは必須です。

サービス エンドポイント
ECR com.amazonaws.region-code.ecr.api、com.amazonaws.region-code.ecr.dkr、および com.amazonaws.region-code.s3

詳細については以下を参照してください。
https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/private-clusters.html#:~:text=クラスターの VPC サブネットには、Pods がアクセスする必要のあるすべての AWS のサービス に対して VPN インターフェイスエンドポイントが必要です。詳細については、「インターフェイス VPC エンドポイントを使用して AWS サービスにアクセスする」を参照してください。下表には、一般的に使用されるサービスとエンドポイントがリスト表示されています。エンドポイントの詳細なリストについては、AWS PrivateLink ガイドの「AWS PrivateLink と連携する AWS サービス」を参照してください。

まとめ

今回はAmazon EKS on EC2のノードのOSをAmazon Linxu 2023にする方法についてまとめました。
個人的に、Packerを使用してAmazon EKS専用のAMIを作成するプロセスと、そのAMIを基にEKSノードを構築するプロセスについて、公式のドキュメントでは説明が不足していると感じた部分が多く、実装にはかなりの時間を要しました。この記事が何かのお役に立てば幸いです。

Discussion