Kubernetesは通常、クラウドプロバイダーから借りて使うもので、コントロールプレーン、ロードバランサー、ストレージクラスがあらかじめ構成されています。専用サーバーで運用すると、この前提が変わります。APIより下のすべてのレイヤーと、これまでプロバイダーが代わりに下していたすべての判断を、自社で担うことになります。
本ガイドでは、企業がベアメタルでクラスターを運用する理由、コントロールプレーン、ロードバランシング、ストレージ、アップグレード、オブザーバビリティの構成方法、そして労力に見合わないケースを解説します。
専用サーバーでKubernetesを運用する理由
1つ目の理由は仮想化レイヤーを介さない性能です。ベアメタルノード上のPodは、ハイパーバイザーによるスケジューリングも、同じホスト上のノイジーネイバーもなく、CPU、メモリ、NVMeドライブを直接使用します。データベース、ビルドファーム、データ処理ジョブでは、その効果はピーク性能の向上よりも、テールレイテンシの低下とスループットの安定として表れます。
専用サーバーは既知の構成に対して毎月固定の金額ですが、クラウドのクラスターはノード時間、ロードバランサー、保存容量のギガバイト、送信データのギガバイトごとに課金されます。1 Gbpsのポートをフル稼働させると1日あたりおよそ10 TBを転送しますが、転送量無制限のポートであれば、そのトラフィックで請求額が変わることはありません。
カーネル、CPUの世代、ディスク構成、各ノードを置く国を自ら選べます。これはデータレジデンシーや、物理コア数に紐づくライセンスにとって重要です。
コントロールプレーンの構成
コントロールプレーンは、APIサーバー、スケジューラー、コントローラーマネージャー、etcdで構成されます。ベアメタルではこれらを自社で運用するため、その配置がマシン障害時のクラスターの挙動を決めます。
etcdはコンセンサスプロトコルを使用しており、書き込みを受け付けるにはメンバーの過半数が必要です。3メンバーなら1つ、5メンバーなら2つの喪失に耐えられます。ほとんどの本番クラスターでは、3台のコントロールプレーンノードが適切な出発点です。
- スタック型etcd。etcdをAPIサーバーと同じ3台のノードで稼働させます。これは一般的なデフォルト構成で、必要なマシンが少なく、kubeadmや多くのディストリビューションで十分にサポートされています。
- 外部etcd。etcdを専用のノードで稼働させます。データストアをAPIの負荷から分離し、非常に大規模なクラスタのキャパシティプランニングを簡素化できますが、運用するサーバーは増えます。
- 専用のコントロールプレーンノード。taintを使ってアプリケーションのPodをコントロールプレーンから排除します。暴走したワークロードがetcdのディスクやメモリを奪うことがあってはなりません。
- etcd用の高速なローカルディスク。etcdはすべての変更をディスクに同期するため、書き込みレイテンシの影響を受けやすいソフトウェアです。ローカルNVMeが適しています。低速なディスクや共有ディスクは、リーダー選出やAPIのタイムアウトのよくある原因です。
- 安定したAPIエンドポイント。ワーカーとクライアントには、APIサーバーへの単一のアドレスが必要です。ベアメタルでは通常、keepalivedやkube-vipなどのツールが提供し、コントロールプレーンノード間を移動する仮想IP、またはノードの前段に置いた一対のロードバランサーで実現します。
施設が許す限り、3台のコントロールプレーンノードは異なるラック、少なくとも異なる電源系統に配置します。
ネットワーク:ロードバランサー、BGP、MetalLB
クラウドでは、type LoadBalancerのServiceがプロバイダーのAPIを呼び出し、外部IPを取得します。ベアメタルではその呼び出しに応答するものがなく、応答する仕組みをインストールするまでServiceはpendingのままになります。
MetalLBは広く使われているオープンソースの解決策です。LoadBalancer型のServiceを監視し、定義したプールからIPを割り当て、そのIPにネットワークから到達できるようにします。大きく分けて2つのモードで動作します。
- レイヤー2モード。1つのノードがサービスIPに対するARP(IPv6ではNDP)に応答し、そのIP宛てのトラフィックはそのノードに流れます。ルーターの設定は不要で、単純なフラットネットワークで動作します。その代わり、1つのサービスのトラフィックは常に単一のノードから入り、フェイルオーバーはクライアントとスイッチが変更を認識できるかどうかに左右されます。
- BGPモード。ノードは上流ルーターとBGPセッションを確立し、サービスIPを経路として広告します。ルーターは等コストマルチパス(ECMP)によって複数のノードにトラフィックを分散でき、フェイルオーバーは通常のルーティング収束に従います。ノードからのBGPを受け入れるルーターと、ネットワーク運用者との調整が必要です。
CNIプラグインの中には、サービスのルートをBGPで直接アナウンスできるものもあり、コンポーネントを1つ減らせます。
PodとServiceのCIDRは、将来の拡張を見込んでサイジングします。後から変更するには、通常クラスターの再構築が必要になるためです。HTTPトラフィックには、ロードバランサーのIPの背後にingressコントローラーまたはゲートウェイを置き、パブリックアドレスの前段には上流のDDoS対策を維持します。
ストレージ:ローカルNVMe、CSI、レプリケーションストレージ
ストレージは、ベアメタルクラスターが最も大きな性能向上を得る領域であり、同時に最も大きなリスクを抱える領域でもあります。KubernetesはContainer Storage Interface(CSI)を通じてストレージとやり取りし、選んだドライバーによって、ノード障害時にデータがどうなるかが決まります。
- ローカルNVMeボリューム。ローカルの永続ボリュームは、Podを特定のノード上のディスクに結び付けます。レイテンシとスループットは最高の水準です。Podはそのデータを失わずに別のノードへ移動できないため、分散データベース、検索クラスタ、独自のレプリケーションを持つメッセージキューなど、アプリケーション層でレプリケーションを行うワークロードに適しています。
- レプリケーション型のソフトウェア定義ストレージ。Ceph(多くの場合Rook経由で運用)、Longhorn、または同様のCSIベースの基盤は、各ボリュームを複数のノードにコピーします。Podは別の場所で再起動してボリュームを再接続できます。その代償として、書き込みのたびに追加のネットワークトラフィックが発生し、追加のディスク容量が必要になり(3つのコピーで物理使用量は3倍)、独自の運用ノウハウを要するストレージシステムを抱えることになります。
- ネットワークブロックストレージ。独立したストレージ基盤がネットワーク経由で提供するボリュームです。状態をコンピュートノードの外に置けるため、ノードの交換が容易になり、コンピュートとは独立して容量を拡張できます。
多くの本番クラスターではこれらを組み合わせています。組み込みのレプリケーション機能を持つデータベースはローカルNVMeに、その他のステートフルサービスはレプリケートされたストレージやネットワークストレージに置きます。
etcdと永続ボリュームは別々にバックアップします。etcdのスナップショットはクラスタのオブジェクトを復元しますが、ボリューム内のデータは復元しません。Veleroなどのツールはリソースとボリュームのスナップショットの両方を取得できます。リストア手順は一度書いて忘れるのではなく、定期的にリハーサルする必要があります。
アップグレードとノードのライフサイクル
Kubernetesはおおむね年3回マイナーバージョンをリリースし、各マイナーバージョンには約14か月間パッチが提供されます。アップグレードしないクラスターは、約1年半でサポート対象外になります。ベアメタルでは、誰も代わりにアップグレードしてくれません。
アップグレードは1マイナーバージョンずつ、コントロールプレーン、ワーカーの順に進めます。予測可能な手順は次のとおりです。
- アップグレード前に、削除されるAPIとマニフェストおよびHelmチャートを照合します。
- etcdのスナップショットを取得し、復元できることを確認します。
- コントロールプレーンノードを1台ずつ更新し、毎回APIを確認。
- 各ワーカーをcordonしてdrainし、kubeletとコンテナランタイムをアップグレードしてから、uncordonします。PodDisruptionBudgetを使い、drainによってサービスのすべてのレプリカが停止することがないようにします。
- ホストOSとファームウェアも同じ周期でパッチを適用します。パッチ未適用のカーネル上では、最新のKubernetesでも脆弱です。
多くのチームはノードを修理するのではなく置き換えます。既知のイメージから再インストールし、クラスターに参加させ、古いマシンを取り外します。ドレインによってクラスターの容量が不足しないよう、プールごとに少なくとも1台の予備ノードを確保してください。
オブザーバビリティ
ベアメタルでは、クラウドが隠すハードウェアの兆候も監視。
- メトリクス。node exporterとkube-state-metricsを備えたPrometheusが一般的な基本構成です。各サーバーのSMARTとNVMeの摩耗データ、温度、電源ユニットの状態、NICのエラーも追加します。
- ログ。コンテナ、kubelet、システムのログをノードの外にある集中ストアへ送ります。障害が発生したノードは、ローカルのログも道連れにします。
- コントロールプレーンの健全性。etcdのリーダー交代、fsyncのレイテンシ、データベースのサイズ、APIサーバーのエラー率に対してアラートを設定します。これらはクラスタの不調を示す最も早い兆候です。
- キャパシティ。ノードプールごとに、CPUとメモリの要求量と実使用量を追跡します。ベアメタルのキャパシティはサーバー単位で追加されるため、クラスタのリソースが尽きる前のリードタイムが必要です。
監視スタックは監視対象のクラスターの外部に置くか、少なくともアラートを外部システムに複製してください。クォーラムを失ったクラスターは、クォーラムを失ったことを通知できません。
労力に見合わないケース
ベアメタルのKubernetesは、Linuxの運用に十分慣れたチームが運用する、安定した高トラフィックで性能に敏感なワークロードに適しています。次のような場合には適していません。
- 小規模なワークロードや変動の激しいワークロード。クラスタが2〜3台の小さなノードで足りる場合や、トラフィックが1日のうちに1桁変動する場合は、通常、マネージドクラウドのキャパシティのほうが安価でシンプルです。
- プラットフォームチームがいない場合。etcd、アップグレード、ストレージ、オンコールには担当者が必要です。それが誰の仕事でもなければ、クラスタはいずれサポート対象外の状態に陥ります。
- マネージドサービスへの依存度が高い場合。アプリケーションがプロバイダーのキュー、データベース、アイデンティティサービスに依存している場合、コンピュートだけを移しても、大きなコスト削減にはならないまま、レイテンシと複雑さが増します。
- Kubernetesを必要としないワークロード。少数のサーバー上の少数のサービスであれば、コンテナと構成管理ツールで十分に運用できます。Kubernetesが真価を発揮するのは、多数のサービスと頻繁なデプロイがある場合です。
ベアメタルクラスタのチェックリスト
- コントロールプレーンノード3台または5台をラックか電源系統で分離し、etcdはローカルNVMeに。
- APIエンドポイント用の仮想IPまたは一対のロードバランサー。
- 自動化され、テスト済みのetcdスナップショットがクラスタ外に保存されていること。
- MetalLBまたはBGP対応CNI、合意済みIPプールとルーターフィルター。
- 将来の拡張を見込んでサイジングし、文書化したPodとServiceのCIDR。
- ワークロード別にストレージクラスを定義し、各々でノード障害を試験。
- ボリュームを別拠点のオブジェクトストレージへバックアップ。復元はリハーサル済み。
- アップグレード手順書、重要なPodへのPodDisruptionBudgets、定期的なOSとファームウェアのパッチ適用。
- ハードウェア、クラスター、コントロールプレーンの指標。アラートはクラスター外へ。
- プールごとに少なくとも1ノードの予備容量。
- リモートコンソールと文書化されたノード交換手順。
- パブリックサービスIPの前段に配置した上流のDDoS対策。
Vonahostがお手伝いできること
Vonahostは、ここで説明した構成に適合するAMD EPYC(第4世代・第5世代)搭載のシングルテナント専用サーバーを提供します。etcdやレイテンシに敏感なボリューム向けのローカルNVMe(2 x 960 GB)、またはステートフルなワークロード向けの最大1 PBのネットワークブロックストレージ、100/200 Gbpsのネットワークファブリック上の転送量無制限の1 Gbps専用ポート、パブリックアドレスの前段に配置するArborのDDoS対策を備えています。サーバーはAlmaLinuxまたはUbuntuで数分でプロビジョニングされ、お客様が選択したリージョンに展開されるため、ノードのライフサイクルにおいて修理ではなく交換するアプローチを実践できます。
すべての提案書には、構成、ロケーション、責任範囲、米ドル建ての月額料金が明記されるため、クラスタのどの部分をお客様が運用し、どの部分を当社が運用するのかが分かります。各サーバーの国はお客様が選択し、データがお客様の承認なしに移動されることはありません。