Citrix ADC ingress controller

Citrix ADC統合カナリア展開ソリューションを展開する

Canary リリースとは、最初に一部のユーザーに変更をロールアウトすることで、新しいソフトウェアバージョンが本番環境に導入されるリスクを軽減する手法です。ユーザー検証後、アプリケーションは多数のユーザーにロールアウトされます。

Citrix Ingress Controllerを使用したカナリア展開では、次のオプションが用意されています。

Canary CRD を使用するデプロイメントでは、Kubernetes CRD を使用してカナリア設定が適用されます。Citrix では、Ingressアノテーションを使用したCanary展開のよりシンプルなオプションもサポートしています。

Canary CRD を使ってカナリアをデプロイする

このセクションでは、Canary CRD を使用して Canary デプロイメントを実行する方法について説明します。

Citrix ADCに統合されたCanary Deploymentソリューションは、継続的デリバリー(CD)のすべてのコンポーネントを結合し、アプリケーション開発者がカナリア展開を容易にします。このソリューションでは、継続的デリバリープラットフォームとして Spinnaker を使用し、カナリア分析用の Spinnaker プラグインとして Kayenta を使用します。Kayenta はオープンソースのカナリア分析サービスで、ユーザーが構成したメトリクスをソースから取得し、統計テストを実行し、カナリアの集計スコアを提供します。統計的テストとカウンターのスコアと成功基準は、カナリアの昇格または不合格に使用されます。

Citrix ADC には、アプリケーション中心の豊富な構成モジュールが付属しており、アプリケーショントラフィックとアプリケーションインスタンスの状態を完全に可視化します。正確なパフォーマンス統計を生成するCitrix ADC 機能をCanary分析に活用して、Canaryの展開についてより適切な意思決定を行うことができます。このソリューションでは、Citrix ADCはSpinnakerプラットフォームと統合され、Kayentaを使用してCanary展開を分析するための正確なメトリックを提供するソースとして機能します。

Citrix ADC Metrics Exporterは 、アプリケーションのパフォーマンスメトリックをオープンソースの監視システムPrometheusにエクスポートし、カナリア展開のメトリックをフェッチするようにKayentaを構成できます。Canaryバージョンへのトラフィック分散は、Citrix ADCポリシーインフラストラクチャを使用して規制できます。特定の種類のトラフィックを本番環境からベースラインおよびカナリアに転送する場合は、一致式を使用して、豊富なCitrix ADCポリシーインフラストラクチャを活用してトラフィックをベースラインとカナリアにリダイレクトできます。

たとえば、一致式 HTTP.REQ.URL.CONTAINS (「citrix india」) を使用して、トラフィックを本番環境からカナリアおよびベースラインに迂回させることができます。式に一致するトラフィックは Canary と baseline に転送され、残りのトラフィックは本番環境に転送されます。

Citrix 統合 Canary 展開ソリューションに含まれるコンポーネントとその機能は次のとおりです。

  • 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は膨大なデータを時系列データベースに保持できる監視システムです。Citrix ADC メトリックは、Prometheus を通じてパフォーマンスメトリックをスピネーカーに公開します。

  • Jenkins: Jenkins はオープンソースのオートメーションサーバーで、ソフトウェアのビルド、テスト、デリバリー、デプロイに関連するあらゆる種類のタスクを自動化するのに役立ちます。Jenkins は、デプロイサイクルの一部としてカスタムスクリプトの実行もサポートしています。

  • Citrix Ingress Controller Citrix は、ベアメタルおよびクラウド展開用のCitrix ADC MPX(ハードウェア)、Citrix ADC VPX(仮想化)、およびCitrix ADC CPX(コンテナ化)用のIngress Controller を提供しています。Citrix Ingress Controller はKubernetes Ingress を中心に構築され、Ingressリソース構成に基づいて1つ以上のCitrix ADCを自動的に構成します。

Citrix 統合 Canary 展開ソリューションには、次のCitrixソフトウェアバージョンが必要です。

  • Citrix Ingress Controller ビルド/バージョン: quay.io/citrix/citrix-k8s-ingress-controller:1.26.7
  • Citrix ADC CPX バージョン: quay.io/citrix/citrix-k8s-cpx-ingress:13.0-83.27
  • Citrix ADCメトリックエクスポータのバージョン: quay.io/citrix/netscaler-metrics-exporter:1.4.0

Citrix ADC 統合カナリア展開ソリューションのスピネーカーパイプラインのワークフロー

次の図は、Citrix ADC 統合カナリア展開ソリューションのスピネーカーパイプラインのワークフローを示しています。

