意識低いおうちKubernetesの作り方
はじめに
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を焼きこむためのツール
ざっくり手順
- UbuntuのブータブルUSBスティックを作成する
- ブータブルUSBスティックを使ってNucBoxにUbuntuをインストールする
- NucBox内にk3sをインストールする
未来のワイが分かればいい手順
UbuntuのブータブルUSBスティックを作成する
NucBoxには既にWindows OSが入っているが、Linux OSでも起動できるようにしたかった。
そのため、最初にUbuntuをUSBメモリから起動できるように、USBメモリの中身を書き換えてあげる。
Rufusというwindowsのソフトウェアを使って、家に転がっていたUSBメモリを書き換えた。64GBのメモリに入っていたゴミデータを削除したが、正直8GBもあれば十分だった。
ブータブルUSBスティックを使ってNucBoxにUbuntuをインストールする
ブータブルUSBスティックを使ってUbuntuを起動するためには、起動時にロゴが出たタイミングでキーボードキーを押せばBIOSの画面が出てきて~という情報が散見されたが、キーが違ってたのかWindowsの画面しか出てこなかった(起動が早いのがせめてもの救い)
最終的に、下記の手順でうまくいった。
- NucBoxをWindowsで起動する
- Windowsのバージョン更新を選択し、セキュリティパッチなど一応当てた状態にしておく(Linuxしか使わないなら意味ないけど)
- 左下の検索から、「回復」と入力し、設定画面を出す
- 「PCの起動をカスタマイズする」の「今すぐ再起動」を選択する
- 青い画面が出てくるので「デバイスの使用」を選び、その中で[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のネット回線サービスに申し込んだので正直よくわからない。
とりあえず、公開される使用可能ポートを確認した後、「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のスタートガイドに従って入力していく。
# 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でスターティングガイド用に使われてるみたい。
所感
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したい
とりあえず、これからも大切に育てるぞい。
Discussion