Implemente uma aplicação

Este documento dá um exemplo de como implementar uma aplicação num cluster de utilizadores criado com o Google Distributed Cloud (apenas software) para VMware.

Antes de começar

Para o exemplo apresentado aqui, precisa de um cluster de utilizadores que use o equilíbrio de carga do MetalLB incluído. Para obter instruções sobre como criar um cluster de utilizadores mínimo que use o MetalLB, consulte o artigo Crie clusters básicos.

Pode usar a Google Cloud consola ou a ferramenta de linha de comandoskubectl na estação de trabalho do administrador para implementar a aplicação.

Consola

  1. Na consola, aceda à página Vista geral dos clusters do Google Kubernetes Engine.

    Aceda aos clusters do GKE

  2. Na lista de clusters, clique no seu cluster de utilizadores e verifique se tem sessão iniciada no cluster.

    Se ainda não tiver sessão iniciada no cluster de utilizadores, inicie sessão seguindo as instruções em Gerir clusters a partir da consola. Google Cloud

Contentores

  1. Em Novo contentor, selecione Imagem de contentor existente.

  2. Para Caminho da imagem, introduza us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0.

  3. Clique em Continuar.

Configuração

  1. Em Nome da implementação, introduza my-deployment.

  2. Em Espaço de nomes, introduza default.

  3. Introduza estas duas etiquetas:

    • Key 1: app, Value 1: metrics
    • Key 2: department, Value 2 sales
  4. No menu pendente Cluster do Kubernetes, selecione o seu cluster.

  5. Clique em Continuar.

Expor

  1. Selecione Expor implementação como um novo serviço.

  2. Para a Porta 1, introduza 80.

  3. Para Porta de destino 1, introduza 8080. Este é o valor adequado porque, por predefinição, o contentor hello-app deteta na porta TCP 8080. Pode ver isto consultando o Dockerfile e o código-fonte da app.

  4. Para Protocolo 1, selecione TCP.

  5. Para Tipo de serviço, selecione LoadBalancer.

Na parte inferior da página, clique no botão Implementar.

Veja detalhes da implementação e do serviço

  1. Quando a implementação estiver pronta, a página Detalhes da implementação é aberta na secção Cargas de trabalho do Kubernetes da Google Cloud consola. Nesta página, pode ver detalhes sobre a implementação e os respetivos três pods.

  2. Em Exposing services, clique no nome do serviço que expõe a sua implementação. Para este exercício, o nome é my-deployment-service.

  3. É apresentada a página Detalhes do serviço. Nesta página, pode ver detalhes sobre o serviço. Por exemplo, pode ver que qualquer Pod que tenha as etiquetas app: metrics e department: sales é membro do serviço. Lembre-se de que os pods em my-deployment têm estas etiquetas.

Também pode ver um valor para IP do equilibrador de carga. O IP do balanceador de carga foi configurado automaticamente no balanceador de carga do cluster.

Encaminhamento para o Serviço

Suponhamos que um cliente fora do cluster envia um pedido para o IP do balanceador de carga na porta TCP 80. O pedido é encaminhado para o balanceador de carga do cluster. O equilibrador de carga encaminha o pedido para um pod membro na porta TCP 8080. Recorde que cada Pod em my-deployment tem um contentor a ouvir na porta TCP 8080.

Teste o seu Serviço

Aceda a uma máquina onde o IP do balanceador de carga seja encaminhável.

Para chamar o seu serviço, introduza o IP do equilibrador de carga num navegador ou use um comando como curl. Por exemplo:

curl [LOAD_BALANCER_IP]:80

O resultado mostra uma mensagem Hello, world!. Por exemplo:

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

Elimine a implementação

Aceda à página Workloads na secção Kubernetes Engine da consola.

Aceda à página Cargas de trabalho

Na lista de implementações, selecione my-deployment.

Na parte superior da página, clique em Eliminar. Isto elimina a implementação e o serviço de exposição.

Linha de comandos

Ligue-se à sua estação de trabalho de administração