Spinnaker_pipeline

次の手順では、この図で指定されているワークフローについて説明します。

  1. 開発者はソースコードを GitHub で管理し、必要に応じて変更を加え、その変更を GitHub にコミットします。
  2. ソースコードの変更をリッスンするように Webhook が GitHub に設定されています。ソースコードが GitHub にチェックインされるたびに Webhook がトリガーされ、新しいソースコードでイメージをビルドするように Docker Hub に通知されます。Docker イメージが作成されると、Docker Hub に設定された別の Webhook が Spinnaker パイプラインをトリガーします。
  3. Spinnaker パイプラインがトリガーされると、Canary バージョンとベースラインバージョンのイメージがデプロイされます。
  4. Canary バージョンとベースラインバージョンがデプロイされると、本番環境からのトラフィックの一部が Canary バージョンとベースラインバージョンに転送されます。Citrix ADCは、Citrix ADCメトリックエクスポーターの助けを借りて、パフォーマンス統計を収集し、その統計をPrometheusにエクスポートします。Prometheus は、カナリア分析のためにこれらの統計を Kayenta に供給します。

  5. Kayenta はパフォーマンス統計に基づいてカナリア分析を実行し、スコアを生成します。このスコアに基づいて、Canary デプロイメントは成功または失敗と呼ばれ、イメージはロールアウトまたはロールバックされます。

Citrix ADC統合カナリア展開ソリューションをGoogle Cloud Platform に展開する

このセクションでは、Spinnaker の設定、Spinnaker パイプラインの作成方法、および Canary デプロイの例について説明します。

Google Cloud Platform にスピネーカーをデプロイする

このトピックでは、Spinnaker のデプロイに関する情報、および Google Cloud Platform(GCP)でのカナリアデプロイのためにプラグインを Spinnaker と統合する方法について説明します。

Spinnaker をデプロイし、プラグインを GCP に統合するには、次の手順を実行します。

  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. 次の手順に従って、Spinnaker を GKE クラスタに展開します。

    1. Spinnaker Webサイトからスピネーカーのquick-install.ymlファイルをダウンロードします
    2. quick-install.yml ファイルを更新して、Docker Hub 以降のさまざまなコンポーネントを統合します。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を設定するにはCitrix ADCメトリックエクスポーターの 「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 コンポーネントに転送して、スピネーカーアクセスを有効にします。

      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 にアクセスするには、クラウドシェルで [ Web プレビュー] アイコンをクリックし 、[ ポート 8080 でプレビュー] を選択します。

      注:

      Spinnaker には、安全に、または HTTP 経由でアクセスできます。スピネーカーを安全に公開するには、 spin-ingress-ssl.yaml ファイルを使用して Ingress をデプロイします。 Spinnaker アプリケーションが公開されると、Spinnaker に割り当てられたドメインまたは Ingress の IP アドレスを使用してアクセスできます。

Spinnaker パイプラインを作成し、自動化されたカナリアデプロイメントを設定する

Spinnaker をデプロイしたら、アプリケーションの Spinnaker パイプラインを作成し、自動化されたカナリアデプロイメントを設定します。

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

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

この例では、Citrix ADC統合Canary展開ソリューションを使用してサンプルアプリケーションのCanary展開を実行する方法を示します。この例では、Citrix ADC CPX、MPX、またはVPXがGKEクラスタのIngressデバイスとして展開されています。Citrix ADC は、カナリア分析に必要なパフォーマンスメトリックを生成します。

前提条件として、サンプルアプリケーションを配備する前に、次の手順を完了しておく必要があります。

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

