- Raspberry Piを買っておうちKubernetesクラスタを作る <- イマココ
- おうちKubernetesにSealedSecretsを入れる
6月の初頭に興味本位でRaspberry Pi4を買ってみた.特に何がしたかったわけではないけど,最近Kubernetesクラスタを作っていなかったのでクラスタが作りたくなった. しかしどうせ作るならControlPlaneは3台ほしい.と思っていた矢先に
こういう記事が出ていたので,これは朗報.とりあえずControlPlane1台で作って,後で2台買い増そう.きっと夏くらいになったら買えるようになるはず.
というわけで初手で買ったもの.
最初に目指す構成.
Name | IP | OS | Machine |
---|---|---|---|
master01 | 192.168.0.50 | Ubuntu Server 22.04 LTS | Raspberry Pi4 |
worker01 | 192.168.60 | Ubuntu Server 22.04 LTS | 古いIntelデスクトップ |
flowchart TB Admin -- kubectl -->VIP subgraph Master01 keepalived-->kube-apiserver VIP-->HAProxy HAProxy-->kube-apiserver etcd end subgraph Worker01 kubelet-->VIP end
Raspberry Pi4にOSを入れる
KIOXIAのmicroSDカードには,SD変換アダプタがついていたのでPC側のSDカード刺し口にそのまま刺せた.
Raspberry Pi用にOSを書き込むにはrpi-imagerが要る.公式から落としてもいいし,
$ yay -S rpi-imager
俺はこうした.
あとは好きなOSを選べばいいのだが,OS周りであまり苦労したくないのでいつもどおりUbuntu Server 22.04 LTSを選んでおく.
で,書き込むだけ.
あとはmicroSDカードをRaspberry Piに挿して電源を入れるのみ.これで勝手にOSが起動する.
SSHする
最近のUbuntu ServerはHDMIケーブルで画面出力しなくてもSSHの設定くらいはオンラインでできてしまう.
まずLANケーブルを接続する.この時点でDHCPで適当なIPが割り振られるはずである.あとは同じLAN内から
$ arp -a ... ? (192.168.0.50) at d8:3a:dd:xx:xx:xx [ether] on enp31s0
すると,接続されている機器が出てくる.
ここのどれかなので,それに該当しそうなものからアタリをつける. あとはそこにSSHしてみる.
$ ssh ubuntu@192.168.0.50
初期パスワードはubuntuになっており,認証すると最初にパスワード変更を求められる.その後は,変更後のパスワードを使ってSSHできる.
このタイミングで公開鍵を ~/.ssh/authorized_keys
に入れてしまえば,あとは公開鍵認証でSSHできるようになる.
IP固定とWiFi設定
IPを固定したいのと,LANケーブルではなくWiFi接続にしておきたい.
というわけで
/etc/netplan/99-manual-conf.yaml
network: wifis: wlan0: dhcp4: false access-points: "access_point": password: "password" addresses: - 192.168.0.50/24 routes: - to: default via: 192.168.0.1 nameservers: addresses: - 192.168.0.1 - 8.8.8.8 search: [] version: 2
としておくことで,IPは192.168.0.50
となり,WiFiで接続できるようになる.
ついでに /etc/hosts
に今回使うIPを書いておく.
192.168.0.40 kube-apiserver.h3poteto.local 192.168.0.50 master01.h3poteto.local 192.168.0.60 worker01.h3poteto.local
192.168.0.40
は将来的にHA構成にしたいので,master01のIPとは別のIPにしておいて,後述するkeepalivedのVIPとして使う.
Kubeadmを使える状態にする
基本的にはすべてここに従っている.
Swapを切る
Kubeletを正しく動作させるためにはswapを切る必要がある.
$ swapoff -a
IPv4フォワーディングを有効化する
コンテナランタイムを入れる前提条件.
$ cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf overlay br_netfilter EOF $ sudo modprobe overlay $ sudo modprobe br_netfilter $ cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-iptables = 1 net.bridge.bridge-nf-call-ip6tables = 1 net.ipv4.ip_forward = 1 EOF $ sudo sysctl --system
containerdを入れる
CRIはcontainerdを使う.containerd自体はdockerと一緒にインストールできる.
$ sudo apt-get install ca-certificates curl gnupg $ sudo install -m 0755 -d /etc/apt/keyrings $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg $ sudo chmod a+r /etc/apt/keyrings/docker.gpg $ echo \ "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null $ sudo apt-get update $ sudo apt-get install containerd.io
その上で,containerdの設定を書き換えておく.こうしておかないとsystemd cgroup driverが使えない.
https://kubernetes.io/docs/setup/production-environment/container-runtimes/#containerd-systemd
/etc/containerd/config.toml
version = 2 [plugins] [plugins."io.containerd.grpc.v1.cri"] [plugins."io.containerd.grpc.v1.cri".containerd] [plugins."io.containerd.grpc.v1.cri".containerd.runtimes] [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc] runtime_type = "io.containerd.runc.v2" [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] SystemdCgroup = true
nerdctlを入れる
ホスト上でのデバッグが便利なので,containerdのインターフェースを叩けるCLIがあると良い.最近はnerdctlを使っている.
HAProxyを入れておく
本来ControlPlane1台のKubernetesであれば不要だけれど,将来的に拡張する気なので予めHAProxyを入れておく. こうしておかないと,将来的にControlPlaneノードを追加したときにAPIServerへのリクエストを分散させる方法がなくなってしまう.
$ sudo apt-get install haproxy keepalived
/etc/haproxy/haproxy.cfg
global log /dev/log local0 log /dev/log local1 notice chroot /var/lib/haproxy stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners stats timeout 30s user haproxy group haproxy maxconn 4000 daemon defaults log global option httplog option dontlognull timeout connect 5000 timeout client 50000 timeout server 50000 frontend kube-apiserver bind *:10443 mode tcp option tcplog default_backend kube-apiserver backend kube-apiserver mode tcp option tcplog option tcp-check balance roundrobin default-server inter 10s downinter 5s rise 2 fall 2 slowstart 60s maxconn 250 maxqueue 256 weight 100 server kube-apiserver-1 192.168.0.50:6443 check
kube-apiserverはデフォルトで6443で起動するので,そこをバックエンドにしておく.あとでノードを追加した際にはbackendにserverを追加していく.
/etc/keepalived/keepalived.conf
global_defs { notification_email { } router_id LVS_DEVEL vrrp_skip_check_adv_addr vrrp_garp_interval 0 vrrp_gna_interval 0 } vrrp_script chk_haproxy { script "killall -0 haproxy" interval 2 weight 2 } vrrp_instance haproxy-vip { state MASTER priority 100 interface wlan0 # Network card virtual_router_id 60 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.0.40/24 # The VIP address } track_script { chk_haproxy } }
で,こういうkeepalivedを作っておくと,VIPでアクセスできる.
kubeadm, kubelet, kubectlを入れる
$ sudo apt-get install apt-transport-https linux-modules-extra-raspi
linux-modules-extra-raspi
を入れておかないと,VXLANが作れないので,いざCNIを入れたときにCNIが動かない.
$ curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-archive-keyring.gpg $ echo "deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list $ sudo apt-get update $ sudo apt-get install -y kubelet kubeadm kubectl $ sudo apt-mark hold kubelet kubeadm kubectl
これで終わり.
kubeadmを叩く
あとは叩くだけ.
$ sudo kubeadm init --pod-network-cidr=10.0.0.0/8 --control-plane-endpoint=kube-apiserver.h3poteto.local --apiserver-cert-extra-sans=kube-apiserver.h3poteto.local Your Kubernetes control-plane has initialized successfully! To start using your cluster, you need to run the following as a regular user: mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config Alternatively, if you are the root user, you can run: export KUBECONFIG=/etc/kubernetes/admin.conf You should now deploy a pod network to the cluster. Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at: https://kubernetes.io/docs/concepts/cluster-administration/addons/ You can now join any number of control-plane nodes by copying certificate authorities and service account keys on each node and then running the following as root: kubeadm join kube-apiserver.h3poteto.local:6443 --token xxxx \ --discovery-token-ca-cert-hash sha256:xxxx \ --control-plane Then you can join any number of worker nodes by running the following on each as root: kubeadm join kube-apiserver.h3poteto.local:6443 --token xxxx \ --discovery-token-ca-cert-hash sha256:xxxx
--control-plane-endpoint
は複数ControlPlaneにするのであれば指定したほうがいい.というか
Turning a single control plane cluster created without --control-plane-endpoint into a highly available cluster is not supported by kubeadm.
なので指定しないと無理なんじゃないだろうか.ここはIPでもドメインでもどちらでも受け取れるのだが,まぁhostsファイルを書き換える手間を惜しまないのであればドメインの方が楽なんじゃないかな…….あとあとkeepalived周りの構成を変えたりしたときに,IPが変わったりすると厄介なので.
--pod-network-cidr
は入れるCNIによっては強制されるので,flannelとか入れる場合は注意したほうがいい.今回はCiliumを入れるので,気にせずでかいCIDRをもらう.
あと,デフォルトではkube-apiserverは6443ポートを指定される.これはHAProxyを設定した際に10443で受けるようにしたので,実際にこのコマンドを使う場合は10443ポートを指定する.
とりあえずこれでControlPlaneは完成. この状態だとまだNodeがRunningにはならない.
Worker
kubeadmの準備までほぼ同じ.たまにaarch64向けのパッケージはamd64に変えなきゃいけないところがあるくらい.
で,
$ kubeadm join kube-apiserver.h3poteto.local:10443 --token xxxx \ --discovery-token-ca-cert-hash sha256:xxxx
こうするだけ.
CNIを入れる
今回はCilium.
といってもhelmで入れるだけなんだけどね.
まとめ
できあがり.
$ k get node NAME STATUS ROLES AGE VERSION master01.h3poteto.local Ready control-plane 18d v1.27.2 worker01.h3poteto.local Ready <none> 18d v1.27.2
なぜHDMIケーブルを買ったのだろう.一度も出番がなかった.それもこれもUbuntu ServerがLANケーブル接続だけでSSH設定を完結できてしまったからなのだが. 今の所デバッグ用途ですら登場シーンがない.本当に何故買ったのだろう.
で,このままだとまだSecretManagerも入れていないし,PVも使えないしで,あんまり動かせるものがない. というわけで,この先の作業は次回に続く.