ホームページ バックエンド開発 Golang Kubernetes オペレーターは同時実行性をどのように処理しますか?

Kubernetes オペレーターは同時実行性をどのように処理しますか?

Oct 10, 2024 am 06:07 AM

元々は私のブログに投稿されました

デフォルトでは、Kubebuilder とコントローラー ランタイムを使用して構築されたオペレーターは、一度に 1 つのリコンサイル リクエストを処理します。オペレータ開発者がアプリケーションのロジックを推論してデバッグするのが容易になるため、これは賢明な設定です。また、コントローラーから ectd や API サーバーなどのコア Kubernetes リソースへのスループットも制限されます。

しかし、ワークキューがバックアップを開始し、リクエストがキュー内に残されて処理を待っているために平均調整時間が増加した場合はどうなるでしょうか?幸いなことに、コントローラー ランタイムのコントローラー構造体には MaxConcurrentReconciles フィールドが含まれています (以前 Kubebuilder のヒント記事で述べたように)。このオプションを使用すると、単一のコントローラーで実行する同時調整ループの数を設定できます。したがって、1 より大きい値を指定すると、複数の Kubernetes リソースを同時に調整できます。

オペレーターとしての取り組みの初期に、私が抱いた疑問の 1 つは、同じリソースが 2 つ以上のゴルーチンによって同時に調整されていないことをどのように保証できるかということでした。 MaxConcurrentReconciles を 1 より大きく設定すると、調整ループ内のオブジェクトの状態が外部ソース (別のスレッドで実行されている調整ループ) からの副作用によって変化する可能性があるため、あらゆる種類の競合状態や望ましくない動作が発生する可能性があります。 .

私はこれについてしばらく考え、ゴルーチンが特定のリソース (名前空間/名前に基づいて) のロックを取得できるようにする sync.Map ベースのアプローチを実装しました。

コントローラーのワークキューにすでにこの機能が含まれていることを最近 (k8s Slack チャネルで) 知ったので、この努力はすべて無駄だったことがわかりました。ただし、実装はより単純です。

これは、k8s コントローラーのワークキューが固有のリソースが順番に調整されることをどのように保証するかについての簡単な説明です。したがって、MaxConcurrentReconciles が 1 より大きく設定されている場合でも、特定のリソースに対して一度に動作する調整関数は 1 つだけであると確信できます。

client-go/util

コントローラー ランタイムは、client-go/util/workqueue ライブラリを使用して、基礎となる調整キューを実装します。パッケージの doc.go ファイルのコメントには、ワークキューが次のプロパティをサポートしていることが記載されています:

  • 公平: アイテムは追加された順序で処理されます。
  • ケチ: 1 つの項目は同時に複数回処理されません。処理される前に項目が複数回追加された場合、処理されるのは 1 回だけです。
  • 複数の消費者と生産者。特に、アイテムの処理中にアイテムを再度キューに入れることができます。
  • 通知をシャットダウンします。

ちょっと待ってください...私の答えはここの 2 番目の項目、「けちな」プロパティにあります。これらのドキュメントによると、キューはコードを 1 行も記述することなく、この同時実行性の問題を自動的に処理します。実装を見てみましょう。

ワークキューはどのように機能しますか?

ワークキュー構造体には、Add、Get、Done の 3 つの主要なメソッドがあります。コントローラー内では、情報提供者が調整リクエスト (汎用 k8s リソースの名前空間名) をワークキューに追加します。別のゴルーチンで実行されている調整ループは、キューから次のリクエストを取得します (キューが空の場合はブロックされます)。このループは、コントローラーに書き込まれたカスタム ロジックをすべて実行し、コントローラーはキュー上で Done を呼び出し、リコンサイル リクエストを引数として渡します。これにより、プロセスが再度開始され、調整ループは Get を呼び出して次の作業項目を取得します。

これは、RabbitMQ でのメッセージの処理に似ています。ワーカーがキューから項目を取り出して処理し、処理が完了し、項目をキューから削除しても安全であることを示す「Ack」をメッセージ ブローカーに送り返します。キュー。

それでも、QuestDB Cloud のインフラストラクチャを強化するオペレーターを運用環境で実行しており、ワークキューが宣伝どおりに動作することを確認したいと考えていました。そこで、動作を検証するための簡単なテストを作成しました。

ちょっとしたテスト

これは、「Stingy」プロパティを検証する簡単なテストです:

package main_test

import (
    "testing"

    "github.com/stretchr/testify/assert"

    "k8s.io/client-go/util/workqueue"
)

func TestWorkqueueStingyProperty(t *testing.T) {

    type Request int

    // Create a new workqueue and add a request
    wq := workqueue.New()
    wq.Add(Request(1))
    assert.Equal(t, wq.Len(), 1)

    // Subsequent adds of an identical object
    // should still result in a single queued one
    wq.Add(Request(1))
    wq.Add(Request(1))
    assert.Equal(t, wq.Len(), 1)

    // Getting the object should remove it from the queue
    // At this point, the controller is processing the request
    obj, _ := wq.Get()
    req := obj.(Request)
    assert.Equal(t, wq.Len(), 0)

    // But re-adding an identical request before it is marked as "Done"
    // should be a no-op, since we don't want to process it simultaneously
    // with the first one
    wq.Add(Request(1))
    assert.Equal(t, wq.Len(), 0)

    // Once the original request is marked as Done, the second
    // instance of the object will be now available for processing
    wq.Done(req)
    assert.Equal(t, wq.Len(), 1)

    // And since it is available for processing, it will be
    // returned by a Get call
    wq.Get()
    assert.Equal(t, wq.Len(), 0)
}
ログイン後にコピー

ワークキューは内部でミューテックスを使用するため、この動作はスレッドセーフです。そのため、キューを壊すために複数の goroutine を使用してキューから高速で読み書きするテストをさらに作成したとしても、ワークキューの実際の動作はシングルスレッド テストの動作と同じになります。

すべてが失われたわけではない

How do Kubernetes Operators Handle Concurrency?

Kubernetes の標準ライブラリには、このような小さな宝石がたくさん隠されており、その一部はあまり目立たない場所 (go クライアント パッケージにあるコントローラー ランタイム ワークキューなど) にあります。この発見や、私が過去に同様の発見をしたにもかかわらず、これらの問題を解決しようとするこれまでの試みは完全な時間の無駄ではないと今でも感じています。これらは、分散システム コンピューティングの基本的な問題について批判的に考えることを強制し、内部で何が起こっているのかをより深く理解するのに役立ちます。そのため、「Kubernetes が成功した」ことがわかるまでに、コードベースを簡素化し、おそらく不必要な単体テストをいくつか削除できると安心しています。

以上がKubernetes オペレーターは同時実行性をどのように処理しますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Debian OpenSSLの脆弱性は何ですか Debian OpenSSLの脆弱性は何ですか Apr 02, 2025 am 07:30 AM

OpenSSLは、安全な通信で広く使用されているオープンソースライブラリとして、暗号化アルゴリズム、キー、証明書管理機能を提供します。ただし、その歴史的バージョンにはいくつかの既知のセキュリティの脆弱性があり、その一部は非常に有害です。この記事では、Debian SystemsのOpenSSLの共通の脆弱性と対応測定に焦点を当てます。 Debianopensslの既知の脆弱性:OpenSSLは、次のようないくつかの深刻な脆弱性を経験しています。攻撃者は、この脆弱性を、暗号化キーなどを含む、サーバー上の不正な読み取りの敏感な情報に使用できます。

フロントエンドからバックエンドの開発に変身すると、JavaやGolangを学ぶことはより有望ですか? フロントエンドからバックエンドの開発に変身すると、JavaやGolangを学ぶことはより有望ですか? Apr 02, 2025 am 09:12 AM

バックエンド学習パス:フロントエンドからバックエンドへの探査の旅は、フロントエンド開発から変わるバックエンド初心者として、すでにNodeJSの基盤を持っています...

GOの浮動小数点番号操作に使用されるライブラリは何ですか? GOの浮動小数点番号操作に使用されるライブラリは何ですか? Apr 02, 2025 pm 02:06 PM

GO言語の浮動小数点数操作に使用されるライブラリは、精度を確保する方法を紹介します...

Go's Crawler Collyのキュースレッドの問題は何ですか? Go's Crawler Collyのキュースレッドの問題は何ですか? Apr 02, 2025 pm 02:09 PM

Go Crawler Collyのキュースレッドの問題は、Go言語でColly Crawler Libraryを使用する問題を調査します。 �...

Beego ormのモデルに関連付けられているデータベースを指定する方法は? Beego ormのモデルに関連付けられているデータベースを指定する方法は? Apr 02, 2025 pm 03:54 PM

Beegoormフレームワークでは、モデルに関連付けられているデータベースを指定する方法は?多くのBEEGOプロジェクトでは、複数のデータベースを同時に操作する必要があります。 Beegoを使用する場合...

Goでは、Printlnとstring()関数を備えた文字列を印刷すると、なぜ異なる効果があるのですか? Goでは、Printlnとstring()関数を備えた文字列を印刷すると、なぜ異なる効果があるのですか? Apr 02, 2025 pm 02:03 PM

Go言語での文字列印刷の違い:printlnとstring()関数を使用する効果の違いはGOにあります...

Redisストリームを使用してGO言語でメッセージキューを実装する場合、user_idタイプの変換の問題を解決する方法は? Redisストリームを使用してGO言語でメッセージキューを実装する場合、user_idタイプの変換の問題を解決する方法は? Apr 02, 2025 pm 04:54 PM

redisstreamを使用してGo言語でメッセージキューを実装する問題は、GO言語とRedisを使用することです...

Golandのカスタム構造ラベルが表示されない場合はどうすればよいですか? Golandのカスタム構造ラベルが表示されない場合はどうすればよいですか? Apr 02, 2025 pm 05:09 PM

Golandのカスタム構造ラベルが表示されない場合はどうすればよいですか?ゴーランドを使用するためにGolandを使用する場合、多くの開発者はカスタム構造タグに遭遇します...

See all articles