Amazon Web Services ブログ

Amazon EKS はマネージド型ノードグループでの Bottlerocket のネイティブサポートを追加しました

この記事は Amazon EKS adds native support for Bottlerocket in Managed Node Groups (記事公開日: 2021 年 10 月 28 日) を翻訳したものです。

2021 年 10 月 28 日、Amazon Elastic Kubernetes Services (Amazon EKS) は、マネージド型ノードグループにおける Bottlerocket のネイティブサポートを発表しました。Bottlerocket は、Amazon が専用に構築した Linux ベースのオープンソースオペレーティングシステムです。セキュリティと保守性に重点を置き、コンテナベースのワークロードに対して、信頼性が高く、一貫性のある安全なプラットフォームを提供します。Amazon EKS のマネージド型ノードグループでの Bottlerocket のサポートによって、マネージド型ノードのプロビジョニングとライフサイクル管理機能のシンプルさを活用しながら、本番環境でコンテナを実行するための最新のベストプラクティスを活用することができます。Bottlerocket ノードで Kubernetes ワークロードを実行することで、セキュリティの強化、クラスター利用率の向上、運用上のオーバーヘッドの軽減などのメリットを得ることができます。

この記事では、Amazon EKS クラスターをセットアップし、Bottlerocket のマネージド型ノードグループを起動します。マネージド型ノードグループのアップデートプロセスを確認し、サンプルアプリケーションをデプロイして Bottlerocket ノードに接続する方法を示します。また、Bottlerocket のマネージド型ノードグループを使用する際の重要な考慮事項についても説明します。

Bottlerocket

企業は、クラウドおよびオンプレミスのアプリケーションのために Kubernetes の標準化に取り組んでいます。Amazon EKS のお客様の大多数は、アプリケーションをクラスターノードにデプロイしています。これらのノードには、さまざまなユースケースに対応した汎用オペレーティングシステムが搭載されており、コンテナオーケストレーションには必要のないパッケージが多数含まれています。コンプライアンス要件を満たすために、これらのパッケージで時間の経過とともに発生する脆弱性に対処するため、オペレーティングシステムをより頻繁にアップデートしなければならない場合があります。また、ノード上で動作するソフトウェアが増えることにより、起動にかかる時間が長くなり、アプリケーションのトラフィック急増に応じてクラスターのコンピューティング能力を迅速にスケールする能力が制限されます。さらに、余分なソフトウェアにより CPU やメモリなどのノードリソースが消費され、コンピューティングコストの増加につながります。

これらの問題に対処するため、AWS は、コンテナ化されたワークロードを実行するために特別に設計された、軽量で安全な Linux ベースのオープンソースオペレーティングシステムである Bottlerocket をリリースしました。Bottlerocket は、コンテナを実行するホストに安全な基盤を提供し、ノードを大規模な維持することに関連する運用上のオーバーヘッドを最小限に抑えるために構築されました。Bottlerocket は、パーミッションの境界を強制することで攻撃対象領域を減らし、セキュリティを強化します。また、イメージベースのアップデート、読み取り専用のルートファイルシステム、API 駆動型の設定により、EKS ノードにまたがる一貫性を確保します。Bottlerocket には、アトミックな自動ソフトウェアアップデートを実行するためのメカニズムがあります。また、デフォルト設定の変更など、通常の管理タスクを実行するためのツールや、緊急時のシナリオに対応するツールも用意されています。

Amazon EKS のマネージド型ノードグループ

Kubernetes はワークロードをノード上にスケジューリングします。これらのノードは、プロビジョニングされ、クラスターに参加し、バージョンアップやセキュリティパッチのために、長期にわたって管理される必要があります。Amazon EKS のマネージド型ノードグループは、Kubernetes クラスターのノードのプロビジョニングとライフサイクル管理を自動化する機能です。Amazon EKS でマネージド型ノードグループを使用する場合、Kubernetes ノードは、アカウント内の Auto Scaling グループによって管理される Amazon Elastic Compute Cloud (Amazon EC2) インスタンスです。マネージド型ノードグループでは、Amazon EC2 インスタンスを個別にプロビジョニングしたり、独自の Kubernetes ノードの AMI を作成したり、クラスターへ参加するノードについて心配したりする必要はありません。Amazon EKS の簡単な操作でノードグループの作成、アップグレード、終了が可能です。

