Expón aplicaciones con servicios

En esta página, se muestra cómo crear servicios de Kubernetes en un clúster de Google Kubernetes Engine. Para ver una explicación del concepto de Servicio y un análisis de los distintos tipos que existen, consulta Servicio.

Introducción

El concepto de Servicio es agrupar un conjunto de extremos de pod en un solo recurso. Puedes configurar varias formas para acceder a la agrupación. De forma predeterminada, obtienes una dirección IP de clúster estable que los clientes dentro del clúster pueden usar para comunicarse con los pods en el servicio. Un cliente envía una solicitud a una dirección IP estable, y la solicitud se enruta a uno de los pods en el Servicio.

Existen 5 tipos de Servicios:

  • ClusterIP (predeterminado)
  • NodePort
  • LoadBalancer
  • ExternalName
  • Headless

Los clústeres de Autopilot son públicos de forma predeterminada. Si eliges un clúster de Autopilot privado, debes configurar Cloud NAT para hacer conexiones a Internet salientes, por ejemplo, mediante la extracción de imágenes de DockerHub.

Este tema tiene varios ejercicios. En cada ejercicio, creas una implementación y expones sus pods mediante la creación de un Servicio. Luego, envías una solicitud HTTP al Servicio.

Antes de comenzar

Antes de comenzar, asegúrate de haber realizado las siguientes tareas:

Establece la configuración de gcloud predeterminada mediante uno de los siguientes métodos:

  • Usa gcloud init si deseas ver una explicación sobre cómo configurar parámetros predeterminados.
  • Usa gcloud config para establecer el ID, la zona y la región del proyecto de manera individual.

Usa gcloud init

Si recibes el error One of [--zone, --region] must be supplied: Please specify location, completa esta sección.

  1. Ejecuta gcloud init y sigue las instrucciones:

    gcloud init

    Si usas SSH en un servidor remoto, usa la marca --console-only para evitar que el comando abra un navegador:

    gcloud init --console-only
  2. Sigue las instrucciones a fin de autorizar a gcloud para que use tu cuenta de Google Cloud.
  3. Crea una configuración nueva o selecciona una existente.
  4. Elige un proyecto de Google Cloud.
  5. Elige una zona predeterminada de Compute Engine para clústeres zonales o una región para clústeres regionales o de Autopilot.

Usa gcloud config

  • Establece tu ID del proyecto predeterminado:
    gcloud config set project PROJECT_ID
  • Si trabajas con clústeres zonales, establece tu zona de procesamiento predeterminada:
    gcloud config set compute/zone COMPUTE_ZONE
  • Si trabajas con clústeres de Autopilot o regionales, configura tu región de procesamiento predeterminada:
    gcloud config set compute/region COMPUTE_REGION
  • Actualiza gcloud a la versión más reciente:
    gcloud components update

Crea un servicio de tipo ClusterIP

kubectl apply

A continuación, se muestra un manifiesto de implementación:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment
spec:
  selector:
    matchLabels:
      app: metrics
      department: sales
  replicas: 3
  template:
    metadata:
      labels:
        app: metrics
        department: sales
    spec:
      containers:
      - name: hello
        image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0"

Copia el manifiesto en un archivo llamado my-deployment.yaml y crea la implementación:

kubectl apply -f my-deployment.yaml

Verifica que los tres pods estén en ejecución:

kubectl get pods

El resultado muestra los tres Pods en ejecución:

NAME                            READY   STATUS    RESTARTS   AGE
my-deployment-dbd86c8c4-h5wsf   1/1     Running   0          7s
my-deployment-dbd86c8c4-qfw22   1/1     Running   0          7s
my-deployment-dbd86c8c4-wt4s6   1/1     Running   0          7s

Aquí hay un manifiesto para un servicio de tipo ClusterIP:

apiVersion: v1
kind: Service
metadata:
  name: my-cip-service
spec:
  type: ClusterIP
  # Uncomment the below line to create a Headless Service
  # clusterIP: None
  selector:
    app: metrics
    department: sales
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080

Este servicio tiene un selector que especifica dos etiquetas:

  • app: metrics
  • department: sales

Todos los Pods del Deployment que creaste anteriormente tienen esas dos etiquetas. Por lo tanto, formarán parte de este servicio.

Copia el manifiesto en un archivo llamado my-cip-service.yaml y crea el servicio:

kubectl apply -f my-cip-service.yaml

Espera un momento a que Kubernetes asigne una dirección interna estable al servicio y revísalo:

kubectl get service my-cip-service --output yaml

La salida muestra un valor para clusterIP:

spec:
  clusterIP: 10.59.241.241

Anota el valor clusterIP para usar más adelante.

Console

Crear una implementación

  1. Dirígete a la página Cargas de trabajo en Cloud Console.

    Ir a Cargas de trabajo

  2. Haz clic en Implementar.

  3. En Contenedor, selecciona Imagen de contenedor existente.

  4. En Ruta de acceso a la imagen, ingresa us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0.

  5. Haz clic en Listo y, luego, en Continuar.

  6. En Configuración, en Nombre de la aplicación, ingresa my-deployment.

  7. En Etiquetas, crea las siguientes etiquetas:

    • Clave: app y Valor: metrics
    • Clave: department y Valor: sales
  8. En Clúster, elige el clúster en el que deseas crear el Deployment.

  9. Haz clic en Implementar.

  10. Cuando tu Deployment esté lista, se abrirá la página Detalles de Deployment. En Pods administrados, puedes ver que tu Deployment tiene uno o más Pods en ejecución.

Crea un servicio para exponer tu Deployment

  1. En la página Detalles de Deployment, haz clic en Acciones > Exponer.
  2. En el diálogo Exponer, en Asignación de puertos, establece los siguientes valores:

    • Puerto: 80
    • Puerto de destino: 8080
    • Protocolo: TCP
  3. En la lista desplegable Tipo de servicio, selecciona IP de clúster.

  4. Haz clic en Exponer.

  5. Cuando tu servicio esté listo, se abrirá la página Detalles del servicio y podrás consultar toda la información. En IP del clúster, anota la dirección IP que Kubernetes le asignó a tu Service. Esta es la dirección IP que los clientes internos pueden usar para llamar al servicio.

Accede a tu servicio

Enumera los Pods en ejecución:

kubectl get pods

En el resultado, copia uno de los nombres de Pods que comience con my-deployment.

NAME                            READY   STATUS    RESTARTS   AGE
my-deployment-dbd86c8c4-h5wsf   1/1     Running   0          2m51s

Obtén una shell en uno de tus contenedores en ejecución:

kubectl exec -it POD_NAME -- sh

Reemplaza POD_NAME por el nombre de uno de los Pods en my-deployment.

En tu shell, instala curl:

apk add --no-cache curl

En el contenedor, usa la dirección IP de tu clúster y el puerto 80 para hacer una solicitud a tu servicio. Ten en cuenta que 80 corresponde al valor del campo port de tu servicio. Este es el puerto que usas como cliente del servicio.

curl CLUSTER_IP:80

Reemplaza CLUSTER_IP por el valor de clusterIP en tu servicio.

Tu solicitud se reenvía a uno de los pods miembros en el puerto TCP 8080, que es el valor del campo targetPort. Ten en cuenta que cada pod miembro del servicio debe tener un contenedor que esté escuchando en el puerto 8080.

La respuesta muestra el resultado de hello-app:

Hello, world!
Version: 2.0.0
Hostname: my-deployment-dbd86c8c4-h5wsf

Para salir de la shell hacia tu contenedor, ingresa exit.

Crea un servicio de tipo NodePort

kubectl apply

A continuación, se muestra un manifiesto de Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment-50000
spec:
  selector:
    matchLabels:
      app: metrics
      department: engineering
  replicas: 3
  template:
    metadata:
      labels:
        app: metrics
        department: engineering
    spec:
      containers:
      - name: hello
        image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0"
        env:
        - name: "PORT"
          value: "50000"

Observa el objeto env en el manifiesto. El objeto env especifica que la variable de entorno PORT del contenedor en ejecución tendrá el valor 50000. La aplicación hello-app escucha en el puerto que se especifica en la variable de entorno PORT. Por lo tanto, en este ejercicio, le indicas al contenedor que escuche en el puerto 50000.

