Despliega una aplicación

En este documento se describe cómo desplegar una aplicación en Google Distributed Cloud.

Antes de empezar

Para desplegar una carga de trabajo, debes tener un clúster de usuario, híbrido o independiente que pueda ejecutar cargas de trabajo.

Crear un despliegue

Con los siguientes pasos se crea un Deployment en tu clúster:

  1. Copia el siguiente manifiesto en un archivo llamado my-deployment.yaml:

    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"
    
  2. Usa kubectl apply para crear la implementación:

    kubectl apply -f my-deployment.yaml --kubeconfig CLUSTER_KUBECONFIG
    

    Sustituye CLUSTER_KUBECONFIG por la ruta del archivo kubeconfig de tu clúster.

  3. Obtén información básica sobre tu implementación para confirmar que se ha creado correctamente:

    kubectl get deployment my-deployment --kubeconfig CLUSTER_KUBECONFIG
    

    El resultado muestra que la implementación tiene tres pods que están disponibles:

    NAME            READY   UP-TO-DATE   AVAILABLE   AGE
    my-deployment   3/3     3            3           27s
    
  4. Lista los pods de tu Deployment:

    kubectl get pods --kubeconfig CLUSTER_KUBECONFIG
    

    La salida muestra que tu Deployment tiene tres pods en ejecución:

    NAME                             READY   STATUS    RESTARTS   AGE
    my-deployment-869f65669b-5259x   1/1     Running   0          34s
    my-deployment-869f65669b-9xfrs   1/1     Running   0          34s
    my-deployment-869f65669b-wn4ft   1/1     Running   0          34s
    
  5. Obtén información detallada sobre tu implementación:

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

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

    apiVersion: apps/v1
    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: "2023-06-29T16:17:17Z"
        lastUpdateTime: "2023-06-29T16:17:17Z"
        message: Deployment has minimum availability.
        reason: MinimumReplicasAvailable
        status: "True"
        type: Available
      - lastTransitionTime: "2023-06-29T16:17:12Z"
        lastUpdateTime: "2023-06-29T16:17:17Z"
        message: ReplicaSet "my-deployment-869f65669b" has successfully progressed.
        reason: NewReplicaSetAvailable
        status: "True"
        type: Progressing
      observedGeneration: 1
      readyReplicas: 3
      replicas: 3
      updatedReplicas: 3
    
  6. Describe tu implementación:

    kubectl describe deployment my-deployment --kubeconfig CLUSTER_KUBECONFIG
    

    El resultado muestra detalles sobre la implementación con un formato adecuado, incluido el ReplicaSet asociado:

    Name:                   my-deployment
    Namespace:              default
    CreationTimestamp:      Thu, 29 Jun 2023 16:17:12 +0000
    Labels:                 <none>
    Annotations:            deployment.kubernetes.io/revision: 1
    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:         <none>
        Host Port:    <none>
        Environment:  <none>
        Mounts:       <none>
      Volumes:        <none>
    Conditions:
      Type           Status  Reason
      ----           ------  ------
      Available      True    MinimumReplicasAvailable
      Progressing    True    NewReplicaSetAvailable
    OldReplicaSets:  <none>
    NewReplicaSet:   my-deployment-869f65669b (3/3 replicas created)
    Events:
      Type    Reason             Age    From                   Message
      ----    ------             ----   ----                   -------
      Normal  ScalingReplicaSet  6m50s  deployment-controller  Scaled up replica set my-deployment-869f65669b to 3
    

Crea un servicio de tipo LoadBalancer.

Una forma de exponer tu Deployment a clientes que no estén en tu clúster es crear un Service de Kubernetes de tipo LoadBalancer.

Para crear un servicio de tipo LoadBalancer, sigue estos pasos:

  1. Copia el siguiente manifiesto en un archivo llamado my-service.yaml:

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

    Estos son los aspectos importantes que debes tener en cuenta sobre el servicio en este ejercicio:

    • Todos los pods que tengan la etiqueta app: metrics y la etiqueta department: sales son miembros del servicio. Los pódcasts de my-deployment tienen estas etiquetas.

    • Cuando un cliente envía una solicitud al servicio en el puerto TCP 80, la solicitud se reenvía a un pod miembro en el puerto TCP 8080.

    • Cada miembro del pod debe tener un contenedor que esté escuchando en el puerto TCP 8080.

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

  2. Usa kubectl apply para crear el servicio en tu clúster:

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

    Sustituye CLUSTER_KUBECONFIG por la ruta del archivo kubeconfig de tu clúster.

  3. Ver tu servicio:

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

    El resultado debería ser similar al siguiente:

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

    En el resultado anterior, puedes ver que tu servicio tiene un clusterIP y una dirección IP externa. También tiene un nodePort, un port y un targetPort.

    El clusterIP no es relevante para este ejercicio. La dirección IP externa (status.loadBalancer.ingress.ip) procede del intervalo de direcciones que especificaste al definir los grupos de direcciones del balanceador de carga (spec.loadBalancer.addressPools) en el archivo de configuración del clúster.

    Por ejemplo, toma los valores que se muestran en el resultado anterior de tu servicio:

    • Dirección IP externa: 192.168.1.13
    • port: 80
    • nodePort: 31565
    • targetPort: 8080

    Un cliente envía una solicitud a 192.168.1.13 en el puerto TCP 80. La solicitud se dirige a tu balanceador de carga y, desde ahí, se reenvía a un pod miembro en el puerto TCP 8080.

  4. Llamar a tu servicio:

    curl INGRESS_IP_ADDRESS
    

    Sustituye INGRESS_IP_ADDRESS por la dirección IP de entrada de la sección status del servicio que has obtenido en el paso anterior (status.loadBalancer.ingress).

    El resultado muestra un mensaje Hello, world!:

    Hello, world!
    Version: 2.0.0
    Hostname: my-deployment-869f65669b-wn4ft
    

Límites de puertos de LoadBalancer

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. De forma predeterminada, Kubernetes asigna puertos de nodo a los servicios de tipo LoadBalancer. Estas asignaciones pueden agotar rápidamente los puertos de nodo disponibles de los 2768 asignados a tu clúster. Para guardar los puertos de nodo, inhabilita la asignación de puertos de nodo del balanceador de carga definiendo el campo allocateLoadBalancerNodePorts como false en la especificación del servicio LoadBalancer. Este ajuste impide que Kubernetes asigne puertos de nodo a los servicios LoadBalancer. Para obtener más información, consulta el artículo sobre cómo inhabilitar la asignación de NodePort del balanceador de carga en la documentación de Kubernetes.

Aquí tienes un manifiesto para crear un servicio que no use ningún puerto de nodo:

apiVersion: v1
kind: Service
metadata:
  name: service-does-not-use-nodeports
spec:
  selector:
    app: my-app
  type: LoadBalancer
  ports:
  - port: 8000
  # Set allocateLoadBalancerNodePorts to false
  allocateLoadBalancerNodePorts: false

Eliminar tu Servicio

Para eliminar tu Servicio, sigue estos pasos:

  1. Usa kubectl delete para eliminar tu servicio del clúster:

    kubectl delete service my-service --kubeconfig CLUSTER_KUBECONFIG
    
  2. Comprueba que tu servicio se haya eliminado:

    kubectl get services --kubeconfig CLUSTER_KUBECONFIG
    

    La salida ya no muestra my-service.

Eliminar tu implementación

Para eliminar tu implementación, sigue estos pasos:

  1. Usa kubectl delete para eliminar tu Deployment del clúster:

    kubectl delete deployment my-deployment --kubeconfig CLUSTER_KUBECONFIG
    

    Verifica que se ha eliminado tu implementación:

    kubectl get deployments --kubeconfig CLUSTER_KUBECONFIG
    

    La salida ya no muestra my-deployment.

Siguientes pasos

Crear objetos Ingress y Service