Amazon EKS での Bottlerocket のマネージド型ノードグループのサポートにより、セキュリティが強化されコンテナに最適化されたマネージド型ノード上でアプリケーションを実行できるようになります。Bottlerocket がマネージド型ノードグループの Amazon Machine Image (AMI) オプションとして組み込まれ、ワンクリックでコンテナに最適化されたノードをプロビジョニングできるようになりました。既存のマネージド型ノードグループの通知メカニズムを活用して、より新しい Amazon EKS Bottlerocket AMI が利用可能になったときにアップデートを行うことができます。また、ノードを定期的にリサイクルすることで、さまざまなノードグループタイプにわたって管理を標準化することもできます。

既存の Amazon EKS のマネージド型ノードの更新動作はすべて、Bottlerocket にも適用されるようになりました。Bottlerocket のマネージド型ノードグループのサポートにより、ノードの同時アップグレードによって発生するワークロードのダウンタイムを最小限に抑えることができるようになります。これは、ノードグループの updateConfig の maxUnavailable フィールドに、アップグレード中に利用不可能なノードの最大数を指定することで可能です。また、maxUnavailablePercentage を選択して、利用不可能なノードの最大数をノードの総数に対する割合で指定することもできます。これを使って、同時にダウンさせるインスタンスの最大数を決めることができます。

始めてみよう

このセクションでは、EKS クラスターを作成し、Bottlerocket ノードを起動し、SSM エージェントを使用してコントロールコンテナに接続します。最後に、Bottlerocket ノードをアップデートしてハンズオンを終了します。

前提条件

  • 適切な認証情報と Session Manager プラグインがインストールされた AWS CLI
  • 選択したリージョンのデフォルト VPC。アカウント内の既存の VPC を使用することもできます。
  • リモートアクセス用のアカウントのキーペア。この例ではキーペアの名前は eks_bottlerocket です。
  • 最新バージョンの eksctl (訳注: v0.72.0 以上が必要です)
  • Amazon EKS が提供する kubectl

EKS クラスターの作成

eksctl を使用してクラスターを作成します。以下の設定をコピーし、cluster.yaml というファイルに保存します。

---
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: bottlerocket-cluster
  region: us-west-2

それでは、クラスターを作成しましょう。

eksctl create cluster -f cluster.yaml

マネージド型ノードグループの作成

Graviton2 ARM ベースのインスタンスタイプを含む、汎用 (T シリーズ、M シリーズ) 、コンピューティング最適化 (C シリーズ) 、メモリ最適化 (R シリーズ) のインスタンスタイプに対して、Bottlerocket のマネージド型ノードグループを作成することができます。高速コンピューティングインスタンスタイプ (P, G, Inf1) はサポートされていません。以下の設定を node-group.yaml にコピーします。なお、この設定ではデモ用に SSH が有効になっています。また、SSM はデフォルトで有効になっています。

---
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: bottlerocket-cluster
  region: us-west-2
  version: "1.20"

managedNodeGroups:
  - name: bottlerocket-nodegroup
    instanceType: m5.xlarge
    minSize: 2
    maxSize: 4
    desiredCapacity: 3
    amiFamily: Bottlerocket
    labels: { role: br-worker }
    tags:
      nodegroup-type: Bottlerocket
    ssh:
      allow: true
      publicKeyName: eks_bottlerocket 

それでは、ノードグループを作成しましょう。

eksctl create nodegroup -f node-group.yaml

EKS クラスター内のノードを、いくつかの関心のある属性とともにリストします。

$ kubectl get nodes -o=custom-columns=NODE:.metadata.name,ARCH:.status.nodeInfo.architecture,OS-Image:.status.nodeInfo.osImage,OS:.status.nodeInfo.operatingSystem

