2021.04.08
1 番「軽い」やつはどれか?
Kubernetes ディストリビューション比較
D.M.です。ローカル Windows で軽い Kubernetes 環境を作る話をします。
ローカル k8s と言えば以前は Minikube が一般的でしたが、2018年2月に Docker Desktop が Kubernetes を標準搭載しました。ホンモノなのでこれが 1 番いいと思われるものの、私の環境ではなぜか動作しませんでした。現状、他の選択肢として Kubernetes ディストリビューションが複数存在していますので、今回はそのうち k3s, k0s を使ってみたいと思います。
TL;DR
やりたいこと
Windows の開発マシン用の軽い Kubernetes を見つけたいです。そのために簡単な課題を用意しました。
課題
・ローカルの Windows 10 で Kubernetes で Nginx コンテナを10個動かす。(pod 10個)
評価指標
A. Windows でのセットアップが簡単か?
B. メモリ消費量が少なくてちゃんと動作するか?
検証環境(メモリの重要性が際立つように、少ないマシンでやってみます)
OS Wndows 10 バージョン 1903 ( WSL 2 が使える)
CPU 4 コア(論理 8 コア)
メモリ 8 GB( OS 起動の段階で 3.5 GBぐらい使っている)
ディスク 500 GB (実質 300 GB 以上空きがあった)
※仮に WSL 2 がなくても Hyper-V または Virtual Box Vagrant で同じ環境を動かせる。
評価対象(動作環境)
Minikube : Hyper-V 上の Buildroot ( minikube start コマンドで作成)
k3s : Hyper-V 上の k3os v0.20.4-k3s1r0 ( Alpine ベース)
k0s : WSL 2 上の Alpine 3.13.4
この Windows 環境には Docker が入っていますが、k0s と k3s はいずれも Docker のインストールを前提としません。自分で containerd を持っていてコンテナを動かしています。
課題で使った Nginx の Pod 10 個作る設定ファイルは Kubernetes の公式からもらっています。
「サービスとアプリケーションの接続」 の run-my-nginx.yaml と nginx-svc.yaml を1ファイルにまとめました。
nginx-deploy-service.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: my-nginx spec: selector: matchLabels: run: my-nginx replicas: 10 template: metadata: labels: run: my-nginx spec: containers: - name: my-nginx image: nginx ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: my-nginx labels: run: my-nginx spec: ports: - port: 80 protocol: TCP selector: run: my-nginx
ここから3つやっていきます。ファイッ!
Minikube 編
もともとローカル練習用の Minikube は非常に簡単な手順ですべてが試せます。
1. 公式に行き、exe をダウンロードして Windows へインストール。
2. Windows 10 のコマンドプロンプト cmd を管理者権限で実行。
3. インストールフォルダに cd して minikube start 。 VM がセットアップされる。
# cd %USERPROFILE%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Kubernetes # minikube start
4. 上記の yaml をコピペして、apply を実行。
# kubectl apply -f nginx-deploy-service.yaml
これで確認はおわりです。簡単です。
Minikube のメモリ消費量
手順3で Hyper-V の VM を作り出す段階でデフォルトで 2200 MB つまり 2.2 GB を確保しています。
公式の minikube start のページでは、 2 GB を推奨しています。
推奨値から減らすとろくでもないことが多いのでこのままで良さそうです。
・超簡単。15分でセットアップできる。
[Minikube の良くなかったところ]
・メモリ使用量は今回一番の多い 2.2 GB 。でも Docker Desktop Kubernetes は 4 GB とか書いてあった気がするのでそれに比べたら半分。
使用メモリの比較を Windows 10 のタスクマネージャーから見てみます。この検証環境はだいぶ少な目なので、やっぱり圧迫感が強い。
Minikube 使用時のメモリ
実際の環境にメモリの余裕があれば Minikube が簡単でいいと思いました。
k3s 編
k3s は IoT 機器の Raspberry Pi など向けの軽量 Kubernetes です。
Rancher Labs 社が開発しています。 私は Rancher のツールを本番でも使っているので贔屓目です。
公式 Github
https://github.com/k3s-io/k3s
小さい機器でも動かせるというのが売りなので、メモリ消費もだいぶ抑えられているはず。期待が高まります。
セットアップ
k3s のインストールはコマンド一発で簡単です。
# curl -sfL https://get.k3s.io | sh -
ただ現状だと Windows には入らないので、別の Linux OS を VM で立てる必要がありますがモダンな Linux ならなんでも入るようです(K3s公式参照)。
k3os
今回は、あらかじめ k3s がセットアップされた k3os をという IOS イメージを使ってみようかと思いました。
公式 Github からダウンロードできます。
https://github.com/rancher/k3os/releases
k3os install コマンドでのセットアップ時に server と agent の 2 種類を選びますが、ローカル向けには server だけのセットアップで充分です。 single node で Nginx コンテナを動かすことができます。
k3os の難しいところは、 Alpine OS のパッケージ管理 apk によるソフトウェアのインストールを許可していないところです。なのでちょっとハマって調査なりで何か入れようとしても何もできません。ファイルの編集や書き込み自体は可能ですが、nmap とか iftop とかも入れることができない。それだけ省エネに特化しているということなのでしょう。
k3os の ISO を Hyper-V マネージャーでセットアップします。
メニューから操作 → 新規 → 仮想マシンを選択してウィザードを開きます。
以下の設定で作成しました。(第 2 世代は k3os が立ち上がりませんでした)
初回は Hyper-V マネージャーから接続します。
root になり以下のコマンドを実行すると初期化セットアップが動き出します。
k3os install
ISOイメージのまま軽く動かしてもコマンドは実行できますが、いろいろ検証したかったのでちゃんとディスクに入れました。
再起動された後に一旦停止し、 ISO を外してから再起動します。
再び Hyper-V マネージャーから接続します。デフォルトでは ssh のパスワードログインを許可していないので以下の変更が必要です。
sudo vi /etc/ssh/sshd_config # PasswordAuthentication yes にする sudo service sshd restart
これで rancher ユーザで入れるようになったのでここから先は ssh クライアントで実行していきます。
サービス起動
service k3s-service start * Starting k3s-service ... [ ok ]
これで kubernetes が動き出しました。だいぶ簡単です。
k3os は kubectl などにも PATH が通っておりコマンドはサクサク実行できます。 node が 1 つあるのを確認して、 nginx をデプロイします。
kubectl get node kubectl apply -f nginx-deploy-service.yaml
curl で動作が確認できました。
以上で完了なのですが、 iso からディスクに入れて ssh 設定して。。など細かい調査の時間が結構かかりました。
手順がわかってしまえば作業時間は正味 20 分ぐらいになります。
※上記とは別の環境で、複数台で agent だけを動作させている node を作ったときに、 Hyper-V 環境では Windows を再起動するたびに IP が DHCP で変わってしまいます。固定する方法などを試す必要があるのですが、ひとまず IP を変更して対応したいときは以下のファイルを修正します。
vi /var/lib/rancher/k3s/agent/etc/k3s-agent-load-balancer.json vi /var/lib/rancher/k3os/config.yaml k3os config
最後の config コマンドでサービスが再起動されて状態が反映されます。以下の設定ファイルも再生されます。
/etc/rancher/k3s/k3s-service.env
k3s のメモリ消費量
k3s の公式ページに素晴らしい情報がありました。
以下の 3 パターンについての最小メモリ値を提示してくれています。
1.K3s server with a workload 768 MB
2.K3s cluster with a single agent 512 MB
3.K3s agent 256 MB
上記の 3 パターンには今回のように single node 全部入りは該当しないようですが、充分参考になります。
こちらによると k3s は一番大きい構成でも 768 MB なので、 minikube の 2200 MB に比べて大幅減。 34.9% しか使わないことになります。
これはすごい。。!
公式がテストしていたコンテナの組み合わせが以下なのですが、結構本気です。 K3s の全パッケージ、 Prometheus と Grafana そして PHP のアプリが入っています。こんな充分な構成が省メモリでうごくとなると、まともに使いこなしたら一番信頼性がありそう。
– K3s 1.19.2 with all packaged components enabled
– Prometheus + Grafana monitoring stack
– Kubernetes Example PHP Guestbook app
テスト環境も今回の私の環境に近い感じでした。
– AWS c5d.xlarge – 4 core, 8 GB RAM, NVME SSD
– Raspberry Pi 4 Model B – 4 core, 8 GB RAM, Class 10 SDHC
そして今回の環境での調査結果です。
768 MB の VM で k3s を起動させ、 10 個のコンテナを立ち上げました。が、しかし重い。。 PC のファンが延々と熱を放出しています。何かがうまく動いていません。
結論としてはメモリを 1 GB に拡張してみたところまともにやっと動作しました。気持ち少し重いかもですが動いています。
動作中に htop で見るとこんなかんじ。メモリが8割以上使われています。
・消費メモリ 1 GB 。軽い。
・k3os が楽。20分ぐらいで構築。
・ラズパイなどの世間的な実績も充分。
[k3s の良くないところ]
・k3os は使い慣れるまで制約などが気になる。
k3s 使用時のタスクマネージャーのメモリ状況。やっぱり少ないのでブラウザなどが利用できる余地がありますね。
k0s 編
k0s は Mantis 社製です。(Rancher に似たクラスタ管理ツール LENS の会社)
k3s に似た軽量 kubernetes で、シングルバイナリーで動作します。
k0s はどんな Linux でも動くらしく、最低限 systemd (systemctl)または opnerc のインストールが前提になっています。
とにかく軽く動かしたいと思い、 k3os にならって Alpine でやってみます。Alpine は WSL 版が MS ストアにありました。(執筆時点では Alpine 3.13.4 )
https://www.microsoft.com/ja-jp/p/alpine-wsl/9p804crf0395?activetab=pivot:overviewtab
k0s のメモリ消費量
公式ページによると最低メモリは 1 GB になっています。
https://docs.k0sproject.io/latest/system-requirements/
WSL の消費メモリはタスクマネージャーを見ると Vmmem プロセスでわかります。
メモリの上限設定は %USERPROFILE%\.wslconfig ファイルで調整できます。(初期はないので、自分で作成)
結論としては 1.5 GB でいい感じに動きました。
[wsl2] memory=1536MB swap=512MB
セットアップ
k0s はセットアップは結構手間を取りました。ここは読み飛ばしていいです(笑)
Microsoft Store の Alpine WSL はダウンロードするとすぐにインストールが完了します。
Alpine は超軽量OSなので、初期段階では一般的な機能があまり入っていません。
k0s は openrc 前提としているので、これを入れておかないと service が使えず、インストール時に以下のような感じで怒られます。
INFO[2021-04-06 13:54:30] Installing k0s service Error: failed to install k0s service: failed to install service: "rc-update" failed: exec: "rc-update": executable file not found in $PATH 2021-04-06 13:54:30.633206 I | failed to install k0s service: failed to install service: "rc-update" failed: exec: "rc-update": executable file not found in $PATH
まず openrc の インストールは apk で。
apk add openrc (1/2) Installing ifupdown-ng (0.10.2-r2) (2/2) Installing openrc (0.42.1-r19) Executing openrc-0.42.1-r19.post-install Executing busybox-1.32.1-r5.trigger OK: 30 MiB in 34 packages
入れたらすぐに設定を実行します。
sed -i 's/#rc_sys=""/rc_sys="lxc"/g' /etc/rc.conf echo 'rc_provide="loopback net"' >> /etc/rc.conf sed -i 's/^#\(rc_logger="YES"\)$/\1/' /etc/rc.conf sed -i '/tty/d' /etc/inittab sed -i 's/hostname $opts/# hostname $opts/g' /etc/init.d/hostname sed -i 's/mount -t tmpfs/# mount -t tmpfs/g' /lib/rc/sh/init.sh sed -i 's/cgroup_add_service /# cgroup_add_service /g' /lib/rc/sh/openrc-run.sh mkdir /run/openrc touch /run/openrc/softlevel
ここからは k0s のインストールコマンドです。 Alpine でない場合はこれを実行すればすぐにインストール可能です。公式からコピペします。
curl -sSLf https://get.k0s.sh | sudo sh Downloading k0s from URL: https://github.com/k0sproject/k0s/releases/download/v0.12.1/k0s-v0.12.1-amd64 k0s k0s - The zero friction Kubernetes - https://k0sproject.io This software is built and distributed by Mirantis, Inc., and is subject to EULA https://k0sproject.io/licenses/eula
1 台で全部入りの設定で動かすセットアップは以下のコマンドでした。
k0s install controller --single INFO[2021-04-06 13:54:30] no config file given, using defaults INFO[2021-04-06 13:54:30] creating user: etcd INFO[2021-04-06 13:54:30] creating user: kube-apiserver INFO[2021-04-06 13:54:30] creating user: konnectivity-server INFO[2021-04-06 13:54:30] creating user: kube-scheduler INFO[2021-04-06 13:54:30] Installing k0s service
rc-status * Caching service dependencies ... Service `machine-id' needs non existent service `dev' [ ok ] Runlevel: sysinit k0scontroller [ stopped ] Dynamic Runlevel: hotplugged Dynamic Runlevel: needed/wanted Dynamic Runlevel: manual
状態を確認してスタートさせます。
service k0scontroller status * status: stopped service k0scontroller start * Starting k0s ... [ ok ]
kubectl は直接使えず k0s kubectl とする必要があります。面倒だったので、 alias を貼ってやります。
alias kubectl='k0s kubectl'
全部入りの single node で動かす場合、k0s コマンドから直接起動の際に enable-worker オプションを利用します。
(上記の service の中身を変更するか、以下を実行する)
nohup k0s server --enable-worker >> /var/log/k0s-server.log &
こんな感じで立ち上がってきました。イェイ。
ps aux PID USER TIME COMMAND 1 root 0:00 /init 1102 root 0:00 /init 1103 root 0:00 /init 1104 matsui 0:00 -ash 1105 root 0:00 su - 1106 root 0:00 -ash 1800 root 0:00 k0s server --enable-worker 1812 etcd 0:01 /var/lib/k0s/bin/etcd --data-dir=/var/lib/k0s/etcd --listen-client-urls=https://127.0.0.1:2379 --a 1835 kube-api 0:04 /var/lib/k0s/bin/kube-apiserver --enable-bootstrap-token-auth=true --requestheader-allowed-names=f 1850 konnecti 0:00 /var/lib/k0s/bin/konnectivity-server --admin-port=8133 --enable-profiling=false --uds-name=/run/k0 1860 kube-sch 0:00 /var/lib/k0s/bin/kube-scheduler --kubeconfig=/var/lib/k0s/pki/scheduler.conf --v=1 --bind-address= 1871 kube-api 0:00 /var/lib/k0s/bin/kube-controller-manager --service-account-private-key-file=/var/lib/k0s/pki/sa.ke 1892 root 0:00 /usr/bin/k0s api --config= --data-dir=/var/lib/k0s 1906 root 0:00 /var/lib/k0s/bin/containerd --root=/var/lib/k0s/containerd --state=/run/k0s/containerd --address=/ 1923 root 0:00 ps aux
このあとの Nginx の deploy 等は他と同じ流れですので割愛。
余談ですが、作業途中で hostname に _ を入れるという新人のようなミスをおかしてしまい kubelet が起動しなくなりました。反省のためにここにエラーメッセージを載せておきます。hostname から _ をなくして解決しました。
less /var/log/k0s-server.log time="2021-04-06 15:05:37" level=info msg="E0406 15:05:37.193862 3377 kubelet_node_status.go:93] Unable to register n ode \"alpine_3_13_4\" with API server: Node \"alpine_3_13_4\" is invalid: metadata.name: Invalid value: \"alpine_3_13_4\ ": a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z 0-9]([-a-z0-9]*[a-z0-9])?)*')" component=kubelet
他にもよくわからないエラーが出まくったらもうお手上げなのでそういうときは k0s reset で初期化します(笑)
以下のファイルに直 IP の記載がありましたので、 IP 変更ぐらいでしたら以下の修正と再起動で治ると思います。
/var/lib/k0s/kubelet.conf
/var/lib/k0s/kubelet-bootstrap.confrequirements
・消費メモリ 1.5 GM。かなり軽量。将来に期待。
・たぶん Alpine じゃなければもっと簡単です(笑)
[k0s の良くないところ]
・構築時間が数時間。たぶん Alpine のせい。
・k3s に比べて少し重い分、何か特徴があるはずだが、私はまだ見い出せてない。
※ Alpine を Dis っているみたいになってしまいましたが、私は普段から使っている Alpinist ですのでご容赦ください。。
k0s 使用時の メモリ状況。k3s と大差ない印象。
まとめ
評価指標
A. Windows でのセットアップが簡単か?
1. Minikube
2. k3s
3. k0s
評価指標
B. メモリ消費量が少なくてちゃんと動作するか?
1. k3s
2. k0s
3. Minikube
他にも Kubernetes ディストリビューションはありますので、さらに軽いのが流行ってもらえると嬉しいと思います。
宣伝
次世代システム研究室では、最新のテクノロジーを調査・検証しながらインターネットのいろんなアプリケーションの開発を行うアーキテクトを募集しています。募集職種一覧 からご応募をお待ちしています。
グループ研究開発本部の最新情報をTwitterで配信中です。ぜひフォローください。
Follow @GMO_RD