コンテナ実行に特化したAWS製オープンソースOS「Bottlerocket」がGAになりました!
みなさん、こんにちは!
AWS事業本部の青柳@福岡オフィスです。
今年3月、AWSからコンテナ実行に特化したOS「Bottlerocket」が発表されました。
発表と同時にパブリックプレビューとして試すことができる状態でしたが、このたび正式版としてリリースされました!
※ なお、Bottlerocketは「EKS」および「ECS」のホストOSとして利用可能ですが、今回GAになったのはEKS向けの利用についてのみですので、ご注意ください。
Bottlerocketとは
パブリックプレビューとして発表された際に、弊社ハマコーがブログ記事を執筆しています。
是非こちらを参照してください。
現時点における制約事項など
今回正式リリースされた時点では、Bottlerocketには以下のような制約があります。
- 「x86」「ARM」の各プロセッサーアーキテクチャに対応しています。
ただし、「GPUインスタンス」「Inferentiaインスタンス」には未対応です。 - EKSをサポートする各リージョンで利用できます。
ただし、以下のリージョンにはデプロイできません。- 中国(北京)リージョン (cn-north-1)
- 中国(寧夏)リージョン (cn-northwest-1)
- AWS GovCloud(米国東部) (us-gov-east-1)
- AWS GovCloud(米国西部) (us-gov-west-1)
- EKSの「マネージドノード」には対応していません。現時点ではアンマネージドなノードとしてデプロイする必要があります。
詳細は、AWSドキュメントを参照してください。
Launching self-managed Bottlerocket nodes - Amazon EKS
試してみた
AWS Blogで公開されている「Getting Started」に沿って、実際に試してみました。
Getting Started with Bottlerocket and Certified AWS Partners | AWS Partner Network (APN) Blog
前提条件
Bottlerocket環境の構築方法にはいくつか手段がありますが、Getting Startedでは「eksctl」コマンドを使用しています。
eksctlはバージョン「0.26.0」以上でBottlerocketに対応しているため、バージョンが古い場合はアップデートしましょう。
ついでに、「kubectl」など関連するツールについても、最新バージョンにしておきます。
$ eksctl version 0.26.0 $ kubectl version --client --short Client Version: v1.18.8 $ aws --version aws-cli/2.0.44 Python/3.7.3 Linux/4.19.104-microsoft-standard exe/x86_64.ubuntu.18
※ kubectlは現在「1.19.0」がリリースされていますが、作成するEKSクラスターのバージョンが「1.17」であるため、マイナーバージョンが2つ以上離れる「1.19.xx」は利用できません。「1.18.xx」を利用しましょう。
Bottlerocketベースのワーカーノードを含むEKSクラスターを作成
パブリックプレビュー時点では、Bottlerocket環境を構築するためには以下の手順が必要でした:
- 通常の (=Amazon Linux 2ベースの) ワーカーノードグループを含むEKSクラスターを作成する
- 作成したEKSクラスターから各種情報 (コントロールプレーン接続のための認証情報など) を取得する
- 作成したノードグループから各種情報 (セキュリティグループ、IAMインスタンスプロファイルなど) を取得する
- BottlerocketのAMIを検索する
- 4.で検索したAMIからEC2インスタンスを起動して、2.および3.で取得した情報を設定する
- 起動した「Bottlerocket」インスタンスがEKSクラスターのワーカーノードとして組み込まれることを確認する
(もっと細かな手順があったかもです)
しかし、GAとなった現在は、もっとシンプルに、Amazon Linux 2ベースのノードグループの場合とほぼ同様の手順で、Bottlerocketベースのノードグループを含んだEKSクラスターを作成することが可能です。
それでは作成していきましょう。
まず、以下のような設定ファイルを作成します。
--- apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: bottlerocket region: ap-northeast-1 version: '1.17' nodeGroups: - name: ng-bottlerocket instanceType: m5.large desiredCapacity: 3 amiFamily: Bottlerocket iam: attachPolicyARNs: - arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy - arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore ssh: allow: true publicKeyName: <キーペア名> bottlerocket: settings: motd: "Hello from eksctl!"
ポイントは以下の通りです:
- 10行目: アンマネージドなノードグループとなるため
nodeGroups:
と記述します。(managedNodeGroups:
と書かないようにしてください) - 14行目:
amiFamily
にBottlerocket
を指定します。 - 15~20行目: これら4つのIAMポリシーは全て必要になりますので、必ず指定します。
- 21~23行目: 後述する「Admin Container」を有効にするために、
ssh:
の設定を記述します - 24~26行目: この部分は必須ではありませんが、Bottlerocketワーカーノードに対して設定したい場合は、ここに記述します。(ここでは
/etc/motd
へメッセージを書き込む設定を行っています)
この設定ファイルを指定して、eksctl create cluster
コマンドを実行します。
$ eksctl create cluster --config-file ./bottlerocket-cluster.yaml
約20分程度でEKSクラスターおよびBottlerocketベースのノードグループが作成されます。
作成されたノードグループを確認してみましょう。
$ kubectl get nodes -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME ip-192-168-38-40.ap-northeast-1.compute.internal Ready <none> 111s v1.17.9 192.168.38.40 18.xx.xx.xx Bottlerocket OS 1.0.0 5.4.50 containerd://1.3.7+unknown ip-192-168-4-210.ap-northeast-1.compute.internal Ready <none> 111s v1.17.9 192.168.4.210 18.xx.xx.xx Bottlerocket OS 1.0.0 5.4.50 containerd://1.3.7+unknown ip-192-168-91-121.ap-northeast-1.compute.internal Ready <none> 111s v1.17.9 192.168.91.121 52.xx.xx.xx Bottlerocket OS 1.0.0 5.4.50 containerd://1.3.7+unknown
各ノードの「OS-IMAGE」の表記が「Bottlerocket OS 1.0.0」となっています。
このように、驚くほどアッサリとBottlerocketベースのノードグループを含んだEKSクラスターを作成することができました。
もちろん、Amazon Linux 2ベースのノードグループと同じように、ノード上でポッドを実行することができます。
(適当なコンテナイメージで試してみてください)
Bottlerocketワーカーノードを管理するための2つの「ツール」
Amazon Linux 2ワーカーノードと変わらない手順で作成することができたBottlerocketワーカーノードですが、Amazon Linux 2ワーカーノードとは大きく異なる点があります。
それは「ワーカーノード (ホストインスタンス) へSSHでログインすることができない」という点です。
(「さっきSSHの設定を書いたやん!」とツッコミたくなったアナタ、もう少し待ってくださいね)
Bottlerocketでは、セキュリティ観点から、sshdサービスが搭載されていません。
しかし、何か問題が発生した時のトラブルシューティングの際など、ノードへ直接ログインすることができないと困りますよね?
そこで、Bottlerocketでは以下の2つの管理用ツールが用意されています。
- Control Container
- Admin Container
これらはいずれも、Bottlerocketワーカーノード上でコンテナとして動作するツールです。
また、これらのコンテナは、EKSコントロールプレーンの管理下にはなく、独立して動作します。
これらのツールについて、順に説明します。
Control Container
Control Containerの主な機能は以下の通りです:
- SSM Session ManagerやSSM Run Commandを使ってControl Containerへ接続することができる
- Bottlerocketワーカーノード上で動作するAPIサーバーに対して、Control ContainerからAPIを発行することができる
SSM Session ManagerでControl Containerへ接続する
細かな説明よりも、実際に使ってみましょう。
作成したBottlerocketワーカーノード3台のうちの1つに対して、SSM Session Managerで接続してみます。
Bottlerocketノードグループを作成する際にデフォルトでControl Containerは有効になっていますし、また、EKSクラスター&Bottlerocketノードグループの構築時にIAMポリシーAmazonSSMManagedInstanceCore
を指定しているため、特に準備をしなくてもSSM Session Managerで接続できるようになっています。
接続に使用するのはAWSマネジメントコンソール、AWS CLIいずれでも構いませんが、今回はAWS CLIを使ってみます。
予め「Session Manager Plugin for the AWS CLI」をインストールしておいてください。
(Optional) Install the Session Manager Plugin for the AWS CLI - AWS Systems Manager
接続対象のBottlerocketワーカーノードのインスタンスIDを確認して、以下のコマンドを実行します。
$ aws ssm start-session --target i-XXXXXXXXXXXXXXXXX
接続に成功すると、以下のようにコンソール表示されます。
Welcome to Bottlerocket's control container! This container gives you access to the Bottlerocket API, which in turn lets you inspect and configure the system. You'll probably want to use the `apiclient` tool for that; for example, to inspect the system: apiclient -u /settings You can run `apiclient --help` for usage details, and check the main Bottlerocket documentation for descriptions of all settings and examples of changing them. If you need to debug the system further, you can enable the admin container. This enables SSH access to the system using the key you specified when you launched the instance. This environment has more debugging tools installed, and allows you to get root access to the host. To enable the admin container, run: enable-admin-container [ssm-user@ip-192-168-4-210 /]$
インスタンスIDを指定して接続しましたが、実際に接続された先はControl Containerとなっています。
APIサーバーへアクセスしてみる
では次に、接続したControl ContainerからBottlerocketワーカーノードのAPIサーバーへアクセスしてみましょう。
APIサーバーへアクセスするためのapiclient
コマンドが用意されています。
$ apiclient Usage: apiclient (-u | --uri) URI [ (-X | -m | --method) METHOD ] [ (-d | --data) DATA ] [ (-s | --socket-path) PATH ] [ -v | --verbose ... ] Method defaults to GET Socket path defaults to /run/api.sock
試しに、以下のようにコマンドを実行してみます。
$ apiclient -u /os
以下のように結果が返ってきます。(見やすいように整形しています)
{ "pretty_name": "Bottlerocket OS 1.0.0", "variant_id": "aws-k8s-1.17", "version_id": "1.0.0", "build_id": "b0e2bc22", "arch": "x86_64" }
Bottlerocketの設定を参照することもできます。
$ apiclient -u /settings
{ "motd": "Hello from eksctl!", "kubernetes": { "cluster-name": "bottlerocket", "cluster-certificate": "XXXX", "api-server": "https://XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.gr7.ap-northeast-1.eks.amazonaws.com", "node-labels": { "alpha.eksctl.io/cluster-name": "bottlerocket", "alpha.eksctl.io/nodegroup-name": "ng-bottlerocket" }, "max-pods": 29, "cluster-dns-ip": "10.100.0.10", "cluster-domain": "cluster.local", "node-ip": "192.168.4.210", "pod-infra-container-image": "602401143452.dkr.ecr.ap-northeast-1.amazonaws.com/eks/pause-amd64:3.1" }, "updates": { "metadata-base-url": "https://updates.bottlerocket.aws/2020-07-07/aws-k8s-1.17/x86_64/", "targets-base-url": "https://updates.bottlerocket.aws/targets/", "seed": 915, "version-lock": "latest", "ignore-waves": false }, "host-containers": { "admin": { "source": "328549459982.dkr.ecr.ap-northeast-1.amazonaws.com/bottlerocket-admin:v0.5.2", "enabled": true, "superpowered": true }, "control": { "source": "328549459982.dkr.ecr.ap-northeast-1.amazonaws.com/bottlerocket-control:v0.4.1", "enabled": true, "superpowered": false } }, "ntp": { "time-servers": [ "169.254.169.123", "2.amazon.pool.ntp.org" ] }, "aws": { "region": "ap-northeast-1" } }
参照だけではなく、設定を変更することもできます。
さきほど出力した設定内容のうち、「ntp」の設定内容を変更してみましょう。
設定を変更するにはHTTPの「PATCH」メソッドを使用します。
$ apiclient -v -u /settings -m PATCH -d '{"ntp": {"time-servers": ["169.254.169.123", "ntp.nict.jp"]}}' 204 No Content
(「204 No Content」は「200 OK」の特殊なパターンで、リクエストは正常に受理されたがレスポンスすべき内容が無い場合のステータスコードです)
PATCHメソッドの実行のみでは完了しておらず、「コミット」を行う必要があります。
コミットは、特定のURLに対して「POST」メソッドをリクエストすることで行います。
$ apiclient -v -u /tx/commit_and_apply -m POST 200 OK
これで、設定の変更が反映されました。
さきほどの「参照」のAPIをリクエストして、「ntp」の設定内容を確認してみましょう。
{ ・・・ "ntp": { "time-servers": [ "169.254.169.123", "ntp.nict.jp" ] }, ・・・ }
ちゃんと変更されたことが確認できました。
SSM Run Commandを使ってControl Containerを操作する
Control Containerに対してSSM Run Commandを使うこともできます。
手元のPCから以下のコマンドを実行します。
$ INSTANCE_ID=i-XXXXXXXXXXXXXXXXX $ COMMAND_ID=$(aws ssm send-command \ --instance-ids $INSTANCE_ID \ --document-name "AWS-RunShellScript" \ --comment "Bottlerocket API Settings" \ --parameters commands="apiclient -u /settings" \ --output text \ --query "Command.CommandId")
これでコマンドが投入されました。
コマンドIDを確認します。
$ echo $COMMAND_ID XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
コマンドIDを指定して、コマンドの実行結果を抽出します。
$ aws ssm list-command-invocations \ --command-id $COMMAND_ID \ --details \ --query 'CommandInvocations[*].CommandPlugins[*][Output]'
さきほどSSM Session Managerで実行した時と同様の結果が返ってきたと思います。
{ "motd": "Hello from eksctl!", "kubernetes": { "cluster-name": "bottlerocket", "cluster-certificate": "XXXX", "api-server": "https://XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.gr7.ap-northeast-1.eks.amazonaws.com", (以下略)
Admin Container
Admin Containerの機能は以下の通りです:
- SSHを使ってAdmin Containerへ接続することができる
- Admin Containerを介して、Bottlerocketワーカーノードに対するshellアクセスを行うことができる
Admin Containerは、デフォルトでは有効になっていません。
場合によってはセキュリティホールになる危険性もあるため、開発やトラブルシューティングなど必要な場合・状況に限定してAdmin Containerを有効にすることが推奨されます。
SSHでAdmin Containerへ接続する
今回は、Bottlerocketノードグループの作成時にAdmin Containerを有効に設定したため、接続が行えるようになっています。
以下のように、構築時に指定したキーペアを使ってSSHで接続します。
$ ssh -i ~/.ssh/<キーペアのpemファイル> ec2-user@<BottlerocketワーカーノードのグローバルIPアドレス>
接続に成功すると、以下のようにコンソール表示されます。
Welcome to Bottlerocket's admin container! This container provides access to the Bottlerocket host filesystems (see /.bottlerocket/rootfs) and contains common tools for inspection and troubleshooting. It is based on Amazon Linux 2, and most things are in the same places you would find them on an AL2 host. To permit more intrusive troubleshooting, including actions that mutate the running state of the Bottlerocket host, we provide a tool called "sheltie" (`sudo sheltie`). When run, this tool drops you into a root shell in the Bottlerocket host's root filesystem. [ec2-user@ip-192-168-4-210 ~]$
BottlerocketワーカーノードのIPアドレスを指定して接続しましたが、実際に接続された先はAdmin Containerとなっています。
Admin ContainerからBottlerocketワーカーノードに対してroot権限でshellアクセスするには、以下のようにsudo sheltie
コマンドを実行します。
$ sudo sheltie bash-5.0#
プロンプトが「#」となり、root権限で各種の管理用コマンドが実行できるようになりました。
ちなみに余談ですが、「sheltie」とは「シェットランド・シープドッグ」という犬の種類の愛称だそうです。
この後に出てくる管理用コマンドは「~dog」というコマンド名で統一されていますので、それにかけたのでしょうかね?
話を元に戻して、いくつかの管理用コマンドを実行してみましょう。
BottlerocketワーカーノードのOSアップデート
Bottlerocketは、パッケージ・ソフトウェア単位ではなくOS全体をまとめてアップデートできることが特徴の一つです。
OSのアップデートを行う流れは以下の通りです。
まずは、アップデートの有無をチェックします。
# updog check-update No update available
う~ん、リリースされたばかりのAMIから起動したためか、「アップデートは無い」という結果になってしまいました。
アップデートが見つかった場合には、以下のコマンドでアップデートを実行することができます。
# updog update
詳しいアップデートの手順については、別途調べてみたいと思います。
Bottlerocketワーカーノードのログ採取
Bottlerocketワーカーノードの各種ログを一括して採取することができます。
# logdog Running: exec containerd-config containerd --config /etc/containerd/config.toml config dump Running: exec containerd-config-host containerd --config /etc/host-containerd/config.toml config dump Running: exec df df -h Running: exec df-inodes df -hi Running: exec dmesg dmesg --color=never --nopager Running: exec iptables-filter iptables -nvL -t filter Running: exec iptables-nat iptables -nvL -t nat Running: exec journalctl-boots journalctl --list-boots --no-pager Running: exec journalctl.errors journalctl -p err -a --no-pager Running: exec journalctl.log journalctl -a --no-pager Running: exec proc-mounts cat /proc/mounts Running: exec settings.json apiclient --method GET --uri / Running: exec signpost signpost status Running: exec wicked wicked show all Running: file os-release /etc/os-release Running: exec kube-status systemctl status kube* -l --no-pager logs are at: /tmp/bottlerocket-logs.tar.gz
様々なログが集められて/tmp/bottlerocket-logs.tar.gz
ファイルにアーカイブされました。
これをローカルPCに持ってきて解析したいところですが、SCPは使えないため、以下のようにしてローカルPCへコピーします。
$ ssh -i ~/.ssh/<キーペアのpemファイル> ec2-user@<BottlerocketワーカーノードのグローバルIPアドレス> "cat /.bottlerocket/rootfs/tmp/bottlerocket-logs.tar.gz" > bottlerocket-logs.tar.gz
あとは、ローカルPCにコピーされたbottlerocket-logs.tar.gz
ファイルを解凍すれば、採取したログを参照・解析することができますね。
おわりに
Bottlerocketには、今回紹介したものの他にも、様々な機能や利用方法があります。
それらについても、おいおい試してみてご紹介したいと思います。
今回ご紹介したように、BottlerocketはこれまでのAmazon Linux 2と同じような手順でデプロイすることができ、既存のシステムを少ない手間でよりセキュアなコンテナ実行環境へ移行できることが期待されます。
また、Bottlerocketはリリース時点で既に多くのサードパーティ (APNパートナー) がサポートを提供しています。
例えば、以下のようなベンダー・製品がBottlerocketをサポートしています。
- 「Datadog」「New Relic」「Splunk」などのロギング・モニタリング製品
- 「Aqua Security」「Trend Micro」などのセキュリティ製品
- 「GitLab」などのDevOps関連製品
(これらはサポートベンダーの一部です。全てのサポートベンダーのリストは、今回参考にしたAWSブログの最後の方に掲載されています)
Announcing the General Availability of Bottlerocket, a new open source Linux-based operating system purpose-built to run containers
このように、将来性が非常に期待できる「Bottlerocket」がいよいよ正式リリースされました。
EKSの新機能・新サービスの中では、比較的簡単に試せるかな?という印象なので(笑)、皆さんも是非試してみてくださいね。