NODE                                        ARCH   OS-Image               OS
ip-10-0-101-226.us-west-2.compute.internal  amd64  Bottlerocket OS 1.0.7  linux
ip-10-0-187-156.us-west-2.compute.internal  amd64  Bottlerocket OS 1.0.7  linux

クラスターノードで実行されている Bottlerocket の構成設定を確認しましょう。ノードのインスタンスロールに対して、 SSM 権限をすでに有効にしたため、AWS SSM エージェントがノード上で動作しているはずです。SSM セッションを介してアクセスできます。以下のコマンドを実行してインスタンス ID を見つけることができます。

$ aws ec2 describe-instances --query 'Reservations[*].Instances[*].[InstanceId]' --output text

i-08f2426c826d38ad5
i-068d8f40c6c90a596
i-068d8f40c6c90a798

SSM セッションの開始

Bottlerocket では、分離された containerd インスタンス上で動作するコントロールコンテナがデフォルトで有効になっています。このコンテナは AWS SSM エージェントを実行し、Bottlerocket ノード上でコマンドを実行したり、インタラクティブなシェルセッションを開始したりできるようにします。インスタンスの 1 つを選択し、SSM セッションを起動しましょう。

$ aws ssm start-session --target i-08f2426c826d38ad5

Starting session with SessionId: eks-course-0bf27ea1e078f5c40
Welcome to Bottlerocket's control container!

これで、Bottlerocket の “コントロール” コンテナに接続されました。このコントロールコンテナを独自のものに置き換えたい場合は、ドキュメントを参照してください。SSM を通じてコンテナにアクセスするには、ノードに適切な IAM ロールを与える必要があります。マネージド型ノードグループを使用する場合は、Amazon EKS がこれを処理します。コントロールコンテナにアクセスできるようになると、コマンドを実行できるようになり、インスタンス上で実行されているローカルサービスに対して適切な API 呼び出しを行い、Bottlerocket ノードの設定と管理を行うことができます。これは完全なシェル環境ではなく、使用できるコマンドのセットは限られています。

Bottlerocket API には、システムのアップデートをチェックして開始するためのメソッドが含まれています。アップデート API の詳細については、アップデートシステムのドキュメントを参照してください。ほとんどの操作は apiclient コマンドを介して行われます。詳細はドキュメントに記載されています。apiclient は、これらのアップデート API を処理する方法を知っています。また、apiclient を使用して、インスタンスの構成設定を確認することもできます。

$ apiclient -u /settings

この出力では、ノードの IP アドレス、DNS 設定、motd コンテンツ、アップデート URL などの重要な詳細情報を確認できます。また、クラスターの作成時に SSH を設定したため、管理コンテナが有効になっていることもわかります。

インスタンスへの接続

Bottlerocket には、”管理” コンテナもあります。これはデフォルトでは無効になっており、ホスト上の独自の containerd インスタンス上で動作します。このコンテナでは、SSH サーバーが稼働しており、EC2 で登録した SSH キーを使って ec2-user としてログインすることができます。

ターミナルウィンドウで、ssh コマンドを使用してインスタンスに接続します。プライベートキー (.pem) のパスとファイル名を指定し、前の手順で確認したパブリック IP を使用します。インスタンスに接続するには、次のコマンドを入力します。

ssh -i ~/.ssh/eks_bottlerocket.pem ec2-user@BottlerocketElasticIP

管理コンテナに入ったら、sheltie を実行して、Bottlerocket インスタンスの完全な root シェルを取得します。その後、他の管理コマンドを呼び出すことができます。たとえば、一連のログを収集できます。

sudo sheltie
logdog

これにより、ログアーカイブ /var/log/support/bottlerocket-logs.tar.gz が作成されます。このファイルは SSH で取得できます。Bottlerocket ホストから抜けて、次のコマンドを実行します。

ssh -i ~/.ssh/eks_bottlerocket.pem \
    ec2-user@BottlerocketElasticIP \
    "cat /.bottlerocket/rootfs/var/log/support/bottlerocket-logs.tar.gz" > bottlerocket-logs.tar.gz

