Una mirada rápida a la API de Kubernetes Gateway
September 7, 2022
En uno de mis posts recientes del blog, describí varias formas de acceder a los pods de Kubernetes. Se puede acceder a un pod a través de su IP, pero los pods son naturalmente transitorios. La forma nominal es configurar un Service
: su IP es estable, y el trabajo de Kubernetes es mantener actualizado el mapeo entre un Service
y los pods subyacentes. Hay diferentes tipos de servicios disponibles: solo internos, NodePort
para permitir finalmente el acceso desde fuera del clúster, y LoadBalancer
que depende de un componente de terceros, generalmente un proveedor de la nube. Finalmente, mencioné el objeto Ingress
, que también permite el enrutamiento.
Deliberadamente dejé fuera al nuevo en el bloque, la API Gateway. Este es el tema de este post.
De Ingress a la API Gateway
El acceso externo a los pods de Kubernetes ha pasado por varios pasos evolutivos, por ejemplo, Ingress
es la respuesta al problema de la falta de enrutamiento en LoadBalancer
. El mayor problema de Ingress
es su dependencia de objetos "propietarios". Como recordatorio, aquí está el fragmento para crear enrutamiento usando Apache APISIX:
apiVersion: apisix.apache.org/v2beta3 #1
kind: ApisixRoute #1
metadata:
name: apisix-route
spec:
http:
- name: left
match:
paths:
- "/left"
backends:
- serviceName: left
servicePort: 80
- name: right
match:
paths:
- "/right"
backends:
- serviceName: right
servicePort: 80
- Objetos propietarios
Los objetos propietarios son un problema al migrar. Aunque la migración de un proveedor a otro probablemente no sea común, debería ser lo más fluida posible. Al usar objetos propietarios, primero necesitas mapear del objeto antiguo a los nuevos. Es probable que no sea un mapeo uno a uno. Luego, necesitas traducir la especificación al nuevo modelo: es probable que sea un proyecto completo.
La idea detrás de la API Gateway es tener una separación clara entre los objetos estándar y la implementación propietaria.
La API Gateway
La API Gateway es un proyecto de código abierto gestionado por la comunidad SIG-NETWORK. Es una colección de recursos que modelan la red de servicios en Kubernetes. Estos recursos -
GatewayClass
,Gateway
,HTTPRoute
,TCPRoute
,Service
, etc - tienen como objetivo evolucionar la red de servicios de Kubernetes a través de interfaces expresivas, extensibles y orientadas a roles que son implementadas por muchos proveedores y tienen un amplio apoyo de la industria.
La definición anterior también menciona una preocupación organizativa: diferentes roles deberían gestionar un conjunto diferente de objetos.
Imagen de gateway-api.sigs.k8s.io
De hecho, las preocupaciones de un operador de clúster y un desarrollador son bastante diferentes. Es bastante similar a los servidores de aplicaciones Java EE de antaño, que ofrecían una especificación organizada en torno a roles: desarrolladores, implementadores y operadores. En mi opinión, la diferencia más significativa es que la especificación se centraba principalmente en la experiencia del desarrollador; el resto dependía de los implementadores. La API Gateway parece preocuparse por todas las personas.
Configurar el acceso a los pods a través de la API Gateway
Reemplacemos el Ingress
que configuramos anteriormente con la API Gateway. Son necesarios varios pasos.
Instalar los nuevos CRDs de Gateway
k apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v0.5.0/standard-install.yaml
Instalar una implementación
Usaré Apache APISIX. Alternativamente, el sitio web de SIG mantiene una lista de implementaciones.
helm install apisix apisix/apisix \
--namespace ingress-apisix \
--create-namespace \
--devel \ #1
--set gateway.type=NodePort \ #2
--set gateway.http.nodePort=30800 \ #2
--set ingress-controller.enabled=true \ #2
--set ingress-controller.config.kubernetes.enableApiGateway=true \ #3
--set ingressPublishService="ingress-apisix/apisix-gateway" #4
- Sin la opción
--devel
, Helm instala la versión más reciente, que no funciona con la API Gateway - El Gateway necesita ser accesible fuera del clúster de todos modos
- ¡Aquí es donde ocurre la magia!
- Volveré a esto más tarde
Verifiquemos que todo funciona:
k get all -n ingress-apisix
NAME READY STATUS RESTARTS AGE
pod/apisix-5fc9b45c69-cf42m 1/1 Running 0 14m #1
pod/apisix-etcd-0 1/1 Running 0 14m #2
pod/apisix-etcd-1 1/1 Running 0 14m #2
pod/apisix-etcd-2 1/1 Running 0 14m #2
pod/apisix-ingress-controller-6f8bd94d9d-wkzfn 1/1 Running 0 14m #3
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
service/apisix-admin ClusterIP 10.96.69.19 <none> 9180/TCP
service/apisix-etcd ClusterIP 10.96.226.79 <none> 2379/TCP,2380/TCP
service/apisix-etcd-headless ClusterIP None <none> 2379/TCP,2380/TCP
service/apisix-gateway NodePort 10.96.101.224 <none> 80:30800/TCP #4
service/apisix-ingress-controller ClusterIP 10.96.141.230 <none> 80/TCP
- Apache APISIX en sí
- Apache APISIX almacena su configuración en
etcd
. El chart programa tres pods por defecto, una buena práctica para manejar fallos en sistemas distribuidos - Controlador de Apache APISIX: un controlador de Kubernetes es un bucle de control que mueve el estado existente hacia el estado deseado
- Servicio de Gateway de Apache APISIX: es el
Service
de tipoNodePort
que instalamos a través del Helm Chart. También es el nombre que referenciamos durante la instalación del Helm Chart -ingressPublishService
En este punto, la infraestructura está lista.
Declarar la implementación del Gateway
Como mencioné anteriormente, la API hace una separación clara entre la especificación y la implementación. Sin embargo, necesitamos vincularla de alguna manera. Es responsabilidad del objeto GatewayClass
:
apiVersion: gateway.networking.k8s.io/v1alpha2 #1
kind: GatewayClass #2
metadata:
name: apisix-gateway-class #3
spec:
controllerName: apisix.apache.org/gateway-controller #4
- No usamos la última versión a propósito, ya que Apache APISIX usa esta versión. Ten en cuenta que evolucionará en el (cercano) futuro
- Objeto
GatewayClass
- Nómbralo como quieras; sin embargo, lo usaremos más tarde para referenciar la clase de gateway
- El nombre del controlador depende de la implementación. Aquí estamos usando el de Apache APISIX.
Nota que el GatewayClass
tiene un alcance de todo el clúster. Este modelo nos permite declarar diferentes implementaciones de la API Gateway y usarlas en paralelo dentro del mismo clúster.
Crear el Gateway
Con Apache APISIX, es bastante sencillo:
apiVersion: gateway.networking.k8s.io/v1alpha2 #1
kind: Gateway #2
metadata:
name: apisix-gateway
spec:
gatewayClassName: apisix-gateway-class #3
listeners: #4
- name: http
protocol: HTTP
port: 80
- Mismo espacio de nombres que arriba
- Objeto
Gateway
- Referencia la clase de gateway declarada anteriormente
- Permite algunas restricciones en este nivel para que el operador del clúster pueda evitar usos no deseados
Advertencia: La API Gateway especifica la opción de cambiar dinámicamente el puerto en el lado del operador. Al momento de escribir esto, la asignación de puertos de Apache APISIX es estática. El plan es hacerla dinámica en el futuro. Por favor, suscríbete a este issue de GitHub para seguir el progreso.
Rutas, rutas, rutas por todas partes
Hasta ahora, todo era infraestructura; finalmente podemos configurar el enrutamiento.
Quiero el mismo enrutamiento que en el post anterior; una rama /left
y una right
. Omitiré la última por brevedad.
apiVersion: gateway.networking.k8s.io/v1alpha2 #1
kind: HTTPRoute #2
metadata:
name: left
spec:
parentRefs:
- name: apisix-gateway #3
rules:
- matches: #4
- path: #4
type: PathPrefix #4
value: /left
backendRefs: #5
- name: left #5
port: 80 #5
- Mismo espacio de nombres que arriba
- Objeto
HTTPRoute
- Referencia el
Gateway
creado anteriormente - Reglas de coincidencia. En nuestro caso, coincidimos con un prefijo de ruta, pero hay muchas reglas disponibles. Puedes coincidir basado en un parámetro de consulta, en un encabezado, etc.
- El "upstream" al que reenviar. Definimos el
Service
left
en el post anterior del blog.
Verificar que funciona
Ahora que hemos configurado nuestras rutas, podemos verificar que funciona.
curl localhost:30800/left
Cuando instalamos el chart de Helm, le dijimos a Apache APISIX que creara un servicio NodePort
en el puerto 30800
. Por lo tanto, podemos usar el puerto para acceder al servicio fuera del clúster.
left
Conclusión
Hay muchas alternativas disponibles para acceder a un pod desde fuera del clúster. La CNCF agregó la mayoría de ellas para mejorar la anterior.
La API Gateway es la última propuesta en este sentido. La especificación es un trabajo en progreso y los productos están en diferentes etapas de implementación. Por esta razón, es demasiado pronto para basar tu producción en la API. Sin embargo, probablemente deberías seguir el progreso, ya que está destinada a ser una mejora considerable sobre los enfoques anteriores.
El código fuente completo para este post se puede encontrar en GitHub.
Para ir más allá: