K8s 拡張ワークロード OpenKruise CloneSet

K8s 拡張ワークロード OpenKruise CloneSet

OpenKruise (https://openkruise.io) は、デプロイメント、リリース、運用と保守、可用性の保護など、クラウドネイティブ アプリケーションの自動化に重点を置いた Kubernetes ベースの拡張スイートです。 OpenKruise が提供する機能のほとんどは、CRD 拡張に基づいて定義されています。外部依存関係はなく、純粋な Kubernetes クラスターで実行できます。 Kubernetes 自体が提供するアプリケーションの展開および管理機能の中には、大規模なアプリケーションやクラスターのシナリオには到底不十分なものもあります。 OpenKruise は、アプリケーションの展開、アップグレード、保護、運用、保守などにおける Kubernetes の欠点を補います。

OpenKruise は次のコア機能を提供します。

  • 拡張ワークロード: OpenKruise には、CloneSet、Advanced StatefulSet、Advanced DaemonSet、BroadcastJob などの一連の拡張ワークロードが含まれています。Kubernetes ネイティブ ワークロードと同様の基本機能をサポートするだけでなく、インプレース アップグレード、構成可能なスケーリング/リリース戦略、同時操作なども提供します。その中でも、インプレース アップグレードは、アプリケーション コンテナ イメージや環境変数までアップグレードする新しい方法です。新しいイメージを使用して Pod 内の特定のコンテナのみが再構築され、Pod 全体やその中の他のコンテナは影響を受けません。したがって、リリース速度が速くなり、スケジューラ、CNI、CSI などの他のコンポーネントへの悪影響が回避されます。
  • アプリケーション バイパス管理: OpenKruise は、バイパスを通じてアプリケーション サイドカー コンテナーとマルチリージョン デプロイメントを管理する複数の方法を提供します。バイパスとは、アプリケーションのワークロードを変更せずに実装できることを意味します。たとえば、SidecarSet を使用すると、一致するすべての Pod が作成されるときに、特定のサイドカー コンテナーをそれらの Pod に挿入できます。ポッド内の他のコンテナに影響を与えることなく、挿入されたサイドカー コンテナ イメージをその場でアップグレードすることもできます。 WorkloadSpread は、ステートレス ワークロードによって拡張された Pod の地域分布を制限できるため、単一のワークロードを複数の地域に柔軟にデプロイできるようになります。
  • 高可用性保護: OpenKruise は、CRD、名前空間、およびほぼすべてのワークロード タイプのリソースを含む Kubernetes リソースがカスケード削除メカニズムによって干渉されるのを防ぎます。 Pod Eviction に対する保護のみを提供するネイティブ Kubernetes PDB と比較して、PodUnavailableBudget は、Pod の削除、Eviction、更新など、多くの自発的な中断シナリオから保護できます。
  • 高度なアプリケーション運用および保守機能: OpenKruise は、アプリケーションの管理を向上させるための高度な運​​用および保守機能も多数提供します。たとえば、ImagePullJob を使用して、任意の範囲のノード上の特定のイメージを事前にプルしたり、Pod 内の 1 つ以上のコンテナーをその場で再起動するように指定したりできます。

建築

次の図は、OpenKruise の全体的なアーキテクチャを示しています。

建築

OpenKruise のすべての機能は Kubernetes CRD を通じて提供されます。 Kruise-manager は、コントローラーと Webhook を実行する中心的なコンポーネントです。これは、Deployment を通じて kruise-system 名前空間にデプロイされます。論理的には、cloneset-controller や sidecarset-controller などのコントローラーは独立して実行されます。ただし、複雑さを軽減するために、これらは別のバイナリ ファイルにパッケージ化され、kruise-controller-manager-xxx Pod で実行されます。コントローラーに加えて、kruise-controller-manager-xxx には、Kruise CRD および Pod リソースのアドミッション Webhook も含まれています。 Kruise-manager は、感知して処理する必要があるリソースを構成するためのいくつかの webhook 構成を作成し、kube-apiserver が呼び出すサービスを提供します。

バージョン v0.8.0 以降では、新しい Kruise-daemon コンポーネントが提供されます。 DaemonSet を通じて各ノードにデプロイされ、イメージのプリヒートやコンテナの再起動などの機能を提供します。

インストール

ここでもインストールには Helm を使用します。注意: v1.0.0 以降では、OpenKruise は Kubernetes >= 1.16 以上のクラスターにインストールして使用する必要があります。

まずチャートのリポジトリを追加します。

  helmリポジトリopenkruiseを追加しますhttps://openkruise.github.io/charts/
helmリポジトリの更新

次に、次のコマンドを実行して、アプリケーションの最新バージョンをインストールします。

  Helmアップグレード-- kruiseをインストールopenkruise / kruise --バージョン1.3 .0

チャートはテンプレート内でデフォルトで名前空間 kruise-system を定義するため、インストール時に指定する必要はありません。ご使用の環境で DockerHub 公式イメージへのアクセスが遅い場合は、次のコマンドを使用してイメージを Alibaba Cloud イメージに置き換えることができます。

 ➜ Helm upgrade --install kruise openkruise/kruise --set manager.image.repository=openkruise-registry.cn-shanghai.cr.aliyuncs.com/openkruise/kruise-manager --version 1.3.0

アプリケーションがデプロイされると、2 つの kruise-manager Pod が kruise-system 名前空間で実行されます。また、マスターを選出するためにリーダー選挙も使用します。高可用性を実現するために、一度に 1 つだけがサービスを提供します。さらに、kruise-daemon コンポーネントは DaemonSet として起動されます。

  kubectl getポッド- n kruise -システム
名前準備完了ステータス再起動年齢
kruise -コントローラー-マネージャー- 7 d78fc5c97 - d6mbb 1 / 1実行中0 52
kruise -コントローラー-マネージャー- 7 d78fc5c97 - wccbn 1 / 1実行中0 52
クルーズ-デーモン- 9f 94 k 1 / 1ランニング0 52 s
kruise - daemon - bqj69 1 / 1実行中0 52
kruise - daemon - h95pf 1 / 1実行中0 52

インストールにデフォルトのパラメータを使用しない場合は、構成をカスタマイズすることもできます。設定可能な値は、チャートのドキュメント https://github.com/openkruise/charts を参照してカスタマイズできます。

クローンセット

CloneSet コントローラーは、OpenKruise が提供するネイティブ デプロイメント用の拡張コントローラーです。使い方はデプロイメントとほぼ同じです。以下は、宣言した CloneSet リソース オブジェクトです。

 #クローンセット- demo.yaml
apiバージョン:アプリクルーズio / v1alpha1
種類: CloneSet
メタデータ:
名前: cs -デモ
仕様:
レプリカ: 3
セレクター:
マッチラベル:
アプリ: cs
テンプレート
メタデータ:
ラベル:
アプリ: cs
仕様:
コンテナ:
-名前: nginx
画像: nginx :アルパイン
imagePullPolicy : IfNotPresent
ポート:
-コンテナポート: 80

上記の CloneSet オブジェクトを直接作成します。

  kubectl apply -fクローンセット-デモ.yaml
kubectl get cloneset cs -デモ
名前希望更新済みUPDATED_READY READY合計年齢
cs -デモ3 3 0 0 3 8
kubectlクローンセットcsの説明-デモ
名前: cs - demo
名前空間:デフォルト
ラベル: <なし>
注釈: <なし>
APIバージョン: appsクルーズio / v1alpha1
種類: CloneSet
# ......
イベント:
タイプ理由年齢送信元 メッセージ
---- ------ ---- ---- -------
正常成功21クローンセットの作成-コントローラーはポッドの作成成功しましたcs -デモ- jfx5s
正常成功21 sクローンセットの作成-コントローラーはポッドcs -デモ- kg9p2の作成成功しました
正常成功21 sクローンセットの作成-コントローラーはポッドcs -デモ- n72frの作成成功しました

オブジェクトが作成された後、kubectl describe コマンドを使用して対応するイベント情報を表示できます。 cloneset-controller が Pod を直接作成していることがわかります。これはネイティブのデプロイメントとは多少異なります。デプロイメントは ReplicaSet を通じて Pod を作成するため、ここでは CloneSet が Pod を直接管理していることがわかります。この時点で、ポッドの 3 つのレプリカも正常に作成されます。

  kubectlポッドを取得- l app = cs
名前準備完了ステータス再起動年齢
cs -デモ- jfx5s 1 / 1実行中0 58
cs -デモ- kg9p2 1 / 1実行中0 58
cs -デモ- n72fr 1 / 1実行中0 58

CloneSet は使用方法が Deployment に似ていますが、Deployment よりも多くの高度な機能を備えています。詳しく紹介していきましょう。

スケーリング

ストリーミングの拡張

CloneSet が拡張されている場合、ScaleStrategy.MaxUnavailable を使用して拡張ステップのサイズを制限し、サービス アプリケーションへの影響を最小限に抑えることができます。絶対値またはパーセンテージを設定できます。この値を設定しない場合は、制限がないことを意味します。

たとえば、上記のリソース リストに次のデータを追加します。

 apiバージョン:アプリクルーズio / v1alpha1
種類: CloneSet
メタデータ:
名前: cs -デモ
仕様:
最小準備秒数: 60
スケール戦略:
最大利用不可: 1
レプリカ: 5
......

上記では、scaleStrategy.maxUnavailable を 1 に設定しています。minReadySeconds パラメータと組み合わせると、スケールアップ時に、CloneSet は、前のスケールアウトされた Pod が 1 分以上 Ready 状態だった場合にのみ、次の Pod を作成することになります。たとえば、ここではレプリカを 5 つまでスケールアップします。上記のオブジェクトを更新した後、CloneSet イベントを表示します。

  kubectlクローンセットcsの説明-デモ
......
イベント:
タイプ理由年齢送信元 メッセージ
---- ------ ---- ---- -------
正常に作成されました4 つのm25sクローン セット-コントローラーがポッドcs -デモ- jfx5sの作成成功しました
正常に完了しました4 つのm25sクローン セットを作成-コントローラーがポッドcsの作成成功-デモ- kg9p2
正常に完了しました4 つのm25sクローン セットの作成-コントローラーがポッドcsの作成成功しました-デモ- n72fr
警告ScaleUpLimited 66cloneset -コントローラーのscaleUp は scaleStrategyにより制限されています最大利用不可制限: 1
正常な成功作成66クローンセット-コントローラーはポッドcs -デモ- x8ndfの作成成功しました
警告ScaleUpLimited 64( 66超えるとx6 ) cloneset - controller scaleUp はscaleStrategyにより制限されます最大利用不可制限: 0
正常成功作成5クローンセット-コントローラーがポッドcs -デモ- 2 sfzzの作成成功

Pod がすぐに拡張されることがわかります。 minReadySeconds: 60 を設定したので、新しく拡張された Pod が正常に作成されてから 1 分後に別の Pod が拡張されます。これは上記のイベント情報でも確認できます。 Pod の AGE を見ると、拡張された 2 つの Pod の間に約 1 分のギャップがあることもわかります。

  kubectlポッドを取得- l app = cs
名前準備完了ステータス再起動年齢
cs -デモ- 2 sfzz 1 / 1実行中0 22
cs -デモ- jfx5s 1 / 1実行中0 4分42秒
cs -デモ- kg9p2 1 / 1実行中0 4分42秒
cs -デモ- n72fr 1 / 1実行中0 4 m42s
cs -デモ- x8ndf 1 / 1実行中0 83

CloneSet がスケールダウンされる場合、削除する Pod を指定することもできますが、これは StatefulSet または Deployment では不可能です。 StatefulSet はシーケンス番号に基づいて Pod を削除しますが、Deployment/ReplicaSet はコントローラーで定義された順序に基づいてのみ削除できます。 CloneSet を使用すると、次に示すように、レプリカの数を減らしながら削除する Pod の名前を指定できます。

 apiバージョン:アプリクルーズio / v1alpha1
種類: CloneSet
メタデータ:
名前: cs -デモ
仕様:
最小準備秒数: 60
スケール戦略:
最大利用不可: 1
削除するポッド:
- cs -デモ- n72fr
レプリカ: 4
......

上記のリソース オブジェクトを更新すると、アプリケーションは 4 つのポッドにスケールダウンされます。 podsToDelete リストに Pod 名が指定されている場合、コントローラーはまずこれらの Pod を削除します。削除された Pod については、コントローラーによって podsToDelete リストから自動的にクリアされます。たとえば、上記のリソース オブジェクトを更新すると、 cs-demo-n72fr Pod は削除され、残りは保持されます。

  kubectlポッドを取得- l app = cs
名前準備完了ステータス再起動年齢
cs -デモ- 2 sfzz 1 / 1実行中0 61
cs -デモ- jfx5s 1 / 1実行中0 5分21秒
cs -デモ- kg9p2 1 / 1実行中0 5分21秒
cs -デモ- x8ndf 1 / 1実行中0 2 m2s

podsToDelete に Pod 名のみを追加し、レプリカの数を変更しない場合、コントローラーは指定された Pod を最初に削除し、新しい Pod を拡張します。 Pod を直接削除する別の方法は、削除する Pod に apps.kruise.io/specified-delete: true ラベルを追加することです。

手動で Pod を削除する場合と比較して、podsToDelete または apps.kruise.io/specified-delete: true を使用すると、CloneSet の maxUnavailable/maxSurge によって削除が保護され、PreparingDelete ライフサイクル フックがトリガーされます。

PVCテンプレート

かなりユニークな機能として、CloneSet では、ユーザーが PVC テンプレート volumeClaimTemplates を構成して、各 Pod に固有の PVC を生成できることが挙げられます。ステートフル アプリケーションでは通常、個別の PVC 設定が必要になるため、これはデプロイメントではサポートされていません。 CloneSet の PVC テンプレートを使用する場合は、次の点に注意する必要があります。

  • 自動的に作成された各 PVC には CloneSet を指す ownerReference があるため、CloneSet が削除されると、作成されたすべての Pod と PVC が削除されます。
  • CloneSet によって作成された各 Pod と PVC には、apps.kruise.io/cloneset-instance-id: xxx というラベルが付けられます。関連付けられている Pod と PVC は同じインスタンス ID を持ち、その名前にはこのインスタンス ID が接尾辞として付加されます。
  • ポッドがスケールダウンされたときに CloneSet コントローラーによって削除されると、そのポッドに関連付けられているすべての PVC も削除されます。
  • 外部からの直接呼び出しによってポッドが削除または排除された場合でも、そのポッドに関連付けられている PVC は引き続き存在します。 CloneSet コントローラーが数が不十分であると判断して容量を再拡張すると、新しく拡張された Pod は元の Pod のインスタンス ID を再利用し、元の PVC に関連付けます。
  • Pod が再構築およびアップグレードされると、関連付けられている PVC が削除され、Pod とともに新しく作成されます。
  • Pod がインプレースでアップグレードされると、関連付けられている PVC は引き続き使用されます。

PVC テンプレートの例を次に示します。

 #クローンセット- pvc.yaml
apiバージョン:アプリクルーズio / v1alpha1
種類: CloneSet
メタデータ:
ラベル:
アプリ:サンプル
名前:サンプル-データ
仕様:
レプリカ: 3
セレクター:
マッチラベル:
アプリ:サンプル
テンプレート
メタデータ:
ラベル:
アプリ:サンプル
仕様:
コンテナ:
-名前: nginx
画像: nginx :アルパイン
ボリュームマウント:
-名前:データ-ボリューム
マウントパス: / usr / share / nginx / html
ボリュームクレームテンプレート:
-メタデータ:
名前:データ- vol
仕様:
アクセスモード: [ "ReadWriteOnce" ]
リソース
リクエスト:
ストレージ: 20 Gi

たとえば、上記のリソース オブジェクトを適用すると、3 つの Pod と 3 つの PVC が自動的に作成され、各 Pod が PVC をマウントします。

  kubectl get pods - l app =サンプル
名前準備完了ステータス再起動年齢
サンプル-データ- t4vq6 0 / 1保留中0 2分13秒
サンプル-データ- vcjnl 0 / 1保留中0 2分13秒
サンプル-データ- znwjd 0 / 1保留中0 2分13秒
kubectl get pvc - l app =サンプル
名前ステータスボリューム容量アクセスモードストレージクラス 年齢
データ-ボリューム-サンプル-データ- t4vq6保留中2分 46 秒
データ- vol -サンプル-データ- vcjnl保留中2分 46 秒
データ-ボリューム-サンプル-データ- znwjd保留中2分 46 秒

アップグレード

CloneSet には 3 つのアップグレード方法があります。

  • 再作成: 古い Pod とその PVC を削除し、新しいバージョンで再作成します。これがデフォルトの方法です。
  • InPlaceIfPossible: 最初に Pod がインプレースでアップグレードされ、それが失敗した場合は再構築されてアップグレードされます。
  • InPlaceOnly: インプレース アップグレードのみが許可されます。したがって、ユーザーは前の項目の制限されたフィールドのみを変更できます。他のフィールドを変更しようとすると拒否されます。

ここで重要な概念は、インプレース アップグレードです。これは、OpenKruise が提供するコア機能の 1 つでもあります。 Pod 内のイメージをアップグレードする場合、再構築アップグレードとインプレース アップグレードの違いは次の図に示されています。

インプレースアップグレード

再構築およびアップグレードするときは、古い Pod を削除して新しい Pod を作成する必要があります。

  • Pod名とuidは、2つの完全に異なるPodオブジェクト(デプロイメントのアップグレードなど)であるため変更されます。
  • Pod名は変更されない可能性がありますが、UIDは変更される可能性があります。これは、同じ名前を再利用する異なるPodオブジェクトであるためです(StatefulSetのアップグレードなど)。
  • 新しいポッドは以前のポッドが配置されていたノードにスケジュールされない可能性が高いため、ポッドが配置されているノードの名前は変更される可能性があります。
  • ポッドのIPが変更されました。新しいポッドには以前のIPアドレスが割り当てられない可能性が高いためです。

ただし、インプレース アップグレードの場合は、同じ Pod オブジェクトを再利用し、そのフィールドを変更するだけです。

  • スケジュール設定、IP アドレスの割り当て、ボリュームのマウントなどの余分な操作やコストを回避できます。
  • 古いイメージのレイヤーのほとんどが再利用され、新しいイメージの変更の一部のレイヤーのみをプルする必要があるため、イメージのプルが高速化されます。
  • コンテナがインプレースでアップグレードされると、ポッド内の他のコンテナは影響を受けず、引き続き実行されます。

したがって、インプレース アップグレード方式を使用してワークロードをアップグレードできれば、オンライン アプリケーションへの影響は最小限に抑えられることは明らかです。前述のように、CloneSet アップグレード タイプは InPlaceIfPossible をサポートしており、これは Kruise が Pod 上でインプレース アップグレードを実行しようとすることを意味します。これが不可能な場合は、再構築アップグレードにフォールバックします。インプレース アップグレードを実行するには、次の変更が許可されます。

  • ラベルや注釈などのワークロードで spec.template.metadata.* を更新すると、Kruise は既存の Pod のメタデータの変更のみを更新します。
  • ワークロード内の spec.template.spec.containers[x].image を更新します。 Kruise は、Pod 全体を再構築せずに、Pod 内のこれらのコンテナのイメージをその場でアップグレードします。
  • Kruise v1.0 以降では、spec.template.metadata.labels/annotations を更新し、コンテナー内の変更されたラベル/注釈から env を構成すると、Kruise はこれらのコンテナーをアップグレードして、新しい env 値を有効にします。

それ以外の場合、spec.template.spec.containers[x].env​ や spec.template.spec.containers[x].resources などの他のフィールドへの変更は、再構築アップグレードに戻されます。

たとえば、上記のアプリケーションのアップグレード方法を InPlaceIfPossible​ に設定する場合、リソース リストに spec.updateStrategy.type: InPlaceIfPossible を追加するだけで済みます。

 apiバージョン:アプリクルーズio / v1alpha1
種類: CloneSet
メタデータ:
名前: cs -デモ
仕様:
更新戦略:
タイプ: InPlaceIfPossible
......
#イメージ: nginx : 1.7.9

アップデート後、Pod のステータスはあまり変化していないことがわかります。名前とIPは同じです。唯一の変更点は画像タグです:

  kubectlポッドを取得- l app = cs
名前準備完了ステータス再起動年齢
cs -デモ- 2 sfzz 1 / 1実行中1 ( 18) 36
cs -デモ- jfx5s 1 / 1実行中0 40 m
cs -デモ- kg9p2 1 / 1実行中0 40 m
cs -デモ- x8ndf 1 / 1実行中0 37
kubectlクローンセットcsの説明-デモ
名前: cs - demo
名前空間:デフォルト
ラベル: <なし>
注釈: <なし>
APIバージョン: appsクルーズio / v1alpha1
種類: CloneSet
......
イベント:
タイプ理由年齢送信元 メッセージ
---- ------ ---- ---- -------
# ......
正常SuccessfulUpdatePodInPlace 6 m58s cloneset - controller がポッドcs - demo - 2 sfzz正常インプレース更新しまし(リビジョンcs - demo - 7 cb9c88699 )
正常SuccessfulUpdatePodInPlace 5 m46s cloneset - controller がポッドcs - demo - x8ndf正常インプレース更新しまし(リビジョンcs - demo - 7 cb9c88699 )
正常SuccessfulUpdatePodInPlace 4 m43s cloneset - controller がポッドcs - demo - kg9p2正常インプレース更新しまし(リビジョンcs - demo - 7 cb9c88699 )
正常SuccessfulUpdatePodInPlace 3 m40s cloneset - controller がポッドcs - demo - jfx5s正常インプレース更新しまし(リビジョンcs - demo - 7 cb9c88699 )
kubectl describe pod cs -デモ- 2 sfzz
......
イベント:
タイプ理由年齢送信元 メッセージ
---- ------ ---- ---- -------
通常スケジュール44 m default - scheduler default / cs - demo - 2 sfzznode2正常に割り当てました
通常44 m のkubeletコンテナイメージ nginx:alpine」が既にマシン上に存在します
通常、 8 つのm8s kubeletコンテナを強制終了するとnginx の定義が変更され再起動されます
通常のプル8 m8s kubeletイメージ"nginx:1.7.9"のプル
通常7分 58 秒( 44x2 ) kubeletコンテナnginx作成
正常開始7分 58 秒( x2 44) kubeletコンテナnginxを開始
通常プル7分 58 秒kubeletイメージ「nginx:1.7.9」を9.720841233正常にプルしました(待機時間を含めると9.720847295)

これはインプレースアップグレードの効果です。インプレース アップグレードの全体的なワークフローを次の図に示します。

インプレースアップグレードプロセス

Kruise をインストールまたはアップグレードするときに PreDownloadImageForInPlaceUpdate 機能ゲートを有効にすると、CloneSet コントローラーは、古いバージョンのポッドが配置されているすべてのノードで、グレースケールでリリースする新しいバージョンのイメージを自動的に事前加熱します。これは、アプリケーションのリリースを高速化するのに非常に役立ちます。

デフォルトでは、CloneSet に事前加熱された各新しいイメージの同時実行性は 1 です。つまり、各ノードはイメージを 1 つずつプルします。調整する必要がある場合は、apps.kruise.io/image-predownload-parallelism アノテーションを使用して CloneSet で同時実行性を設定できます。

さらに、Kruise v1.1.0 以降では、少数の新しいバージョンの Pod が正常にアップグレードされた後に、apps.kruise.io/image-predownload-min-updated-ready-pods を使用してイメージの事前加熱を制御することもできます。その値は絶対数またはパーセンテージにすることができます。

 apiバージョン:アプリクルーズio / v1alpha1
種類: CloneSet
メタデータ:
注釈:
アプリクルーズio /画像-事前ダウンロード-並列処理: "5"
アプリクルーズio /イメージ-事前ダウンロード-最小-更新済み-準備完了-ポッド: "2"

不要なイメージのプルを回避するために、自動プレウォーミングは現在、レプリカが 3 を超える CloneSet に対してのみ実行されることに注意してください。

さらに、CloneSet はバッチ グレースケールもサポートします。 updateStrategy​ プロパティでは、古いバージョンの Pod の数または割合を保持するために使用できるパーティション パラメータを設定できます。デフォルト値は 0 です。

  • 数値の場合、コントローラーは(レプリカ - パーティション)数のポッドを最新バージョンに更新します。
  • パーセンテージの場合、コントローラーは (レプリカ * (100% - パーティション)) 個のポッドを最新バージョンに更新します。

たとえば、上記の例のイメージを nginx:latest​ に更新し、partitinotallow=2 を設定します。更新後、アップグレードされたポッドは 2 つだけであることがわかります。

  kubectl get pods -l app = cs -Lコントローラー-リビジョン-ハッシュ
名前準備完了ステータス再起動年齢コントローラ-改訂-ハッシュ
cs -デモ- 2 sfzz 1 / 1実行中1 ( 11) 47cs -デモ- 7 cb9c88699
cs -デモ- jfx5s 1 / 1実行中2 ( 99) 52cs -デモ- 7 c4d79f5bc
cs -デモ- kg9p2 1 / 1実行中2 ( 27) 52cs -デモ- 7 c4d79f5bc
cs -デモ- x8ndf 1 / 1実行中1 ( 10) 48cs -デモ- 7 cb9c88699
kubectl get pods - o custom - columns = 'DATA:metadata.name,CONTAINERS:spec.containers[*].name,IMAGES:spec.containers[*].image' - l app = cs
データコンテナ画像
cs -デモ- 2 sfzz nginx nginx : 1.7 .9
cs -デモ- jfx5s nginx nginx :最新
cs -デモ- kg9p2 nginx nginx :最新
cs -デモ- x8ndf nginx nginx : 1.7 .9

さらに、CloneSet は、Pod リリースの優先ルールを制御するための優先ポリシーの定義、Pod のタイプをリリース プロセス全体に分割するためのポリシーの定義、Pod リリースやその他の操作の一時停止など、より高度な使用法もサポートしています。

ライフサイクルフック

CloneSet によって管理される各 Pod にはクリアな状態があり、これは Pod ラベルの lifecycle.apps.kruise.io/state にマークされます。

  • 正常: 通常の状態。
  • PreparingUpdate: インプレース アップグレードの準備をしています。
  • 更新中: インプレースアップグレード中。
  • 更新: インプレース アップグレードが完了しました。
  • PreparingDelete: 削除の準備をしています。

ライフサイクル フックは、上記の状態フローのポイントをブロックすることによって、インプレース アップグレードの前後および削除の前にカスタム操作 (トラフィックの切り替え、アラームなど) を実装します。 CloneSet ライフサイクルは、主に preDelete と inPlaceUpdate の 2 つのプロパティをサポートします。

 apiバージョン:アプリクルーズio / v1alpha1
種類: CloneSet
仕様:

#ファイナライザを介してフックを定義する
ライフサイクル
preDelete : # PreDeletePodが削除される前のフックです
ファイナライザーハンドラー:
-.io /未準備-ブロッカー
inPlaceUpdate : # InPlaceUpdate はPod更新の前後のフックです
ファイナライザーハンドラー:
-.io /未準備-ブロッカー

#またはラベル定義することもできます
ライフサイクル
インプレースアップデート:
ラベルハンドラ:
.io / block -未準備: "true"

アップグレードまたは削除する前にポッドを NotReady に設定する

ライフサイクル
事前削除:
markPodNotReady : true
ファイナライザーハンドラー:
-.io /未準備-ブロッカー
インプレースアップデート:
markPodNotReady : true
ファイナライザーハンドラー:
-.io /未準備-ブロッカー
  • preDelete.markPodNotReady=true を設定した場合:
  • Pod が PreparingDelete 状態に入ると、Kruise は KruisePodReady Pod Condition を False に設定し、Pod は NotReady になります。
  • inPlaceUpdate.markPodNotReady=true を設定した場合:
  • Pod が PreparingUpdate 状態に入ると、Kruise は KruisePodReady Pod Condition を False に設定し、Pod は NotReady になります。

  • Kruise は、KruisePodReady Pod Condition を True に戻そうとします。

この機能を使用すると、コンテナが実際に停止する前にポッド上のトラフィックを除外して、トラフィックの損失を防ぐことができます。

フロー図

ライフサイクル図

  • CloneSet が Pod を削除する場合 (通常のスケールダウン、再構築、アップグレードを含む) :
  • ライフサイクル フックが定義されていない場合、または Pod が preDelete 条件を満たしていない場合は、直接削除されます。
  • それ以外の場合は、まず Pod のステータスを PreparingDelete に変更します。 Kruise は、ユーザー コントローラーがタスクを完了し、ラベル/ファイナライザーを削除し、Pod が preDelete 条件を満たさない場合にのみ、Pod を削除します。
  • PreparingDelete 状態の Pod は削除フェーズにあり、アップグレードされないことに注意してください。
  • CloneSet が Pod をインプレースでアップグレードする場合:
  • アップグレードする前に、ライフサイクルフックが定義されていて、PodがinPlaceUpdate条件を満たしている場合は、PodのステータスをPreparingUpdateに変更します。

  • ユーザー コントローラーがタスクを完了してラベル/ファイナライザーを削除し、Pod が inPlaceUpdate 条件を満たさない場合、kruise は Pod のステータスを Updating に変更し、アップグレードを開始します。

  • アップグレードが完了した後、ライフサイクルフックが定義されていて、PodがinPlaceUpdate条件を満たしていない場合は、PodのステータスをUpdatedに変更します。

  • ユーザー コントローラーがタスクを完了してラベル/ファイナライザーを追加し、Pod が inPlaceUpdate 条件を満たすと、kruise は Pod のステータスを Normal に変更し、アップグレードが成功したと判断します。

PreparingDelete から Normal 状態に戻ることについては、設計上サポートされています (指定された削除を元に戻すことによって) が、通常、この使用方法はお勧めしません。 PreparingDelete 状態の Pod はアップグレードされないため、Normal 状態に戻った後すぐに再びリリース フェーズに入る可能性があり、ユーザーにとってフックの処理が難しい問題となります。

ユーザーコントローラロジックの例

上記の例に従って、次のように定義できます。

  • example.io/unready-blocker ファイナライザーをフックとして使用します。
  • 初期化アノテーションとして example.io/initialing アノテーションを使用します。

CloneSet テンプレートに次のフィールドを追加します。

 apiバージョン:アプリクルーズio / v1alpha1
種類: CloneSet
仕様:
テンプレート
メタデータ:
注釈:
.io /初期化中: "true"
ファイナライザー:
-.io /未準備-ブロッカー
# ...
ライフサイクル
事前削除:
ファイナライザーハンドラー:
-.io /未準備-ブロッカー
インプレースアップデート:
ファイナライザーハンドラー:
-.io /未準備-ブロッカー

ユーザー コントローラーのロジックは次のようになります。

  • Normal 状態の Pod の場合、アノテーションに example.io/initialing: true が含まれており、Pod ステータスの準備完了条件が True の場合、トラフィックが接続され、アノテーションは削除されます。
  • PreparingDelete および PreparingUpdate 状態の Pod の場合、トラフィックは切断され、example.io/unready-blocker ファイナライザーは削除されます。
  • 更新状態の Pod の場合は、トラフィックを許可し、example.io/unready-blocker ファイナライザーを追加します。

使用シナリオ

さまざまな歴史的理由や客観的な要因により、一部のユーザーは自社のシステム アーキテクチャ全体を Kubernetes 化できない場合があります。たとえば、一部のユーザーは、Kubernetes 自体が提供するサービス検出メカニズムを一時的に使用できず、代わりに Kubernetes とは独立した別のサービス登録および検出システムを使用します。このアーキテクチャでは、ユーザーがサービスを Kubernetes に変換すると、多くの問題が発生する可能性があります。たとえば、Kubernetes が Pod を正常に作成するたびに、内部および外部にサービスを提供できるように、その Pod をサービス検出センターに登録する必要があります。同様に、Pod をオフラインにする場合は、通常、Pod を正常にオフラインにする前に、まずサービス検出センターから削除する必要があります。そうしないと、トラフィック損失が発生する可能性があります。ただし、ネイティブ Kubernetes システムでは、Pod のライフサイクルはワークロード (デプロイメントなど) によって管理されます。これらのワークロードのレプリカ フィールドが変更されると、対応するコントローラーはすぐにポッドを追加または削除するため、ユーザーがポッドのライフサイクルの管理をカスタマイズすることが難しくなります。

この問題には、一般的に 2 つの解決策があります。1 つは、Kubernetes の弾力性を制限することです。たとえば、ワークロードを特定のリンクでのみスケールアップまたはスケールダウンできるように規定して、Pod が削除される前に Pod IP がサービス レジストリから削除されるようにします。しかし、これにより Kubernetes 自体の弾力性が制約され、リンク管理の難しさやリスクが増大します。 2 つ目は、既存のサービス検出システムを根本的に変革することですが、これは明らかにより時間がかかり、リスクの高い作業です。

CloneSet ライフサイクル変換

では、既存のサービス検出システムの変換を回避しながら Kubernetes の弾力性を最大限に活用し、2 つのシステム間のギャップを迅速に埋める方法はあるのでしょうか?

OpenKruise CloneSet は、このようなシナリオに特化して対処するための高度にカスタマイズ可能な拡張機能のセットを提供し、ユーザーが Pod ライフサイクルのより洗練されたカスタマイズされた管理を実行できるようにします。 CloneSet は、Pod ライフサイクルのいくつかの重要な時点でフックを予約し、ユーザーがこれらの時点でカスタマイズされた拡張アクションを挿入できるようにします。たとえば、Pod をアップグレードする前に、サービス検出センターで Pod IP を削除し、アップグレードが完了した後に Pod IP をサービス検出センターに登録するか、特別なスニッフィングおよび監視アクションを実行します。

次のようなシナリオがあると仮定しましょう。

  • ユーザーは Kubernetes Service をサービス検出メカニズムとして使用しません。サービス検出システムは Kubernetes から完全に独立しています。
  • CloneSet を Kubernetes ワークロードとして使用します。

そして、具体的なニーズについて、次のような合理的な仮定を立てます。

  • Kubernetes Pod が作成されると、次のようになります。
  • 作成が成功し、ポッドの準備が整うと、ポッド IP がサービス検出センターに登録されます。
  • Kubernetes Pod がインプレースでアップグレードされると、次のようになります。
  • アップグレードする前に、サービス検出センターから Pod IP を削除する (またはアクティブにフェイルオーバーする) 必要があります。

  • アップグレードが完了し、ポッドの準備ができたら、ポッド IP をサービス検出センターに再度登録します。

  • Kubernetes Pod が削除されると:

  • 削除する前に、サービス検出センターから Pod IP を削除する必要があります。

上記の前提に基づいて、実際に CloneSet LifeCycle を使用して、ユーザー定義の Pod ライフサイクル管理メカニズムを実装する単純な Operator を作成できます。

先ほど、CloneSet LifeCycle は Pod のライフサイクルを 5 つの状態に定義し、5 つの状態間の遷移ロジックはステート マシンによって制御されることを説明しました。関心のあるノードを 1 つ以上選択し、独立した Operator を記述してこれらの状態の遷移を実装し、Pod のライフサイクルを制御し、関心のあるノードに独自のカスタマイズされたロジックを挿入することができます。

 apiバージョン:アプリクルーズio / v1alpha1
種類: CloneSet
メタデータ:
名前空間:デモ
名前:クローンセット-ライフサイクル-デモ
仕様:
レプリカ2
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
##ライフサイクル構成
ライフサイクル
インプレースアップデート:
ラベルハンドラ:
##タグを定義する:
# # 1.クローンセットコントローラインプレースPod更新を防止する
# # 2.オペレータにinPlace更新フックを実行するように通知する
.com / unready - blocker - inplace : "true"
事前削除:
ラベルハンドラ:
##タグを定義する:
# # 1.クローンセットコントローラポッド削除を防止する
# # 2.オペレータにpreDeleteフックを実行するよう通知する
.com / unready - blocker - delete : "true"
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
セレクター:
マッチラベル:
アプリ: nginx
テンプレート
メタデータ:
ラベル:
アプリ: nginx
# #このラベルは、このポッドが新しく作成されたかどうかを判断するために使用できます
.com / new - create : "true"
# #仕様対応します。ライフサイクルinPlaceUpdateラベル ハンドラcom /未準備-ブロッカー-インプレース
.com / unready - blocker - inplace : "true"
# #仕様に準拠しています。ライフサイクル事前削除ラベル ハンドラcom /未準備-ブロッカー-インプレース
.com / unready - blocker - delete : "true"
コンテナ:
-名前:メイン
画像: nginx :最新
imagePullPolicy :常に
更新戦略:
最大利用不可: 20 %
タイプ: InPlaceIfPossible

前の CRD の章では、Operator の開発方法について説明しました。ここでは詳細には触れません。コントローラーのコアコードは次のとおりです。

定数(
deleteHookLabel = "example.com/unready-blocker-delete"
inPlaceHookLabel = "example.com/unready-blocker-inplace"
newCreatElabel = "Example.com/newly-create"


funcr * samplereconcinerreconcile reqctrl。request ctrl。resulterror {
... ...

switchlabel= func pod * v1。podkeyvalue stringerror {
ボディ= fmtsprintf` { " metadata " :{ " labels " :{ "%s ""%s " }}} `keyvalue
err = rPatchContext。Todo ()、 PodClient。RawPatchTypes。StrategicMergePatchType 、[ ] bytebody ;エラー!=ゼロ{
エラーを返す
}
ゼロを返す
}

/*
ポッドライフサイクルフックロジック
*/
スイッチ{
//新しく作成されたポッドを処理します
ケースISNewlyCreateHookedPOD ):
//このポッドをサービスディスカバリーセンターに登録します
err= posttregistrypod;エラー!=ゼロ{
retuncileを返します結果{}、 err
}
err= switchlabelpodnewlycreatelabel"false";エラー!=ゼロ{
retuncileを返します結果{}、 err
}

//インプレースアップグレードの準備ができているポッドを処理する
ケースISPREUPDATEHOOKEDPOD ):
//サービスディスカバリーセンターにこのポッドを失敗させます
err= postfailoverpod;エラー!=ゼロ{
retuncileを返します結果{}、 err
}
err= switchlabelpodinplacehooklabel"false";エラー!=ゼロ{
retuncileを返します結果{}、 err
}

//アップデートが完了した後、PODを処理します
case isUpdatedhookedpod ):
//サービスディスカバリーセンターにポッドを再登録させます
err= posttregistrypod;エラー!=ゼロ{
retuncileを返します結果{}、 err
}
err= switchlabelpodinplacehooklabel"true";エラー!=ゼロ{
retuncileを返します結果{}、 err
}

//削除するポッドを処理します
ケースISPREDELETEHOOKEDPOD ):
//サービスディスカバリーセンターのポッドを解除します
err= postunregisterpod;エラー!=ゼロ{
retuncileを返します結果{}、 err
}
err= switchlabelpoddeletehooklabel"false";エラー!=ゼロ{
retuncileを返します結果{}、 err
}
}

ctrlを返します結果{}、 nil
}

func isnewlycreatehooked pod * v1。podbool {
Kruiseappspubを返しますlifecyclestateType pod。labels [ kruiseappspub。lifecyclestatekey ]) == kruiseappspubライフサイクルスタテンモルマル&&ポッドラベル[ NewlyCreatelabel ] == "True" && isPodReadyPOD
}

func ispreupdatehooked pod * v1。podbool {
Kruiseappspubを返しますlifecyclestateType pod。labels [ kruiseappspub。lifecyclestatekey ]) == kruiseappspublifecyclestatepreparingupdate && podラベル[ inplacehooklabel ] == "true"
}

func isupdatedhooked pod * v1。podbool {
Kruiseappspubを返しますlifecyclestateType pod。labels [ kruiseappspub。lifecyclestatekey ]) == kruiseappspublifecyclestateUpdated && podラベル[ inplacehooklabel ] == "false" && ispodreadypod
}

func ispredeletehooked pod * v1。podbool {
Kruiseappspubを返しますlifecyclestateType pod。labels [ kruiseappspub。lifecyclestatekey ]) == kruiseappspublifecyclestatepreparingdelete && podラベル[ deletehooklabel ] == "true"
}

上記のコードでは、4つの分岐は、対応するポッドの4つの重要な宣言サイクルサイクルノード、つまり作成後、アップグレード前、削除前に対応します。実際のニーズに応じて、対応するフックを改善できます。上記のフックの動作は具体的には次のとおりです。

  • Postregistry(POD *V1.POD):PODサービスを登録するために、リクエスト通知サービスディスカバリーセンターを送信します。
  • PostFailover(POD *V1.POD):リクエスト通知サービスディスカバリーセンターを送信このPODサービスに失敗します。
  • Postunregiste(pod *v1.pod):リクエスト通知サービスディスカバリーセンターを送信して、ポッドサービスからログアウトします。

これがクローンセットライフサイクルの力です。ニーズに応じて、カスタマイズされたロジックをPODライフサイクル管理に完全に挿入できます。

<<:  エッジコンピューティングと5Gが将来の電力網をどう形作るのか

>>:  2023 年にクラウド コンピューティング テクノロジーはどのように発展するでしょうか?

推薦する

起業家精神の共有: Instagram がユーザーの心をつかむ方法

Zhihu には興味深い質問があります。「パソコンの電源を入れるとすぐに QQ を開かずにはいられま...

ウェブサイトの最適化は模倣や盗作ではなく、成功の鍵は分析にあります(パート 1)

中国の古代の教育モデルでは、教師が教壇で講義し、生徒がステージの下でメモを取るというパターンがよく見...

Google アナリティクスの新しいユーザー インターフェース分析の最近の改善点

今日、GA の新しいユーザー インターフェイスに皆さんが注目したと思います。以前と比較すると、アイコ...

エッジコンピューティングの3つの主なメリット

クラウドの登場と大規模な導入以来、企業はさまざまなデジタル変革の段階にあります。すべてのデータをクラ...

大きな記事を掲載した小さなブログは、あなたのビジネスを即座に強化することができます

私たちは、自分自身の楽しみのためにブログを書いているのではありません。ブログを書いた後、私たちのブロ...

anynode: 年間 12 ドル、現在 cn2 gia ネットワークを使用する最も安価な VPS

anynode、最新のホットニュース(中国で初公開):ロサンゼルスのコンピュータルームのKVM仮想V...

A5とchinaz.comの提出物の違いを詳しく見る

草の根レベルで、私はウェブサイトを作る趣味があり、自分のウェブサイトを有名にして、もっと多くの人に知...

ウェブサイトのキーワードがランキングされた後、ランキングを維持する方法

ウェブサイトをランク付けするのは実はとても簡単です。現在、多くの新しいウェブサイトは、価値あるコンテ...

SEO最適化のワークフローの詳細説明:準備

SEO 最適化担当者にとって、最適化は盲目的に行われるものではなく、計画的に実施されるものです。まず...

災害復旧のためにクラウドを導入する企業向けの 3 つのヒント

毎年多くの自然災害が発生しているため、多くの企業は自社の災害復旧方法が効果的かどうか、また自社の計画...

これら4つのポイントをマスターすれば、キーワードの選択に悩む必要はありません

キーワードの選択は、SEO 担当者をテストする重要な要素です。キーワードの難易度、キーワードのレイア...

インターネットマーケティングの理論はたくさんあるのに、なぜうまくできないのでしょうか?

月収10万元の起業の夢を実現するミニプログラム起業支援プランインターネットマーケティングは急速に成長...

企業はどのように独自のコミュニティを構築すべきでしょうか?これらの経験が役に立ちます

2018年最もホットなプロジェクト:テレマーケティングロボットがあなたの参加を待っています1. コミ...

業界ドメイン名の伝説:DVD.com が外国の映画レンタル会社に買収される

ドメイン名ニュース: 昨日、オンライン映画レンタルサービスプロバイダーである Netflix のトッ...

初心者のためのウェブサイト診断レポートの書き方

先日書いた「Webサイト診断レポートの鉄則14か条(前編)」が皆様に好評をいただいており、大変嬉しく...