サンプルアプリケーションを Canary リリースとしてデプロイするには、次の手順を実行します。

  1. rbac.yaml ファイルを展開して、Citrix ADC に必要なRBACルールを作成します

    kubectl apply -f rbac.yaml
    
  2. Citrix Ingress Controller は、Citrix ADC CPX のサイドカーとして、または Citrix ADC VPX または MPX を制御するスタンドアロンポッドとして展開できます。

    cpx-with-cic-sidecar.yml ファイルを使用して、Citrix ADC CPXのサイドカーとしてCitrixIngress Controllerを展開します。また、Citrix ADC メトリックエクスポーターを同じポッドに展開します。

    kubectl apply -f cpx-with-cic-sidecar.yml 
    

    Citrix Ingress Controller を Citrix ADC VPX または MPX のスタンドアロンポッドとして展開するには、 cic-vpx.yaml ファイルを使用します。この展開では、 exporter.yaml ファイルを使用して Citrix ADC メトリックエクスポーターを展開する必要があります。

    kubectl apply -f cic-vpx.yaml
    kubectl apply -f exporter.yaml
    

    注:

    Citrix Ingress Controllerのデプロイ方法に応じて、Citrix Ingress Controller デプロイメント用の YAML ファイルを編集し、「Citrix Ingress Controller デプロイ」に記載されている環境変数の値を変更する必要があります。

  3. spin-ingress-ssl.yaml ファイルを使用してスピネーカーを安全に公開するために Ingress を展開します。

    kubectl apply -f spin-ingress-ssl.yaml
    

    注:

    Ingress用のTLS証明書の作成について詳しくは、「 Citrix IngIngress Controller でのTLS証明書」を参照してください。

  4. Citrix ADC を使用してスピネーカーを公開したら、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 を作成したら、10 秒間待ってから CRD オブジェクトを適用します。

  9. カナリア構成をカスタマイズするために、 カナリア CRD に基づいて CRD オブジェクト canary-crd-object.yaml を作成します。

    kubectl apply -f canary-crd-object.yaml
    

    次の表では、Canary CRD オブジェクトのフィールドについて説明します。

    フィールド 説明
    ServiceNames この CRD を適用する必要があるサービスのリスト
    配備 デプロイメントストラテジーを Kayenta として指定します。
    パーセント 本番環境からベースラインおよびカナリアに迂回するトラフィックの割合を指定します。
    マッチエクスプレッション (オプション) Citrix ADCがサポートするポリシー。Canaryバージョンとベースラインバージョンにリダイレクトされるユーザーのサブセットを定義するために使用できます。x パーセントのトラフィックが設定されている場合、MatchExpression に一致するユーザのサブセット内から x パーセントのユーザだけがベースラインとカナリアに転送されます。残りのユーザーは本番環境に移行されます。
    スピネーカー サービスに適用する Spinnaker パイプライン設定を指定します。
    ドメイン スピネーカーゲートの IP アドレスまたはドメイン名。
    port スピネーカーゲートのポート番号。
    アプリケーション名 Spinnaker 内のアプリケーションの名前。
    PipelineName Spinnaker アプリケーションの下にあるパイプラインの名前。
    serviceName スピネーカー設定を適用するサービスの名前を指定します。
  10. Canary バージョンとベースラインバージョンのアプリケーションをデプロイします。

    注:

    Canary デプロイを完全に自動化する場合は、Spinnaker パイプラインの Deploy (Manifest) ステージを使用して Canary バージョンとベースラインバージョンをデプロイします 。この手順を実行する必要はありません。

    Canary バージョンとベースラインバージョンを手動でデプロイするには、 canary.yaml ファイルと baseline.yaml ファイルを使用します。

    kubectl apply -f canary.yaml
    kubectl apply -f baseline.yaml
    

トラブルシューティング

展開のトラブルシューティングを行うには、次の手順を実行します。

  1. スピネーカー、Prometheus、Kayenta、Citrix ADC CPX、Citrix ADC メトリックエクスポーター、Citrix Ingress Controller などのそれぞれのコンポーネントがあるようにポッドログを確認します。
  2. Citrix プロキシの構成中に、Citrix Ingress Controller ポッドログに構成関連のエラーがないか確認します。
  3. Citrix Ingress Controllerポッドログで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"
}
<!--NeedCopy-->

カナリア構成を自動化するためのサンプル 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"
}
<!--NeedCopy-->

Ingress アノテーションを使用した Canary デプロイの簡略化

このトピックでは、Ingress アノテーションを使用した簡略化された Canary デプロイメントに関する情報を提供します。CitrixはCanary展開をサポートするために複数のオプションを提供していますが、Canary展開の方がシンプルなタイプです。

Ingress アノテーションを使用する Canary は、ルールベースのカナリアデプロイメントです。このアプローチでは、ルールベースのカナリアデプロイメント戦略に基づいてアプリケーションリクエストを処理する必要があることを示すために、特定のアノテーションを持つ追加の Ingress オブジェクトを定義する必要があります。Citrix ソリューションでは、IngressレベルでのCanaryベースのトラフィックルーティングは、以下のようにさまざまなルールセットを定義することで実現できます。

  • 体重に基づいてカナリアールを適用する
  • HTTP リクエストヘッダーに基づいた Canary ルールの適用
  • HTTP ヘッダー値に基づいてカナリアールを適用する

カナリアールールの優先順位は次のとおりです。

Canary by HTTP リクエストヘッダー値 —> Canary by HTTP リクエストヘッダー —> Canary by Weight

体重に基づくカナリア配備

