🫐

Alpine Linux + K3sで実現するRaspberry Piの超軽量Kubernetesノード構築

に公開

Summary

  • Raspberry Pi 2/3/4でAlpine Linux + K3sによる超軽量Kubernetes環境を構築
  • メモリ使用量を300MB程度に抑制し、Ubuntu Server比で大幅なパフォーマンス向上を実現
  • 10-20秒の高速ブート時間を達成し、従来のUbuntu Server環境(1分程度)を大幅に改善

やらないこと

  • K3s serverの構築手順(本記事はagent構築のみ。server構築手順はk3sドキュメントまたは前回記事を参照)
  • 複雑なKubernetesアプリケーションのデプロイメント
  • 基本的なパーティション作成、フォーマット操作

本記事における課題

以前、Raspberry Pi に軽量 Kubernetes を導入し高可用な自宅サーバーを実現するでRaspberry Pi 2/3/4でUbuntuベースのKubernetes環境を構築したが、以下の深刻なパフォーマンス問題に直面した:

  1. メモリ不足の頻発:特にRaspberry Pi 2/3(1GB RAM)ではOSだけでメモリを大量消費
  2. 起動時間の長さ:Ubuntuでは1分程度の起動時間でレスポンスが悪い
  3. 運用継続困難:主にメモリ不足からくるパフォーマンスの悪化により、前回記事の運用開始後、Raspberry Pi 2/3を除外していた

これらの課題を解決するため、Alpine Linuxベースの"超"軽量環境を検討し、劇的な改善を実現した経験を共有する。

やったこと

1. Alpine Linux SDカード準備とヘッドレスセットアップ

Alpine LinuxのSDカード準備手順

従来のRaspberry Pi Imagerではなく、ヘッドレス(キーボード+モニタなし)でのAlpine Linuxセットアップを行う。ここでは有線LANが必要である。

1. Alpine Linuxイメージのダウンロード

Alpine LinuxのダウンロードページからRaspberry Pi用のイメージをダウンロードする。

  • Raspberry Pi 4/3: aarch64版をダウンロード
  • Raspberry Pi 2: armv7版をダウンロード

2. ヘッドレスインストール用Bootstrapのダウンロード

alpine-linux-headless-bootstrapの最新バージョンをダウンロードする。各バージョンごとに headless.apkovl.tar.gz が準備されている。

3. SDカードのパーティション作成

microSDカードに以下のパーティション構成を作成する:

  • パーティション1: 256MB FAT32(ブート用)
  • パーティション2: 残り容量 ext4(データ用)

この作業は一般的なパーティション管理ツール(fdisk、gparted等)で実行可能である。

4. Alpine Linuxファイルの展開とコピー

ダウンロードしたAlpine Linuxイメージを展開し、展開後のファイル一式をFAT32パーティションにコピーする。

5. Bootstrapファイルの配置

headless.apkovl.tar.gz を圧縮ファイルのままFAT32パーティションにコピーする。

最終的に、FAT32パーティションには以下が配置される:

  • Alpine Linuxイメージの展開ファイル一式
  • headless.apkovl.tar.gz(圧縮ファイルのまま)

6. 初回起動とIP特定

# SDカードをRaspberry Piに挿入し、有線LANを接続して電源投入

# SSH接続マシンからRaspberry PiのIPを特定
# 方法1: arp-scanを使用
sudo arp-scan -I eth0 192.168.xxx.0/24

# 方法2: ルーターの管理画面でDHCP払出し状況を確認

7. 初回SSH接続

# 特定したIPアドレスにSSH接続(初回はパスワードなし)
ssh root@192.168.xxx.xxx

2. Alpine Linux初期セットアップ

基本設定(setup-alpine実行)

# SSH接続(初回)
ssh root@192.168.xxx.xxx

# Alpine Linuxセットアップウィザード実行
setup-alpine

セットアップウィザードでの設定内容:

  • Hostname: お好きな名前
  • Network Interface: eth0(静的IP設定)
    • IP address: 192.168.xxx.xxx
    • Netmask: 255.255.255.0
    • Gateway: 192.168.xxx.xxx
  • DNS: 192.168.xxx.xxx
  • Root Password: お好きなパスワード
  • Timezone: Asia/Tokyo
  • APK Mirror: 57 (ftp.udx.icscoe.jp)
  • User: お好きなユーザー名
  • SSH Server: openssh
  • Disk: Boot media /media/mmcblk0p1使用

SSH設定調整と永続化

# rootログインを許可
echo "PermitRootLogin yes" >> /etc/ssh/sshd_config
# 設定を永続化用パーティションに書き込み可能にする
mount -o remount,rw /media/mmcblk0p1
# 不要なファイル削除
rm /media/mmcblk0p1/*.apkovl.tar.gz
# 設定をコミット
lbu add /etc/init.d
lbu add /root/.ssh
lbu add /usr/local/bin  # for k3s binary
lbu commit -d
# 再起動して設定反映
reboot

:::note alert
rootにパスワードログインできてしまうことは望ましくないので、よりセキュアに運用する場合は鍵認証を推奨する。
:::

3. 軽量ストレージ戦略の実装

データディスク設定

# SDカードパーティション確認
blkid
# データ用パーティションのマウントポイント作成
mkdir /media/mmcblk0p2
# fstabに基本マウント設定追加
echo "/dev/mmcblk0p2 /media/mmcblk0p2 ext4 rw,relatime 0 0" >> /etc/fstab
# マウント実行
mount -a

バインドマウントによるメモリ効率化

Alpine Linuxのlbu(Local Backup Utility)は軽量性を重視した設計であり、大容量データの管理には不適切である。そのため、K3sやTailscaleの大容量データを外部ストレージにバインドマウントする手法を採用した。

# K3s用ディレクトリ作成
mkdir -p /media/mmcblk0p2/k3s/lib
mkdir -p /media/mmcblk0p2/k3s/kubelet
# Tailscale用ディレクトリ作成
mkdir -p /media/mmcblk0p2/tailscale/lib

# fstabにバインドマウント設定追加
cat >> /etc/fstab << 'EOF'
/media/mmcblk0p2/k3s/lib /var/lib/rancher none bind 0 0
/media/mmcblk0p2/k3s/kubelet /var/lib/kubelet none bind 0 0
/media/mmcblk0p2/tailscale/lib /var/lib/tailscale none bind 0 0
EOF

起動時マウント設定

# 起動時スクリプト作成(K3s用)
cat > /etc/local.d/rancher.start << 'EOF'
#!/bin/sh
mkdir -p /var/lib/rancher
mkdir -p /var/lib/kubelet
mount /var/lib/rancher
mount /var/lib/kubelet
EOF
chmod +x /etc/local.d/rancher.start

# Tailscale用起動スクリプト
cat > /etc/local.d/tailscale.start << 'EOF'
#!/bin/sh
mkdir -p /var/lib/tailscale
mount /var/lib/tailscale
EOF
chmod +x /etc/local.d/tailscale.start

# localサービス有効化
rc-update add local
lbu commit -d

4. Tailscale VPN接続設定

# Tailscale公式インストールスクリプト実行
curl -fsSL https://tailscale.com/install.sh | sh
# VPN接続(認証URLが表示されるのでブラウザで認証)
tailscale up
# 接続状態確認
tailscale status
# tailscaleのバイナリ保存
lbu commit -d

5. Kubernetes対応設定

カーネルパラメータ調整

# ブートパーティションを書き込み可能にマウント
mount -o remount,rw /media/mmcblk0p1
# cmdline.txtを編集
vi /media/mmcblk0p1/cmdline.txt

cmdline.txtの設定内容:

modules=loop,squashfs,sd-mod,usb-storage quiet console=tty1 cgroup_enable=cpuset cgroup_enable=memory cgroup_memory=1

cgroupsとマウント設定

# OpenRCでcgroupsモード設定
echo 'rc_cgroup_mode="unified"' >> /etc/rc.conf

# cgroup v2用マウント設定
echo 'cgroup2 /sys/fs/cgroup cgroup2 rw,nosuid,nodev,noexec,relatime,nsdelegate 0 0' >> /etc/fstab

# cgroupsサービス有効化
rc-update add cgroups default

# マウント共有設定
cat > /etc/local.d/mount-shared.start << 'EOF'
#!/bin/sh
mount --make-rshared /
EOF
chmod +x /etc/local.d/mount-shared.start

# 設定保存
lbu commit -d

6. K3s Agentインストール

# K3s agentインストール
curl -sfL https://get.k3s.io | \
  K3S_TOKEN="XXXXXX" \
  K3S_KUBECONFIG_MODE=644 \
  sh -s - agent \
  --server https://[K3s serverのIPまたはドメイン]:6443 \
  --flannel-iface tailscale0

# 設定保存
lbu commit -d

7. パフォーマンス確認

# システムメモリ使用状況確認
free -h
# プロセス別メモリ使用量確認
htop

正確に測ってないが、概ね以前と比べて以下の違いが出た。

Ubuntu 22.04環境:

  • 起動時間: 約60秒
  • OS基本メモリ使用量: 約100-200MB
  • K3s agent + Tailscale込みメモリ使用量: 約400-500MB
  • Raspberry Pi 2/3での動作: メモリ不足で実質運用不可

Alpine Linux環境:

  • 起動時間: 約10-20秒
  • OS基本メモリ使用量: 約80MB
  • K3s agent + Tailscale込み: 約300MB
  • Raspberry Pi 2/3での動作: 快適に動作

以下はRaspberry Pi 2におけるhtopの実行結果。
一通りセットアップを終えた後、Kuberenetesクラスターに参加し、RedisやCoreDNS、Node Exporter、Promtailなどを動作させている。

この改善により、運用から外れていたRaspberry Pi 2/3でも実用的なKubernetes環境を構築できるようになった。

まとめ・所感

Alpine Linux + K3sの組み合わせにより、前回のUbuntu環境と比較して劇的なパフォーマンス改善を実現できた。特に以下が顕著である:

  1. 基本コンポーネント(OS+Tailscale+K3s agent)のメモリ使用量の大幅削減: Ubuntu比で40%以上の削減(500MB→300MB)
  2. 起動時間の短縮: 1分→10-20秒へと大幅改善
  3. Raspberry Pi 2/3の実用化: 以前は運用困難だったが、今回は快適に動作

特にRaspberry Pi 2/3での動作改善は予想以上で、1GB RAMでも十分な余裕を持って動作している。これにより、古いRaspberry Piも有効活用でき、コストパフォーマンスが大幅に向上した。

従来のUbuntu環境では「使えるが重い」状態だったが、Alpine Linux環境では「軽快で実用的」な環境を実現できている。同様の課題(これまでのイベントで貰ったRaspberry Piを持ち腐らせている?)を抱える方にとって、本手順が参考になれば幸いである。

参考リンク

Discussion