如何在Apache APISIX Ingress Controller中代理外部服务

Yeqi Peng

January 13, 2023

Products

このチュートリアルでは、ApisixUpstreamリソースで外部サービスを設定する方法を紹介します。

これは、サービスがサードパーティのサービスや別のK8sクラスタのサービスに依存している場合に便利です。また、参照されるサービス名が更新されたときに大量のApisixRouteを変更することなく、共有されたExternalNameサービスでApisixRouteを管理する方法も提供します。

前提条件

  • 利用可能なKubernetesクラスタ
  • 利用可能なAPISIXおよびAPISIX Ingress Controllerのインストール

APISIXがapisixネームスペースにインストールされていると仮定します。

イントロダクション

APISIX Ingressは、K8sのExternalNameサービスや直接のドメインとして外部サービスをバックエンドとして設定することをサポートしています。

この場合、ApisixRouteリソースのbackendsフィールドを設定しません。代わりに、externalNodesフィールドが設定されたApisixUpstreamリソースを参照するためにupstreamsフィールドを使用します。

例えば:

# httpbin-route.yaml
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  name: httpbin-route
spec:
  http:
  - name: rule1
    match:
      hosts:
      - local.httpbin.org
      paths:
      - /*
    # backends:  # `backends`フィールドは使用しません
    #    - serviceName: httpbin
    #      servicePort: 80
    upstreams:
    - name: httpbin-upstream

この設定は、IngressコントローラにK8sサービスを通じてアップストリームホストを解決するのではなく、参照されたApisixUpstreamで定義された設定を使用するように指示します。

参照されるApisixUpstreamには、externalNodesフィールドが設定されている必要があります。例えば:

# httpbin-upstream.yaml
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
  name: httpbin-upstream
spec:
  externalNodes:
  - type: Domain
    name: httpbin.org

このyamlの例では、httpbin.orgをバックエンドとして設定しています。Domainタイプは、これがサードパーティのサービスであることを示し、ここでは任意のドメイン名がサポートされます。

K8sクラスタ内の外部名サービスを使用したい場合、タイプはServiceで、名前はサービス名である必要があります。ServiceタイプでApisixUpstreamを設定することで、IngressコントローラはExternalNameサービスの内容とその変更を自動的に追跡します。

外部ドメインのアップストリーム

apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  name: httpbin-route
spec:
  http:
  - name: rule1
    match:
      hosts:
      - local.httpbin.org
      paths:
      - /*
    upstreams:
    - name: httpbin-upstream
---
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
  name: httpbin-upstream
spec:
  externalNodes:
  - type: Domain
    name: httpbin.org

上記の設定を適用した後、APISIXを通じて直接httpbin.orgにアクセスしてみることができます。

kubectl exec -it -n apisix APISIX_POD_NAME -- curl -i -H "Host: local.httpbin.org" http://127.0.0.1:9080/get

すべてが正常に動作している場合、次のような結果が表示されます:

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Date: Thu, 15 Dec 2022 10:47:30 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Server: APISIX/3.0.0

{
  "args": {},
  "headers": {
    "Accept": "*/*",
    "Host": "local.httpbin.org",
    "User-Agent": "curl/7.29.0",
    "X-Amzn-Trace-Id": "Root=xxxxx",
    "X-Forwarded-Host": "local.httpbin.org"
  },
  "origin": "127.0.0.1, xxxxxxxxx",
  "url": "http://local.httpbin.org/get"
}

Server: APISIX/3.0.0というヘッダは、リクエストがAPISIXから送信されたことを示しています。また、レスポンスにはX-Amzn-Trace-Idが含まれており、リクエストがオンラインのhttpbinサービスによって処理されたことを示しています。

外部名サービスのアップストリーム

後で作成する外部名サービスのバックエンドとして、testネームスペースに簡単なhttpbinアプリをデプロイします。

kubectl create ns test
kubectl -n test run httpbin --image-pull-policy IfNotPresent --image=kennethreitz/httpbin --port 80
kubectl -n test expose pod/httpbin --port 80

次に、apisixネームスペースにExternalNameサービスを作成するために以下の設定を使用します。

apiVersion: v1
kind: Service
metadata:
  name: ext-httpbin
spec:
  type: ExternalName
  externalName: httpbin.test.svc

これで、ExternalNameサービスのApisixRouteとApisixUpstreamを作成できます。

apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  name: ext-route
spec:
  http:
  - name: rule1
    match:
      hosts:
      - ext.httpbin.org
      paths:
      - /*
    upstreams:
    - name: ext-upstream
---
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
  name: ext-upstream
spec:
  externalNodes:
  - type: Service
    name: ext-httpbin

設定が同期されたら、次のコマンドでアクセスしてみてください。

変更する唯一の引数は、渡すヘッダです。

kubectl exec -it -n apisix APISIX_POD_NAME -- curl -i -H "Host: ext.httpbin.org" http://127.0.0.1:9080/get

出力は次のようになります:

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 234
Connection: keep-alive
Date: Thu, 15 Dec 2022 10:54:21 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Server: APISIX/3.0.0

{
  "args": {},
  "headers": {
    "Accept": "*/*",
    "Host": "ext.httpbin.org",
    "User-Agent": "curl/7.29.0",
    "X-Forwarded-Host": "ext.httpbin.org"
  },
  "origin": "127.0.0.1",
  "url": "http://ext.httpbin.org/get"
}

レスポンスは前のものと似ていますが、いくつかのフィールドが存在しません。これは、リクエストがオンラインのhttpbinサービスではなく、ローカルのhttpbinサービスに送信されたためです。

外部名サービス内のドメイン

外部名サービスは、K8sクラスタ外の任意のドメイン名を保持することもできます。

前のセクションで適用した外部サービスの設定を更新しましょう。

apiVersion: v1
kind: Service
metadata:
  name: ext-httpbin
spec:
  type: ExternalName
  externalName: httpbin.org

再度アクセスしてみると、出力には複数のoriginX-Amzn-Trace-Idヘッダが含まれており、オンラインのhttpbin.orgサービスにアクセスしていることを意味します。

結論

このチュートリアルでは、APISIX Ingress Controllerの機能範囲を拡張し、外部サービスへのリクエストをプロキシする方法を紹介しました。これにより、ユーザーは認証サービスやクロスクラスタサービスなどのサードパーティサービスを簡単に統合できます。

APIゲートウェイに関する詳細情報は、ブログをご覧いただくか、お問い合わせください。

Tags: