NetScaler統合型カナリアデプロイメントソリューションの展開

最終公開日 : Oct 02, 2026
カナリアリリースとは、新しいソフトウェアバージョンを本番環境に導入する際のリスクを軽減するために、まず変更を少数のユーザーに展開する手法です。ユーザーによる検証後、アプリケーションはより多くのユーザーに展開されます。
NetScalerは、NetScaler Ingress Controllerを使用してカナリアデプロイメントを行うための以下のオプションを提供します。
Canary CRDを使用したデプロイメントでは、カナリア構成はKubernetes CRDを使用して適用されます。Citrix®は、Ingressアノテーションを使用したカナリアデプロイメントのよりシンプルなオプションもサポートしています。

Canary CRDを使用したカナリアの展開

このセクションでは、Canary CRDを使用してカナリアデプロイメントを実行する方法について説明します。
NetScaler統合型カナリアデプロイメントソリューションは、継続的デリバリー (CD) のすべてのコンポーネントを連携させ、アプリケーション開発者にとってカナリアデプロイメントをより簡単にします。このソリューションは、継続的デリバリープラットフォームとしてSpinnakerを、カナリア分析用のSpinnakerプラグインとしてKayentaを使用します。Kayentaは、ユーザーが設定したメトリクスをソースから取得し、統計テストを実行して、カナリアの集計スコアを提供するオープンソースのカナリア分析サービスです。統計テストとカウンターからのスコアは、成功基準とともにカナリアを昇格または失敗させるために使用されます。
NetScalerは、豊富なアプリケーション中心の構成モジュールを備えており、アプリケーションのトラフィックとアプリケーションインスタンスの健全性に対する完全な可視性を提供します。NetScalerの正確なパフォーマンス統計を生成する機能は、カナリア分析に活用され、カナリアデプロイメントに関するより良い決定を下すことができます。このソリューションでは、NetScalerはSpinnakerプラットフォームと統合され、Kayentaを使用したカナリアデプロイメント分析のための正確なメトリクスを提供するソースとして機能します。
NetScaler Metrics Exporterは、アプリケーションのパフォーマンスメトリクスをオープンソースの監視システムPrometheusにエクスポートし、Kayentaを設定してカナリアデプロイメント用のメトリクスを取得できます。カナリアバージョンへのトラフィック分散は、NetScalerポリシーインフラストラクチャを使用して調整できます。特定の種類のトラフィックを本番環境からベースラインとカナリアに迂回させたい場合は、豊富なNetScalerポリシーインフラストラクチャを活用して、一致式を使用してトラフィックをベースラインとカナリアにリダイレクトできます。
たとえば、一致式 HTTP.REQ.URL.CONTAINS("citrix india") を使用して、本番環境からカナリアおよびベースラインにトラフィックを迂回させることができます。この式に一致するトラフィックはカナリアおよびベースラインに迂回され、残りのトラフィックは本番環境に送られます。
Citrix統合型カナリアデプロイメントソリューションの一部であるコンポーネントとその機能は次のとおりです。
  • GitHub: GitHubは、Gitが提供するすべての分散バージョン管理およびソースコード管理機能を提供し、追加機能も備えています。 GitHubには、Docker HubやSpinnakerなど、CI/CDパイプラインの一部を構成する他のツールと統合するための多くのユーティリティが用意されています。
  • Docker Hub: Docker Hubは、Dockerが提供するクラウドベースのリポジトリサービスで、Dockerイメージの共有と検索に使用されます。GitHubとDocker Hubを統合して、GitHubのソースコードからイメージを自動的にビルドし、ビルドされたイメージをDocker Hubにプッシュできます。
  • Spinnaker: Spinnakerは、ソフトウェアの変更を高速かつ確実にリリースするためのオープンソースのマルチクラウド継続的デリバリープラットフォームです。Spinnakerのアプリケーションデプロイ機能を使用して、継続的デリバリーワークフローを構築および管理できます。Spinnakerにおける主要なデプロイ管理の構成要素はパイプラインとして知られています。Spinnakerのパイプラインは、ステージとして知られる一連のアクションで構成されています。Spinnakerは、アプリケーションのデプロイ、スクリプトの実行、カナリア分析の実行、デプロイの削除など、さまざまなステージを提供します。Spinnakerを多くのサードパーティツールと統合して、多くの追加機能をサポートできます。
  • Prometheus: Prometheusは、オープンソースのシステム監視およびアラートツールキットです。Prometheusは、時系列データベースに大量のデータを保持できる監視システムです。NetScaler Metricsは、Prometheusを介してパフォーマンスメトリックをSpinnakerに公開します。
  • Jenkins: Jenkinsは、ソフトウェアのビルド、テスト、デリバリー、デプロイに関連するあらゆる種類のタスクを自動化するのに役立つオープンソースの自動化サーバーです。Jenkinsは、デプロイサイクルの一部としてカスタムスクリプトの実行もサポートしています。
  • NetScaler Ingress Controller NetScalerは、ベアメタルおよびクラウドデプロイメント向けに、NetScaler MPX(ハードウェア)、NetScaler VPX(仮想化)、およびNetScaler CPX(コンテナ化)用のIngress Controllerを提供します。NetScaler Ingress ControllerはKubernetes Ingressを中心に構築されており、Ingressリソース構成に基づいて1つ以上のNetScalerを自動的に構成します。
Citrix統合カナリアデプロイメントソリューションには、以下のNetScaler®ソフトウェアバージョンが必要です。
  • ネットスケーラー イングレス コントローラーのビルド/バージョン: quay.io/citrix/citrix-k8s-ingress-controller:1.29.5。
  • NetScaler CPXバージョン: quay.io/citrix/citrix-k8s-cpx-ingress:13.0-83.27。
  • NetScaler Metrics Exporterバージョン: quay.io/citrix/netscaler-metrics-exporter:1.4.0。

NetScaler統合カナリアデプロイメントソリューションのためのSpinnakerパイプラインのワークフロー

次の図は、NetScaler統合カナリアデプロイメントソリューションのためのSpinnakerパイプラインのワークフローを示しています。
Spinnaker_パイプライン
次の手順は、図に示されているワークフローを説明しています。
  1. 開発者はGitHubでソースコードを管理し、必要に応じて変更を加え、その変更をGitHubにコミットします。
  2. ソースコードの変更をリッスンするために、GitHubにWebhookが構成されています。ソースコードがGitHubにチェックインされるたびに、Webhookがトリガーされ、Docker Hubに新しいソースコードでイメージをビルドするように通知します。Dockerイメージが作成されると、Docker Hubに構成された別のWebhookがSpinnakerパイプラインをトリガーします。
  3. Spinnakerパイプラインがトリガーされると、イメージのカナリアバージョンとベースラインバージョンがデプロイされます。
  4. カナリアバージョンとベースラインバージョンがデプロイされると、本番環境からのトラフィックの一部がカナリアバージョンとベースラインバージョンに転送されます。NetScalerはパフォーマンス統計を収集し、NetScaler Metrics Exporterの助けを借りてPrometheusに統計をエクスポートします。Prometheusはこれらの統計をKayentaに提供し、カナリア分析を行います。
  5. Kayentaはパフォーマンス統計に基づいてカナリア分析を実行し、スコアを生成します。このスコアに基づいて、カナリアデプロイメントは成功または失敗と判断され、イメージはロールアウトまたはロールバックされます。

Google Cloud PlatformでNetScaler統合カナリアデプロイメントソリューションをデプロイする

このセクションには、Spinnakerのセットアップ方法、Spinnakerパイプラインの作成方法、およびカナリアデプロイメントのサンプルに関する情報が含まれています。

Google Cloud PlatformでSpinnakerをデプロイする

このトピックには、Spinnakerのデプロイ方法と、Google Cloud Platform (GCP) でのカナリアデプロイメントのためにプラグインをSpinnakerと統合する方法に関する情報が含まれています。
GCPでSpinnakerをデプロイし、プラグインを統合するには、以下の手順を実行します。
  1. 以下のコマンドを使用して、環境をセットアップし、GKEクラスターを作成します。
    export GOOGLE_CLOUD_PROJECT=[PROJECT_ID]
    gcloud config set project $GOOGLE_CLOUD_PROJECT
    gcloud config set compute/zone us-central1-f
    gcloud services enable container.googleapis.com
    gcloud beta container clusters create kayenta-tutorial
    --machine-type=n1-standard-2 --enable-stackdriver-kubernetes
  2. 以下のコマンドを使用して、PrometheusをStackdriverと統合するためのプラグインをインストールします。
    kubectl apply --as=admin --as-group=system:masters -f \
    https://storage.googleapis.com/stackdriver-prometheus-documentation/rbac-setup.yml
    curl -sS "https://storage.googleapis.com/stackdriver-prometheus-documentation/prometheus-service.yml" |
    \sed "s/_stackdriver_project_id:.*/_stackdriver_project_id: $GOOGLE_CLOUD_PROJECT/" |
    \sed "s/_kubernetes_cluster_name:.*/_kubernetes_cluster_name: kayenta-tutorial/" |
    \sed "s/_kubernetes_location:.*/_kubernetes_location: us-central1-f/" |
    \kubectl apply -f -
  3. 以下の手順を使用して、GKEクラスターにSpinnakerをデプロイします。
    1. SpinnakerウェブサイトからSpinnaker用のquick-install.ymlファイルをダウンロードします。
    2. Docker Hubから始まるさまざまなコンポーネントを統合するために、quick-install.ymlファイルを更新します。SpinnakerをDocker Hubと統合するには、quick-install.ymlファイル内のConfigMapの下にあるアドレス、ユーザー名、パスワード、メール、およびリポジトリの値を更新します。
      dockerRegistry:
                  enabled: true
                  accounts:
                  - name: my-docker-registry
                  requiredGroupMembership: []
                  providerVersion: V1
                  permissions: {}
                  address: https://index.docker.io
                  username: <username>
                  password: <password>
                  email: <mail-id>
                  cacheIntervalSeconds: 30
                  clientTimeoutMillis: 60000
                  cacheThreads: 1
                  paginateSize: 100
                  sortTagsByDate: false
                  trackDigests: false
                  insecureRegistry: false
                  repositories:- <repository-name>
                  primaryAccount: my-docker-registry
    3. (オプション) Jenkinsをセットアップするには、以下の手順を実行します。
      sudo apt-get update
      sudo apt-get upgrade
      sudo apt-get install openjdk-8-jdk
      wget -q -O - https://jenkins-ci.org/debian/jenkins-ci.org.key |
      sudo apt-key add -
      sudo sh -c 'echo deb http://pkg.jenkins-ci.org/debian binary/ > /etc/apt/sources.list.d/jenkins.list'
      sudo apt-get update
      sudo apt-get install jenkins git
      sudo apt-get install software-properties-common python-software-properties apt-transport-https
      sudo add-apt-repository https://dl.bintray.com/spinnaker-releases/debians
      注:
      JenkinsがKubernetesのノードのいずれかにインストールされている場合、パブリックアクセス用にそのノードのファイアウォールルールを更新する必要があります。
    4. JenkinsをSpinnakerと統合するために、quick-install.ymlファイルで以下の値を更新します。
          data:igor.yml: |
      enabled: true
      skipLifeCycleManagement: false
          ci:jenkins:
      enabled: true
        masters:
      - name: master
            address: <endpoint>
          username: <username>
        password: <password>
    5. PrometheusとGrafanaをセットアップするには、NetScaler Metrics Exporterの「PrometheusとGrafanaの統合」セクションを参照し、手順を実行します。
    6. PrometheusをSpinnakerと統合するには、quick-install.ymlファイルで以下の値を更新します。
        data:
        config: |
          deploymentConfigurations:
          canary:
          enabled: true
      serviceIntegrations:
            - name: prometheus
        enabled: true
      accounts:
        - name: my-prometheus
      endpoint:
            baseUrl: prometheus-endpoint
          supportedTypes:
      - METRICS_STORE
        data:
        config: |
          deploymentConfigurations:
          metricStores:
            prometheus:
            enabled: true
            add_source_metalabels: true
            stackdriver:
        enabled: true
          period: 30
          enabled: true
    7. 通知のためにSlackをSpinnakerと統合するには、quick-install.ymlファイルで以下の値を更新します。
      data:
       config: |
        deploymentConfigurations:
         notifications:
          slack:
           enabled: true
            botName: <BotName>
            token: <token>
    8. 必要なすべてのコンポーネントが統合されたら、次の手順を実行してSpinnakerをデプロイします。
      kubectl apply -f quick-install.yaml
    9. 次のコマンドを使用してデプロイの進行状況を確認します。デプロイが完了すると、このコマンドはすべてのポッドをReady x/xとして出力します。
      watch kubectl -n spinnaker get pods
  4. Spinnakerをデプロイしたら、次の手順を使用してデプロイをテストできます。
    1. 次のコマンドを使用して、ローカルポートをSpinnakerのdeckコンポーネントに転送することで、Spinnakerへのアクセスを有効にします。
      DECK_POD=$(kubectl -n spinnaker get pods -l \
      cluster=spin-deck,app=spin \
      -o=jsonpath='{.items[0].metadata.name}')
      kubectl -n spinnaker port-forward $DECK_POD 8080:9000 >/dev/null &
    2. Spinnakerにアクセスするには、Cloud ShellでWeb Previewアイコンをクリックし、Preview on port 8080を選択します。
      注:
      Spinnakerには安全に、またはHTTP経由でアクセスできます。Spinnakerを安全に公開するには、spin-ingress-ssl.yamlファイルを使用してIngressをデプロイします。 Spinnakerアプリケーションが公開されたら、Spinnakerに割り当てられたドメインまたはIngressのIPアドレスを使用してアクセスできます。

Spinnakerパイプラインを作成し、自動カナリアデプロイメントを構成する

Spinnakerをデプロイしたら、アプリケーション用のSpinnakerパイプラインを作成し、自動カナリアデプロイメントを構成します。
  1. Spinnakerパイプラインを作成します。Sample JSON filesで提供されているサンプルファイルを使用して、パイプラインをJSONファイルとして編集できます。
  2. Spinnakerで自動カナリア分析のための自動カナリア設定を作成します。JSONファイルで提供されている設定を、自動カナリア設定のサンプルとして使用できますサンプルJSONファイル。

カナリア用のサンプルアプリケーションをデプロイする

この例では、NetScaler統合カナリアデプロイメントソリューションを使用して、サンプルアプリケーションのカナリアデプロイメントを実行する方法を示します。この例では、NetScaler CPX、MPX、またはVPXがGKEクラスターのIngressデバイスとしてデプロイされます。NetScalerは、カナリア分析に必要なパフォーマンスメトリックを生成します。
前提条件として、サンプルアプリケーションをデプロイする前に、次の手順を完了する必要があります。

サンプルアプリケーションをデプロイする

カナリアリリースとしてサンプルアプリケーションをデプロイするには、次の手順を実行します。
  1. rbac.yamlファイルをデプロイして、NetScalerに必要なRBACルールを作成します。
    kubectl apply -f rbac.yaml
  2. NetScaler Ingress Controllerは、NetScaler CPXのサイドカーとしてデプロイすることも、NetScaler VPXまたはMPXを制御するスタンドアロンポッドとしてデプロイすることもできます。
    cpx-with-cic-sidecar.ymlファイルを使用して、NetScaler Ingress ControllerをNetScaler CPXのサイドカーとしてデプロイします。これにより、NetScaler Metrics Exporterも同じポッドにデプロイされます。
    kubectl apply -f cpx-with-cic-sidecar.yml
    NetScaler Ingress ControllerをNetScaler VPXまたはMPX用のスタンドアロンポッドとしてデプロイするには、cic-vpx.yamlファイルを使用します。このデプロイでは、NetScaler Metrics Exporterをデプロイするためにexporter.yamlファイルを使用する必要があります。
    kubectl apply -f cic-vpx.yaml
    kubectl apply -f exporter.yaml
    注:
    NetScaler Ingress Controllerのデプロイ方法に応じて、NetScaler Ingress Controllerデプロイメント用のYAMLファイルを編集し、NetScaler Ingress Controllerのデプロイに記載されている環境変数の値を変更する必要があります。
  3. spin-ingress-ssl.yamlファイルを使用して、Spinnakerを安全に公開するためのIngressをデプロイします。
    kubectl apply -f spin-ingress-ssl.yaml
    注:
    Ingress 用の TLS 証明書の作成に関する詳細については、NetScaler Ingress Controller の TLS 証明書 を参照してください。
  4. NetScaler を使用して Spinnaker が公開されたら、Spinnaker にアクセスし、まだ手順が完了していない場合は、Spinnaker パイプラインを作成し、自動カナリアデプロイメントを構成する の手順を実行します。
  5. production.yaml ファイルを使用して、アプリケーションのプロダクションバージョンをデプロイします。
    kubectl apply -f production.yaml
  6. ingress.yaml ファイルを使用して、クラスター外からのトラフィックをクラスター内のサービスに公開する Ingress リソースルールを作成します。
    kubectl apply -f ingress.yaml
  7. service.yaml ファイルを使用して、カナリアデプロイメントが必要なアプリケーションの Kubernetes サービスを作成します。
    kubectl apply -f service.yaml
  8. canary-crd-class.yaml ファイルを使用して、カナリア構成を定義するカナリア CRD をデプロイします。
    kubectl apply -f canary-crd-class.yaml
    注:
    CRD を作成したら、CRD オブジェクトを適用する前に 10 秒間待機します。
  9. カナリア構成をカスタマイズするために、カナリア CRD に基づいて CRD オブジェクト canary-crd-object.yaml を作成します。
    kubectl apply -f canary-crd-object.yaml
    次の表は、カナリア CRD オブジェクトのフィールドについて説明しています。
    フィールド 説明
    serviceNames この CRD を適用する必要があるサービスの一覧
    デプロイメント デプロイ戦略をKayentaとして指定します。
    パーセンテージ プロダクションからベースラインおよびカナリアに転送されるトラフィックの割合を指定します。
    matchExpression (オプション) カナリアバージョンとベースラインバージョンに誘導されるユーザーのサブセットを定義するために使用できる、NetScalerがサポートする任意のポリシー。トラフィックのxパーセンテージが設定されている場合、matchExpressionに一致するユーザーのサブセット内から、xパーセンテージのユーザーのみがベースラインとカナリアに転送されます。残りのユーザーはプロダクションに転送されます。
    スピナッカー サービスに適用するSpinnakerパイプライン構成を指定します。
    ドメイン SpinnakerゲートのIPアドレスまたはドメイン名。
    ポート Spinnakerゲートのポート番号。
    applicationName Spinnaker内のアプリケーション名。
    pipelineName Spinnakerアプリケーション下のパイプライン名。
    serviceName Spinnaker構成を適用するサービスの名前を指定します。
  10. アプリケーションのカナリアバージョンとベースラインバージョンをデプロイします。
    注:
    カナリアデプロイメントを完全に自動化している場合は、Spinnakerパイプラインのデプロイ (マニフェスト) ステージを使用してカナリアバージョンとベースラインバージョンをデプロイするため、この手順を実行する必要はありません。
    カナリアバージョンとベースラインバージョンを手動でデプロイするには、canary.yamlとbaseline.yamlファイルを使用します。
    kubectl apply -f canary.yaml
    kubectl apply -f baseline.yaml

