DUICUO

Kubernetesのワークロード管理についてお話しましょう

Kubernetes では、Pod は管理の最小単位で、緊密に接続されたコンテナのグループです。

しかし、スタンドアロンのPodでは可用性を保証できません。例えば、nginx Podを作成した後、何らかの理由で誤って削除された場合、同じ属性を持つ新しいPodを自動的に作成する必要があります。しかし、残念ながら、シンプルなPodではこの要件を満たすことができません。

これに対処するため、Kubernetes は Pod を管理するための一連のコントローラーを実装し、Pod の期待状態と実際の状態が一致するようにします。一般的に使用されるコントローラーには以下が含まれます。

  • 展開
  • ステートフルセット
  • デーモンセット
  • ジョブ/CronJob

このセクションでは、デプロイメント、デーモンセット、ジョブ/クロンジョブについてのみ説明します。StatefulSet は、サービス、PV/PVC など、他の多くの概念に関係するため、 ​Kubernetes有状态应用管理​セクションで後ほど説明します。これらの概念を説明した後に、StatefulSet について説明することをお勧めします。

展開

デプロイメントについて説明する前に、まず ReplicaSet (RS) について理解しましょう。

Kubernetesの初期には、レプリケーションコントローラー(RC)がポッドを制御し、ユーザーの期待通りに動作することを保証するために使用されていました。しかし、RCは後に様々な理由から段階的に廃止され、レプリケーションコントローラー(RS)に置き換えられました。機能的にはRCとRSに大きな違いはありません。唯一の違いは、RSがコレクションセレクターをサポートし、より複雑な条件を定義できることです。

感覚をつかむために、簡単な ReplicaSet を定義してみましょう。

 apiバージョン: アプリ/ v1
種類: レプリカセット
メタデータ
名前: nginx - セット
ラベル:
アプリ: nginx
仕様:
レプリカ2
セレクター:
マッチラベル
アプリ: nginx
テンプレート
メタデータ
名前: nginx
ラベル:
アプリ: nginx
仕様:
コンテナ
- 名前: nginx
画像: nginx

作成結果は以下のとおりです。

 $ kubectl でpo を取得
名前準備完了ステータス再起動年齢
nginx - セット- hmtq4 0/1 コンテナ作成0 2
nginx - set - j2jpr 0/1 ContainerCreating 0 2 s
$ kubectl でrs を取得する
名前希望現在の年齢準備年齢
nginx - 2 2 0 5 を設定

ご覧の通り、 replicas: 2 は2つのPodを作成することを期待しています。そのため、 kubectl get pod を実行すると、2つのPodが作成されていることがわかります。Podを削除すると、RSは期待どおりにすぐに新しいPodをプルします。

しかし、実際にはリソースリスト(RS)が直接使用されることはほとんどなく、代わりにデプロイメントが使用されます。デプロイメントはRSよりも上位のリソースオブジェクトであり、以下のようにRSを制御および管理します。

上の図に示すように、Deployment、ReplicaSet、およびPodは階層的な制御関係にあります。Deploymentは複数のReplicaSetを持つことができ、ReplicaSetは複数のPodを持つことができます。Deploymentが複数のReplicaSetを持つことができる主な理由は、ロールバック操作をサポートするためです。Deploymentが操作されるたびに新しいReplicaSetが作成され、新しいPodが徐々に更新されます。古いReplicaSetのPod数は徐々に減少し、最終的には新しいReplicaSetが完全に引き継ぎます。このプロセスでは古いReplicaSetは削除されず、将来のロールバックで使用するためにシステムによって保存されます。

ReplicaSetは、「コントローラパターン」を通じて、システム内のPod数が常に期待値と一致するようにする役割も担っています。これが、DeploymentでrestartPolicy=Alwaysのみが許可される理由でもあります。コンテナが常に実行状態にあることを保証できる場合にのみ、ReplicaSetを通じてPod数を調整する意味があるからです。

これを基に、Deployment は「コントローラーパターン」を使用して ReplicaSet の数と属性を操作し、水平方向のスケーリング/縮小とローリングアップデートを実装します。水平方向のスケーリングと縮小は非常に簡単に実装でき、Deployment コントローラーは ReplicaSet 内の Pod レプリカの数を変更するだけで済みます。

以下はデプロイメントを作成するための項目のリストです。

 apiバージョン: アプリ/ v1
種類: デプロイメント
メタデータ
名前: nginx - デプロイメント
ラベル:
アプリ: nginx
仕様:
レプリカ3
セレクター:
マッチラベル
アプリ: nginx
テンプレート
メタデータ
ラベル:
アプリ: nginx
仕様:
コンテナ
- 名前: nginx
画像: nginx

起動後、次の情報が表示されます。

 $ kubectl でデプロイメント.apps を取得します
名前準備完了最新利用可能年齢
nginx - デプロイメント3/3 3 3 19
$ kubectl でrs を取得する
名前希望現在の年齢準備年齢
nginx - デプロイメント- 8f 458 dc5b 3 3 3 21 s
$ kubectl でpo を取得
名前準備完了ステータス再起動年齢
nginx - デプロイメント- 8f 458 dc5b - 8 nn5c 1 / 1 実行中0 24
nginx - デプロイメント- 8f 458 dc5b - hxc57 1 / 1 実行中0 24
nginx - デプロイメント- 8f 458 dc5b - znrff 1 / 1 実行中0 24

上記の情報からわかるように、Deployment オブジェクトが作成されると、RS オブジェクトが自動的に作成され、その後、RS オブジェクトを通じて対応する数の Pod が作成されます。

水平方向の拡大/縮小

上記では、3つのレプリカを持つポッドを作成しました。このポッドを拡張/縮小する必要がある場合は、以下の3つの方法で行うことができます。

  • `kubectl scale` コマンド。
  • kubectl は実行中のデプロイメントを編集します。
  • YAML マニフェストを変更し、kubectl apply を使用して更新します。

使用する具体的な方法は状況によって異なります。

1. kubectl scale コマンドを使用してスケールする

拡張と縮小のコマンドは同じです。拡張するとレプリカの数が増え、縮小するとレプリカの数が減ります。

(1)現在の3つのレプリカを拡張して4つのレプリカが必要な場合は、次のコマンドを使用します。

 $ kubectl スケールデプロイメントnginx - デプロイメント-- レプリカ4
デプロイメント.apps / nginx - デプロイメントのスケール

ご覧のとおり、ポッドの数は 4 に増加しました。

 $ kubectl でpo を取得
名前準備完了ステータス再起動年齢
nginx - デプロイメント- 8f 458 dc5b - 8 nn5c 1 / 1 実行中0 8 m3s
nginx - デプロイメント- 8f 458 dc5b - cv6mw 1 / 1 実行中0 29
nginx - デプロイメント- 8f 458 dc5b - hxc57 1 / 1 実行中0 8 m3s
nginx - デプロイメント- 8f 458 dc5b - znrff 1 / 1 実行中0 8 m3s

(2) 縮小 現在、クラスタには4つのレプリカがあります。レプリカを2つだけ必要な場合は、以下のコマンドを使用します。

 $ kubectl スケールデプロイメントnginx - デプロイメント-- レプリカ2
デプロイメント.apps / nginx - デプロイメントのスケール

現在、クラスターには 2 つの Pod のみがあります。

 $ kubectl でpo を取得
名前準備完了ステータス再起動年齢
nginx - デプロイメント- 8f 458 dc5b - 8 nn5c 1 / 1 実行中0 9 分36秒
nginx - デプロイメント- 8f 458 dc5b - hxc57 1 / 1 実行中0 9 分36秒

2. kubectl edit を使用してデプロイメントを直接編集する

次のように、kubectl edit を使用して実行中のデプロイメントを直接編集し、レプリカ数を変更することもできます。

 $ kubectl edit デプロイメント. apps nginx - デプロイメント- oyaml

編集インターフェースは次のとおりです。

変更を加えたら、`:wq` で保存して終了します。すると、レプリカの数が 4 に戻っていることがわかります。

 $ kubectl でpo を取得
名前準備完了ステータス再起動年齢
nginx - デプロイメント- 8f 458 dc5b - 8 nn5c 1 / 1 実行中0 14
nginx - デプロイメント- 8f 458 dc5b - hxc57 1 / 1 実行中0 14
nginx - デプロイメント- 8f 458 dc5b - mq69h 1 / 1 実行中0 92
nginx - デプロイメント- 8f 458 dc5b - xktq2 1 / 1 実行中0 92

3. `kubectl apply` を使用してローカル YAML ファイルを更新します。

ローカル YAML ファイルを直接変更してコピー数を調整することもできます。たとえば、YAML ファイルでコピー数を直接 2 に変更します。

 apiバージョン: アプリ/ v1
種類: デプロイメント
メタデータ
名前: nginx - デプロイメント
ラベル:
アプリ: nginx
仕様:
レプリカ2
セレクター:
マッチラベル
アプリ: nginx
テンプレート
メタデータ
ラベル:
アプリ: nginx
仕様:
コンテナ
- 名前: nginx
画像: nginx

その後、kubectl apply -f nginx.yaml を使用して直接デプロイできます。

ローリングアップデート/ロールバック

ビジネスアプリケーションは、ほとんどの場合、デプロイメントを介してKubernetes上にデプロイされます。アプリケーションの更新とロールバックは、特に迅速な反復がユーザー獲得に不可欠なインターネット企業では日常的なタスクです。

ただし、すべての反復が 100% 成功するとは限らず、異常から迅速に回復する方法も考慮する必要があります。

このシナリオに適応するために、デプロイメントではローリング アップデートとクイック ロールバックを実行する機能が提供されます。

ローリングアップデート

デプロイメントのデフォルトの更新方法はローリング更新ですが、strategy.type を使用して更新方法を指定できます。

  • 再作成: 最初にすべてのポッドを削除してから、再作成します。
  • RollingUpdate: 最初に新しい Pod を起動し、次に古い Pod を置き換えます。

更新方法を変更するには、次のように設定します。

 apiバージョン: アプリ/ v1
種類: デプロイメント
メタデータ
名前: nginx - デプロイメント
ラベル:
アプリ: nginx
仕様:
...
戦略
タイプ: ローリングアップデート
ローリングアップデート:
最大サージ1
最大利用不可: 1

例:

(1) maxSurge: DESIREDの数に加えて、1回のローリングアップデート中にデプロイメントが作成できるPodの数を定義します。

(2) maxUnavailable: ローリングアップデート中にデプロイメントが削除できるポッドの最大数を定義します。さらに、これら2つの構成はパーセンテージで表すこともできます。

一般的には、本番環境で最もよく使用されるデフォルトの更新方法をそのまま使用すれば十分です。

それでは、ローリングアップデートの効果を確認してみましょう。まず、以下のようにnginxアプリケーションを作成します。

 apiバージョン: アプリ/ v1
種類: デプロイメント
メタデータ
名前: nginx - デプロイメント
ラベル:
アプリ: nginx
仕様:
レプリカ3
セレクター:
マッチラベル
アプリ: nginx
テンプレート
メタデータ
ラベル:
アプリ: nginx
仕様:
コンテナ
- 名前: nginx
画像: nginx : 1.8

次に、`kubectl apply -f deploy.yaml` を使用し、`kubectl get po -w` を使用してアップグレードの効果を確認します。

別のシェル ウィンドウを開き、次のコマンドを使用してアプリケーションを更新します。

 $ kubectl patch デプロイメントnginx - デプロイメント-- パッチ'{"spec": {"template": {"spec": {"containers": [{"name": "nginx","image":"nginx:1.9"}]}}}'

以下のように、別のウィンドウでアップグレード プロセスを表示できます。

 $ kubectl get po -w 