Copia el manifiesto en un archivo llamado my-deployment-50000.yaml y crea la implementación:

kubectl apply -f my-deployment-50000.yaml

Verifica que los tres pods estén en ejecución:

kubectl get pods

A continuación, se muestra un manifiesto de un servicio de tipo NodePort:

apiVersion: v1
kind: Service
metadata:
  name: my-np-service
spec:
  type: NodePort
  selector:
    app: metrics
    department: engineering
  ports:
  - protocol: TCP
    port: 80
    targetPort: 50000

Copia el manifiesto en un archivo llamado my-np-service.yaml y crea el servicio:

kubectl apply -f my-np-service.yaml

Observa el servicio:

kubectl get service my-np-service --output yaml

La salida muestra un valor nodePort:

...
  spec:
    ...
    ports:
    - nodePort: 30876
      port: 80
      protocol: TCP
      targetPort: 50000
    selector:
      app: metrics
      department: engineering
    sessionAffinity: None
    type: NodePort
...

Si los nodos de tu clúster tienen direcciones IP externas, busca la dirección IP externa de uno de los nodos:

kubectl get nodes --output wide

En el resultado aparecerán las direcciones IP externas de tus nodos:

NAME          STATUS    ROLES     AGE    VERSION        EXTERNAL-IP
gke-svc-...   Ready     none      1h     v1.9.7-gke.6   203.0.113.1

No todos los clústeres tienen direcciones IP externas para los nodos. Por ejemplo, los nodos de clústeres privados no tienen direcciones IP externas.

Crea una regla de firewall para permitir el tráfico de TCP en el puerto del nodo:

gcloud compute firewall-rules create test-node-port \
    --allow tcp:NODE_PORT

Reemplaza NODE_PORT por el valor del campo nodePort del servicio.

Console

Crear una implementación

  1. Dirígete a la página Cargas de trabajo en Cloud Console.

    Ir a Cargas de trabajo

  2. Haz clic en Implementar.

  3. En Contenedor, selecciona Imagen de contenedor existente.

  4. En Ruta de acceso a la imagen, ingresa us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0.

  5. Haz clic en Agregar variable de entorno.

  6. En Clave, ingresa PORT y en Valor, ingresa 50000.

  7. Haz clic en Listo y, luego, en Continuar.

  8. En Configuración, en Nombre de la aplicación, ingresa my-deployment-50000.

  9. En Etiquetas, crea las siguientes etiquetas:

    • Clave: app y Valor: metrics
    • Clave: department y Valor: engineering
  10. En Clúster, elige el clúster en el que deseas crear el Deployment.

  11. Haz clic en Implementar.

  12. Cuando tu Deployment esté lista, se abrirá la página Detalles de Deployment. En Pods administrados, puedes ver que tu Deployment tiene uno o más Pods en ejecución.

Crea un servicio para exponer tu Deployment

  1. En la página Detalles de Deployment, haz clic en Acciones > Exponer.
  2. En el diálogo Exponer, en Asignación de puertos, establece los siguientes valores:

    • Puerto: 80
    • Puerto de destino: 50000
    • Protocolo: TCP
  3. En la desplegable Tipo de servicio, selecciona Puerto del nodo.

  4. Haz clic en Exponer.

  5. Cuando tu servicio esté listo, se abrirá la página Detalles del servicio y podrás consultar toda la información. En Puertos, anota el Puerto del nodo que Kubernetes le asignó a tu Service.

Crea una regla de firewall para el puerto del nodo

  1. Dirígete a la página Firewall en Cloud Console.

    Ir a Firewall

  2. Haz clic en Crear regla de firewall.

  3. En Nombre, ingresa test-node-port.

  4. En la lista desplegable Destinos, selecciona Todas las instancias de la red.

  5. En Rangos de IP de origen, ingresa 0.0.0.0/0.

  6. En Protocolos y puertos, selecciona Protocolos y puertos especificados.

  7. Selecciona la casilla de verificación tcp y, luego, ingresa el valor del puerto de nodo que anotaste.

  8. Haz clic en Crear.

Busca la dirección IP externa de uno de los nodos de tu clúster.

  1. Ve a la página de Google Kubernetes Engine en Cloud Console:

    Ir a Google Kubernetes Engine

  2. Haz clic en el nombre del clúster que usas para el ejercicio.

  3. En la página Detalles del clúster, haz clic en la pestaña Nodos.

  4. En Grupos de nodos, haz clic en el nombre de un grupo de nodos para abrir la página Detalles del grupo de nodos.

  5. En Grupos de instancias, haz clic en el nombre del grupo de instancias.

  6. En la lista de nodos, toma nota de una de las direcciones IP externas.

Accede a tu servicio

En la barra de direcciones del navegador, ingresa lo siguiente:

NODE_IP_ADDRESS:NODE_PORT

Reemplaza lo siguiente:

  • NODE_IP_ADDRESS: la dirección IP externa de uno de tus nodos, que se encuentra cuando se crea el servicio en la tarea anterior.
  • NODE_PORT: es el valor del puerto del nodo.

El resultado es similar a este:

Hello, world!
Version: 2.0.0
Hostname: my-deployment-50000-6fb75d85c9-g8c4f

Crea un Servicio de tipo LoadBalancer

kubectl apply

A continuación, se muestra un manifiesto de Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment-50001
spec:
  selector:
    matchLabels:
      app: products
      department: sales
  replicas: 3
  template:
    metadata:
      labels:
        app: products
        department: sales
    spec:
      containers:
      - name: hello
        image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0"
        env:
        - name: "PORT"
          value: "50001"

Ten en cuenta que los contenedores de esta implementación escucharán en el puerto 50001.

Copia el manifiesto en un archivo llamado my-deployment-50001.yaml y crea la implementación:

kubectl apply -f my-deployment-50001.yaml

Verifica que los tres pods estén en ejecución:

kubectl get pods

Aquí hay un manifiesto para un servicio de tipo LoadBalancer:

apiVersion: v1
kind: Service
metadata:
  name: my-lb-service
spec:
  type: LoadBalancer
  selector:
    app: products
    department: sales
  ports:
  - protocol: TCP
    port: 60000
    targetPort: 50001

Copia el manifiesto en un archivo llamado my-lb-service.yaml, y crea el servicio:

kubectl apply -f my-lb-service.yaml

Cuando creas un servicio de tipo LoadBalancer, un controlador de Google Cloud se activa y configura un balanceador de cargas de red. Espera un minuto a que el controlador configure el balanceador de cargas de la red y genere una dirección IP estable.

Observa el servicio:

kubectl get service my-lb-service --output yaml

En el resultado, se muestra una dirección IP externa estable en loadBalancer:ingress.

...
spec:
  ...
  ports:
  - ...
    port: 60000
    protocol: TCP
    targetPort: 50001
  selector:
    app: products
    department: sales
  sessionAffinity: None
  type: LoadBalancer
status:
  loadBalancer:
    ingress:
    - ip: 203.0.113.10

Console

Crear una implementación

  1. Dirígete a la página Cargas de trabajo en Cloud Console.

    Ir a Cargas de trabajo

  2. Haz clic en Implementar.

  3. En Contenedor, selecciona Imagen de contenedor existente.

  4. En Ruta de acceso a la imagen, ingresa us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0.

  5. Haz clic en Agregar variable de entorno.

  6. En Clave, ingresa PORT y en Valor, ingresa 50001.

  7. Haz clic en Listo y, luego, en Continuar.

  8. En Configuración, en Nombre de la aplicación, ingresa my-deployment-50001.

  9. En Etiquetas, crea las siguientes etiquetas:

    • Clave: app y Valor: products
    • Clave: department y Valor: sales
  10. En Clúster, elige el clúster en el que deseas crear el Deployment.

  11. Haz clic en Implementar.

  12. Cuando tu Deployment esté lista, se abrirá la página Detalles de Deployment. En Pods administrados, puedes ver que tu Deployment tiene uno o más Pods en ejecución.