サンプルアプリケーションのデプロイ

続いて、サンプル Web アプリケーションをデプロイしましょう。

cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-app
  labels:
    role: webserver
spec:
  replicas: 4
  selector:
    matchLabels:
      role: webserver
  template:
    metadata:
      labels:
        role: webserver
    spec:
      containers:
      - name: frontend
        image: httpd
        ports:
        - containerPort: 80
        command: [ "/bin/sh" ]
        args: ["-c",  "echo '<html> <head> <title>Amazon EKS Sample App</title> <style>body {margin-top: 40px; background-color: #333;} </style> </head><body> <div style=color:white;text-align:center> <h1>Amazon EKS Sample App</h1> <h2>Congratulations!</h2> <p>Your application is now running on a Bottlerocket node in Amazon EKS.</p> </div></body></html>' >  /usr/local/apache2/htdocs/index.html && httpd-foreground"]
EOF

次に、LoadBalancer タイプのサービスを作成します。

cat << EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
  name: sample-app
spec:
  selector:
    role: webserver
  ports:
    - port: 80
      targetPort: 80
  type: LoadBalancer
EOF

新しくデプロイしたサービスの URL を取得します。ロードバランサーのプロビジョニングが完了するまで、数分待つ必要がある場合があります。

kubectl get service sample-app
NAME                TYPE           CLUSTER-IP      EXTERNAL-IP                                                 PORT(S)        AGE
sampleapp-service   LoadBalancer   10.100.14.152   afa7b503ed46f288e96-265681492.us-west-2.elb.amazonaws.com   80:31452/TCP   4m9s

アプリケーションにアクセスして、サンプルの Web アプリケーションの動きを確認しましょう。

