1. K8s を使用する理由
1. リソースの分離
現在の Redis クラスターは物理マシン クラスターにデプロイされています。リソース使用率を向上させ、コストを節約するために、複数のビジネスラインの Redis クラスターが混在しています。 CPU リソースの分離がないため、Redis ノードの CPU 使用率が高すぎることがよくあり、他の Redis クラスター ノードが CPU リソースをめぐって競合し、遅延ジッターが発生します。異なるクラスターが混在しているため、このような問題を迅速に特定することが難しく、運用と保守の効率に影響を与えます。 K8s のコンテナ化された展開では、CPU リクエストと CPU 制限を指定できるため、リソースの競合を回避しながらリソースの使用率が向上します。
2. 自動デプロイメント
物理マシン上での Redis Cluster の現在のデプロイメント プロセスは非常に煩雑であり、メタ情報データベースをチェックして、次のようなマシンを見つける必要があります。無料のリソースがあり、多くの手動変更が必要です。その後、構成ファイルが 1 つずつデプロイされ、最後に redis_trib ツールを使用してクラスターが作成されます。新しいクラスターの初期化には、多くの場合 1 ~ 2 時間かかります。
K8s は、StatefulSet を通じて Redis クラスターをデプロイし、configmap を使用して構成ファイルを管理します。新しいクラスターのデプロイには数分しかかからず、運用とメンテナンスの効率が大幅に向上します。
2. K8s
クライアントは LVS の VIP を通じて統合され、Redis プロキシを通じてサービス リクエストを Redis Cluster クラスターに転送します。ここでは、リクエストを転送するための Redis プロキシを紹介します。
1. Redis Cluster のデプロイ方法
Redis は StatefulSet としてデプロイされ、ステートフル サービスとして選択するのが最も合理的です。 StatefulSet: ノードの RDB/AOF を分散ストレージに永続化します。ノードが再起動して他のマシンに移動すると、マウントされた PVC (Persistent VolumeClaim) を介して元の RDB/AOF を取得してデータを同期できます。
Ceph ブロック サービスは、私たちが選択した永続ストレージ PV (Persistent Volume) です。 Ceph の読み取りおよび書き込みパフォーマンスはローカル ハードディスクよりも劣るため、読み取りおよび書き込みの遅延が 100 ~ 200 ミリ秒増加します。 Redis の RDB/AOF 書き込みは非同期であるため、分散ストレージの読み取りおよび書き込みの遅延はサービスに影響しません。
#2. プロキシの選択
オープン ソースの Redis プロキシは数多くありますが、一般的なオープン ソースの Redis プロキシは次のとおりです。
私たちは、引き続き Redis クラスターを使用して Redis クラスターを管理したいと考えているため、Codis と Twemproxy は考慮されなくなりました。 redis-cluster-proxy は、Redis Cluster プロトコルをサポートする Redis バージョン 6.0 で正式に開始された Proxy ですが、現時点では安定したバージョンがなく、当面は大規模に適用できません。
唯一の選択肢は Cerberus と Predixy です。以下は、K8s 環境で実施した Cerberus と Predixy のパフォーマンス テスト結果です。
テスト環境
テスト ツール: redis-benchmark
プロキシ CPU: 2 コア
クライアント CPU: 2 コア
Redis クラスター: 3 つのマスター ノード、ノードごとに 1 つの CPU
テスト結果
##Predixy は、同じワークロードと構成の下でより高い QPS を達成でき、レイテンシも Cerberus に非常に近いです。全体として、Predixy は Cerberus よりも 33% ~ 60% パフォーマンスが高く、データのキー/値が大きいほど Predixy の利点が明確になるため、最終的に Predixy を選択しました。 ビジネス環境と K8s 環境に適応するために、オンラインにする前に Predixy に多くの変更を加え、バックエンド Redis クラスターの動的切り替え、ブラック リストとホワイト リスト、異常動作監査など3. プロキシの導入方法
ステートレスかつ軽量な導入特性により、ロード バランシング (LB) を通じてサービスを提供する導入方法としてプロキシ (Proxy) が使用されます。 ) 、動的な拡張と収縮を簡単に実現できます。同時に、オンラインでRedis Clusterを追加・切り替えできる、バックエンドのRedis Cluster for Proxyを動的に切り替える機能を開発しました。4. Proxy の自動拡張・縮小方法
K8s のネイティブ HPA (horizontal Pod Autoscaler) を使用して、Proxy の動的な拡張・縮小を実現します。すべてのプロキシ ポッドの平均 CPU 使用率が特定のしきい値を超えると、拡張が自動的にトリガーされます。HPA はプロキシのレプリカ数を 1 増やします。その後、LVS は新しいプロキシ ポッドを検出し、トラフィックの一部を遮断します。 CPU 使用率が指定されたしきい値を超えると、容量が拡張されますが、それでも CPU 使用率が要件を満たさない場合は、拡張ロジックが引き続きトリガーされます。ただし、拡張が成功してから 5 分以内は、CPU 使用率がどれほど低下しても、縮小ロジックはトリガーされないため、頻繁な拡張と縮小がクラスターの安定性に与える影響は回避されます。 HPA では、クラスター内のポッドの最小数 (MINPODS) と最大数 (MAXPODS) を構成できます。クラスターの負荷がどれほど低くても、MINPODS を下回るポッド数にはスケールダウンされません。 MINPODS と MAXPODS の値は、お客様が実際のビジネス状況を判断して決定することをお勧めします。3. プロキシを使用する理由
1. Redis ポッドを再起動すると IP が変更される可能性があります
Redis クラスターを使用する Redis クライアントは、クライアントの再起動時に Redis クラスターへの入り口を見つけるためにクラスターの IP とポートを構成する必要があります。物理マシンクラスターにデプロイされた Redis ノードの場合、インスタンスが再起動されたりマシンが再起動されたりしても、IP とポートは変更されず、クライアントは引き続き Redis クラスターのトポロジを見つけることができます。ただし、K8s にデプロイされた Redis クラスターの場合、(元の K8s ノードで再起動された場合でも) ポッドの再起動時に IP が変更されないことが保証されないため、クライアントの再起動時に、ポッドが見つからない可能性があります。 Redis クラスターへの入り口。
クライアントと Redis クラスターの間にプロキシを追加することで、Redis クラスターの情報がクライアントから保護されます。プロキシは、Redis クラスターのトポロジの変更を動的に感知できます。クライアントは、IP:ポートを変更するだけで済みます。 LVS: エントリ ポイントとして、リクエストはプロキシに転送されます。つまり、Redis スマート クライアントを必要とせずに、Redis Cluster クラスターを Redis のスタンドアロン バージョンのように使用できます。
2. Redis は高い接続負荷を処理します
バージョン 6.0 より前は、Redis はほとんどのタスクを単一スレッドで処理していました。 Redis ノードへの接続が多い場合、Redis はこれらの接続を処理するために大量の CPU リソースを消費する必要があり、その結果、遅延が増加します。プロキシを使用すると、プロキシ上に多数の接続が存在し、プロキシと Redis インスタンス間で維持される接続はわずかになるため、Redis の負荷が軽減され、接続の増加による Redis レイテンシの増加が回避されます。
3. クラスターの移行と切り替えにはアプリケーションの再起動が必要です
使用中、ビジネスの成長に伴い、Redis クラスターのデータ量は増加し続けます。データ量が多すぎると、BGSAVE 時間が大幅に延長され、クラスターの可用性が低下します。同時に、QPS の増加は各ノードの CPU 使用率の増加にもつながります。これは、拡張クラスターを追加することで解決する必要があります。現時点では、Redis クラスターの水平方向のスケーラビリティはあまり良くなく、ネイティブ スロットの移行ソリューションは非常に非効率的です。新しいノードを追加すると、セキュリティ メカニズムにより、Lettuce などの一部のクライアントは新しいノードを認識できなくなります。さらに、移行にかかる時間はまったく予測できず、移行プロセス中に問題が発生した場合は元に戻すことはできません。
物理マシン クラスターの現在の拡張計画は次のとおりです:
オンデマンドで新しいクラスターを作成します;
同期ツールを使用して、データの転送 古いクラスタから新しいクラスタに同期します;
データが正しいことを確認した後、ビジネスと通信し、サービスを再起動して新しいクラスタに切り替えます。
プロセス全体は面倒でリスクがあり、企業はサービスを再開する必要があります。
プロキシ レイヤーを使用すると、バックエンドの作成、同期、およびクラスターの切り替えをクライアントから保護できます。新旧クラスターの同期が完了したら、プロキシにコマンドを送信して新しいクラスターへの接続を切り替えることができ、クライアントを全く意識しないクラスターの拡張・縮小を実現できます。
4. データ セキュリティ リスク
Redis は AUTH による認証操作を実装しています。クライアントは Redis に直接接続されており、パスワードはクライアントに保存する必要があります。プロキシを使用すると、クライアントはプロキシのパスワードを介して Redis にアクセスするだけでよく、Redis パスワードを知る必要はありません。また、プロキシは FLUSHDB や CONFIG SET などの操作を制限し、顧客が誤ってデータを消去したり Redis 構成を変更したりすることを防ぎ、システムのセキュリティを大幅に向上させます。
同時に、Redis は監査機能を提供しません。プロキシ サーバー上でリスクの高い操作のログ機能を追加し、全体的なパフォーマンスに影響を与えることなく監査機能を提供します。
4. プロキシによって引き起こされる問題
1. もう 1 つのホップによって引き起こされる遅延
プロキシクライアントと Redis インスタンスの間にあります。クライアントが Redis データにアクセスするときは、最初にプロキシにアクセスし、次に Redis ノードにアクセスする必要があります。ホップが 1 つ増えると、遅延が増加します。テスト結果によると、ホップを 1 つ追加すると遅延が 0.2 ~ 0.3 ミリ秒増加しますが、これは通常、ビジネスでは許容できる範囲です。
2. ポッドのドリフトによる IP の変更
K8s では、プロキシはデプロイメントによって実装されるため、ノードの再起動によって生じる IP の変更の問題もあります。 。当社の K8s LB ソリューションは、プロキシの IP 変更を感知し、LVS トラフィックを再起動されたプロキシに動的に切り替えることができます。
3. LVS によるレイテンシー
以下の表に示すテストでは、さまざまなデータ長の get/set 操作によってもたらされる LVS レイテンシーは 0.1 未満です。 MS。
#5. K8s によってもたらされるメリット
1. 簡単な導入
運用保守基盤を通じて K8s API を呼び出してクラスターを展開することで、運用保守効率が大幅に向上します。2. ポート管理の問題を解決する
現在、Xiaomi の物理マシン上の Redis インスタンスのデプロイはポートによって区別されており、オフライン ポートは再利用できません。会社全体の各 Redis インスタンスに一意のポート番号があるとします。現在、65,535 の港のうち 40,000 港以上が利用されており、現在の事業開発率によると、港湾リソースは 2 年以内に枯渇すると予想されています。 K8s のデプロイメントにより、各 Redis インスタンスに対応する K8s ポッドは独立した IP を持ち、ポートの枯渇や複雑な管理の問題が発生しません。3. 顧客が使用するためのしきい値を下げる
アプリケーションの場合、VIP に接続するには非インテリジェント クライアントのスタンドアロン バージョンを使用するだけで済みます。これにより、使用のしきい値が低くなり、面倒で複雑なパラメーター設定が回避されます。 VIP とポートは静的に固定されているため、アプリケーションは Redis クラスターのトポロジ自体を処理する必要はありません。
4. クライアントのパフォーマンスの向上
スマート クライアントはクライアントのキーをハッシュする必要があるため、非スマート クライアントを使用すると、クライアントの負荷を軽減することもできます。 QPS が比較的高い場合に、リクエストの送信先となる Redis ノードがクライアント マシンの CPU リソースを消費するかを決定します。もちろん、クライアント アプリケーションの移行を容易にするために、プロキシもスマート クライアント プロトコルをサポートするようにしました。
5. 動的アップグレードと拡張・縮小
プロキシは、Redis Cluster を動的に追加・切り替えする機能をサポートしており、Redis Cluster のクラスタアップグレードおよび拡張切り替えプロセスをサポートします。ビジネスエンドはまったく知りません。例えば、ビジネス側では30ノードのRedisクラスターを使用していますが、業務量の増加によりデータ量とQPSが急増しており、クラスターサイズを2倍にする必要があります。元の物理マシンで容量を拡張する場合は、次のプロセスが必要です:
リソースを調整し、60 ノードの新しいクラスターを展開します。
手動構成移行 現在のクラスターのデータを新しいクラスターに移行するツール;
データが正しいことを確認した後、Redis クラスター接続プールを変更するようにビジネス パーティに通知します。トポロジを変更してサービスを再起動します。
Redis Cluster はオンライン拡張をサポートしていますが、拡張プロセス中のスロットの再配置はオンライン ビジネスに影響を及ぼし、移行時間は制御できないため、この方法は現時点ではほとんど使用されていません。リソースが著しく不足している場合にのみ使用されます。
新しい K8s アーキテクチャでは、移行プロセスは次のとおりです:
API インターフェイスを介して 1 クリックで 60 ノードの新しいクラスターを作成します。
また、API インターフェイスを介してワンクリックでクラスター同期ツールを作成し、データを新しいクラスターに移行します。
データが正しいことを確認した後、送信します。コマンドをプロキシに送信して、新しいクラスタ情報を追加し、切り替えを完了します。
プロセス全体はビジネスエンドをまったく意識しません。
クラスターのアップグレードも非常に便利です。ビジネス側が特定の遅延グリッチを許容できる場合は、オフピーク時間に StatefulSet ローリング アップグレードを通じて実装できます。ビジネスに遅延の要件がある場合は、データを移行できます。新しいクラスターを作成することでそれを実現します。
6. サービスの安定性とリソース使用率の向上
K8s のリソース分離機能を使用して、異なる種類のアプリケーションの混合デプロイを可能にします。これにより、リソースの使用率が向上するだけでなく、サービスの安定性も確保されます。
6. 発生した問題
1. ポッドの再起動によりデータ損失が発生する
K8s ポッドがクラッシュする問題が再起動されると、再起動速度が速すぎるため、Redis Cluster クラスターが検出されてマスターに切り替わる前にポッドが再起動されます。ポッド上の Redis がスレーブである場合、影響はありません。ただし、Redis がマスターで AOF がない場合、再起動後に元のメモリ データはすべてクリアされ、Redis は以前に保存した RDB ファイルを再読み込みしますが、RDB ファイルはリアルタイム データではありません。その後、スレーブは自身のデータを以前の RDB ファイルのデータ ミラーと同期するため、一部のデータ損失が発生します。
StatefulSet をデプロイする場合、Pod 名は特定の命名形式に従い、固定番号が含まれるため、StatefulSet はステートフル サービスです。 Redis クラスターを初期化するときに、隣接する番号付きポッドをマスター/スレーブ関係に設定します。ポッドを再起動するときは、ポッド名でスレーブを決定します。ポッドを再起動する前に、クラスタ フェイルオーバー コマンドをスレーブ ノードに送信して、生き残っているスレーブ ノードを強制的にマスターにします。このようにして、再起動後、ノードはスレーブ ノードとして自動的にクラスターに参加します。
LVS マッピングの遅延
プロキシのポッドは LVS を通じて負荷分散されます。LVS がバックエンドの IP:ポート マッピングに影響を与えるまでに一定の遅延が発生します。プロキシノードが突然オフラインになると、一部の接続が失われます。ビジネスに対するプロキシの運用とメンテナンスの影響を最小限に抑えるために、プロキシ展開テンプレートに次のオプションを追加しました:
lifecycle: preStop: exec: command: - sleep - "171"
通常のプロキシ ポッド オフライン用 (クラスタの削減、プロキシ バージョンのローリング アップデートなど) K8s によって制御されるポッドがオフラインになると、LVS にメッセージを送信し、ポッドがオフラインになるまで 171 秒待機します。この時間は、LVS が何も意識することなく、このポッドのトラフィックを他のポッドに徐々に切り替えるのに十分な時間です。ビジネス。
2. K8s StatefulSet は Redis Cluster のデプロイメント要件を満たすことができません
K8s ネイティブ StatefulSet は Redis Cluster デプロイメントの要件を完全には満たすことができません:
Redis Cluster では、マスター/スタンバイ関係を持つノードを同じマシンにデプロイすることはできません。これは簡単に理解できますが、マシンがダウンすると、データシャードが使用できなくなります。
2) Redis クラスターでは、クラスター内のマスター ノードの半分以上が失敗することは許可されません。これは、マスター ノードの半分以上が失敗すると、要件を満たすのに十分なノード投票がなくなるためです。ゴシッププロトコル。 Redis クラスターのプライマリ ノードとセカンダリ ノードはいつでも切り替えることができるため、同じマシン上のすべてのノードがプライマリ ノードになる状況は避けられないため、デプロイメント中はクラスター内のノードの 1/4 を超えるノードを許可することはできません。同じマシンにデプロイされます。
上記の要件を満たすために、ネイティブ StatefulSet はアンチアフィニティ機能を使用して、同じクラスターが同じマシン上に 1 つのノードのみをデプロイするようにできますが、このマシンの使用率は非常に低くなります。
そこで私たちは、Redis ノードをデプロイするためにさまざまな戦略を使用する、StatefulSet に基づく CRD: RedisStatefulSet を開発しました。 RedisStatefulSet で Redis を管理するための機能がいくつか追加されました。これらについては、引き続き他の記事で詳しく説明します。
7. 概要
数十の Redis クラスターが K8 上にデプロイされ、6 か月以上実行されており、これらのクラスターにはグループ内の複数のビジネスが関与しています。 K8 の迅速な導入と障害移行機能のおかげで、これらのクラスターの運用と保守の作業負荷は、物理マシン上の Redis クラスターの作業負荷よりもはるかに低くなり、その安定性は十分に検証されています。
また、運用保守の過程でも多くの問題に遭遇しましたが、記事で取り上げた機能の多くは実際のニーズに基づいて改良されました。次のプロセスでは、リソースの利用効率とサービス品質を向上させるために、まだ多くの問題を徐々に解決する必要があります。
1. 混合デプロイメントと独立したデプロイメント
物理マシンの Redis インスタンスは個別にデプロイされ、すべての Redis インスタンスは単一の物理マシンにデプロイされます。経営には有利ですが、リソースの利用率は高くありません。 Redis インスタンスは CPU、メモリ、ネットワーク IO を使用しますが、ストレージ容量は基本的に無駄になります。 Redis インスタンスが K8s にデプロイされている場合、他のタイプのサービスは、それが配置されているマシンにデプロイできます。これによりマシンの使用率は向上しますが、Redis のような高可用性と待ち時間の要件があるサービスの場合、削除されると、マシンのメモリが不足しているため、これは受け入れられません。そのため、運用保守担当者はRedisインスタンスが配置されているすべてのマシンのメモリを監視する必要があり、メモリが不足した場合はマスターを切り離してノードを移行することになりますが、運用保守の負担が増加します。
ハイブリッド デプロイメントに他の高ネットワーク スループットのアプリケーションがある場合、Redis サービスに悪影響を及ぼす可能性があります。 K8s のアンチアフィニティ機能は、そのようなアプリケーションを持たないマシンに Redis インスタンスを選択的にデプロイできますが、マシンのリソースが不足している場合、この状況は避けられません。
2. Redis クラスター管理
Redis クラスターは、セントラル ノードのない P2P クラスター アーキテクチャであり、ゴシップ プロトコルに依存して伝播および調整され、Redis クラスターのステータスを自動的に修復します。クラスターのノードがオンラインとオフラインになります。ネットワークの問題により、Redis クラスター内の一部のノードのステータスに問題が発生する可能性があります。たとえば、クラスター トポロジやスプリット ブレインに、障害が発生したノードやハンドシェイク ステータスのノードが表示される場合があります。この異常状態に対しては、Redis CRD に機能を追加することで段階的に解消し、運用保守効率をさらに向上させることができます。
3. 監査とセキュリティ
Redis は Auth パスワード認証保護機能のみを提供しており、権限管理がないため、セキュリティは比較的低いです。 Proxyを利用することで、クライアントの種類をパスワードで区別することができ、管理者と一般ユーザーでは異なるパスワードでログインし、実行可能な操作権限も異なるため、権限管理や操作監査などの機能を実現できます。
4. 複数の Redis クラスターのサポート
ゴシップ プロトコルの制限により、単一の Redis クラスターの水平方向の拡張機能は限られています。クラスター サイズが 300 ノードの場合、ノード選択は、クラス トポロジ変更の効率が大幅に低下します。同時に、単一の Redis インスタンスの容量が大きすぎてはいけないため、単一の Redis クラスターで TB を超えるデータ規模をサポートすることは困難です。プロキシを使用すると、キーを論理的にシャーディングできるため、単一のプロキシを複数の Redis クラスターに接続できるようになり、クライアントの観点からは、より大きなデータ スケールをサポートできる Redis クラスターに接続するのと同じになります。
以上がRedis クラスターインスタンスの分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。