|
Kubernetes では、Pod は管理の最小単位で、緊密に接続されたコンテナのグループです。 しかし、スタンドアロンのPodでは可用性を保証できません。例えば、nginx Podを作成した後、何らかの理由で誤って削除された場合、同じ属性を持つ新しいPodを自動的に作成する必要があります。しかし、残念ながら、シンプルなPodではこの要件を満たすことができません。 これに対処するため、Kubernetes は Pod を管理するための一連のコントローラーを実装し、Pod の期待状態と実際の状態が一致するようにします。一般的に使用されるコントローラーには以下が含まれます。
このセクションでは、デプロイメント、デーモンセット、ジョブ/クロンジョブについてのみ説明します。StatefulSet は、サービス、PV/PVC など、他の多くの概念に関係するため、 展開デプロイメントについて説明する前に、まず ReplicaSet (RS) について理解しましょう。 Kubernetesの初期には、レプリケーションコントローラー(RC)がポッドを制御し、ユーザーの期待通りに動作することを保証するために使用されていました。しかし、RCは後に様々な理由から段階的に廃止され、レプリケーションコントローラー(RS)に置き換えられました。機能的にはRCとRSに大きな違いはありません。唯一の違いは、RSがコレクションセレクターをサポートし、より複雑な条件を定義できることです。 感覚をつかむために、簡単な ReplicaSet を定義してみましょう。 apiバージョン: アプリ/ v1 作成結果は以下のとおりです。 $ kubectl でpo を取得 ご覧の通り、 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 起動後、次の情報が表示されます。 $ kubectl でデプロイメント.apps を取得します 上記の情報からわかるように、Deployment オブジェクトが作成されると、RS オブジェクトが自動的に作成され、その後、RS オブジェクトを通じて対応する数の Pod が作成されます。 水平方向の拡大/縮小上記では、3つのレプリカを持つポッドを作成しました。このポッドを拡張/縮小する必要がある場合は、以下の3つの方法で行うことができます。
使用する具体的な方法は状況によって異なります。 1. kubectl scale コマンドを使用してスケールする拡張と縮小のコマンドは同じです。拡張するとレプリカの数が増え、縮小するとレプリカの数が減ります。 (1)現在の3つのレプリカを拡張して4つのレプリカが必要な場合は、次のコマンドを使用します。 $ kubectl スケールデプロイメントnginx - デプロイメント-- レプリカ4 ご覧のとおり、ポッドの数は 4 に増加しました。 $ kubectl でpo を取得 (2) 縮小 現在、クラスタには4つのレプリカがあります。レプリカを2つだけ必要な場合は、以下のコマンドを使用します。 $ kubectl スケールデプロイメントnginx - デプロイメント-- レプリカ2 現在、クラスターには 2 つの Pod のみがあります。 $ kubectl でpo を取得 2. kubectl edit を使用してデプロイメントを直接編集する次のように、kubectl edit を使用して実行中のデプロイメントを直接編集し、レプリカ数を変更することもできます。 $ kubectl edit デプロイメント. apps nginx - デプロイメント- oyaml 編集インターフェースは次のとおりです。 変更を加えたら、`:wq` で保存して終了します。すると、レプリカの数が 4 に戻っていることがわかります。 $ kubectl でpo を取得 3. `kubectl apply` を使用してローカル YAML ファイルを更新します。ローカル YAML ファイルを直接変更してコピー数を調整することもできます。たとえば、YAML ファイルでコピー数を直接 2 に変更します。 apiバージョン: アプリ/ v1 その後、kubectl apply -f nginx.yaml を使用して直接デプロイできます。 ローリングアップデート/ロールバックビジネスアプリケーションは、ほとんどの場合、デプロイメントを介してKubernetes上にデプロイされます。アプリケーションの更新とロールバックは、特に迅速な反復がユーザー獲得に不可欠なインターネット企業では日常的なタスクです。 ただし、すべての反復が 100% 成功するとは限らず、異常から迅速に回復する方法も考慮する必要があります。 このシナリオに適応するために、デプロイメントではローリング アップデートとクイック ロールバックを実行する機能が提供されます。 ローリングアップデートデプロイメントのデフォルトの更新方法はローリング更新ですが、strategy.type を使用して更新方法を指定できます。
更新方法を変更するには、次のように設定します。 apiバージョン: アプリ/ v1 例: (1) maxSurge: DESIREDの数に加えて、1回のローリングアップデート中にデプロイメントが作成できるPodの数を定義します。 (2) maxUnavailable: ローリングアップデート中にデプロイメントが削除できるポッドの最大数を定義します。さらに、これら2つの構成はパーセンテージで表すこともできます。 一般的には、本番環境で最もよく使用されるデフォルトの更新方法をそのまま使用すれば十分です。 それでは、ローリングアップデートの効果を確認してみましょう。まず、以下のようにnginxアプリケーションを作成します。 apiバージョン: アプリ/ v1 次に、`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-deployment-6c74f576b9-*、新しいバージョンはnginx-deployment-778d9f5866-*です。まず新しいバージョンのPodが作成され、その後古いバージョンのPodが削除されます。このプロセスは、すべての古いバージョンが置き換えられるまで継続されます。 基本的なロジックは、Deployment を通じて新しい ReplicaSet を作成し、その新しい ReplicaSet を通じて新しい Pod を作成することです。これは $ kubectl でrs を取得する このローリング アップデートの利点は、アップデート プロセス中に新しいバージョンの Pod に問題が発生した場合、ローリング アップデートが停止することです。この時点で、運用チームと開発チームが介入して原因を調査できます。アプリケーションにはまだ 2 つの古いバージョンの Pod がオンラインになっているため、サービスに大きな影響を与えることはありません。もちろん、この場合、コンテナの実行状態に単に依存するのではなく、アプリケーションのヘルス ステータスを確認するために、Pod にヘルス チェックを追加する必要があります。サービスの継続性をさらに確保するために、デプロイメント コントローラは、特定の時間枠内で指定された割合の Pod のみがオフラインになるようにし、また、特定の時間枠内で指定された割合の Pod のみが作成されるようにします。この割合は、デフォルトでは DESIRED Pod の 25% です。 もちろん、Deployment オブジェクトの RollingUpdateStrategy というフィールドを変更することでカスタマイズできます。次に例を示します。 apiバージョン: アプリ/ v1 例: (1) maxSurge: DESIRED Podの数に加えて、1回のローリングアップデート中にデプロイメントが作成できるPodの数を定義します。 (2) maxUnavailable: ローリングアップデート中にデプロイメントが削除できるポッドの最大数を定義します。さらに、これら2つの構成はパーセンテージで表すこともできます。 したがって、次の関係図が得られます。 レプリカセットの数と各レプリカセットの属性は、デプロイメントによって実際に制御されます。アプリケーションのバージョンは1つのレプリカセットに対応し、各バージョンが持つべきポッドの数は、レプリカセット自身のコントローラーによって管理されます。 ロールバックアップデートがあり、ロールバックがあり、彼らは運命的に引き裂かれた恋人同士です。 Kubernetesでは、ロールバックは`kubectl rollout`コマンドを使用して実行されます。ローリングアップデートのセクションでは、Nginxアプリケーションを更新しました。新しいバージョンに問題がある場合は、ロールバックが必要になります。 (1)ロールバック可能な過去のバージョンを表示する $ kubectl ロールアウト履歴デプロイメントnginx - デプロイメント 2 つのバージョンがあることがわかりました。現在はバージョン 2 を使用しており、バージョン 1 にロールバックする必要があります。 (2)以下のコマンドを実行して古いバージョンにロールバックします。 $ kubectl rollout undo デプロイメントnginx - デプロイメント-- to - リビジョン1 (3)RSをチェックして、古いバージョンにロールバックできるかどうかを確認します。 $ kubectl でrs を取得する 明示的に以前のバージョンにロールバックできる場合は、`kubectl rollout undo deployment nginx-deployment` を直接使用できます。 ロールバックは比較的簡単な操作ですが、リリースが頻繁に行われ、履歴データが特定のバージョン数(デフォルトでは 10 バージョン)を超えると、古いバージョンにロールバックできなくなります。 もちろん、次のように、デフォルトで 10 に設定されている spec.revisionHistoryLimit を定義することで、保持するバージョン番号の数を定義することができます。 apiバージョン: アプリ/ v1 上記は、デプロイメントのロールバック操作について説明しました。操作コマンドは比較的シンプルです。重要なのは、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 実行後、次のように、Filebeat が kk-node01 ノード上で実行されていることがわかります。 $ kubectl get po - o ワイド クラスター自体に 2 つのノードがあるのに、なぜ 1 つの Pod だけがデプロイされるのか疑問に思う人もいるかもしれません。 これは、マスター(コントロールノード)にテイント(汚染)があり、その上位の DaemonSet がこの汚染を許容しないため、スケジュールされなかったためです。具体的なスケジュール戦略については、Kubernetes のスケジュールと管理のセクションで説明します。 DaemonSet はアップデートとロールバックもサポートしており、具体的な操作は Deployment と似ているため、ここでは詳細には説明しません。 ただし、DaemonSet の更新戦略を導入する必要があります。現在、次の 2 つの更新戦略がサポートされています。
ここで、rollingUpdate アップデート戦略について触れておきましょう。以前のバージョンの Kubernetes では、DaemonSet で実行できるノードは 1 つだけだったため、maxUnavailable のみが存在し、maxSurge はありませんでした。しかし、新しいバージョンでは、利用可能なノードの数を制御する maxSurge パラメータが導入されました。例えば、合計 100 ノードがあり、maxSurge が 30% に設定されている場合、少なくとも 30 ノードが利用可能になります。 ジョブ/CronJobKubernetesの主な役割は、Pod内のアプリケーションの長期的かつ安定した運用を確保することです。しかし、時には一度だけ実行して終了する「短期的な」タスクが必要になることもあります。このような場合、Deploymentなどのコントローラーではニーズを満たすことができません。Kubernetesは、このような要件を特に処理するためにJob Controllerを作成しました。 仕事ジョブは、一度だけ実行されるタスクを処理します。1つ以上のバッチタスクの成功を保証します。具体的な構文は「kubectl explain job」で確認できます。 基本操作ジョブを定義する構文は、デプロイメントやポッドの構文と似ています。以下はジョブを定義する簡単な例です。 apiバージョン: バッチ/ v1 このジョブは、スクリプトを実行し、10回ループして結果を出力するだけです。このジョブは、`kubectl apply -f job-demo.yaml` を使用して以下のように作成されます。 $ kubectl apply -f ジョブ- デモ.yaml 次に、次のように `kubectl logs` を使用してログ出力を表示できます。 $ kubectl ログジョブ- デモ- wd67s すべて期待通りに進んでいます。では、ジョブとポッドのステータスを見てみましょう。 $ kubectl get jobs . バッチ ジョブのステータスには、デプロイメントのような「Ready」というキーワードはなく、「COMPLETIONS」というキーワードが使用され、1/1 はジョブが完了したことを示します。ジョブによって制御されるポッドのステータスも「Completed」となり、このステータスはジョブが成功したことを示します。 成功した場合、ジョブのポッドは1回実行されて停止します。失敗した場合はどうなりますか? 次に、ジョブの YAML を次のように変更します。 apiバージョン: バッチ/ v1 実行後、以下に示すように、Pod が継続的に再構築されていることがわかります。 $ kubectl でpo を取得 再起動ではなく再構築する理由は何ですか? 上記のYAMLで「restartPolicy: Never」を設定しているため、ジョブは失敗した場合にのみ再構築されます。再起動が必要な場合は、「restartPolicy: OnFaliure」を設定できます。これは、ジョブがステータスが「Failure」の場合にのみ再起動されることを意味します。このジョブには「Always」パラメータはありません。 上記の YAML で `restartPolicy` を `OnFaliure` に変更すると、結果は次のようになります。 $ kubectl でpo を取得 ご覧のとおり、ジョブは再開し続けます。 ジョブが終わらない場合はどうすればよいでしょうか? たとえば、上記の YAML ファイルを次のように変更してみましょう。 apiバージョン: バッチ/ v1 この状況を回避するには、次のように、YAML ファイルに `activeDeadlineSeconds` パラメータを追加して、Pod の有効期間を指定します。 apiバージョン: バッチ/ v1 この値は、ジョブが作成するポッドの数に関係なく、ジョブのライフサイクル全体に適用されます。ジョブの実行時間がactiveDeadlineSeconds秒に達すると、実行中のすべてのポッドが終了し、ジョブのステータスがタイプ「Failed」、理由「DeadlineExceeded」に更新されます。 ジョブの `.spec.activeDeadlineSeconds` プロパティは、`.spec.backoffLimit` 設定よりも優先されます。したがって、ジョブが失敗した Pod を 1 つ以上再試行する場合、再試行回数が `.spec.backoffLimit` で設定された制限に達していなくても、`activeDeadlineSeconds` で設定された時間制限に達すると、ジョブは追加の Pod をデプロイしません。 並列制御Job オブジェクトでは、並列処理を制御するパラメータは次のとおりです。
ジョブに対して次の YAML ファイルを定義します。 apiバージョン: バッチ/ v1 parallelism: 2 と completions: 4 は、4つのポッドを完了させる必要があることを示しています。同時に2つのポッドを実行できます。このジョブを作成し、結果を確認します。 $ kubectl で po を取得 上記からわかるように、ジョブコントローラーは実際にポッドを制御します。ジョブコントローラーは作成されると、ジョブとポッドにランダムな文字列ラベルを自動的に生成し、それらをバインドします。 実際のチューニング操作では、ジョブコントローラは、実行中のPodの実際の数、終了したPodの数、並列度と完了数のパラメータ値に基づいて、ジョブサイクル内で作成または削除するPodの数を計算します。そして、kube-apiを呼び出してこれらの操作を実行します。 したがって、ジョブ コントローラは実際には、ポッドの並列処理と完了するタスクの合計数という 2 つの重要なパラメータを制御します。 CronジョブCronJobは基本的に、Podを管理するためにDeploymentを使用するのと同様に、時間スケジュールが追加されたJobです。LinuxのCrontabに非常に似ています。 たとえば、単純な CronJob を定義します。 apiバージョン: バッチ/ v1 スペックは実際には単なるジョブテンプレートであることがわかります。さらに、スケジュールは標準的なCron形式に準拠しており、以下のようになります。 分時間日 月曜日 実行後、次のようにステータスを確認します。 $ kubectl でcronjobs .batch を取得します cronの性質上、前のタスクの実行が完了する前に新しいタスクが開始される場合があることにご注意ください。`spec.concurrencyPolicy`フィールドを使用してルールを定義できます。例:
ジョブの作成に失敗した場合、ミスとしてマークされます。指定された時間枠内にミス回数が100回に達すると、CronJobはそのジョブの作成を停止します。この時間枠は `spec.startingDeadlineSeconds` で指定できます。 要約上記では、日常業務でよく使用されるコントローラーを紹介しました。中でも、DeploymentとDaemonSetは最も頻繁に使用されます。これらのコントローラーを習得し、どのコントローラーをいつ使用するかを適切に理解することで、効果的に活用し、作業効率を最大限に高めることができます。 |