Crea un servicio para exponer tu Deployment

  1. En la página Detalles de Deployment, haz clic en Acciones > Exponer.
  2. En el diálogo Exponer, en Asignación de puertos, establece los siguientes valores:

    • Puerto: 60000
    • Puerto de destino: 50001
    • Protocolo: TCP
  3. En la lista desplegable Tipo de servicio, selecciona Balanceador de cargas.

  4. Haz clic en Exponer.

  5. Cuando tu servicio esté listo, se abrirá la página Detalles del servicio y podrás consultar toda la información. En Balanceador de cargas, toma nota de la dirección IP externa del balanceador de cargas.

Accede a tu servicio

Espera unos minutos a que GKE configure el balanceador de cargas.

En la barra de direcciones del navegador, ingresa lo siguiente:

LOAD_BALANCER_ADDRESS:60000

Reemplaza LOAD_BALANCER_ADDRESS por la dirección IP externa del balanceador de cargas.

La respuesta muestra la salida de hello-app:

Hello, world!
Version: 2.0.0
Hostname: my-deployment-50001-68bb7dfb4b-prvct

Ten en cuenta que el valor de port en un servicio es arbitrario En el ejemplo anterior, esto se demuestra con el valor port en 60000.

Crea un servicio de tipo ExternalName

Un servicio de tipo ExternalName proporciona un alias interno para un nombre de DNS externo. Los clientes internos hacen solicitudes con el nombre de DNS interno, y las solicitudes se redireccionan a un nombre externo.

Aquí hay un manifiesto para un servicio de tipo ExternalName:

apiVersion: v1
kind: Service
metadata:
  name: my-xn-service
spec:
  type: ExternalName
  externalName: example.com

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, esta se redirecciona a example.com.

Usa kubectl expose para crear un servicio

Como alternativa a escribir un manifiesto de servicio, puedes crear un servicio con kubectl expose para exponer una implementación.

Si deseas exponer my-deployment, tal como se demostró antes en este tema, puedes ingresar este comando:

kubectl expose deployment my-deployment --name my-cip-service \
    --type ClusterIP --protocol TCP --port 80 --target-port 8080

Si deseas exponer my-deployment-50000, tal como se demostró antes en este tema, puedes ingresar este comando:

kubectl expose deployment my-deployment-50000 --name my-np-service \
    --type NodePort --protocol TCP --port 80 --target-port 50000

Si deseas exponer my-deployment-50001, tal como se demostró antes en este tema, puedes ingresar este comando:

kubectl expose deployment my-deployment-50001 --name my-lb-service \
    --type LoadBalancer --port 60000 --target-port 50001

Realiza una limpieza

Después de completar los ejercicios de esta página, sigue estos pasos para quitar los recursos a fin de prevenir cobros no deseados en tu cuenta:

kubectl apply

Borra tus Servicios

kubectl delete services my-cip-service my-np-service my-lb-service

Borrar tus Deployments

kubectl delete deployments my-deployment my-deployment-50000 my-deployment-50001

Borrar tus reglas de firewall

gcloud compute firewall-rules delete test-node-port

Console

Borra tus Servicios

  1. Dirígete a la página Objetos de Service en Cloud Console.

    Ir a Servicios

  2. Selecciona los objetos de Servicio que creaste en este ejercicio y, luego, haz clic en Borrar.

  3. Cuando se te solicite confirmar, haz clic en Borrar.

Borrar tus Deployments

  1. Dirígete a la página Cargas de trabajo en Cloud Console.

    Ir a Cargas de trabajo

  2. Selecciona los objetos Deployment que creaste en este ejercicio y haz clic en Borrar.

  3. Cuando se te solicite confirmación, selecciona la casilla de verificación Borrar los escaladores automáticos de pod horizontales asociados con los Deployments seleccionados y, luego, haz clic en Borrar.

Borra tus reglas de firewall

  1. Dirígete a la página Firewall en Cloud Console.

    Ir a Firewall

  2. Selecciona la casilla de verificación test-node-port y, luego, haz clic en Borrar.

  3. Cuando se te solicite confirmar, haz clic en Borrar.

¿Qué sigue?