重量ベースのカナリア配備は、広く使用されているカナリア配備アプローチです。この方法では、重みを 0 ~ 100 の範囲で設定できます。これにより、アプリケーションの Canary バージョンと本番バージョンに送信されるトラフィックの割合が決まります。

重量ベースのカナリア展開のワークフローを次に示します。

  • 最初は、重みを 0 に設定できます。これは、トラフィックが Canary バージョンに転送されないことを示します。

  • Canary デプロイを開始することを決定したら、トラフィックが Canary バージョンにも誘導されるように、加重を必要なパーセンテージに変更します。

  • 最後に、Canary バージョンをリリースする準備ができていると判断したら、すべてのトラフィックが Canary バージョンに転送されるように、ウェイトを 100 に変更します。

Citrix Ingress Controller を使用して重量ベースのカナリアを展開するには、Canaryアノテーションingress.citrix.com/canary-weight:付きの新しいIngressを作成し、Canaryバージョンに転送されるトラフィックの割合を指定します。

HTTP リクエストヘッダーに基づく Canary デプロイ

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

HTTP リクエストヘッダー値に基づく Canary デプロイ

Canary by header の拡張である HTTP リクエストヘッダーの値に基づいて Canary デプロイメントを設定することもできます。この展開では、 ingress.citrix.com/canary-by-header: 注釈とともに、ingress.citrix.com/canary-by-header-value:注釈も指定します。リクエストヘッダーの値が Ingressアノテーションingress.citrix.com/canary-by-header-value:で指定された値と一致すると、リクエストは Canary Ingress で指定されたサービスにルーティングされます。複数のヘッダー値を文字列のリストとして指定できます。

以下は、HTTP リクエストヘッダー値に基づく Canary デプロイメントのサンプルアノテーションです。

ingress.citrix.com/canary-by-header-value: ‘[“value1”,”value2”,”value3”,”value4”]’

Ingress アノテーションを使用してカナリアデプロイメントを設定する

サンプルアプリケーションを Canary リリースとしてデプロイするには、次の手順を実行します。

  1. Citrix Ingress Controller 展開の手順に従って、 Citrix Ingress Controller を展開します。Citrix Ingress Controller は、Citrix ADC CPX のサイドカーとして、または Citrix ADC 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.yaml ファイルを使用して、 Guestbook アプリケーションの Ingress オブジェクトをデプロイします。

      kubectl apply -f  guestbook-ingress.yaml
    
  5. canary-deployment.yaml ファイルを使用して、 Guestbook アプリケーションのカナリアバージョンをデプロイします

        kubectl apply –f canary-deployment.yaml
    
  6. canary-service.yaml ファイルを使用して、CanaryバージョンのGuestbookアプリケーションを公開するサービスをデプロイします。

        kubectl apply –f canary-service.yaml       
    
  7. canary-ingress.yaml ファイルを使用して、 Guestbook アプリケーションのカナリアバージョンのアノテーションを含む Ingress オブジェクトをデプロイします。

        kubectl apply –f canary-ingress.yaml
    
    
    
          apiVersion: networking.k8s.io/v1
          kind: Ingress
          metadata:
            annotations:
              ingress.citrix.com/canary-weight: "10"
              kubernetes.io/ingress.class: citrix
            name: canary-by-weight
          spec:
            rules:
            - host: webapp.com
              http:
                paths:
                - backend:
                    service:
                      name: guestbook-canary
                      port:
                        number: 80
                  path: /
                  pathType: Prefix
    

    Here, the annotation ingress.citrix.com/canary-weight: “10” is the annotation for the weight based canary. This annotation specifies the Citrix ingress controller to configure the Citrix ADC in such a way that 10 percent of the total requests destined to webapp.com is sent to the guestbook-canary service. This is the service for the canary version of the Guestbook application.

Citrix Ingress Controller を使用して HTTP ヘッダーベースの Canary を展開する場合は、Canaryアノテーションingress.citrix.com/canary-weight:canary-ingress.yamlファイル内のingress.citrix.com/canary-by-header: アノテーションに置き換えます。

Citrix Ingress Controllerを使用してHTTPヘッダー値ベースのCanaryをデプロイする場合は、canary-ingress.yamlファイル内のingress.citrix.com/canary-weight:注釈をingress.citrix.com/canary-by-header:およびingress.citrix.com/canary-by-header-value:注釈に置き換えます。

注:

ヘッダーに基づく Canary と、ヘッダー値に基づく Canary を達成するための YAML の例を見ることができます

Citrix ADC統合カナリア展開ソリューションを展開する