curl http://afa7b503ed46f288e96-265681492.us-west-2.elb.amazonaws.com/
<html> <head> <title>Amazon EKS Sample App</title> <style>body {margin-top: 40px; background-color: #333;} </style> </head><body> <div style=color:white;text-align:center> <h1>Amazon EKS Sample App</h1> <h2>Congratulations!</h2> <p>Your application is now running on a Bottlerocket node in Amazon EKS.</p> </div></body></html>

マネージド型ノードグループのアップグレード

既存のアップデート CLI および API を使用して、Bottlerocket ノードグループをアップデートすることができます。Bottlerocket ノードをアップデートする場合、さまざまなシナリオがあります。次のコマンドを使用して、マネージド型ノードグループを、現在ノードにデプロイされているのと同じ Kubernetes バージョンの最新の Bottlerocket AMI リリースにアップデートできます。例えば、パッチバージョン 1.20.7 にアップグレードできます。

eksctl upgrade nodegroup --name=bottlerocket-nodegroup --cluster=bottlerocket-cluster

ノードグループをコントロールプレーンの Kubernetes バージョンと同じバージョンにアップグレードすることができます。例えば、Kubernetes 1.21 を実行しているクラスターがある場合、現在 Kubernetes 1.20 を実行しているノードを以下のコマンドでバージョン 1.21 にアップグレードできます。

eksctl upgrade nodegroup --name=bottlerocket-nodegroup --cluster=bottlerocket-cluster --kubernetes-version=1.21

また、最新バージョンではなく、特定の AMI のリリースバージョンにアップグレードすることも可能です。

eksctl upgrade nodegroup --name=bottlerocket-nodegroup --cluster=bottlerocket-cluster --release-version=1.3.0-395b459c

重要な考慮事項

Bottlerocket は、コンテナの実行に必要な最低限のコンポーネントのみをホストにインストールしてゼロから構築されています。監視エージェントや Container Insights、Prometheus、OpenTelemetry などのメトリック収集システムなどの追加ソフトウェアは、DaemonSet として実行する必要があります。また、Bottlerocket では、Static Pod やホストコンテナの使用も推奨しています。

Bottlerocket で起動テンプレートを使用することで、kubelet に追加の引数を与えたり、ボリュームの種類やサイズを完全に制御したりといったシナリオが可能になります。Bottlerocket マネージド型ノードグループで起動テンプレートを使用する場合、ユーザーデータは TOML 形式である必要があります。ユーザーデータを介して許可される Kubernetes の設定の完全なリストについては、Bottlerocket のドキュメントを参照してください。

Bottlerocket はイメージベースであり、実行中にカスタマイズするためのパッケージマネージャーは含まれていません。設計上の主な目標の一つは、セキュリティとパフォーマンスの観点から、オペレーティングシステムイメージをできるだけ小さくすることです。さまざまなオーケストレーターやバージョンで使用するために、さまざまなバリアントが用意されており、それぞれが固有のソフトウェアや API の設定のセットを持っています。バリアントは、基本的には、インストールされたパッケージのリストと API を定義したモデルです。Kubernetes のバリアントには、AWS 上で Kubernetes ノードを実行するために必要な kubelet、Container Network Interface (CNI) プラグイン、AWS IAM authenticator が含まれています。

カスタム Bottlerocket バリアントを構築するのではなく、DaemonSet を使用することをお勧めします。Bottlerocket AMI でサポートされていない特定のユースケースでは、マネージド型ノードグループのカスタム AMI 機能を使用できます。カスタム AMI を使用する場合は、必要なブートストラップデータ (Kubernetes クラスター接続情報) を EC2 ユーザーデータに含む起動テンプレートが必要です。カスタム AMI、起動テンプレート、ユーザーデータを管理することになります。カスタム AMI の使用に関する詳細は、Amazon EKS のユーザーガイドを参照してください。

さらに、ホストを変更したい場合は、Bottlerocket のブートストラップコンテナを使用することをお勧めします。ブートストラップコンテナは、Kubernetes などのサービスの起動前にホストを初期化するために使用できるホストコンテナです。ブートストラップコンテナは、標準的なホストコンテナ (コントロールコンテナと管理コンテナ) とよく似ており、永続的なストレージと、オプションのユーザーデータを保存する機能を持ちます。ブートストラップコンテナは、ホストのルートファイルシステムとすべてのデバイスへのアクセス権を持ち、CAP_SYS_ADMIN ケーパビリティーで構成されています。これにより、ブートストラップコンテナは、ホスト上にファイル、ディレクトリを生成したり、マウントしたりすることができます。ブートストラップコンテナは、ブートスクリプトが実行される前に実行されます。ここで概要を説明した手順に従って、起動テンプレートとユーザーデータを利用して、ブートストラップコンテナを設定することができます。Bottlerocket ノードで起動テンプレートを使用する方法の詳細については、Amazon EKS ユーザーガイドを参照してください。

クリーンアップ

ハンズオンが完了したら、作成されたリソースを削除して、将来のコストを回避しましょう。

kubectl delete svc sample-app
kubectl delete deployment sample-app
eksctl delete nodegroup --cluster bottlerocket-cluster --name bottlerocket-nodegroup
eksctl delete cluster --name=bottlerocket-cluster

まとめ

この記事では、Amazon EKS のマネージド型ノードグループで Bottlerocket をネイティブに使用する方法と、Bottlerocket のクラスターノードを直接操作する方法を紹介しました。Bottlerocket のコンポーネントはオープンソースです。Bottlerocket はコラボレーティブなコミュニティプロジェクトであること目指しているため、直接貢献したり、独自のカスタマイズ バージョンを作成したりすることができます。Bottlerocket の GitHub プロジェクトに参加し、Issue を開いたりプルリクエストを作成したりして参加することができます。

AWS は Amazon EKS のマネージド型ノードグループでの Bottlerocket のネイティブサポートをご紹介することができ、嬉しく思います。この先も、マネージド型ノードグループのインプレースアップデートや、Amazon EC2 の高速コンピューティングインスタンスタイプでの Bottlerocket サポートなど、エキサイティングなロードマップがあります。今後の機能について学んだり、提案したりするには、GitHub の AWS Containers Roadmap または Bottlerocket Roadmap をご覧ください。

翻訳はプロフェッショナルサービスの杉田が担当しました。原文はこちらです。