Vida
Cuando una caja Pod crea una instancia, termina y se mueve de un nodo a otro y, por lo tanto, cambia su dirección IP, ¿cómo hacemos el seguimiento de eso para obtener funcionalidades ininterrumpidas del conjunto Pod? Incluso si la caja de’Pod no se mueve, ¿cómo llega el tráfico a grupos de pods a través de una sola entidad?
La respuesta a ambas preguntas es Kubernetes servicio.
El servicio es una abstracción que define un conjunto lógico de pods y una política, por la que puede acceder a ellos. Consideremos que los servicios son de su perdedora en – un’restaurante de gran tamaño este puesto’es en lugar de cocinar: en vez de eso, es una abstracción de todo lo happing en la cocina y solo tiene que enfrentarse a este único espera.
El servicio es un equilibrador de carga de capa 4 que expone las funciones del conjunto Pod a través de una dirección IP y un puerto específicos. El servicio y los pods se vinculan a través de etiquetas como RS. Y existen’tres tipos diferentes de servicios:
ClusterIP
NodePort
Multiplexor
Servicio ClusterIP
El servicio clusterIP es el servicio más sencillo, y el modo predeterminado si no se especifica el ServiceType. La Figure 1 ilustra cómo funciona el servicio clusterIP.
Puede ver que el servicio ClusterIP se expone en un clusterIP y en un puerto de servicio. Cuando los pods de cliente necesitan acceder al servicio que envía solicitudes hacia este puerto de clusterIP y servicio. Este modelo funciona genialmente si todas las solicitudes proceden del mismo clúster. La naturaleza de la clusterIP limita el ámbito del servicio para que solo esté dentro del clúster. En general, de forma predeterminada, el clusterIP no es accesible externamente.
Crear servicio ClusterIP
#service-web-clusterip.yaml apiVersion: v1 kind: Service metadata: name: service-web-clusterip spec: ports: - port: 8888 targetPort: 80 selector: app: webserver
El archivo YAML parece bastante sencillo y se explica por sí mismo. Se define una service/service-web-clusterip
con el puerto de servicio 8888, que se asigna a targetPort, que significa puerto de contenedor 80 en algún conjunto Pod. El selector indica que cualquier Pod con una etiqueta y una aplicación: WebServer será la solicitud de servicio de backend Pod responding.
Bien, ahora genere el servicio:
$ kubectl apply -f service-web-clusterip.yaml service/service-web-clusterip created
Utilizados kubectl
comandos para comprobar rápidamente el servicio y los objetos de pod de back-end:
$ kubectl get svc -o wide NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR service-web-clusterip ClusterIP 10.101.150.135 <none> 8888/TCP 9m10s app=webserver $ kubectl get pod -o wide -l 'app=webserver' No resources found.
El servicio se creó correctamente, pero no hay pods para el servicio. Esto se debe a que no hay un conjunto Pod con una etiqueta que coincida con el selector en el servicio. Por lo tanto, solo es necesario crear una caja Pod con la etiqueta adecuada.
Ahora, puede definir un conjunto Pod directamente, pero teniendo en cuenta las ventajas de RC y la implementación a pods, según se ha explicado anteriormente, el uso de’RC o la implementación es más práctico (pronto veremos el porqué).
A modo de ejemplo,’Supongamos que define un objeto de implementación denominado WebServer:
#deploy-webserver-do.yaml apiVersion: apps/v1 kind: Deployment metadata: name: webserver labels: app: webserver spec: replicas: 1 selector: matchLabels: app: webserver matchExpressions: - {key: app, operator: In, values: [webserver]} template: metadata: name: webserver labels: app: webserver spec: containers: - name: webserver image: contrailk8sdayone/contrail-webserver securityContext: privileged: true ports: - containerPort: 80
El servidor WebServer de implementación tiene una aplicación de etiquetas: servidor webserver, coincidiendo con el selector
definido en nuestro servicio. El servicio replicas
: 1 indica al controlador que inicie solo un conjunto Pod en este momento. Veamos’:
$ kubectl apply -f deployment-webserver-do.yaml deployment.extensions/webserver created $ kubectl get pod -o wide -l 'app=webserver' NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE webserver-7c7c458cc5-vl6zs 1/1 Running 0 24s 10.47.255.238 cent333 <none>
Y, inmediatamente, el conjunto Pod se elige como el back-end.
Breves resúmenes acerca del anterior kubectl
get svc
el resultado del comando es:
El servicio obtuvo una clusterIP, o IP de servicio, de 10.101.150.135 asignados del grupo de direcciones IP del servicio.
El puerto de servicio es 8888 como el que se define en YAML.
De forma predeterminada, el tipo de protocolo es TCP si no se declara en el archivo YAML Puede utilizar el protocolo: UDP para declarar un servicio UDP.
El POD back-end puede estar ubicado con el selector de etiqueta.
El ejemplo que se muestra aquí utiliza un selector de igualdad (-l) para ubicar el conjunto pod de back-end, pero también puede usar una sintaxis basada en conjuntos para archivar el mismo efecto. Por ejemplo: kubectl get
pod -o wide -l 'app in (webserver)'
.
Comprobar servicio ClusterIP
Para comprobar que el servicio funciona realmente, deje’que s inicie otro Pod como cliente para iniciar una solicitud HTTP hacia el servicio. Para esta prueba, se’inicia e inicia sesión en una caja pod de cliente y se utiliza el comando rizo para enviar una solicitud HTTP al servicio. Puede’ver que el mismo Pod se utiliza como cliente para enviar solicitudes a lo largo de este libro:
#pod-client-do.yaml apiVersion: v1 kind: Pod metadata: name: client labels: app: client spec: containers: - name: contrail-webserver image: contrailk8sdayone/contrail-webserver
Crear la caja pod de cliente:
$ kubectl apply -f pod-client-do.yaml pod/client created
La caja de cliente no es más que un conjunto de Pod generado basado en la misma imagen, cualquiera que sea la implementación de WebServer y sus pods. Esto es lo mismo que con los servidores físicos y las máquinas virtuales: nada hace que un servidor deje de hacer’el trabajo cliente:
$ kubectl exec -it client -- curl 10.101.150.135:8888 <html> <style> h1 {color:green} h2 {color:red} </style> <div align="center"> <head> <title>Contrail Pod</title> </head> <body> <h1>Hello</h1><br><h2>This page is served by a <b>Contrail</b> pod</h2><br><h3>IP address = 10.47.255.238<br>Hostname = webserver-7c7c458cc5-vl6zs</h3> <img src="/static/giphy.gif"> </body> </div> </html>
La solicitud HTTP para el servicio llega a un conjunto Pod que ejecuta la aplicación del servidor Web, que responde con una página HTML.
Para demostrar mejor qué Pod proporciona el servicio, deje’que configure una imagen Pod personalizada que ejecute un simple servidor Web. El servidor web está configurado de tal forma que, cuando reciba una solicitud, devolverá una página HTML sencilla con un nombre de host y una dirección IP Pod local incorporados. De este modo, el doblez devuelve algo más significativo en nuestra prueba.
El código HTML devuelto parece relativamente adecuado para leerlo, pero hay una forma de hacerlo más fácil de ver:
$ kubectl exec -it client -- curl 10.101.150.135:8888 | w3m -T text/html | head Hello This page is served by a Contrail pod IP address = 10.47.255.238 Hostname = webserver-7c7c458cc5-vl6zs
La herramienta w3m es un navegador web ligero basado en consola que está instalado en el host. Con w3m puede representar una página web HTML en texto, que es más legible que la página HTML.
Ahora que se verifica el servicio, las solicitudes de servicio se han redirigido al conjunto pod de back-end correcto, con una IP Pod of 10.47.255.238 y un nombre pod de WebServer-7c7c458cc5-vl6zs.
Especificar un ClusterIP
Si desea tener un clusterIP específico, puede mencionarlo en la especificación. Las direcciones IP deben encontrarse en el grupo IP del servicio.
Aquí’enaquí s un ejemplo de YAML con determinados clusterIP
:
#service-web-clusterip-static.yaml apiVersion: v1 kind: Service metadata: name: service-web-clusterip-static spec: clusterIP: 10.101.150.150 #<--- ports: - port: 8888 targetPort: 80 selector: app: webserver
Servicio NodePort
El segundo tipo general de servicio, NodePort, expone un servicio en cada IP de’nodo en un puerto estático. Asigna el puerto estático de cada nodo con un puerto de la aplicación en la caja Pod, tal como se muestra en la Figure 2.
#service-web-nodeport apiVersion: v1 kind: Service metadata: name: service-web-nodeport spec: selector: app: webserver type: NodePort ports: - targetPort: 80 port: 80 nodePort: 32001 #<--- (optional)
A continuación, figuran algunos aspectos destacados de este archivo YAML de servicios:
selector
: El selector de etiqueta que determina qué conjunto de pods se destina a este servicio; aquí, cualquier conjunto Pod con la aplicación de etiquetas: el servidor WebServer será seleccionado por este servicio como back-end.Port
: Este es el puerto de servicio.TargetPort
: Puerto Real utilizado por la aplicación en el contenedor. Aquí, it’s el puerto 80, ya que planeamos ejecutar un servidor Web.NodePort
: Puerto en el host de cada nodo del clúster.
Deje’que s cree el servicio:
$ kubectl create -f service-web-nodeport.yaml service "service-web-nodeport" created $ kubectl describe service web-app Name: service-web-nodeport Namespace: default Labels: <none> Annotations: <none> Selector: app=webserver Type: NodePort IP: 10.98.108.168 Port: <unset> 80/TCP TargetPort: 80/TCP NodePort: <unset> 32001/TCP Endpoints: 10.47.255.228:80 Session Affinity: None External Traffic Policy: Cluster Events: <none>
Escríba El tipo de servicio predeterminado es
ClusterIP
. En este ejemplo, establecemos el tipo enNodePort
.NodePort
: De forma predeterminada, Kubernetes asigna puertos de nodo en el rango 30000-32767, si no se menciona en la especificación. Esto puede cambiarse mediante la marca--service-node-port-range
. El servicioNodePort
también se puede establecer el valor, pero asegúrese de’que lo hace en el rango configuradoEndpoints
: PodIP y el puerto de contenedor expuesto. La solicitud de servicio a IP y al puerto de servicio se dirigirá aquí, y 10.47.255.252:80 indica que hemos creado un conjunto Pod que tiene una etiqueta coincidente con el servicio, por lo que su dirección IP está seleccionada como uno de los extremos.
Para esta prueba, asegúrese de que hay al menos un conjunto Pod con la etiqueta app:webserver
funciona. Los pods de secciones anteriores se crean con esta etiqueta. Volver a crear la pod de cliente es’suficiente si ya las quitó.
Ahora podemos probarlo mediante el comando rizo para activar una solicitud HTTP que apunta a cualquier dirección IP del nodo:
$kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE client 1/1 Running 0 20m 10.47.255.252 cent222 <none>
Con la potencia del servicio NodePort, puede tener acceso al servidor Web que se ejecuta en el conjunto Pod desde cualquier nodo a través de la nodePort 32001:
$ kubectl get node -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP ... KERNEL-VERSION CONTAINER-RUNTIME cent111 NotReady master 100d v1.12.3 10.85.188.19 ... 3.10.0-957.10.1.el7.x86_64 docker://18.3.1 cent222 Ready <none> 100d v1.12.3 10.85.188.20 ... 3.10.0-957.10.1.el7.x86_64 docker://18.3.1 cent333 Ready <none> 100d v1.12.3 10.85.188.21 ... 3.10.0-957.10.1.el7.x86_64 docker://18.3.1 $ curl 10.85.188.20:32001 <html> <style> h1 {color:green} h2 {color:red} </style> <div align="center"> <head> <title>Contrail Pod</title> </head> <body> <h1>Hello</h1><br><h2>This page is served by a <b>Contrail</b> pod</h2><br><h3>IP address = 10.47.255.228<br>Hostname = client</h3> <img src="/static/giphy.gif"> </body> </div> </html>
Servicio del equilibrador de carga
El tercer servicio, el servicio equilibrador de carga , va un paso más allá del servicio NodePort al exponer el servicio de forma externa mediante un’equilibrador de carga de proveedor en la nube. El servicio de equilibrador de carga por su propia naturaleza incluye automáticamente todas las características y funciones de los servicios NodePort y ClusterIP.
Kubernetes los clústeres que se ejecutan en proveedores de nube admiten la disposición automática de un equilibrador de carga. La única diferencia entre los tres servicios es el valor Type (tipo). Para volver a usar el mismo archivo de YAML de servicio de NodePort y crear un servicio del equilibrador de carga, solo tiene que establecer el tipo en LoadBalancer:
#service-web-lb.yaml apiVersion: v1 kind: Service metadata: name: service-web-lb spec: ports: - port: 8888 targetPort: 80 selector: app: webserver type: LoadBalancer #<---
La nube verá esta palabra clave y se creará un equilibrador de carga. Mientras tanto, se asigna una balancerIP de carga pública externa para que sirva como dirección IP virtual de front-end. El tráfico que llega a este loadbalancerIP se redirigirá al conjunto Pod del backend de servicio. Tenga en cuenta que este proceso de redirección sólo es una operación de capa de transporte. El loadbalancerIP y el puerto se traducirán a Private back-’end clusterIP y IT s targetPort. No implica ninguna actividad de capa de aplicación. No hay nada como analizar una dirección URL, una solicitud HTTP de proxy, etc., como lo que sucede en el proceso de proxy HTTP. Dado que loadbalancerIP es accesible de forma pública, cualquier host de Internet que tenga acceso a él (y el puerto de servicio) puede tener acceso al servicio que proporciona el clúster Kubernetes.
Desde el punto de’vista de un host de Internet, cuando solicita servicio, se refiere a este puerto público de servicio de loadbalancerIP Plus externo, y la solicitud llegará al pod de back-end. El loadbalancerIP actúa como puerta de enlace entre el servicio dentro del clúster y el mundo exterior.
Algunos proveedores de nube le permiten especificar el loadBalancerIP
. En esos casos, el equilibrador de carga se crea con el loadBalancerIP especificado por el usuario. Si no se especifica el campo loadBalancerIP, el equilibrador de carga se configura con una dirección IP efímera. Si especifica un loadBalancerIP pero su proveedor de nube no admite la característica, se omitirá el campo loadbalancerIP que establezca.
El modo en que un equilibrador de carga se implementa en el servicio de equilibrador de carga es específico del proveedor. Un equilibrador de carga GCE puede funcionar de una manera totalmente diferente con un equilibrador de carga de AWS. Hay una demostración detallada de cómo funciona el servicio del equilibrador de carga en un entorno de Contrail Kubernetes en el capítulo 4.
IP externas
Exponer el servicio fuera del clúster también puede lograrse mediante el externalIPs
,. He’aquí un ejemplo:
#service-web-externalips.yaml apiVersion: v1 kind: Service metadata: name: service-web-externalips spec: ports: - port: 8888 targetPort: 80 selector: app: webserver externalIPs: #<--- - 101.101.101.1 #<---
De la Service
Spec, externalIPs se puede especificar junto con cualquiera de los tipos de servicio. Las direcciones IP externas no se administran mediante Kubernetes y son responsabilidad del administrador de clústeres.
Las direcciones IP externas son distintas a las de loadbalancerIP, que son las asignadas por el administrador de clústeres, mientras que las IP externas vienen con el equilibrador de carga creado por el clúster que la admite.
Implementación del servicio: Kube-proxy
De forma predeterminada, Kubernetes utiliza el módulo de proxy de Kube para los servicios, pero los proveedores de CNI pueden tener sus propias implementaciones para servicios.
Kube-proxy se puede implementar en uno de los tres modos siguientes:
modo de proxy de espacio de usuario
modo de proxy iptables
modo de proxy IPVS
Cuando el tráfico llega a un nodo’, lo reenvía a uno de los pods back-end a través de un plano de reenvío Kube implementado. En este libro no se abordarán explicaciones detalladas ni comparaciones de estos tres modos, pero puede consultar Kubernetes sitio web oficial para obtener más información. En el capítulo 4 se ilustra cómo Juniper Contrail como proveedor de interfaz de red de contenedor (CNI) implementa el servicio.