名前準備完了ステータス再起動年齢
nginx - デプロイメント- 6 c74f576b9 - h565l 1 / 1 実行中0 22
nginx - デプロイメント- 6 c74f576b9 - k65q6 1 / 1 実行中0 22
nginx - デプロイメント- 6 c74f576b9 - qr2xc 1 / 1 実行中0 22
nginx - デプロイメント- 778 d9f5866 - n69qd 0 / 1 保留中0 0
nginx - デプロイメント- 778 d9f5866 - n69qd 0 / 1 保留中0 0
nginx - デプロイメント- 778 d9f5866 - n69qd 0/1 コンテナ作成0 0
nginx - デプロイメント- 778 d9f5866 - n69qd 0/1 コンテナ作成0 0
nginx - デプロイメント- 778 d9f5866 - n69qd 1 / 1 実行中0 41
nginx - デプロイメント- 6 c74f576b9 - qr2xc 1/1 終了中0 3 分23 秒
nginx - デプロイメント- 778 d9f5866-42 vhv 0/1 保留中0 0 s
nginx - デプロイメント- 778 d9f5866-42 vhv 0/1 保留中0 0 s
nginx - デプロイメント- 778 d9f5866-42 vhv 0/1 ContainerCreating 0 0 s
nginx - デプロイメント- 778 d9f5866-42 vhv 0/1 ContainerCreating 0 1 s
nginx - デプロイメント- 6 c74f576b9 - qr2xc 1/1 終了中0 3 分24 秒
nginx - デプロイメント- 6 c74f576b9 - qr2xc 0/1 終了中0 3 分24 秒
nginx - デプロイメント- 778 d9f5866-42 vhv 1 / 1 実行中0 1
nginx - デプロイメント- 6 c74f576b9 - k65q6 1 / 1 終了中0 3 分24秒
nginx - デプロイメント- 778 d9f5866 - tndn8 0/1 保留中0 0
nginx - デプロイメント- 778 d9f5866 - tndn8 0/1 保留中0 0
nginx - デプロイメント- 778 d9f5866 - tndn8 0/1 コンテナ作成0 0
nginx - デプロイメント- 6 c74f576b9 - k65q6 1 / 1 終了中0 3 分24秒
nginx - デプロイメント- 6 c74f576b9 - qr2xc 0/1 終了中0 3 分24 秒
nginx - デプロイメント- 6 c74f576b9 - qr2xc 0/1 終了中0 3 分24 秒
nginx - デプロイメント- 778 d9f5866 - tndn8 0/1 コンテナ作成0 0
nginx - デプロイメント- 6 c74f576b9 - k65q6 0/1 終了中0 3 分 25 秒
nginx - デプロイメント- 6 c74f576b9 - k65q6 0/1 終了中0 3 分 25 秒
nginx - デプロイメント- 6 c74f576b9 - k65q6 0/1 終了中0 3 分 25 秒
nginx - デプロイメント- 778 d9f5866 - tndn8 1 / 1 実行中0 1
nginx - デプロイメント- 6 c74f576b9 - h565l 1 / 1 終了中0 3 分25秒
nginx - デプロイメント- 6 c74f576b9 - h565l 1 / 1 終了中0 3 分25秒
nginx - デプロイメント- 6 c74f576b9 - h565l 0/1 終了中0 3 分 26 秒
nginx - デプロイメント- 6 c74f576b9 - h565l 0/1 終了中0 3 分 26 秒
nginx - デプロイメント- 6 c74f576b9 - h565l 0/1 終了中0 3 分 26 秒

古いバージョンはnginx-deployment-6c74f576b9-*、新しいバージョンはnginx-deployment-778d9f5866-*です。まず新しいバージョンのPodが作成され、その後古いバージョンのPodが削除されます。このプロセスは、すべての古いバージョンが置き換えられるまで継続されます。

基本的なロジックは、Deployment を通じて新しい ReplicaSet を作成し、その新しい ReplicaSet を通じて新しい Pod を作成することです。これは​kubectl get rs​で確認できます。

 $ kubectl でrs を取得する
名前希望現在の年齢準備年齢
nginx - デプロイメント- 6 c74f576b9 0 0 0 9 分49秒
nginx - デプロイメント- 778 d9f5866 3 3 3 7 m7s

このローリング アップデートの利点は、アップデート プロセス中に新しいバージョンの Pod に問題が発生した場合、ローリング アップデートが停止することです。この時点で、運用チームと開発チームが介入して原因を調査できます。アプリケーションにはまだ 2 つの古いバージョンの Pod がオンラインになっているため、サービスに大きな影響を与えることはありません。もちろん、この場合、コンテナの実行状態に単に依存するのではなく、アプリケーションのヘルス ステータスを確認するために、Pod にヘルス チェックを追加する必要があります。サービスの継続性をさらに確保するために、デプロイメント コントローラは、特定の時間枠内で指定された割合の Pod のみがオフラインになるようにし、また、特定の時間枠内で指定された割合の Pod のみが作成されるようにします。この割合は、デフォルトでは DESIRED Pod の 25% です。

もちろん、Deployment オブジェクトの RollingUpdateStrategy というフィールドを変更することでカスタマイズできます。次に例を示します。

 apiバージョン: アプリ/ v1
種類: デプロイメント
メタデータ
名前: nginx - デプロイメント
ラベル:
アプリ: nginx
仕様:
...
戦略
タイプ: ローリングアップデート
ローリングアップデート:
最大サージ1
最大利用不可: 1

例:

(1) maxSurge: DESIRED Podの数に加えて、1回のローリングアップデート中にデプロイメントが作成できるPodの数を定義します。

(2) maxUnavailable: ローリングアップデート中にデプロイメントが削除できるポッドの最大数を定義します。さらに、これら2つの構成はパーセンテージで表すこともできます。

したがって、次の関係図が得られます。

レプリカセットの数と各レプリカセットの属性は、デプロイメントによって実際に制御されます。アプリケーションのバージョンは1つのレプリカセットに対応し、各バージョンが持つべきポッドの数は、レプリカセット自身のコントローラーによって管理されます。

ロールバック

アップデートがあり、ロールバックがあり、彼らは運命的に引き裂かれた恋人同士です。

Kubernetesでは、ロールバックは`kubectl rollout`コマンドを使用して実行されます。ローリングアップデートのセクションでは、Nginxアプリケーションを更新しました。新しいバージョンに問題がある場合は、ロールバックが必要になります。

(1)ロールバック可能な過去のバージョンを表示する

 $ kubectl ロールアウト履歴デプロイメントnginx - デプロイメント
deployment.apps / nginx - デプロイメント
改訂変更- 原因
1 < なし>
2 < なし>

2 つのバージョンがあることがわかりました。現在はバージョン 2 を使用しており、バージョン 1 にロールバックする必要があります。

(2)以下のコマンドを実行して古いバージョンにロールバックします。

 $ kubectl rollout undo デプロイメントnginx - デプロイメント-- to - リビジョン1
デプロイメント.apps / nginx - デプロイメントがロールバックれました

(3)RSをチェックして、古いバージョンにロールバックできるかどうかを確認します。

 $ kubectl でrs を取得する
名前希望現在の年齢準備年齢
nginx - デプロイメント- 6 c74f576b9 3 3 3 27 m
nginx - デプロイメント- 778 d9f5866 0 0 0 25

明示的に以前のバージョンにロールバックできる場合は、`kubectl rollout undo deployment nginx-deployment` を直接使用できます。

ロールバックは比較的簡単な操作ですが、リリースが頻繁に行われ、履歴データが特定のバージョン数(デフォルトでは 10 バージョン)を超えると、古いバージョンにロールバックできなくなります。

もちろん、次のように、デフォルトで 10 に設定されている spec.revisionHistoryLimit を定義することで、保持するバージョン番号の数を定義することができます。

 apiバージョン: アプリ/ v1
種類: デプロイメント
メタデータ
ラベル:
アプリ: nginx
名前: nginx - デプロイメント
仕様:
進捗期限秒数: 600
レプリカ3
改訂履歴制限: 10
セレクター:
マッチラベル
アプリ: nginx
戦略
ローリングアップデート:
最大サージ25
最大利用不可: 25 %
タイプ: ローリングアップデート
テンプレート
メタデータ
作成タイムスタンプ: null
ラベル:
アプリ: nginx
仕様:
コンテナ
- イメージ: nginx : 1.8
imagePullPolicy : IfNotPresent
名前: nginx
リソース: {}
終了メッセージパス: / dev / 終了- ログ
終了メッセージポリシー: ファイル
dnsポリシー: ClusterFirst
再起動ポリシー: 常に
schedulerName : デフォルト- スケジューラ
セキュリティコンテキスト: {}
終了猶予期間秒数: 30

上記は、デプロイメントのロールバック操作について説明しました。操作コマンドは比較的シンプルです。重要なのは、Kubernetesがこの機能を提供していることを理解し、不測の事態に備えることです。

要約

全文からわかるように、Deploymentは実際には2層のコントローラです。(1)ReplicaSetの数によってアプリケーションのバージョン数を記述します。(2)ReplicaSetの属性によってPodのレプリカ数を保証します。そして、Deploymentの柔軟な制御により、水平方向のスケール/縮小、ローリングアップデート、ロールバック操作の実行が容易になります。

デーモンセット

DaemonSet は、各ノードで Pod が実行されるようにします。新しいノードが追加されると、その Pod も新しいノードで実行されます。DaemonSet を削除すると、そのノードで作成されたすべての Pod が削除されます。DaemonSet は、クラスターのログ収集や監視などのグローバルアプリケーションのデプロイによく使用されます。

一般的なシナリオは次のとおりです。

1. Ceph や Glusterd などのストレージ クラスター デーモンを実行します。

