Implementare un'applicazione

Questo documento descrive come eseguire il deployment di un'applicazione su Google Distributed Cloud.

Prima di iniziare

Per eseguire il deployment di un carico di lavoro, devi disporre di un cluster utente, ibrido o autonomo in grado di eseguire carichi di lavoro.

Creazione di un deployment

I passaggi seguenti creano un deployment nel tuo cluster:

  1. Copia il seguente manifest in un file denominato 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 per creare il deployment:

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

    Sostituisci CLUSTER_KUBECONFIG con il percorso del file kubeconfig per il tuo cluster.

  3. Visualizza informazioni di base sul tuo deployment per verificare che sia stato creato correttamente:

    kubectl get deployment my-deployment --kubeconfig CLUSTER_KUBECONFIG
    

    L'output mostra che il deployment ha tre pod disponibili:

    NAME            READY   UP-TO-DATE   AVAILABLE   AGE
    my-deployment   3/3     3            3           27s
    
  4. Elenca i pod nel tuo deployment:

    kubectl get pods --kubeconfig CLUSTER_KUBECONFIG
    

    L'output mostra che il deployment ha tre pod in esecuzione:

    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. Visualizza informazioni dettagliate sul deployment:

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

    L'output mostra i dettagli della specifica e dello stato 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. Descrivi il tuo deployment:

    kubectl describe deployment my-deployment --kubeconfig CLUSTER_KUBECONFIG
    

    L'output mostra i dettagli ben formattati del deployment, incluso il ReplicaSet associato:

    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 servizio di tipo LoadBalancer

Un modo per esporre il deployment ai clienti esterni al cluster è creare un servizio Kubernetes di tipo LoadBalancer.

Per creare un servizio di tipo LoadBalancer:

  1. Copia il seguente manifest in un file denominato my-service.yaml:

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

    Di seguito sono riportati gli aspetti importanti da comprendere in merito al Servizio nel allenamento:

    • Tutti i pod con l'etichetta app: metrics e l'etichetta department: sales è un membro del Servizio. I pod in my-deployment hanno queste etichette.

    • Quando un client invia una richiesta al servizio sulla porta TCP80, la richiesta viene inoltrata a un pod membro sulla porta TCP 8080.

    • Ogni pod membro deve avere un container in ascolto sulla porta TCP8080.

    Per impostazione predefinita, il container hello-app rimane in ascolto sulla porta TCP 8080. Puoi vedere questa impostazione della porta esaminando il Dockerfile e il codice sorgente dell'app.

  2. Utilizza kubectl apply per creare il servizio nel tuo cluster:

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

    Sostituisci CLUSTER_KUBECONFIG con il percorso del file kubeconfig per il tuo cluster.

  3. Visualizza il tuo servizio:

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

    L'output è simile al seguente:

    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
    

    Nell'output precedente, puoi vedere che il tuo servizio ha un valore clusterIP, e un indirizzo IP esterno. Ha anche nodePort, port e targetPort.

    clusterIP non è pertinente per questo esercizio. L'indirizzo IP esterno (status.loadBalancer.ingress.ip) proviene dall'intervallo di indirizzi che hai specificato quando hai definito i pool di indirizzi del bilanciatore del carico (spec.loadBalancer.addressPools) nel file di configurazione del cluster.

    Ad esempio, prendi i valori mostrati nell'output precedente per Servizio:

    • Indirizzo IP esterno: 192.168.1.13
    • port: 80
    • nodePort: 31565
    • targetPort: 8080

    Un client invia una richiesta a 192.168.1.13 sulla porta TCP 80. La richiesta viene indirizzata al bilanciatore del carico e da lì inoltrata a un pod membro sulla porta TCP 8080.

  4. Chiama il servizio:

    curl INGRESS_IP_ADDRESS
    

    Sostituisci INGRESS_IP_ADDRESS con l'indirizzo IP di ingresso nella sezione status del servizio recuperato nel passaggio precedente (status.loadBalancer.ingress).

    L'output mostra un messaggio Hello, world!:

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

Limiti delle porte di LoadBalancer

Il tipo LoadBalancer è un'estensione del tipo NodePort. Pertanto, un servizio di tipo LoadBalancer ha un indirizzo IP cluster e uno o più valori nodePort. Per impostazione predefinita, Kubernetes alloca le porte dei nodi ai servizi di tipo LoadBalancer. Queste allocazioni possono esaurire rapidamente le porte dei nodi disponibili tra le 2768 assegnate al tuo cluster. Per salvare le porte dei nodi, disattiva l'allocazione delle porte dei nodi del bilanciatore del carico impostando il campo allocateLoadBalancerNodePorts su false nella specifica del servizio LoadBalancer. Questa impostazione impedisce a Kubernetes di allocare le porte dei nodi ai servizi LoadBalancer. Per ulteriori informazioni, vedi Disabilitazione dell'allocazione NodePort del bilanciatore del carico nella documentazione di Kubernetes.

Di seguito è riportato un manifest per creare un servizio che non utilizza alcuna porta del 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

Eliminare il servizio

Per eliminare il Servizio:

  1. Usa kubectl delete per eliminare il servizio dal cluster:

    kubectl delete service my-service --kubeconfig CLUSTER_KUBECONFIG
    
  2. Verifica che il servizio sia stato eliminato:

    kubectl get services --kubeconfig CLUSTER_KUBECONFIG
    

    L'output non mostra più my-service.

Elimina il tuo deployment

Per eliminare il tuo deployment:

  1. Usa kubectl delete per eliminare il deployment dal cluster:

    kubectl delete deployment my-deployment --kubeconfig CLUSTER_KUBECONFIG
    

    Verifica che il deployment sia stato eliminato:

    kubectl get deployments --kubeconfig CLUSTER_KUBECONFIG
    

    L'output non mostra più my-deployment.

Passaggi successivi

Creare un servizio e un Ingress