Como Proxiar Serviços Externos no Apache APISIX Ingress Controller

Yeqi Peng

January 13, 2023

Products

Neste tutorial, vamos apresentar como configurar serviços externos em recursos ApisixUpstream.

Isso é útil quando o seu serviço depende de um serviço de terceiros ou de um serviço de outro cluster K8s. Também fornece uma maneira de gerenciar seu ApisixRoute com serviços ExternalName compartilhados, sem a necessidade de modificar um grande número de ApisixRoutes quando o nome do serviço referenciado é atualizado.

Pré-requisitos

  • Um cluster Kubernetes disponível
  • Uma instalação disponível do APISIX e do APISIX Ingress Controller

Assumimos que o seu APISIX está instalado no namespace apisix.

Introdução

O APISIX Ingress suporta a configuração de serviços externos como backends, tanto para serviços ExternalName do K8s quanto para domínios diretos.

Neste caso, não configuramos o campo backends no recurso ApisixRoute. Em vez disso, usaremos o campo upstreams para referenciar um recurso ApisixUpstream com o campo externalNodes configurado.

Por exemplo:

# 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:  # Não usaremos o campo `backends`
    #    - serviceName: httpbin
    #      servicePort: 80
    upstreams:
    - name: httpbin-upstream

Esta configuração informa ao controlador de ingress para não resolver os hosts upstream através dos serviços K8s, mas sim usar a configuração definida no ApisixUpstream referenciado.

O ApisixUpstream referenciado DEVE ter o campo externalNodes configurado. Por exemplo:

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

Neste exemplo de yaml, configuramos httpbin.org como o backend. O tipo Domain indica que este é um serviço de terceiros, e qualquer nome de domínio é suportado aqui.

Se você quiser usar um serviço de nome externo no cluster K8s, o tipo deve ser Service e o nome deve ser o nome do serviço. Ao configurar o ApisixUpstream com o tipo Service, o controlador de ingress rastreará automaticamente o conteúdo do serviço ExternalName e suas alterações.

Upstream de Domínio Externo

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

Após aplicar a configuração acima, podemos tentar acessar httpbin.org diretamente através do APISIX.

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

Se tudo funcionar, você verá o resultado assim:

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"
}

O cabeçalho Server: APISIX/3.0.0 indica que a solicitação foi enviada pelo APISIX. E a resposta contém X-Amzn-Trace-Id, indicando que a solicitação foi tratada pelo serviço httpbin online.

Upstream de Serviço de Nome Externo

Vamos implantar um aplicativo httpbin simples no namespace test como o backend para o serviço de nome externo que criaremos posteriormente.

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

Em seguida, use a seguinte configuração para criar um serviço ExternalName no namespace apisix.

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

Agora podemos criar um ApisixRoute e ApisixUpstream para o serviço ExternalName.

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

Assim que as configurações forem sincronizadas, tente acessá-la com o seguinte comando.

O único argumento que muda é o cabeçalho que passamos.

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

A saída deve ser semelhante a:

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"
}

Podemos ver que a resposta é semelhante à anterior, mas alguns campos não existem. Isso ocorre porque a solicitação foi enviada para o nosso serviço httpbin local, e não para o online.

Domínio em Serviço de Nome Externo

O serviço de nome externo também pode conter qualquer nome de domínio fora do cluster K8s.

Vamos atualizar a configuração do serviço externo que aplicamos na seção anterior.

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

Tente acessá-lo novamente, e a saída deve conter múltiplos origin e um cabeçalho X-Amzn-Trace-Id, o que significa que estamos acessando o serviço online httpbin.org.

Conclusão

Neste tutorial, estendemos os limites funcionais do APISIX Ingress Controller ao encaminhar solicitações para serviços externos. Isso permite que os usuários integrem facilmente serviços de terceiros, como serviços de autenticação ou serviços entre clusters.

Para mais informações sobre gateway de API, visite nossos blogs ou entre em contato conosco.

Tags: