sample-the-physical-ai-toolchain-on-aws

Activity, over time

Daily observations from the public event archive.

Attention

Daily stars & forks

Loading attention chart

Star accumulation

Cumulative stars

Loading star accumulation chart

Pull requests

Daily opens & merges

Loading pull requests chart

Conversations

Daily issues & comments

Loading conversations chart

Community

Daily accounts & reviews

Loading community chart

Releases

Daily releases

Loading releases chart

Mentions

4posts · 30d
Nov 40 posts
  1. Zenn · · @yohakucode

    1台の VM の k3s で Deployment・Service・Job を動かして確かめる Kubernetes と EKS の入門 docker run を使うと、コンテナを1つ動かせます。ただ、たくさんの人がアクセスするようなシステムでは、コンテナが1つだけだと、アクセスが増えたときに処理が追いつかずに応答が遅くなり、そのコンテナが落ちれば全体が止まってしまいます。そのため、同じコンテナをいくつも並べて動かすことがよくあります。 コンテナを3つ並べておけば、リクエストを3つに分けて受けられ、1つが落ちても残りの2つで応答を続けられます。新しいバージョンへの入れ替えも、1つずつ行えば、サービスを止めずに済みます。ロボットの学習でも、同じシミュレーションを何本も並べて流せば、データを早くそろえられます。 並べる数が増えれば増えるほど、落ちたものを見つけて立て直す、順に入れ替える、といった作業を人が手でこなすのは大変になってきます。そこで活躍するのが Kubernetes(k8s)です。 AWS Physical AI Toolchain の記事では、データ作り・学習・評価といった段階をつなぐ OSMO が、Amazon EKS(AWS の k8s)の上で動く、と書きました。この記事は、その土台になる k8s の入門です。1台の VM に k3s(軽い k8s)を入れて、基本の部品を1つずつ動かしながら確かめます。最後に、EKS で何が変わるかと、OSMO とのつながりをまとめます。 Kubernetes が受け持つこと k8s には「このコンテナを3つ動かしておく」のように、こうなっていてほしい形を書いて渡します。k8s は、その形になるように動き、ずれたら直し続けます。この記事で動かすものの関係を、ノード3台とコントロールプレーン1台の、マシン4台の形で図にしました1。マシンごとに、中で何が動いているかを描いています。Pod をどのノードに何個置くかは、こちらでは書きません。コントロールプレーンのスケジューラーが決めます(図では、ノード1に2つ、ノード3に1つ)。この記事で試すのは、オレンジの点線で囲んだ範囲です。VM 1台の k3s が、コントロールプレーンとノード1台を兼ねるので、3つの Pod はすべてそのノードに置かれます。 指示の流れ(黒の①〜④)と、ノードが取りに行く流れ(紫)と、リクエストの道(緑)。Service は1つのプログラムではなく、記録はコントロールプレーンに、振り分けの決まりは各ノードにある。オレンジの点線の中が、この記事で試す範囲 Pod:コンテナを動かす最小の単位。Pod 1つに IP が1つ付く。消えたり立ったりするので、IP も変わる Deployment:「この Pod を何個」と書いたもの。バージョンごとに ReplicaSet を作り、ReplicaSet が Pod の数を保つ Service:同じラベル(Pod に付ける目印。ここでは app: web)の Pod をまとめ、変わらない名前と IP で呼べるようにする ノード:Pod が動くマシン。中で kubelet というプログラムが動き、言われた Pod のコンテナを起動する コントロールプレーン:クラスター全体を管理するプログラムのまとまり。マニフェストを受け取って、どのノードで動かすかを決め、書かれた形を保ち続ける。昔はマスターと呼ばれていた。普通はノードとは別のマシンで動かすが、この記事の k3s では、ノードと同じ VM で動く クラスター:k8s が面倒を見るマシンのまとまり。普通は何台ものマシンで1つのクラスターを作り、どのマシンで動かすかは k8s が決める。この記事では、k3s を入れた VM 1台がそのままクラスターになる。Pod や Service は、クラスターの中に作られる マニフェストと kubectl:マニフェストは、クラスターに作ってほしいもの(Deployment や Service など)を書いた YAML のファイル。この記事では web.yaml と job.yaml。kubectl は、マニフェストをクラスターに渡したり、中の様子を見たりするコマンド k3s を入れる k3s は、k8s を1つの実行ファイルにまとめたものです。1台に入れるだけで、全部が動きます。試した VM は Oracle Linux 9(Arm)、CPU 1コア、メモリ 6GB で、k3s の公式の最低条件(CPU 2コア)を下回っています。このあとの秒数や失敗の回数は、この小さな VM でのものです。 k3s には、兄弟にあたる RKE2 もあります。入れ方は k3s をもとにしていて、セキュリティの基準(CIS ベンチマーク。k8s を安全に設定するためのチェック項目)を、初期設定のままで満たしやすく作られています。公式の最低条件は k3s より大きく、メモリは k3s の 2GB に対して 4GB です。この記事は小さな VM での入門なので、k3s を使います。 curl -sfL get.k3s.io | \ INSTALL_K3S_VERSION='v1.36.5+k3s1' \ INSTALL_K3S_EXEC='server --disable traefik --disable servicelb' \ sh - k3s には、外から来たリクエストを受けるためのソフトが、最初から2つ入っています。 servicelb:Service には、外から受けるための type: LoadBalancer という種類があります。クラウドでは、これを作るとクラウドの側がロードバランサーを用意します(AWS なら NLB)。自分のマシンには用意してくれる相手がいないので、k3s では servicelb が代わりを務めます。各ノードで、Service に書いたポート番号(たとえば 80 番)をそのまま受けて、Service に渡します。ノードが1台なら振り分ける先はなく、外からの入口を開けるだけです。Pod への振り分けは、このあと出てくる kube-proxy が書いた決まりで行われます Traefik:リバースプロキシ(外から来た HTTP のリクエストを受けて、後ろに渡すソフト)です。Ingress(URL ごとに、どの Service へ渡すかを書いた決まり)に従って振り分けます。k3s では、Traefik 自身が type: LoadBalancer の Service になっていて、servicelb を通してノードのポートの 80 番と 443 番で受けます 2つは別々に外せます。組み合わせごとに、外からどこで受けるかを図にしました。 servicelb と Traefik の組み合わせと、外からの入口 この記事では、2つとも k3s を入れるときに外しました。外からは NodePort でつなぎます。NodePort は、ノードのポートを 30000〜32767 番の範囲から1つ開ける種類の Service で、ロードバランサーがなくても使えます。 RHEL 系の OS では、2つ気をつけることがあります。 SELinux:有効なら、導入スクリプトが k3s-selinux を入れます。この手順を INSTALL_K3S_SKIP_SELINUX_RPM=true で飛ばしたら、実行ファイルに SELinux のラベルが付かず「Permission denied」で起動しませんでした。sudo restorecon -v /usr/local/bin/k3s で直りました firewalld:公式の手順は firewalld を止めることを勧めています。止めない場合は、Pod と Service が使う範囲を信頼する側に足します sudo firewall-cmd --permanent --zone=trusted --add-source=10.42.0.0/16 # Pod の範囲 sudo firewall-cmd --permanent --zone=trusted --add-source=10.43.0.0/16 # Service の範囲 sudo firewall-cmd --reload OS に関係なく、気をつけることがもう2つあります。 ufw:Ubuntu などで使う ufw も、公式の手順は止めることを勧めています。止めない場合は、firewalld と同じく、Pod と Service の範囲からの通信を許します sudo ufw allow from 10.42.0.0/16 to any # Pod の範囲 sudo ufw allow from 10.43.0.0/16 to any # Service の範囲 範囲の重なり:Pod と Service の範囲(10.42.0.0/16 と 10.43.0.0/16)が、クラスターとやり取りする相手(つなぎに来る利用者、Pod からつなぐ先、VPN。Tailscale なら 100.64.0.0/10)の範囲と重なると、その相手に届かなくなったり、応答が戻らなくなったりします。重なるときは、入れるときに --cluster-cidr(Pod の範囲)と --service-cidr(Service の範囲)で、10.0.0.0/8 などのプライベートの範囲から、重ならない範囲を選びます。あとから変える手順は公式に載っていないので、最初に決めておきます。範囲を変えたら、firewalld や ufw に足した範囲も合わせて変えます kubectl は、root しか読めない設定ファイルを自分の場所に写してから使います。このファイルにはクラスターの管理者の鍵が入っているので、人に渡さないでください。 mkdir -p ~/.kube sudo cat /etc/rancher/k3s/k3s.yaml > ~/.kube/config chmod 600 ~/.kube/config export KUBECONFIG=~/.kube/config # 指定しないと /etc/rancher/k3s/k3s.yaml を読みに行く kubectl get nodes 30秒ほどでノードが使える状態(Ready)になりました。k3s 全体のメモリは、およそ 1GB でした。 Deployment で3つ並べる ここからは、1つのマニフェスト web.yaml を使います。コンテナは traefik/whoami という小さな Web サーバーで、自分の Pod の名前を返します。どの Pod が応答したかが分かるので、振り分けを見るのに向いています。 web.yaml apiVersion: apps/v1 kind: Deployment metadata: name: web spec: replicas: 3 # Pod を3つ動かしておく selector: matchLabels: app: web # ラベル app: web の Pod の面倒を見る template: # Pod の作り方 metadata: labels: app: web spec: containers: - name: whoami image: traefik/whoami:v1.11.0 args: ["--port", "8080"] ports: - containerPort: 8080 readinessProbe: # /health が失敗を返したら、振り分け先から外す httpGet: path: /health port: 8080 periodSeconds: 2 failureThreshold: 2 lifecycle: # 止める前に5秒待つ preStop: sleep: seconds: 5 resources: requests: cpu: 50m memory: 16Mi limits: memory: 64Mi --- apiVersion: v1 kind: Service metadata: name: web spec: type: NodePort selector: app: web # 振り分け先はラベル app: web の Pod ports: - port: 80 targetPort: 8080 nodePort: 30080 # クラスターの外からは、ノードのポート 30080 番で受ける kubectl apply -f web.yaml kubectl rollout status deployment/web kubectl get rs,pods 7.5 秒でそろいました。web という名前の Deployment が、web-5f94c944b という名前の ReplicaSet を作り、その ReplicaSet が web-5f94c944b-xxxxx という名前の Pod を3つ作っています。真ん中の 5f94c944b は、Pod の作り方(template)の中身から計算した値で、作り方を変えると変わります。最後の5文字は、Pod ごとにランダムに付きます。 NAME DESIRED CURRENT READY AGE replicaset.apps/web-5f94c944b 3 3 3 8s NAME READY STATUS RESTARTS AGE pod/web-5f94c944b-kftn5 1/1 Running 0 8s pod/web-5f94c944b-kpff5 1/1 Running 0 8s pod/web-5f94c944b-mrx7f 1/1 Running 0 8s kubectl delete pod で Pod を1つ消すと、数秒で代わりの Pod が立ち、3つに戻りました。マニフェストの kind は作るものの種類で、kind: Pod や kind: ReplicaSet と書いて直接作ることもできます。ただ、Pod だけを作ると、消えても誰も立て直しません。ReplicaSet は数を保ちますが、新しいバージョンへの入れ替えはできません(入れ替えは、Deployment が新旧2つの ReplicaSet を使い分けて行います)。そのため、ずっと動かすものは Deployment に、終わりのある仕事は Job に作らせるのが普通です。kind に書けるほかの種類は、記事の最後の付録にまとめました。 resources の requests は「このくらいは確保してほしい」量で、k8s はこれを見て Pod を置くノードを選びます。limits は上限で、メモリが超えるとコンテナは止められます。CPU は上限に当たっても遅くなるだけなので、メモリだけ上限を決めました(考え方が分かれるところです)。 Service でまとめる Pod の IP は変わるので、Pod を名指しで呼ぶと追いかけるのが大変です。Service は、ラベル app: web の Pod をまとめて、変わらない名前で呼べるようにします。 ラベルは キー: 値 の形の目印で、キーも値も自分で決めます。web.yaml では、Deployment の template の中で Pod に app: web を付け、Service の selector で同じ app: web を指定しました。app は決まった言葉ではなく、k8s のドキュメントの例でもよく使われるキーの名前です。metadata の name は、そのもの自身の名前です。名前空間(namespace。クラスターの中を分ける区切りで、指定しなければ default)ごとに、同じ種類の中で1つだけで、kubectl get service web のように名指しするときに使います。Service の名前は、このあとの名前引きの名前(web)にもなります。ラベルは何個のものに同じ値を付けてもよい目印で、Service や Deployment はこれで Pod を選びます。web.yaml では、Deployment の名前、Service の名前、ラベルの値をどれも web にそろえましたが、それぞれ別々に決められます。 クラスターの中からは、web という名前で呼べます。使い捨ての Pod を立てて試しました。 kubectl run tmp --rm -i --restart=Never --image=busybox:1.37 -- wget -qO- web Hostname: web-5f94c944b-kftn5 名前を答えているのは、クラスターの中で Pod として動く CoreDNS(名前引きのサーバー。k3s では最初から入っている)です。名前を引くと Service の IP(10.43.121.7)が返り、正式な名前は web.default.svc.cluster.local でした。Service の名前 web のあとに、名前空間の default が続きます。同じ名前空間の Pod からは web だけで、別の名前空間からは web.default のように呼びます。 Service の IP は、Pod の IP とは別の範囲から付きます。k3s の初期設定では、Pod は 10.42.0.0/16、Service は 10.43.0.0/16 です。Service の IP 宛に送ったリクエストは、ノードの Linux の iptables(通信の行き先を書き換えたり、通すか止めるかを決めたりする仕組み)によって、どれか1つの Pod の IP 宛に書き換えられて届きます。そのための決まりを iptables に書くのが kube-proxy です。kube-proxy は各ノードで動くプログラムで、Service と Pod の様子を見張り、Pod が増えたり減ったりするたびに決まりを書き直します。リクエストそのものは kube-proxy を通りません。書き換えるのは、決まりに従ったノードの Linux です。Service の IP はクラスターの中で使うものなので、外からは次の NodePort でつなぎます。 Service には種類があり、type で選びます。下の種類ほど、上の種類の働きを含みます。 種類 呼べる場所 ClusterIP(何も書かないとこれ) クラスターの中だけ。Service の IP と名前で呼ぶ NodePort 上に加えて、すべてのノードの同じポート(30000〜32767 番)で、外から呼べる LoadBalancer 上に加えて、外のロードバランサーを付ける。クラウドでは自動で用意され、k3s では servicelb が代わりをする web.yaml は NodePort にしました。NodePort はプログラムではなく、kube-proxy が各ノードに書く決まりです。ノードのポート 30080 番に来たリクエストを、web の Pod のどれかに渡します。ほかの入口を使うときの書き分けは、記事の最後の付録にまとめました。 クラスターの外からは、ノードの IP のポート 30080 番(NodePort)で呼べます。Pod の IP や Service の IP は、クラスターの中だけで使うものなので、外からは使えません。この記事ではノードは VM 1台なので、ノードの IP は VM の IP です。VM の外からつなぐときは、クラウドの側のファイアウォール(OCI のセキュリティ・リストなど)でも 30080 番を開けます。 ノードの IP の 30080 番に、30回送りました。 for i in $(seq 30); do curl -s http://<ノードの IP>:30080/ | grep Hostname; done | sort | uniq -c 8 Hostname: web-5f94c944b-kftn5 12 Hostname: web-5f94c944b-kpff5 10 Hostname: web-5f94c944b-mrx7f 3つに分かれましたが、順番ではありません。kube-proxy が書いた iptables の決まりが、リクエストごとに確率で行き先を選んでいます。 readinessProbe で調子の悪い Pod を外す readinessProbe は、Pod の調子を決まった間隔で確かめる仕組みです。web.yaml では、2秒ごとに /health を確かめ、2回続けて失敗したら、Service の振り分け先から外します。返ってきた状態コードが 200〜399 なら成功、それ以外は失敗です。 whoami は、/health に POST すると返す状態コードを変えられます。1つの Pod だけ 500 を返すようにしました。 curl -X POST -d 500 http://<Pod の IP>:8080/health 2.3 秒で、その Pod の READY が 0/1 になり、振り分け先の一覧(EndpointSlice)でも外れました。この間に30回送ると、外れた Pod には1回も渡りませんでした。 web-5f94c944b-kpff5 0/1 Running 0 48s 12 Hostname: web-5f94c944b-ml9l4 18 Hostname: web-5f94c944b-mrx7f ml9l4 は、Deployment の節で Pod を1つ消したときに、代わりに立った Pod です(実際には、Service の節の30回を送ったあとに消しました)。200 に戻すと、READY は 1/1 に戻りました。外すだけで Pod は止めないので、RESTARTS も 0 のままです。 似た仕組みの livenessProbe は、失敗したらコンテナを起動し直します。k8s のドキュメントは、間違った設定は連鎖的な障害につながるので気をつけて使うように、と書いています。この記事では試していません。 止めずに新しいバージョンへ入れ替える kubectl set image deployment/web whoami=traefik/whoami:v1.12.0 kubectl rollout status deployment/web Deployment は、新しい Pod を立てては古い Pod を止める、を繰り返して入れ替えます(ローリングアップデート)。何も書かなければ、一度に増やしてよい数も減らしてよい数も 25% で、Pod が3つなら「1つ増やし、使えるようになったら古いのを1つ止める」になります。10秒ほどで入れ替わりました。 入れ替えの途中の失敗 入れ替えの間、0.05 秒おきに NodePort へ送り続けて(1回の入れ替えで370〜540回)、失敗を数えました。 preStop 入れ替えた回数 1回の入れ替えでの失敗の数 なし 5回 2, 4, 2, 5, 6 あり(5秒) 9回 1, 1, 0, 0, 0, 0, 1, 0, 0 失敗には、すぐ断られるもの(curl の終了コード 7)と、3秒待っても応答がないもの(終了コード 28)がありました。 すぐ断られるほうには、はっきりした理由があります。Pod を止めると決まると、k8s は「振り分け先から外す」と「コンテナに止まれと合図(SIGTERM)を送る」を同時に進めます。コンテナが先に止まると、まだ外れる前の振り分けで届いたリクエストが、もういないコンテナに当たります。 Pod を止めるときの順番 preStop の sleep は、合図を送る前に決めた秒数だけ待ちます。その間に振り分け先から外れます。preStop ありでは、すぐ断られる失敗は、記録できた範囲で出ませんでした(最初の2回は種類を記録していません)。3秒の時間切れは、ありなしにかかわらず少し出て、理由は確かめられていません。CPU 1コアで、新しい Pod の起動と取り合っているのかもしれませんが、推測です。 sleep は、コンテナの中のコマンドを使わずに待てる書き方で、シェルの入っていないイメージでも使えます。待つ時間は、Pod を止めるまでの猶予(何も書かなければ30秒)に含まれます。 前のバージョンには kubectl rollout undo で戻せますが、kubectl apply で渡した Deployment に使うと「ファイルを戻して apply し直して」という意味の警告が出ました。set image も含めて、ファイルを正にするなら、バージョンもファイルで書き換えて apply するのが筋です。 Job で終わりのある仕事を流す Deployment は「ずっと動かしておく」もの、Job は「終わりのある仕事を、最後までやらせる」ものです。Deployment では、コンテナの中のプログラムが終わると「落ちた」とみなされて、起動し直されます。Job では、プログラムがうまく終われば「やり終えた」とみなされ、Pod は完了(Completed)のまま残ります。失敗して終わったときだけ、やり直します。データを作る、学習を回す、といった仕事は、こちらで流します。 試した job.yaml は、本物の仕事の代わりに、part 0 start と表示して3秒待ち、part 0 done と表示して終わるだけのコマンドを動かします。本物の仕事なら、command のところが、データを作るスクリプトや学習のスクリプトになります。 job.yaml apiVersion: batch/v1 kind: Job metadata: name: count spec: completionMode: Indexed # 0、1、2 の番号を振る completions: 3 # 3つの部分をそれぞれ1回成功させる parallelism: 1 # 同時に動かすのは1つ(CPU 1コアなので) backoffLimit: 2 # 失敗したら2回までやり直す ttlSecondsAfterFinished: 600 # 終わって10分たったら片付ける template: spec: restartPolicy: Never containers: - name: work image: busybox:1.37 command: ["sh", "-c", "echo part $JOB_COMPLETION_INDEX start; sleep 3; echo part $JOB_COMPLETION_INDEX done"] この Job は、同じ仕事を 0・1・2 の番号で3つに分けて、1つずつ流します。 completions: 3:Pod が3つ成功したら、Job は終わり completionMode: Indexed:Pod に 0・1・2 の番号を振る。番号は、環境変数 JOB_COMPLETION_INDEX でコンテナに渡る parallelism: 1:同時に動かす Pod は1つ。この VM は CPU 1コアなので、1つずつにした kubectl apply -f job.yaml で渡すと、23秒で 3/3 が終わりました。番号ごとのログは part 0 start、part 0 done、…、part 2 done でした。 いくつも同時に流す parallelism を 3 にすると、番号 0・1・2 の Pod が同時に動きます。番号で仕事を分けておけば、「データの 0 番目のかたまりは、番号 0 の Pod が受け持つ」のように、大きな仕事を分けて並べられます。 中身の違う仕事は、Job を別々に書いて、それぞれ kubectl apply で渡します。Job 同士は互いを待たず、ノードに空きがあれば同時に動きます。空きが足りなければ、Pod は Pending のまま、空くのを待ちます。 順番に流す 「データを作る Job が終わってから、学習の Job を流す」のような順番は、Job のマニフェストには書けません。Job には、ほかの Job を待つという書き方がないからです。一番簡単なのは、手元で前の Job が終わるのを待ってから、次を渡す方法です。3行を && でつないで、1つのコマンドとして流します。 kubectl apply -f make-data.yaml && kubectl wait --for=condition=complete job/make-data --timeout=1h && # 終わるまで待つ kubectl apply -f train.yaml 1行ずつ手で打つなら、kubectl wait が終わるまで次の行は打てないので、&& がなくても順番は守れます。&& でつないでおくと、まとめて貼り付けたときや、スクリプトにして放っておくときも、前が成功したときだけ次に進みます。; でつなぐと、前が失敗しても次に進んでしまいます。make-data が失敗すると、kubectl wait は1時間たつまで待ち続けて失敗で終わるので、train.yaml は渡されません。段が増えたり、枝分かれしたりするなら、Argo Workflows のような、Job の順番を書くための仕組みを使います。EKS の節で出てくる OSMO も、データ作り・学習・評価といった段階を、順につないで流す仕組みです。GPU を使う学習やシミュレーションを Job で流す話は、別の記事で扱う予定です。 k3s 以外の選び方 ここまでは k3s で動かしてきましたが、k8s を動かすソフトはほかにもいくつもあります。どれも中身は k8s なので、マニフェストの基本の書き方は同じです。違うのは、どこで、何のために動かすかです。この節は公式のページを読んでまとめたもので、k3s 以外は試していません。 やりたいこと 候補 手元の PC で触ってみる minikube・kind・k3d 小さなサーバーやエッジで動かす k3s・k0s・MicroK8s 自分のサーバーで本番を動かす RKE2・kubeadm・Talos Linux・OpenShift クラウドで本番を動かす EKS・GKE・AKS minikube:k8s の公式プロジェクト。アプリを作る人と、k8s を初めて使う人に向けている kind:Docker のコンテナをノードの代わりにする。もとは k8s そのもののテスト用で、CI にも使える k3d:k3s を Docker のコンテナの中で動かすツール k0s:k3s と同じく、1つの実行ファイルで動く MicroK8s:Canonical(Ubuntu の会社)製。snap で入れて、機能をコマンド1つで足したり外したりする kubeadm:公式の組み立てツール。クラスターを立てるところだけを受け持ち、マシンの用意や、ネットワークなどの追加部品(アドオン)は自分で入れる Talos Linux:k8s のためだけの OS。SSH もシェルもなく、API で操作する OpenShift:Red Hat 製。k8s に手を加え、部品をたくさん最初から入れた大きな作り。もとになっているのは、コミュニティが作る OKD で、無料で使える GKE・AKS:Google Cloud と Microsoft Azure の k8s。この記事では、次の節で EKS だけを取り上げる ここからは公式の基準ではなく、私の整理です。迷ったときは、次の順に考えると絞れます。 コントロールプレーンの面倒を誰が見るか 一番大きな分かれ目です。自分で持つと、バージョンを上げる、etcd(クラスターの状態を覚えておくデータベース)のバックアップを取る、といった作業も自分の仕事になります。クラウドを使えるなら、EKS のようなサービスに任せるのが最初に考える候補です 壊して作り直してよいか 試すだけなら、PC の上ですぐ作り直せる minikube・kind・k3d で足ります マシンの大きさ メモリが少ないマシンや、エッジの機械なら k3s・k0s・MicroK8s です セキュリティの基準を求められるか CIS ベンチマークなどへの対応を求められるなら、最初からそれを見込んで作られている RKE2 や OpenShift が候補です EKS では何が変わるか EKS は試していないので、公式のドキュメントから整理しました。 この記事の k3s Amazon EKS コントロールプレーン 同じ VM の中 AWS が動かす。1か所が止まっても続くように、いくつかのデータセンター(アベイラビリティーゾーン)に分けて置かれる。クラスター1つにつき1時間 0.10 ドル(標準サポートのバージョンの場合) ノード 同じ VM EC2。自分でノードグループを作るか、EKS Auto Mode に任せる 外からの入口 NodePort Service から NLB、Ingress から ALB を作る ディスク ノードのディスク EBS(AWS のブロックストレージ) kubectl 同じ 同じ。aws eks update-kubeconfig で設定ファイルを作る EKS Auto Mode を使うと、マシンの増減、ロードバランサー、ディスク、GPU まわりを AWS が最初から用意します。eksctl(EKS のクラスターを作るコマンド)なら、クラスターの名前と地域に autoModeConfig: {enabled: true} を足しただけの YAML で作れます。Auto Mode を使わない場合は、AWS Load Balancer Controller や EBS 用のドライバーを自分で入れます。入れないまま LoadBalancer の Service を作ると、NLB ではなく、古い種類のロードバランサー(CLB)ができます。Deployment、Service、Job、readinessProbe、preStop の考え方は、EKS でもそのまま使えます。 AWS Physical AI Toolchain のサンプルには、OSMO を EKS に入れる一式(osmo-on-aws)が入っています。OSMO には、イメージ、コマンド、GPU の枚数を書いたワークフローの YAML を渡します。すると OSMO が、EKS のクラスターの上で Pod を動かします。OSMO を使う人は Pod や Job を直接は書きませんが、その下では、この記事で動かした Pod やノードが働いています。GPU のマシンの用意と、サンプルの中身を読む話は、続きの記事で扱う予定です。 片付け kubectl delete -f web.yaml -f job.yaml /usr/local/bin/k3s-uninstall.sh sudo firewall-cmd --permanent --zone=trusted --remove-source=10.42.0.0/16 sudo firewall-cmd --permanent --zone=trusted --remove-source=10.43.0.0/16 sudo firewall-cmd --reload rm ~/.kube/config k3s-uninstall.sh で、k3s 本体、k3s-selinux、Rancher のリポジトリの設定が消えました。一緒に入った container-selinux は残るので、要らなければ別に消します。 まとめ k8s には「こうなっていてほしい」を書いて渡す。Pod を1つ消すと、数秒で立て直された Service はラベルで Pod をまとめ、変わらない名前で呼べるようにする。この k3s では、行き先は確率で選ばれた readinessProbe で Pod の調子を確かめる。失敗した Pod は振り分けから外れた 入れ替えの途中の「すぐ断られる」失敗は、preStop の sleep で出なくなった 終わりのある仕事は Job で流す。同時に流すのは Job を並べるだけだが、順番は Job には書けない k3s のほかにも、k8s を動かすソフトはいくつもある。選ぶときは、コントロールプレーンの面倒を自分で見るかどうかから考えると絞りやすい(私の整理) EKS では、マシン・入口・ディスクの用意が変わるが、マニフェストの考え方はそのまま使える AWS Physical AI Toolchain の OSMO も、EKS の上で Pod を動かす。ワークフローの YAML の下で、この記事の部品が働いている 付録 kind に書ける主な種類 kind に書けるものは、ほかにもたくさんあります。よく使うものを挙げます。 kind 何を表すか Pod コンテナを動かす最小の単位。普通は直接書かない ReplicaSet Pod の数を保つもの。普通は Deployment が作る Deployment ずっと動かしておく Pod の数と作り方 Service Pod をまとめて、変わらない名前で呼ぶための入口 Job 終わりのある仕事。最後までやったら完了 Ingress URL ごとに、どの Service へ渡すかの決まり ConfigMap 設定の値 Secret パスワードなどの秘密の値 Namespace クラスターの中を区切る仕切り そのクラスターで書ける種類の一覧は、kubectl api-resources で見られます。 外からの入口ごとの Service の書き方 この記事では NodePort でつなぎましたが、外からの入口の作り方を変えると、Service の type と、まわりに足すものが変わります。 入口 Service の type ほかに要るもの NodePort(この記事) NodePort なし。ノードのポートの 30000〜32767 番で受ける ロードバランサー LoadBalancer ロードバランサーを用意する仕組み。k3s では servicelb、自分のマシンでは MetalLB など。EKS では AWS が NLB を作る リバースプロキシ ClusterIP Traefik などのリバースプロキシと、Ingress。リバースプロキシ自身は LoadBalancer か NodePort の Service で外から受ける クラスターの外のロードバランサー NodePort 外のロードバランサーの行き先を、各ノードの NodePort にする。前から使っているロードバランサーを、そのまま入口にしたいときに使う どれを選んでも、Deployment や Pod の書き方は変わりません。 参考 Requirements・Advanced Options(k3s のドキュメント) Introduction・Requirements(RKE2 のドキュメント) minikube・kind・k3d・k0s・MicroK8s・kubeadm・Talos Linux・OpenShift・OKD(各ソフトの公式ページ) Deployments・Service・Jobs・Creating a cluster with kubeadm・kubectl wait(k8s のドキュメント) Argo Workflows Liveness, Readiness, and Startup Probes・Container Lifecycle Hooks(k8s のドキュメント) traefik/whoami Amazon EKS の料金 Amazon EKS architecture・Route TCP and UDP traffic with Network Load Balancers(EKS のドキュメント) EKS Auto Mode(eksctl のドキュメント) aws-samples/sample-the-physical-ai-toolchain-on-aws(AWS のサンプル。OSMO を EKS に入れる一式は osmo-on-aws) 脚注 本番のクラスターでは、コントロールプレーンとノードを別のマシンに分けるのが一般的です。公式の組み立てツールの kubeadm で作ると、安全のため、初期設定ではコントロールプレーンのマシンに Pod を置きません。EKS などのクラウドのサービスでは、コントロールプレーンのマシンは利用者からは見えず、Pod も置けません。この記事のように1台で兼ねるのは、試すときや小さな環境で、k3s は初期設定のままで兼ねます。 ↩︎

  2. Sources - AWS, "Introducing the Physical AI Toolchain on AWS", 7 Oct 2026 — aws.amazon.com Code (Apache 2.0) — aws-samples/sample-the-physical-ai-toolchain-on-aws About Amazon — aboutamazon.com AWS RoboMaker end of support — docs.aws.amazon.com NVIDIA, 16 Mar 2026 (Azure toolchain statement) — investor.nvidia.com The Robot Report, 8 Oct 2026 — therobotreport.com Educational analysis, not investment advice. I'm not a registered investment advisor. Markets carry risk — do your own research.

    1 like · 16 views
  3. Sources: AWS repo README, costs + status (primary): aws-samples/sample-the-physical-ai-toolchain-on-aws AWS blog: aws.amazon.com Amazon announcement: aboutamazon.com The Robot Report: therobotreport.com

    12 views
  4. We built the AWS Physical AI Toolchain alongside @nvidia so you can quickly spin up policy training and evaluation on AWS. Generalized robotics isnt solved yet, but the plumbing required to get there shouldnt be the bottleneck. aws-samples/sample-the-physical-ai-toolchain-on-aws ^^^Fine-tune VLAs, generate synthetic data, and run RL in Isaac Lab, and evaluate policies from a single repo

    1 like · 52 views

Latest stargazers

The last 10 distinct accounts we observed this year.

Most active participants

PR, issue, comment & review events in the past year.

Packages

Scan pending.

README badges

Embed a badge in your README or website.

Live mentions · last 30 days
aws-samples/sample-the-physical-ai-toolchain-on-aws mentions in the last 30 days