Implementa una aplicación

En este documento, se ofrece un ejemplo de cómo implementar una aplicación en un clúster de usuario para Google Distributed Cloud.

Antes de comenzar

Para el ejemplo que se brinda aquí, necesitas un clúster de usuario que use el balanceo de cargas de MetalLB integrado. Si deseas obtener instrucciones para crear un clúster de usuario mínimo que use MetalLB, consulta Crea clústeres básicos.

Puedes usar la consola de Google Cloud o la herramienta de línea de comandos kubectl en tu estación de trabajo de administrador para implementar la aplicación.

Console

  1. En la consola, ve a la página Descripción general de los clústeres de Google Kubernetes Engine.

    Ir a los clústeres de GKE

  2. En la lista de clústeres, haz clic en tu clúster de usuario y verifica que hayas accedido a él.

    Si aún no accediste al clúster de usuario, sigue las instrucciones en Administra clústeres desde la consola de Google Cloud para acceder.

Contenedores

  1. En Contenedor nuevo, selecciona Imagen de contenedor existente.

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

  3. Haz clic en Continuar.

Configuración

  1. En Nombre de la implementación, ingresa my-deployment.

  2. En Espacio de nombres, ingresa default.

  3. Ingresa estas dos etiquetas:

    • Clave 1: app, Valor 1: metrics
    • Clave 2: department, valor 2 sales
  4. En el menú desplegable Clúster de Kubernetes, selecciona tu clúster.

  5. Haz clic en Continuar.

Exponer

  1. Marca Exponer la implementación como un servicio nuevo.

  2. En Puerto 1, ingresa 80.

  3. En Puerto de destino 1, ingresa 8080. Este es el valor apropiado porque el contenedor hello-app escucha en el puerto TCP 8080 de forma predeterminada. Puedes ver esto si observas el Dockerfile y el código fuente de la aplicación.

  4. En Protocolo 1, selecciona TCP.

  5. En Tipo de servicio, selecciona LoadBalancer.

En la parte inferior de la página, haz clic en el botón Implementar.

Ver detalles de la implementación y el servicio

  1. Cuando la Deployment esté lista, se abrirá la página Detalles de la implementación en la sección Cargas de trabajo de Kubernetes de la consola de Google Cloud. En esta página, puedes ver detalles sobre el Deployment y sus tres Pods.

  2. En Servicios expuestos, haz clic en el nombre del servicio que expone tu Deployment. Para este ejercicio, el nombre es my-deployment-service.

  3. Se abrirá la página Detalles del servicio. En esta página, puedes ver detalles sobre el servicio. Por ejemplo, puedes ver que cualquier Pod que tenga las etiquetas app: metrics y department: sales es miembro del Service. Recuerda que los Pods en my-deployment tienen estas etiquetas.

También puedes ver un valor para la IP del balanceador de cargas. La IP del balanceador de cargas se configuró de forma automática en el balanceador de cargas del clúster.

Reenvío del servicio

Supongamos que un cliente fuera del clúster envía una solicitud a la IP del balanceador de cargas en el puerto TCP 80. La solicitud se enruta al balanceador de cargas del clúster. El balanceador de cargas reenvía la solicitud a un Pod miembro en el puerto TCP 8080. Recuerda que cada Pod de my-deployment tiene un contenedor que escucha en el puerto TCP 8080.

Prueba tu Service

Ve a una máquina en la que la IP del balanceador de cargas se pueda enrutar.

Para llamar a tu servicio, ingresa la IP del balanceador de cargas en un navegador o usa un comando como curl. Por ejemplo:

curl [LOAD_BALANCER_IP]:80

El resultado muestra un mensaje Hello, world!. Por ejemplo:

curl 203.0.113.1:80
Hello, world!
Version: 2.0.0
Hostname: my-deployment-dbd86c8c4-9wpbv

Borra el objeto Deployment

Ve a la página Cargas de trabajo en la sección Kubernetes Engine de la consola.

Ir a la página Cargas de trabajo

En la lista de Deployments, selecciona my-deployment.

En la parte superior de la página, haz clic en Borrar. Esto borra el Deployment y el Service de exposición.

Línea de comandos

Conéctate a la estación de trabajo de administrador

Obtener una conexión SSH a tu estación de trabajo de administrador Sigue estos pasos en la estación de trabajo de administrador.

Crear una implementación

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

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 --kubeconfig USER_CLUSTER_KUBECONFIG -f my-deployment.yaml

En el ejemplo anterior, USER_CLUSTER_KUBECONFIG es la ruta de acceso del archivo kubeconfig del clúster de usuario.

Obtén información básica sobre el Deployment:

kubectl --kubeconfig USER_CLUSTER_KUBECONFIG get deployment my-deployment

El resultado muestra que el Deployment tiene tres Pods y que todos están disponibles:

NAME            READY   UP-TO-DATE   AVAILABLE   AGE
my-deployment   3/3     3            3           27s

Obtén una lista de los Pods del Deployment:

kubectl --kubeconfig USER_CLUSTER_KUBECONFIG get pods

El resultado muestra que tu Deployment tiene tres Pods en ejecución:

NAME                             READY   STATUS    RESTARTS   AGE
my-deployment-54944c8d55-4srm2   1/1     Running   0          6s
my-deployment-54944c8d55-7z5nn   1/1     Running   0          6s
my-deployment-54944c8d55-j62n9   1/1     Running   0          6s

Obtén información detallada sobre el Deployment:

kubectl --kubeconfig USER_CLUSTER_KUBECONFIG get deployment my-deployment --output yaml

El resultado muestra detalles sobre la especificación y el estado del Deployment:

kind: Deployment
metadata:
  ...
  generation: 1
  name: my-deployment
  namespace: default
  ...
spec:
  ...
  replicas: 3
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: metrics
      department: sales
  ...
    spec:
      containers:
      - image: us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0
        imagePullPolicy: IfNotPresent
        name: hello
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
status:
  availableReplicas: 3
  conditions:
  ‑ lastTransitionTime: "2019-11-11T18:44:02Z"
    lastUpdateTime: "2019-11-11T18:44:02Z"
    message: Deployment has minimum availability.
    reason: MinimumReplicasAvailable
    status: "True"
    type: Available
  ‑ lastTransitionTime: "2019-11-11T18:43:58Z"
    lastUpdateTime: "2019-11-11T18:44:02Z"
    message: ReplicaSet "my-deployment-54944c8d55" has successfully progressed.
    reason: NewReplicaSetAvailable
    status: "True"
    type: Progressing
  observedGeneration: 1
  readyReplicas: 3
  replicas: 3
  updatedReplicas: 3

Describe tu Deployment:

kubectl --kubeconfig USER_CLUSTER_KUBECONFIG describe deployment my-deployment

En el resultado, se muestran detalles con un buen formato sobre el Deployment, incluido el ReplicaSet asociado:

Name:                   my-deployment
Namespace:              default
CreationTimestamp:      Mon, 11 Nov 2019 10:43:58 -0800
Labels:                 
...
Selector:               app=metrics,department=sales
Replicas:               3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  app=metrics
           department=sales
  Containers:
    hello:
    Image:        us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0
    Port:         
    Host Port:    
    Environment:  
    Mounts:       
  Volumes:        
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  
NewReplicaSet:   my-deployment-54944c8d55 (3/3 replicas created)

Crea un Service de tipo LoadBalancer

Una forma de exponer el Deployment a clientes fuera de tu clúster es crear un Service de Kubernetes de tipo LoadBalancer.

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

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: metrics
    department: sales
  type: LoadBalancer
  ports:
  ‑ port: 80
    targetPort: 8080

Para los fines de este ejercicio, aquí se presentan los puntos importantes que debes comprender sobre el Service:

  • Cualquier Pod que tenga las etiquetas app: metrics y department: sales es miembro del Service. Ten en cuenta que los Pods en my-deployment tienen estas etiquetas.

  • Cuando un cliente envía una solicitud al Service en el puerto TCP 80, 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 8080.

De forma predeterminada, el contenedor hello-app escucha en el puerto TCP 8080. Puedes ver esto si observas el Dockerfile y el código fuente de la aplicación.

Guarda el manifiesto en un archivo denominado my-service.yaml y crea el Service:

kubectl --kubeconfig USER_CLUSTER_KUBECONFIG apply -f my-service.yaml

En el ejemplo anterior, USER_CLUSTER_KUBECONFIG es la ruta de acceso del archivo kubeconfig del clúster de usuario.

Cuando creas el servicio, GKE en VMware configura de forma automática la dirección loadBalancerIP en el balanceador de cargas del clúster.

Observa tu servicio:

kubectl --kubeconfig USER_CLUSTER_KUBECONFIG get service my-service --output yaml

El resultado es similar al siguiente ejemplo:

kind: Service
metadata:
  ...
  name: my-service
  namespace: default
  ...
spec:
  allocateLoadBalancerNodePorts: true
  clusterIP: 10.96.1.39
  clusterIPs:
  - 10.96.1.39
  externalTrafficPolicy: Cluster
  internalTrafficPolicy: Cluster
  ipFamilies:
  - IPv4
  ipFamilyPolicy: SingleStack
  ports:
  - nodePort: 31184
    port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    app: metrics
    department: sales
  sessionAffinity: None
  type: LoadBalancer
status:
  loadBalancer:
    ingress:
    - ip: 203.0.113.1

En el resultado anterior, puedes ver que tu Service tiene una clusterIP y una loadBalancerIP. También tiene un port y un targetPort.

La clusterIP no es relevante para este ejercicio. loadBalancerIP es la dirección IP que los clientes fuera del clúster pueden usar para llamar al servicio.

Por ejemplo, toma los valores que se muestran en el resultado anterior. Es decir, supongamos que tu Service tiene loadBalancerIP = 203.0.113.1, port = 80 y targetPort = 8080.

Un cliente envía una solicitud a 203.0.113.1 en el puerto TCP 80. La solicitud se enruta al balanceador de cargas del clúster. El balanceador de cargas reenvía la solicitud a un Pod miembro en el puerto TCP 8080.

Llama a tu Service:

curl LOAD_BALANCER_IP

El resultado muestra un mensaje Hello, world!:

curl 203.0.113.1
Hello, world!
Version: 2.0.0
Hostname: my-deployment-dbd86c8c4-9wpbv

Borra tu Service

Borra el Service:

kubectl --kubeconfig USER_CLUSTER_KUBECONFIG delete service my-service

Verifica que se haya borrado tu Service:

kubectl --kubeconfig USER_CLUSTER_KUBECONFIG get services

El resultado ya no muestra my-service.

Borra tu Deployment

Borra el Deployment:

kubectl --kubeconfig USER_CLUSTER_KUBECONFIG delete deployment my-deployment

Verifica que se haya borrado el Deployment:

kubectl --kubeconfig USER_CLUSTER_KUBECONFIG get deployments

El resultado ya no muestra my-deployment.

¿Qué sigue?

Crea un Service y un Ingress