Kubernetes GatewayとIngress APIの比較

Navendu Pottekkat

Navendu Pottekkat

October 21, 2022

Ecosystem

数ヶ月前、新しいKubernetes Gateway APIがベータ版に昇格しました

安定したKubernetes Ingress API多数の実装があるのに、なぜ外部トラフィックを処理するための別のAPIが必要なのでしょうか?新しいGateway APIは、Ingress APIのどのような問題を解決するのでしょうか?これはIngress APIの終わりを意味するのでしょうか?

この記事では、これらのAPIを実際に触りながら、それらがどのように進化してきたのかを見ていくことで、これらの質問に答えようと思います。

サービスへの外部アクセスの標準化:Ingress API

Kubernetes Ingress APIは、Kubernetes内のサービスを外部トラフィックに公開することを標準化するために作成されました。Ingress APIは、ルーティングやSSL終端などの機能を導入することで、デフォルトのサービスタイプであるNodePortLoadBalancerの制限を克服しました。

Kubernetes Ingress

20以上のIngressコントローラーの実装が利用可能です。この記事では、Apache APISIXとそのIngressコントローラーを例として使用します。

APISIX Ingressコントローラー

APISIXや他のIngress実装を設定するために、Ingressリソースを作成できます。

以下の例は、APISIX Ingressを使用してアプリケーションの2つのバージョン間でトラフィックをルーティングする方法を示しています:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: api-routes
spec:
  ingressClassName: apisix
  rules:
    - host: local.navendu.me
      http:
        paths:
          - backend:
              service:
                name: bare-minimum-api-v1
                port:
                  number: 8080
            path: /v1
            pathType: Prefix
          - backend:
              service:
                name: bare-minimum-api-v2
                port:
                  number: 8081
            path: /v2
            pathType: Prefix

ヒント: KubernetesでApache APISIX Ingressコントローラーを使用してIngressを設定する方法について詳しく知りたい場合は、このハンズオンチュートリアルをチェックしてください。

Ingress APIは特定のコントローラー実装に縛られていないため、APISIXを他のIngressコントローラーと交換しても同様に動作します。

これは単純なルーティングには問題ありません。しかし、APIには制限があり、Ingressコントローラーが提供するすべての機能を使用したい場合、アノテーションに頼らざるを得ません。

例えば、Kubernetes Ingress APIはリライトを設定するためのスキーマを提供していません。リライトは、アップストリーム/バックエンドのURLがIngressルールで設定されたパスと異なる場合に便利です。

APISIXはこの機能をサポートしており、カスタムアノテーションを使用してそれを活用する必要があります:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: api-routes
  annotations:
    k8s.apisix.apache.org/rewrite-target-regex: "/app/(.*)"
    k8s.apisix.apache.org/rewrite-target-regex-template: "/$1"
spec:
  ingressClassName: apisix
  rules:
    - host: local.navendu.me
      http:
        paths:
          - backend:
              service:
                name: bare-minimum-api
                port:
                  number: 8080
            path: /app
            pathType: Prefix

これにより、/appプレフィックスを持つリクエストをプレフィックスを削除してバックエンドにルーティングするIngressリソースが作成されます。例えば、/app/versionへのリクエストは/versionに転送されます。

アノテーションは選択したIngressコントローラーに固有です。これらの「独自の」拡張機能は、Ingress APIで当初意図されていた移植性の範囲を制限しました。

カスタムCRD > Ingress API

アノテーションに頼らざるを得ないことは、Ingressコントローラーの使いやすさも犠牲にします。

そのため、コントローラーはIngress APIの制限を克服するために独自のカスタムリソースを作成しました。以下の例は、APISIXのカスタムリソースを使用してアプリケーションの2つのバージョン間でトラフィックをルーティングするIngressを設定する方法を示しています:

apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  name: api-routes
spec:
  http:
    - name: route-1
      match:
        hosts:
          - local.navendu.me
        paths:
          - /v1
      backends:
        - serviceName: bare-minimum-api-v1
          servicePort: 8080
    - name: route-2
      match:
        hosts:
          - local.navendu.me
        paths:
          - /v2
      backends:
        - serviceName: bare-minimum-api-v2
          servicePort: 8081

これらのCRDにより、Ingressの設定がはるかに簡単になりましたが、特定のIngressコントローラー実装に縛られます。Ingress APIが進化しない限り、使いやすさと移植性のどちらかを選ばなければなりませんでした。

Ingressの拡張とGateway APIへの進化

Ingress APIは壊れていたわけではありませんが、制限がありました。Gateway APIはこれらの制限を克服するために設計されました。

(Gateway API) は、表現力豊かで拡張可能な、役割指向のインターフェースを通じてKubernetesのサービスネットワーキングを進化させることを目指しています...

これは、前述のさまざまなIngressコントローラーのカスタムCRDからインスピレーションを得ています。

Gateway APIは、Ingress APIの機能の「上に」多くの機能を追加します。これには、HTTPヘッダーに基づくマッチング、重み付きトラフィック分割、およびIngress APIではカスタムの独自アノテーションが必要な他の機能が含まれます。

APISIX Ingressリソースを使用したトラフィック分割(ApisixRoute/v2リファレンスを参照):

apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  name: traffic-split
spec:
  http:
    - name: rule-1
      match:
        hosts:
          - local.navendu.me
        paths:
          - /get*
      backends:
        - serviceName: bare-minimum-api-v1
          servicePort: 8080
          weight: 90
        - serviceName: bare-minimum-api-v2
          servicePort: 8081
          weight: 10

Gateway APIを使用したトラフィック分割(Canary traffic rolloutを参照):

apiVersion: gateway.networking.k8s.io/v1alpha2
kind: HTTPRoute
metadata:
  name: traffic-split
spec:
  hostnames:
  - local.navendu.me
  rules:
  - backendRefs:
    - name: bare-minimum-api-v1
      port: 8080
      weight: 90
    - name: bare-minimum-api-v2
      port: 8081
      weight: 10

Ingress APIからのもう一つの改善点は、Gateway APIが関心の分離をどのように行うかです。Ingressでは、アプリケーション開発者とクラスターオペレーターが同じIngressオブジェクトを操作し、互いの責任を認識せずに誤設定の扉を開いていました。

Gateway APIは、設定をRouteオブジェクトとGatewayオブジェクトに分離し、アプリケーション開発者とクラスターオペレーターに自律性を提供します。以下の図はこれを明確に説明しています:

Gateway APIにおける関心の分離

これはIngress APIの終わりでしょうか?

Gateway APIは比較的新しく、その実装は常に変化しています。一方、Ingress APIは安定版リリースであり、時間の試練に耐えてきました。

もしあなたのユースケースが単純なルーティングのみを含み、追加機能を得るためにカスタムアノテーションを使用することに問題がない場合、Ingress APIはまだ堅実な選択肢です。

Gateway APIがIngress APIのスーパーセットであることを考えると、両方を統合することは理にかなっているかもしれません。SIG Networkコミュニティのおかげで、Gateway APIはまだ成長中であり、すぐに本番環境で使用できるようになるでしょう。

ほとんどのIngressコントローラーとサービスメッシュは、すでにIngress APIとともにGateway APIを実装しており、プロジェクトが進化するにつれて、さらに多くの実装が登場するでしょう。

個人的には、少なくとも今のところ、Ingress APIやGateway APIではなく、Apache APISIXのようなIngressコントローラーが提供するカスタムCRDを使用することを選ぶでしょう。

Tags: