In this tutorial, we will introduce how to configure external services in the ApisixUpstream resources.
We assume that your APISIX is installed in the apisix namespace.
APISIX ingress supports configuring external services as backends, both for K8s external name services and direct domains. In this case, we don't configure the backends field in the ApisixRoute resource. Instead, we will use the upstreams field to refer to an ApisixUpstream resources with the externalNodes field configured.
For example:
# 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: # We won't use the `backends` field # - serviceName: httpbin # servicePort: 80 upstreams: - name: httpbin-upstream
This configuration tells the ingress controller not to resolve upstream hosts through the K8s services, but to use the configuration defined in the referenced ApisixUpstream. The referenced ApisixUpstream MUST have externalNodes field configured. For example:
# httpbin-upstream.yaml apiVersion: apisix.apache.org/v2 kind: ApisixUpstream metadata: name: httpbin-upstream spec: externalNodes: - type: Domain name: httpbin.org
In this yaml example, we configured httpbin.org as the backend. The type Domain indicates that this is a third-party service, and any domain name is supported here.
If you want to use an external name service in the K8s cluster, the type should be Service and the name should be the service name. By configuring ApisixUpstream with type Service, the ingress controller will automatically keep track of the content of the external name service and its changes.
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
After applying the above configuration, we can try to access httpbin.org directly through APISIX.
kubectl exec -it -n apisix APISIX_POD_NAME -- curl -i -H "Host: local.httpbin.org" http://127.0.0.1:9080/get
If everything works, you will see the result like this:
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" }
The header Server: APISIX/3.0.0 indicates that the request is sent from APISIX.
Let's deploy a simple httpbin app in the namespace test as the backend for the external name service we will create later.
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
Then use the following configuration to create an external name service in the apisix namespace.
apiVersion: v1 kind: Service metadata: name: ext-httpbin spec: type: ExternalName externalName: httpbin.test.svc
Now we can create an external name service ApisixRoute and 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
Once the configurations is synced, try to access it with the following command.
The only argument that changes is the header we pass.
kubectl exec -it -n apisix APISIX_POD_NAME -- curl -i -H "Host: ext.httpbin.org" http://127.0.0.1:9080/get
The output should be like:
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" }
The external name service can also hold any domain name outside of the K8s cluster.
Let's update the external service configuration we applied in the previous section.
apiVersion: v1 kind: Service metadata: name: ext-httpbin spec: type: ExternalName externalName: httpbin.org
Try accessing it again, and the output should contain multiple origin, and an X-Amzn-Trace-Id header, which means we are accessing the actual online httpbin.org service.