Implementa una aplicación

En este documento, se describe cómo implementar una aplicación en GKE en Bare Metal.

Antes de comenzar

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

Crear una implementación

Sigue estos pasos para crear un Deployment en tu clúster:

  1. Luego, copia el siguiente manifiesto a 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 el Deployment:

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

    Reemplaza CLUSTER_KUBECONFIG por la ruta de acceso del archivo kubeconfig del clúster.

  3. Obtén información básica sobre tu Deployment para confirmar que se creó de forma correcta:

    kubectl get deployment my-deployment --kubeconfig CLUSTER_KUBECONFIG
    

    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
    
  4. Obtén una lista de los Pods del Deployment:

    kubectl get pods --kubeconfig CLUSTER_KUBECONFIG
    

    El resultado 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 el Deployment:

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

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

    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 Deployment:

    kubectl describe deployment my-deployment --kubeconfig CLUSTER_KUBECONFIG
    

    El resultado muestra detalles con un buen formato sobre la Deployment, 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 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.

Para crear un Service de tipo LoadBalancer, haz lo siguiente:

  1. Luego, copia el siguiente manifiesto a 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 comprender sobre el servicio en este ejercicio:

    • Cualquier pod que tenga las etiquetas app: metrics y department: sales es miembro del servicio. 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 la configuración del puerto en el Dockerfile y el código fuente de la app.

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

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

    Reemplaza CLUSTER_KUBECONFIG por la ruta de acceso del archivo kubeconfig del clúster.

  3. Observa tu servicio:

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

    El resultado es 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 el Service 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) proviene del rango de direcciones que especificaste cuando definiste grupos de direcciones del balanceador de cargas (spec.loadBalancer.addressPools) en el archivo de configuración del clúster.

    Como ejemplo, toma los valores que se muestran en el resultado anterior para tu Service:

    • 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 enruta al balanceador de cargas y desde allí se reenvía a un Pod miembro en el puerto TCP 8080.

  4. Llama a tu Service:

    curl INGRESS_IP_ADDRESS
    

    Reemplaza INGRESS_IP_ADDRESS por la dirección IP de entrada en la sección status del servicio que recuperaste 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 LoadBalancer

El tipo LoadBalancer es una extensión del tipo NodePort. Entonces, un servicio de tipo LoadBalancer tiene una dirección IP de clúster y uno o más valores nodePort. De forma predeterminada, Kubernetes asigna puertos de nodo a Services de tipo LoadBalancer. Estas asignaciones pueden agotar con rapidez los puertos de nodo disponibles de los 2,768 asignados a tu clúster. Para guardar los puertos de nodo, inhabilita la asignación de puertos del nodo del balanceador de cargas mediante la configuración del campo allocateLoadBalancerNodePorts en false en la especificación del Service LoadBalancer. Esta configuración evita que Kubernetes asigne puertos de nodo a los servicios de LoadBalancer. Para obtener más información, consulta Inhabilita la asignación de NodePort del balanceador de cargas en la documentación de Kubernetes.

A continuación, se muestra un manifiesto para crear un Service 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

Borrar el servicio

Para borrar el Service, haz lo siguiente:

  1. Usa kubectl delete para borrar el Service del clúster:

    kubectl delete service my-service --kubeconfig CLUSTER_KUBECONFIG
    
  2. Verifica que se haya borrado tu Service:

    kubectl get services --kubeconfig CLUSTER_KUBECONFIG
    

    El resultado ya no muestra my-service.

Borra el Deployment

Para borrar tu Deployment, haz lo siguiente:

  1. Usa kubectl delete para borrar el Deployment del clúster:

    kubectl delete deployment my-deployment --kubeconfig CLUSTER_KUBECONFIG
    

    Verifica que se haya borrado el Deployment:

    kubectl get deployments --kubeconfig CLUSTER_KUBECONFIG
    

    El resultado ya no muestra my-deployment.

¿Qué sigue?

Crea un Service y un Ingress