🏠

意識低いおうちKubernetesの作り方

2023/06/03に公開

はじめに

TwitterのTLで一目ぼれしてGMKtec NucBox G1というミニPCを三台購入したので、おうちkubernetesを組んでみた。

準備したもの

ハード面

  • GMKtec NucBox G1(以降、NucBox) x 3台
  • スイッチハブ
  • LANケーブル x 4本
  • USBメモリ(Ubuntu Desktopブート用)

ソフト面

  • Ubuntu Desktop 日本語 Remix
    • Ubuntu 22.04 LTS Desktopをベースに日本語への対応がされたもの
  • k3s
    • Rancherが出している軽量なkubernetesディストリビューション
    • 通常etcdが使われるメタ情報のデータベースがSQLiteで構成されていたり、シングルバイナリに必要なアプリケーションが入っていたり、少ないリソースでk8sを動かすための工夫がされている
    • でも、CNCFの互換性テストを通ってるのでちゃんとしたKubernetes。
    • 選んだ理由はセットアップが死ぬほど楽(後述)
  • Rufus
    • USBメモリにUbuntuを焼きこむためのツール

ざっくり手順

  1. UbuntuのブータブルUSBスティックを作成する
  2. ブータブルUSBスティックを使ってNucBoxにUbuntuをインストールする
  3. NucBox内にk3sをインストールする

未来のワイが分かればいい手順

UbuntuのブータブルUSBスティックを作成する

NucBoxには既にWindows OSが入っているが、Linux OSでも起動できるようにしたかった。
そのため、最初にUbuntuをUSBメモリから起動できるように、USBメモリの中身を書き換えてあげる。

Rufusというwindowsのソフトウェアを使って、家に転がっていたUSBメモリを書き換えた。64GBのメモリに入っていたゴミデータを削除したが、正直8GBもあれば十分だった。
https://ubuntu.com/tutorials/create-a-usb-stick-on-windows#1-overview

ブータブルUSBスティックを使ってNucBoxにUbuntuをインストールする

ブータブルUSBスティックを使ってUbuntuを起動するためには、起動時にロゴが出たタイミングでキーボードキーを押せばBIOSの画面が出てきて~という情報が散見されたが、キーが違ってたのかWindowsの画面しか出てこなかった(起動が早いのがせめてもの救い)

最終的に、下記の手順でうまくいった。

  1. NucBoxをWindowsで起動する
  2. Windowsのバージョン更新を選択し、セキュリティパッチなど一応当てた状態にしておく(Linuxしか使わないなら意味ないけど)
  3. 左下の検索から、「回復」と入力し、設定画面を出す
  4. 「PCの起動をカスタマイズする」の「今すぐ再起動」を選択する
  5. 青い画面が出てくるので「デバイスの使用」を選び、その中で[USB]から始まるそれっぽいのを選ぶ

そうするとNucBox起動後に、「Ubuntuを試す」と「Ubuntuをインストール」という二択画面が出てくるので、「Ubuntuをインストール」を選択する。

その後、画面なりに進むと「インストールの種類」というタイトルが出てくるので「UbuntuをWindows Boot Managerとは別にインストール」を選択する。その後、パーティションのサイズなど聞かれるが...NucBoxはそのために1TBのM.2 SSD積んだのだ。スペックのゆとりは心のゆとり...なんも考えずすべてデフォルトで設定する。

インストール作業完了後、再起動するか聞かれるので「今すぐ再起動する」を選択すると、先ほどは出てこなかったGNU GRUBの真っ黒い画面が出てくる。なんも考えず、Enterキーを押すとUbuntuが起動するようになる。

IPアドレスを固定する

Ubuntu起動後に細かい準備作業をする。

「ubuntu ipアドレス 固定」でググって出てきた手順に従って、「サーバーのIPアドレス」、「ネットマスク」、「ゲートウェイ」の設定を行う。

SSHを有効にする

「アプリ」-> 「端末」からコンソール画面を開いてSSHを有効にする

sudo apt install openssh-server

ufwを無効にする

自宅はIPv6プラスという仕組みでインターネットにつながっているらしい。自分で契約しててなんだが、とりあえず一番早いというノリで10Gbpsのネット回線サービスに申し込んだので正直よくわからない。

