如何在Apache APISIX Ingress Controller中代理外部服务
Yeqi Peng
January 13, 2023
このチュートリアルでは、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
再度アクセスしてみると、出力には複数のorigin
とX-Amzn-Trace-Id
ヘッダが含まれており、オンラインのhttpbin.org
サービスにアクセスしていることを意味します。
結論
このチュートリアルでは、APISIX Ingress Controllerの機能範囲を拡張し、外部サービスへのリクエストをプロキシする方法を紹介しました。これにより、ユーザーは認証サービスやクロスクラスタサービスなどのサードパーティサービスを簡単に統合できます。