En esta página se describen los diferentes tipos de servicios de Kubernetes y cómo usa Google Kubernetes Engine (GKE) los servicios para agrupar los endpoints de los pods.
Aprenderás a crear servicios mediante ejemplos de YAML. Cada tipo de servicio usa la dirección IP estable del servicio para reducir la complejidad de tareas específicas de redes y comunicaciones. Por ejemplo, aprenderás a usar varios puertos y endpoints, así como a configurar opciones de pila única o doble que admitan IPv4 e IPv6.
Para saber cómo crear un servicio, consulta Exponer aplicaciones mediante servicios.
Esta página está dirigida a operadores y desarrolladores que aprovisionan y configuran recursos en la nube, y despliegan aplicaciones y servicios. Para obtener más información sobre los roles habituales y las tareas de ejemplo que se mencionan en el contenido, consulta Roles y tareas habituales de los usuarios de GKE. Google Cloud
¿Qué es un servicio de Kubernetes?
La idea de un servicio es agrupar un conjunto de endpoints de pods en un único recurso. Puedes configurar varias formas de acceder a la agrupación. De forma predeterminada, obtienes una dirección IP de clúster estable que los clientes del clúster pueden usar para ponerse en contacto con los pods del servicio. Un cliente envía una solicitud a la dirección IP estable y la solicitud se dirige a uno de los pods del servicio.
Un servicio identifica sus pods miembros con un selector. Para que un pod sea miembro del servicio, debe tener todas las etiquetas especificadas en el selector. Una etiqueta es un par clave-valor arbitrario que se adjunta a un objeto.
El siguiente manifiesto de servicio tiene un selector que especifica dos etiquetas. El campo selector
indica que cualquier pod que tenga tanto la etiqueta app: metrics
como la etiqueta department:engineering
es miembro de este servicio.
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
# Use labels to select the member Pods of the Service.
selector:
app: metrics
department: engineering
ports:
...
¿Por qué usar un servicio de Kubernetes?
En un clúster de Kubernetes, cada pod tiene una dirección IP interna. Sin embargo, los pods de un deployment van y vienen, y sus direcciones IP cambian. Por lo tanto, no tiene sentido usar direcciones IP de pods directamente. Con un servicio, obtienes una dirección IP estable que dura toda la vida del servicio, aunque cambien las direcciones IP de los pods miembros.
Un servicio también proporciona balanceo de carga. Los clientes llaman a una única dirección IP estable y sus solicitudes se equilibran entre los pods que son miembros del servicio.
Tipos de servicios de Kubernetes
Hay cinco tipos de Servicios:
ClusterIP (predeterminado): los clientes internos envían solicitudes a una dirección IP interna estable.
NodePort: los clientes envían solicitudes a la dirección IP de un nodo en uno o varios valores de
nodePort
especificados por el servicio.LoadBalancer: los clientes envían solicitudes a la dirección IP de un balanceador de carga de red.
ExternalName: los clientes internos usan el nombre de DNS de un servicio como alias de un nombre de DNS externo.
Sin interfaz gráfica: puedes usar un servicio sin interfaz gráfica cuando quieras agrupar pods, pero no necesites una dirección IP estable.
El tipo NodePort
es una extensión del tipo ClusterIP
. Por lo tanto, un servicio de tipo NodePort
tiene una dirección IP de clúster.
El tipo LoadBalancer
es una extensión del tipo NodePort
. Por lo tanto, un servicio de tipo LoadBalancer
tiene una dirección IP de clúster y uno o varios valores de nodePort
.
Servicios de tipo ClusterIP
Cuando creas un servicio de tipo ClusterIP
, Kubernetes crea una dirección IP estable a la que se puede acceder desde los nodos del clúster.
Este es un manifiesto de un servicio de tipo ClusterIP:
apiVersion: v1
kind: Service
metadata:
name: my-cip-service
spec:
selector:
app: metrics
department: sales
# Create a ClusterIP Service. Kubernetes dynamically allocates an IP address
# to the Service.
type: ClusterIP
ports:
- protocol: TCP
port: 80
targetPort: 8080
Puedes crear el servicio
con kubectl apply -f [MANIFEST_FILE]
. Una vez que hayas creado el servicio, puedes usar kubectl get service
para ver la dirección IP estable:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
my-cip-service ClusterIP 10.11.247.213 none 80/TCP
Los clientes del clúster llaman al servicio mediante la dirección IP del clúster y el puerto TCP especificado en el campo port
del manifiesto del servicio. La solicitud se reenvía a uno de los pods miembros en el puerto TCP especificado en el campo targetPort
. En el ejemplo anterior, un cliente llama al servicio en 10.11.247.213
en el puerto TCP 80. La solicitud se reenvía a uno de los pods miembros en el puerto TCP 8080. El Pod miembro debe tener un contenedor que esté escuchando en el puerto TCP 8080. Si no hay ningún contenedor escuchando en el puerto 8080, los clientes verán un mensaje como "No se ha podido conectar" o "No se puede acceder a este sitio".
Servicio de tipo NodePort
Cuando creas un servicio de tipo NodePort
, Kubernetes te asigna un valor nodePort
. Después, se podrá acceder al servicio mediante la dirección IP de cualquier nodo junto con el valor nodePort
.
A continuación, se muestra un manifiesto de un servicio de tipo NodePort
:
apiVersion: v1
kind: Service
metadata:
name: my-np-service
spec:
selector:
app: products
department: sales
# Kubernetes allocates a nodePort between 30000 and 32767 for external traffic
# that reaches the node IP address. Additionally, Kubernetes dynamically
# allocates a clusterIP IP address for internal traffic.
type: NodePort
ports:
- protocol: TCP
port: 80 # Route internal traffic that reaches the clusterIP IP address on this port.
targetPort: 8080
Después de crear el servicio, puedes usar kubectl get service -o yaml
para ver su especificación y el valor de nodePort
.
spec:
clusterIP: 10.11.254.114
externalTrafficPolicy: Cluster
ports:
- nodePort: 32675
port: 80
protocol: TCP
targetPort: 8080
Los clientes externos llaman al servicio mediante la dirección IP externa de un nodo junto con el puerto TCP especificado por nodePort
. La solicitud se reenvía a uno de los pods miembros en el puerto TCP especificado por el campo targetPort
.
Por ejemplo, supongamos que la dirección IP externa de uno de los nodos del clúster es 203.0.113.2
. En el ejemplo anterior, el cliente externo llama al servicio en 203.0.113.2
a través del puerto TCP 32675. La solicitud se reenvía a uno de los pods miembros en el puerto TCP 8080. El pod miembro debe tener un contenedor
que escuche en el puerto TCP 8080.
El tipo de servicio NodePort
es una extensión del tipo de servicio ClusterIP
. Por lo tanto, los clientes internos tienen dos formas de llamar al servicio:
- Usa
clusterIP
yport
. - Usa la dirección IP de un nodo y
nodePort
.
En algunas configuraciones de clúster, el balanceador de carga de aplicaciones externo usa un servicio de tipo NodePort
.
Un balanceador de carga de aplicaciones externo es un servidor proxy y es fundamentalmente diferente del balanceador de carga de red de paso a través externo que se describe en este tema en Servicio de tipo LoadBalancer.
Servicios de tipo LoadBalancer
Para obtener más información sobre los servicios de tipo LoadBalancer, consulta Conceptos de servicio LoadBalancer.
Servicio de tipo ExternalName
Un servicio de tipo ExternalName
proporciona un alias interno para un nombre de DNS externo. Los clientes internos hacen solicitudes mediante el nombre de DNS interno y las solicitudes se redirigen al nombre externo.
A continuación, se muestra un manifiesto de un servicio de tipo ExternalName
:
apiVersion: v1
kind: Service
metadata:
name: my-xn-service
spec:
type: ExternalName
externalName: example.com
Cuando creas un servicio, Kubernetes crea un nombre de DNS que los clientes internos pueden usar para llamar al servicio. En el ejemplo anterior, el nombre de DNS es my-xn-service.default.svc.cluster.local. Cuando un cliente interno hace una solicitud a my-xn-service.default.svc.cluster.local, la solicitud se redirige a example.com.
El tipo de servicio ExternalName
es fundamentalmente diferente de los demás tipos de servicio. De hecho, un servicio de tipo ExternalName
no se ajusta a la definición de servicio que se ha dado al principio de este tema. Un servicio de tipo
ExternalName
no está asociado a un conjunto de pods y no tiene una dirección IP estable. En su lugar, un servicio de tipo ExternalName
es una asignación de un nombre de DNS interno a un nombre de DNS externo.
Servicio sin interfaz gráfica
Un servicio sin encabezado es un tipo de servicio de Kubernetes que no asigna una dirección IP de clúster. En su lugar, un servicio sin encabezado usa DNS para exponer las direcciones IP de los pods asociados al servicio. De esta forma, puedes conectarte directamente a los pods en lugar de hacerlo a través de un proxy.
Los servicios sin interfaz gráfica son útiles en diversas situaciones, como las siguientes:
Descubrimiento de servicios: puedes usar un servicio sin encabezado para implementar el descubrimiento de servicios. Para implementar esto, crea un servicio con un nombre y un selector. El registro DNS del servicio sin encabezado contiene todas las IPs de los pods que están detrás del servicio y que coinciden con el selector. Los clientes pueden usar estos registros DNS para encontrar las direcciones IP de los pods asociados al servicio.
Acceso directo a los pods: los clientes pueden conectarse directamente a los pods asociados a un servicio sin interfaz, lo que puede ser útil para los servicios que requieren acceso directo a los pods subyacentes, como los balanceadores de carga y los servidores DNS.
Flexibilidad: los servicios sin encabezado se pueden usar para crear varias topologías diferentes, como balanceadores de carga, servidores DNS y bases de datos distribuidas.
Si tienes requisitos de red especiales para tus cargas de trabajo que no se pueden resolver con servicios sin encabezado con selectores, también puedes usar servicios sin encabezado sin selectores. Los servicios sin encabezado son una herramienta útil para acceder a servicios que no se encuentran en el propio clúster de Kubernetes, ya que el plano de control no crea objetos EndpointSlice. Puedes consultar más información sobre este tema en Servicio sin selectores.
El siguiente ejemplo es un manifiesto de un servicio sin interfaz gráfica:
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
# Prevent Kubernetes from allocating an IP address to the Service.
clusterIP: None
selector:
app: nginx
ports:
- name: http
port: 80
targetPort: 80
Una vez que hayas creado un servicio sin encabezado, puedes encontrar las direcciones IP de los pods asociados al servicio consultando el DNS. Por ejemplo, el siguiente comando muestra las direcciones IP de los pods asociados al servicio nginx:
dig +short nginx.default.svc.cluster.local
Otro ejemplo que usa la expansión de consultas de Kubernetes::
dig +short +search nginx
Puedes crear un servicio sin interfaz gráfica con un solo comando, y estos servicios son fáciles de actualizar y escalar.
kubectl create service clusterip my-svc --clusterip="None" --dry-run=client -o yaml > [file.yaml]
Abstracción de servicios
Un servicio es una abstracción en el sentido de que no es un proceso que escucha en alguna interfaz de red. Parte de la abstracción se implementa en las reglas iptables de los nodos del clúster. En función del tipo de servicio, otras partes de la abstracción se implementan mediante un balanceador de carga de red de paso a través externo o un balanceador de carga de aplicaciones externo.
Puertos de servicio arbitrarios
El valor del campo port
de un manifiesto de servicio es arbitrario. Sin embargo,
el valor de targetPort
no es arbitrario. Cada Pod miembro debe tener un contenedor que escuche en targetPort
.
Aquí tienes un servicio de tipo LoadBalancer
que tiene un valor port
de 50.000:
apiVersion: v1
kind: Service
metadata:
name: my-ap-service
spec:
# Set your own IP address for internal traffic instead of letting Kubernetes
# select one for you.
clusterIP: 10.11.241.93
externalTrafficPolicy: Cluster
ports:
- nodePort: 30641 # Set a port for external traffic that reaches the node IP address.
port: 50000 # Set a port for internal traffic that reaches the clusterIP IP address.
protocol: TCP
targetPort: 8080
selector:
app: parts
department: engineering
sessionAffinity: None
type: LoadBalancer
status:
loadBalancer:
ingress:
- ip: 203.0.113.200
Un cliente llama al Servicio al número 203.0.113.200
a través del puerto TCP 50000. La solicitud se reenvía a uno de los pods miembros en el puerto TCP 8080.
Varios puertos
El campo ports
de un servicio es una matriz de objetos ServicePort. El objeto ServicePort tiene estos campos:
name
protocol
port
targetPort
nodePort
Si tiene más de un ServicePort, cada uno de ellos debe tener un nombre único.
A continuación, se muestra un servicio de tipo LoadBalancer
que tiene dos objetos ServicePort
:
apiVersion: v1
kind: Service
metadata:
name: my-tp-service
spec:
clusterIP: 10.11.242.196
externalTrafficPolicy: Cluster
ports:
# Forward traffic that reaches port 31233 on the node IP address, or port
# 60000 on the clusterIP IP address, to port 50000 on a member Pod.
- name: my-first-service-port
nodePort: 31233
port: 60000
protocol: TCP
targetPort: 50000
# Forward traffic that reaches port 31081 on the node IP address, or port
# 60001 on the clusterIP IP address, to port 8080 on a member Pod.
- name: my-second-service-port
nodePort: 31081
port: 60001
protocol: TCP
targetPort: 8080
selector:
app: tests
department: engineering
sessionAffinity: None
type: LoadBalancer
status:
loadBalancer:
ingress:
- ip: 203.0.113.201
En el ejemplo anterior, si un cliente llama al servicio en 203.0.113.201
en el puerto 60000 de TCP, la solicitud se reenvía a un pod miembro en el puerto 50000 de TCP. Sin embargo, si un cliente llama al servicio en 203.0.113.201
en el puerto TCP 60001, la solicitud se reenvía a un pod miembro en el puerto TCP 8080.
Cada pod miembro debe tener un contenedor que escuche en el puerto TCP 50000 y otro que escuche en el puerto TCP 8080. Puede ser un solo contenedor con dos hilos o dos contenedores que se ejecuten en el mismo pod.
Puntos finales de servicio
Cuando creas un servicio, Kubernetes crea un objeto Endpoints que tiene el mismo nombre que el servicio. Kubernetes usa el objeto Endpoints para registrar qué pods son miembros del servicio.
Servicios de pila única y de pila dual
Puedes crear un servicio IPv6 de tipo
ClusterIP
o NodePort
.
En cada uno de estos tipos de servicio, puedes definir los campos ipFamilies
y ipFamilyPolicy
como IPv4, IPv6 o un servicio de pila dual.
Siguientes pasos
- Consulta más información sobre los servicios de Kubernetes.
- Exponer aplicaciones mediante servicios
- Consulta más información sobre StatefulSets.
- Consulta más información sobre Ingress.