おうちKubernetesを構築した話
Kubernetesの資格CKA/CKADを取得し、なにか自分にご褒美を与えたいな〜と思い……おうちKubernetesを構築することにしました!楽しみにしてたんだ!!
前日譚: ryusa.hatenablog.com
モチベーション 🦾
そもそもなんでおうちKubernetesなんて?と言う話から……
自分の仕事柄、職場のエンジニアの多くが自宅になにかしら機材を持ち込んで幸せになってる人が多いんですよね
- おうちKubernetes
- おうちサーバー&おうち iLO
- おうちESXi
- おうちクラウドサービス
- おうちハニーポット
- おうちBGPフルルート
先日も仕事の帰り道に数万する機材をポチって自宅に搬入したとか話を聞き、これはもはや一種の宗教じゃないのか とても羨ましい!ぜひ我が家にも!!と、ぼくも家に機材を搬入してみたいな〜と思ってました。
とはいえ、残念ながら自分は仕事で機材に触る機会も少なく、いきなり高価な機材に手を出すのは難易度が高すぎると感じていたので、まず簡単なKubernetesクラスターを家に置いておきたい欲求があったわけでした。
構築 - 物理編
まずは機材の調達から。 今回はRaspberry Pi 4 3台をクラスタリングするので備品を調達。
それらをPoEで繋ぐので適当なLANケーブルとハブを用意
SDカードは適当に家に転がっていた32GBのものを利用しています。
先にネタばらししてしまうと、Raspberry Piのみでクラスターを構築した際にどうしてもコントロールプレーンが不安定になってしまったため、家に転がっていたノートPCをコントロールプレーンとして活用しています。
コントロールプレーン:DELL Inspiron13 7378 (Ubuntu Server化済み)
構築 - 論理編
一通り機材のインストールが完了した後、いよいよKubernetesクラスターの構築作業です。microk8sで構築してもいいかな〜とも思いましたが、やはりここはおうちクラスター、妥協はしたくありません。kubeadmでインストールをしました。
今回のクラスターでは、下記の構成で構築していきました。
- OS:Ununtu20.04
- Kubernetes: v1.21.0
- コンテナランタイム:containerd 1.4.4
- CNI:Calico v3.18.3
またStorageのprovisionerとしてNFSを利用したいので、コントロールプレーンにはNFSもインストールしておきます。
最終的な我が家のネットワークはこちら
┌──────────────┐ │ The Internet │ └──────────────┘ ▲ │ │ │ Router 192.168.0.0/16 │ │ ┌───────────────────────┐ │ │ Home Network │ ├─────────┤ 192.168.1.0/24 (DHCP) │ │ └───────────────────────┘ │ │ ┌────────────────────────────────────────────┐ │ │ Kubernetes Cluster Network │ │ │ 192.168.100.0/24 │ │ │ │ │ │ │ │ │ ┌──────────────────────────────┐ │ │ │ │ Seagull Ship(Control Plane) │ │ │ │ │ 192.168.100.101 │ │ │ │ └──────────────────────────────┘ │ │ │ │ │ │ ┌──────────────────────────────┐ │ │ │ │ Seagull (Data Plane) │ │ │ │ │ 192.168.100.[1-3] │ │ │ │ └──────────────────────────────┘ │ └─────────┤ │ │ ┌──────────────────────────────┐ │ │ │ MetalLB │ │ │ │ 192.168.100.[200-250] │ │ │ └──────────────────────────────┘ │ │ │ └────────────────────────────────────────────┘
これに合わせてuser-dataなどに色々インストールしていきます。
Control Plane
適当に転がっているUSBメモリにUbuntuイメージを焼き、ブートさせました。公式のKubernetesのインストール手順に従ってKubernetesをインストールしました。
/etc/netplan/99-manual.yaml
にIPアドレス周りの設定を記入して完了(諸事情によりWifiでコントロールプレーンの運用をしてみました、今のところ安定して動いてます)
network: version: 2 renderer: NetworkManager wifis: wlp1s0: dhcp4: no dhcp6: no addresses: [192.168.100.101/24] gateway4: 192.168.0.1 nameservers: addresses: - 192.168.0.1 access-points: "YOUR_SSID": password: "YOUR_PASSWORD"
Data Plane
Raspberry Piにインストールする予定のSDカードにuser-dataを埋め込み全自動kubernetesインストールまで組み込みました。下記のようなuser-dataを作成し、/system-boot/
配下に配置しておくとRaspberry Pi起動時に自動的にkubeadm/kubeletのインストールがされるようになります。
#cloud-config # hostname hostname: seagull01 # Japan timezone: "Asia/Tokyo" # Never allow to ssh using password ssh_pwauth: false # User "user" users: - name: user gecos: I am user primary_group: user groups: [adm, audio, cdrom, dialout, dip, floppy, lxd, netdev, plugdev, sudo, video] shell: /bin/bash sudo: ALL=(ALL) NOPASSWD:ALL lock_passwd: true ssh_import_id: - gh:RyuSA # Update packages package_update: true package_upgrade: true packages: - apt-transport-https - ca-certificates - curl - gnupg - lsb-release - nfs-common # for nfs client mounts: - [ tmpfs, /tmp, tmpfs, "defaults,size=256m", "0", "0" ] - [ tmpfs, /var/tmp, tmpfs, "defaults,size=256m", "0", "0" ] write_files: # iptablesがブリッジを通過するトラフィックを処理できるようにする - content: | net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 owner: root:root path: /etc/sysctl.d/k8s.conf permissions: '0644' # containerdに必要な設定 - content: | overlay br_netfilter owner: root:root path: /etc/modules-load.d/containerd.conf permissions: '0644' # 必要なカーネルパラメータ - content: | net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1 net.bridge.bridge-nf-call-ip6tables = 1 owner: root:root path: /etc/sysctl.d/99-kubernetes-cri.conf permissions: '0644' runcmd: - sudo swapoff -a - sudo sysctl --system # install containerd - curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg - echo "deb [arch=arm64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null - sudo apt-get update - sudo apt-get install containerd.io - sudo mkdir -p /etc/containerd - containerd config default | sed -e '/containerd.runtimes.runc.options/a \ \ \ \ \ \ \ \ \ \ \ SystemdCgroup = true' | sudo tee /etc/containerd/config.toml - sudo systemctl restart containerd # install kubeadm - sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg - echo "deb [signed-by=/usr/share/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 containerd.io
起動して30分程度放置すると完了しているので、再起動して各ノードでkubeadm join
コマンドを叩いてKubernetesクラスターに参加すればOKです。かんたん!
不安定なクラスター
実は一度Raspberry Piのみでクラスターを構築してみました。……が、かなり不安定になってしまいすぐコントロールプレーンが死んでしまう事態に。 原因としては、どうやらSDカードのI/Oスループットが遅すぎるせいでetcdの書き込みが遅れてしまいkube-apiserverが死んでしまう……ということっぽかったです。(詳細は不明)
そのため、急遽家に転がっていたDellのノートPCをUbuntu Serverにしてコントロールプレーンとして再起動することでクラスターを安定化させました。
おわりに
さて、これでKubernetesクラスターが出来上がりましたが……知ってる人は知っての通り、このままでこのクラスターはあまり美味しくありません。
- 永続化ボリュームが自動で作成されない
- provisioner/storageclassがない
- なんらかの方法でボリュームを作成して使いたい人に渡してあげる必要がある
- Serviceのtype: LoadBalancerが使えない
- Kubernetesの外へアプリケーションの公開が面倒になる
- Ingressが使えない
- Ingress Controllerがない
かなり美味しくないです。美味しくないので、加工してより美味しくするための加工作業を進めていきます。(書いたら↓に追加していきます)