Как проксировать внешние сервисы в Apache APISIX Ingress Controller
Yeqi Peng
January 13, 2023
В этом руководстве мы расскажем, как настроить внешние сервисы в ресурсах ApisixUpstream.
Это полезно, когда ваш сервис зависит от стороннего сервиса или сервиса из другого кластера K8s. Это также предоставляет способ управления вашим ApisixRoute с использованием общих сервисов ExternalName, без необходимости изменять большое количество ApisixRoutes при обновлении имени ссылочного сервиса.
Предварительные требования
- доступный кластер Kubernetes
- установленные APISIX и APISIX Ingress Controller
Мы предполагаем, что ваш APISIX установлен в пространстве имен apisix.
Введение
APISIX Ingress поддерживает настройку внешних сервисов в качестве бэкендов, как для сервисов K8s ExternalName, так и для прямых доменов.
В этом случае мы не настраиваем поле backends в ресурсе ApisixRoute. Вместо этого мы будем использовать поле upstreams для ссылки на ресурс ApisixUpstream с настроенным полем externalNodes.
Например:
# 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, а имя должно быть именем сервиса. Настроив ApisixUpstream с типом Service, контроллер 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
После применения вышеуказанной конфигурации мы можем попробовать получить доступ к httpbin.org напрямую через APISIX.
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.
Внешний сервис с именем в качестве бэкенда
Давайте развернем простое приложение httpbin в пространстве имен test в качестве бэкенда для сервиса с внешним именем, который мы создадим позже.
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
Затем используйте следующую конфигурацию для создания сервиса ExternalName в пространстве имен apisix.
apiVersion: v1 kind: Service metadata: name: ext-httpbin spec: type: ExternalName externalName: httpbin.test.svc
Теперь мы можем создать 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, а не на онлайн-сервис.
Домен во внешнем сервисе с именем
Сервис с внешним именем также может содержать любое доменное имя за пределами кластера 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, проксируя запросы на внешние сервисы. Это позволяет пользователям легко интегрировать сторонние сервисы, такие как сервисы аутентификации или кросс-кластерные сервисы.
Для получения дополнительной информации о API-шлюзах, пожалуйста, посетите наши блоги или свяжитесь с нами.