ブログ

GitOps で数千の Edge Kubernetes クラスターを管理する

F5 サムネイル
F5
2019年12月18日公開

Volterra では、SRE チームの仕事は、グローバルなSaaS ベースのエッジ プラットフォームを運用することです。 私たちは、さまざまな状態 (オンライン、オフライン、管理ダウンなど) にある多数のアプリケーション クラスターを管理する上でさまざまな課題を解決する必要があり、GitOps を使用した宣言型プルベース モデルで Kubernetes エコシステムとツールを活用することでこれを実現します。

このブログでは、次の内容について説明します。

GitOps を使用して、大規模なインフラストラクチャ (物理またはクラウド ホスト) と K8s クラスターを効果的に管理および監視します。

  1. CI/CDに関する問題を解決するために構築したツール
  2. オブジェクトオーケストレーションと構成管理
  3. インフラとK8sクラスタ全体の可観測性

大規模(3000 エッジ サイト)で学んだ教訓について、さらに詳しく掘り下げていきます。これは、サンディエゴで開催された Cloud Native Rejekts での最近の講演でも取り上げられました。

TL;DR (要約)

  1. パブリッククラウド、オンプレミス、またはノマドロケーション全体で数千(場合によっては数百万)のアプリケーションとインフラストラクチャクラスターを展開および運用するために使用できる、シンプルですぐに使用できるソリューションを見つけることができませんでした。
     
  2. このソリューションでは、ホスト (物理またはクラウド)、Kubernetes コントロール プレーン、アプリケーション ワークロード、およびさまざまなサービスの継続的な構成のライフサイクル管理を提供する必要がありました。 さらに、ソリューションは、宣言型定義、不変ライフサイクル、gitops、クラスターへの直接アクセスなしなど、SRE 設計要件を満たす必要がありました。
     
  3. Kubespray+Ansible (Kubernetes デプロイメント用) や Helm/Spinnaker (ワークロード管理用) など、さまざまなオープン ソース プロジェクトを評価した結果、各エッジ サイトで大幅なソフトウェアの肥大化を招くことなく、これらのソリューションのいずれも上記の要件を満たすことはできないという結論に達しました。 その結果、ホスト (物理またはクラウド)、Kubernetes コントロール プレーン、およびアプリケーション ワークロードのライフサイクル管理を実行する独自の Golang ベースのソフトウェア デーモンを構築することにしました。
     
  4. システムを 3000 クラスター以上に拡張すると (単一テナント内)、パブリック クラウド プロバイダー、ソフトウェア デーモンのスケーラビリティ、運用ツール、および可観測性インフラストラクチャに関するすべての想定が体系的に崩壊しました。 これらの課題を克服するには、ソフトウェア コンポーネントの一部を再設計する必要がありました。

エッジの定義

  • カスタマー エッジ (CE) — クラウド内の顧客の場所 (AWS、Azure、GCP、プライベート クラウドなど)、オンプレミスの場所 (工場現場、石油/ガス施設など)、または移動場所 (自動車、ロボットなど) です。 CE は Volterra SRE チームによって管理されますが、顧客が希望する場所にオンデマンドで展開することもできます。
  • リージョナル エッジ (RE) — これらは、主要なメトロ マーケットのコロケーション施設にある Volterra のプレゼンス ポイント (PoP) であり、当社独自の高度にメッシュ化されたプライベート バックボーンによって相互接続されています。 これらの地域エッジ サイトは、顧客エッジ (CE) ロケーションを安全に相互接続したり、アプリケーション サービスをパブリック インターネットに公開したりするためにも使用されます。 RE サイトは、Volterra インフラストラクチャ運用 (Infra SRE) チームによって完全に管理および所有されます。
管理01
図1: システム概要

上記のアーキテクチャ図 (図 1) は、RE と CE 間の論理接続を示しています。各 CE は、最も近い RE への冗長 (IPSec または SSL VPN) 接続を確立します。

エッジ管理の要件

約 2 年前にプラットフォームの設計を開始したとき、製品チームから次の課題を解決するように依頼されました。

  1. システムのスケーラビリティ— お客様は数千 (最終的には数百万) の顧客エッジ サイトをサポートすることを求めており、これはクラウド リージョンで少数の Kubernetes クラスターを実行することとは大きく異なります。 たとえば、当社の顧客の中には約 17,000 軒のコンビニエンス ストアを運営している企業や、20,000 軒を超える充電ステーションを運営している企業があります。 この規模は、少数のクラスターを処理する場合とはまったく異なる方法でツールを構築する必要があることを意味しました。
  2. ゼロタッチデプロイメント- ハードウェア、ソフトウェア、Kubernetes についてあまり理解していなくても、誰でも新しいサイトをデプロイできる必要があります。 エッジ サイトは、電源がオンになり、ホームに電話をかけ、オンラインになるブラックボックスのように動作する必要がありました。
  3. フリート管理— 数千のサイトとワークロードを個別に処理する必要なく、管理を簡素化します。 変更またはアップグレードが要求された時点で、サイトがオフラインになったり、利用できなくなったりする場合があります。 その結果、サイトはオンラインになったときに更新を取得する必要があります。
  4. フォールト トレランス- いずれかのコンポーネントに障害が発生した後でもエッジ サイトは動作し続ける必要があります。 すべてをリモートで管理し、障害発生時に工場出荷時設定へのリセットやサイトの再構築などの機能を提供する必要があります。 現場には物理的なアクセスがないと想定する必要がありました。

設計原則 (Kubectl なし) Ansible はありません! パッケージはありません!

高度に分散されたシステムを運用するための要件と課題を考慮し、下流の問題を軽減するために SRE チームが従う必要のあるいくつかの原則を設定することにしました。

  1. 宣言的定義— システム全体を宣言的に記述する必要があります。これにより、簡単な抽象モデルを作成し、モデルに対して検証を実行できるようになります。
     
  2. 不変のライフサイクル管理— 過去には、Ansible、Salt、Puppet などの変更可能な LCM ツールを使用して、大規模なプライベート クラウドのインストールに取り組んでいました。 今回は、ベース OS を非常にシンプルに保ち、パッケージ管理や構成管理ツールを必要とせずにすべてをコンテナとして出荷しようと考えました。
     
  3. GitOps — Kubernetes クラスターを管理するための標準運用モデルを提供します。 また、追加のワークフロー管理システムを構築することなく、変更の承認、監査、ワークフローをすぐに実行できるようになります。 したがって、すべてを git 経由で行うことを決定しました。
     
  4. kubectl なし— 誰もアプリケーション クラスターに直接アクセスできないため、これは最も重要な原則の 1 つでした。 その結果、個々のエッジ クラスター内で kubectl を実行したり、集中 CD システムなどの中央の場所から実行されるスクリプトを使用したりすることができなくなりました。 プッシュ方式の集中型 CD システムは数十のクラスターには適していますが、100% のネットワーク可用性が保証されない数千のクラスターには適していません。
     
  5. 誇大宣伝のないテクノロジー (またはツール) — 過去の経験から、人気のあるオープンソース ツールの多くは宣伝どおりの成果を上げていないことがわかっています。 インフラストラクチャ、K8、アプリケーション ワークロード (Helm、Spinnaker、Terraform など) を提供するためのいくつかのコミュニティ プロジェクトを評価しましたが、最終的には仮想インフラストラクチャ部分に Terraform のみを使用し、このブログの次の部分で説明するカスタム コードを開発しました。

サイトライフサイクル管理

エッジ サイトのライフサイクル管理の一環として、ホスト OS のプロビジョニング、基本的な構成 (ユーザー管理、証明機関、hugepages など) の実行、K8 の起動、ワークロードのデプロイ、進行中の構成変更の管理の方法を解決する必要がありました。

私たちが検討したが最終的に却下したオプションの 1 つは、KubeSpray + Ansible (OS の管理と K8 のデプロイ) と Helm/Spinnaker (ワークロードのデプロイ) を使用することです。 これを拒否した理由は、エッジ クラスターの自動スケーリング、セキュア TPM モジュールのサポート、差分アップグレードなどの機能を追加するにつれて要件が拡大し続け、2 ~ 3 個のオープン ソース ツールを管理し、要件を満たすために大幅な変更を加える必要があったためです。

