ローカルストレージを超えて:Longhornによる耐障害性に優れたKubernetesボリュームの構築

DevOps tutorial - IT technology blog
DevOps tutorial - IT technology blog

午前2時15分のPagerDutyアラート:なぜローカルストレージでは不十分なのか

ある火曜日の朝、私のスマートフォンがけたたましく鳴り始めました。本番クラスターのワーカーノード(標準的な8コアのベアメタルインスタンス)で、完全なハードウェア障害が発生したのです。理論上、Kubernetesはこうした事態を想定して設計されています。スケジューラがPostgreSQLとRedisのPodを、正常なノードへ自動的に移行させてくれるものと考えていました。

しかし、現実は違いました。PostgreSQLのPodは10分以上もPending状態のままだったのです。ログには、`Podにバインドされていない即時PersistentVolumeClaimsがあります`という、恐ろしいエラーが表示されていました。こうしたYAMLの『針』探しのようなトラブルシューティングを強いられ、特定のNVMeドライブに紐付けられたローカルストレージクラスを使用していたため、データが故障したハードウェアの中に閉じ込められてしまったのです。ストレージに移動性がなかったために、Kubernetesの「自己修復」の約束は果たされませんでした。

永続ストレージのパラドックス

Kubernetesは、標準ではノード間でのデータレプリケーション(複製)を管理しません。hostPathやローカルの静的ボリュームに依存している場合、データは厳密に1つのディスク上にしか存在しません。そのディスクが故障すれば、アプリケーションも道連れになります。ステートフルなマイクロサービスにとって、これは分散クラスターの利点を打ち消してしまう単一障害点となります。特に宣言的なデータベース・スキーマ管理を行っている場合、下位レイヤーのディスク障害は致命的です。

私は、以下の4つの特定の基準を満たすストレージレイヤーを必要としていました。

  • ブロックストレージ: データベースのワークロードに適した、高性能で低レイテンシなアクセス。
  • 同期レプリケーション: データが少なくとも3つのノードに同時に存在すること。
  • 低い運用負荷: 専任のストレージエンジニアを必要としないシステム。
  • ディザスタリカバリ: オフサイトのS3バケットへ自動送信されるスナップショット。

選択肢の検討

クラウドネイティブストレージの市場は混雑しています。私はコストと複雑さに基づいて, 主に3つのパスに絞り込みました。

1. マネージドクラウドディスク (AWS EBS, Azure Disk)

これらは信頼性は高いですが、「クラウド税」とも言えるコストがかかります。AWS EBS gp3ボリュームのコストは、1GBあたり月額約0.08ドルです。さらに重要なのは、故障したノードからボリュームを切り離し、新しいノードに再接続するまでに60秒から120秒かかる場合があることです。高可用性の要件において、この遅延はしばしば許容範囲を超えます。

2. Rook と Ceph

Cephはエンタープライズグレードのストレージとして非常に強力です。しかし、リソース消費が激しいことで知られています。一般的なRook/Cephの構成では、OSD (Object Storage Daemon) ごとに少なくとも2GBのRAMが必要です。中規模のクラスターでは、このオーバーヘッドがアプリケーション自体のメリットを上回ってしまうことがよくあります。

3. Longhorn

LonghornはSUSEが管理するオープンソースプロジェクトです。ノードの既存のローカルストレージを、分散ブロックストレージプールに変換します。軽量で、1つのHelmチャートでインストールでき、非常に直感的なダッシュボードを備えています。パフォーマンスのベンチマークを行った結果、私たちのマイクロサービスアーキテクチャにとって、Longhornが最もバランスの取れた選択肢として浮上しました。

それ以来、私は本番環境のワークロードをこの構成に移行しました。結果は非常に安定しています。堅牢なストレージ基盤を構築するために私が行ったプロセスを以下に示します。

ステップ 1: ノードの準備

Longhornはホスト上のiscsiadmを利用してブロックデバイスを管理します。このユーティリティがないと、ボリュームの接続に失敗し、Podが永久にPending状態のままになります。これはインストール失敗の最も頻繁な原因です。

すべてのワーカーノードに必要な依存関係をインストールします。

sudo apt update
sudo apt install open-iscsi -y
sudo systemctl enable --now iscsid

続行する前に、公式のLonghornチェックスクリプトを使用して環境を確認してください。本番環境でのバグになる前に、設定の問題を特定できます。

curl -sSfL https://raw.githubusercontent.com/longhorn/longhorn/v1.5.x/scripts/environment_check.sh | bash

ステップ 2: Helmによるデプロイ