2. Logstash や Fluentd などのログ収集デーモンを実行します。

3. Prometheus Node Exporter、collectd、New Relic エージェント、Ganglia gmond などの監視デーモンを実行します。

たとえば、Filebeat を実行する DaemonSet は次のように定義されます。

 apiバージョン: アプリ/ v1
種類: DaemonSet
メタデータ
名前: filebeat - ds
名前空間: デフォルト
仕様:
セレクター:
マッチラベル
アプリ: ファイルビート
役割: ログストレージ
テンプレート
メタデータ
ラベル:
アプリ: ファイルビート
役割: ログストレージ
仕様:
コンテナ
- 名前: ファイルビート
画像: ikubernetes / ファイルビート: 5.6 .5 - アルパイン
環境:
- 名前: REDIS_HOST
: redis.default.svc.cluster.local

実行後、次のように、Filebeat が kk-node01 ノード上で実行されていることがわかります。

 $ kubectl get po - o ワイド
名前準備完了ステータス再起動年齢IP ノード指名ノード準備完了ゲート
filebeat - ds - kgqcq 1 / 1 実行中0 28 172.16 .51 .212 kk - node01 < なし> < なし>

クラスター自体に 2 つのノードがあるのに、なぜ 1 つの Pod だけがデプロイされるのか疑問に思う人もいるかもしれません。

これは、マスター(コントロールノード)にテイント(汚染)があり、その上位の DaemonSet がこの汚染を許容しないため、スケジュールされなかったためです。具体的なスケジュール戦略については、Kubernetes のスケジュールと管理のセクションで説明します。

DaemonSet はアップデートとロールバックもサポートしており、具体的な操作は Deployment と似ているため、ここでは詳細には説明しません。

ただし、DaemonSet の更新戦略を導入する必要があります。現在、次の 2 つの更新戦略がサポートされています。

  • OnDelete: 先に削除し、後で起動します。これは、まず古いPodを削除してから新しいPodを起動することを意味します。この戦略では、更新プロセス中にノードが切断される可能性があります。
  • RollingUpdate: デプロイメント ローリング メソッドと同じローリング アップデートがデフォルトの戦略です。

ここで、rollingUpdate アップデート戦略について触れておきましょう。以前のバージョンの Kubernetes では、DaemonSet で実行できるノードは 1 つだけだったため、maxUnavailable のみが存在し、maxSurge はありませんでした。しかし、新しいバージョンでは、利用可能なノードの数を制御する maxSurge パラメータが導入されました。例えば、合計 100 ノードがあり、maxSurge が 30% に設定されている場合、少なくとも 30 ノードが利用可能になります。

ジョブ/CronJob

Kubernetesの主な役割は、Pod内のアプリケーションの長期的かつ安定した運用を確保することです。しかし、時には一度だけ実行して終了する「短期的な」タスクが必要になることもあります。このような場合、Deploymentなどのコントローラーではニーズを満たすことができません。Kubernetesは、このような要件を特に処理するためにJob Controllerを作成しました。

仕事

ジョブは、一度だけ実行されるタスクを処理します。1つ以上のバッチタスクの成功を保証します。具体的な構文は「kubectl explain job」で確認できます。

基本操作

ジョブを定義する構文は、デプロイメントやポッドの構文と似ています。以下はジョブを定義する簡単な例です。

 apiバージョン: バッチ/ v1
種類: 仕事
メタデータ
名前: ジョブ- デモ
名前空間: デフォルト
仕様:
テンプレート
メタデータ
名前: ジョブ- デモ
仕様:
コンテナ
- 名前: テスト- ジョブ
画像: Busybox
imagePullPolicy : IfNotPresent
指示
- 「/bin/sh」
- 「-c」
引数:
- "for i in $(seq 10); do echo $i; 完了"
再起動ポリシー: なし
バックオフ制限: 4

このジョブは、スクリプトを実行し、10回ループして結果を出力するだけです。このジョブは、`kubectl apply -f job-demo.yaml` を使用して以下のように作成されます。

 $ kubectl apply -f ジョブ- デモ.yaml 
job.batch / ジョブ- デモが作成されました

次に、次のように `kubectl logs` を使用してログ出力を表示できます。

 $ kubectl ログジョブ- デモ- wd67s

すべて期待通りに進んでいます。では、ジョブとポッドのステータスを見てみましょう。

 $ kubectl get jobs . バッチ
名前完了期間年齢
ジョブ- デモ1/1 23 112
$ kubectl でpo を取得
名前準備完了ステータス再起動年齢
ジョブ- デモ- wd67s 0 / 1 完了0 114

ジョブのステータスには、デプロイメントのような「Ready」というキーワードはなく、「COMPLETIONS」というキーワードが使用され、1/1 はジョブが完了したことを示します。ジョブによって制御されるポッドのステータスも「Completed」となり、このステータスはジョブが成功したことを示します。

成功した場合、ジョブのポッドは1回実行されて停止します。失敗した場合はどうなりますか?

次に、ジョブの YAML を次のように変更します。

 apiバージョン: バッチ/ v1
種類: 仕事
メタデータ
名前: ジョブ- デモ
名前空間: デフォルト
仕様:
テンプレート
メタデータ
名前: ジョブ- デモ
仕様:
コンテナ
- 名前: テスト- ジョブ
画像: Busybox
imagePullPolicy : IfNotPresent
指示
- 「/bin/sh」
- 「-c」
引数:
- 「xxxxx」
再起動ポリシー: なし
バックオフ制限: 4

実行後、以下に示すように、Pod が継続的に再構築されていることがわかります。

 $ kubectl でpo を取得
名前準備完了ステータス再起動年齢
ジョブ- デモ- kwsl8 0 / 1 エラー0 3
ジョブ- デモ- ltsvq 0 / 1 ContainerCreating 0 0
ジョブ- デモ- w54s4 0 / 1 エラー0 6

再起動ではなく再構築する理由は何ですか?

上記のYAMLで「restartPolicy: Never」を設定しているため、ジョブは失敗した場合にのみ再構築されます。再起動が必要な場合は、「restartPolicy: OnFaliure」を設定できます。これは、ジョブがステータスが「Failure」の場合にのみ再起動されることを意味します。このジョブには「Always」パラメータはありません。

上記の YAML で `restartPolicy` を `OnFaliure` に変更すると、結果は次のようになります。

 $ kubectl でpo を取得
名前準備完了ステータス再起動年齢
ジョブ- デモ- p9dkp 0 / 1 CrashLoopBackOff 3 ( 24 ) 68

ご覧のとおり、ジョブは再開し続けます。

ジョブが終わらない場合はどうすればよいでしょうか? たとえば、上記の YAML ファイルを次のように変更してみましょう。

 apiバージョン: バッチ/ v1
種類: 仕事
メタデータ
名前: ジョブ- デモ
名前空間: デフォルト
仕様:
テンプレート
メタデータ
名前: ジョブ- デモ
仕様:
コンテナ
- 名前: テスト- ジョブ
画像: Busybox
imagePullPolicy : IfNotPresent
指示
- 「/bin/sh」
- 「-c」
引数:
- 「睡眠3600」
再起動ポリシー: 失敗時
バックオフ制限: 4

この状況を回避するには、次のように、YAML ファイルに `activeDeadlineSeconds` パラメータを追加して、Pod の有効期間を指定します。

 apiバージョン: バッチ/ v1
種類: 仕事
メタデータ
名前: ジョブ- デモ
名前空間: デフォルト
仕様:
テンプレート
メタデータ
名前: ジョブ- デモ
仕様:
コンテナ
- 名前: テスト- ジョブ
画像: Busybox
imagePullPolicy : IfNotPresent
指示
- 「/bin/sh」
- 「-c」
引数:
- 「睡眠3600」
再起動ポリシー: 失敗時
バックオフ制限: 4
アクティブ期限秒数: 10

この値は、ジョブが作成するポッドの数に関係なく、ジョブのライフサイクル全体に適用されます。ジョブの実行時間がactiveDeadlineSeconds秒に達すると、実行中のすべてのポッドが終了し、ジョブのステータスがタイプ「Failed」、理由「DeadlineExceeded」に更新されます。

ジョブの `.spec.activeDeadlineSeconds` プロパティは、`.spec.backoffLimit` 設定よりも優先されます。したがって、ジョブが失敗した Pod を 1 つ以上再試行する場合、再試行回数が `.spec.backoffLimit` で設定された制限に達していなくても、`activeDeadlineSeconds` で設定された時間制限に達すると、ジョブは追加の Pod をデプロイしません。

並列制御

Job オブジェクトでは、並列処理を制御するパラメータは次のとおりです。

  • 完了数: ジョブが完了する必要があるポッドの最小数、つまりジョブの完了の最小数を定義します。
  • 並列処理: ジョブが特定の時点で開始できるポッドの最大数を定義します。

ジョブに対して次の YAML ファイルを定義します。

 apiバージョン: バッチ/ v1
種類: 仕事
メタデータ
名前: ジョブ- デモ
名前空間: デフォルト
仕様:
並列度2
完了数: 4
テンプレート
メタデータ
名前: ジョブ- デモ
仕様:
コンテナ
- 名前: テスト- ジョブ
画像: Busybox
imagePullPolicy : IfNotPresent
指示
- 「/bin/sh」
- 「-c」
引数:
- "for i in $(seq 10); do echo $i; 完了"
再起動ポリシー: 失敗時
バックオフ制限: 4
アクティブデッドライン秒数: 100

parallelism: 2 と completions: 4 は、4つのポッドを完了させる必要があることを示しています。同時に2つのポッドを実行できます。このジョブを作成し、結果を確認します。

 $ kubectl で po を取得
名前 準備完了 ステータス 再起動 年齢
job-demo-5wlp8 0/1 完了 0 2秒
job-demo-6wfkw 0/1 完了 0 2秒
job-demo-d54vz 0/1 完了 0 5秒
job-demo-x5mpz 0/1 完了 0 5秒

上記からわかるように、ジョブコントローラーは実際にポッドを制御します。ジョブコントローラーは作成されると、ジョブとポッドにランダムな文字列ラベルを自動的に生成し、それらをバインドします。

実際のチューニング操作では、ジョブコントローラは、実行中のPodの実際の数、終了したPodの数、並列度と完了数のパラメータ値に基づいて、ジョブサイクル内で作成または削除するPodの数を計算します。そして、kube-apiを呼び出してこれらの操作を実行します。

したがって、ジョブ コントローラは実際には、ポッドの並列処理と完了するタスクの合計数という 2 つの重要なパラメータを制御します。

Cronジョブ

CronJobは基本的に、Podを管理するためにDeploymentを使用するのと同様に、時間スケジュールが追加されたJobです。LinuxのCrontabに非常に似ています。

たとえば、単純な CronJob を定義します。

 apiバージョン: バッチ/ v1
種類: CronJob
メタデータ
名前: こんにちは
仕様:
スケジュール「*/1 * * * *」
ジョブテンプレート:
仕様:
テンプレート
仕様:
コンテナ
- 名前: こんにちは
画像: Busybox
指示
- 「/bin/sh」
- 「-c」
引数:
- "for i in $(seq 10); do echo $i; 完了"
再起動ポリシー: 失敗時

スペックは実際には単なるジョブテンプレートであることがわかります。さらに、スケジュールは標準的なCron形式に準拠しており、以下のようになります。

 時間日 月曜日
* * * * *

実行後、次のようにステータスを確認します。

 $ kubectl でcronjobs .batch を取得します
名前スケジュール一時停止アクティブ最終スケジュール年齢
こんにちは*/ 1 * * * * 0 45 69
$ kubectl でpo を取得
名前準備完了ステータス再起動年齢
こんにちは- 27628291 - h8skg 0 / 1 完了0 50

cronの性質上、前のタスクの実行が完了する前に新しいタスクが開始される場合があることにご注意ください。`spec.concurrencyPolicy`フィールドを使用してルールを定義できます。例:

  • concurrencyPolicy=Allow: これは、これらのジョブが同時に存在できることを意味します。
  • concurrencyPolicy=Firbid: これは、新しいジョブが作成されないことを意味し、このスケジュールされたタスクはスキップされることを意味します。
  • concurrencyPolicy=Replace: これは、新しいジョブが古いジョブを置き換えることを意味します。

ジョブの作成に失敗した場合、ミスとしてマークされます。指定された時間枠内にミス回数が100回に達すると、CronJobはそのジョブの作成を停止します。この時間枠は `spec.startingDeadlineSeconds` で指定できます。

要約

上記では、日常業務でよく使用されるコントローラーを紹介しました。中でも、DeploymentとDaemonSetは最も頻繁に使用されます。これらのコントローラーを習得し、どのコントローラーをいつ使用するかを適切に理解することで、効果的に活用し、作業効率を最大限に高めることができます。