私たちの目標はシンプルさを保ち、OS 内 (Kubernetes 外部) で直接実行されるコンポーネントの数を最小限に抑えることだったので、Volterra Platform Manager (VPM) と呼ばれる軽量の Golang デーモンを作成することにしました。 これは OS 内の唯一の systemd Docker コンテナであり、多くの機能を実行するスイスアーミーナイフとして機能します。

ホストライフサイクル

VPM は、インストール、アップグレード、パッチ、構成など、ホスト オペレーティング システムのライフサイクルを管理する役割を担います。 設定が必要な側面は多数あります(例:hugepages の割り当て、/etc/hosts など)

  1. OS アップグレード管理— 残念ながら、エッジは Kubernetes だけに関するものではなく、カーネルと OS のバージョン全般を管理する必要があります。 当社のエッジは、アクティブ パーティションとパッシブ パーティションを備えた CoreOS (または顧客のニーズに応じて CentOS) に基づいています。 アップグレードがスケジュールされると、更新は常にパッシブ パーティションにダウンロードされます。 再起動は更新の最後のステップであり、アクティブ パーティションとパッシブ パーティションが交換されます。 唯一敏感な部分は、すべてのノードを同時に再起動することはできないため、再起動戦略 (マルチノード クラスターの場合) です。 クラスター内のノードが 1 つずつ再起動される独自の etcd 再起動ロック (VPM 内) を実装しました。
  2. OS へのユーザー アクセス管理- ユーザーと、その SSH およびコンソールへのリモート アクセスを制限する必要があります。 VPM は、ssh CA ローテーションなどのすべての操作を実行します。
  3. 独自のL3-L7データパスを開発したため、ハードウェア(またはクラウドVM)の種類に応じてホストOSに2Mまたは1Gの巨大ページを構成する必要があります。

Kubernetes ライフサイクル

Kubernetes マニフェストのライフサイクルを提供する管理。 Helm を使用する代わりに、K8s client-go ライブラリを使用することを決定し、これを VPM に統合して、このライブラリのいくつかの機能を使用しました。

  1. 楽観的デプロイメントと悲観的デプロイメント— この機能を使用すると、正常になるまで待機する必要があるアプリケーションを分類できます。 これは、K8s マニフェストves.io/deploy: optimisticのアノテーションを監視するだけです。

    楽観的= リソースを作成し、ステータスを待機しません。 これは、実際のポッドが正常に起動したかどうかがわからないkubernetes applyコマンドと非常によく似ています。

    悲観的= Kubernetes リソースの状態を待機します。 たとえば、デプロイメントはすべてのポッドの準備が整うまで待機します。 これは新しいkubectl waitコマンドに似ています。

  2. 事前プルなどの更新前アクション— 特にネットワーク データ プレーンが出荷されている場合、K8s のローリング更新に依存できない場合があります。 その理由は、古いポッドが破棄され、新しいポッドが取り外されるからです。 ただし、データ プレーンの場合は、ネットワーク接続が失われます。 したがって、新しいコンテナ イメージをプルできず、ポッドは起動しません。 イメージのリストを含むメタデータ注釈 ves.io/prepull は、K8s マニフェストが適用される前にプル アクションをトリガーします。
  3. 適用に失敗した場合の再試行とロールバック。 これは、K8s API サーバーが断続的に停止した場合によく発生する状況です。

進行中の構成

K8s マニフェストに関連する構成に加えて、API を介してさまざまな Volterra サービスを構成する必要もあります。 一例として、IPsec/SSL VPN 構成が挙げられます。VPM はグローバル コントロール プレーンから構成を受信し、個々のノードにプログラムします。

工場出荷時設定にリセット

この機能を使用すると、ボックスをリモートで元の状態にリセットし、インストールと登録のプロセス全体を再度実行できます。 これは、コンソール/物理アクセスを必要とするサイトを回復するための非常に重要な機能です。

K8s ライフサイクル管理は多くの人にとって大きな議論のテーマのように見えるかもしれませんが、私たちのチームにとっては、全体の作業量の 40~50% 程度でしょう。

ゼロタッチプロビジョニング

あらゆる場所 (クラウド、オンプレミス、またはノマディック エッジ) でのエッジ サイトのゼロタッチ プロビジョニングは重要な機能です。個々のサイトにアクセスすることは期待できず、個々のサイトのインストールと管理に多くの Kubernetes エキスパートを配置することも望んでいないためです。 数千にまで拡張できないだけです。

次の図 (図 2) は、新しいサイトの登録プロセスに VPM がどのように関与するかを示しています。

管理02
図2 — ゼロタッチプロビジョニングフロー
  1. 電源がオンになると、CE 上で実行されている VPM (緑色のボックスで表示) は、新しい登録を作成するためにグローバル コントロール プレーン (GC) に登録トークンを提示します。 登録トークンは、クラウド VM の cloud-init の一部として提供され、ブート プロセス中に人間が入力したキー、またはエッジ ハードウェアの TPM にプログラムされたキーである場合があります。
  2. GC はトークン付きのリクエストを受信し、これによりテナント (トークンにエンコードされている) の下に新しい登録を作成できます。 顧客オペレーターは、マップ上で新しいエッジ サイトをすぐに確認し、名前やその他の構成パラメータを入力して承認することができます。
  3. GC 内の VP コントローラは、etcd、K8s、VPM の構成 (例: K8s マスター、ミニオンなどの決定) と証明書を生成します。
  4. VPM は、Docker イメージのダウンロード、HugePages の構成、K8s クラスターのインストール、Volterra コントロール プレーン サービスの開始など、サイトのブートストラップを開始します。
  5. VPM は、サイト間およびパブリック ネットワーク間のデータ トラフィックと相互接続に使用される最も近い 2 つの地域エッジ サイトへの冗長トンネル (IPSec/SSL VPN) を構成します。

ご覧のとおり、プロセス全体は完全に自動化されており、ユーザーは詳細な構成について何も知る必要はなく、手動の手順を実行する必要もありません。 デバイス全体をオンライン状態にして、顧客のアプリやリクエストに対応できるようになるまでに約 5 分かかります。

インフラストラクチャソフトウェアのアップグレード

アップグレードは、私たちが解決しなければならなかった最も複雑なことの 1 つです。 エッジサイトでアップグレードされるものを定義しましょう。 

  • オペレーティング システムのアップグレード- カーネルとすべてのシステム パッケージが対象となります。 標準的な Linux OS ディストリビューションを運用したことがある人なら、マイナー バージョン間でのアップグレード (例: Ubuntu 16.04.x から 16.04.y への移行) の苦労や、メジャー バージョン間でのアップグレード (例: Ubuntu 16.04 から 18.04 への移行) のさらに大きな苦労を知っています。 数千のサイトの場合、アップグレードは決定論的である必要があり、サイト間で異なる動作をすることはできません。 そのため、2 つのパーティションとパス上の読み取り専用ファイル システムを使用して A/B アップグレードを実行できる CoreOS と CentOS Atomic を選択しました。 これにより、ブート順序パーティションを切り替えることですぐに元に戻すことができ、OS パッケージをメンテナンスせずに OS の一貫性を保つことができます。 ただし、新しいパッケージをインストールするだけでは、システム内の個々のコンポーネント (たとえば、openssh サーバー) をアップグレードすることはできなくなりました。 個々のコンポーネントへの変更は、新しい不変の OS バージョンとしてリリースする必要があります。
     
  • ソフトウェア アップグレード- これには、K8s ワークロードとして実行される VPM、etcd、Kubernetes、および Volterra 制御サービスが含まれます。 すでに述べたように、私たちの目標は、K8s 内のすべてを systemd コンテナとして実行することです。 幸運なことに、次の 3 つのサービスを除いてすべてを K8s ワークロードとして変換できました。 VPM、etcd、kubelet。

エッジ サイトに更新を配信するために使用できる既知の方法は 2 つあります。 

  1. プッシュベース- プッシュ方式は通常、Spinnaker、Jenkins、Ansible ベースの CM などの集中型 CD (継続的デリバリー) ツールによって実行されます。 この場合、中央ツールはターゲット サイトまたはクラスターにアクセスできる必要があり、アクションを実行できる必要があります。
  2. プルベース- プルベースの方法では、集中型の配信メカニズムを使用せずにアップグレード情報を独立して取得します。 拡張性が向上し、すべてのサイトの資格情報を 1 か所に保存する必要がなくなります。

アップグレードの目標は、標準的な携帯電話のアップグレードと同様に、シンプルさと信頼性を最大限に高めることでした。 さらに、アップグレード戦略が満たさなければならない他の考慮事項もあります。たとえば、アップグレードのコンテキストはサイトの運営者のみにある場合や、接続の問題などによりデバイスがオフラインまたはしばらく使用できない場合があります。 これらの要件はプル方式でより簡単に満たすことができるため、ニーズを満たすためにプル方式を採用することにしました。

ギットオプス

さらに、Kubernetes クラスター、ワークフロー、監査の変更を管理するための標準運用モデルを SRE チームに提供しやすくするため、GitOps を選択しました。

何千ものサイトのスケーリング問題を解決するために、図 3 に示す SRE のアーキテクチャを考案しました。

管理03
図3 — GitOpsフロー

まず、Git は状態やマニフェストを保存するためだけに使用しているのではないことを強調しておきます。 その理由は、当社のプラットフォームでは K8s マニフェストだけでなく、進行中の API 構成、K8s バージョンなども処理する必要があるためです。 私たちの場合、K8s マニフェストは宣言型構成全体の約 60% を占めます。 このため、git に保存される独自の DSL 抽象化をその上に作成する必要がありました。 また、git は API やパラメータのマージ機能を提供していないため、SRE 用に追加の Golang デーモンを開発する必要がありました。 Config API、Executor、VP コントローラー。

当社の SaaS プラットフォームを使用して、顧客エッジで新しいソフトウェア バージョンをリリースするワークフローを見てみましょう。 

  1. オペレーターは新しいバージョンをリリースすることを決定し、gitモデルに対してマージリクエスト(MR)を開きます。
     
  2. この MR が承認され、マージされると、CI は git モデル構成を SRE Config-API デーモンにロードするアクションをトリガーします。 このデーモンには、パラメータのマージ、内部 DNS 構成などのための API がいくつかあります。
     
  3. Config-API は Executor デーモンによって監視され、git の変更が読み込まれるとすぐに、アノテーションにバージョンが含まれた最終的な K8s マニフェストのレンダリングを開始します。 これらのマニフェストは、パスce01-site// .ymlの下のArtifactストレージ(S3のような)にアップロードされます。
     
  4. 新しいバージョンがレンダリングされ、アーティファクトストレージにアップロードされると、Executorは顧客APIに利用可能なバージョンを含む新しいステータスを生成します。これは、携帯電話で利用可能な新しいバージョンと非常によく似ています。
     
  5. 顧客 (またはオペレーター) は、自分のサイトを最新バージョンに更新するスケジュールを設定でき、この情報は VP-Controller に渡されます。 VP-Controller は、プロビジョニング、廃止、または別の場所への移行を含むサイト管理を担当するデーモンです。 これはゼロタッチプロビジョニングですでに部分的に説明されており、mTLS APIを介してエッジサイトを更新する役割を担っています。
     
  6. 図の最後のステップはエッジサイトで行われます。IPSec/SSL VPN接続が確立されると、VP-ControllerはエッジのVPMに新しいバージョンの更新をダウンロードするように通知します。ただし、接続が切断されたり断続的に問題が発生したりした場合は、VPMは5分ごとに更新をポーリングします。
     
  7. 新しい K8s マニフェストと構成が取得され、K8s にデプロイされます。 前のセクションで説明した悲観的なデプロイメントの機能を使用して、VPMはすべてのポッドが準備完了するまで待機します。
     
  8. 最後のステップとして、VPM はアップグレードのステータスを VP コントローラに送り返し、それがステータスとして顧客 API にプッシュされます。

ワークフロー全体のデモはここでご覧いただけます:

3000 のエッジ サイトのテストから学んだ教訓

前のセクションでは、ツールを使用してエッジ サイトのライフサイクルを展開および管理する方法について説明しました。 設計を検証するために、3,000の顧客エッジサイトを備えた大規模な環境を構築することにしました(図4を参照)。

管理04
図4 — 3000の顧客エッジサイト

私たちは、スケールをシミュレートするために、Terraform を使用して、AWS、Azure、Google、および自社のオンプレミスのベアメタル クラウドにわたって 3000 台の VM をプロビジョニングしました。 これらの VM はすべて独立した CE (顧客エッジ サイト) であり、地域のエッジ サイト (PoP) への冗長トンネルを確立していました。

以下のスクリーンショットは SRE ダッシュボードからのもので、円のサイズで表される場所のエッジ番号を示しています。 スクリーンショットを撮った時点では、正常なエッジ サイトが約 2711 個、異常なエッジ サイトが 356 個ありました。

管理05
図 5–3000 カスタマー エッジ サイトの展開

主な調査結果: オペレーション

スケーリングの一環として、構成と運用面でいくつかの問題が見つかり、ソフトウェア デーモンに変更を加える必要がありました。 さらに、クラウド プロバイダーでは、API 応答の遅延、単一リージョンで 500 台を超える VM を取得できないなど、複数のサポート チケットを開くことになる多くの問題が発生しました。 

  1. VP-Controller を最適化します。当初は、etcd、kubernetes、VPM のさまざまな証明書を作成する必要があったため、登録を順番に処理し、それぞれに約 2 分かかりました。 今回は、より高いエントロピーを使用してキーを事前に生成し、より多くのワーカーで並列化することで最適化しました。 これにより、100 サイトの登録を 20 秒以内に処理できるようになりました。 VP コントローラで約 1 つの vCPU と 2 GB の RAM を消費するだけで、3000 のエッジ サイトすべてに対応できました。
     
  2. Docker イメージ配信の最適化— スケーリングを開始したとき、エッジ サイトで送信されるデータの量が膨大であることに気付きました。 各エッジは約 600 MB (3000 倍) をダウンロードしたため、合計 1.8 TB のデータが送信されました。 また、テスト中にエッジ サイトを何度も再構築していたため、その数は実際にはさらに多くなります。 その結果、ダウンロードを減らすために、Docker イメージのサイズを最適化し、事前にプルされた Docker イメージを使用してクラウド イメージと ISO イメージを構築する必要がありました。 当社はまだパブリック クラウド コンテナ レジストリ サービスを使用していますが、コンテナ レジストリを RE (PoP) を通じて配布し、増分 (バイナリ差分) アップグレードを実行する設計に積極的に取り組んでいます。
     
  3. グローバル制御データベース操作を最適化— 当社のすべての Volterra 制御サービスは、ETCD をデータベースとして使用する Golang サービス フレームワークに基づいています。 すべてのサイトは構成オブジェクトとして表されます。 各サイト構成オブジェクトには、software-upgrade、hardware-info、ipsec-status などの StatusObjects がいくつかあります。 これらの StatusObjects はさまざまなプラットフォーム コンポーネントによって生成され、すべてグローバル構成 API で参照されます。サイト数が 3,000 に達したとき、オブジェクト スキーマで特定の最適化を行う必要がありました。 たとえば、グローバル構成 API で受け入れられる StatusObjects タイプの数を制限したり、構成オブジェクト DB の過負荷のリスクを軽減するために、それらを専用の ETCD インスタンスに移動したりします。 これにより、構成データベースの可用性と応答時間が向上し、障害が発生した場合にステータス DB を再構築することも可能になります。 最適化のもう 1 つの例としては、すべてのテナントにわたって不要なサイト オブジェクト リスト操作の実行を停止したり、セカンダリ インデックスを導入してデータベースの負荷を軽減したりすることが挙げられます。

主な調査結果: 可観測性

分散システム全体の可観測性は、システムの規模が拡大するにつれて、はるかに大きな課題をもたらしました。