トラブルシューティング

デプロイメントのトラブルシューティングを行うには、次の手順を実行します。
  1. Spinnaker、Prometheus、Kayenta、NetScaler CPX、NetScaler Metrics Exporter、NetScaler Ingress Controllerなどの各コンポーネントのPodログを確認します。
  2. NetScalerプロキシの構成中に、NetScaler Ingress ControllerのPodログで構成関連のエラーがないか確認します。
  3. 問題を絞り込むには、NetScaler Ingress ControllerのPodログでexception/Exceptionキーワードを検索します。
  4. 検索より前のログを確認します。失敗して問題を引き起こした構成を確認します。
  5. 構成中の失敗の原因を確認します。
  6. 誤った構成が原因で障害が発生した場合は、構成を修正します。

サンプルJSONファイル

このトピックには、Spinnakerパイプライン構成と自動カナリア構成のサンプルJSONファイルが含まれています。これらのファイルは、Spinnakerパイプラインと自動カナリア構成を作成する際の参照として使用できます。

Spinnakerパイプライン構成用のサンプルJSONファイル**

{
  "appConfig": {},
  "description": "This pipeline deploys a canary version of the application, and a baseline (identical to production) version.\nIt compares them, and if the canary is OK, it triggers the production deployment pipeline.",
  "executionEngine": "v2",
  "expectedArtifacts": [
    {
      "defaultArtifact": {
        "kind": "custom"
      },
      "id": "ac842617-988f-48dc-a7a4-7f020d93cc42",
      "matchArtifact": {
        "kind": "docker",
        "name": "index.docker.io/sample/demo",
        "type": "docker/image"
      },
      "useDefaultArtifact": false,
      "usePriorExecution": false
    }
  ],
  "keepWaitingPipelines": false,
  "lastModifiedBy": "anonymous",
  "limitConcurrent": true,
  "parallel": true,
  "parameterConfig": [],
  "stages": [
    {
      "account": "my-kubernetes-account",
      "cloudProvider": "kubernetes",
      "kinds": [
        "Deployment",
        "ConfigMap"
      ],
      "labelSelectors": {
        "selectors": [
          {
            "key": "version",
            "kind": "EQUALS",
            "values": [
              "canary"
            ]
          }
        ]
      },
      "location": "default",
      "name": "Delete Canary",
      "options": {
        "cascading": true
      },
      "refId": "12",
      "requisiteStageRefIds": [
        "19",
        "26"
      ],
      "type": "deleteManifest"
    },
    {
      "account": "my-kubernetes-account",
      "cloudProvider": "kubernetes",
      "kinds": [
        "Deployment"
      ],
      "labelSelectors": {
        "selectors": [
          {
            "key": "version",
            "kind": "EQUALS",
            "values": [
              "baseline"
            ]
          }
        ]
      },
      "location": "default",
      "name": "Delete Baseline",
      "options": {
        "cascading": true
      },
      "refId": "13",
      "requisiteStageRefIds": [
        "19",
        "26"
      ],
      "type": "deleteManifest"
    },
    {
      "name": "Successful deployment",
      "preconditions": [],
      "refId": "14",
      "requisiteStageRefIds": [
        "12",
        "13"
      ],
      "type": "checkPreconditions"
    },
    {
      "application": "sampleapplicaion",
      "expectedArtifacts": [
        {
          "defaultArtifact": {
            "kind": "custom"
          },
          "id": "9185c756-c6cd-49bc-beee-e3f7118f3412",
          "matchArtifact": {
            "kind": "docker",
            "name": "index.docker.io/sample/demo",
            "type": "docker/image"
          },
          "useDefaultArtifact": false,
          "usePriorExecution": false
        }
      ],
      "failPipeline": true,
      "name": "Deploy to Production",
      "pipeline": "7048e5ac-2464-4557-a05a-bec8bdf868fc",
      "refId": "19",
      "requisiteStageRefIds": [
        "25"
      ],
      "stageEnabled": {
        "expression": "\"${ #stage('Canary Analysis')['status'].toString() == 'SUCCEEDED'}\"",
        "type": "expression"
      },
      "type": "pipeline",
      "waitForCompletion": true
    },
    {
      "account": "my-kubernetes-account",
      "cloudProvider": "kubernetes",
      "manifestArtifactAccount": "embedded-artifact",
      "manifests": [
        {
          "apiVersion": "apps/v1",
          "kind": "Deployment",
          "metadata": {
            "labels": {
              "name": "sampleapplicaion-prod",
              "version": "baseline"
            },
            "name": "sampleapplicaion-baseline-deployment",
            "namespace": "default"
          },
          "spec": {
            "replicas": 4,
            "strategy": {
              "rollingUpdate": {
                "maxSurge": 10,
                "maxUnavailable": 10
              },
              "type": "RollingUpdate"
            },
            "template": {
              "metadata": {
                "labels": {
                  "name": "sampleapplicaion-prod"
                }
              },
              "spec": {
                "containers": [
                  {
                    "image": "index.docker.io/sample/demo:v1",
                    "imagePullPolicy": "Always",
                    "name": "sampleapplicaion-prod",
                    "ports": [
                      {
                        "containerPort": 8080,
                        "name": "port-8080"
                      }
                    ]
                  }
                ]
              }
            }
          }
        }
      ],
      "moniker": {
        "app": "sampleapplicaion"
      },
      "name": "Deploy Baseline",
      "refId": "20",
      "relationships": {
        "loadBalancers": [],
        "securityGroups": []
      },
      "requisiteStageRefIds": [],
      "source": "text",
      "type": "deployManifest"
    },
    {
      "account": "my-kubernetes-account",
      "cloudProvider": "kubernetes",
      "manifestArtifactAccount": "embedded-artifact",
      "manifests": [
        {
          "apiVersion": "apps/v1",
          "kind": "Deployment",
          "metadata": {
            "labels": {
              "name": "sampleapplicaion-prod",
              "version": "canary"
            },
            "name": "sampleapplicaion-canary-deployment",
            "namespace": "default"
          },
          "spec": {
            "replicas": 4,
            "strategy": {
              "rollingUpdate": {
                "maxSurge": 10,
                "maxUnavailable": 10
              },
              "type": "RollingUpdate"
            },
            "template": {
              "metadata": {
                "labels": {
                  "name": "sampleapplicaion-prod"
                }
              },
              "spec": {
                "containers": [
                  {
                    "image": "index.docker.io/sample/demo",
                    "imagePullPolicy": "Always",
                    "name": "sampleapplicaion-prod",
                    "ports": [
                      {
                        "containerPort": 8080,
                        "name": "port-8080"
                      }
                    ]
                  }
                ]
              }
            }
          }
        }
      ],
      "moniker": {
        "app": "sampleapplicaion"
      },
      "name": "Deploy Canary",
      "refId": "21",
      "relationships": {
        "loadBalancers": [],
        "securityGroups": []
      },
      "requiredArtifactIds": [
        "ac842617-988f-48dc-a7a4-7f020d93cc42"
      ],
      "requisiteStageRefIds": [],
      "source": "text",
      "type": "deployManifest"
    },
    {
      "analysisType": "realTime",
      "canaryConfig": {
        "beginCanaryAnalysisAfterMins": "2",
        "canaryAnalysisIntervalMins": "",
        "canaryConfigId": "7bdb4ab4-f933-4a41-865f-6d3e9c786351",
        "combinedCanaryResultStrategy": "LOWEST",
        "lifetimeDuration": "PT0H5M",
        "metricsAccountName": "my-prometheus",
        "scopes": [
          {
            "controlLocation": "default",
            "controlScope": "k8s-sampleapplicaion.default.80.k8s-sampleapplicaion.default.8080.svc-baseline",
            "experimentLocation": "default",
            "experimentScope": "k8s-sampleapplicaion.default.80.k8s-sampleapplicaion.default.8080.svc-canary",
            "extendedScopeParams": {},
            "scopeName": "default"
          }
        ],
        "scoreThresholds": {
          "marginal": "0",
          "pass": "70"
        },
        "storageAccountName": "kayenta-minio"
      },
      "name": "Canary Analysis",
      "refId": "25",
      "requisiteStageRefIds": [
        "20",
        "21"
      ],
      "type": "kayentaCanary"
    },
    {
      "continuePipeline": false,
      "failPipeline": true,
      "job": "NJob",
      "master": "master",
      "name": "Auto Cleanup:  GCR Image and code revert",
      "parameters": {},
      "refId": "26",
      "requisiteStageRefIds": [
        "25"
      ],
      "stageEnabled": {
        "type": "expression"
      },
      "type": "jenkins"
    }
  ],
  "triggers": [
    {
      "account": "my-docker-registry",
      "enabled": true,
      "expectedArtifactIds": [
        "ac842617-988f-48dc-a7a4-7f020d93cc42"
      ],
      "organization": "sample",
      "payloadConstraints": {},
      "registry": "index.docker.io",
      "repository": "sample/demo",
      "source": "dockerhub",
      "type": "webhook"
    }
  ],
  "updateTs": "1553144362000"
}

自動カナリア構成のサンプルJSONファイル

以下は、自動カナリア構成のサンプルJSONファイルです。
{
  "applications": [
    "sampleapplicaion"
  ],
  "classifier": {
    "groupWeights": {
      "Group 1": 70,
      "Group 2": 30
    },
    "scoreThresholds": {
      "marginal": 75,
      "pass": 95
    }
  },
  "configVersion": "1",
  "createdTimestamp": 1552650414234,
  "createdTimestampIso": "2019-03-15T11:46:54.234Z",
  "description": "Canary Config",
  "judge": {
    "judgeConfigurations": {},
    "name": "NetflixACAJudge-v1.0"
  },
  "metrics": [
    {
      "analysisConfigurations": {
        "canary": {
          "direction": "increase"
        }
      },
      "groups": [
        "Group 1"
      ],
      "name": "Server Response Errors - 5XX",
      "query": {
        "customFilterTemplate": "tot_requests",
        "metricName": "netscaler_lb_vserver_svr_busy_err_rate",
        "serviceType": "prometheus",
        "type": "prometheus"
      },
      "scopeName": "default"
    },
    {
      "analysisConfigurations": {
        "canary": {
          "direction": "either",
          "nanStrategy": "replace"
        }
      },
      "groups": [
        "Group 2"
      ],
      "name": "Server Response Latency - TTFB",
      "query": {
        "customFilterTemplate": "ttfb",
        "metricName": "netscaler_lb_vserver_hits_total",
        "serviceType": "prometheus",
        "type": "prometheus"
      },
      "scopeName": "default"
    }
  ],
  "name": "canary-config",
  "templates": {
    "tot_requests": "lb_vserver_name = \"${scope}\"",
    "ttfb": "lb_vserver_name = \"${scope}\""
  },
  "updatedTimestamp": 1553098513495,
  "updatedTimestampIso": "2019-03-20T16:15:13.495Z"
}

Ingressアノテーションを使用した簡素化されたカナリアデプロイ

このトピックでは、Ingressアノテーションを使用した簡素化されたカナリアデプロイメントに関する情報を提供します。NetScalerはカナリアデプロイメントをサポートするための複数のオプションを提供していますが、これはよりシンプルなタイプのカナリアデプロイメントです。
Ingressアノテーションを使用したカナリアは、ルールベースのカナリアデプロイメントです。このアプローチでは、アプリケーションリクエストがルールベースのカナリアデプロイメント戦略に基づいて処理される必要があることを示すために、特定の注釈を持つ追加のIngressオブジェクトを定義する必要があります。Citrixソリューションでは、Ingressレベルでのカナリアベースのトラフィックルーティングは、次のようにさまざまなルールセットを定義することで実現できます。
  • 重みに基づいてカナリアルールを適用する
  • HTTPリクエストヘッダーに基づいてカナリアルールを適用する
  • HTTPヘッダー値に基づいてカナリアルールを適用する
カナリアルールの優先順位は次のとおりです。
HTTPリクエストヘッダー値によるカナリア --> HTTPリクエストヘッダーによるカナリア --> 重みによるカナリア

重みに基づくカナリアデプロイ

重みベースのカナリアデプロイメントは、広く使用されているカナリアデプロイメントのアプローチです。このアプローチでは、カナリアバージョンとアプリケーションのプロダクションバージョンに振り分けられるトラフィックの割合を決定する重みを0から100の範囲で設定できます。
重みベースのカナリアデプロイメントのワークフローは次のとおりです。
  • 最初は重みをゼロに設定できます。これは、トラフィックがカナリアバージョンに転送されないことを示します。
  • カナリアデプロイメントを開始することを決定したら、トラフィックがカナリアバージョンにも向けられるように、重みを必要なパーセンテージに変更します。
  • 最後に、カナリアバージョンがリリース準備完了であると判断したら、すべてのトラフィックがカナリアバージョンに転送されるように、重みを100に変更します。
