4.3. DeploymentConfig ストラテジーの使用

デプロイメントストラテジー は、アプリケーションを変更またはアップグレードする 1 つの方法です。この目的は、ユーザーには改善が加えられていることが分からないように、ダウンタイムなしに変更を加えることにあります。

エンドユーザーは通常ルーターによって処理されるルート経由でアプリケーションにアクセスするため、デプロイメントストラテジーは、DeploymentConfig 機能またはルーティング機能に重点を置きます。DeploymentConfig に重点を置くストラテジーは、アプリケーションを使用するすべてのルートに影響を与えます。ルーター機能を使用するストラテジーは個別のルートにターゲットを設定します。

デプロイメントストラテジーの多くは、DeploymentConfig でサポートされ、追加のストラテジーはルーター機能でサポートされます。このセクションでは、DeploymentConfig ストラテジーについて説明します。

デプロイメントストラテジーの選択

デプロイメントストラテジーを選択する場合に、以下を考慮してください。

  • 長期間実行される接続は正しく処理される必要があります。
  • データベースの変換は複雑になる可能性があり、アプリケーションと共に変換し、ロールバックする必要があります。
  • アプリケーションがマイクロサービスと従来のコンポーネントを使用するハイブリッドの場合には、移行の完了時にダウンタイムが必要になる場合があります。
  • これを実行するためのインフラストラクチャーが必要です。
  • テスト環境が分離されていない場合は、新規バージョンと以前のバージョン両方が破損してしまう可能性があります。

デプロイメントストラテジーは、readiness チェックを使用して、新しい Pod の使用準備ができているかを判断します。readiness チェックに失敗すると、DeploymentConfig は、タイムアウトするまで Pod の実行を再試行します。デフォルトのタイムアウトは、10m で、値は dc.spec.strategy.*paramsTimeoutSeconds で設定します。

4.3.1. ローリングストラテジー

ローリングデプロイメントは、以前のバージョンのアプリケーションインスタンスを、新しいバージョンのアプリケーションインスタンスに徐々に置き換えます。ローリングストラテジーは、DeploymentConfig にストラテジーが指定されていない場合に使用されるデフォルトのデプロイメントストラテジーです。

ローリングデプロイメントは通常、新規 Pod が readiness check によって ready になるのを待機してから、古いコンポーネントをスケールダウンします。重大な問題が生じる場合、ローリングデプロイメントは中止される場合があります。

ローリングデプロイメントの使用のタイミング

  • ダウンタイムを発生させずに、アプリケーションの更新を行う場合
  • 以前のコードと新しいコードの同時実行がアプリケーションでサポートされている場合

ローリングデプロイメントとは、以前のバージョンと新しいバージョンのコードを同時に実行するという意味です。これは通常、アプリケーションで N-1 互換性に対応する必要があります。

ローリングストラテジー定義の例

strategy:
  type: Rolling
  rollingParams:
    updatePeriodSeconds: 1 1
    intervalSeconds: 1 2
    timeoutSeconds: 120 3
    maxSurge: "20%" 4
    maxUnavailable: "10%" 5
    pre: {} 6
    post: {}

1
各 Pod が次に更新されるまで待機する時間。指定されていない場合、デフォルト値は 1 となります。
2
更新してからデプロイメントステータスをポーリングするまでの間待機する時間。指定されていない場合、デフォルト値は 1 となります。
3
イベントのスケーリングを中断するまでの待機時間。この値はオプションです。デフォルトは 600 です。ここでの 中断 とは、自動的に以前の完全なデプロイメントにロールバックされるという意味です。
4
maxSurge はオプションで、指定されていない場合には、デフォルト値は 25% となります。以下の手順の次にある情報を参照してください。
5
maxUnavailable はオプションで、指定されていない場合には、デフォルト値は 25% となります。以下の手順の次にある情報を参照してください。
6
pre および post はどちらもライフサイクルフックです。

ローリングストラテジー:

  1. pre ライフサイクルフックを実行します。
  2. サージ数に基づいて新しい ReplicationController をスケールアップします。
  3. 最大利用不可数に基づいて以前の ReplicationController をスケールダウンします。
  4. 新しい ReplicationController が希望のレプリカ数に到達して、以前の ReplicationController の数がゼロになるまで、このスケーリングを繰り返します。
  5. post ライフサイクルフックを実行します。
重要

スケールダウン時には、ローリングストラテジーは Pod の準備ができるまで待機し、スケーリングを行うことで可用性に影響が出るかどうかを判断します。Pod をスケールアップしたにもかかわらず、準備が整わない場合には、デプロイメントプロセスは最終的にタイムアウトして、デプロイメントに失敗します。

maxUnavailable パラメーターは、更新時に利用できない Pod の最大数です。maxSurge パラメーターは、元の Pod 数を超えてスケジュールできる Podの 最大数です。どちらのパラメーターも、パーセント (例: 10%) または絶対値 (例: 2) のいずれかに設定できます。両方のデフォルト値は 25% です。

以下のパラメーターを使用して、デプロイメントの可用性やスピードを調整できます。以下は例になります。

  • maxUnavailable*=0 および maxSurge*=20% が指定されていると、更新時および急速なスケールアップ時に完全なキャパシティーが維持されるようになります。
  • maxUnavailable*=10% および maxSurge*=0 が指定されていると、追加のキャパシティーを使用せずに更新を実行します (インプレース更新)。
  • maxUnavailable*=10% および maxSurge*=10% の場合は、キャパシティーが失われる可能性がありますが、迅速にスケールアップおよびスケールダウンします。

一般的に、迅速にロールアウトする場合は maxSurge を使用します。リソースのクォータを考慮して、一部に利用不可の状態が発生してもかまわない場合には、maxUnavailable を使用します。

4.3.1.1. カナリアデプロイメント

OpenShift Container Platform におけるすべてのローリングデプロイメントは カナリアデプロイメント です。新規バージョン (カナリア) はすべての古いインスタンスが置き換えられる前にテストされます。readiness チェックが成功しない場合、カナリアインスタンスは削除され、DeploymentConfig は自動的にロールバックされます。

readiness チェックはアプリケーションコードの一部であり、新規インスタンスが使用できる状態にするために必要に応じて高度な設定をすることができます。(実際のユーザーワークロードを新規インスタンスに送信するなどの) アプリケーションのより複雑なチェックを実装する必要がある場合、カスタムデプロイメントや blue-green デプロイメントストラテジーの実装を検討してください。

4.3.1.2. ローリングデプロイメントの作成

ローリングデプロイメントは OpenShift Container Platform のデフォルトタイプです。CLI を使用してローリングデプロイメントを作成できます。

手順

  1. DockerHub にあるデプロイメントイメージの例を基にアプリケーションを作成します。

    $ oc new-app openshift/deployment-example
  2. ルーターをインストールしている場合は、ルートを使用してアプリケーションを利用できるようにしてください (または、サービス IP を直接使用してください)。

    $ oc expose svc/deployment-example
  3. deployment-example.<project>.<router_domain> でアプリケーションを参照し、v1 イメージが表示されることを確認します。
  4. レプリカが最大 3 つになるまで、DeploymentConfig をスケーリングします。

    $ oc scale dc/deployment-example --replicas=3
  5. 新しいバージョンの例を latest とタグ付けして、新規デプロイメントを自動的にトリガーします。

    $ oc tag deployment-example:v2 deployment-example:latest
  6. ブラウザーで、v2 イメージが表示されるまでページを更新します。
  7. CLI を使用している場合は、以下のコマンドで、バージョン 1 に Pod がいくつあるか、バージョン 2 にはいくつあるかを表示します。Web コンソールでは、Pod が徐々に v2 に追加され、v1 から削除されます。

    $ oc describe dc deployment-example

デプロイメントプロセス時に、新規 ReplicationController は徐々にスケールアップされます。(rediness チェックをパスした後に) 新規 Pod に ready のマークが付けられると、デプロイメントプロセスは継続されます。

Pod が準備状態にならない場合、プロセスは中止し、DeploymentConfig は直前のバージョンにロールバックします。

4.3.2. 再作成ストラテジー

再作成ストラテジーは、基本的なロールアウト動作で、デプロイメントプロセスにコードを挿入するためのライフサイクルフックをサポートします。

再作成ストラテジー定義の例

strategy:
  type: Recreate
  recreateParams: 1
    pre: {} 2
    mid: {}
    post: {}

1
recreateParams はオプションです。
2
premid、および post はライフサイクルフックです。

再作成ストラテジー:

  1. pre ライフサイクルフックを実行します。
  2. 以前のデプロイメントをゼロにスケールダウンします。
  3. 任意の mid ライフサイクルフックを実行します。
  4. 新規デプロイメントをスケールアップします。
  5. post ライフサイクルフックを実行します。
重要

スケールアップ中に、デプロイメントのレプリカ数が複数ある場合は、デプロイメントの最初のレプリカが準備できているかどうかが検証されてから、デプロイメントが完全にスケールアップされます。最初のレプリカの検証に失敗した場合には、デプロイメントは失敗とみなされます。

再作成デプロイメントの使用のタイミング:

  • 新規コードを起動する前に、移行または他のデータの変換を行う必要がある場合
  • 以前のバージョンと新しいバージョンのアプリケーションコードの同時使用をサポートしていない場合
  • 複数のレプリカ間での共有がサポートされていない、RWO ボリュームを使用する場合

再作成デプロイメントでは、短い期間にアプリケーションのインスタンスが実行されなくなるので、ダウンタイムが発生します。ただし、以前のコードと新しいコードは同時には実行されません。

4.3.3. カスタムストラテジー

カスタムストラテジーでは、独自のデプロイメントの動作を提供できるようになります。

カスタムストラテジー定義の例

strategy:
  type: Custom
  customParams:
    image: organization/strategy
    command: [ "command", "arg1" ]
    environment:
      - name: ENV_1
        value: VALUE_1

上記の例では、organization/strategy コンテナーイメージにより、デプロイメントの動作が提供されます。オプションの command 配列は、イメージの Dockerfile で指定した CMD ディレクティブを上書きします。指定したオプションの環境変数は、ストラテジープロセスの実行環境に追加されます。

さらに、OpenShift Container Platform は以下の環境変数をデプロイメントプロセスに提供します。

環境変数説明

OPENSHIFT_DEPLOYMENT_NAME

新規デプロイメント名 (ReplicationController)

OPENSHIFT_DEPLOYMENT_NAMESPACE

新規デプロイメントの namespace

新規デプロイメントのレプリカ数は最初はゼロです。ストラテジーの目的は、ユーザーのニーズに最適な仕方で対応するロジックを使用して新規デプロイメントをアクティブにすることにあります。

または customParams を使用して、カスタムのデプロイメントロジックを、既存のデプロイメントストラテジーに挿入します。カスタムのシェルスクリプトロジックを指定して、openshift-deploy バイナリーを呼び出します。カスタムのデプロイヤーコンテナーイメージを用意する必要はありません。ここでは、代わりにデフォルトの OpenShift Container Platform デプロイヤーイメージが使用されます。

strategy:
  type: Rolling
  customParams:
    command:
    - /bin/sh
    - -c
    - |
      set -e
      openshift-deploy --until=50%
      echo Halfway there
      openshift-deploy
      echo Complete

この設定により、以下のようなデプロイメントになります。

Started deployment #2
--> Scaling up custom-deployment-2 from 0 to 2, scaling down custom-deployment-1 from 2 to 0 (keep 2 pods available, don't exceed 3 pods)
    Scaling custom-deployment-2 up to 1
--> Reached 50% (currently 50%)
Halfway there
--> Scaling up custom-deployment-2 from 1 to 2, scaling down custom-deployment-1 from 2 to 0 (keep 2 pods available, don't exceed 3 pods)
    Scaling custom-deployment-1 down to 1
    Scaling custom-deployment-2 up to 2
    Scaling custom-deployment-1 down to 0
--> Success
Complete

カスタムデプロイメントストラテジーのプロセスでは、OpenShift Container Platform API または Kubernetes API へのアクセスが必要な場合には、ストラテジーを実行するコンテナーは、認証用のコンテナーで利用可能なサービスアカウントのトークンを使用できます。

4.3.4. ライフサイクルフック

ローリングおよび再作成ストラテジーは、ストラテジーで事前に定義したポイントでデプロイメントプロセスに動作を挿入できるようにする ライフサイクルフック またはデプロイメントフックをサポートします。

pre ライフサイクルフックの例

pre:
  failurePolicy: Abort
  execNewPod: {} 1

1
execNewPod は Pod ベースのライフサイクルフックです。

フックにはすべて、フックに問題が発生した場合にストラテジーが取るべきアクションを定義する failurePolicy が含まれます。

Abort

フックに失敗すると、デプロイメントプロセスも失敗とみなされます。

Retry

フックの実行は、成功するまで再試行されます。

Ignore

フックの失敗は無視され、デプロイメントは続行されます。

フックには、フックの実行方法を記述するタイプ固有のフィールドがあります。現在、フックタイプとしてサポートされているのは Pod ベースのフックのみで、このフックは execNewPod フィールドで指定されます。

Pod ベースのライフサイクルフック

Pod ベースのライフサイクルフックは、DeploymentConfig のテンプレートをベースとする新しい Pod でフックコードを実行します。

以下の DeploymentConfig 例は簡素化されており、この例ではローリングストラテジーを使用します。簡潔にまとめられるように、トリガーおよびその他の詳細は省略しています。

kind: DeploymentConfig
apiVersion: v1
metadata:
  name: frontend
spec:
  template:
    metadata:
      labels:
        name: frontend
    spec:
      containers:
        - name: helloworld
          image: openshift/origin-ruby-sample
  replicas: 5
  selector:
    name: frontend
  strategy:
    type: Rolling
    rollingParams:
      pre:
        failurePolicy: Abort
        execNewPod:
          containerName: helloworld 1
          command: [ "/usr/bin/command", "arg1", "arg2" ] 2
          env: 3
            - name: CUSTOM_VAR1
              value: custom_value1
          volumes:
            - data 4
1
helloworld の名前は spec.template.spec.containers[0].name を参照します。
2
この command は、openshift/origin-ruby-sample イメージで定義される ENTRYPOINT を上書きします。
3
env は、フックコンテナーの環境変数です (任意)。
4
volumes は、フックコンテナーのボリューム参照です (任意)。

この例では、pre フックは、helloworld コンテナーからの openshift/origin-ruby-sample イメージを使用して新規 Pod で実行されます。フック Pod には以下のプロパティーが設定されます。

  • フックコマンドは /usr/bin/command arg1 arg2 です。
  • フックコンテナーには、CUSTOM_VAR1=custom_value1 環境変数が含まれます。
  • フックの失敗ポリシーは Abort で、フックが失敗するとデプロイメントプロセスも失敗します。
  • フック Pod は、DeploymentConfig Pod から data ボリュームを継承します。

4.3.4.1. ライフサイクルフックの設定

CLI を使用して DeploymentConfig 用に、ライフサイクルフックまたはデプロイメントフックを設定できます。

手順

  1. oc set deployment-hookコマンドを使用して、必要なフックのタイプを設定します (--pre--mid、または --post)。たとえば、デプロイメント前のフックを設定するには、以下を実行します。

    $ oc set deployment-hook dc/frontend \
        --pre -c helloworld -e CUSTOM_VAR1=custom_value1 \
        -v data --failure-policy=abort -- /usr/bin/command arg1 arg2