とりあえず、
https://isecj.jp/tools/portcheck-map-e/
公開される使用可能ポートを確認した後、「6443」ポートがないことを確認して、Ubuntuのソフトウェアファイアウォール ufw を無効化する。[1]

sudo ufw disable

同じ手順を2回、他のNucBoxにも繰り返す

上記手順を2回、他のNucBoxにも繰り返す。

今日からお前がController Nodeだ

3台のNucBoxのセットアップが完了したところで、そのうち一台をController Node兼操作用踏み台サーバーと決めて、その中で作業する。最終的なkubernetesクラスタのイメージ図っぽいものも書いておく。

LANケーブルのポートが足りなかったので、Amazonで買ってきたスイッチを適当に挿して、払い出されたIPアドレスをそのまま使用する。


以降は、Controler Nodeと決めた親機?のNucBoxで作業する。

k3sをセットアップする

コンソール画面を開く。

k3sのスタートガイドに従って入力していく。
https://docs.k3s.io/quick-start

# controllerって作業ディレクトリを作ってそこで作業する
soharaki@soharaki-NucBox-G1:~$ mkdir controller
soharaki@soharaki-NucBox-G1:~$ cd controller
# curlが入ってないのでセットアップする
soharaki@soharaki-NucBox-G1:~/controller$ sudo apt install curl
# k3sをセットアップする
soharaki@soharaki-NucBox-G1:~/controller$ curl -sfL https://get.k3s.io | sh -
(なんかインストールログが出てくるがこれでおしまい)

あっけなく終わって嘘だろ...と衝撃を受ける。
Controler Nodeへの作業が終わったのでWorker Nodeにもk3sを設定する。

# serverのnode-tokenがあることを確認する
soharaki@soharaki-NucBox-G1:~/controller$ sudo cat /var/lib/rancher/k3s/server/node-token
K00000...
# node-tokenを各Worker Nodeにファイル転送する
soharaki@soharaki-NucBox-G1:~/controller$ sudo scp /var/lib/rancher/k3s/server/node-token soharaki@192.168.1.8:/home/soharaki
soharaki@soharaki-NucBox-G1:~/controller$ sudo scp /var/lib/rancher/k3s/server/node-token soharaki@192.168.1.5:/home/soharaki

各Worker Nodeサーバーに入って、k3sをセットアップし、Controler Nodeと接続する。

# worker1に入って作業する(worker2も同様)
soharaki@soharaki-NucBox-G1:~$ ssh 192.168.1.8
# 先ほど転送したnode-tokenがあることを確認する
soharaki@soharaki-NucBox-G1-3:~$ ls
node-token
# node-tokenを使ってWorker Nodeのセットアップを行う
# K3S_URLは先ほど決めた親機のIPアドレスにする
soharaki@soharaki-NucBox-G1-3:~$ K3S_TOKEN=$(cat node-token)
soharaki@soharaki-NucBox-G1-3:~$ curl -sfL https://get.k3s.io | K3S_URL=https://192.168.1.13:6443 K3S_TOKEN=$K3S_TOKEN sh -
[INFO]  Finding release for channel stable

[INFO]  Using v1.26.5+k3s1 as release
[INFO]  Downloading hash https://github.com/k3s-io/k3s/releases/download/v1.26.5+k3s1/sha256sum-amd64.txt
[INFO]  Skipping binary downloaded, installed k3s matches hash
[INFO]  Skipping installation of SELinux RPM
[INFO]  Skipping /usr/local/bin/kubectl symlink to k3s, already exists
[INFO]  Skipping /usr/local/bin/crictl symlink to k3s, already exists
[INFO]  Skipping /usr/local/bin/ctr symlink to k3s, already exists
[INFO]  Creating killall script /usr/local/bin/k3s-killall.sh
[INFO]  Creating uninstall script /usr/local/bin/k3s-agent-uninstall.sh
[INFO]  env: Creating environment file /etc/systemd/system/k3s-agent.service.env
[INFO]  systemd: Creating service file /etc/systemd/system/k3s-agent.service
[INFO]  systemd: Enabling k3s-agent unit
Created symlink /etc/systemd/system/multi-user.target.wants/k3s-agent.service → /etc/systemd/system/k3s-agent.service.
[INFO]  systemd: Starting k3s-agent
(これで終わり)

