軽量なKubernetes「K3s」でクラスタを組んでみる(Ubuntu Server)


TL;DR

  • めちゃくちゃ軽量なK8sディストリビューション「K3s」をUbuntu Serverで動かす
  • マスター(server)1台、ワーカー(agent)2台のKubernetes(K3s)クラスタを組む
  • deployment、service、ingressをデプロイする(サンプルymlあり)

構成

K3sをコントロールするマスター(server)を1台と、コンテナ(Pod)を動かすワーカー(agent)を2台用意します。
最低限しか書いていないので厳密にはもっと複雑ですが、こんな感じです。

クラウドVMでも、ローカルマシン上にVMを立てても、物理マシンを用意しても大丈夫です。
私の場合はローカルマシン(CPU:i5-10500)のHyper-V上にUbuntu Serverの仮想マシンを作成しました。

OSバージョン 20.04.2 LTS (Focal Fossa)
CPU 1コア
メモリ 1GB

構築

以下の流れで構築していきます。

  1. ホスト名を一意に設定したUbuntu Serverを3台用意
  2. 各サーバで/etc/hostsを設定
  3. マスターノードでK3sインストール & 起動
  4. ワーカーノードでK3sインストール & クラスタに追加
  5. リソースのデプロイ

1. ホスト名を一意に設定したUbuntu Serverを3台用意する

ホスト名を重複させないようにするため、以下のように設定をしました。

マスターノード ワーカーノード1 ワーカーノード2
ホスト名 k3s-master k3s-wk1 k3s-wk2
IPアドレス 192.168.1.150 192.168.1.151 192.168.1.152

ホスト名が重複する場合は、環境変数もしくは起動時のオプションで一意なノード名を指定する必要があります。
環境変数の場合 $K3S_NODE_NAME
起動時のオプションの場合 --node-name ノード名

2. 各サーバで/etc/hostsを設定する

各ノードの/etc/hostsに情報を追記します。

  • 単純に名前解決できたほうが楽
  • issue「cannot run k3s server」の対応策としてhostsに定義を追加することが有効である

マスターノード(k3s-master)の/etc/hosts

root@k3s-master:~# cat /etc/hosts
127.0.0.1 localhost
127.0.1.1 k3s-master
192.168.1.150 k3s-master
192.168.1.151 k3s-wk1
192.168.1.152 k3s-wk2

ワーカーノード1(k3s-wk1)の/etc/hosts

root@k3s-wk1:~# cat /etc/hosts
127.0.0.1 localhost
127.0.1.1 k3s-wk1
192.168.1.150 k3s-master
192.168.1.151 k3s-wk1
192.168.1.152 k3s-wk2

ワーカーノード2(k3s-wk2)の/etc/hosts

root@k3s-wk2:~# cat /etc/hosts
127.0.0.1 localhost
127.0.1.1 k3s-wk2
192.168.1.150 k3s-master
192.168.1.151 k3s-wk1
192.168.1.152 k3s-wk2

3. マスターノードでK3sインストール & 起動

K3sが用意しているインストールスクリプトを使います。

root@k3s-master:~# curl -sfL https://get.k3s.io | sh -
[INFO]  Finding release for channel stable
(中略)
[INFO]  systemd: Starting k3s
root@k3s-master:~# 

スクリプトの実行が完了するとK3sが起動しているはずです。
kubectlコマンドでnodeが起動していることを確認できます。

root@k3s-master:~# k3s kubectl get nodes
NAME         STATUS   ROLES                  AGE    VERSION
k3s-master   Ready    control-plane,master   2m3s   v1.21.1+k3s1

次はワーカーノードの起動ですが、その前に...
クラスタに組み込むために必要な情報(トークン)がマスターノードにあるので確認しておきます。

root@k3s-master:~# cat /var/lib/rancher/k3s/server/token
K109adb1784f9ffbc3ff5e272a6956d9407d7f96f9fcf742586c9fc108a031fc9b9::server:1158cefa7ef95ea0894d3446079d9c4a

4. ワーカーノードでK3sインストール & クラスタに追加

マスターノードでの起動とトークン確認が終わったら、次はワーカーノードでの作業です。
マスターノードと同じようにインストールスクリプトを使って導入していきます。
ただし、ワーカーノードとして起動させるためのオプション指定があるため、少しコマンドが異なります。

  • K3S_TOKENにマスターノードで確認した情報(トークン)を設定する
  • K3S_URLにマスターノードの6443ポートを設定する
root@k3s-wk1:~# curl -sfL https://get.k3s.io |\
K3S_TOKEN="K109adb1784f9ffbc3ff5e272a6956d9407d7f96f9fcf742586c9fc108a031fc9b9::server:1158cefa7ef95ea0894d3446079d9c4a" \
K3S_URL=https://k3s-master:6443 sh -
[INFO]  Finding release for channel stable
(中略)
[INFO]  systemd: Starting k3s-agent
root@k3s-wk1:~# 

マスターノードに戻って、kubectlコマンドでワーカーノードが追加されていることを確認できます。

root@k3s-master:~# k3s kubectl get nodes
NAME         STATUS   ROLES                  AGE   VERSION
k3s-master   Ready    control-plane,master   17m   v1.21.1+k3s1
k3s-wk1      Ready    <none>                 20s   v1.21.1+k3s1

もう一台のワーカーノードでも同じインストールコマンドを実行することで、同様にクラスタに追加されます。

root@k3s-wk2:~# curl -sfL https://get.k3s.io |\
> K3S_TOKEN="K109adb1784f9ffbc3ff5e272a6956d9407d7f96f9fcf742586c9fc108a031fc9b9::server:1158cefa7ef95ea0894d3446079d9c4a" \
> K3S_URL=https://k3s-master:6443 sh -
[INFO]  Finding release for channel stable
(中略)
[INFO]  systemd: Starting k3s-agent
------------------------------------------------------------------------ 
root@k3s-master:~# k3s kubectl get nodes
NAME         STATUS   ROLES                  AGE    VERSION
k3s-master   Ready    control-plane,master   24m    v1.21.1+k3s1
k3s-wk1      Ready    <none>                 7m4s   v1.21.1+k3s1
k3s-wk2      Ready    <none>                 1s     v1.21.1+k3s1

5. リソースをデプロイする

ここまで来たらあとはいつものKubernetesと同じように
kubectlコマンドを使ってリソースをデプロイできます。

ただ、今回はk3sの特徴を生かした自動デプロイ機能を使ってみます。

Any file found in /var/lib/rancher/k3s/server/manifests will automatically be deployed to Kubernetes in a manner similar to kubectl apply.
/var/lib/rancher/k3s/server/manifests にファイルを配置することで、自動的にKubernetesにデプロイされます(kubectl applyのように)

5-1. 使用するリソース

今回はK3sを動かすことにフォーカスしているので、そんなに凝ったものはデプロイしません。
nginxが動くpod(deploymentから作成します)、pod接続用のservice、serivceの外部公開ロードバランサのingressで構成しています。
serviceは8088番ポートでトラフィックを受け、podの80番ポートへトラフィックを流します。

Loadbalancerタイプのserviceを作成すればingressは無しでもOKです

今回使用したymlはgithubに公開しておいたので、K3sを試したい方は使ってください。

root@k3s-master:~# git clone https://github.com/otsukousan/sample-k3s-resource.git

5-2. deployment

root@k3s-master:~# cp deployment.yml /var/lib/rancher/k3s/server/manifests/deployment.yml
(十数秒後)
root@k3s-master:~# k3s kubectl get pod
NAME                     READY   STATUS    RESTARTS   AGE
nginx-7dc45fbd74-dfjg6   1/1     Running   0          23s
nginx-7dc45fbd74-lc5q7   1/1     Running   0          23s
nginx-7dc45fbd74-bjgxq   1/1     Running   0          23s
root@k3s-master:~# k3s kubectl get pod -o wide
NAME                     READY   STATUS    RESTARTS   AGE    IP           NODE      NOMINATED NODE   READINESS GATES
nginx-7dc45fbd74-dfjg6   1/1     Running   0          31s   10.42.2.9    k3s-wk2   <none>           <none>
nginx-7dc45fbd74-lc5q7   1/1     Running   0          31s   10.42.2.8    k3s-wk2   <none>           <none>
nginx-7dc45fbd74-bjgxq   1/1     Running   0          31s   10.42.1.11   k3s-wk1   <none>           <none>

きちんと各ノードに分散配置されていますね。
試しにpodの中から自身のnginxに向かってcurlを打ってみました。

root@k3s-master:~# k3s kubectl exec -it nginx-7dc45fbd74-dfjg6 -- curl http://localhost
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
root@k3s-master:~#

いつものやつ🤗

5-3. service

serviceもdeploymentと同様に自動デプロイ機能を使ってデプロイします。

root@k3s-master:~# cp service.yml /var/lib/rancher/k3s/server/manifests/service.yml
(数秒後)
root@k3s-master:~# k3s kubectl get svc
NAME            TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
kubernetes      ClusterIP   10.43.0.1      <none>        443/TCP    62m
nginx-service   ClusterIP   10.43.74.131   <none>        80/TCP      6s
root@k3s-master:~#

5-4. ingress

ingressも同様です。

root@k3s-master:~# cp ingress.yml /var/lib/rancher/k3s/server/manifests/ingress.yml
(数秒後)
root@k3s-master:~# k3s kubectl get ing
NAME            CLASS    HOSTS   ADDRESS                                     PORTS   AGE
nginx-ingress   <none>   *       192.168.1.150,192.168.1.151,192.168.1.152   80      12s
root@k3s-master:~#

ちなみにK3sはTraefikというingressコントローラが標準で入っているので、コントローラのデプロイなしで使用することができます。

逆にTrarfik以外のingressコントローラを使う場合は、マスターノードでのk3s起動時に指定が必要みたいです。

curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="--disable=traefik" sh -

結果確認

ローカルPCのブラウザからingressで公開したアドレスを入力するとnginxのトップページが表示されました。

また、podのログからもアクセスが来ていることがわかります。

root@k3s-master:~# k3s kubectl logs nginx-7dc45fbd74-dfjg6
(中略)
10.42.0.7 - - [26/Jun/2021:10:30:28 +0000] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36" "10.42.0.1"
------------------------------------------------------------------------ 
root@k3s-master:~# k3s kubectl logs nginx-7dc45fbd74-lc5q7
(中略)
10.42.0.7 - - [26/Jun/2021:10:35:18 +0000] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36" "10.42.0.1"
------------------------------------------------------------------------ 
root@k3s-master:~# k3s kubectl logs nginx-7dc45fbd74-bjgxq
(中略)
10.42.0.7 - - [26/Jun/2021:10:30:31 +0000] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36" "10.42.0.1"

お疲れさまでした!!!

感想

マネージドサービスを使わずにKubernetesクラスタを組んだのは初めてでしたが、思ったよりもスムーズに進められました。
せっかく軽量なKubernetesなので、今度はシングルボードコンピュータでk3sクラスタを組んで遊ぼうと思います。

参考

日本語版k3s マニュアルダウンロード - 株式会社スタイルズ
k3s でクラスタ (Master 1台/Worker 2台) を構築してみた - SIOS TECH.LAB