完全な切り替えの前に、ヘッダー、Cookie、または重みに基づいて、新しいサービスバージョンにトラフィックを段階的に移行します。
背景情報
段階的リリース (カナリアリリースとも呼ばれます) とブルーグリーンリリースは、どちらも旧バージョンと並行して新バージョンを実行し、トラフィックの一部を新バージョンにルーティングします。新バージョンが安定したら、すべてのトラフィックを切り替え、旧バージョンを廃止します。
ACK Nginx Ingress Controller は、アノテーションに基づいた 2 つのトラフィック分割方式をサポートしています:
| メソッド | ステータス | 注 |
|---|---|---|
canary-* アノテーション |
アクティブ | 公式コミュニティの方式です。すべての新しい構成には、この方式を使用してください。 |
service-* アノテーション |
非推奨 | Nginx Ingress Controller v1.12 以降では利用できなくなりました。使用しないでください。 |
利用シーン
-
クライアントリクエストに基づくトラフィック分割:リクエストに特定のヘッダーまたは Cookie (例:
foo=bar) が含まれている場合にのみ、新バージョンにトラフィックをルーティングします。その他のリクエストは旧バージョンにルーティングされます。安定したら、すべてのトラフィックを切り替えます。 -
サービスの重みに基づくトラフィック分割:トラフィックの一定の割合 (例:20%) を新バージョンにルーティングします。すべてのトラフィックが新バージョンにルーティングされるまで、この割合を徐々に増やしていきます。
サポートされているトラフィック分割のディメンション:
-
リクエストヘッダー — 段階的リリースおよび A/B テストに適しています
-
Cookie — 段階的リリースおよび A/B テストに適しています
-
クエリパラメーター — 段階的リリースおよび A/B テストに適しています
-
サービスの重み — ブルーグリーンリリースに適しています
canary-* アノテーション方式
アノテーションリファレンス
すべてのカナリア構成には、nginx.ingress.kubernetes.io/canary: "true" アノテーションが必要です。その他のアノテーションはルーティングロジックを定義します。
| アノテーション | 説明 | 最小バージョン |
|---|---|---|
nginx.ingress.kubernetes.io/canary |
カナリア機能を有効にします。他のカナリアアノテーションを有効にするには、true に設定する必要があります。有効な値:true、false。
|
>=v0.22.0 |
nginx.ingress.kubernetes.io/canary-by-header |
リクエストヘッダーに基づいて、リクエストをカナリアサービスにルーティングします。特別な値:always (常にカナリアにルーティング)、never (カナリアにルーティングしない)。値が指定されていない場合、ヘッダーが存在するたびにトラフィックが転送されます。 |
>=v0.22.0 |
nginx.ingress.kubernetes.io/canary-by-header-value |
canary-by-header で指定されたヘッダーが正確な値と一致する場合に、リクエストをカナリアサービスにルーティングします。canary-by-header と一緒に使用する必要があります。 |
>=v0.30.0 |
nginx.ingress.kubernetes.io/canary-by-header-pattern |
canary-by-header で指定されたヘッダーが正規表現と一致する場合に、リクエストをカナリアサービスにルーティングします。canary-by-header と一緒に使用する必要があります。 |
>=v0.44.0 |
nginx.ingress.kubernetes.io/canary-by-cookie |
Cookie に基づいてリクエストをカナリアサービスにルーティングします。例:nginx.ingress.kubernetes.io/canary-by-cookie: foo。Cookie の値:always (foo=always はカナリアにルーティング)、never (foo=never はルーティングしない)。トラフィックは、Cookie が存在し、その値が always の場合にのみ転送されます。 |
>=v0.22.0 |
nginx.ingress.kubernetes.io/canary-weight |
重みに基づいて、リクエストのパーセンテージをカナリアサービスにルーティングします。範囲:0 から canary-weight-total (デフォルトは 100)。 |
>=v0.22.0 |
nginx.ingress.kubernetes.io/canary-weight-total |
合計の重みの分母を設定します。デフォルト:100。 |
>=v1.1.2 |
アノテーションの優先度 (降順):
canary-by-header > canary-by-cookie > canary-weight
各 Ingress ルールは、1 つのカナリア Ingress のみをサポートします。追加のカナリア Ingress は無視されます。
ステップ 1:サービスのデプロイ
Nginx サービスをデプロイし、Nginx Ingress Controller を使用してレイヤー 7 ドメインアクセス用に公開します。
-
Deployment と Service を作成します。次の内容を
nginx.yamlとして保存します。マニフェストを適用します:
kubectl apply -f nginx.yaml -
Ingress を作成します。次の内容を
ingress.yamlとして保存します。v1.19 以降のクラスター
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: gray-release spec: ingressClassName: nginx rules: - host: www.example.com http: paths: # サービスの旧バージョン - path: / backend: service: name: old-nginx port: number: 80 pathType: ImplementationSpecificv1.19 より前のクラスター
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: gray-release spec: rules: - host: www.example.com http: paths: # サービスの旧バージョン - path: / backend: serviceName: old-nginx servicePort: 80マニフェストを適用します:
kubectl apply -f ingress.yaml -
デプロイメントを検証します。外部 IP アドレスを取得します:
kubectl get ingressルーティングアクセスを確認します:
curl -H "Host: www.example.com" http://<EXTERNAL_IP>期待される出力:
old
ステップ 2:新しいサービスバージョンのリリース
新しい Nginx バージョンをデプロイし、カナリアルーティングルールを構成します。
-
新しい Deployment と Service を作成します。次の内容を
nginx1.yamlとして保存します。マニフェストを適用します:
kubectl apply -f nginx1.yaml -
新しいバージョンにトラフィックをルーティングするためのカナリア Ingress を作成します。3 つの戦略が利用可能です。戦略 A:リクエストヘッダーによるルーティング
fooヘッダーがbarと等しい場合にのみ、リクエストを新しいバージョンにルーティングします。その他のリクエストは古いバージョンにルーティングされます。次の内容をingress1.yamlとして保存します。v1.19 以降のクラスターの場合:-
`foo: bar` ヘッダーあり:トラフィックの 100% が
new-nginxにルーティングされます (canary-by-headerとcanary-by-header-valueによって制御)。 -
`foo: bar` ヘッダーなし:トラフィックの 50% が
new-nginxにルーティングされます (canary-weightによって制御)。
v1.19 以降のクラスター
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: gray-release-canary annotations: # カナリアルーティングを有効にする nginx.ingress.kubernetes.io/canary: "true" # foo ヘッダーが bar と等しい場合に new-nginx にルーティングする nginx.ingress.kubernetes.io/canary-by-header: "foo" nginx.ingress.kubernetes.io/canary-by-header-value: "bar" spec: ingressClassName: nginx rules: - host: www.example.com http: paths: # サービスの新バージョン - path: / backend: service: name: new-nginx port: number: 80 pathType: ImplementationSpecificv1.19 より前のクラスター
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: gray-release-canary annotations: nginx.ingress.kubernetes.io/canary: "true" nginx.ingress.kubernetes.io/canary-by-header: "foo" nginx.ingress.kubernetes.io/canary-by-header-value: "bar" nginx.ingress.kubernetes.io/canary-weight: "50" spec: rules: - host: www.example.com http: paths: - path: / backend: serviceName: new-nginx servicePort: 80マニフェストを適用して検証します:
kubectl get ingress curl -H "Host: www.example.com" http://<EXTERNAL_IP>ヘッダーなしでテストします (旧バージョンにルーティングされます):
curl -H "Host: www.example.com" http://<EXTERNAL_IP>期待される出力:
oldfoo: barヘッダーありでテストします (新バージョンにルーティングされます):curl -H "Host: www.example.com" -H "foo: bar" http://<EXTERNAL_IP>期待される出力:
new戦略 B:ヘッダーによるルーティングと残りのトラフィックの重みによる分割
foo=barを含むすべてのリクエストを新バージョンにルーティングし、その他のリクエストの 50% を新バージョンにルーティングします。次の内容でingress1.yamlを更新します。v1.19 以降のクラスター
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: gray-release-canary annotations: nginx.ingress.kubernetes.io/canary: "true" # すべてのトラフィックの 50% を new-nginx にルーティングします。デフォルトの合計の重みは 100 です。 nginx.ingress.kubernetes.io/canary-weight: "50" spec: ingressClassName: nginx rules: - host: www.example.com http: paths: - path: / backend: service: name: new-nginx port: number: 80 pathType: ImplementationSpecificv1.19 より前のクラスター
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: gray-release-canary annotations: nginx.ingress.kubernetes.io/canary: "true" nginx.ingress.kubernetes.io/canary-by-header: "foo" nginx.ingress.kubernetes.io/canary-by-header-value: "bar" nginx.ingress.kubernetes.io/canary-weight: "50" spec: rules: - host: www.example.com http: paths: - path: / backend: serviceName: new-nginx servicePort: 80マニフェストを適用します:
kubectl apply -f ingress1.yaml戦略 C:重みのみによるルーティング
ヘッダーや Cookie に関係なく、トラフィックの 50% を新バージョンにルーティングします。次の内容で
ingress1.yamlを更新します。v1.19 以降のクラスター
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: gray-release-canary annotations: nginx.ingress.kubernetes.io/canary: "true" # すべてのトラフィックの 50% を new-nginx にルーティングする。デフォルトの合計の重みは 100 nginx.ingress.kubernetes.io/canary-weight: "50" spec: ingressClassName: nginx rules: - host: www.example.com http: paths: - path: / backend: service: name: new-nginx port: number: 80 pathType: ImplementationSpecificv1.19 より前のクラスター
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: gray-release-canary annotations: nginx.ingress.kubernetes.io/canary: "true" nginx.ingress.kubernetes.io/canary-weight: "50" spec: rules: - host: www.example.com http: paths: - path: / backend: serviceName: new-nginx servicePort: 80マニフェストを適用します:
kubectl apply -f ingress1.yaml検証:このコマンドを数回実行します。応答の約 50% が
newを返すはずです。curl -H "Host: www.example.com" http://<EXTERNAL_IP> -
ステップ 3:トラフィックの完全な切り替え
新バージョンが安定したら、旧バージョンを廃止します。
-
nginx.yamlを更新して、古い Service を新しい Deployment にリダイレクトします。更新を適用します:
kubectl apply -f nginx.yaml -
すべてのトラフィックが新バージョンにルーティングされることを確認します:
kubectl get ingress curl -H "Host: www.example.com" http://<EXTERNAL_IP>期待される出力:
new -
カナリア Ingress を削除します:
kubectl delete ingress gray-release-canary -
古い Deployment と新しい Service を削除します:
kubectl delete deploy old-nginx kubectl delete svc new-nginx
service-* アノテーション方式
service-* アノテーションは、Nginx Ingress Controller v1.12 以降では使用できなくなりました。使用しないでください。
アノテーションリファレンス
| アノテーション | 説明 |
|---|---|
nginx.ingress.kubernetes.io/service-match |
リクエスト属性をサービスにマッピングするルーティングルールを定義します。構文:nginx.ingress.kubernetes.io/service-match: | <service-name>: <match-rule>。サポートされているマッチタイプ:header、cookie、query。マッチフォーマット:正規表現 /regular expression/、完全一致 "exact value"。例:new-nginx: header("foo", /^bar$/)、new-nginx: header("foo", "bar")、new-nginx: cookie("foo", /^sticky-.+$/)、new-nginx: query("foo", "bar")。
|
nginx.ingress.kubernetes.io/service-weight |
新旧のサービスバージョン間のトラフィックの重みを設定します。構文:nginx.ingress.kubernetes.io/service-weight: | <new-svc-name>:<new-svc-weight>, <old-svc-name>:<old-svc-weight>。例:new-nginx: 20, old-nginx: 60。 |
ステップ 1:サービスのデプロイ
Nginx サービスをデプロイし、Nginx Ingress Controller を使用してレイヤー 7 ドメインアクセス用に公開します。
-
Deployment と Service を作成します。次の内容を
nginx.yamlとして保存します。マニフェストを適用します:
kubectl apply -f nginx.yaml -
Ingress を作成します。次の内容を
ingress.yamlとして保存します。v1.19 以降のクラスター
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: gray-release spec: ingressClassName: nginx rules: - host: www.example.com http: paths: # サービスの旧バージョン - path: / backend: service: name: old-nginx port: number: 80 pathType: ImplementationSpecificv1.19 より前のクラスター
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: gray-release spec: rules: - host: www.example.com http: paths: - path: / backend: serviceName: new-nginx servicePort: 80マニフェストを適用します:
kubectl apply -f ingress.yaml kubectl get ingress -
デプロイメントを検証します。外部 IP アドレスを取得します:
kubectl get ingressルーティングアクセスを確認します:
curl -H "Host: www.example.com" http://<EXTERNAL_IP>期待される出力:
old
ステップ 2:新しいサービスバージョンのリリース
新しい Nginx バージョンをデプロイし、ルーティングルールを構成します。
-
新しい Deployment と Service を作成します。次の内容を
nginx1.yamlとして保存します。マニフェストを適用します:
kubectl apply -f nginx1.yaml -
gray-releaseIngress を変更します。3 つの戦略が利用可能です。戦略 A:リクエストヘッダーによるルーティングfooヘッダーがbarと一致する場合にのみ、リクエストを新しいバージョンにルーティングします。次の内容でingress.yamlを更新します。v1.19 以降のクラスターの場合:v1.19 以降のクラスター
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: gray-release annotations: # foo ヘッダーが ^bar$ と一致する場合に new-nginx にルーティングする nginx.ingress.kubernetes.io/service-match: | new-nginx: header("foo", /^bar$/) spec: ingressClassName: nginx rules: - host: www.example.com http: paths: # サービスの旧バージョン - path: / backend: service: name: old-nginx port: number: 80 pathType: ImplementationSpecific # サービスの新バージョン - path: / backend: service: name: new-nginx port: number: 80 pathType: ImplementationSpecificv1.19 より前のクラスター
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: gray-release annotations: nginx.ingress.kubernetes.io/service-match: | new-nginx: header("foo", /^bar$/) nginx.ingress.kubernetes.io/service-weight: | new-nginx: 50, old-nginx: 50 spec: rules: - host: www.example.com http: paths: - path: / backend: serviceName: old-nginx servicePort: 80 - path: / backend: serviceName: new-nginx servicePort: 80マニフェストを適用して検証します:
kubectl apply -f ingress.yaml kubectl get ingressヘッダーなしでテストします (旧バージョンにルーティングされます):
curl -H "Host: www.example.com" http://<EXTERNAL_IP>期待される出力:
oldfoo: barヘッダーありでテストします (新バージョンにルーティングされます):curl -H "Host: www.example.com" -H "foo: bar" http://<EXTERNAL_IP>期待される出力:
new戦略 B:重み付け分割を伴うヘッダーによるルーティング
foo=barに一致するリクエストを両方のバージョンにルーティングし、それぞれに 50% ずつ割り当てます。次の内容でingress.yamlを更新します。v1.19 以降のクラスター
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: gray-release annotations: nginx.ingress.kubernetes.io/service-match: | new-nginx: header("foo", /^bar$/) # 一致するリクエストのうち、50% を new-nginx に、50% を old-nginx にルーティングする nginx.ingress.kubernetes.io/service-weight: | new-nginx: 50, old-nginx: 50 spec: ingressClassName: nginx rules: - host: www.example.com http: paths: - path: / backend: service: name: old-nginx port: number: 80 pathType: ImplementationSpecific - path: / backend: service: name: new-nginx port: number: 80 pathType: ImplementationSpecificv1.19 より前のクラスター
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: gray-release annotations: nginx.ingress.kubernetes.io/service-match: | new-nginx: header("foo", /^bar$/) nginx.ingress.kubernetes.io/service-weight: | new-nginx: 50, old-nginx: 50 spec: rules: - host: www.example.com http: paths: - path: / backend: serviceName: old-nginx servicePort: 80 - path: / backend: serviceName: new-nginx servicePort: 80マニフェストを適用します:
kubectl apply -f ingress.yamlテストコマンドを数回実行します。
foo: barリクエストの約 50% がnewを返すはずです。戦略 C:重みのみによるルーティング
トラフィックの 50% を新バージョンにルーティングします。次の内容で
ingress.yamlを更新します。v1.19 以降のクラスター
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: gray-release annotations: # すべてのトラフィックの 50% を new-nginx にルーティングする nginx.ingress.kubernetes.io/service-weight: | new-nginx: 50, old-nginx: 50 spec: ingressClassName: nginx rules: - host: www.example.com http: paths: - path: / backend: service: name: old-nginx port: number: 80 pathType: ImplementationSpecific - path: / backend: service: name: new-nginx port: number: 80 pathType: ImplementationSpecificv1.19 より前のクラスター
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: gray-release annotations: nginx.ingress.kubernetes.io/service-weight: | new-nginx: 50, old-nginx: 50 spec: rules: - host: www.example.com http: paths: - path: / backend: serviceName: old-nginx servicePort: 80 - path: / backend: serviceName: new-nginx servicePort: 80マニフェストを適用します:
kubectl apply -f ingress.yaml検証:このコマンドを数回実行します。応答の約 50% が
newを返すはずです。curl -H "Host: www.example.com" http://<EXTERNAL_IP>
ステップ 3:トラフィックの完全な切り替え
新バージョンが安定したら、旧バージョンを廃止します。
-
v1.19 以降のクラスター
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: gray-release spec: ingressClassName: nginx rules: - host: www.example.com http: paths: # サービスの新バージョン - path: / backend: service: name: new-nginx port: number: 80 pathType: ImplementationSpecificv1.19 より前のクラスター
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: gray-release spec: rules: - host: www.example.com http: paths: - path: / backend: serviceName: new-nginx servicePort: 80更新を適用します:
kubectl apply -f ingress.yaml -
すべてのトラフィックが新バージョンにルーティングされることを確認します:
kubectl get ingress curl -H "Host: www.example.com" http://<EXTERNAL_IP>期待される出力:
new -
古い Deployment と Service を削除します:
kubectl delete deploy <Deployment_name> kubectl delete svc <Service_name>