こんにちは。サイオステクノロジー OSS サポート担当 Y です。
今回は、最近話題の k3s をシングルノード構成でインストールしてみました。(※以下の内容は CentOS 7.6/k3s v0.2.0 にて検証しています。)
■はじめに
今回は、Rancher Labs が開発した k3s を試してみました。
こちらのページにも記載されていますが、k3s は “軽量な Kubernetes (Lightweight Kubernetes)” です。
名前の由来は “5 less than k8s” であり、通常の Kubernetes から 5つの要素が変更 (及び削除) され、より軽量な実装になっているようです。通常の Kubernetes からの変更内容については GitHub の README に記載されています。
■k3s のインストール
それではさっそく、検証してみようと思います。
まずはインストールですが、k3s はシングルバイナリで提供されているため、そのバイナリを 1つダウンロードするだけです。(1つのバイナリの中に “API Server”, “Controller Manager”, “Scheduler” 等の Kubernetes のコンポーネントがまとめられているそうです)
[root@k3s-master ~]# cd /usr/local/bin/ [root@k3s-master bin]# [root@k3s-master bin]# wget https://github.com/rancher/k3s/releases/download/v0.2.0/k3s ~(中略)~ 2019-03-29 16:07:20 (109 KB/s) - 'k3s' saved [37735552/37735552] [root@k3s-master bin]# [root@k3s-master bin]# ls -l ./k3s -rw-r--r--. 1 root root 37735552 Mar 9 11:48 ./k3s [root@k3s-master bin]# [root@k3s-master bin]# chmod 755 ./k3s [root@k3s-master bin]# [root@k3s-master bin]# ls -l ./k3s -rwxr-xr-x. 1 root root 37735552 Mar 9 11:48 ./k3s
■k3s 起動
では、ダウンロードしたバイナリを使って k3s を起動してみます。
Quick start に記載されている通り、シングルノード構成 (Master のみ起動する) であれば、1コマンドで起動してくれるようです。
[root@k3s-master ~]# k3s server & [1] 7301 [root@k3s-master ~]# INFO[0000] Preparing data dir /var/lib/rancher/k3s/data/e44f7a46cadac4cec9a759756f2a27fdb25e705a83d8d563207c6a6c5fa368b4 INFO[2019-03-29T16:09:54.806708216+09:00] Starting k3s v0.2.0 (2771ae1) INFO[2019-03-29T16:09:56.655759768+09:00] Running kube-apiserver --watch-cache=false --cert-dir /var/lib/rancher/k3s/server/tls/temporary-certs --allow-privileged=true --authorization-mode Node,RBAC --service-account-signing-key-file /var/lib/rancher/k3s/server/tls/service.key --service-cluster-ip-range 10.43.0.0/16 --advertise-port 6445 --advertise-address 127.0.0.1 --insecure-port 0 --secure-port 6444 --bind-address 127.0.0.1 --tls-cert-file /var/lib/rancher/k3s/server/tls/localhost.crt --tls-private-key-file /var/lib/rancher/k3s/server/tls/localhost.key --service-account-key-file /var/lib/rancher/k3s/server/tls/service.key --service-account-issuer k3s --api-audiences unknown --basic-auth-file /var/lib/rancher/k3s/server/cred/passwd --kubelet-client-certificate /var/lib/rancher/k3s/server/tls/token-node.crt --kubelet-client-key /var/lib/rancher/k3s/server/tls/token-node.key INFO[2019-03-29T16:09:57.859363977+09:00] Running kube-scheduler --kubeconfig /var/lib/rancher/k3s/server/cred/kubeconfig-system.yaml --port 10251 --address 127.0.0.1 --secure-port 0 --leader-elect=false INFO[2019-03-29T16:09:57.861980258+09:00] Running kube-controller-manager --kubeconfig /var/lib/rancher/k3s/server/cred/kubeconfig-system.yaml --service-account-private-key-file /var/lib/rancher/k3s/server/tls/service.key --allocate-node-cidrs --cluster-cidr 10.42.0.0/16 --root-ca-file /var/lib/rancher/k3s/server/tls/token-ca.crt --port 10252 --address 127.0.0.1 --secure-port 0 --leader-elect=false Flag --address has been deprecated, see --bind-address instead. INFO[2019-03-29T16:09:58.175879088+09:00] Creating CRD listenerconfigs.k3s.cattle.io INFO[2019-03-29T16:09:58.278159768+09:00] Creating CRD addons.k3s.cattle.io INFO[2019-03-29T16:09:58.289000446+09:00] Creating CRD helmcharts.k3s.cattle.io INFO[2019-03-29T16:09:58.356016822+09:00] Waiting for CRD addons.k3s.cattle.io to become available INFO[2019-03-29T16:09:58.857861109+09:00] Done waiting for CRD addons.k3s.cattle.io to become available INFO[2019-03-29T16:09:58.857906242+09:00] Waiting for CRD helmcharts.k3s.cattle.io to become available INFO[2019-03-29T16:09:59.359129840+09:00] Done waiting for CRD helmcharts.k3s.cattle.io to become available INFO[2019-03-29T16:09:59.362419610+09:00] Listening on :6443 INFO[2019-03-29T16:10:00.209554234+09:00] Node token is available at /var/lib/rancher/k3s/server/node-token INFO[2019-03-29T16:10:00.209587670+09:00] To join node to cluster: k3s agent -s https://10.1.1.21:6443 -t ${NODE_TOKEN} INFO[2019-03-29T16:10:00.213282980+09:00] Writing manifest: /var/lib/rancher/k3s/server/manifests/coredns.yaml INFO[2019-03-29T16:10:00.213478225+09:00] Writing manifest: /var/lib/rancher/k3s/server/manifests/traefik.yaml INFO[2019-03-29T16:10:00.466295407+09:00] Wrote kubeconfig /etc/rancher/k3s/k3s.yaml INFO[2019-03-29T16:10:00.466325821+09:00] Run: k3s kubectl INFO[2019-03-29T16:10:00.466353276+09:00] k3s is up and running INFO[2019-03-29T16:10:00.527756870+09:00] Logging containerd to /var/lib/rancher/k3s/agent/containerd/containerd.log INFO[2019-03-29T16:10:00.528155373+09:00] Running containerd -c /var/lib/rancher/k3s/agent/etc/containerd/config.toml -a /run/k3s/containerd/containerd.sock --state /run/k3s/containerd --root /var/lib/rancher/k3s/agent/containerd INFO[2019-03-29T16:10:00.548474695+09:00] Waiting for containerd startup: rpc error: code = Unavailable desc = all SubConns are in TransientFailure, latest connection error: connection error: desc = "transport: Error while dialing dial unix /run/k3s/containerd/containerd.sock: connect: no such file or directory" containerd: exit status 1 [1]+ Exit 1 k3s server [root@k3s-master ~]#
しかし、上記の様なエラーになってしまいました。
このエラーについて調べてみたところ、いくつかの類似する Issues あるようであり、それらの内容を見ると /etc/hosts にホスト名を記載すると事象が改善するという情報があったので、試してみました。
[root@k3s-master ~]# tail -n 1 /etc/hosts 127.0.0.1 k3s-master.example.com
[root@k3s-master ~]# k3s server & [1] 7384 [root@k3s-master ~]# INFO[2019-03-29T16:12:10.045436976+09:00] Starting k3s v0.2.0 (2771ae1) INFO[2019-03-29T16:12:10.046896713+09:00] Running kube-apiserver --watch-cache=false --cert-dir /var/lib/rancher/k3s/server/tls/temporary-certs --allow-privileged=true --authorization-mode Node,RBAC --service-account-signing-key-file /var/lib/rancher/k3s/server/tls/service.key --service-cluster-ip-range 10.43.0.0/16 --advertise-port 6445 --advertise-address 127.0.0.1 --insecure-port 0 --secure-port 6444 --bind-address 127.0.0.1 --tls-cert-file /var/lib/rancher/k3s/server/tls/localhost.crt --tls-private-key-file /var/lib/rancher/k3s/server/tls/localhost.key --service-account-key-file /var/lib/rancher/k3s/server/tls/service.key --service-account-issuer k3s --api-audiences unknown --basic-auth-file /var/lib/rancher/k3s/server/cred/passwd --kubelet-client-certificate /var/lib/rancher/k3s/server/tls/token-node.crt --kubelet-client-key /var/lib/rancher/k3s/server/tls/token-node.key INFO[2019-03-29T16:12:10.237101874+09:00] Running kube-scheduler --kubeconfig /var/lib/rancher/k3s/server/cred/kubeconfig-system.yaml --port 10251 --address 127.0.0.1 --secure-port 0 --leader-elect=false INFO[2019-03-29T16:12:10.239400669+09:00] Running kube-controller-manager --kubeconfig /var/lib/rancher/k3s/server/cred/kubeconfig-system.yaml --service-account-private-key-file /var/lib/rancher/k3s/server/tls/service.key --allocate-node-cidrs --cluster-cidr 10.42.0.0/16 --root-ca-file /var/lib/rancher/k3s/server/tls/token-ca.crt --port 10252 --address 127.0.0.1 --secure-port 0 --leader-elect=false Flag --address has been deprecated, see --bind-address instead. INFO[2019-03-29T16:12:10.587535026+09:00] Listening on :6443 INFO[2019-03-29T16:12:10.694976126+09:00] Node token is available at /var/lib/rancher/k3s/server/node-token INFO[2019-03-29T16:12:10.695061557+09:00] To join node to cluster: k3s agent -s https://10.1.1.21:6443 -t ${NODE_TOKEN} INFO[2019-03-29T16:12:10.698546209+09:00] Writing manifest: /var/lib/rancher/k3s/server/manifests/coredns.yaml INFO[2019-03-29T16:12:10.698799294+09:00] Writing manifest: /var/lib/rancher/k3s/server/manifests/traefik.yaml INFO[2019-03-29T16:12:10.820298416+09:00] Wrote kubeconfig /etc/rancher/k3s/k3s.yaml INFO[2019-03-29T16:12:10.820343262+09:00] Run: k3s kubectl INFO[2019-03-29T16:12:10.820356995+09:00] k3s is up and running INFO[2019-03-29T16:12:10.912675876+09:00] Logging containerd to /var/lib/rancher/k3s/agent/containerd/containerd.log INFO[2019-03-29T16:12:10.913887304+09:00] Running containerd -c /var/lib/rancher/k3s/agent/etc/containerd/config.toml -a /run/k3s/containerd/containerd.sock --state /run/k3s/containerd --root /var/lib/rancher/k3s/agent/containerd INFO[2019-03-29T16:12:10.929450459+09:00] Waiting for containerd startup: rpc error: code = Unavailable desc = all SubConns are in TransientFailure, latest connection error: connection error: desc = "transport: Error while dialing dial unix /run/k3s/containerd/containerd.sock: connect: connection refused" WARN[2019-03-29T16:12:11.953653919+09:00] failed to write value 1 at /proc/sys/net/bridge/bridge-nf-call-iptables: open /proc/sys/net/bridge/bridge-nf-call-iptables: no such file or directory INFO[2019-03-29T16:12:11.954703327+09:00] Connecting to wss://localhost:6443/v1-k3s/connect INFO[2019-03-29T16:12:11.954755360+09:00] Connecting to proxy url="wss://localhost:6443/v1-k3s/connect" INFO[2019-03-29T16:12:11.960526648+09:00] Handling backend connection request [k3s-master.example.com] WARN[2019-03-29T16:12:11.962176214+09:00] Disabling CPU quotas due to missing cpu.cfs_period_us INFO[2019-03-29T16:12:11.962763120+09:00] Running kubelet --healthz-bind-address 127.0.0.1 --read-only-port 0 --allow-privileged=true --cluster-domain cluster.local --kubeconfig /var/lib/rancher/k3s/agent/kubeconfig.yaml --eviction-hard imagefs.available<5%,nodefs.available<5% --eviction-minimum-reclaim imagefs.available=10%,nodefs.available=10% --fail-swap-on=false --cgroup-driver cgroupfs --root-dir /var/lib/rancher/k3s/agent/kubelet --cert-dir /var/lib/rancher/k3s/agent/kubelet/pki --seccomp-profile-root /var/lib/rancher/k3s/agent/kubelet/seccomp --cni-conf-dir /var/lib/rancher/k3s/agent/etc/cni/net.d --cni-bin-dir /var/lib/rancher/k3s/data/e44f7a46cadac4cec9a759756f2a27fdb25e705a83d8d563207c6a6c5fa368b4/bin --cluster-dns 10.43.0.10 --container-runtime remote --container-runtime-endpoint unix:///run/k3s/containerd/containerd.sock --address 127.0.0.1 --anonymous-auth=false --client-ca-file /var/lib/rancher/k3s/agent/client-ca.pem --hostname-override k3s-master.example.com --cpu-cfs-quota=false --runtime-cgroups /systemd/user.slice/user-0.slice --kubelet-cgroups /systemd/user.slice/user-0.slice Flag --allow-privileged has been deprecated, will be removed in a future version INFO[2019-03-29T16:12:12.391708233+09:00] waiting for node k3s-master.example.com: nodes "k3s-master.example.com" not found INFO[2019-03-29T16:12:14.393831404+09:00] waiting for node k3s-master.example.com CIDR not assigned yet INFO[2019-03-29T16:12:16.396318069+09:00] waiting for node k3s-master.example.com CIDR not assigned yet INFO[2019-03-29T16:12:18.398246129+09:00] waiting for node k3s-master.example.com CIDR not assigned yet INFO[2019-03-29T16:12:20.400212293+09:00] waiting for node k3s-master.example.com CIDR not assigned yet [root@k3s-master ~]# [root@k3s-master ~]#
[root@k3s-master ~]# k3s kubectl get node NAME STATUS ROLES AGE VERSION k3s-master.example.com Ready8m52s v1.13.4-k3s.1
すると、上記の様に正常に起動することができました。
■動作検証 (Pod のデプロイ)
最後に、起動した k3s 上にコンテナ (Pod) をデプロイしてみます。
今回は、こちらの記事で利用したものと同じマニフェスト (YAML ファイル) を作成し、k3s kubectl apply コマンドで適用します。
[root@k3s-master ~]# cat << EOF > ~/k3s-yaml/nginx-test.yaml > apiVersion: v1 > kind: Service > metadata: > name: nginx-test-service > labels: > app: nginx-test > spec: > selector: > app: nginx-test > type: NodePort > ports: > - protocol: TCP > port: 80 > targetPort: 80 > nodePort: 30080 > --- > apiVersion: apps/v1 > kind: Deployment > metadata: > name: nginx-test-deployment > spec: > replicas: 3 > selector: > matchLabels: > app: nginx-test > template: > metadata: > labels: > app: nginx-test > spec: > containers: > - name: nginx-container > image: nginx:1.15.9 > ports: > - containerPort: 80 > lifecycle: > postStart: > exec: > command: > - /bin/sh > - -c > - echo "NGINX container!" > /usr/share/nginx/html/index.html && echo "Pod name is \$(hostname) ." >> /usr/share/nginx/html/index.html > EOF
[root@k3s-master ~]# k3s kubectl apply -f ~/k3s-yaml/nginx-test.yaml service/nginx-test-service created deployment.apps/nginx-test-deployment created
マニフェストの詳細は割愛しますが、大雑把に説明すると以下の様な設定を実施しています。
・NGINX コンテナ (Pod) を 3つデプロイ。
・k3s をインストールした仮想サーバの 30080番 port 宛の通信を、いずれかの NGINX コンテナの 80番 port に転送。
また、どの NGINX コンテナ (Pod) からのレスポンスであるかを判断できるように、Pod 名をレスポンス (index.html) に含めるようにしています。
デプロイが完了すると、各リソースの状態が以下の様になると思います。
[root@k3s-master ~]# k3s kubectl get deployment NAME READY UP-TO-DATE AVAILABLE AGE nginx-test-deployment 3/3 3 3 71s [root@k3s-master ~]# [root@k3s-master ~]# k3s kubectl get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.43.0.1443/TCP 2d22h nginx-test-service NodePort 10.43.34.173 80:30080/TCP 80s [root@k3s-master ~]# [root@k3s-master ~]# k3s kubectl get pod NAME READY STATUS RESTARTS AGE nginx-test-deployment-56fdfc565c-49xm9 1/1 Running 0 87s nginx-test-deployment-56fdfc565c-jdd6m 1/1 Running 0 87s nginx-test-deployment-56fdfc565c-m4mjp 1/1 Running 0 87s
それでは、実際に k3s をインストールした仮想サーバの 30080番 port 宛てに HTTP リクエストを投げてみます。
[root@k3s-master ~]# curl -XGET https://10.1.1.21:30080/ NGINX container! Pod name is nginx-test-deployment-56fdfc565c-m4mjp . [root@k3s-master ~]# [root@k3s-master ~]# curl -XGET https://10.1.1.21:30080/ NGINX container! Pod name is nginx-test-deployment-56fdfc565c-m4mjp . [root@k3s-master ~]# [root@k3s-master ~]# curl -XGET https://10.1.1.21:30080/ NGINX container! Pod name is nginx-test-deployment-56fdfc565c-jdd6m . [root@k3s-master ~]# [root@k3s-master ~]# curl -XGET https://10.1.1.21:30080/ NGINX container! Pod name is nginx-test-deployment-56fdfc565c-49xm9 . [root@k3s-master ~]# [root@k3s-master ~]# curl -XGET https://10.1.1.21:30080/ NGINX container! Pod name is nginx-test-deployment-56fdfc565c-m4mjp . [root@k3s-master ~]# [root@k3s-master ~]# curl -XGET https://10.1.1.21:30080/ NGINX container! Pod name is nginx-test-deployment-56fdfc565c-49xm9 . [root@k3s-master ~]# [root@k3s-master ~]# curl -XGET https://10.1.1.21:30080/ NGINX container! Pod name is nginx-test-deployment-56fdfc565c-49xm9 . [root@k3s-master ~]# [root@k3s-master ~]# curl -XGET https://10.1.1.21:30080/ NGINX container! Pod name is nginx-test-deployment-56fdfc565c-jdd6m . [root@k3s-master ~]# [root@k3s-master ~]# curl -XGET https://10.1.1.21:30080/ NGINX container! Pod name is nginx-test-deployment-56fdfc565c-jdd6m . [root@k3s-master ~]# [root@k3s-master ~]# curl -XGET https://10.1.1.21:30080/ NGINX container! Pod name is nginx-test-deployment-56fdfc565c-49xm9 .
すると、上記の様に正常に HTTP レスポンスが返ってきました。
何回かリクエストを実行すると、レスポンスに含まれている Pod 名が変わっている (複数の NGINX コンテナ宛てにリクエストが振り分けられている) ことも確認できます。
上記の通り基本的な機能については、k3s が通常の Kubernetes と同じように動作 (Pod のデプロイや Service での負荷分散等) していることが確認できました。
■まとめ
今回は、最近話題の k3s を試してみました。
Lightweight Kubernetes という記載の通り、実際に利用したバイナリのサイズを確認してみると約 36MB となっていました。
[root@k3s-master ~]# du -h /usr/local/bin/k3s 36M /usr/local/bin/k3s
また、こちらのページに記載されているシステム要件も以下の様になっており、スペックの低いマシンでも動作させることができるようです。
Minimum System Requirements Linux 3.10+ 512 MB of ram per server 75 MB of ram per node 200 MB of disk space x86_64, ARMv7, ARM64
実際に、今回の検証は CPU 1 core / Memory 2GB の仮想サーバ上で実施していますし、コマンド 1つで簡単に起動できるので、ちょっとした Kubernetes の動作検証には丁度良いかもしれません。
まだリリースされて日が浅く、本記事の執筆時点では Server HA 等の機能が実装されていないため、本番環境での利用は難しそうですが、よりシンプルかつ軽量な Kubernetes として今後に期待できそうです。
機会があれば、複数ノードを利用した k3s クラスタ構築にも挑戦してみようと思います。