当初、メトリクスについては、Prometheus フェデレーションから始めました。これは、グローバル制御の中央 Prometheus が地域エッジ (RE) の Promethei をフェデレーションし、サービス メトリクスをスクレイピングして、接続された CE からメトリクスをフェデレーションするものです。 最上位レベルの Prometheus はアラートを評価し、さらなる分析のためのメトリック ソースとして機能しました。 このアプローチはすぐに限界に達し(約 1000 CE)、CE 数の増加による影響を最小限に抑えようとしました。 ヒストグラムやその他の高カーディナリティ メトリックの事前計算済みシリーズを生成し始めました。 これにより、1、2 日の節約ができましたが、その後はメトリックのホワイトリストを採用する必要がありました。 最終的に、各 CE サイトの時系列メトリックの数を約 60,000 から 2000 に削減することができました。

最終的に、3,000 を超える CE サイトへの拡張を継続し、本番環境で何日も実行した後、これは拡張可能ではないことが明らかになり、監視インフラストラクチャを再考する必要がありました。 私たちは、トップレベルの Prometheus (グローバル制御) を削除し、各 RE の Prometheus を 2 つの個別のインスタンスに分割することにしました。 1 つはローカル サービス メトリックのスクレイピングを担当し、もう 1 つは CE メトリックのフェデレーションを担当します。 どちらもアラートを生成し、メトリックを Cortex の中央ストレージにプッシュします。 Cortex は分析および視覚化ソースとして使用され、コア監視アラート フローの一部ではありません。 私たちは、Thanos と M3db といういくつかの集中型メトリクス ソリューションをテストし、Cortex が私たちのニーズに最も適していることを発見しました。

管理06
図6 — メトリック収集アーキテクチャ

次のスクリーンショット (図 7) は、3000 エンドポイントの時点での prometheus-cef のスクレイピングによるメモリ消費量を示しています。 興味深いのは、消費される RAM が 29.7 GB であることです。これは、システムの規模を考えると、実際にはそれほど多くはありません。 スクレイピングを複数に分割したり、Cortex へのリモート書き込みをエッジ自体に直接移動したりすることで、さらに最適化できます。

管理07
図7 — REサイトでの資源利用

次のスクリーンショット (図 8) は、この規模で Cortex インジェスター (最大 19 GB RAM) とディストリビューターに必要なメモリと CPU リソースの量を示しています。 Cortex の最大の利点は水平スケーリングです。これにより、垂直スケーリングが必要な Prometheus と比較して、より多くのレプリカを追加できます。

管理08
図8 — グローバル制御におけるリソース使用率

CE および RE のログ記録インフラストラクチャでは、ノードごとに Fluentbit サービスを使用して、サービスおよびシステム ログ イベントを収集し、接続された RE の Fluentd に転送します。 Fluentd は、RE にある ElasticSearch にデータを転送します。 ElasticSearch からのデータは Elastalert によって評価され、Alertmanager アラートを作成するためのルールが設定されます。 私たちは、Elastalert から Alertmananger へのカスタム統合を使用して、Prometheus が生成するものと同じラベルのアラートを生成しています。

監視の旅の重要なポイント:

  • 新しい Prometheus フェデレーション フィルターを使用して未使用のメトリックやラベルを削除する

    - 当初はCEあたり約50,000の時系列があり、平均15のラベルがありました。

    - 平均してCEあたり2000に最適化しました

    メトリック名にはシンプルな while リスト、ラベル名にはブラックリスト

  • グローバル Prometheus フェデレーションから Cortex クラスタへの移行

    - 集中型PrometheusはすべてのREとCEのPrometheusをスクレイピングしました

    - 西暦1000年には、指標の量を管理することが不可能になった。

    - 現在、各REにPrometheus(接続されたCEのPrometheiと連携)があり、RWはCortexに接続されています。

  • Elasticsearch クラスターとログ

    - 分散ログアーキテクチャ

    - 各ノードのコレクターであるFluentbitは、REのFluentd(アグリゲータ)にログを転送します。

    - ElasticSearch は、リモート クラスター検索を使用してすべての RE にデプロイされ、単一の Kibana インスタンスからログを照会します。

まとめ

このブログが、世界中に展開されている何千ものエッジ サイトとクラスターを管理するために考慮すべきすべての事項についての洞察を与えてくれることを願っています。 当初の設計要件のほとんどを満たし、検証することができましたが、まだ改善すべき点はたくさんあります…