2021.04.08

1 番「軽い」やつはどれか?
Kubernetes ディストリビューション比較

D.M.です。ローカル Windows で軽い Kubernetes 環境を作る話をします。

ローカル k8s と言えば以前は Minikube が一般的でしたが、2018年2月に Docker Desktop が Kubernetes を標準搭載しました。ホンモノなのでこれが 1 番いいと思われるものの、私の環境ではなぜか動作しませんでした。現状、他の選択肢として Kubernetes ディストリビューションが複数存在していますので、今回はそのうち k3s, k0s を使ってみたいと思います。

TL;DR

  • k3os 上で動く k3s はメモリ 1 GB で動いたので最軽量。専用 OS もあり設定も簡単。
  • k0s はメモリ 1.5 GB で動いた。充分に軽い。設定は簡単だが、 Alpine の場合がやや面倒だった。
  • minikube はデフォルトでメモリ 2.2 GB 。何も設定しないでコマンド1つインストールできるのは一番楽。

  • やりたいこと


    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 編
  • k3s 編
  • k0s 編

  • 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 を推奨しています。
    推奨値から減らすとろくでもないことが多いのでこのままで良さそうです。

    [Minikube の良いところ]
    ・超簡単。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 の公式ページに素晴らしい情報がありました。

    K3s Resource Profiling

    以下の 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割以上使われています。

    [k3s の良いところ]
    ・消費メモリ 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

    [k0s の良いところ]
    ・消費メモリ 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 ディストリビューションはありますので、さらに軽いのが流行ってもらえると嬉しいと思います。

    宣伝


    次世代システム研究室では、最新のテクノロジーを調査・検証しながらインターネットのいろんなアプリケーションの開発を行うアーキテクトを募集しています。募集職種一覧 からご応募をお待ちしています。

    Pocket

    関連記事