k3sが動いていることをkubectlコマンドで確認する

Worker Node作業が終わったら、Controller Nodeに戻ってくる。
下記のコマンドでkubectlコマンドをインストール、k3sに接続し、ステータスを確認する。

soharaki@soharaki-NucBox-G1:~$ curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"

# kubeconfigファイルはk3sセットアップ時に払い出してくれる親切設計なのでそのまま利用する
soharaki@soharaki-NucBox-G1:~$ sudo chmod 644 /etc/rancher/k3s/k3s.yaml 
# rebootするとなぜかyamlのパーミッション権限が外れるので固定する
soharaki@soharaki-NucBox-G1:~$ echo K3S_KUBECONFIG_MODE="644" >> /etc/systemd/system/k3s.service.env
soharaki@soharaki-NucBox-G1:~$ export KUBECONFIG=/etc/rancher/k3s/k3s.yaml  
soharaki@soharaki-NucBox-G1:~$ kubectl get nodes
NAME                   STATUS   ROLES                  AGE   VERSION
soharaki-nucbox-g1-2   Ready    <none>                 53m   v1.26.5+k3s1
soharaki-nucbox-g1     Ready    control-plane,master   78m   v1.26.5+k3s1
soharaki-nucbox-g1-3   Ready    <none>                 57m   v1.26.5+k3s1

動いたー!


他、気になったことをちまちま直していく

NodeのROLESにラベルを付ける

kubectl label node soharaki-nucbox-g1-2 node-role.kubernetes.io/worker=worker
kubectl label node soharaki-nucbox-g1-3 node-role.kubernetes.io/worker=worker

簡単そうなデモアプリを動かしてみる

DegitalOceanのpod-infoというデモアプリが可愛かったので動かしてみる。

$ sudo apt install git
$ git clone https://github.com/digitalocean/kubernetes-sample-apps.git
$ cd kubernetes-sample-apps/
$ kubectl apply -k podinfo-example/kustomize
(ちょっと待つ)
$ kubectl get all -n podinfo
NAME                           READY   STATUS    RESTARTS   AGE
pod/podinfo-575f4f875f-dmfh9   1/1     Running   0          11m
pod/podinfo-575f4f875f-sqd5f   1/1     Running   0          11m

NAME              TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)             AGE
service/podinfo   ClusterIP   10.43.182.66   <none>        9898/TCP,9999/TCP   11m

NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/podinfo   2/2     2            2           11m

NAME                                 DESIRED   CURRENT   READY   AGE
replicaset.apps/podinfo-575f4f875f   2         2         2       11m

NAME                                          REFERENCE            TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
horizontalpodautoscaler.autoscaling/podinfo   Deployment/podinfo   2%/99%    2         4         2          11m
$ kubectl port-forward service/podinfo -n podinfo 9898:9898
Forwarding from 127.0.0.1:9898 -> 9898

画面出た!

https://github.com/stefanprodan/podinfo によると、E2Eテストやワークショップなどに使えるらしい。 curl localhost:9898/swagger.json でAPIを調べたら色々出てきた。

GitOpsツールのFluxでスターティングガイド用に使われてるみたい。
https://fluxcd.io/flux/get-started/#add-podinfo-repository-to-flux

所感

RedditのHomelabスレを見てるとアハハってなるけど、一つのサーバーでminikubeをセットアップして動かしてもそれはホームラボと言えるのか?みたいなレベル感を狙って、

  • 仮想化基盤(VMware ESXiとかDockerとか)を使わないベアメタル・サーバーを使う
  • サーバー(ノード)を複数台用意する

という縛りで雑にKubernetesクラスタを構成したらほとんど詰まることなくできてしまった。初めてKubernetesに出会った頃に「Kubernetes the hard way」はいいぞと騙されて第四章で呪文のように証明書コマンド打ってたのはなんだったんだろう。。

今後やりたいこととしては、

  • keplerでエコりたい
  • UISP EdgeRouter Xが手に入ったのでMetallbのBGP Mode頑張りたい
  • traefikを別のCNIに入れ替えたい
  • Equinix MetalでPXE Bootしたい

とりあえず、これからも大切に育てるぞい。

脚注
  1. 公式手順だし。。 SELinuxよりも市民権がなくてよかった。 ↩︎

Discussion