Implementar um aplicativo

Neste documento, descrevemos como implantar um aplicativo no Google Distributed Cloud.

Antes de começar

Para implementar uma carga de trabalho, você precisa ter um cluster de usuário, híbrido ou independente capaz de executar cargas de trabalho.

Crie uma implantação

As etapas a seguir criam uma implantação no cluster:

  1. copie o seguinte manifesto para um arquivo chamado 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. Use kubectl apply para criar a implantação:

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

    Substitua CLUSTER_KUBECONFIG pelo caminho do arquivo kubeconfig do cluster.

  3. Receba informações básicas sobre sua implantação para confirmar se ela foi criada com sucesso:

    kubectl get deployment my-deployment --kubeconfig CLUSTER_KUBECONFIG
    

    A saída mostra que a implantação tem três pods disponíveis:

    NAME            READY   UP-TO-DATE   AVAILABLE   AGE
    my-deployment   3/3     3            3           27s
    
  4. Liste os pods na implantação:

    kubectl get pods --kubeconfig CLUSTER_KUBECONFIG
    

    A saída mostra que a implantação tem três pods em execução:

    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. Encontre informações detalhadas sobre sua implantação:

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

    A saída mostra informações detalhadas sobre a especificação e o status da implantação:

    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. Descreva a implantação:

    kubectl describe deployment my-deployment --kubeconfig CLUSTER_KUBECONFIG
    

    A saída mostra informações detalhadas bem formatadas sobre a implantação, incluindo o ReplicaSet associado:

    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
    

Criar um serviço do tipo LoadBalancer

Uma maneira de expor a implantação para clientes fora do cluster é criar um serviço do Kubernetes do tipo LoadBalancer.

Para criar um serviço do tipo LoadBalancer:

  1. Copie o seguinte manifesto para um arquivo chamado my-service.yaml:

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

    Veja a seguir informações importantes sobre o Serviço neste exercício:

    • Qualquer pod que tenha o rótulo app: metrics e o rótulo department: sales é um membro do serviço. Os pods em my-deployment têm esses rótulos.

    • Quando um cliente envia uma solicitação ao serviço na porta TCP 80, a solicitação é encaminhada a um pod membro na porta TCP 8080.

    • Cada pod de membro precisa ter um contêiner detectando a porta TCP 8080.

    Por padrão, o contêiner hello-app detecta a porta TCP 8080. Essa configuração de porta pode ser vista no Dockerfile e no código-fonte do app.

  2. Use kubectl apply para criar o serviço no cluster:

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

    Substitua CLUSTER_KUBECONFIG pelo caminho do arquivo kubeconfig do cluster.

  3. Veja seu serviço:

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

    O resultado será assim:

    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
    

    Na saída anterior, é possível ver que o serviço tem um clusterIP e um endereço IP externo. Ele também tem um nodePort, um port e um targetPort.

    O clusterIP não é relevante para este exercício. O endereço IP externo (status.loadBalancer.ingress.ip) vem do intervalo de endereços que você especificou quando definiu os pools de endereços do balanceador de carga (spec.loadBalancer.addressPools) no arquivo de configuração do cluster.

    Por exemplo, veja os valores mostrados na saída anterior do seu serviço:

    • Endereço IP externo: 192.168.1.13
    • port: 80
    • nodePort: 31565
    • targetPort: 8080

    Um cliente envia uma solicitação para 192.168.1.13 na porta TCP 80. A solicitação é encaminhada para o balanceador de carga e, a partir daí, é encaminhada para um pod membro na porta TCP 8080.

  4. Chame o serviço:

    curl INGRESS_IP_ADDRESS
    

    Substitua INGRESS_IP_ADDRESS pelo endereço IP de entrada na seção status do Serviço que você recuperou na etapa anterior (status.loadBalancer.ingress).

    A saída mostra uma mensagem Hello, world!:

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

Limites de portas do LoadBalancer

O tipo LoadBalancer é uma extensão do tipo NodePort. Portanto, um Service do tipo LoadBalancer tem um endereço IP de cluster e um ou mais valores nodePort. Por padrão, o Kubernetes aloca portas de nó para serviços do tipo LoadBalancer. Essas alocações podem esgotar rapidamente as portas de nó disponíveis das 2.768 alocadas para o cluster. Para salvar portas de nó, desative a alocação de porta de nó do balanceador de carga definindo o campo allocateLoadBalancerNodePorts como false na especificação do serviço LoadBalancer. Isso impede que o Kubernetes aloque portas de nó para serviços LoadBalancer. Para mais informações, consulte Como desativar a alocação de NodePort do balanceador de carga na documentação do Kubernetes.

Confira aqui um manifesto para criar um Serviço que não usa nenhuma porta de nó:

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

Excluir o Serviço

Para excluir o serviço:

  1. Use kubectl delete para excluir o serviço do cluster:

    kubectl delete service my-service --kubeconfig CLUSTER_KUBECONFIG
    
  2. Verifique se o serviço foi excluído:

    kubectl get services --kubeconfig CLUSTER_KUBECONFIG
    

    A saída não mostra mais my-service.

Excluir a implantação

Para excluir a implantação:

  1. Use kubectl delete para excluir a implantação do cluster:

    kubectl delete deployment my-deployment --kubeconfig CLUSTER_KUBECONFIG
    

    Verifique se a implantação foi excluída:

    kubectl get deployments --kubeconfig CLUSTER_KUBECONFIG
    

    A saída não mostra mais my-deployment.

A seguir

Crie um serviço e uma entrada