Viene de Medium power by Christopher Grant
En este artículo, se cubren una variedad de desafíos a la que se enfrenta y que soluciones que descubrió al implementar una aplicación real en un clúster Global utilizando el controlador de Ingress GCE.
Ha cubierto cómo configurar Global Kubernetes en 3 pasos en un artículo separado. Este artículo se centrará en cómo usarlo una vez que esté configurado. En la parte 1, se discutiren los conceptos, y en la parte se realizara una implementación de extremo a extremo con código real.
Contenido:
- Ejemplo simple
- Variaciones
- IP global
- Anotaciones
- Chequeo Health
- Tipo de puerto de nodo y puerto
- Contextos de ruta
- Clúster Equilibrado
Tener varios servicios desplegados que responden bajo un nombre de dominio es una práctica común en aplicaciones más grandes. Con Kubernetes puede exponer Implementaciones como Servicios independientes, utilizando ClusterIPs, NodePort y LoadBalancers. También puede exponer múltiples servicios como una sola entidad virtual utilizando recursos de Ingress.
En teoría, los recursos de Ingress son sencillos y fáciles de usar, pero en la práctica puede haber una curva de aprendizaje más empinada. En este artículo, repasaremos los conceptos básicos de la creación de recursos de Ingress y algunas peculiaridades que se encontraran en la vida real.
Ejemplo simple
Hay tres recursos principales involucrados en este proceso: el despliegue, su servicio y el Ingress en sí. Veamos una simple entrada de Hello World.
De la documentación de Kubernetes para el recurso Ingress, podemos ver muchos de los elementos clave
Ejemplo de Ingress en formato Yaml
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: test annotations: ingress.kubernetes.io/rewrite-target: / spec: rules: - host: foo.bar.com http: paths: - path: /foo backend: serviceName: s1 servicePort: 80 - path: /bar backend: serviceName: s2 servicePort: 80
Solo cubriendo lo que está aquí, cualquier solicitud para alojar foo.bar.com será procesada por las reglas contenidas en ese bloque, foo.bar.com/foo enrutará al servicio s1 en el puerto 80, solicitudes a foo.bar.com/bar dirigirá al servicio s2 en el puerto 80.
Variaciones no enumeradas explícitamente en los documentos
Para todos los host
Si no desea tratar con el nombre de host, puede eliminar el valor de host y solo se evaluarán las reglas de ruta para todos los hosts / IP.
Ejemplo de uso
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test
annotations:
ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- http:
paths:
- path: /foo
backend:
serviceName: s1
servicePort: 80
- path: /bar
backend:
serviceName: s2
servicePort: 80
Backend predeterminado
Los documentos muestran una opción de Ingress de Servicio Único y sin reglas. Puede combinar esto con las reglas de ruta para definir su propio back-end predeterminado con reglas adicionales.
Vamos al ejemplo.
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: test annotations: ingress.kubernetes.io/rewrite-target: / spec: backend: serviceName: testsvc servicePort: 80 rules: - http: paths: - path: /foo backend: serviceName: s1 servicePort: 80 - path: /bar backend: serviceName: s2 servicePort: 80
Aquí cualquier solicitud a este Ingress con / foo con ir al servicio s1, cualquier solicitud para / bar se enrutará a s2, y todos los demás se enviarán a testsvc
Es importante tener en cuenta que si no define un back-end predeterminado, Kubernetes creará uno detrás de la escena. Además, el backend creado para usted solo existe en un clúster. Lo verá cuando consulte los desarrollos de carga del backend en GCP más adelante.
IP Global
Este es otro punto importante para el Ingress global. Necesitarás crear y usar explícitamente una IP global de Google. Las IP efímeras predeterminadas creadas son solo regionales y no podrán admitir servicios de back-end de diferentes regiones.
Pasé mucho tiempo con esto, NO TE DESPISTES
Desde la línea de comando crea una IP global
gcloud compute addresses create ingress-ip --global
Luego, en tu ficherio ingress.yaml.
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: test annotations: kubernetes.io/ingress.global-static-ip-name: ingress-ip ingress.kubernetes.io/rewrite-target: / spec: backend: serviceName: testsvc servicePort: 80 rules: - http: paths: - path: /foo backend: serviceName: s1 servicePort: 80 - path: /bar backend: serviceName: s2 servicePort: 80
Anotaciones en el Ingress
En la sección de metadatos de la definición de Ingress se pueden proporcionar varias anotaciones para ayudar a kubernetes a comprender mejor sus intenciones.
Controlador de Ingress
Dependiendo de dónde y cómo despliegues kubernetes, puedes elegir qué ejecutará realmente en la definición de ingress yaml que proporciones. Muchos de los documentos se refieren a nginx como el controlador de ingreso, pero para este ejemplo mostraré cómo usar GCE nativo.
Aunque no es obligatorio, es una buena práctica agregar una anotación que indique qué controlador está intentando usar. Esto es útil si hay múltiples opciones dentro de un entorno dado como ejemplo
Como quiero usar GCE para este controlador de Ingress, lo especificaré explícitamente usando la anotación kubernetes.io/ingress.class: “gce”
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: test annotations: kubernetes.io/ingress.class: "gce" ingress.kubernetes.io/rewrite-target: / spec: backend: serviceName: testsvc servicePort: 80 rules: - http: paths: - path: /foo backend: serviceName: s1 servicePort: 80 - path: /bar backend: serviceName: s2 servicePort: 80
Chequeos health
De manera predeterminada, el Ingrees configurará las comprobaciones de estado de loadblancer al hacer ping en la raíz de su servicio. Es importante saber esto en caso de que elija no enrutar "/" en su servicio. Para garantizar que su aplicación registre su estado de health correctamente, proporcione una ruta "/" o configure las sondas Liveness and Readiness para sus necesidades.
Terminé simplemente dejando el contexto root en la aplicación por simplicidad
NodePort
Aquí hay otro elemento que tiene sentido después de trabajarlo. En primer lugar, utilizar el controlador de Ingress GCE requiere un servicio expuesto con NodePort, no puede ser solo ClusterIP.
En segundo lugar, cuando se despliega en un clúster federado, los puertos de nodo para su contenedor deben ser los mismos en todos los clústeres, por lo que debemos definirlo explícitamente. De forma predeterminada, cada contenedor proporcionaría un puerto aleatorio para el tipo NodePort, pero en un modelo federado, necesitamos que sean iguales para que la verificación de estado sea precisa. Una vez en funcionamiento, verá el chequeo de health consultando el mismo puerto en todos los nodos de su aplicación.
Para definir esto, en la definición del servicio para nuestra implementación, especificaremos los valores exactos que queremos. Aquí hay un ejemplo
apiVersion: v1 kind: Service metadata: name: s1 labels: app: app1 spec: type: NodePort ports: - port: 80 nodePort: 30041 selector: app: app1
Tendrá que definir un puerto de nodo diferente para cada servicio para que no haya colisiones
Contextos de ruta
Este fue probablemente el problema más complicado al que me enfrenté y solo lo cree con una aplicación real. Hasta ahora, todas las aplicaciones demos y hello world han funcionado bien. / foo rutas a svc1, y / bar a svc2. Cuando desplegué una aplicación real, sin embargo, las cosas no fueron tan claras.
Me gustaría obtener la página principal para mis servicios, pero todo lo demás volvería al equilibrador de carga predeterminado. Vamos a descubrir que hay una [peculiaridad con ingress]
(https://github.com/kubernetes/contrib/issues/885) porque los controladores de ingress Nginx y GCE no funcionan igual.
Básicamente en Nginx / foo está buscando cualquier cosa con un prefijo de / foo donde el controlador gce lo vea como un mapeo explícito. Para solucionar esto, necesitamos agregar * mapeos a nuestras rutas de reglas en el ingress.yaml de la siguiente manera:
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: test annotations: kubernetes.io/ingress.class: "gce" ## ingress.kubernetes.io/rewrite-target: / spec: backend: serviceName: testsvc servicePort: 80 rules: - http: paths: - path: /foo backend: serviceName: s1 servicePort: 80 - path: /foo/* backend: serviceName: s1 servicePort: 80 - path: /bar backend: serviceName: s2 servicePort: 80 - path: /bar/* backend: serviceName: s2 servicePort: 80
Al agregar las asignaciones adicionales, cualquier solicitud para /foo o /foo/baz/bar se enrutará correctamente al servicio s1 y las solicitudes para /bar o /bar/baz /foo se enrutarán al servicio s2
Cluster Balancing
En la mayoría de los casos, kubernetes intentará equilibrar los clústeres para que las aplicaciones se distribuyan uniformemente entre los clusters, pero puedes reflejar sus intenciones usando
federation.kubernetes.io/deployment-preferences:: usando de la siguiente manera
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: app1 spec: replicas: 4 template: metadata: annotations: federation.kubernetes.io/deployment-preferences: | { "rebalance": true, "clusters": { "east-cluster": { "minReplicas": 1 }, "west-cluster": { "minReplicas": 1 } } } labels: app: app1 spec: containers: - name: app1 image: myrepo/appi:v7 ports: - containerPort: 80 resources: requests: cpu: 100m memory: 100Mi
Las anotaciones anteriores le piden a los kubernetes que reequilibren y mantengan un mínimo de una réplica en el este y un mínimo de una réplica en el oeste.
Conclusión
Los controladores de ingreso de Kubernetes son una herramienta poderosa. Con poco conocimiento adicional, se convierten en un recurso simple para administrar también. La utilización del tipo de controlador GCE le permite implementar la entrada rápida y fácilmente en Google Container Engine sin necesidad de recursos adicionales.
Espero que esto haya sido útil y asegúrese de consultar la guía de instalación y la demostración de principio a fin.