1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

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

1
Posted at

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版をダウンロード

image.png

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使用

USB HDDを使う場合は /media/sda1 または /media/usb として認識される。

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

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

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

データディスク設定

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

ここではあまり触れないが(きちんと理解していないとも言える)、この手法では基本的に/dev/mmcblk0p1の内容が起動時にRAMに展開され、必要に応じて/dev/mmcblk0p2をマウントして読み書きする形になるので、microSDへ直接読み書きする頻度が減る。そのため高速化と同時にストレージの寿命を長くすることにも繋がる。

ただしログローテやキャッシュがメモリ上で間に合わなくなった場合はどうなるんだろう...という点は運用しながら観察したい。

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

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

当方の環境では、K3s serverをクラウドVPSに置いており、外部からアクセスするためのゲートウェイを兼ねている。(どこかで記事化したい)

そのためNAT越えにTailscale VPNを採用している。有線LANもしくは無線LANのみ接続し、VPNを利用しないならば、通常は --flannel-iface の指定は不要。

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などを動作させている。

image.png

この改善により、運用から外れていた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も有効活用でき、コストパフォーマンスが大幅に向上した。

と言いつつ、Raspberry Pi 2は64bitでは動作しないので、最新ソフトウェアのコンテナは動作しない場合がある。どうしても最新ソフトウェアを動かしたければ、自前でコンテナビルドが必要。

CloudNativePGでPostgreSQLのクラスターを組み、コンテナを各ノードに散らして冗長化しているので、Raspberry Pi 2用にCloudNativePGコンテナをビルドしたいかも。最近公式ではarmv7のサポートが外れたそう、残念。

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

個人・会社問わず、Kubernetesを運用する機会が増えたのでちゃんと勉強したい。良さそうなコミュニティがあれば参加させてください...

参考リンク

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?