Estabeleça uma ligação SSH à sua estação de trabalho de administrador. Siga os passos seguintes na estação de trabalho do administrador.

Crie uma implementação

Segue-se um manifesto para uma implementação:

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"

Copie o manifesto para um ficheiro com o nome my-deployment.yaml e crie a implementação:

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

em que USER_CLUSTER_KUBECONFIG é o caminho do ficheiro kubeconfig para o cluster de utilizadores.

Obtenha informações básicas sobre a sua implementação:

kubectl --kubeconfig USER_CLUSTER_KUBECONFIG get deployment my-deployment

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

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

Apresente a lista dos pods na sua implementação:

kubectl --kubeconfig USER_CLUSTER_KUBECONFIG get pods

A saída mostra que a sua implementação tem 3 pods em execução:

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

Obtenha informações detalhadas sobre a sua implementação:

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

O resultado mostra detalhes sobre a especificação e o estado da implementação:

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

Descreva a sua implementação:

kubectl --kubeconfig USER_CLUSTER_KUBECONFIG describe deployment my-deployment

A saída mostra detalhes formatados sobre a implementação, incluindo o ReplicaSet associado:

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)

Crie um serviço do tipo LoadBalancer

Uma forma de expor a sua implementação a clientes fora do cluster é criar um serviço do Kubernetes do tipo LoadBalancer.

Segue-se um manifesto para um serviço do tipo LoadBalancer:

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

Para efeitos deste exercício, seguem-se os aspetos importantes a compreender acerca do Serviço:

  • Qualquer Pod que tenha a etiqueta app: metrics e a etiqueta department: sales é membro do serviço. Tenha em atenção que os agrupamentos em my-deployment têm estas etiquetas.

  • Quando um cliente envia um pedido para o serviço na porta TCP 80, o pedido é encaminhado para um pod membro na porta TCP 8080.

  • Cada membro do pod tem de ter um contentor que esteja a ouvir na porta TCP 8080.

Por predefinição, o contentor hello-app escuta na porta TCP 8080. Pode ver isto consultando o Dockerfile e o código-fonte da app.

Guarde o manifesto num ficheiro com o nome my-service.yaml e crie o serviço:

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

em que USER_CLUSTER_KUBECONFIG é o caminho do ficheiro kubeconfig para o cluster de utilizadores.

Quando cria o serviço, o Google Distributed Cloud configura automaticamente o endereço loadBalancerIP no equilibrador de carga do cluster.

Veja o seu serviço:

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

O resultado é semelhante a este:

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

Na saída anterior, pode ver que o seu serviço tem um clusterIP e um loadBalancerIP. Também tem um port e um targetPort.

O clusterIP não é relevante para este exercício. O loadBalancerIP é o endereço IP que os clientes fora do cluster podem usar para chamar o Serviço.

Por exemplo, considere os valores apresentados no resultado anterior. Ou seja, suponhamos que o seu serviço tem loadBalancerIP = 203.0.113.1, port = 80 e targetPort = 8080.

Um cliente envia um pedido para 203.0.113.1 na porta TCP 80. O pedido é encaminhado para o balanceador de carga do cluster. O balanceador de carga encaminha o pedido para um pod membro na porta TCP 8080.

Ligue para o seu serviço:

curl LOAD_BALANCER_IP

O resultado mostra uma mensagem Hello, world!:

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

Elimine o seu serviço

Elimine o seu serviço:

kubectl --kubeconfig USER_CLUSTER_KUBECONFIG delete service my-service

Verifique se o seu serviço foi eliminado:

kubectl --kubeconfig USER_CLUSTER_KUBECONFIG get services

O resultado já não mostra my-service.

Elimine a sua implementação

Elimine a sua implementação:

kubectl --kubeconfig USER_CLUSTER_KUBECONFIG delete deployment my-deployment

Verifique se a implementação foi eliminada:

kubectl --kubeconfig USER_CLUSTER_KUBECONFIG get deployments

O resultado já não mostra my-deployment.

O que se segue?

Crie um serviço e uma entrada