NetScaler Ingress Controller を使用して重みベースのカナリアをデプロイするには、カナリアアノテーション ingress.citrix.com/canary-weight: を持つ新しい Ingress を作成し、カナリアバージョンに転送するトラフィックの割合を指定します。

HTTPリクエストヘッダーに基づくカナリアデプロイメント

クライアントによって制御されるHTTPリクエストヘッダーに基づいてカナリアデプロイメントを構成できます。リクエストヘッダーは、カナリアIngressで指定されたサービスにリクエストをルーティングするようにIngressに通知します。リクエストヘッダーにIngressアノテーション ingress.citrix.com/canary-by-header: で指定された値が含まれている場合、リクエストはカナリアIngressで指定されたサービスにルーティングされます。

HTTPリクエストヘッダー値に基づくカナリアデプロイメント

ヘッダーによるカナリアの拡張であるHTTPリクエストヘッダーの値に基づいてカナリアデプロイメントを構成することもできます。このデプロイメントでは、ingress.citrix.com/canary-by-header: アノテーションに加えて、ingress.citrix.com/canary-by-header-value: アノテーションも指定します。リクエストヘッダー値がIngressアノテーション ingress.citrix.com/canary-by-header-value: で指定された値と一致する場合、リクエストはカナリアIngressで指定されたサービスにルーティングされます。複数のヘッダー値を文字列のリストとして指定できます。
HTTPリクエストヘッダー値に基づくカナリアデプロイメントのサンプルアノテーションは次のとおりです。
ingress.citrix.com/canary-by-header-value: ''

Ingressアノテーションを使用したカナリアデプロイメントの構成

サンプルアプリケーションをカナリアリリースとしてデプロイするには、次の手順を実行します。
  1. NetScaler Ingress Controller をデプロイする の手順に従って、NetScaler Ingress Controller をデプロイします。NetScaler Ingress Controller は、NetScaler CPX とともにサイドカーとしてデプロイすることも、NetScaler VPX または MPX を制御するスタンドアロンポッドとしてデプロイすることもできます。
  2. guestbook-deploy.yaml ファイルを使用して、Guestbook アプリケーションをデプロイします。
    kubectl apply -f guestbook-deploy.yaml
  3. guestbook-service.yaml ファイルを使用して、Guestbook アプリケーションを公開するサービスをデプロイします。
    kubectl apply -f guestbook-service.yaml
  4. Guestbookアプリケーション用のIngressオブジェクトをguestbook-ingress.yamlファイルを使用してデプロイします。
    kubectl apply -f  guestbook-ingress.yaml
  5. Guestbookアプリケーションのカナリアバージョンをcanary-deployment.yamlファイルを使用してデプロイします。
    kubectl apply –f canary-deployment.yaml
  6. Guestbookアプリケーションのカナリアバージョンを公開するサービスをcanary-service.yamlファイルを使用してデプロイします。
    kubectl apply –f canary-service.yaml
  7. Guestbookアプリケーションのカナリアバージョン用のアノテーション付きIngressオブジェクトをcanary-ingress.yamlファイルを使用してデプロイします。
        kubectl apply –f canary-ingress.yaml



          apiVersion: networking.k8s.io/v1
          kind: Ingress
          metadata:
            annotations:
                ingress.citrix.com/canary-weight: "10"
            name: canary-by-weight
          spec:
            ingressClassName: citrix
            rules:
            - host: webapp.com
              http:
                paths:
                - backend:
                    service:
                      name: guestbook-canary
                      port:
                        number: 80
                  path: /
                  pathType: Prefix
    ここで、アノテーションingress.citrix.com/canary-weight: “10”は、重みベースのカナリア用のアノテーションです。このアノテーションは、webapp.com宛ての総リクエストの10パーセントがguestbook-canaryサービスに送信されるようにNetScalerを構成するようNetScaler Ingress Controllerに指定します。これは、Guestbookアプリケーションのカナリアバージョン用のサービスです。
NetScaler Ingress Controllerを使用してHTTPヘッダーベースのカナリアをデプロイするには、canary-ingress.yamlファイル内のカナリアアノテーションingress.citrix.com/canary-weight:をingress.citrix.com/canary-by-header:アノテーションに置き換えます。
NetScaler Ingress Controllerを使用してHTTPヘッダー値ベースのカナリアをデプロイするには、canary-ingress.yamlファイル内のingress.citrix.com/canary-weight:アノテーションをingress.citrix.com/canary-by-header:とingress.citrix.com/canary-by-header-value:アノテーションに置き換えます。
注:
ヘッダーベースのカナリアとヘッダー値ベースのカナリアを実現するためのCanary example YAMLsを参照してください。