Helmは、Longhornのライフサイクルを管理する最も信頼できる方法です。アップグレードや設定変更が簡素化されます。まずリポジトリを追加します。

helm repo add longhorn https://charts.longhorn.io
helm repo update

標準的な3ノードクラスターの場合、デフォルトのレプリカ数を3に設定します。これにより、2つのノードが故障しても、3つ目のノードでデータにアクセスし続けることができます。

helm install longhorn longhorn/longhorn \
  --namespace longhorn-system \
  --create-namespace \
  --set persistence.defaultClassReplicaCount=3

ステップ 3: ダッシュボードによる監視

Longhornには、データの健全性を視覚化する強力なUIが含まれています。GUIだけでなく、ターミナルからKubernetesクラスタを管理する際にも、どのノードがどのレプリカを保持しているかを正確に確認できることは大きな利点です。Ingressなしでアクセスするには、クイックポートフォワードを使用します。

kubectl port-forward -n longhorn-system svc/longhorn-frontend 8080:80

http://localhost:8080にアクセスすると、ノードの構成、ディスク使用率、ボリュームの健全性の内訳が表示されます。生のログを解析するよりも、ストレージの問題のトラブルシューティングをはるかに迅速に行えます。

ステップ 4: 回復力のあるPVCの実装

エンジンが動作したら、PersistentVolumeClaim (PVC) を定義できます。Longhornはデフォルトでlonghornという名前のStorageClassを作成します。以下は10GBのPostgreSQLボリュームのマニフェストです。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: postgres-data-pvc
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: longhorn
  resources:
    requests:
      storage: 10Gi

適用されると、Longhornは領域を切り出し、3つのノードに複製します。データベースをホストしているノードがクラッシュした場合、KubernetesはPodを別の場所に再スケジュールします。するとLonghornは、その新しいノード上のローカルデータレプリカを即座に接続します。

ステップ 5: オフサイトS3バックアップ

レプリケーションはハードウェアの故障からは守ってくれますが、ヒューマンエラーからは守ってくれません。スクリプトが誤ってデータベースを削除した場合、その削除も即座に複製されます。真に安全を確保するには、オフサイトバックアップが必要です。

私はAWS S3を使用していますが、MinIOやBackblaze B2でも同様に機能します。まず、認証情報をSecretに保存します。

kubectl create secret generic longhorn-s3-secret \
  --from-literal=AWS_ACCESS_KEY_ID=YOUR_KEY \
  --from-literal=AWS_SECRET_ACCESS_KEY=YOUR_SECRET \
  -n longhorn-system

Longhornの設定で、Backup Targetをs3://your-bucket-name@region/に設定します。Recurring Job(定期的ジョブ)の設定をお勧めします。2時間ごとのスナップショットと24時間ごとのフルバックアップにより、安全性とストレージコストのバランスを良好に保つことができます。

本番環境からの教訓

Longhornを大規模に運用することで、基本的なドキュメントには記載されていないいくつかの実践的な知見が得られました。

CPUオーバーヘッドを監視する

Longhornの各ボリュームは、専用のinstance-manager Podを起動します。それぞれが約0.1 CPUコアと100MiBのRAMを消費します。1GBの小さなボリュームを数百個作成すると、累積的なオーバーヘッドがノードのパフォーマンスを低下させる可能性があります。可能な限りストレージを統合してください。

ディスクの枯渇を避ける

Longhornは、ディスク容量が90%に達するとレプリカのスケジューリングを停止します。私は設定でStorage Overprovisioning Tolerance(ストレージ・オーバープロビジョニング許容値)を150%に設定しています。これにより一時的な増加は許容されますが、読み取り専用ロックを避けるためにホストのディスク使用率を厳密に監視する必要があります。

メンテナンスモードを使用する

準備なしにノードを再起動してはいけません。まずLonghorn UIを使用して、対象ノードの「Disable Scheduling(スケジューリングの無効化)」を行ってください。これにより、短時間のメンテナンス中にシステムが不必要にレプリカを再構築するのを防ぐことができます。

最後に

耐障害性に優れたストレージは、本格的なKubernetes運用のバックボーンです。特に複数環境にまたがるクラスターのライフサイクル管理を行う際、ローカルボリュームからLonghornへ移行することで、脆弱な環境を回復力のある環境に変えることができました。ノードの故障は今や、午前2時の緊急事態ではなく、単なる小さな出来事に過ぎません。スマートなアラート管理と組み合わせることで、高いパフォーマンスと容易なメンテナンスのバランスが必要なら、Longhornは最も現実的な道と言えるでしょう。

Share: