はじめに
この記事は、箱庭もくもく会 #1 - connpassで「2022年の年明け」から手を動かした内容を記録したものです。
表題のkind(Kubernetes in docker)は、公式によると
kind is a tool for running local Kubernetes clusters using Docker container “nodes”. kind was primarily designed for testing Kubernetes itself, but may be used for local development or CI.
だそうです。
手元の環境を汚さず、Dockerコンテナを使ってローカルでKubernetesクラスタを実行するためのツールです。基本的にはローカル開発とかCIで使うことを想定して開発されているようです。Kubernetesを勉強するのにはうってつけとして、界隈では注目を集めています。
そんなクラスタを使って、ROS2を動かしてみようというのが今回の企画。
セットアップ
Docker、Kubectlはインストール済み、セットアップ済み前提で記載します。
kindのインストール
kind – Quick Start
公式のドキュメントによると、Windows/Mac/LinuxなんでもOK!っていう感じ。
# mac
brew install kind
# windows
choco install kind
コマンド補完(Mac)
kind
コマンドに対して補完を有効化したい場合は、以下を追加しよう。
[[ /usr/local/bin/kubectl ]] && source <(kind completion zsh)
設定ファイル
ROS2の肝?である、UDPマルチキャストを利用するためにKubenetestのCNIとしてWeave Netを使いたい。ゆえに、デフォルトのネットワークを無効化した上で使用する。disableDefaultCNI: true
とりあえず、kind-example-config.yaml
で保存する。
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
networking:
disableDefaultCNI: true
nodes:
- role: control-plane
- role: control-plane
- role: control-plane
- role: worker
- role: worker
- role: worker
クラスタの生成
kind create cluster --config kind-example-config.yaml --name rdbox-hakoniwa
kubectlのcontext
kubectl cluster-info --context kind-rdbox-hakoniwa
Weave Netのapply
kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
しばらくしてからkubectl get node
を実行。全てのノードがReadyになっていることを確認する。
❯ kubectl get node
NAME STATUS ROLES AGE VERSION
rdbox-hakoniwa-control-plane Ready control-plane,master 7m27s v1.21.1
rdbox-hakoniwa-control-plane2 Ready control-plane,master 7m v1.21.1
rdbox-hakoniwa-control-plane3 Ready control-plane,master 6m7s v1.21.1
rdbox-hakoniwa-worker Ready <none> 5m56s v1.21.1
rdbox-hakoniwa-worker2 Ready <none> 5m56s v1.21.1
rdbox-hakoniwa-worker3 Ready <none> 5m55s v1.21.1
ROS2アプリを動かしてみる
フォルダ構成
.
└── ros2
├── ros2_listener.yaml
└── ros2_talker.yaml
ros2_talker.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: simulation-talker
labels:
app: simulation-talker
spec:
replicas: 1
selector:
matchLabels:
app: simulation-talker
template:
metadata:
labels:
app: simulation-talker
role: my-role
spec:
containers:
- name: simulation-talker
image: osrf/ros:foxy-desktop
tty: true
ros2_listener.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: simulation-listener
labels:
app: simulation-listener
spec:
replicas: 1
selector:
matchLabels:
app: simulation-listener
template:
metadata:
labels:
app: simulation-listener
role: my-role
spec:
containers:
- name: simulation-listener
image: osrf/ros:foxy-desktop
tty: true
マニフェストを展開する
kubectl apply -f ros2
しばらくしてからkubectl get pod
を実行。全てのpodがRunningになっていることを確認する。
❯ kubectl get pod
NAME READY STATUS RESTARTS AGE
simulation-listener-8699f4f798-b4rrf 1/1 Running 0 2m42s
simulation-talker-8595bdb886-xst67 1/1 Running 0 2m42s
中に入ってROSコマンドを動かす
PodNameは、上記で実行し取得したNameを使用する。①からトピックをPubして、②で受け取る感じ。
端末①
$ kubectl exec -it simulation-talker-8595bdb886-xst67 -- /bin/bash
$ source ros_entrypoint.sh
$ ros2 run demo_nodes_cpp talker
[INFO] [1641090170.460439541] [talker]: Publishing: 'Hello World: 1'
[INFO] [1641090171.460306556] [talker]: Publishing: 'Hello World: 2'
[INFO] [1641090172.460231589] [talker]: Publishing: 'Hello World: 3'
[INFO] [1641090173.460365240] [talker]: Publishing: 'Hello World: 4'
[INFO] [1641090174.460597760] [talker]: Publishing: 'Hello World: 5'
[INFO] [1641090175.460255840] [talker]: Publishing: 'Hello World: 6'
端末②
$ kubectl exec -it simulation-listener-8699f4f798-b4rrf -- /bin/bash
$ source ros_entrypoint.sh
$ ros2 run demo_nodes_cpp listener
[INFO] [1641090170.461078099] [listener]: I heard: [Hello World: 1]
[INFO] [1641090171.460873884] [listener]: I heard: [Hello World: 2]
[INFO] [1641090172.460738264] [listener]: I heard: [Hello World: 3]
[INFO] [1641090173.460742628] [listener]: I heard: [Hello World: 4]
[INFO] [1641090174.460995658] [listener]: I heard: [Hello World: 5]
[INFO] [1641090175.460751746] [listener]: I heard: [Hello World: 6]
外から見ると、、、
このような状態で、docker ps
してみると以下のような感じになる。Kubernetesのノード1つにつき、Dockerコンテナが一つ割り当てられるようなイメージ。
その辺の設計についてkind – Initial designを見て私自身ももうちょっと深堀りしていきたいと思います。
❯ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ec8c214a4bf7 kindest/haproxy:v20200708-548e36db "/docker-entrypoint.…" 29 minutes ago Up 29 minutes 127.0.0.1:52302->6443/tcp rdbox-hakoniwa-external-load-balancer
25c273b79e7d kindest/node:v1.21.1 "/usr/local/bin/entr…" 29 minutes ago Up 29 minutes rdbox-hakoniwa-worker3
15505559f31c kindest/node:v1.21.1 "/usr/local/bin/entr…" 29 minutes ago Up 29 minutes rdbox-hakoniwa-worker
e12cd9839935 kindest/node:v1.21.1 "/usr/local/bin/entr…" 29 minutes ago Up 29 minutes 127.0.0.1:52303->6443/tcp rdbox-hakoniwa-control-plane2
63bd1bbca037 kindest/node:v1.21.1 "/usr/local/bin/entr…" 29 minutes ago Up 29 minutes rdbox-hakoniwa-worker2
09cede1487ab kindest/node:v1.21.1 "/usr/local/bin/entr…" 29 minutes ago Up 29 minutes 127.0.0.1:52305->6443/tcp rdbox-hakoniwa-control-plane
405188ac6d8f kindest/node:v1.21.1 "/usr/local/bin/entr…" 29 minutes ago Up 29 minutes 127.0.0.1:52304->6443/tcp rdbox-hakoniwa-control-plane3
後片付け
検証が終わったら以下を実行します。
# ROS2アプリの削除
$ kubectl delete -f ros2
# クラスタの削除
$ kind delete cluster --name rdbox-hakoniwa
おわりに
今回はもくもく会の1.5時間という時間内でやれる範囲で、簡単な動作確認をしました。結構普通に使えることが分かったので
この辺りをもう少し深堀りしていって展開させて頂ければと思います。
また、2022年は、箱庭のもくもく会や勉強会を定期的に開催予定です。ぜひ箱庭 - connpassもご注目下さい。
それにしても、手を動かすのって楽しいですね!!!!
(最近、全然手を動かさせてもらえない男の叫び)